Home Home > GIT Browse > SLE15
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2017-11-19 22:04:49 +0100
committerJiri Kosina <jkosina@suse.cz>2017-11-19 22:04:49 +0100
commit349e50cfae788dccfab9b141e4d3c28757e6b4a5 (patch)
tree1f886f5ccd63d6ee2b7a25fff64f65cc0f1bbd40
parentc655a63413d5011285b7dc247ceddbccc998f1a3 (diff)
parent36648268a21942f2a6c3865dfeada3beb1f65122 (diff)
Merge remote-tracking branch 'origin/users/ykaukab/SLE15/for-next' into SLE15rpm-4.12.14-4--SLE-15-Packages-Beta3rpm-4.12.14-4--SLE-12-SP4-RT-RC1rpm-4.12.14-4
-rw-r--r--config/arm64/default63
-rw-r--r--patches.drivers/0001-PCI-rockchip-Factor-out-rockchip_pcie_get_phys.patch65
-rw-r--r--patches.drivers/0001-PM-devfreq-rk3399_dmc-fix-error-return-code-in-rk339.patch46
-rw-r--r--patches.drivers/0001-lib-mpi-call-cond_resched-from-mpi_powm-loop.patch55
-rw-r--r--patches.drivers/0002-PCI-rockchip-Add-per-lane-PHY-support.patch180
-rw-r--r--patches.drivers/0002-iio-adc-rockchip_saradc-add-NULL-check-on-of_match_d.patch41
-rw-r--r--patches.drivers/0003-iio-adc-rockchip_saradc-explicitly-request-exclusive.patch49
-rw-r--r--patches.drivers/0004-clocksource-drivers-rockchip-pr_err-strings-should-e.patch37
-rw-r--r--patches.drivers/0005-pinctrl-rockchip-remove-unneeded-void-casts-in-of_ma.patch66
-rw-r--r--patches.drivers/0006-pinctrl-rockchip-Add-iomux-route-switching-support.patch161
-rw-r--r--patches.drivers/0007-pinctrl-rockchip-Add-iomux-route-switching-support-f.patch174
-rw-r--r--patches.drivers/0008-pinctrl-rockchip-Add-iomux-route-switching-support-f.patch125
-rw-r--r--patches.drivers/0009-pinctrl-rockchip-Add-iomux-route-switching-support-f.patch83
-rw-r--r--patches.drivers/0010-pinctrl-rockchip-Use-common-interface-for-recalced-i.patch234
-rw-r--r--patches.drivers/0011-pinctrl-rockchip-Fix-the-rk3399-gpio0-and-gpio1-bank.patch56
-rw-r--r--patches.drivers/0012-iommu-rockchip-Enable-Rockchip-IOMMU-on-ARM64.patch39
-rw-r--r--patches.drivers/0013-iommu-rockchip-add-multi-irqs-support.patch89
-rw-r--r--patches.drivers/0014-iommu-rockchip-ignore-isp-mmu-reset-operation.patch55
-rw-r--r--patches.drivers/0015-spi-rockchip-fix-error-handling-when-probe.patch115
-rw-r--r--patches.drivers/0016-spi-rockchip-Set-GPIO_SS-flag-to-enable-Slave-Select.patch35
-rw-r--r--patches.drivers/0017-spi-rockchip-Disable-Runtime-PM-when-chip-select-is-.patch129
-rw-r--r--patches.drivers/0018-spi-rockchip-Slightly-rework-return-value-handling.patch116
-rw-r--r--patches.drivers/0019-spi-rockchip-Fix-clock-handling-in-remove.patch46
-rw-r--r--patches.drivers/0020-spi-rockchip-Fix-clock-handling-in-suspend-resume.patch65
-rw-r--r--patches.drivers/0021-spi-rockchip-configure-CTRLR1-according-to-size-and-.patch43
-rw-r--r--patches.drivers/0022-clk-rockchip-add-ids-for-camera-on-rk3399.patch34
-rw-r--r--patches.drivers/0023-clk-rockchip-add-dt-binding-header-for-rk3128.patch315
-rw-r--r--patches.drivers/0024-clk-rockchip-add-ids-for-rk3399-testclks-used-for-ca.patch42
-rw-r--r--patches.drivers/0025-clk-fractional-divider-allow-overriding-of-approxima.patch94
-rw-r--r--patches.drivers/0026-clk-rockchip-add-special-approximation-to-fix-up-fra.patch92
-rw-r--r--patches.drivers/0027-clk-rockchip-Mark-rockchip_fractional_approximation-.patch38
-rw-r--r--patches.drivers/0028-clk-rockchip-Remove-superfluous-error-message-in-roc.patch38
-rw-r--r--patches.drivers/0029-phy-qcom-usb-Remove-unused-ulpi-phy-header.patch66
-rw-r--r--patches.drivers/0030-phy-Move-ULPI-phy-header-out-of-drivers-to-include-p.patch124
-rw-r--r--patches.drivers/0031-phy-Group-vendor-specific-phy-drivers.patch45969
-rw-r--r--patches.drivers/0032-phy-rockchip-inno-usb2-add-a-delay-after-phy-resume.patch37
-rw-r--r--patches.drivers/0033-phy-rockchip-inno-usb2-increase-otg-sm-work-first-sc.patch60
-rw-r--r--patches.drivers/0034-phy-rockchip-inno-usb2-add-one-phy-comprises-with-tw.patch63
-rw-r--r--patches.drivers/0035-phy-rockchip-inno-usb2-add-support-of-usb2-phy-for-r.patch113
-rw-r--r--patches.drivers/0036-phy-rockchip-inno-usb2-Replace-the-extcon-API.patch66
-rw-r--r--patches.drivers/0037-phy-rockchip-inno-usb2-add-support-for-rockchip-usbg.patch361
-rw-r--r--patches.drivers/0038-phy-rockchip-inno-usb2-add-support-for-otg-mux-inter.patch120
-rw-r--r--patches.drivers/0039-phy-rockchip-inno-usb2-add-support-of-usb2-phy-for-r.patch95
-rw-r--r--patches.drivers/0040-phy-rockchip-typec-remove-unused-dfp-variable.patch44
-rw-r--r--patches.drivers/0041-phy-rockchip-pcie-Reconstruct-driver-to-support-per-.patch272
-rw-r--r--patches.drivers/0042-phy-rockchip-typec-Set-the-AUX-channel-flip-state-ea.patch174
-rw-r--r--patches.drivers/0043-phy-rockchip-typec-Don-t-set-the-aux-voltage-swing-t.patch104
-rw-r--r--patches.drivers/0044-phy-rockchip-typec-Check-for-errors-from-tcphy_phy_i.patch60
-rw-r--r--patches.drivers/0045-phy-rockchip-typec-Avoid-magic-numbers-add-delays-in.patch381
-rw-r--r--patches.drivers/0046-phy-rockchip-typec-Do-the-calibration-more-correctly.patch77
-rw-r--r--patches.drivers/0047-pwm-rockchip-Add-APB-and-function-both-clocks-suppor.patch177
-rw-r--r--patches.drivers/0048-pwm-rockchip-Remove-the-judge-from-return-value-of-p.patch61
-rw-r--r--patches.drivers/0049-pwm-rockchip-Use-pwm_apply-instead-of-pwm_enable.patch256
-rw-r--r--patches.drivers/0050-pwm-rockchip-Move-the-configuration-of-polarity.patch148
-rw-r--r--patches.drivers/0051-pwm-rockchip-Use-same-PWM-ops-for-each-IP.patch273
-rw-r--r--patches.drivers/0052-mfd-rk808-Fix-up-the-chip-id-get-failed.patch79
-rw-r--r--patches.drivers/0053-drm-rockchip-Set-line-flag-config-register-in-vop_cr.patch138
-rw-r--r--patches.drivers/0054-drm-rockchip-analogix_dp-Remove-unused-check-and-var.patch55
-rw-r--r--patches.drivers/0055-drm-rockchip-use-drm_for_each_connector_iter.patch52
-rw-r--r--patches.drivers/0056-drm-rockchip-gem-add-the-lacks-lock-and-trivial-chan.patch75
-rw-r--r--patches.drivers/0057-drm-rockchip-Remove-unnecessary-NULL-check.patch40
-rw-r--r--patches.drivers/0058-drm-rockchip-dw_hdmi-add-RK3399-HDMI-support.patch155
-rw-r--r--patches.drivers/0059-drm-rockchip-dw_hdmi-introduce-the-VPLL-clock-settin.patch108
-rw-r--r--patches.drivers/0060-drm-rockchip-dw_hdmi-introduce-the-pclk-for-grf.patch84
-rw-r--r--patches.drivers/0061-drm-rockchip-Drop-drm_vblank_cleanup.patch44
-rw-r--r--patches.drivers/0062-drm-rockchip-fix-NULL-check-on-devm_kzalloc-return-v.patch48
-rw-r--r--patches.drivers/0063-drm-rockchip-Use-for_each_oldnew_plane_in_state-in-v.patch57
-rw-r--r--patches.drivers/0064-drm-rockchip-Use-.dumb_map_offset-and-.dumb_destroy-.patch92
-rw-r--r--patches.drivers/0065-drm-rockchip-vop-initialize-registers-directly.patch219
-rw-r--r--patches.drivers/0066-drm-rockchip-vop-move-write_relaxed-flags-to-vop-reg.patch198
-rw-r--r--patches.drivers/0067-drm-rockchip-vop-move-line_flag_num-to-interrupt-reg.patch141
-rw-r--r--patches.drivers/0068-drm-rockchip-vop-group-vop-registers.patch509
-rw-r--r--patches.drivers/0069-drm-rockchip-vop-add-a-series-of-vop-support.patch1281
-rw-r--r--patches.drivers/0070-drm-rockchip-vop-rk3328-fix-overlay-abnormal.patch74
-rw-r--r--patches.drivers/0071-drm-rockchip-vop-fix-iommu-page-fault-when-resume.patch103
-rw-r--r--patches.drivers/0072-drm-rockchip-vop-fix-NV12-video-display-error.patch37
-rw-r--r--patches.drivers/0073-drm-rockchip-vop-round_up-pitches-to-word-align.patch54
-rw-r--r--patches.drivers/0074-drm-rockchip-vop-report-error-when-check-resource-er.patch40
-rw-r--r--patches.drivers/0075-drm-rockchip-vop-no-need-wait-vblank-on-crtc-enable.patch70
-rw-r--r--patches.drivers/0076-drm-rockchip-fix-race-with-kms-hotplug-and-fbdev.patch78
-rw-r--r--patches.drivers/0077-drm-rockchip-make-drm_connector_funcs-structures-con.patch68
-rw-r--r--patches.drivers/0078-drm-rockchip-Fix-suspend-crash-when-drm-is-not-bound.patch72
-rw-r--r--patches.drivers/0079-drm-rockchip-switch-to-drm_-_get-drm_-_put-helpers.patch113
-rw-r--r--patches.drivers/0080-drm-rockchip-Add-support-for-Rockchip-Soc-LVDS.patch794
-rw-r--r--patches.drivers/0081-drm-rockchip-Replace-dev_-with-DRM_DEV_.patch838
-rw-r--r--patches.drivers/0082-drm-rockchip-Fix-uninitialized-use-of-ret.patch67
-rw-r--r--patches.drivers/0083-drm-rockchip-Cocci-spatch-vma_pages.patch37
-rw-r--r--patches.drivers/0084-drm-rockchip-Rely-on-the-default-best_encoder-behavi.patch53
-rw-r--r--patches.drivers/0085-drm-rockchip-add-PINCTRL-dependency-for-LVDS.patch43
-rw-r--r--patches.drivers/0086-drm-rockchip-add-CONFIG_OF-dependency-for-lvds.patch45
-rw-r--r--series.conf96
-rw-r--r--supported.conf32
92 files changed, 57979 insertions, 31 deletions
diff --git a/config/arm64/default b/config/arm64/default
index aa51aabb81..21b2122bba 100644
--- a/config/arm64/default
+++ b/config/arm64/default
@@ -494,7 +494,7 @@ CONFIG_PCIE_IPROC_PLATFORM=m
CONFIG_PCIE_IPROC_MSI=y
CONFIG_PCI_HOST_THUNDER_PEM=y
CONFIG_PCI_HOST_THUNDER_ECAM=y
-CONFIG_PCIE_ROCKCHIP=y
+# CONFIG_PCIE_ROCKCHIP is not set
#
# PCI Endpoint
@@ -3697,7 +3697,8 @@ CONFIG_GPIO_PISOSR=m
#
CONFIG_GPIO_VIPERBOARD=m
# CONFIG_W1 is not set
-# CONFIG_POWER_AVS is not set
+CONFIG_POWER_AVS=y
+CONFIG_ROCKCHIP_IODOMAIN=m
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_GPIO=y
CONFIG_POWER_RESET_GPIO_RESTART=y
@@ -4098,7 +4099,7 @@ CONFIG_MFD_RTSX_PCI=m
# CONFIG_MFD_RT5033 is not set
CONFIG_MFD_RTSX_USB=m
# CONFIG_MFD_RC5T583 is not set
-# CONFIG_MFD_RK808 is not set
+CONFIG_MFD_RK808=m
# CONFIG_MFD_RN5T618 is not set
# CONFIG_MFD_SEC_CORE is not set
# CONFIG_MFD_SI476X_CORE is not set
@@ -4180,6 +4181,7 @@ CONFIG_REGULATOR_LTC3676=m
CONFIG_REGULATOR_PWM=m
CONFIG_REGULATOR_QCOM_RPM=m
CONFIG_REGULATOR_QCOM_SMD_RPM=m
+CONFIG_REGULATOR_RK808=m
# CONFIG_REGULATOR_TPS51632 is not set
# CONFIG_REGULATOR_TPS62360 is not set
# CONFIG_REGULATOR_TPS65023 is not set
@@ -4774,6 +4776,13 @@ CONFIG_NOUVEAU_DEBUG_DEFAULT=3
CONFIG_DRM_NOUVEAU_BACKLIGHT=y
# CONFIG_DRM_VGEM is not set
# CONFIG_DRM_EXYNOS is not set
+CONFIG_DRM_ROCKCHIP=m
+CONFIG_ROCKCHIP_ANALOGIX_DP=y
+CONFIG_ROCKCHIP_CDN_DP=y
+CONFIG_ROCKCHIP_DW_HDMI=y
+CONFIG_ROCKCHIP_DW_MIPI_DSI=y
+CONFIG_ROCKCHIP_INNO_HDMI=y
+CONFIG_ROCKCHIP_LVDS=y
CONFIG_DRM_UDL=m
CONFIG_DRM_AST=m
CONFIG_DRM_MGAG200=m
@@ -4825,6 +4834,7 @@ CONFIG_DRM_SIL_SII8620=m
CONFIG_DRM_SII902X=m
CONFIG_DRM_TOSHIBA_TC358767=m
CONFIG_DRM_TI_TFP410=m
+CONFIG_DRM_ANALOGIX_DP=m
CONFIG_DRM_I2C_ADV7511=m
# CONFIG_DRM_I2C_ADV7511_AUDIO is not set
CONFIG_DRM_I2C_ADV7533=y
@@ -5868,6 +5878,7 @@ CONFIG_RTC_DRV_DS1374_WDT=y
CONFIG_RTC_DRV_DS1672=m
# CONFIG_RTC_DRV_HYM8563 is not set
CONFIG_RTC_DRV_MAX6900=m
+CONFIG_RTC_DRV_RK808=m
CONFIG_RTC_DRV_RS5C372=m
CONFIG_RTC_DRV_ISL1208=m
# CONFIG_RTC_DRV_ISL12022 is not set
@@ -6126,6 +6137,7 @@ CONFIG_COMMON_CLK=y
CONFIG_COMMON_CLK_VERSATILE=y
CONFIG_CLK_SP810=y
CONFIG_CLK_VEXPRESS_OSC=y
+CONFIG_COMMON_CLK_RK808=m
CONFIG_COMMON_CLK_HI655X=m
CONFIG_COMMON_CLK_SCPI=m
# CONFIG_COMMON_CLK_SI5351 is not set
@@ -6238,6 +6250,7 @@ CONFIG_IOMMU_IO_PGTABLE_ARMV7S=y
CONFIG_IOMMU_IOVA=y
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
+CONFIG_ROCKCHIP_IOMMU=y
# CONFIG_TEGRA_IOMMU_SMMU is not set
CONFIG_EXYNOS_IOMMU=y
# CONFIG_EXYNOS_IOMMU_DEBUG is not set
@@ -6404,41 +6417,41 @@ CONFIG_RESET_TEGRA_BPMP=y
# PHY Subsystem
#
CONFIG_GENERIC_PHY=y
+CONFIG_PHY_MT65XX_USB3=m
+CONFIG_PHY_XGENE=m
+CONFIG_PHY_SUN4I_USB=m
+CONFIG_PHY_SUN9I_USB=m
+CONFIG_PHY_MESON8B_USB2=m
+CONFIG_BCM_KONA_USB2_PHY=m
CONFIG_PHY_BCM_NS_USB2=m
CONFIG_PHY_BCM_NS_USB3=m
-CONFIG_PHY_BERLIN_USB=m
+CONFIG_PHY_NS2_PCIE=m
+CONFIG_PHY_BRCM_SATA=m
+CONFIG_PHY_HI6220_USB=m
CONFIG_PHY_BERLIN_SATA=m
-CONFIG_PHY_EXYNOS_MIPI_VIDEO=m
+CONFIG_PHY_BERLIN_USB=m
CONFIG_PHY_PXA_28NM_HSIC=m
CONFIG_PHY_PXA_28NM_USB2=m
-CONFIG_PHY_EXYNOS_DP_VIDEO=m
-CONFIG_BCM_KONA_USB2_PHY=m
-CONFIG_PHY_MT65XX_USB3=m
-CONFIG_PHY_HI6220_USB=m
-CONFIG_PHY_SUN4I_USB=m
-CONFIG_PHY_SUN9I_USB=m
-# CONFIG_PHY_SAMSUNG_USB2 is not set
-# CONFIG_PHY_EXYNOS5_USBDRD is not set
-CONFIG_PHY_EXYNOS_PCIE=y
CONFIG_PHY_QCOM_APQ8064_SATA=m
CONFIG_PHY_QCOM_IPQ806X_SATA=m
-CONFIG_PHY_ROCKCHIP_USB=m
-CONFIG_PHY_ROCKCHIP_INNO_USB2=m
-CONFIG_PHY_ROCKCHIP_EMMC=m
-CONFIG_PHY_ROCKCHIP_DP=m
-CONFIG_PHY_ROCKCHIP_PCIE=m
-CONFIG_PHY_ROCKCHIP_TYPEC=m
-CONFIG_PHY_XGENE=m
CONFIG_PHY_QCOM_QMP=m
CONFIG_PHY_QCOM_QUSB2=m
CONFIG_PHY_QCOM_UFS=m
CONFIG_PHY_QCOM_USB_HS=m
CONFIG_PHY_QCOM_USB_HSIC=m
-# CONFIG_PHY_TUSB1210 is not set
-CONFIG_PHY_BRCM_SATA=m
+CONFIG_PHY_ROCKCHIP_DP=m
+CONFIG_PHY_ROCKCHIP_EMMC=m
+CONFIG_PHY_ROCKCHIP_INNO_USB2=m
+CONFIG_PHY_ROCKCHIP_PCIE=m
+CONFIG_PHY_ROCKCHIP_TYPEC=m
+CONFIG_PHY_ROCKCHIP_USB=m
+CONFIG_PHY_EXYNOS_DP_VIDEO=m
+CONFIG_PHY_EXYNOS_MIPI_VIDEO=m
+CONFIG_PHY_EXYNOS_PCIE=y
+# CONFIG_PHY_SAMSUNG_USB2 is not set
+# CONFIG_PHY_EXYNOS5_USBDRD is not set
CONFIG_PHY_TEGRA_XUSB=m
-CONFIG_PHY_NS2_PCIE=m
-CONFIG_PHY_MESON8B_USB2=m
+# CONFIG_PHY_TUSB1210 is not set
# CONFIG_POWERCAP is not set
# CONFIG_MCB is not set
diff --git a/patches.drivers/0001-PCI-rockchip-Factor-out-rockchip_pcie_get_phys.patch b/patches.drivers/0001-PCI-rockchip-Factor-out-rockchip_pcie_get_phys.patch
new file mode 100644
index 0000000000..07c8a2c1dd
--- /dev/null
+++ b/patches.drivers/0001-PCI-rockchip-Factor-out-rockchip_pcie_get_phys.patch
@@ -0,0 +1,65 @@
+From cad366ee2c76cc4b081262ba61a6b7e5130c8a48 Mon Sep 17 00:00:00 2001
+From: Shawn Lin <shawn.lin@rock-chips.com>
+Date: Wed, 19 Jul 2017 17:55:12 +0800
+Subject: [PATCH 1/2] PCI: rockchip: Factor out rockchip_pcie_get_phys()
+
+Git-commit: 2ba5991f340b28fe467333740a01a17412ba63dc
+Patch-mainline: v4.14-rc1
+References: fate#323912
+
+We plan to introduce per-lane PHYs, so factor out rockchip_pcie_get_phys()
+to make it easier in the future. No functional change intended.
+
+Tested-by: Jeffy Chen <jeffy.chen@rock-chips.com>
+Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Brian Norris <briannorris@chromium.org>
+Acked-by: Kishon Vijay Abraham I <kishon@ti.com>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/pci/host/pcie-rockchip.c | 22 ++++++++++++++++------
+ 1 file changed, 16 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/pci/host/pcie-rockchip.c b/drivers/pci/host/pcie-rockchip.c
+index 4590eb95d5d8..d274ed9ddfb0 100644
+--- a/drivers/pci/host/pcie-rockchip.c
++++ b/drivers/pci/host/pcie-rockchip.c
+@@ -818,6 +818,19 @@ static void rockchip_pcie_legacy_int_handler(struct irq_desc *desc)
+ chained_irq_exit(chip, desc);
+ }
+
++static int rockchip_pcie_get_phys(struct rockchip_pcie *rockchip)
++{
++ struct device *dev = rockchip->dev;
++
++ rockchip->phy = devm_phy_get(dev, "pcie-phy");
++ if (IS_ERR(rockchip->phy)) {
++ if (PTR_ERR(rockchip->phy) != -EPROBE_DEFER)
++ dev_err(dev, "missing phy\n");
++ return PTR_ERR(rockchip->phy);
++ }
++
++ return 0;
++}
+
+ /**
+ * rockchip_pcie_parse_dt - Parse Device Tree
+@@ -848,12 +861,9 @@ static int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip)
+ if (IS_ERR(rockchip->apb_base))
+ return PTR_ERR(rockchip->apb_base);
+
+- rockchip->phy = devm_phy_get(dev, "pcie-phy");
+- if (IS_ERR(rockchip->phy)) {
+- if (PTR_ERR(rockchip->phy) != -EPROBE_DEFER)
+- dev_err(dev, "missing phy\n");
+- return PTR_ERR(rockchip->phy);
+- }
++ err = rockchip_pcie_get_phys(rockchip);
++ if (err)
++ return err;
+
+ rockchip->lanes = 1;
+ err = of_property_read_u32(node, "num-lanes", &rockchip->lanes);
+--
+2.11.0
+
diff --git a/patches.drivers/0001-PM-devfreq-rk3399_dmc-fix-error-return-code-in-rk339.patch b/patches.drivers/0001-PM-devfreq-rk3399_dmc-fix-error-return-code-in-rk339.patch
new file mode 100644
index 0000000000..b46a425850
--- /dev/null
+++ b/patches.drivers/0001-PM-devfreq-rk3399_dmc-fix-error-return-code-in-rk339.patch
@@ -0,0 +1,46 @@
+From 734578f314b2711e1acb4df18b9faf83ab879671 Mon Sep 17 00:00:00 2001
+From: "Gustavo A. R. Silva" <garsilva@embeddedor.com>
+Date: Mon, 3 Jul 2017 07:59:26 -0500
+Subject: [PATCH 01/86] PM / devfreq: rk3399_dmc: fix error return code in
+ rk3399_dmcfreq_probe()
+
+Git-commit: da55b1ad4b29b6ab44d5dc8ea8306260246d2699
+Patch-mainline: v4.13-rc1
+References: fate#323912
+
+platform_get_irq() returns an error code, but the rk3399_dmc
+driver ignores it and always returns -EINVAL. This is not correct,
+and prevents -EPROBE_DEFER from being propagated properly.
+
+Notice that platform_get_irq() no longer returns 0 on error:
+https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e330b9a6bb35dc7097a4f02cb1ae7b6f96df92af
+
+Print and propagate the return value of platform_get_irq on failure.
+
+Reviewed-by: Chanwoo Choi <cw00.choi@samsung.com>
+Signed-off-by: Gustavo A. R. Silva <garsilva@embeddedor.com>
+Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/devfreq/rk3399_dmc.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/devfreq/rk3399_dmc.c b/drivers/devfreq/rk3399_dmc.c
+index 40a2499730fc..1b89ebbad02c 100644
+--- a/drivers/devfreq/rk3399_dmc.c
++++ b/drivers/devfreq/rk3399_dmc.c
+@@ -336,8 +336,9 @@ static int rk3399_dmcfreq_probe(struct platform_device *pdev)
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+- dev_err(&pdev->dev, "Cannot get the dmc interrupt resource\n");
+- return -EINVAL;
++ dev_err(&pdev->dev,
++ "Cannot get the dmc interrupt resource: %d\n", irq);
++ return irq;
+ }
+ data = devm_kzalloc(dev, sizeof(struct rk3399_dmcfreq), GFP_KERNEL);
+ if (!data)
+--
+2.11.0
+
diff --git a/patches.drivers/0001-lib-mpi-call-cond_resched-from-mpi_powm-loop.patch b/patches.drivers/0001-lib-mpi-call-cond_resched-from-mpi_powm-loop.patch
new file mode 100644
index 0000000000..8f652d0d94
--- /dev/null
+++ b/patches.drivers/0001-lib-mpi-call-cond_resched-from-mpi_powm-loop.patch
@@ -0,0 +1,55 @@
+From d6f56f1f998fb61bbc7c28b5a1cd675837fb1d56 Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Tue, 7 Nov 2017 14:15:27 -0800
+Subject: [PATCH] lib/mpi: call cond_resched() from mpi_powm() loop
+
+Git-commit: 1d9ddde12e3c9bab7f3d3484eb9446315e3571ca
+Patch-mainline: Queued
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
+References: bsc#1066688
+
+On a non-preemptible kernel, if KEYCTL_DH_COMPUTE is called with the
+largest permitted inputs (16384 bits), the kernel spends 10+ seconds
+doing modular exponentiation in mpi_powm() without rescheduling. If all
+threads do it, it locks up the system. Moreover, it can cause
+rcu_sched-stall warnings.
+
+Notwithstanding the insanity of doing this calculation in kernel mode
+rather than in userspace, fix it by calling cond_resched() as each bit
+from the exponent is processed. It's still noninterruptible, but at
+least it's preemptible now.
+
+Do the cond_resched() once per bit rather than once per MPI limb because
+each limb might still easily take 100+ milliseconds on slow CPUs.
+
+Cc: <stable@vger.kernel.org> # v4.12+
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ lib/mpi/mpi-pow.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c
+index e24388a863a7..468fb7cd1221 100644
+--- a/lib/mpi/mpi-pow.c
++++ b/lib/mpi/mpi-pow.c
+@@ -26,6 +26,7 @@
+ * however I decided to publish this code under the plain GPL.
+ */
+
++#include <linux/sched.h>
+ #include <linux/string.h>
+ #include "mpi-internal.h"
+ #include "longlong.h"
+@@ -256,6 +257,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod)
+ }
+ e <<= 1;
+ c--;
++ cond_resched();
+ }
+
+ i--;
+--
+2.11.0
+
diff --git a/patches.drivers/0002-PCI-rockchip-Add-per-lane-PHY-support.patch b/patches.drivers/0002-PCI-rockchip-Add-per-lane-PHY-support.patch
new file mode 100644
index 0000000000..16927f09d0
--- /dev/null
+++ b/patches.drivers/0002-PCI-rockchip-Add-per-lane-PHY-support.patch
@@ -0,0 +1,180 @@
+From b5c70231ed3b1b23d4770856157c4e5ba939ede5 Mon Sep 17 00:00:00 2001
+From: Shawn Lin <shawn.lin@rock-chips.com>
+Date: Fri, 25 Aug 2017 15:59:01 -0500
+Subject: [PATCH 2/2] PCI: rockchip: Add per-lane PHY support
+
+Git-commit: 9e87240c460637620d9b4b8c6475a53b48267dc6
+Patch-mainline: v4.14-rc1
+References: fate#323912
+
+We distinguish the legacy PHY from newer per-lane PHYs by adding legacy_phy
+flag. Note that the legacy PHY is still the first option to be searched in
+order not to break the backward compatibility of DTB.
+
+Tested-by: Jeffy Chen <jeffy.chen@rock-chips.com>
+Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
+[bhelgaas: tidy rockchip_pcie_get_phys()]
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Brian Norris <briannorris@chromium.org>
+Acked-by: Kishon Vijay Abraham I <kishon@ti.com>
+
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/pci/host/pcie-rockchip.c | 78 +++++++++++++++++++++++++++++-----------
+ 1 file changed, 58 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/pci/host/pcie-rockchip.c b/drivers/pci/host/pcie-rockchip.c
+index d274ed9ddfb0..4a0dfff94fa6 100644
+--- a/drivers/pci/host/pcie-rockchip.c
++++ b/drivers/pci/host/pcie-rockchip.c
+@@ -47,6 +47,7 @@
+ #define HIWORD_UPDATE_BIT(val) HIWORD_UPDATE(val, val)
+
+ #define ENCODE_LANES(x) ((((x) >> 1) & 3) << 4)
++#define MAX_LANE_NUM 4
+
+ #define PCIE_CLIENT_BASE 0x0
+ #define PCIE_CLIENT_CONFIG (PCIE_CLIENT_BASE + 0x00)
+@@ -204,7 +205,8 @@
+ struct rockchip_pcie {
+ void __iomem *reg_base; /* DT axi-base */
+ void __iomem *apb_base; /* DT apb-base */
+- struct phy *phy;
++ bool legacy_phy;
++ struct phy *phys[MAX_LANE_NUM];
+ struct reset_control *core_rst;
+ struct reset_control *mgmt_rst;
+ struct reset_control *mgmt_sticky_rst;
+@@ -474,7 +476,7 @@ static void rockchip_pcie_set_power_limit(struct rockchip_pcie *rockchip)
+ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
+ {
+ struct device *dev = rockchip->dev;
+- int err;
++ int err, i;
+ u32 status;
+
+ gpiod_set_value(rockchip->ep_gpio, 0);
+@@ -497,10 +499,12 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
+ return err;
+ }
+
+- err = phy_init(rockchip->phy);
+- if (err < 0) {
+- dev_err(dev, "fail to init phy, err %d\n", err);
+- return err;
++ for (i = 0; i < MAX_LANE_NUM; i++) {
++ err = phy_init(rockchip->phys[i]);
++ if (err) {
++ dev_err(dev, "init phy%d err %d\n", i, err);
++ return err;
++ }
+ }
+
+ err = reset_control_assert(rockchip->core_rst);
+@@ -562,10 +566,12 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
+ PCIE_CLIENT_MODE_RC,
+ PCIE_CLIENT_CONFIG);
+
+- err = phy_power_on(rockchip->phy);
+- if (err) {
+- dev_err(dev, "fail to power on phy, err %d\n", err);
+- return err;
++ for (i = 0; i < MAX_LANE_NUM; i++) {
++ err = phy_power_on(rockchip->phys[i]);
++ if (err) {
++ dev_err(dev, "power on phy%d err %d\n", i, err);
++ return err;
++ }
+ }
+
+ /*
+@@ -821,12 +827,39 @@ static void rockchip_pcie_legacy_int_handler(struct irq_desc *desc)
+ static int rockchip_pcie_get_phys(struct rockchip_pcie *rockchip)
+ {
+ struct device *dev = rockchip->dev;
++ struct phy *phy;
++ char *name;
++ u32 i;
++
++ phy = devm_phy_get(dev, "pcie-phy");
++ if (!IS_ERR(phy)) {
++ rockchip->legacy_phy = true;
++ rockchip->phys[0] = phy;
++ dev_warn(dev, "legacy phy model is deprecated!\n");
++ return 0;
++ }
++
++ if (PTR_ERR(phy) == -EPROBE_DEFER)
++ return PTR_ERR(phy);
++
++ dev_dbg(dev, "missing legacy phy; search for per-lane PHY\n");
++
++ for (i = 0; i < MAX_LANE_NUM; i++) {
++ name = kasprintf(GFP_KERNEL, "pcie-phy-%u", i);
++ if (!name)
++ return -ENOMEM;
+
+- rockchip->phy = devm_phy_get(dev, "pcie-phy");
+- if (IS_ERR(rockchip->phy)) {
+- if (PTR_ERR(rockchip->phy) != -EPROBE_DEFER)
+- dev_err(dev, "missing phy\n");
+- return PTR_ERR(rockchip->phy);
++ phy = devm_of_phy_get(dev, dev->of_node, name);
++ kfree(name);
++
++ if (IS_ERR(phy)) {
++ if (PTR_ERR(phy) != -EPROBE_DEFER)
++ dev_err(dev, "missing phy for lane %d: %ld\n",
++ i, PTR_ERR(phy));
++ return PTR_ERR(phy);
++ }
++
++ rockchip->phys[i] = phy;
+ }
+
+ return 0;
+@@ -1245,7 +1278,7 @@ static int rockchip_pcie_wait_l2(struct rockchip_pcie *rockchip)
+ static int __maybe_unused rockchip_pcie_suspend_noirq(struct device *dev)
+ {
+ struct rockchip_pcie *rockchip = dev_get_drvdata(dev);
+- int ret;
++ int ret, i;
+
+ /* disable core and cli int since we don't need to ack PME_ACK */
+ rockchip_pcie_write(rockchip, (PCIE_CLIENT_INT_CLI << 16) |
+@@ -1258,8 +1291,10 @@ static int __maybe_unused rockchip_pcie_suspend_noirq(struct device *dev)
+ return ret;
+ }
+
+- phy_power_off(rockchip->phy);
+- phy_exit(rockchip->phy);
++ for (i = 0; i < MAX_LANE_NUM; i++) {
++ phy_power_off(rockchip->phys[i]);
++ phy_exit(rockchip->phys[i]);
++ }
+
+ clk_disable_unprepare(rockchip->clk_pcie_pm);
+ clk_disable_unprepare(rockchip->hclk_pcie);
+@@ -1451,14 +1486,17 @@ static int rockchip_pcie_remove(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+ struct rockchip_pcie *rockchip = dev_get_drvdata(dev);
++ int i;
+
+ pci_stop_root_bus(rockchip->root_bus);
+ pci_remove_root_bus(rockchip->root_bus);
+ pci_unmap_iospace(rockchip->io);
+ irq_domain_remove(rockchip->irq_domain);
+
+- phy_power_off(rockchip->phy);
+- phy_exit(rockchip->phy);
++ for (i = 0; i < MAX_LANE_NUM; i++) {
++ phy_power_off(rockchip->phys[i]);
++ phy_exit(rockchip->phys[i]);
++ }
+
+ clk_disable_unprepare(rockchip->clk_pcie_pm);
+ clk_disable_unprepare(rockchip->hclk_pcie);
+--
+2.11.0
+
diff --git a/patches.drivers/0002-iio-adc-rockchip_saradc-add-NULL-check-on-of_match_d.patch b/patches.drivers/0002-iio-adc-rockchip_saradc-add-NULL-check-on-of_match_d.patch
new file mode 100644
index 0000000000..2a13fcbffc
--- /dev/null
+++ b/patches.drivers/0002-iio-adc-rockchip_saradc-add-NULL-check-on-of_match_d.patch
@@ -0,0 +1,41 @@
+From c05a953472695ba7ad8a898639ba6736cf6d019a Mon Sep 17 00:00:00 2001
+From: "Gustavo A. R. Silva" <garsilva@embeddedor.com>
+Date: Fri, 7 Jul 2017 01:51:31 -0500
+Subject: [PATCH 02/86] iio: adc: rockchip_saradc: add NULL check on
+ of_match_device() return value
+
+Git-commit: 36d311bc1663f004529d2f870c1fc939d00c49f0
+Patch-mainline: v4.14-rc1
+References: fate#323912
+
+Check return value from call to of_match_device()
+in order to prevent a NULL pointer dereference.
+
+In case of NULL print error message and return -ENODEV
+
+Signed-off-by: Gustavo A. R. Silva <garsilva@embeddedor.com>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/iio/adc/rockchip_saradc.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c
+index ae6d3324f518..2bf2ed15a870 100644
+--- a/drivers/iio/adc/rockchip_saradc.c
++++ b/drivers/iio/adc/rockchip_saradc.c
+@@ -224,6 +224,11 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
+ info = iio_priv(indio_dev);
+
+ match = of_match_device(rockchip_saradc_match, &pdev->dev);
++ if (!match) {
++ dev_err(&pdev->dev, "failed to match device\n");
++ return -ENODEV;
++ }
++
+ info->data = match->data;
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+--
+2.11.0
+
diff --git a/patches.drivers/0003-iio-adc-rockchip_saradc-explicitly-request-exclusive.patch b/patches.drivers/0003-iio-adc-rockchip_saradc-explicitly-request-exclusive.patch
new file mode 100644
index 0000000000..d977ce5be7
--- /dev/null
+++ b/patches.drivers/0003-iio-adc-rockchip_saradc-explicitly-request-exclusive.patch
@@ -0,0 +1,49 @@
+From dd9a58312c08987e0c9c29c9771cde55a859f056 Mon Sep 17 00:00:00 2001
+From: Philipp Zabel <p.zabel@pengutronix.de>
+Date: Wed, 19 Jul 2017 17:25:35 +0200
+Subject: [PATCH 03/86] iio: adc: rockchip_saradc: explicitly request exclusive
+ reset control
+
+Git-commit: 87587016f614e96d873f883609a0099e820172e8
+Patch-mainline: v4.14-rc1
+References: fate#323912
+
+Commit a53e35db70d1 ("reset: Ensure drivers are explicit when requesting
+reset lines") started to transition the reset control request API calls
+to explicitly state whether the driver needs exclusive or shared reset
+control behavior. Convert all drivers requesting exclusive resets to the
+explicit API call so the temporary transition helpers can be removed.
+
+No functional changes.
+
+Cc: Jonathan Cameron <jic23@kernel.org>
+Cc: Hartmut Knaack <knaack.h@gmx.de>
+Cc: Lars-Peter Clausen <lars@metafoo.de>
+Cc: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
+Cc: Heiko Stuebner <heiko@sntech.de>
+Cc: linux-iio@vger.kernel.org
+Cc: linux-rockchip@lists.infradead.org
+Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/iio/adc/rockchip_saradc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c
+index 2bf2ed15a870..5f612d694b33 100644
+--- a/drivers/iio/adc/rockchip_saradc.c
++++ b/drivers/iio/adc/rockchip_saradc.c
+@@ -240,7 +240,8 @@ static int rockchip_saradc_probe(struct platform_device *pdev)
+ * The reset should be an optional property, as it should work
+ * with old devicetrees as well
+ */
+- info->reset = devm_reset_control_get(&pdev->dev, "saradc-apb");
++ info->reset = devm_reset_control_get_exclusive(&pdev->dev,
++ "saradc-apb");
+ if (IS_ERR(info->reset)) {
+ ret = PTR_ERR(info->reset);
+ if (ret != -ENOENT)
+--
+2.11.0
+
diff --git a/patches.drivers/0004-clocksource-drivers-rockchip-pr_err-strings-should-e.patch b/patches.drivers/0004-clocksource-drivers-rockchip-pr_err-strings-should-e.patch
new file mode 100644
index 0000000000..b95c87bf51
--- /dev/null
+++ b/patches.drivers/0004-clocksource-drivers-rockchip-pr_err-strings-should-e.patch
@@ -0,0 +1,37 @@
+From f37e267721786d0ebafea1f3b7d0b06f521c8b23 Mon Sep 17 00:00:00 2001
+From: Arvind Yadav <arvind.yadav.cs@gmail.com>
+Date: Mon, 25 Sep 2017 13:46:41 +0530
+Subject: [PATCH 04/86] clocksource/drivers/rockchip: pr_err() strings should
+ end with newlines
+
+Git-commit: 7d995655d7fd1606e5a76df59e32909905b17c7a
+Patch-mainline: Queued
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
+References: fate#323912
+
+pr_err() messages should end with a new-line to avoid other messages being
+concatenated.
+
+Signed-off-by: Arvind Yadav <arvind.yadav.cs@gmail.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/clocksource/rockchip_timer.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/clocksource/rockchip_timer.c b/drivers/clocksource/rockchip_timer.c
+index 49c02be50eca..54884ba39aba 100644
+--- a/drivers/clocksource/rockchip_timer.c
++++ b/drivers/clocksource/rockchip_timer.c
+@@ -274,7 +274,7 @@ static int __init rk_clksrc_init(struct device_node *np)
+ TIMER_NAME, rk_clksrc->freq, 250, 32,
+ clocksource_mmio_readl_down);
+ if (ret) {
+- pr_err("Failed to register clocksource");
++ pr_err("Failed to register clocksource\n");
+ goto out_clocksource;
+ }
+
+--
+2.11.0
+
diff --git a/patches.drivers/0005-pinctrl-rockchip-remove-unneeded-void-casts-in-of_ma.patch b/patches.drivers/0005-pinctrl-rockchip-remove-unneeded-void-casts-in-of_ma.patch
new file mode 100644
index 0000000000..cacc8694c8
--- /dev/null
+++ b/patches.drivers/0005-pinctrl-rockchip-remove-unneeded-void-casts-in-of_ma.patch
@@ -0,0 +1,66 @@
+From 5875e6e93281389a51d2e7723e787aabcb1feac5 Mon Sep 17 00:00:00 2001
+From: Masahiro Yamada <yamada.masahiro@socionext.com>
+Date: Fri, 28 Apr 2017 21:50:35 +0900
+Subject: [PATCH 05/86] pinctrl: rockchip: remove unneeded (void *) casts in
+ of_match_table
+
+Git-commit: cdbbd26f482b569b9c3a3b49887699f7a956d4e0
+Patch-mainline: v4.13-rc1
+References: fate#323912
+
+of_device_id::data is an opaque pointer. No explicit cast is needed.
+
+Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
+Reviewed-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/pinctrl/pinctrl-rockchip.c | 22 +++++++++++-----------
+ 1 file changed, 11 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
+index 9dd981ddbb17..173bbced3810 100644
+--- a/drivers/pinctrl/pinctrl-rockchip.c
++++ b/drivers/pinctrl/pinctrl-rockchip.c
+@@ -2962,27 +2962,27 @@ static struct rockchip_pin_ctrl rk3399_pin_ctrl = {
+
+ static const struct of_device_id rockchip_pinctrl_dt_match[] = {
+ { .compatible = "rockchip,rv1108-pinctrl",
+- .data = (void *)&rv1108_pin_ctrl },
++ .data = &rv1108_pin_ctrl },
+ { .compatible = "rockchip,rk2928-pinctrl",
+- .data = (void *)&rk2928_pin_ctrl },
++ .data = &rk2928_pin_ctrl },
+ { .compatible = "rockchip,rk3036-pinctrl",
+- .data = (void *)&rk3036_pin_ctrl },
++ .data = &rk3036_pin_ctrl },
+ { .compatible = "rockchip,rk3066a-pinctrl",
+- .data = (void *)&rk3066a_pin_ctrl },
++ .data = &rk3066a_pin_ctrl },
+ { .compatible = "rockchip,rk3066b-pinctrl",
+- .data = (void *)&rk3066b_pin_ctrl },
++ .data = &rk3066b_pin_ctrl },
+ { .compatible = "rockchip,rk3188-pinctrl",
+- .data = (void *)&rk3188_pin_ctrl },
++ .data = &rk3188_pin_ctrl },
+ { .compatible = "rockchip,rk3228-pinctrl",
+- .data = (void *)&rk3228_pin_ctrl },
++ .data = &rk3228_pin_ctrl },
+ { .compatible = "rockchip,rk3288-pinctrl",
+- .data = (void *)&rk3288_pin_ctrl },
++ .data = &rk3288_pin_ctrl },
+ { .compatible = "rockchip,rk3328-pinctrl",
+- .data = (void *)&rk3328_pin_ctrl },
++ .data = &rk3328_pin_ctrl },
+ { .compatible = "rockchip,rk3368-pinctrl",
+- .data = (void *)&rk3368_pin_ctrl },
++ .data = &rk3368_pin_ctrl },
+ { .compatible = "rockchip,rk3399-pinctrl",
+- .data = (void *)&rk3399_pin_ctrl },
++ .data = &rk3399_pin_ctrl },
+ {},
+ };
+
+--
+2.11.0
+
diff --git a/patches.drivers/0006-pinctrl-rockchip-Add-iomux-route-switching-support.patch b/patches.drivers/0006-pinctrl-rockchip-Add-iomux-route-switching-support.patch
new file mode 100644
index 0000000000..7468e8e1d2
--- /dev/null
+++ b/patches.drivers/0006-pinctrl-rockchip-Add-iomux-route-switching-support.patch
@@ -0,0 +1,161 @@
+From de6588f7a8e0df76b0a838ac48c93a5a142416fe Mon Sep 17 00:00:00 2001
+From: David Wu <david.wu@rock-chips.com>
+Date: Fri, 26 May 2017 15:20:20 +0800
+Subject: [PATCH 06/86] pinctrl: rockchip: Add iomux-route switching support
+
+Git-commit: bd35b9bf8284338db35b3ff0d391b95d67b90444
+Patch-mainline: v4.13-rc1
+References: fate#323912
+
+On the some rockchip SOCS, some things like rk3399 specific uart2 can use
+multiple pins. Somewhere between the pin io-cells and the uart it seems
+to have some sort of switch to decide to which pin to actually route the
+data.
+
++-------+ +--------+ /- GPIO4_B0 (pinmux 2)
+
+| uart2 | -- | switch | --- GPIO4_C0 (pinmux 2)
+
++-------+ +--------+ \- GPIO4_C3 (pinmux 2)
+(switch selects one of the 3 pins base on the GRF_SOC_CON7[BIT0, BIT1])
+
+The routing switch is determined by one pin of a specific group to be set
+to its special pinmux function. If the pinmux setting is wrong for that
+pin the ip block won't work correctly anyway.
+
+Signed-off-by: David Wu <david.wu@rock-chips.com>
+Reviewed-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/pinctrl/pinctrl-rockchip.c | 65 +++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 64 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
+index 173bbced3810..b4ca2f4ab304 100644
+--- a/drivers/pinctrl/pinctrl-rockchip.c
++++ b/drivers/pinctrl/pinctrl-rockchip.c
+@@ -143,6 +143,7 @@ struct rockchip_drv {
+ * @gpio_chip: gpiolib chip
+ * @grange: gpio range
+ * @slock: spinlock for the gpio bank
++ * @route_mask: bits describing the routing pins of per bank
+ */
+ struct rockchip_pin_bank {
+ void __iomem *reg_base;
+@@ -165,6 +166,7 @@ struct rockchip_pin_bank {
+ struct pinctrl_gpio_range grange;
+ raw_spinlock_t slock;
+ u32 toggle_edge_mode;
++ u32 route_mask;
+ };
+
+ #define PIN_BANK(id, pins, label) \
+@@ -288,6 +290,22 @@ struct rockchip_pin_bank {
+ }
+
+ /**
++ * struct rockchip_mux_recalced_data: represent a pin iomux data.
++ * @bank_num: bank number.
++ * @pin: index at register or used to calc index.
++ * @func: the min pin.
++ * @route_offset: the max pin.
++ * @route_val: the register offset.
++ */
++struct rockchip_mux_route_data {
++ u8 bank_num;
++ u8 pin;
++ u8 func;
++ u32 route_offset;
++ u32 route_val;
++};
++
++/**
+ */
+ struct rockchip_pin_ctrl {
+ struct rockchip_pin_bank *pin_banks;
+@@ -299,6 +317,8 @@ struct rockchip_pin_ctrl {
+ int pmu_mux_offset;
+ int grf_drv_offset;
+ int pmu_drv_offset;
++ struct rockchip_mux_route_data *iomux_routes;
++ u32 niomux_routes;
+
+ void (*pull_calc_reg)(struct rockchip_pin_bank *bank,
+ int pin_num, struct regmap **regmap,
+@@ -580,6 +600,30 @@ static void rk3328_recalc_mux(u8 bank_num, int pin, int *reg,
+ *bit = data->bit;
+ }
+
++static bool rockchip_get_mux_route(struct rockchip_pin_bank *bank, int pin,
++ int mux, u32 *reg, u32 *value)
++{
++ struct rockchip_pinctrl *info = bank->drvdata;
++ struct rockchip_pin_ctrl *ctrl = info->ctrl;
++ struct rockchip_mux_route_data *data;
++ int i;
++
++ for (i = 0; i < ctrl->niomux_routes; i++) {
++ data = &ctrl->iomux_routes[i];
++ if ((data->bank_num == bank->bank_num) &&
++ (data->pin == pin) && (data->func == mux))
++ break;
++ }
++
++ if (i >= ctrl->niomux_routes)
++ return false;
++
++ *reg = data->route_offset;
++ *value = data->route_val;
++
++ return true;
++}
++
+ static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin)
+ {
+ struct rockchip_pinctrl *info = bank->drvdata;
+@@ -678,7 +722,7 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
+ struct regmap *regmap;
+ int reg, ret, mask, mux_type;
+ u8 bit;
+- u32 data, rmask;
++ u32 data, rmask, route_reg, route_val;
+
+ ret = rockchip_verify_mux(bank, pin, mux);
+ if (ret < 0)
+@@ -714,6 +758,15 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
+ if (ctrl->iomux_recalc && (mux_type & IOMUX_RECALCED))
+ ctrl->iomux_recalc(bank->bank_num, pin, &reg, &bit, &mask);
+
++ if (bank->route_mask & BIT(pin)) {
++ if (rockchip_get_mux_route(bank, pin, mux, &route_reg,
++ &route_val)) {
++ ret = regmap_write(regmap, route_reg, route_val);
++ if (ret)
++ return ret;
++ }
++ }
++
+ data = (mask << (bit + 16));
+ rmask = data | (data >> 16);
+ data |= (mux & mask) << bit;
+@@ -2549,6 +2602,16 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(
+
+ bank_pins += 8;
+ }
++
++ /* calculate the per-bank route_mask */
++ for (j = 0; j < ctrl->niomux_routes; j++) {
++ int pin = 0;
++
++ if (ctrl->iomux_routes[j].bank_num == bank->bank_num) {
++ pin = ctrl->iomux_routes[j].pin;
++ bank->route_mask |= BIT(pin);
++ }
++ }
+ }
+
+ return ctrl;
+--
+2.11.0
+
diff --git a/patches.drivers/0007-pinctrl-rockchip-Add-iomux-route-switching-support-f.patch b/patches.drivers/0007-pinctrl-rockchip-Add-iomux-route-switching-support-f.patch
new file mode 100644
index 0000000000..a5b03c5f4c
--- /dev/null
+++ b/patches.drivers/0007-pinctrl-rockchip-Add-iomux-route-switching-support-f.patch
@@ -0,0 +1,174 @@
+From 14c4f31f10dd866c6f7df46d7150c54858f8a30f Mon Sep 17 00:00:00 2001
+From: David Wu <david.wu@rock-chips.com>
+Date: Fri, 26 May 2017 15:20:21 +0800
+Subject: [PATCH 07/86] pinctrl: rockchip: Add iomux-route switching support
+ for rk3228
+
+Git-commit: d4970ee076f9aed396c322b41f56443a617116df
+Patch-mainline: v4.13-rc1
+References: fate#323912
+
+There are 9 IP blocks pin routes need to be switched, that are
+pwm-0, pwm-1, pwm-2, pwm-3, sdio, spi, emmc, uart2, uart1.
+
+Signed-off-by: David Wu <david.wu@rock-chips.com>
+Reviewed-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/pinctrl/pinctrl-rockchip.c | 132 +++++++++++++++++++++++++++++++++++++
+ 1 file changed, 132 insertions(+)
+
+diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
+index b4ca2f4ab304..5df96319036f 100644
+--- a/drivers/pinctrl/pinctrl-rockchip.c
++++ b/drivers/pinctrl/pinctrl-rockchip.c
+@@ -600,6 +600,136 @@ static void rk3328_recalc_mux(u8 bank_num, int pin, int *reg,
+ *bit = data->bit;
+ }
+
++static struct rockchip_mux_route_data rk3228_mux_route_data[] = {
++ {
++ /* pwm0-0 */
++ .bank_num = 0,
++ .pin = 26,
++ .func = 1,
++ .route_offset = 0x50,
++ .route_val = BIT(16),
++ }, {
++ /* pwm0-1 */
++ .bank_num = 3,
++ .pin = 21,
++ .func = 1,
++ .route_offset = 0x50,
++ .route_val = BIT(16) | BIT(0),
++ }, {
++ /* pwm1-0 */
++ .bank_num = 0,
++ .pin = 27,
++ .func = 1,
++ .route_offset = 0x50,
++ .route_val = BIT(16 + 1),
++ }, {
++ /* pwm1-1 */
++ .bank_num = 0,
++ .pin = 30,
++ .func = 2,
++ .route_offset = 0x50,
++ .route_val = BIT(16 + 1) | BIT(1),
++ }, {
++ /* pwm2-0 */
++ .bank_num = 0,
++ .pin = 28,
++ .func = 1,
++ .route_offset = 0x50,
++ .route_val = BIT(16 + 2),
++ }, {
++ /* pwm2-1 */
++ .bank_num = 1,
++ .pin = 12,
++ .func = 2,
++ .route_offset = 0x50,
++ .route_val = BIT(16 + 2) | BIT(2),
++ }, {
++ /* pwm3-0 */
++ .bank_num = 3,
++ .pin = 26,
++ .func = 1,
++ .route_offset = 0x50,
++ .route_val = BIT(16 + 3),
++ }, {
++ /* pwm3-1 */
++ .bank_num = 1,
++ .pin = 11,
++ .func = 2,
++ .route_offset = 0x50,
++ .route_val = BIT(16 + 3) | BIT(3),
++ }, {
++ /* sdio-0_d0 */
++ .bank_num = 1,
++ .pin = 1,
++ .func = 1,
++ .route_offset = 0x50,
++ .route_val = BIT(16 + 4),
++ }, {
++ /* sdio-1_d0 */
++ .bank_num = 3,
++ .pin = 2,
++ .func = 1,
++ .route_offset = 0x50,
++ .route_val = BIT(16 + 4) | BIT(4),
++ }, {
++ /* spi-0_rx */
++ .bank_num = 0,
++ .pin = 13,
++ .func = 2,
++ .route_offset = 0x50,
++ .route_val = BIT(16 + 5),
++ }, {
++ /* spi-1_rx */
++ .bank_num = 2,
++ .pin = 0,
++ .func = 2,
++ .route_offset = 0x50,
++ .route_val = BIT(16 + 5) | BIT(5),
++ }, {
++ /* emmc-0_cmd */
++ .bank_num = 1,
++ .pin = 22,
++ .func = 2,
++ .route_offset = 0x50,
++ .route_val = BIT(16 + 7),
++ }, {
++ /* emmc-1_cmd */
++ .bank_num = 2,
++ .pin = 4,
++ .func = 2,
++ .route_offset = 0x50,
++ .route_val = BIT(16 + 7) | BIT(7),
++ }, {
++ /* uart2-0_rx */
++ .bank_num = 1,
++ .pin = 19,
++ .func = 2,
++ .route_offset = 0x50,
++ .route_val = BIT(16 + 8),
++ }, {
++ /* uart2-1_rx */
++ .bank_num = 1,
++ .pin = 10,
++ .func = 2,
++ .route_offset = 0x50,
++ .route_val = BIT(16 + 8) | BIT(8),
++ }, {
++ /* uart1-0_rx */
++ .bank_num = 1,
++ .pin = 10,
++ .func = 1,
++ .route_offset = 0x50,
++ .route_val = BIT(16 + 11),
++ }, {
++ /* uart1-1_rx */
++ .bank_num = 3,
++ .pin = 13,
++ .func = 1,
++ .route_offset = 0x50,
++ .route_val = BIT(16 + 11) | BIT(11),
++ },
++};
++
+ static bool rockchip_get_mux_route(struct rockchip_pin_bank *bank, int pin,
+ int mux, u32 *reg, u32 *value)
+ {
+@@ -2862,6 +2992,8 @@ static struct rockchip_pin_ctrl rk3228_pin_ctrl = {
+ .label = "RK3228-GPIO",
+ .type = RK3288,
+ .grf_mux_offset = 0x0,
++ .iomux_routes = rk3228_mux_route_data,
++ .niomux_routes = ARRAY_SIZE(rk3228_mux_route_data),
+ .pull_calc_reg = rk3228_calc_pull_reg_and_bit,
+ .drv_calc_reg = rk3228_calc_drv_reg_and_bit,
+ };
+--
+2.11.0
+
diff --git a/patches.drivers/0008-pinctrl-rockchip-Add-iomux-route-switching-support-f.patch b/patches.drivers/0008-pinctrl-rockchip-Add-iomux-route-switching-support-f.patch
new file mode 100644
index 0000000000..2a633f4a08
--- /dev/null
+++ b/patches.drivers/0008-pinctrl-rockchip-Add-iomux-route-switching-support-f.patch
@@ -0,0 +1,125 @@
+From 475956ac654268726da37522cadc9260db01231d Mon Sep 17 00:00:00 2001
+From: David Wu <david.wu@rock-chips.com>
+Date: Fri, 26 May 2017 15:20:22 +0800
+Subject: [PATCH 08/86] pinctrl: rockchip: Add iomux-route switching support
+ for rk3328
+
+Git-commit: cedc964a59d48c793ddc0884b2f72a68fc234ae4
+Patch-mainline: v4.13-rc1
+References: fate#323912
+
+There are 8 IP blocks pin routes need to be switched, that are
+uart2dbg, gmac-m1-optimized, pdm, spi, i2s2, card, tsp, cif.
+
+Signed-off-by: David Wu <david.wu@rock-chips.com>
+Reviewed-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/pinctrl/pinctrl-rockchip.c | 83 ++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 83 insertions(+)
+
+diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
+index 5df96319036f..a0568a2cc125 100644
+--- a/drivers/pinctrl/pinctrl-rockchip.c
++++ b/drivers/pinctrl/pinctrl-rockchip.c
+@@ -730,6 +730,87 @@ static struct rockchip_mux_route_data rk3228_mux_route_data[] = {
+ },
+ };
+
++static struct rockchip_mux_route_data rk3328_mux_route_data[] = {
++ {
++ /* uart2dbg_rxm0 */
++ .bank_num = 1,
++ .pin = 1,
++ .func = 2,
++ .route_offset = 0x50,
++ .route_val = BIT(16) | BIT(16 + 1),
++ }, {
++ /* uart2dbg_rxm1 */
++ .bank_num = 2,
++ .pin = 1,
++ .func = 1,
++ .route_offset = 0x50,
++ .route_val = BIT(16) | BIT(16 + 1) | BIT(0),
++ }, {
++ /* gmac-m1-optimized_rxd0 */
++ .bank_num = 1,
++ .pin = 11,
++ .func = 2,
++ .route_offset = 0x50,
++ .route_val = BIT(16 + 2) | BIT(16 + 10) | BIT(2) | BIT(10),
++ }, {
++ /* pdm_sdi0m0 */
++ .bank_num = 2,
++ .pin = 19,
++ .func = 2,
++ .route_offset = 0x50,
++ .route_val = BIT(16 + 3),
++ }, {
++ /* pdm_sdi0m1 */
++ .bank_num = 1,
++ .pin = 23,
++ .func = 3,
++ .route_offset = 0x50,
++ .route_val = BIT(16 + 3) | BIT(3),
++ }, {
++ /* spi_rxdm2 */
++ .bank_num = 3,
++ .pin = 2,
++ .func = 4,
++ .route_offset = 0x50,
++ .route_val = BIT(16 + 4) | BIT(16 + 5) | BIT(5),
++ }, {
++ /* i2s2_sdim0 */
++ .bank_num = 1,
++ .pin = 24,
++ .func = 1,
++ .route_offset = 0x50,
++ .route_val = BIT(16 + 6),
++ }, {
++ /* i2s2_sdim1 */
++ .bank_num = 3,
++ .pin = 2,
++ .func = 6,
++ .route_offset = 0x50,
++ .route_val = BIT(16 + 6) | BIT(6),
++ }, {
++ /* card_iom1 */
++ .bank_num = 2,
++ .pin = 22,
++ .func = 3,
++ .route_offset = 0x50,
++ .route_val = BIT(16 + 7) | BIT(7),
++ }, {
++ /* tsp_d5m1 */
++ .bank_num = 2,
++ .pin = 16,
++ .func = 3,
++ .route_offset = 0x50,
++ .route_val = BIT(16 + 8) | BIT(8),
++ }, {
++ /* cif_data5m1 */
++ .bank_num = 2,
++ .pin = 16,
++ .func = 4,
++ .route_offset = 0x50,
++ .route_val = BIT(16 + 9) | BIT(9),
++ },
++};
++
+ static bool rockchip_get_mux_route(struct rockchip_pin_bank *bank, int pin,
+ int mux, u32 *reg, u32 *value)
+ {
+@@ -3061,6 +3142,8 @@ static struct rockchip_pin_ctrl rk3328_pin_ctrl = {
+ .label = "RK3328-GPIO",
+ .type = RK3288,
+ .grf_mux_offset = 0x0,
++ .iomux_routes = rk3328_mux_route_data,
++ .niomux_routes = ARRAY_SIZE(rk3328_mux_route_data),
+ .pull_calc_reg = rk3228_calc_pull_reg_and_bit,
+ .drv_calc_reg = rk3228_calc_drv_reg_and_bit,
+ .iomux_recalc = rk3328_recalc_mux,
+--
+2.11.0
+
diff --git a/patches.drivers/0009-pinctrl-rockchip-Add-iomux-route-switching-support-f.patch b/patches.drivers/0009-pinctrl-rockchip-Add-iomux-route-switching-support-f.patch
new file mode 100644
index 0000000000..f218bc4d66
--- /dev/null
+++ b/patches.drivers/0009-pinctrl-rockchip-Add-iomux-route-switching-support-f.patch
@@ -0,0 +1,83 @@
+From 666db9c0405102aa362c0eb6a588d5772b841220 Mon Sep 17 00:00:00 2001
+From: David Wu <david.wu@rock-chips.com>
+Date: Fri, 26 May 2017 15:20:23 +0800
+Subject: [PATCH 09/86] pinctrl: rockchip: Add iomux-route switching support
+ for rk3399
+
+Git-commit: accc1ce7d2ffc6419a8eaf8c0190d9240df0c43f
+Patch-mainline: v4.13-rc1
+References: fate#323912
+
+There are 2 IP blocks pin routes need to be switched, that are
+uart2dbg, pcie_clkreq.
+
+Signed-off-by: David Wu <david.wu@rock-chips.com>
+Reviewed-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/pinctrl/pinctrl-rockchip.c | 41 ++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 41 insertions(+)
+
+diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
+index a0568a2cc125..e831647c56a6 100644
+--- a/drivers/pinctrl/pinctrl-rockchip.c
++++ b/drivers/pinctrl/pinctrl-rockchip.c
+@@ -811,6 +811,45 @@ static struct rockchip_mux_route_data rk3328_mux_route_data[] = {
+ },
+ };
+
++static struct rockchip_mux_route_data rk3399_mux_route_data[] = {
++ {
++ /* uart2dbga_rx */
++ .bank_num = 4,
++ .pin = 8,
++ .func = 2,
++ .route_offset = 0xe21c,
++ .route_val = BIT(16 + 10) | BIT(16 + 11),
++ }, {
++ /* uart2dbgb_rx */
++ .bank_num = 4,
++ .pin = 16,
++ .func = 2,
++ .route_offset = 0xe21c,
++ .route_val = BIT(16 + 10) | BIT(16 + 11) | BIT(10),
++ }, {
++ /* uart2dbgc_rx */
++ .bank_num = 4,
++ .pin = 19,
++ .func = 1,
++ .route_offset = 0xe21c,
++ .route_val = BIT(16 + 10) | BIT(16 + 11) | BIT(11),
++ }, {
++ /* pcie_clkreqn */
++ .bank_num = 2,
++ .pin = 26,
++ .func = 2,
++ .route_offset = 0xe21c,
++ .route_val = BIT(16 + 14),
++ }, {
++ /* pcie_clkreqnb */
++ .bank_num = 4,
++ .pin = 24,
++ .func = 1,
++ .route_offset = 0xe21c,
++ .route_val = BIT(16 + 14) | BIT(14),
++ },
++};
++
+ static bool rockchip_get_mux_route(struct rockchip_pin_bank *bank, int pin,
+ int mux, u32 *reg, u32 *value)
+ {
+@@ -3234,6 +3273,8 @@ static struct rockchip_pin_ctrl rk3399_pin_ctrl = {
+ .pmu_mux_offset = 0x0,
+ .grf_drv_offset = 0xe100,
+ .pmu_drv_offset = 0x80,
++ .iomux_routes = rk3399_mux_route_data,
++ .niomux_routes = ARRAY_SIZE(rk3399_mux_route_data),
+ .pull_calc_reg = rk3399_calc_pull_reg_and_bit,
+ .drv_calc_reg = rk3399_calc_drv_reg_and_bit,
+ };
+--
+2.11.0
+
diff --git a/patches.drivers/0010-pinctrl-rockchip-Use-common-interface-for-recalced-i.patch b/patches.drivers/0010-pinctrl-rockchip-Use-common-interface-for-recalced-i.patch
new file mode 100644
index 0000000000..d8557c52c3
--- /dev/null
+++ b/patches.drivers/0010-pinctrl-rockchip-Use-common-interface-for-recalced-i.patch
@@ -0,0 +1,234 @@
+From f18e92e0bdb4b1b0ed7799e243684b1fa8eed642 Mon Sep 17 00:00:00 2001
+From: David Wu <david.wu@rock-chips.com>
+Date: Fri, 21 Jul 2017 14:27:14 +0800
+Subject: [PATCH 10/86] pinctrl: rockchip: Use common interface for recalced
+ iomux
+
+Git-commit: c04c3fa65ac5c66711584322669b8e8fd9ae2a7a
+Patch-mainline: v4.14-rc1
+References: fate#323912
+
+The other Socs also need the feature of recalced iomux, so
+make it as a common interface like iomux route feature.
+
+Signed-off-by: David Wu <david.wu@rock-chips.com>
+Reviewed-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/pinctrl/pinctrl-rockchip.c | 89 +++++++++++++++++++++-----------------
+ 1 file changed, 50 insertions(+), 39 deletions(-)
+
+diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
+index e831647c56a6..fd4e491225df 100644
+--- a/drivers/pinctrl/pinctrl-rockchip.c
++++ b/drivers/pinctrl/pinctrl-rockchip.c
+@@ -76,7 +76,6 @@ enum rockchip_pinctrl_type {
+ #define IOMUX_SOURCE_PMU BIT(2)
+ #define IOMUX_UNROUTED BIT(3)
+ #define IOMUX_WIDTH_3BIT BIT(4)
+-#define IOMUX_RECALCED BIT(5)
+
+ /**
+ * @type: iomux variant using IOMUX_* constants
+@@ -166,6 +165,7 @@ struct rockchip_pin_bank {
+ struct pinctrl_gpio_range grange;
+ raw_spinlock_t slock;
+ u32 toggle_edge_mode;
++ u32 recalced_mask;
+ u32 route_mask;
+ };
+
+@@ -291,6 +291,22 @@ struct rockchip_pin_bank {
+
+ /**
+ * struct rockchip_mux_recalced_data: represent a pin iomux data.
++ * @num: bank number.
++ * @pin: pin number.
++ * @bit: index at register.
++ * @reg: register offset.
++ * @mask: mask bit
++ */
++struct rockchip_mux_recalced_data {
++ u8 num;
++ u8 pin;
++ u8 reg;
++ u8 bit;
++ u8 mask;
++};
++
++/**
++ * struct rockchip_mux_recalced_data: represent a pin iomux data.
+ * @bank_num: bank number.
+ * @pin: index at register or used to calc index.
+ * @func: the min pin.
+@@ -317,6 +333,8 @@ struct rockchip_pin_ctrl {
+ int pmu_mux_offset;
+ int grf_drv_offset;
+ int pmu_drv_offset;
++ struct rockchip_mux_recalced_data *iomux_recalced;
++ u32 niomux_recalced;
+ struct rockchip_mux_route_data *iomux_routes;
+ u32 niomux_routes;
+
+@@ -326,8 +344,6 @@ struct rockchip_pin_ctrl {
+ void (*drv_calc_reg)(struct rockchip_pin_bank *bank,
+ int pin_num, struct regmap **regmap,
+ int *reg, u8 *bit);
+- void (*iomux_recalc)(u8 bank_num, int pin, int *reg,
+- u8 *bit, int *mask);
+ int (*schmitt_calc_reg)(struct rockchip_pin_bank *bank,
+ int pin_num, struct regmap **regmap,
+ int *reg, u8 *bit);
+@@ -382,22 +398,6 @@ struct rockchip_pinctrl {
+ unsigned int nfunctions;
+ };
+
+-/**
+- * struct rockchip_mux_recalced_data: represent a pin iomux data.
+- * @num: bank number.
+- * @pin: pin number.
+- * @bit: index at register.
+- * @reg: register offset.
+- * @mask: mask bit
+- */
+-struct rockchip_mux_recalced_data {
+- u8 num;
+- u8 pin;
+- u8 reg;
+- u8 bit;
+- u8 mask;
+-};
+-
+ static struct regmap_config rockchip_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+@@ -557,7 +557,7 @@ static const struct pinctrl_ops rockchip_pctrl_ops = {
+ * Hardware access
+ */
+
+-static const struct rockchip_mux_recalced_data rk3328_mux_recalced_data[] = {
++static struct rockchip_mux_recalced_data rk3328_mux_recalced_data[] = {
+ {
+ .num = 2,
+ .pin = 12,
+@@ -579,20 +579,22 @@ static const struct rockchip_mux_recalced_data rk3328_mux_recalced_data[] = {
+ },
+ };
+
+-static void rk3328_recalc_mux(u8 bank_num, int pin, int *reg,
+- u8 *bit, int *mask)
++static void rockchip_get_recalced_mux(struct rockchip_pin_bank *bank, int pin,
++ int *reg, u8 *bit, int *mask)
+ {
+- const struct rockchip_mux_recalced_data *data = NULL;
++ struct rockchip_pinctrl *info = bank->drvdata;
++ struct rockchip_pin_ctrl *ctrl = info->ctrl;
++ struct rockchip_mux_recalced_data *data;
+ int i;
+
+- for (i = 0; i < ARRAY_SIZE(rk3328_mux_recalced_data); i++)
+- if (rk3328_mux_recalced_data[i].num == bank_num &&
+- rk3328_mux_recalced_data[i].pin == pin) {
+- data = &rk3328_mux_recalced_data[i];
++ for (i = 0; i < ctrl->niomux_recalced; i++) {
++ data = &ctrl->iomux_recalced[i];
++ if (data->num == bank->bank_num &&
++ data->pin == pin)
+ break;
+- }
++ }
+
+- if (!data)
++ if (i >= ctrl->niomux_recalced)
+ return;
+
+ *reg = data->reg;
+@@ -877,7 +879,6 @@ static bool rockchip_get_mux_route(struct rockchip_pin_bank *bank, int pin,
+ static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin)
+ {
+ struct rockchip_pinctrl *info = bank->drvdata;
+- struct rockchip_pin_ctrl *ctrl = info->ctrl;
+ int iomux_num = (pin / 8);
+ struct regmap *regmap;
+ unsigned int val;
+@@ -916,8 +917,8 @@ static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin)
+ mask = 0x3;
+ }
+
+- if (ctrl->iomux_recalc && (mux_type & IOMUX_RECALCED))
+- ctrl->iomux_recalc(bank->bank_num, pin, &reg, &bit, &mask);
++ if (bank->recalced_mask & BIT(pin))
++ rockchip_get_recalced_mux(bank, pin, &reg, &bit, &mask);
+
+ ret = regmap_read(regmap, reg, &val);
+ if (ret)
+@@ -967,7 +968,6 @@ static int rockchip_verify_mux(struct rockchip_pin_bank *bank,
+ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
+ {
+ struct rockchip_pinctrl *info = bank->drvdata;
+- struct rockchip_pin_ctrl *ctrl = info->ctrl;
+ int iomux_num = (pin / 8);
+ struct regmap *regmap;
+ int reg, ret, mask, mux_type;
+@@ -1005,8 +1005,8 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
+ mask = 0x3;
+ }
+
+- if (ctrl->iomux_recalc && (mux_type & IOMUX_RECALCED))
+- ctrl->iomux_recalc(bank->bank_num, pin, &reg, &bit, &mask);
++ if (bank->recalced_mask & BIT(pin))
++ rockchip_get_recalced_mux(bank, pin, &reg, &bit, &mask);
+
+ if (bank->route_mask & BIT(pin)) {
+ if (rockchip_get_mux_route(bank, pin, mux, &route_reg,
+@@ -2853,6 +2853,16 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(
+ bank_pins += 8;
+ }
+
++ /* calculate the per-bank recalced_mask */
++ for (j = 0; j < ctrl->niomux_recalced; j++) {
++ int pin = 0;
++
++ if (ctrl->iomux_recalced[j].num == bank->bank_num) {
++ pin = ctrl->iomux_recalced[j].pin;
++ bank->recalced_mask |= BIT(pin);
++ }
++ }
++
+ /* calculate the per-bank route_mask */
+ for (j = 0; j < ctrl->niomux_routes; j++) {
+ int pin = 0;
+@@ -3165,12 +3175,12 @@ static struct rockchip_pin_bank rk3328_pin_banks[] = {
+ PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", 0, 0, 0, 0),
+ PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", 0, 0, 0, 0),
+ PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0,
+- IOMUX_WIDTH_3BIT | IOMUX_RECALCED,
+- IOMUX_WIDTH_3BIT | IOMUX_RECALCED,
++ IOMUX_WIDTH_3BIT,
++ IOMUX_WIDTH_3BIT,
+ 0),
+ PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3",
+ IOMUX_WIDTH_3BIT,
+- IOMUX_WIDTH_3BIT | IOMUX_RECALCED,
++ IOMUX_WIDTH_3BIT,
+ 0,
+ 0),
+ };
+@@ -3181,11 +3191,12 @@ static struct rockchip_pin_ctrl rk3328_pin_ctrl = {
+ .label = "RK3328-GPIO",
+ .type = RK3288,
+ .grf_mux_offset = 0x0,
++ .iomux_recalced = rk3328_mux_recalced_data,
++ .niomux_recalced = ARRAY_SIZE(rk3328_mux_recalced_data),
+ .iomux_routes = rk3328_mux_route_data,
+ .niomux_routes = ARRAY_SIZE(rk3328_mux_route_data),
+ .pull_calc_reg = rk3228_calc_pull_reg_and_bit,
+ .drv_calc_reg = rk3228_calc_drv_reg_and_bit,
+- .iomux_recalc = rk3328_recalc_mux,
+ .schmitt_calc_reg = rk3328_calc_schmitt_reg_and_bit,
+ };
+
+--
+2.11.0
+
diff --git a/patches.drivers/0011-pinctrl-rockchip-Fix-the-rk3399-gpio0-and-gpio1-bank.patch b/patches.drivers/0011-pinctrl-rockchip-Fix-the-rk3399-gpio0-and-gpio1-bank.patch
new file mode 100644
index 0000000000..62b8d7474a
--- /dev/null
+++ b/patches.drivers/0011-pinctrl-rockchip-Fix-the-rk3399-gpio0-and-gpio1-bank.patch
@@ -0,0 +1,56 @@
+From 2e20dd6104584f9e50d54e45b6bb24b68e8ec9c6 Mon Sep 17 00:00:00 2001
+From: David Wu <david.wu@rock-chips.com>
+Date: Sat, 30 Sep 2017 20:13:20 +0800
+Subject: [PATCH 11/86] pinctrl: rockchip: Fix the rk3399 gpio0 and gpio1
+ banks' drv_offset at pmu grf
+
+Git-commit: c437f65c42d2640ababace37eb89bff2395c1dc3
+Patch-mainline: Queued
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
+References: fate#323912
+
+The offset of gpio0 and gpio1 bank drive strength is 0x8, not 0x4.
+But the mux is 0x4, we couldn't use the IOMUX_WIDTH_4BIT flag, so
+we give them actual offset.
+
+Signed-off-by: David Wu <david.wu@rock-chips.com>
+Reviewed-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/pinctrl/pinctrl-rockchip.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
+index fd4e491225df..a1928ebb6388 100644
+--- a/drivers/pinctrl/pinctrl-rockchip.c
++++ b/drivers/pinctrl/pinctrl-rockchip.c
+@@ -3232,8 +3232,8 @@ static struct rockchip_pin_bank rk3399_pin_banks[] = {
+ DRV_TYPE_IO_1V8_ONLY,
+ DRV_TYPE_IO_DEFAULT,
+ DRV_TYPE_IO_DEFAULT,
+- 0x0,
+- 0x8,
++ 0x80,
++ 0x88,
+ -1,
+ -1,
+ PULL_TYPE_IO_1V8_ONLY,
+@@ -3249,10 +3249,10 @@ static struct rockchip_pin_bank rk3399_pin_banks[] = {
+ DRV_TYPE_IO_1V8_OR_3V0,
+ DRV_TYPE_IO_1V8_OR_3V0,
+ DRV_TYPE_IO_1V8_OR_3V0,
+- 0x20,
+- 0x28,
+- 0x30,
+- 0x38
++ 0xa0,
++ 0xa8,
++ 0xb0,
++ 0xb8
+ ),
+ PIN_BANK_DRV_FLAGS_PULL_FLAGS(2, 32, "gpio2", DRV_TYPE_IO_1V8_OR_3V0,
+ DRV_TYPE_IO_1V8_OR_3V0,
+--
+2.11.0
+
diff --git a/patches.drivers/0012-iommu-rockchip-Enable-Rockchip-IOMMU-on-ARM64.patch b/patches.drivers/0012-iommu-rockchip-Enable-Rockchip-IOMMU-on-ARM64.patch
new file mode 100644
index 0000000000..a73ba06e2e
--- /dev/null
+++ b/patches.drivers/0012-iommu-rockchip-Enable-Rockchip-IOMMU-on-ARM64.patch
@@ -0,0 +1,39 @@
+From bd9fdcffa0ccf858391511cfa83eac9025b488b6 Mon Sep 17 00:00:00 2001
+From: Simon Xue <xxm@rock-chips.com>
+Date: Wed, 3 May 2017 17:19:40 +0200
+Subject: [PATCH 12/86] iommu/rockchip: Enable Rockchip IOMMU on ARM64
+
+Git-commit: 4f1fcfe94c1700f9e891adc1ca364a5cef00bbfd
+Patch-mainline: v4.13-rc1
+References: fate#323912
+
+This patch makes it possible to compile the rockchip-iommu driver on
+ARM64, so that it can be used with 64-bit SoCs equipped with this type
+of IOMMU.
+
+Signed-off-by: Simon Xue <xxm@rock-chips.com>
+Signed-off-by: Shunqian Zheng <zhengsq@rock-chips.com>
+Signed-off-by: Tomasz Figa <tfiga@chromium.org>
+Reviewed-by: Matthias Brugger <mbrugger@suse.com>
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/iommu/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
+index 6ee3a25ae731..99c6366a2551 100644
+--- a/drivers/iommu/Kconfig
++++ b/drivers/iommu/Kconfig
+@@ -219,7 +219,7 @@ config OMAP_IOMMU_DEBUG
+
+ config ROCKCHIP_IOMMU
+ bool "Rockchip IOMMU Support"
+- depends on ARM
++ depends on ARM || ARM64
+ depends on ARCH_ROCKCHIP || COMPILE_TEST
+ select IOMMU_API
+ select ARM_DMA_USE_IOMMU
+--
+2.11.0
+
diff --git a/patches.drivers/0013-iommu-rockchip-add-multi-irqs-support.patch b/patches.drivers/0013-iommu-rockchip-add-multi-irqs-support.patch
new file mode 100644
index 0000000000..3963badef9
--- /dev/null
+++ b/patches.drivers/0013-iommu-rockchip-add-multi-irqs-support.patch
@@ -0,0 +1,89 @@
+From e3c8f4799a03e13ecad4806703d493174a4e2ac8 Mon Sep 17 00:00:00 2001
+From: Simon Xue <xxm@rock-chips.com>
+Date: Mon, 24 Jul 2017 10:37:14 +0800
+Subject: [PATCH 13/86] iommu/rockchip: add multi irqs support
+
+Git-commit: 03f732f89034b3f5fbe7ef34cd3482f2e9c335cf
+Patch-mainline: v4.14-rc1
+References: fate#323912
+
+RK3368 vpu mmu have two irqs, this patch support multi irqs
+
+Signed-off-by: Simon Xue <xxm@rock-chips.com>
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/iommu/rockchip-iommu.c | 35 ++++++++++++++++++++++++++---------
+ 1 file changed, 26 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
+index 4ba48a26b389..e2852b041231 100644
+--- a/drivers/iommu/rockchip-iommu.c
++++ b/drivers/iommu/rockchip-iommu.c
+@@ -90,7 +90,8 @@ struct rk_iommu {
+ struct device *dev;
+ void __iomem **bases;
+ int num_mmu;
+- int irq;
++ int *irq;
++ int num_irq;
+ struct iommu_device iommu;
+ struct list_head node; /* entry in rk_iommu_domain.iommus */
+ struct iommu_domain *domain; /* domain to which iommu is attached */
+@@ -825,10 +826,12 @@ static int rk_iommu_attach_device(struct iommu_domain *domain,
+
+ iommu->domain = domain;
+
+- ret = devm_request_irq(iommu->dev, iommu->irq, rk_iommu_irq,
+- IRQF_SHARED, dev_name(dev), iommu);
+- if (ret)
+- return ret;
++ for (i = 0; i < iommu->num_irq; i++) {
++ ret = devm_request_irq(iommu->dev, iommu->irq[i], rk_iommu_irq,
++ IRQF_SHARED, dev_name(dev), iommu);
++ if (ret)
++ return ret;
++ }
+
+ for (i = 0; i < iommu->num_mmu; i++) {
+ rk_iommu_write(iommu->bases[i], RK_MMU_DTE_ADDR,
+@@ -878,7 +881,8 @@ static void rk_iommu_detach_device(struct iommu_domain *domain,
+ }
+ rk_iommu_disable_stall(iommu);
+
+- devm_free_irq(iommu->dev, iommu->irq, iommu);
++ for (i = 0; i < iommu->num_irq; i++)
++ devm_free_irq(iommu->dev, iommu->irq[i], iommu);
+
+ iommu->domain = NULL;
+
+@@ -1157,10 +1161,23 @@ static int rk_iommu_probe(struct platform_device *pdev)
+ if (iommu->num_mmu == 0)
+ return PTR_ERR(iommu->bases[0]);
+
+- iommu->irq = platform_get_irq(pdev, 0);
+- if (iommu->irq < 0) {
+- dev_err(dev, "Failed to get IRQ, %d\n", iommu->irq);
++ iommu->num_irq = platform_irq_count(pdev);
++ if (iommu->num_irq < 0)
++ return iommu->num_irq;
++ if (iommu->num_irq == 0)
+ return -ENXIO;
++
++ iommu->irq = devm_kcalloc(dev, iommu->num_irq, sizeof(*iommu->irq),
++ GFP_KERNEL);
++ if (!iommu->irq)
++ return -ENOMEM;
++
++ for (i = 0; i < iommu->num_irq; i++) {
++ iommu->irq[i] = platform_get_irq(pdev, i);
++ if (iommu->irq[i] < 0) {
++ dev_err(dev, "Failed to get IRQ, %d\n", iommu->irq[i]);
++ return -ENXIO;
++ }
+ }
+
+ err = iommu_device_sysfs_add(&iommu->iommu, dev, NULL, dev_name(dev));
+--
+2.11.0
+
diff --git a/patches.drivers/0014-iommu-rockchip-ignore-isp-mmu-reset-operation.patch b/patches.drivers/0014-iommu-rockchip-ignore-isp-mmu-reset-operation.patch
new file mode 100644
index 0000000000..b2e84c6ab8
--- /dev/null
+++ b/patches.drivers/0014-iommu-rockchip-ignore-isp-mmu-reset-operation.patch
@@ -0,0 +1,55 @@
+From 70c45286e5697f4b2173a7dd9fc722375a9cfb37 Mon Sep 17 00:00:00 2001
+From: Simon Xue <xxm@rock-chips.com>
+Date: Mon, 24 Jul 2017 10:37:15 +0800
+Subject: [PATCH 14/86] iommu/rockchip: ignore isp mmu reset operation
+
+Git-commit: c3aa47424918acdfed8982d5a3588351ebefdfc1
+Patch-mainline: v4.14-rc1
+References: fate#323912
+
+ISP mmu can't support reset operation, it won't get the
+expected result when reset, but rest functions work normally.
+Add this patch as a WA for this issue.
+
+Signed-off-by: Simon Xue <xxm@rock-chips.com>
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/iommu/rockchip-iommu.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
+index e2852b041231..78ea341c7c75 100644
+--- a/drivers/iommu/rockchip-iommu.c
++++ b/drivers/iommu/rockchip-iommu.c
+@@ -92,6 +92,7 @@ struct rk_iommu {
+ int num_mmu;
+ int *irq;
+ int num_irq;
++ bool reset_disabled;
+ struct iommu_device iommu;
+ struct list_head node; /* entry in rk_iommu_domain.iommus */
+ struct iommu_domain *domain; /* domain to which iommu is attached */
+@@ -415,6 +416,9 @@ static int rk_iommu_force_reset(struct rk_iommu *iommu)
+ int ret, i;
+ u32 dte_addr;
+
++ if (iommu->reset_disabled)
++ return 0;
++
+ /*
+ * Check if register DTE_ADDR is working by writing DTE_ADDR_DUMMY
+ * and verifying that upper 5 nybbles are read back.
+@@ -1180,6 +1184,9 @@ static int rk_iommu_probe(struct platform_device *pdev)
+ }
+ }
+
++ iommu->reset_disabled = device_property_read_bool(dev,
++ "rockchip,disable-mmu-reset");
++
+ err = iommu_device_sysfs_add(&iommu->iommu, dev, NULL, dev_name(dev));
+ if (err)
+ return err;
+--
+2.11.0
+
diff --git a/patches.drivers/0015-spi-rockchip-fix-error-handling-when-probe.patch b/patches.drivers/0015-spi-rockchip-fix-error-handling-when-probe.patch
new file mode 100644
index 0000000000..ee7527d203
--- /dev/null
+++ b/patches.drivers/0015-spi-rockchip-fix-error-handling-when-probe.patch
@@ -0,0 +1,115 @@
+From 415d52ab7f221846bd0171072216649087210e2e Mon Sep 17 00:00:00 2001
+From: Jeffy Chen <jeffy.chen@rock-chips.com>
+Date: Tue, 13 Jun 2017 13:25:40 +0800
+Subject: [PATCH 15/86] spi: rockchip: fix error handling when probe
+
+Git-commit: c351587e2502050f36d16e9e32c6c98975ecd6a2
+Patch-mainline: v4.13-rc1
+References: fate#323912
+
+After failed to request dma tx chain, we need to disable pm_runtime.
+Also cleanup error labels for better readability.
+
+Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
+Reviewed-by: Brian Norris <briannorris@chromium.org>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/spi/spi-rockchip.c | 27 ++++++++++++++-------------
+ 1 file changed, 14 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
+index acf31f36b898..bab9b13f0ad0 100644
+--- a/drivers/spi/spi-rockchip.c
++++ b/drivers/spi/spi-rockchip.c
+@@ -684,33 +684,33 @@ static int rockchip_spi_probe(struct platform_device *pdev)
+ rs->regs = devm_ioremap_resource(&pdev->dev, mem);
+ if (IS_ERR(rs->regs)) {
+ ret = PTR_ERR(rs->regs);
+- goto err_ioremap_resource;
++ goto err_put_master;
+ }
+
+ rs->apb_pclk = devm_clk_get(&pdev->dev, "apb_pclk");
+ if (IS_ERR(rs->apb_pclk)) {
+ dev_err(&pdev->dev, "Failed to get apb_pclk\n");
+ ret = PTR_ERR(rs->apb_pclk);
+- goto err_ioremap_resource;
++ goto err_put_master;
+ }
+
+ rs->spiclk = devm_clk_get(&pdev->dev, "spiclk");
+ if (IS_ERR(rs->spiclk)) {
+ dev_err(&pdev->dev, "Failed to get spi_pclk\n");
+ ret = PTR_ERR(rs->spiclk);
+- goto err_ioremap_resource;
++ goto err_put_master;
+ }
+
+ ret = clk_prepare_enable(rs->apb_pclk);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to enable apb_pclk\n");
+- goto err_ioremap_resource;
++ goto err_put_master;
+ }
+
+ ret = clk_prepare_enable(rs->spiclk);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to enable spi_clk\n");
+- goto err_spiclk_enable;
++ goto err_disable_apbclk;
+ }
+
+ spi_enable_chip(rs, 0);
+@@ -728,7 +728,7 @@ static int rockchip_spi_probe(struct platform_device *pdev)
+ if (!rs->fifo_len) {
+ dev_err(&pdev->dev, "Failed to get fifo length\n");
+ ret = -EINVAL;
+- goto err_get_fifo_len;
++ goto err_disable_spiclk;
+ }
+
+ spin_lock_init(&rs->lock);
+@@ -755,7 +755,7 @@ static int rockchip_spi_probe(struct platform_device *pdev)
+ /* Check tx to see if we need defer probing driver */
+ if (PTR_ERR(rs->dma_tx.ch) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+- goto err_get_fifo_len;
++ goto err_disable_pm_runtime;
+ }
+ dev_warn(rs->dev, "Failed to request TX DMA channel\n");
+ rs->dma_tx.ch = NULL;
+@@ -786,23 +786,24 @@ static int rockchip_spi_probe(struct platform_device *pdev)
+ ret = devm_spi_register_master(&pdev->dev, master);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to register master\n");
+- goto err_register_master;
++ goto err_free_dma_rx;
+ }
+
+ return 0;
+
+-err_register_master:
+- pm_runtime_disable(&pdev->dev);
++err_free_dma_rx:
+ if (rs->dma_rx.ch)
+ dma_release_channel(rs->dma_rx.ch);
+ err_free_dma_tx:
+ if (rs->dma_tx.ch)
+ dma_release_channel(rs->dma_tx.ch);
+-err_get_fifo_len:
++err_disable_pm_runtime:
++ pm_runtime_disable(&pdev->dev);
++err_disable_spiclk:
+ clk_disable_unprepare(rs->spiclk);
+-err_spiclk_enable:
++err_disable_apbclk:
+ clk_disable_unprepare(rs->apb_pclk);
+-err_ioremap_resource:
++err_put_master:
+ spi_master_put(master);
+
+ return ret;
+--
+2.11.0
+
diff --git a/patches.drivers/0016-spi-rockchip-Set-GPIO_SS-flag-to-enable-Slave-Select.patch b/patches.drivers/0016-spi-rockchip-Set-GPIO_SS-flag-to-enable-Slave-Select.patch
new file mode 100644
index 0000000000..d4c54315b3
--- /dev/null
+++ b/patches.drivers/0016-spi-rockchip-Set-GPIO_SS-flag-to-enable-Slave-Select.patch
@@ -0,0 +1,35 @@
+From 0f2a43a55a74671100286ac908f71efe3b840507 Mon Sep 17 00:00:00 2001
+From: Jeffy Chen <jeffy.chen@rock-chips.com>
+Date: Wed, 28 Jun 2017 12:38:42 +0800
+Subject: [PATCH 16/86] spi: rockchip: Set GPIO_SS flag to enable Slave Select
+ with GPIO CS
+
+Git-commit: c863795c4c0787e5f885099e3b673e1433448b82
+Patch-mainline: v4.13-rc1
+References: fate#323912
+
+The rockchip spi still requires slave selection when using GPIO CS.
+
+Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
+Reviewed-by: Douglas Anderson <dianders@chromium.org>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/spi/spi-rockchip.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
+index bab9b13f0ad0..52ea1605d4c6 100644
+--- a/drivers/spi/spi-rockchip.c
++++ b/drivers/spi/spi-rockchip.c
+@@ -749,6 +749,7 @@ static int rockchip_spi_probe(struct platform_device *pdev)
+ master->transfer_one = rockchip_spi_transfer_one;
+ master->max_transfer_size = rockchip_spi_max_transfer_size;
+ master->handle_err = rockchip_spi_handle_err;
++ master->flags = SPI_MASTER_GPIO_SS;
+
+ rs->dma_tx.ch = dma_request_chan(rs->dev, "tx");
+ if (IS_ERR(rs->dma_tx.ch)) {
+--
+2.11.0
+
diff --git a/patches.drivers/0017-spi-rockchip-Disable-Runtime-PM-when-chip-select-is-.patch b/patches.drivers/0017-spi-rockchip-Disable-Runtime-PM-when-chip-select-is-.patch
new file mode 100644
index 0000000000..c4fe93caf1
--- /dev/null
+++ b/patches.drivers/0017-spi-rockchip-Disable-Runtime-PM-when-chip-select-is-.patch
@@ -0,0 +1,129 @@
+From 77eb994453b29c93be8e2bd31036b0844f5ce430 Mon Sep 17 00:00:00 2001
+From: Jeffy Chen <jeffy.chen@rock-chips.com>
+Date: Wed, 28 Jun 2017 12:38:43 +0800
+Subject: [PATCH 17/86] spi: rockchip: Disable Runtime PM when chip select is
+ asserted
+
+Git-commit: aa099382ac0cda27e10fa8f45bf91edea0d1d35e
+Patch-mainline: v4.13-rc1
+References: fate#323912
+
+The rockchip spi would stop driving pins when runtime suspended, which
+might break slave's xfer(for example cros_ec).
+
+Since we have pullups on those pins, we only need to care about this
+when the CS asserted.
+
+So let's keep the spi alive when chip select is asserted.
+
+Also use pm_runtime_put instead of pm_runtime_put_sync.
+
+Suggested-by: Doug Anderson <dianders@chromium.org>
+Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
+Reviewed-by: Douglas Anderson <dianders@chromium.org>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/spi/spi-rockchip.c | 51 +++++++++++++++++++++++-----------------------
+ 1 file changed, 26 insertions(+), 25 deletions(-)
+
+diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
+index 52ea1605d4c6..0b4a52b3e1dc 100644
+--- a/drivers/spi/spi-rockchip.c
++++ b/drivers/spi/spi-rockchip.c
+@@ -25,6 +25,11 @@
+
+ #define DRIVER_NAME "rockchip-spi"
+
++#define ROCKCHIP_SPI_CLR_BITS(reg, bits) \
++ writel_relaxed(readl_relaxed(reg) & ~(bits), reg)
++#define ROCKCHIP_SPI_SET_BITS(reg, bits) \
++ writel_relaxed(readl_relaxed(reg) | (bits), reg)
++
+ /* SPI register offsets */
+ #define ROCKCHIP_SPI_CTRLR0 0x0000
+ #define ROCKCHIP_SPI_CTRLR1 0x0004
+@@ -149,6 +154,8 @@
+ */
+ #define ROCKCHIP_SPI_MAX_TRANLEN 0xffff
+
++#define ROCKCHIP_SPI_MAX_CS_NUM 2
++
+ enum rockchip_ssi_type {
+ SSI_MOTO_SPI = 0,
+ SSI_TI_SSP,
+@@ -193,6 +200,8 @@ struct rockchip_spi {
+ /* protect state */
+ spinlock_t lock;
+
++ bool cs_asserted[ROCKCHIP_SPI_MAX_CS_NUM];
++
+ u32 use_dma;
+ struct sg_table tx_sg;
+ struct sg_table rx_sg;
+@@ -264,37 +273,29 @@ static inline u32 rx_max(struct rockchip_spi *rs)
+
+ static void rockchip_spi_set_cs(struct spi_device *spi, bool enable)
+ {
+- u32 ser;
+ struct spi_master *master = spi->master;
+ struct rockchip_spi *rs = spi_master_get_devdata(master);
++ bool cs_asserted = !enable;
+
+- pm_runtime_get_sync(rs->dev);
++ /* Return immediately for no-op */
++ if (cs_asserted == rs->cs_asserted[spi->chip_select])
++ return;
+
+- ser = readl_relaxed(rs->regs + ROCKCHIP_SPI_SER) & SER_MASK;
++ if (cs_asserted) {
++ /* Keep things powered as long as CS is asserted */
++ pm_runtime_get_sync(rs->dev);
+
+- /*
+- * drivers/spi/spi.c:
+- * static void spi_set_cs(struct spi_device *spi, bool enable)
+- * {
+- * if (spi->mode & SPI_CS_HIGH)
+- * enable = !enable;
+- *
+- * if (spi->cs_gpio >= 0)
+- * gpio_set_value(spi->cs_gpio, !enable);
+- * else if (spi->master->set_cs)
+- * spi->master->set_cs(spi, !enable);
+- * }
+- *
+- * Note: enable(rockchip_spi_set_cs) = !enable(spi_set_cs)
+- */
+- if (!enable)
+- ser |= 1 << spi->chip_select;
+- else
+- ser &= ~(1 << spi->chip_select);
++ ROCKCHIP_SPI_SET_BITS(rs->regs + ROCKCHIP_SPI_SER,
++ BIT(spi->chip_select));
++ } else {
++ ROCKCHIP_SPI_CLR_BITS(rs->regs + ROCKCHIP_SPI_SER,
++ BIT(spi->chip_select));
+
+- writel_relaxed(ser, rs->regs + ROCKCHIP_SPI_SER);
++ /* Drop reference from when we first asserted CS */
++ pm_runtime_put(rs->dev);
++ }
+
+- pm_runtime_put_sync(rs->dev);
++ rs->cs_asserted[spi->chip_select] = cs_asserted;
+ }
+
+ static int rockchip_spi_prepare_message(struct spi_master *master,
+@@ -739,7 +740,7 @@ static int rockchip_spi_probe(struct platform_device *pdev)
+ master->auto_runtime_pm = true;
+ master->bus_num = pdev->id;
+ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP;
+- master->num_chipselect = 2;
++ master->num_chipselect = ROCKCHIP_SPI_MAX_CS_NUM;
+ master->dev.of_node = pdev->dev.of_node;
+ master->bits_per_word_mask = SPI_BPW_MASK(16) | SPI_BPW_MASK(8);
+
+--
+2.11.0
+
diff --git a/patches.drivers/0018-spi-rockchip-Slightly-rework-return-value-handling.patch b/patches.drivers/0018-spi-rockchip-Slightly-rework-return-value-handling.patch
new file mode 100644
index 0000000000..457dd6b48f
--- /dev/null
+++ b/patches.drivers/0018-spi-rockchip-Slightly-rework-return-value-handling.patch
@@ -0,0 +1,116 @@
+From 2b325874b66c47bc34dd9c62a2d42b58515aaf96 Mon Sep 17 00:00:00 2001
+From: Jeffy Chen <jeffy.chen@rock-chips.com>
+Date: Mon, 7 Aug 2017 20:40:18 +0800
+Subject: [PATCH 18/86] spi: rockchip: Slightly rework return value handling
+
+Git-commit: 43de979ddc099c57858b243619c66e2f663a2f97
+Patch-mainline: v4.14-rc1
+References: fate#323912
+
+Slightly rework return value handling, no functional changes.
+
+Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/spi/spi-rockchip.c | 24 ++++++++++++------------
+ 1 file changed, 12 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
+index 0b4a52b3e1dc..5497650992c7 100644
+--- a/drivers/spi/spi-rockchip.c
++++ b/drivers/spi/spi-rockchip.c
+@@ -666,7 +666,7 @@ static bool rockchip_spi_can_dma(struct spi_master *master,
+
+ static int rockchip_spi_probe(struct platform_device *pdev)
+ {
+- int ret = 0;
++ int ret;
+ struct rockchip_spi *rs;
+ struct spi_master *master;
+ struct resource *mem;
+@@ -703,13 +703,13 @@ static int rockchip_spi_probe(struct platform_device *pdev)
+ }
+
+ ret = clk_prepare_enable(rs->apb_pclk);
+- if (ret) {
++ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to enable apb_pclk\n");
+ goto err_put_master;
+ }
+
+ ret = clk_prepare_enable(rs->spiclk);
+- if (ret) {
++ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to enable spi_clk\n");
+ goto err_disable_apbclk;
+ }
+@@ -786,7 +786,7 @@ static int rockchip_spi_probe(struct platform_device *pdev)
+ }
+
+ ret = devm_spi_register_master(&pdev->dev, master);
+- if (ret) {
++ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to register master\n");
+ goto err_free_dma_rx;
+ }
+@@ -834,12 +834,12 @@ static int rockchip_spi_remove(struct platform_device *pdev)
+ #ifdef CONFIG_PM_SLEEP
+ static int rockchip_spi_suspend(struct device *dev)
+ {
+- int ret = 0;
++ int ret;
+ struct spi_master *master = dev_get_drvdata(dev);
+ struct rockchip_spi *rs = spi_master_get_devdata(master);
+
+ ret = spi_master_suspend(rs->master);
+- if (ret)
++ if (ret < 0)
+ return ret;
+
+ if (!pm_runtime_suspended(dev)) {
+@@ -849,12 +849,12 @@ static int rockchip_spi_suspend(struct device *dev)
+
+ pinctrl_pm_select_sleep_state(dev);
+
+- return ret;
++ return 0;
+ }
+
+ static int rockchip_spi_resume(struct device *dev)
+ {
+- int ret = 0;
++ int ret;
+ struct spi_master *master = dev_get_drvdata(dev);
+ struct rockchip_spi *rs = spi_master_get_devdata(master);
+
+@@ -878,7 +878,7 @@ static int rockchip_spi_resume(struct device *dev)
+ clk_disable_unprepare(rs->apb_pclk);
+ }
+
+- return ret;
++ return 0;
+ }
+ #endif /* CONFIG_PM_SLEEP */
+
+@@ -901,14 +901,14 @@ static int rockchip_spi_runtime_resume(struct device *dev)
+ struct rockchip_spi *rs = spi_master_get_devdata(master);
+
+ ret = clk_prepare_enable(rs->apb_pclk);
+- if (ret)
++ if (ret < 0)
+ return ret;
+
+ ret = clk_prepare_enable(rs->spiclk);
+- if (ret)
++ if (ret < 0)
+ clk_disable_unprepare(rs->apb_pclk);
+
+- return ret;
++ return 0;
+ }
+ #endif /* CONFIG_PM */
+
+--
+2.11.0
+
diff --git a/patches.drivers/0019-spi-rockchip-Fix-clock-handling-in-remove.patch b/patches.drivers/0019-spi-rockchip-Fix-clock-handling-in-remove.patch
new file mode 100644
index 0000000000..cffc0b1cfc
--- /dev/null
+++ b/patches.drivers/0019-spi-rockchip-Fix-clock-handling-in-remove.patch
@@ -0,0 +1,46 @@
+From 221f384bbc66b53166592509daf1f44d34fb61dd Mon Sep 17 00:00:00 2001
+From: Jeffy Chen <jeffy.chen@rock-chips.com>
+Date: Mon, 7 Aug 2017 20:40:19 +0800
+Subject: [PATCH 19/86] spi: rockchip: Fix clock handling in remove
+
+Git-commit: 6a06e895b262621a81b3b08126b4bc5e1b8eef05
+Patch-mainline: v4.14-rc1
+References: fate#323912
+
+We are assuming clocks enabled when calling rockchip_spi_remove, which
+is not always true. Those clocks might already been disabled by the
+runtime PM at that time.
+
+Call pm_runtime_get_sync before trying to disable clocks to avoid that.
+
+Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/spi/spi-rockchip.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
+index 5497650992c7..a75fd9bb76de 100644
+--- a/drivers/spi/spi-rockchip.c
++++ b/drivers/spi/spi-rockchip.c
+@@ -816,11 +816,15 @@ static int rockchip_spi_remove(struct platform_device *pdev)
+ struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
+ struct rockchip_spi *rs = spi_master_get_devdata(master);
+
+- pm_runtime_disable(&pdev->dev);
++ pm_runtime_get_sync(&pdev->dev);
+
+ clk_disable_unprepare(rs->spiclk);
+ clk_disable_unprepare(rs->apb_pclk);
+
++ pm_runtime_put_noidle(&pdev->dev);
++ pm_runtime_disable(&pdev->dev);
++ pm_runtime_set_suspended(&pdev->dev);
++
+ if (rs->dma_tx.ch)
+ dma_release_channel(rs->dma_tx.ch);
+ if (rs->dma_rx.ch)
+--
+2.11.0
+
diff --git a/patches.drivers/0020-spi-rockchip-Fix-clock-handling-in-suspend-resume.patch b/patches.drivers/0020-spi-rockchip-Fix-clock-handling-in-suspend-resume.patch
new file mode 100644
index 0000000000..448ace1f4a
--- /dev/null
+++ b/patches.drivers/0020-spi-rockchip-Fix-clock-handling-in-suspend-resume.patch
@@ -0,0 +1,65 @@
+From dc72d4940fe373c97446790b4b083250c7ed0c7c Mon Sep 17 00:00:00 2001
+From: Jeffy Chen <jeffy.chen@rock-chips.com>
+Date: Mon, 7 Aug 2017 20:40:20 +0800
+Subject: [PATCH 20/86] spi: rockchip: Fix clock handling in suspend/resume
+
+Git-commit: d38c4ae194bb8a3d8cf7d95378c5b2799cdd0a3b
+Patch-mainline: v4.14-rc1
+References: fate#323912
+
+The runtime suspend callback might be called by pm domain framework at
+suspend_noirq stage. It would try to disable the clocks which already
+been disabled by rockchip_spi_suspend.
+
+Call pm_runtime_force_suspend/pm_runtime_force_resume when
+suspend/resume to avoid that.
+
+Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/spi/spi-rockchip.c | 21 ++++++---------------
+ 1 file changed, 6 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
+index a75fd9bb76de..34f6440a5255 100644
+--- a/drivers/spi/spi-rockchip.c
++++ b/drivers/spi/spi-rockchip.c
+@@ -846,10 +846,9 @@ static int rockchip_spi_suspend(struct device *dev)
+ if (ret < 0)
+ return ret;
+
+- if (!pm_runtime_suspended(dev)) {
+- clk_disable_unprepare(rs->spiclk);
+- clk_disable_unprepare(rs->apb_pclk);
+- }
++ ret = pm_runtime_force_suspend(dev);
++ if (ret < 0)
++ return ret;
+
+ pinctrl_pm_select_sleep_state(dev);
+
+@@ -864,17 +863,9 @@ static int rockchip_spi_resume(struct device *dev)
+
+ pinctrl_pm_select_default_state(dev);
+
+- if (!pm_runtime_suspended(dev)) {
+- ret = clk_prepare_enable(rs->apb_pclk);
+- if (ret < 0)
+- return ret;
+-
+- ret = clk_prepare_enable(rs->spiclk);
+- if (ret < 0) {
+- clk_disable_unprepare(rs->apb_pclk);
+- return ret;
+- }
+- }
++ ret = pm_runtime_force_resume(dev);
++ if (ret < 0)
++ return ret;
+
+ ret = spi_master_resume(rs->master);
+ if (ret < 0) {
+--
+2.11.0
+
diff --git a/patches.drivers/0021-spi-rockchip-configure-CTRLR1-according-to-size-and-.patch b/patches.drivers/0021-spi-rockchip-configure-CTRLR1-according-to-size-and-.patch
new file mode 100644
index 0000000000..1532718c11
--- /dev/null
+++ b/patches.drivers/0021-spi-rockchip-configure-CTRLR1-according-to-size-and-.patch
@@ -0,0 +1,43 @@
+From 3e4c194c78a397ccb227951cb67b5077c4d8ca34 Mon Sep 17 00:00:00 2001
+From: Huibin Hong <huibin.hong@rock-chips.com>
+Date: Wed, 16 Aug 2017 10:12:02 +0800
+Subject: [PATCH 21/86] spi: rockchip: configure CTRLR1 according to size and
+ data frame
+
+Git-commit: 04b37d2d02c0a5ae2f4e59326ef6deaff18e0456
+Patch-mainline: v4.14-rc1
+References: fate#323912
+
+CTRLR1 is number of data frames, when rx only.
+When data frame is 8 bit, CTRLR1 is len-1.
+When data frame is 16 bit, CTRLR1 is (len/2)-1.
+
+Signed-off-by: Huibin Hong <huibin.hong@rock-chips.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/spi/spi-rockchip.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
+index 34f6440a5255..7df207f176fc 100644
+--- a/drivers/spi/spi-rockchip.c
++++ b/drivers/spi/spi-rockchip.c
+@@ -568,7 +568,13 @@ static void rockchip_spi_config(struct rockchip_spi *rs)
+
+ writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0);
+
+- writel_relaxed(rs->len - 1, rs->regs + ROCKCHIP_SPI_CTRLR1);
++ if (rs->n_bytes == 1)
++ writel_relaxed(rs->len - 1, rs->regs + ROCKCHIP_SPI_CTRLR1);
++ else if (rs->n_bytes == 2)
++ writel_relaxed((rs->len / 2) - 1, rs->regs + ROCKCHIP_SPI_CTRLR1);
++ else
++ writel_relaxed((rs->len * 2) - 1, rs->regs + ROCKCHIP_SPI_CTRLR1);
++
+ writel_relaxed(rs->fifo_len / 2 - 1, rs->regs + ROCKCHIP_SPI_TXFTLR);
+ writel_relaxed(rs->fifo_len / 2 - 1, rs->regs + ROCKCHIP_SPI_RXFTLR);
+
+--
+2.11.0
+
diff --git a/patches.drivers/0022-clk-rockchip-add-ids-for-camera-on-rk3399.patch b/patches.drivers/0022-clk-rockchip-add-ids-for-camera-on-rk3399.patch
new file mode 100644
index 0000000000..5f54cc8e48
--- /dev/null
+++ b/patches.drivers/0022-clk-rockchip-add-ids-for-camera-on-rk3399.patch
@@ -0,0 +1,34 @@
+From 3eec7529aa71fde5ca51359e57464e88a3a901ef Mon Sep 17 00:00:00 2001
+From: Eddie Cai <eddie.cai.linux@gmail.com>
+Date: Tue, 25 Apr 2017 14:41:09 +0800
+Subject: [PATCH 22/86] clk: rockchip: add ids for camera on rk3399
+
+Git-commit: f22e4359cd73fc335df4b13e85dbcda8bf1f25f0
+Patch-mainline: v4.13-rc1
+References: fate#323912
+
+we use SCLK_TESTCLKOUT1 and SCLK_TESTCLKOUT2 for camera, so add those ids.
+
+Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ include/dt-bindings/clock/rk3399-cru.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/include/dt-bindings/clock/rk3399-cru.h b/include/dt-bindings/clock/rk3399-cru.h
+index 220a60f20d3b..22cb1dfa9004 100644
+--- a/include/dt-bindings/clock/rk3399-cru.h
++++ b/include/dt-bindings/clock/rk3399-cru.h
+@@ -132,6 +132,8 @@
+ #define SCLK_RMII_SRC 166
+ #define SCLK_PCIEPHY_REF100M 167
+ #define SCLK_DDRC 168
++#define SCLK_TESTCLKOUT1 169
++#define SCLK_TESTCLKOUT2 170
+
+ #define DCLK_VOP0 180
+ #define DCLK_VOP1 181
+--
+2.11.0
+
diff --git a/patches.drivers/0023-clk-rockchip-add-dt-binding-header-for-rk3128.patch b/patches.drivers/0023-clk-rockchip-add-dt-binding-header-for-rk3128.patch
new file mode 100644
index 0000000000..1d5dac940e
--- /dev/null
+++ b/patches.drivers/0023-clk-rockchip-add-dt-binding-header-for-rk3128.patch
@@ -0,0 +1,315 @@
+From 9ae2aed3761adb3104d733cc6d2767c176794065 Mon Sep 17 00:00:00 2001
+From: Elaine Zhang <zhangqing@rock-chips.com>
+Date: Fri, 2 Jun 2017 09:47:23 +0800
+Subject: [PATCH 23/86] clk: rockchip: add dt-binding header for rk3128
+
+Git-commit: b20841b9e0d730206de6ee95f4d00e3f8815ad50
+Patch-mainline: v4.13-rc1
+References: fate#323912
+
+Add the dt-bindings header for the rk3128,
+that gets shared between the clock controller and
+the clock references in the dts.
+Add softreset ID for rk3128.
+And it also applies to the RK3126 SoC.
+
+Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
+Acked-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ include/dt-bindings/clock/rk3128-cru.h | 282 +++++++++++++++++++++++++++++++++
+ 1 file changed, 282 insertions(+)
+ create mode 100644 include/dt-bindings/clock/rk3128-cru.h
+
+diff --git a/include/dt-bindings/clock/rk3128-cru.h b/include/dt-bindings/clock/rk3128-cru.h
+new file mode 100644
+index 000000000000..92894f4306cf
+--- /dev/null
++++ b/include/dt-bindings/clock/rk3128-cru.h
+@@ -0,0 +1,282 @@
++/*
++ * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
++ * Author: Elaine <zhangqing@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, 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.
++ */
++
++#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3128_H
++#define _DT_BINDINGS_CLK_ROCKCHIP_RK3128_H
++
++/* core clocks */
++#define PLL_APLL 1
++#define PLL_DPLL 2
++#define PLL_CPLL 3
++#define PLL_GPLL 4
++#define ARMCLK 5
++#define PLL_GPLL_DIV2 6
++#define PLL_GPLL_DIV3 7
++
++/* sclk gates (special clocks) */
++#define SCLK_SPI0 65
++#define SCLK_NANDC 67
++#define SCLK_SDMMC 68
++#define SCLK_SDIO 69
++#define SCLK_EMMC 71
++#define SCLK_UART0 77
++#define SCLK_UART1 78
++#define SCLK_UART2 79
++#define SCLK_I2S0 80
++#define SCLK_I2S1 81
++#define SCLK_SPDIF 83
++#define SCLK_TIMER0 85
++#define SCLK_TIMER1 86
++#define SCLK_TIMER2 87
++#define SCLK_TIMER3 88
++#define SCLK_TIMER4 89
++#define SCLK_TIMER5 90
++#define SCLK_SARADC 91
++#define SCLK_I2S_OUT 113
++#define SCLK_SDMMC_DRV 114
++#define SCLK_SDIO_DRV 115
++#define SCLK_EMMC_DRV 117
++#define SCLK_SDMMC_SAMPLE 118
++#define SCLK_SDIO_SAMPLE 119
++#define SCLK_EMMC_SAMPLE 121
++#define SCLK_VOP 122
++#define SCLK_MAC_SRC 124
++#define SCLK_MAC 126
++#define SCLK_MAC_REFOUT 127
++#define SCLK_MAC_REF 128
++#define SCLK_MAC_RX 129
++#define SCLK_MAC_TX 130
++#define SCLK_HEVC_CORE 134
++#define SCLK_RGA 135
++#define SCLK_CRYPTO 138
++#define SCLK_TSP 139
++#define SCLK_OTGPHY0 142
++#define SCLK_OTGPHY1 143
++#define SCLK_DDRC 144
++#define SCLK_PVTM_FUNC 145
++#define SCLK_PVTM_CORE 146
++#define SCLK_PVTM_GPU 147
++#define SCLK_MIPI_24M 148
++#define SCLK_PVTM 149
++#define SCLK_CIF_SRC 150
++#define SCLK_CIF_OUT_SRC 151
++#define SCLK_CIF_OUT 152
++#define SCLK_SFC 153
++#define SCLK_USB480M 154
++
++/* dclk gates */
++#define DCLK_VOP 190
++#define DCLK_EBC 191
++
++/* aclk gates */
++#define ACLK_VIO0 192
++#define ACLK_VIO1 193
++#define ACLK_DMAC 194
++#define ACLK_CPU 195
++#define ACLK_VEPU 196
++#define ACLK_VDPU 197
++#define ACLK_CIF 198
++#define ACLK_IEP 199
++#define ACLK_LCDC0 204
++#define ACLK_RGA 205
++#define ACLK_PERI 210
++#define ACLK_VOP 211
++#define ACLK_GMAC 212
++#define ACLK_GPU 213
++
++/* pclk gates */
++#define PCLK_SARADC 318
++#define PCLK_WDT 319
++#define PCLK_GPIO0 320
++#define PCLK_GPIO1 321
++#define PCLK_GPIO2 322
++#define PCLK_GPIO3 323
++#define PCLK_VIO_H2P 324
++#define PCLK_MIPI 325
++#define PCLK_EFUSE 326
++#define PCLK_HDMI 327
++#define PCLK_ACODEC 328
++#define PCLK_GRF 329
++#define PCLK_I2C0 332
++#define PCLK_I2C1 333
++#define PCLK_I2C2 334
++#define PCLK_I2C3 335
++#define PCLK_SPI0 338
++#define PCLK_UART0 341
++#define PCLK_UART1 342
++#define PCLK_UART2 343
++#define PCLK_TSADC 344
++#define PCLK_PWM 350
++#define PCLK_TIMER 353
++#define PCLK_CPU 354
++#define PCLK_PERI 363
++#define PCLK_GMAC 367
++#define PCLK_PMU_PRE 368
++#define PCLK_SIM_CARD 369
++
++/* hclk gates */
++#define HCLK_SPDIF 440
++#define HCLK_GPS 441
++#define HCLK_USBHOST 442
++#define HCLK_I2S_8CH 443
++#define HCLK_I2S_2CH 444
++#define HCLK_VOP 452
++#define HCLK_NANDC 453
++#define HCLK_SDMMC 456
++#define HCLK_SDIO 457
++#define HCLK_EMMC 459
++#define HCLK_CPU 460
++#define HCLK_VEPU 461
++#define HCLK_VDPU 462
++#define HCLK_LCDC0 463
++#define HCLK_EBC 465
++#define HCLK_VIO 466
++#define HCLK_RGA 467
++#define HCLK_IEP 468
++#define HCLK_VIO_H2P 469
++#define HCLK_CIF 470
++#define HCLK_HOST2 473
++#define HCLK_OTG 474
++#define HCLK_TSP 475
++#define HCLK_CRYPTO 476
++#define HCLK_PERI 478
++
++#define CLK_NR_CLKS (HCLK_PERI + 1)
++
++/* soft-reset indices */
++#define SRST_CORE0_PO 0
++#define SRST_CORE1_PO 1
++#define SRST_CORE2_PO 2
++#define SRST_CORE3_PO 3
++#define SRST_CORE0 4
++#define SRST_CORE1 5
++#define SRST_CORE2 6
++#define SRST_CORE3 7
++#define SRST_CORE0_DBG 8
++#define SRST_CORE1_DBG 9
++#define SRST_CORE2_DBG 10
++#define SRST_CORE3_DBG 11
++#define SRST_TOPDBG 12
++#define SRST_ACLK_CORE 13
++#define SRST_STRC_SYS_A 14
++#define SRST_L2C 15
++
++#define SRST_CPUSYS_H 18
++#define SRST_AHB2APBSYS_H 19
++#define SRST_SPDIF 20
++#define SRST_INTMEM 21
++#define SRST_ROM 22
++#define SRST_PERI_NIU 23
++#define SRST_I2S_2CH 24
++#define SRST_I2S_8CH 25
++#define SRST_GPU_PVTM 26
++#define SRST_FUNC_PVTM 27
++#define SRST_CORE_PVTM 29
++#define SRST_EFUSE_P 30
++#define SRST_ACODEC_P 31
++
++#define SRST_GPIO0 32
++#define SRST_GPIO1 33
++#define SRST_GPIO2 34
++#define SRST_GPIO3 35
++#define SRST_MIPIPHY_P 36
++#define SRST_UART0 39
++#define SRST_UART1 40
++#define SRST_UART2 41
++#define SRST_I2C0 43
++#define SRST_I2C1 44
++#define SRST_I2C2 45
++#define SRST_I2C3 46
++#define SRST_SFC 47
++
++#define SRST_PWM 48
++#define SRST_DAP_PO 50
++#define SRST_DAP 51
++#define SRST_DAP_SYS 52
++#define SRST_CRYPTO 53
++#define SRST_GRF 55
++#define SRST_GMAC 56
++#define SRST_PERIPH_SYS_A 57
++#define SRST_PERIPH_SYS_H 58
++#define SRST_PERIPH_SYS_P 59
++#define SRST_SMART_CARD 60
++#define SRST_CPU_PERI 61
++#define SRST_EMEM_PERI 62
++#define SRST_USB_PERI 63
++
++#define SRST_DMA 64
++#define SRST_GPS 67
++#define SRST_NANDC 68
++#define SRST_USBOTG0 69
++#define SRST_OTGC0 71
++#define SRST_USBOTG1 72
++#define SRST_OTGC1 74
++#define SRST_DDRMSCH 79
++
++#define SRST_SDMMC 81
++#define SRST_SDIO 82
++#define SRST_EMMC 83
++#define SRST_SPI 84
++#define SRST_WDT 86
++#define SRST_SARADC 87
++#define SRST_DDRPHY 88
++#define SRST_DDRPHY_P 89
++#define SRST_DDRCTRL 90
++#define SRST_DDRCTRL_P 91
++#define SRST_TSP 92
++#define SRST_TSP_CLKIN 93
++#define SRST_HOST0_ECHI 94
++
++#define SRST_HDMI_P 96
++#define SRST_VIO_ARBI_H 97
++#define SRST_VIO0_A 98
++#define SRST_VIO_BUS_H 99
++#define SRST_VOP_A 100
++#define SRST_VOP_H 101
++#define SRST_VOP_D 102
++#define SRST_UTMI0 103
++#define SRST_UTMI1 104
++#define SRST_USBPOR 105
++#define SRST_IEP_A 106
++#define SRST_IEP_H 107
++#define SRST_RGA_A 108
++#define SRST_RGA_H 109
++#define SRST_CIF0 110
++#define SRST_PMU 111
++
++#define SRST_VCODEC_A 112
++#define SRST_VCODEC_H 113
++#define SRST_VIO1_A 114
++#define SRST_HEVC_CORE 115
++#define SRST_VCODEC_NIU_A 116
++#define SRST_PMU_NIU_P 117
++#define SRST_LCDC0_S 119
++#define SRST_GPU 120
++#define SRST_GPU_NIU_A 122
++#define SRST_EBC_A 123
++#define SRST_EBC_H 124
++
++#define SRST_CORE_DBG 128
++#define SRST_DBG_P 129
++#define SRST_TIMER0 130
++#define SRST_TIMER1 131
++#define SRST_TIMER2 132
++#define SRST_TIMER3 133
++#define SRST_TIMER4 134
++#define SRST_TIMER5 135
++#define SRST_VIO_H2P 136
++#define SRST_VIO_MIPI_DSI 137
++
++#endif
+--
+2.11.0
+
diff --git a/patches.drivers/0024-clk-rockchip-add-ids-for-rk3399-testclks-used-for-ca.patch b/patches.drivers/0024-clk-rockchip-add-ids-for-rk3399-testclks-used-for-ca.patch
new file mode 100644
index 0000000000..3197b78260
--- /dev/null
+++ b/patches.drivers/0024-clk-rockchip-add-ids-for-rk3399-testclks-used-for-ca.patch
@@ -0,0 +1,42 @@
+From fbec6cbce3c0d825b4f78ae995a257586d2e21f3 Mon Sep 17 00:00:00 2001
+From: Eddie Cai <eddie.cai.linux@gmail.com>
+Date: Tue, 25 Apr 2017 14:41:10 +0800
+Subject: [PATCH 24/86] clk: rockchip: add ids for rk3399 testclks used for
+ camera handling
+
+Git-commit: 25fb42b1cfde85f905dd1d61ea1e089c16e1ad77
+Patch-mainline: v4.13-rc1
+References: fate#323912
+
+clk_testout1 and clk_testout2 are used for camera handling, so add their ids.
+
+Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/clk/rockchip/clk-rk3399.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c
+index fa3cbef08776..6847120b61cd 100644
+--- a/drivers/clk/rockchip/clk-rk3399.c
++++ b/drivers/clk/rockchip/clk-rk3399.c
+@@ -1066,13 +1066,13 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
+ /* cif_testout */
+ MUX(0, "clk_testout1_pll_src", mux_pll_src_cpll_gpll_npll_p, 0,
+ RK3399_CLKSEL_CON(38), 6, 2, MFLAGS),
+- COMPOSITE(0, "clk_testout1", mux_clk_testout1_p, 0,
++ COMPOSITE(SCLK_TESTCLKOUT1, "clk_testout1", mux_clk_testout1_p, 0,
+ RK3399_CLKSEL_CON(38), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(13), 14, GFLAGS),
+
+ MUX(0, "clk_testout2_pll_src", mux_pll_src_cpll_gpll_npll_p, 0,
+ RK3399_CLKSEL_CON(38), 14, 2, MFLAGS),
+- COMPOSITE(0, "clk_testout2", mux_clk_testout2_p, 0,
++ COMPOSITE(SCLK_TESTCLKOUT2, "clk_testout2", mux_clk_testout2_p, 0,
+ RK3399_CLKSEL_CON(38), 13, 1, MFLAGS, 8, 5, DFLAGS,
+ RK3399_CLKGATE_CON(13), 15, GFLAGS),
+
+--
+2.11.0
+
diff --git a/patches.drivers/0025-clk-fractional-divider-allow-overriding-of-approxima.patch b/patches.drivers/0025-clk-fractional-divider-allow-overriding-of-approxima.patch
new file mode 100644
index 0000000000..c9695f5643
--- /dev/null
+++ b/patches.drivers/0025-clk-fractional-divider-allow-overriding-of-approxima.patch
@@ -0,0 +1,94 @@
+From 449c3a968dbfd0fe1a65d5a725c9cac4c9dc7fda Mon Sep 17 00:00:00 2001
+From: Elaine Zhang <zhangqing@rock-chips.com>
+Date: Tue, 1 Aug 2017 18:21:22 +0200
+Subject: [PATCH 25/86] clk: fractional-divider: allow overriding of
+ approximation
+
+Git-commit: ec52e462564b9c5bfdf1f79638c537c7103e1d2b
+Patch-mainline: v4.14-rc1
+References: fate#323912
+
+Fractional dividers may have special requirements concerning numerator
+and denominator selection that differ from just getting the best
+approximation.
+
+For example on Rockchip socs the denominator must be at least 20 times
+larger than the numerator to generate precise clock frequencies.
+
+Therefore add the ability to provide custom approximation functions.
+
+Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
+Acked-by: Stephen Boyd <sboyd@codeaurora.org>
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/clk/clk-fractional-divider.c | 28 ++++++++++++++++++++--------
+ include/linux/clk-provider.h | 3 +++
+ 2 files changed, 23 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/clk/clk-fractional-divider.c b/drivers/clk/clk-fractional-divider.c
+index aab904618eb6..fdf625fb10fa 100644
+--- a/drivers/clk/clk-fractional-divider.c
++++ b/drivers/clk/clk-fractional-divider.c
+@@ -49,16 +49,12 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,
+ return ret;
+ }
+
+-static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate,
+- unsigned long *parent_rate)
++static void clk_fd_general_approximation(struct clk_hw *hw, unsigned long rate,
++ unsigned long *parent_rate,
++ unsigned long *m, unsigned long *n)
+ {
+ struct clk_fractional_divider *fd = to_clk_fd(hw);
+ unsigned long scale;
+- unsigned long m, n;
+- u64 ret;
+-
+- if (!rate || rate >= *parent_rate)
+- return *parent_rate;
+
+ /*
+ * Get rate closer to *parent_rate to guarantee there is no overflow
+@@ -71,7 +67,23 @@ static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate,
+
+ rational_best_approximation(rate, *parent_rate,
+ GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0),
+- &m, &n);
++ m, n);
++}
++
++static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate,
++ unsigned long *parent_rate)
++{
++ struct clk_fractional_divider *fd = to_clk_fd(hw);
++ unsigned long m, n;
++ u64 ret;
++
++ if (!rate || rate >= *parent_rate)
++ return *parent_rate;
++
++ if (fd->approximation)
++ fd->approximation(hw, rate, parent_rate, &m, &n);
++ else
++ clk_fd_general_approximation(hw, rate, parent_rate, &m, &n);
+
+ ret = (u64)*parent_rate * m;
+ do_div(ret, n);
+diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
+index a428aec36ace..1bbd5a4a4616 100644
+--- a/include/linux/clk-provider.h
++++ b/include/linux/clk-provider.h
+@@ -564,6 +564,9 @@ struct clk_fractional_divider {
+ u8 nwidth;
+ u32 nmask;
+ u8 flags;
++ void (*approximation)(struct clk_hw *hw,
++ unsigned long rate, unsigned long *parent_rate,
++ unsigned long *m, unsigned long *n);
+ spinlock_t *lock;
+ };
+
+--
+2.11.0
+
diff --git a/patches.drivers/0026-clk-rockchip-add-special-approximation-to-fix-up-fra.patch b/patches.drivers/0026-clk-rockchip-add-special-approximation-to-fix-up-fra.patch
new file mode 100644
index 0000000000..5b0fca34b8
--- /dev/null
+++ b/patches.drivers/0026-clk-rockchip-add-special-approximation-to-fix-up-fra.patch
@@ -0,0 +1,92 @@
+From f9d1e46e334518eba69491134ae6b4f7c114327f Mon Sep 17 00:00:00 2001
+From: Elaine Zhang <zhangqing@rock-chips.com>
+Date: Tue, 1 Aug 2017 18:22:24 +0200
+Subject: [PATCH 26/86] clk: rockchip: add special approximation to fix up
+ fractional clk's jitter
+
+Git-commit: 5d890c2df900db0197d46ec75383d7633ef41c82
+Patch-mainline: v4.14-rc1
+References: fate#323912
+
+>From Rockchips fractional divider description:
+ 3.1.9 Fractional divider usage
+ To get specific frequency, clocks of I2S, SPDIF, UARTcan be generated by
+ fractional divider. Generally you must set that denominator is 20 times
+ larger than numerator to generate precise clock frequency. So the
+ fractional divider applies only to generate low frequency clock like
+ I2S, UART.
+
+Therefore add a special approximation function that handles this
+special requirement.
+
+Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/clk/rockchip/clk.c | 36 ++++++++++++++++++++++++++++++++++++
+ 1 file changed, 36 insertions(+)
+
+diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
+index fe1d393cf678..b6db79a00602 100644
+--- a/drivers/clk/rockchip/clk.c
++++ b/drivers/clk/rockchip/clk.c
+@@ -29,6 +29,7 @@
+ #include <linux/mfd/syscon.h>
+ #include <linux/regmap.h>
+ #include <linux/reboot.h>
++#include <linux/rational.h>
+ #include "clk.h"
+
+ /**
+@@ -164,6 +165,40 @@ static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb,
+ return notifier_from_errno(ret);
+ }
+
++/**
++ * fractional divider must set that denominator is 20 times larger than
++ * numerator to generate precise clock frequency.
++ */
++void rockchip_fractional_approximation(struct clk_hw *hw,
++ unsigned long rate, unsigned long *parent_rate,
++ unsigned long *m, unsigned long *n)
++{
++ struct clk_fractional_divider *fd = to_clk_fd(hw);
++ unsigned long p_rate, p_parent_rate;
++ struct clk_hw *p_parent;
++ unsigned long scale;
++
++ p_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
++ if ((rate * 20 > p_rate) && (p_rate % rate != 0)) {
++ p_parent = clk_hw_get_parent(clk_hw_get_parent(hw));
++ p_parent_rate = clk_hw_get_rate(p_parent);
++ *parent_rate = p_parent_rate;
++ }
++
++ /*
++ * Get rate closer to *parent_rate to guarantee there is no overflow
++ * for m and n. In the result it will be the nearest rate left shifted
++ * by (scale - fd->nwidth) bits.
++ */
++ scale = fls_long(*parent_rate / rate - 1);
++ if (scale > fd->nwidth)
++ rate <<= scale - fd->nwidth;
++
++ rational_best_approximation(rate, *parent_rate,
++ GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0),
++ m, n);
++}
++
+ static struct clk *rockchip_clk_register_frac_branch(
+ struct rockchip_clk_provider *ctx, const char *name,
+ const char *const *parent_names, u8 num_parents,
+@@ -210,6 +245,7 @@ static struct clk *rockchip_clk_register_frac_branch(
+ div->nwidth = 16;
+ div->nmask = GENMASK(div->nwidth - 1, 0) << div->nshift;
+ div->lock = lock;
++ div->approximation = rockchip_fractional_approximation;
+ div_ops = &clk_fractional_divider_ops;
+
+ clk = clk_register_composite(NULL, name, parent_names, num_parents,
+--
+2.11.0
+
diff --git a/patches.drivers/0027-clk-rockchip-Mark-rockchip_fractional_approximation-.patch b/patches.drivers/0027-clk-rockchip-Mark-rockchip_fractional_approximation-.patch
new file mode 100644
index 0000000000..4ab3e2a801
--- /dev/null
+++ b/patches.drivers/0027-clk-rockchip-Mark-rockchip_fractional_approximation-.patch
@@ -0,0 +1,38 @@
+From f3e13b9cfa18f1c2a851578bda3d81c8b15b2d46 Mon Sep 17 00:00:00 2001
+From: Stephen Boyd <sboyd@codeaurora.org>
+Date: Wed, 23 Aug 2017 15:35:41 -0700
+Subject: [PATCH 27/86] clk: rockchip: Mark rockchip_fractional_approximation
+ static
+
+Git-commit: 1dfcfa721f9390ed5fd1e9c48e9fd6e8208a4963
+Patch-mainline: v4.14-rc1
+References: fate#323912
+
+Silence the sparse warning
+
+clk/rockchip/clk.c:172:6: warning: symbol 'rockchip_fractional_approximation' was not declared. Should it be static?
+
+Cc: Elaine Zhang <zhangqing@rock-chips.com>
+Cc: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/clk/rockchip/clk.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
+index b6db79a00602..35dbd63c2f49 100644
+--- a/drivers/clk/rockchip/clk.c
++++ b/drivers/clk/rockchip/clk.c
+@@ -169,7 +169,7 @@ static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb,
+ * fractional divider must set that denominator is 20 times larger than
+ * numerator to generate precise clock frequency.
+ */
+-void rockchip_fractional_approximation(struct clk_hw *hw,
++static void rockchip_fractional_approximation(struct clk_hw *hw,
+ unsigned long rate, unsigned long *parent_rate,
+ unsigned long *m, unsigned long *n)
+ {
+--
+2.11.0
+
diff --git a/patches.drivers/0028-clk-rockchip-Remove-superfluous-error-message-in-roc.patch b/patches.drivers/0028-clk-rockchip-Remove-superfluous-error-message-in-roc.patch
new file mode 100644
index 0000000000..26fc96ea25
--- /dev/null
+++ b/patches.drivers/0028-clk-rockchip-Remove-superfluous-error-message-in-roc.patch
@@ -0,0 +1,38 @@
+From 3d08cc94146be2319fb8895139aa4d7b34230dc6 Mon Sep 17 00:00:00 2001
+From: Markus Elfring <elfring@users.sourceforge.net>
+Date: Wed, 27 Sep 2017 11:38:17 +0200
+Subject: [PATCH 28/86] clk: rockchip: Remove superfluous error message in
+ rockchip_clk_register_cpuclk()
+
+Git-commit: 9edb39d750c0a9a6f7dafb8d9d15e63f6d44b68c
+Patch-mainline: Queued
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
+References: fate#323912
+
+Omit an extra message for a memory allocation failure in this function.
+
+This issue was detected by using the Coccinelle software.
+
+Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/clk/rockchip/clk-cpu.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c
+index 0e09684d43a5..32c19c0f1e14 100644
+--- a/drivers/clk/rockchip/clk-cpu.c
++++ b/drivers/clk/rockchip/clk-cpu.c
+@@ -322,8 +322,6 @@ struct clk *rockchip_clk_register_cpuclk(const char *name,
+ sizeof(*rates) * nrates,
+ GFP_KERNEL);
+ if (!cpuclk->rate_table) {
+- pr_err("%s: could not allocate memory for cpuclk rates\n",
+- __func__);
+ ret = -ENOMEM;
+ goto unregister_notifier;
+ }
+--
+2.11.0
+
diff --git a/patches.drivers/0029-phy-qcom-usb-Remove-unused-ulpi-phy-header.patch b/patches.drivers/0029-phy-qcom-usb-Remove-unused-ulpi-phy-header.patch
new file mode 100644
index 0000000000..ea2c5e96a1
--- /dev/null
+++ b/patches.drivers/0029-phy-qcom-usb-Remove-unused-ulpi-phy-header.patch
@@ -0,0 +1,66 @@
+From 5d77c4b0af9689c7b4850d95d276f7f985c01614 Mon Sep 17 00:00:00 2001
+From: Vivek Gautam <vivek.gautam@codeaurora.org>
+Date: Thu, 11 May 2017 12:17:40 +0530
+Subject: [PATCH 29/86] phy: qcom-usb: Remove unused ulpi phy header
+
+Git-commit: 706a3b69955816bd0f3591be738db64cba74b674
+Patch-mainline: v4.13-rc1
+References: fate#323912
+
+Ulpi phy header is not used for anything. Remove the same
+from qcom-hs and qcom-hsic phy drivers.
+
+Signed-off-by: Vivek Gautam <vivek.gautam@codeaurora.org>
+Suggested-by: Stephen Boyd <stephen.boyd@linaro.org>
+Cc: Kishon Vijay Abraham I <kishon@ti.com>
+Cc: linux-arm-kernel@lists.infradead.org
+Cc: linux-arm-msm@vger.kernel.org
+Cc: linux-kernel@vger.kernel.org
+Cc: linux-usb@vger.kernel.org
+Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/phy/phy-qcom-usb-hs.c | 3 +--
+ drivers/phy/phy-qcom-usb-hsic.c | 3 +--
+ 2 files changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/phy/phy-qcom-usb-hs.c b/drivers/phy/phy-qcom-usb-hs.c
+index 94dfbfd739c3..4b20abc3ae2f 100644
+--- a/drivers/phy/phy-qcom-usb-hs.c
++++ b/drivers/phy/phy-qcom-usb-hs.c
+@@ -11,12 +11,11 @@
+ #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>
+
+-#include "ulpi_phy.h"
+-
+ #define ULPI_PWR_CLK_MNG_REG 0x88
+ # define ULPI_PWR_OTG_COMP_DISABLE BIT(0)
+
+diff --git a/drivers/phy/phy-qcom-usb-hsic.c b/drivers/phy/phy-qcom-usb-hsic.c
+index 47690f9945b9..c110563a73cb 100644
+--- a/drivers/phy/phy-qcom-usb-hsic.c
++++ b/drivers/phy/phy-qcom-usb-hsic.c
+@@ -8,13 +8,12 @@
+ #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>
+
+-#include "ulpi_phy.h"
+-
+ #define ULPI_HSIC_CFG 0x30
+ #define ULPI_HSIC_IO_CAL 0x33
+
+--
+2.11.0
+
diff --git a/patches.drivers/0030-phy-Move-ULPI-phy-header-out-of-drivers-to-include-p.patch b/patches.drivers/0030-phy-Move-ULPI-phy-header-out-of-drivers-to-include-p.patch
new file mode 100644
index 0000000000..3bde85c2f4
--- /dev/null
+++ b/patches.drivers/0030-phy-Move-ULPI-phy-header-out-of-drivers-to-include-p.patch
@@ -0,0 +1,124 @@
+From d2ccd317892f1c5eb1edacdaa751336037c57740 Mon Sep 17 00:00:00 2001
+From: Vivek Gautam <vivek.gautam@codeaurora.org>
+Date: Thu, 11 May 2017 12:17:41 +0530
+Subject: [PATCH 30/86] phy: Move ULPI phy header out of drivers to include
+ path
+
+Git-commit: 858edde001e14f070d0fff347fb56c6c79e15312
+Patch-mainline: v4.13-rc1
+References: fate#323912
+
+Although ULPI phy is currently being used by tusb1210,
+there can be other consumers too in future. So move this
+to the includes path for phy.
+
+Signed-off-by: Vivek Gautam <vivek.gautam@codeaurora.org>
+Cc: Stephen Boyd <stephen.boyd@linaro.org>
+Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Cc: Kishon Vijay Abraham I <kishon@ti.com>
+Cc: linux-arm-kernel@lists.infradead.org
+Cc: linux-kernel@vger.kernel.org
+Cc: linux-omap@vger.kernel.org
+Cc: linux-usb@vger.kernel.org
+Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/phy/phy-tusb1210.c | 3 +--
+ drivers/phy/ulpi_phy.h | 31 -------------------------------
+ include/linux/phy/ulpi_phy.h | 31 +++++++++++++++++++++++++++++++
+ 3 files changed, 32 insertions(+), 33 deletions(-)
+ delete mode 100644 drivers/phy/ulpi_phy.h
+ create mode 100644 include/linux/phy/ulpi_phy.h
+
+diff --git a/drivers/phy/phy-tusb1210.c b/drivers/phy/phy-tusb1210.c
+index 4f6d5e71507d..bb3fb031c478 100644
+--- a/drivers/phy/phy-tusb1210.c
++++ b/drivers/phy/phy-tusb1210.c
+@@ -12,8 +12,7 @@
+ #include <linux/module.h>
+ #include <linux/ulpi/driver.h>
+ #include <linux/gpio/consumer.h>
+-
+-#include "ulpi_phy.h"
++#include <linux/phy/ulpi_phy.h>
+
+ #define TUSB1210_VENDOR_SPECIFIC2 0x80
+ #define TUSB1210_VENDOR_SPECIFIC2_IHSTX_SHIFT 0
+diff --git a/drivers/phy/ulpi_phy.h b/drivers/phy/ulpi_phy.h
+deleted file mode 100644
+index f2ebe490a4bc..000000000000
+--- a/drivers/phy/ulpi_phy.h
++++ /dev/null
+@@ -1,31 +0,0 @@
+-#include <linux/phy/phy.h>
+-
+-/**
+- * Helper that registers PHY for a ULPI device and adds a lookup for binding it
+- * and it's controller, which is always the parent.
+- */
+-static inline struct phy
+-*ulpi_phy_create(struct ulpi *ulpi, const struct phy_ops *ops)
+-{
+- struct phy *phy;
+- int ret;
+-
+- phy = phy_create(&ulpi->dev, NULL, ops);
+- if (IS_ERR(phy))
+- return phy;
+-
+- ret = phy_create_lookup(phy, "usb2-phy", dev_name(ulpi->dev.parent));
+- if (ret) {
+- phy_destroy(phy);
+- return ERR_PTR(ret);
+- }
+-
+- return phy;
+-}
+-
+-/* Remove a PHY that was created with ulpi_phy_create() and it's lookup. */
+-static inline void ulpi_phy_destroy(struct ulpi *ulpi, struct phy *phy)
+-{
+- phy_remove_lookup(phy, "usb2-phy", dev_name(ulpi->dev.parent));
+- phy_destroy(phy);
+-}
+diff --git a/include/linux/phy/ulpi_phy.h b/include/linux/phy/ulpi_phy.h
+new file mode 100644
+index 000000000000..f2ebe490a4bc
+--- /dev/null
++++ b/include/linux/phy/ulpi_phy.h
+@@ -0,0 +1,31 @@
++#include <linux/phy/phy.h>
++
++/**
++ * Helper that registers PHY for a ULPI device and adds a lookup for binding it
++ * and it's controller, which is always the parent.
++ */
++static inline struct phy
++*ulpi_phy_create(struct ulpi *ulpi, const struct phy_ops *ops)
++{
++ struct phy *phy;
++ int ret;
++
++ phy = phy_create(&ulpi->dev, NULL, ops);
++ if (IS_ERR(phy))
++ return phy;
++
++ ret = phy_create_lookup(phy, "usb2-phy", dev_name(ulpi->dev.parent));
++ if (ret) {
++ phy_destroy(phy);
++ return ERR_PTR(ret);
++ }
++
++ return phy;
++}
++
++/* Remove a PHY that was created with ulpi_phy_create() and it's lookup. */
++static inline void ulpi_phy_destroy(struct ulpi *ulpi, struct phy *phy)
++{
++ phy_remove_lookup(phy, "usb2-phy", dev_name(ulpi->dev.parent));
++ phy_destroy(phy);
++}
+--
+2.11.0
+
diff --git a/patches.drivers/0031-phy-Group-vendor-specific-phy-drivers.patch b/patches.drivers/0031-phy-Group-vendor-specific-phy-drivers.patch
new file mode 100644
index 0000000000..9631838883
--- /dev/null
+++ b/patches.drivers/0031-phy-Group-vendor-specific-phy-drivers.patch
@@ -0,0 +1,45969 @@
+From aa8e9cfd9ac2755fbdf5e667b132c57f124e3738 Mon Sep 17 00:00:00 2001
+From: Vivek Gautam <vivek.gautam@codeaurora.org>
+Date: Thu, 11 May 2017 12:17:42 +0530
+Subject: [PATCH 31/86] phy: Group vendor specific phy drivers
+
+Git-commit: 0b56e9a7e8358e59b21d8a425e463072bfae523c
+Patch-mainline: v4.13-rc1
+References: fate#323912
+
+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>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ MAINTAINERS | 18 +-
+ drivers/phy/Kconfig | 491 +---------
+ drivers/phy/Makefile | 70 +-
+ drivers/phy/allwinner/Kconfig | 31 +
+ drivers/phy/allwinner/Makefile | 2 +
+ drivers/phy/allwinner/phy-sun4i-usb.c | 891 +++++++++++++++++
+ drivers/phy/allwinner/phy-sun9i-usb.c | 202 ++++
+ drivers/phy/amlogic/Kconfig | 14 +
+ drivers/phy/amlogic/Makefile | 1 +
+ drivers/phy/amlogic/phy-meson8b-usb2.c | 286 ++++++
+ drivers/phy/broadcom/Kconfig | 55 ++
+ drivers/phy/broadcom/Makefile | 6 +
+ drivers/phy/broadcom/phy-bcm-cygnus-pcie.c | 221 +++++
+ drivers/phy/broadcom/phy-bcm-kona-usb2.c | 155 +++
+ drivers/phy/broadcom/phy-bcm-ns-usb2.c | 137 +++
+ drivers/phy/broadcom/phy-bcm-ns-usb3.c | 303 ++++++
+ drivers/phy/broadcom/phy-bcm-ns2-pcie.c | 101 ++
+ drivers/phy/broadcom/phy-brcm-sata.c | 493 ++++++++++
+ drivers/phy/hisilicon/Kconfig | 20 +
+ drivers/phy/hisilicon/Makefile | 2 +
+ drivers/phy/hisilicon/phy-hi6220-usb.c | 168 ++++
+ drivers/phy/hisilicon/phy-hix5hd2-sata.c | 191 ++++
+ drivers/phy/marvell/Kconfig | 50 +
+ drivers/phy/marvell/Makefile | 6 +
+ drivers/phy/marvell/phy-armada375-usb2.c | 158 +++
+ drivers/phy/marvell/phy-berlin-sata.c | 299 ++++++
+ drivers/phy/marvell/phy-berlin-usb.c | 214 ++++
+ drivers/phy/marvell/phy-mvebu-sata.c | 138 +++
+ drivers/phy/marvell/phy-pxa-28nm-hsic.c | 220 +++++
+ drivers/phy/marvell/phy-pxa-28nm-usb2.c | 355 +++++++
+ drivers/phy/phy-armada375-usb2.c | 158 ---
+ drivers/phy/phy-bcm-cygnus-pcie.c | 221 -----
+ drivers/phy/phy-bcm-kona-usb2.c | 155 ---
+ drivers/phy/phy-bcm-ns-usb2.c | 137 ---
+ drivers/phy/phy-bcm-ns-usb3.c | 303 ------
+ drivers/phy/phy-bcm-ns2-pcie.c | 101 --
+ drivers/phy/phy-berlin-sata.c | 299 ------
+ drivers/phy/phy-berlin-usb.c | 214 ----
+ drivers/phy/phy-brcm-sata.c | 493 ----------
+ drivers/phy/phy-da8xx-usb.c | 251 -----
+ drivers/phy/phy-dm816x-usb.c | 290 ------
+ drivers/phy/phy-exynos-dp-video.c | 122 ---
+ drivers/phy/phy-exynos-mipi-video.c | 377 --------
+ drivers/phy/phy-exynos-pcie.c | 281 ------
+ drivers/phy/phy-exynos4210-usb2.c | 260 -----
+ drivers/phy/phy-exynos4x12-usb2.c | 378 --------
+ drivers/phy/phy-exynos5-usbdrd.c | 782 ---------------
+ drivers/phy/phy-exynos5250-sata.c | 250 -----
+ drivers/phy/phy-exynos5250-usb2.c | 401 --------
+ drivers/phy/phy-hi6220-usb.c | 168 ----
+ drivers/phy/phy-hix5hd2-sata.c | 191 ----
+ drivers/phy/phy-meson8b-usb2.c | 286 ------
+ drivers/phy/phy-miphy28lp.c | 1286 -------------------------
+ drivers/phy/phy-mvebu-sata.c | 138 ---
+ drivers/phy/phy-omap-control.c | 360 -------
+ drivers/phy/phy-omap-usb2.c | 439 ---------
+ drivers/phy/phy-pxa-28nm-hsic.c | 220 -----
+ drivers/phy/phy-pxa-28nm-usb2.c | 355 -------
+ drivers/phy/phy-qcom-apq8064-sata.c | 287 ------
+ drivers/phy/phy-qcom-ipq806x-sata.c | 209 ----
+ drivers/phy/phy-qcom-qmp.c | 1153 ----------------------
+ drivers/phy/phy-qcom-qusb2.c | 493 ----------
+ drivers/phy/phy-qcom-ufs-i.h | 155 ---
+ drivers/phy/phy-qcom-ufs-qmp-14nm.c | 178 ----
+ drivers/phy/phy-qcom-ufs-qmp-14nm.h | 177 ----
+ drivers/phy/phy-qcom-ufs-qmp-20nm.c | 232 -----
+ drivers/phy/phy-qcom-ufs-qmp-20nm.h | 235 -----
+ drivers/phy/phy-qcom-ufs.c | 691 -------------
+ drivers/phy/phy-qcom-usb-hs.c | 295 ------
+ drivers/phy/phy-qcom-usb-hsic.c | 159 ---
+ drivers/phy/phy-rcar-gen2.c | 337 -------
+ drivers/phy/phy-rcar-gen3-usb2.c | 507 ----------
+ drivers/phy/phy-rockchip-dp.c | 154 ---
+ drivers/phy/phy-rockchip-emmc.c | 383 --------
+ drivers/phy/phy-rockchip-inno-usb2.c | 1284 ------------------------
+ drivers/phy/phy-rockchip-pcie.c | 346 -------
+ drivers/phy/phy-rockchip-typec.c | 1023 --------------------
+ drivers/phy/phy-rockchip-usb.c | 540 -----------
+ drivers/phy/phy-s5pv210-usb2.c | 187 ----
+ drivers/phy/phy-samsung-usb2.c | 267 -----
+ drivers/phy/phy-samsung-usb2.h | 73 --
+ drivers/phy/phy-spear1310-miphy.c | 261 -----
+ drivers/phy/phy-spear1340-miphy.c | 294 ------
+ drivers/phy/phy-stih407-usb.c | 180 ----
+ drivers/phy/phy-sun4i-usb.c | 891 -----------------
+ drivers/phy/phy-sun9i-usb.c | 202 ----
+ drivers/phy/phy-ti-pipe3.c | 697 --------------
+ drivers/phy/phy-tusb1210.c | 146 ---
+ drivers/phy/phy-twl4030-usb.c | 839 ----------------
+ drivers/phy/qualcomm/Kconfig | 58 ++
+ drivers/phy/qualcomm/Makefile | 9 +
+ drivers/phy/qualcomm/phy-qcom-apq8064-sata.c | 287 ++++++
+ drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c | 209 ++++
+ drivers/phy/qualcomm/phy-qcom-qmp.c | 1153 ++++++++++++++++++++++
+ drivers/phy/qualcomm/phy-qcom-qusb2.c | 493 ++++++++++
+ drivers/phy/qualcomm/phy-qcom-ufs-i.h | 155 +++
+ drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.c | 178 ++++
+ drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.h | 177 ++++
+ drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.c | 232 +++++
+ drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.h | 235 +++++
+ drivers/phy/qualcomm/phy-qcom-ufs.c | 691 +++++++++++++
+ drivers/phy/qualcomm/phy-qcom-usb-hs.c | 295 ++++++
+ drivers/phy/qualcomm/phy-qcom-usb-hsic.c | 159 +++
+ drivers/phy/renesas/Kconfig | 17 +
+ drivers/phy/renesas/Makefile | 2 +
+ drivers/phy/renesas/phy-rcar-gen2.c | 337 +++++++
+ drivers/phy/renesas/phy-rcar-gen3-usb2.c | 507 ++++++++++
+ drivers/phy/rockchip/Kconfig | 51 +
+ drivers/phy/rockchip/Makefile | 6 +
+ drivers/phy/rockchip/phy-rockchip-dp.c | 154 +++
+ drivers/phy/rockchip/phy-rockchip-emmc.c | 383 ++++++++
+ drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 1284 ++++++++++++++++++++++++
+ drivers/phy/rockchip/phy-rockchip-pcie.c | 346 +++++++
+ drivers/phy/rockchip/phy-rockchip-typec.c | 1023 ++++++++++++++++++++
+ drivers/phy/rockchip/phy-rockchip-usb.c | 540 +++++++++++
+ drivers/phy/samsung/Kconfig | 95 ++
+ drivers/phy/samsung/Makefile | 11 +
+ drivers/phy/samsung/phy-exynos-dp-video.c | 122 +++
+ drivers/phy/samsung/phy-exynos-mipi-video.c | 377 ++++++++
+ drivers/phy/samsung/phy-exynos-pcie.c | 281 ++++++
+ drivers/phy/samsung/phy-exynos4210-usb2.c | 260 +++++
+ drivers/phy/samsung/phy-exynos4x12-usb2.c | 378 ++++++++
+ drivers/phy/samsung/phy-exynos5-usbdrd.c | 782 +++++++++++++++
+ drivers/phy/samsung/phy-exynos5250-sata.c | 250 +++++
+ drivers/phy/samsung/phy-exynos5250-usb2.c | 401 ++++++++
+ drivers/phy/samsung/phy-s5pv210-usb2.c | 187 ++++
+ drivers/phy/samsung/phy-samsung-usb2.c | 267 +++++
+ drivers/phy/samsung/phy-samsung-usb2.h | 73 ++
+ drivers/phy/st/Kconfig | 33 +
+ drivers/phy/st/Makefile | 4 +
+ drivers/phy/st/phy-miphy28lp.c | 1286 +++++++++++++++++++++++++
+ drivers/phy/st/phy-spear1310-miphy.c | 261 +++++
+ drivers/phy/st/phy-spear1340-miphy.c | 294 ++++++
+ drivers/phy/st/phy-stih407-usb.c | 180 ++++
+ drivers/phy/ti/Kconfig | 78 ++
+ drivers/phy/ti/Makefile | 7 +
+ drivers/phy/ti/phy-da8xx-usb.c | 251 +++++
+ drivers/phy/ti/phy-dm816x-usb.c | 290 ++++++
+ drivers/phy/ti/phy-omap-control.c | 360 +++++++
+ drivers/phy/ti/phy-omap-usb2.c | 439 +++++++++
+ drivers/phy/ti/phy-ti-pipe3.c | 697 ++++++++++++++
+ drivers/phy/ti/phy-tusb1210.c | 146 +++
+ drivers/phy/ti/phy-twl4030-usb.c | 839 ++++++++++++++++
+ 143 files changed, 22382 insertions(+), 22337 deletions(-)
+ create mode 100644 drivers/phy/allwinner/Kconfig
+ create mode 100644 drivers/phy/allwinner/Makefile
+ create mode 100644 drivers/phy/allwinner/phy-sun4i-usb.c
+ create mode 100644 drivers/phy/allwinner/phy-sun9i-usb.c
+ create mode 100644 drivers/phy/amlogic/Kconfig
+ create mode 100644 drivers/phy/amlogic/Makefile
+ create mode 100644 drivers/phy/amlogic/phy-meson8b-usb2.c
+ create mode 100644 drivers/phy/broadcom/Kconfig
+ create mode 100644 drivers/phy/broadcom/Makefile
+ create mode 100644 drivers/phy/broadcom/phy-bcm-cygnus-pcie.c
+ create mode 100644 drivers/phy/broadcom/phy-bcm-kona-usb2.c
+ create mode 100644 drivers/phy/broadcom/phy-bcm-ns-usb2.c
+ create mode 100644 drivers/phy/broadcom/phy-bcm-ns-usb3.c
+ create mode 100644 drivers/phy/broadcom/phy-bcm-ns2-pcie.c
+ create mode 100644 drivers/phy/broadcom/phy-brcm-sata.c
+ create mode 100644 drivers/phy/hisilicon/Kconfig
+ create mode 100644 drivers/phy/hisilicon/Makefile
+ create mode 100644 drivers/phy/hisilicon/phy-hi6220-usb.c
+ create mode 100644 drivers/phy/hisilicon/phy-hix5hd2-sata.c
+ create mode 100644 drivers/phy/marvell/Kconfig
+ create mode 100644 drivers/phy/marvell/Makefile
+ create mode 100644 drivers/phy/marvell/phy-armada375-usb2.c
+ create mode 100644 drivers/phy/marvell/phy-berlin-sata.c
+ create mode 100644 drivers/phy/marvell/phy-berlin-usb.c
+ create mode 100644 drivers/phy/marvell/phy-mvebu-sata.c
+ create mode 100644 drivers/phy/marvell/phy-pxa-28nm-hsic.c
+ create mode 100644 drivers/phy/marvell/phy-pxa-28nm-usb2.c
+ delete mode 100644 drivers/phy/phy-armada375-usb2.c
+ delete mode 100644 drivers/phy/phy-bcm-cygnus-pcie.c
+ delete mode 100644 drivers/phy/phy-bcm-kona-usb2.c
+ delete mode 100644 drivers/phy/phy-bcm-ns-usb2.c
+ delete mode 100644 drivers/phy/phy-bcm-ns-usb3.c
+ delete mode 100644 drivers/phy/phy-bcm-ns2-pcie.c
+ delete mode 100644 drivers/phy/phy-berlin-sata.c
+ delete mode 100644 drivers/phy/phy-berlin-usb.c
+ delete mode 100644 drivers/phy/phy-brcm-sata.c
+ delete mode 100644 drivers/phy/phy-da8xx-usb.c
+ delete mode 100644 drivers/phy/phy-dm816x-usb.c
+ delete mode 100644 drivers/phy/phy-exynos-dp-video.c
+ delete mode 100644 drivers/phy/phy-exynos-mipi-video.c
+ delete mode 100644 drivers/phy/phy-exynos-pcie.c
+ delete mode 100644 drivers/phy/phy-exynos4210-usb2.c
+ delete mode 100644 drivers/phy/phy-exynos4x12-usb2.c
+ delete mode 100644 drivers/phy/phy-exynos5-usbdrd.c
+ delete mode 100644 drivers/phy/phy-exynos5250-sata.c
+ delete mode 100644 drivers/phy/phy-exynos5250-usb2.c
+ delete mode 100644 drivers/phy/phy-hi6220-usb.c
+ delete mode 100644 drivers/phy/phy-hix5hd2-sata.c
+ delete mode 100644 drivers/phy/phy-meson8b-usb2.c
+ delete mode 100644 drivers/phy/phy-miphy28lp.c
+ delete mode 100644 drivers/phy/phy-mvebu-sata.c
+ delete mode 100644 drivers/phy/phy-omap-control.c
+ delete mode 100644 drivers/phy/phy-omap-usb2.c
+ delete mode 100644 drivers/phy/phy-pxa-28nm-hsic.c
+ delete mode 100644 drivers/phy/phy-pxa-28nm-usb2.c
+ delete mode 100644 drivers/phy/phy-qcom-apq8064-sata.c
+ delete mode 100644 drivers/phy/phy-qcom-ipq806x-sata.c
+ delete mode 100644 drivers/phy/phy-qcom-qmp.c
+ delete mode 100644 drivers/phy/phy-qcom-qusb2.c
+ delete mode 100644 drivers/phy/phy-qcom-ufs-i.h
+ delete mode 100644 drivers/phy/phy-qcom-ufs-qmp-14nm.c
+ delete mode 100644 drivers/phy/phy-qcom-ufs-qmp-14nm.h
+ delete mode 100644 drivers/phy/phy-qcom-ufs-qmp-20nm.c
+ delete mode 100644 drivers/phy/phy-qcom-ufs-qmp-20nm.h
+ delete mode 100644 drivers/phy/phy-qcom-ufs.c
+ delete mode 100644 drivers/phy/phy-qcom-usb-hs.c
+ delete mode 100644 drivers/phy/phy-qcom-usb-hsic.c
+ delete mode 100644 drivers/phy/phy-rcar-gen2.c
+ delete mode 100644 drivers/phy/phy-rcar-gen3-usb2.c
+ delete mode 100644 drivers/phy/phy-rockchip-dp.c
+ delete mode 100644 drivers/phy/phy-rockchip-emmc.c
+ delete mode 100644 drivers/phy/phy-rockchip-inno-usb2.c
+ delete mode 100644 drivers/phy/phy-rockchip-pcie.c
+ delete mode 100644 drivers/phy/phy-rockchip-typec.c
+ delete mode 100644 drivers/phy/phy-rockchip-usb.c
+ delete mode 100644 drivers/phy/phy-s5pv210-usb2.c
+ delete mode 100644 drivers/phy/phy-samsung-usb2.c
+ delete mode 100644 drivers/phy/phy-samsung-usb2.h
+ delete mode 100644 drivers/phy/phy-spear1310-miphy.c
+ delete mode 100644 drivers/phy/phy-spear1340-miphy.c
+ delete mode 100644 drivers/phy/phy-stih407-usb.c
+ delete mode 100644 drivers/phy/phy-sun4i-usb.c
+ delete mode 100644 drivers/phy/phy-sun9i-usb.c
+ delete mode 100644 drivers/phy/phy-ti-pipe3.c
+ delete mode 100644 drivers/phy/phy-tusb1210.c
+ delete mode 100644 drivers/phy/phy-twl4030-usb.c
+ create mode 100644 drivers/phy/qualcomm/Kconfig
+ create mode 100644 drivers/phy/qualcomm/Makefile
+ create mode 100644 drivers/phy/qualcomm/phy-qcom-apq8064-sata.c
+ create mode 100644 drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c
+ create mode 100644 drivers/phy/qualcomm/phy-qcom-qmp.c
+ create mode 100644 drivers/phy/qualcomm/phy-qcom-qusb2.c
+ create mode 100644 drivers/phy/qualcomm/phy-qcom-ufs-i.h
+ create mode 100644 drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.c
+ create mode 100644 drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.h
+ create mode 100644 drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.c
+ create mode 100644 drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.h
+ create mode 100644 drivers/phy/qualcomm/phy-qcom-ufs.c
+ create mode 100644 drivers/phy/qualcomm/phy-qcom-usb-hs.c
+ create mode 100644 drivers/phy/qualcomm/phy-qcom-usb-hsic.c
+ create mode 100644 drivers/phy/renesas/Kconfig
+ create mode 100644 drivers/phy/renesas/Makefile
+ create mode 100644 drivers/phy/renesas/phy-rcar-gen2.c
+ create mode 100644 drivers/phy/renesas/phy-rcar-gen3-usb2.c
+ create mode 100644 drivers/phy/rockchip/Kconfig
+ create mode 100644 drivers/phy/rockchip/Makefile
+ create mode 100644 drivers/phy/rockchip/phy-rockchip-dp.c
+ create mode 100644 drivers/phy/rockchip/phy-rockchip-emmc.c
+ create mode 100644 drivers/phy/rockchip/phy-rockchip-inno-usb2.c
+ create mode 100644 drivers/phy/rockchip/phy-rockchip-pcie.c
+ create mode 100644 drivers/phy/rockchip/phy-rockchip-typec.c
+ create mode 100644 drivers/phy/rockchip/phy-rockchip-usb.c
+ create mode 100644 drivers/phy/samsung/Kconfig
+ create mode 100644 drivers/phy/samsung/Makefile
+ create mode 100644 drivers/phy/samsung/phy-exynos-dp-video.c
+ create mode 100644 drivers/phy/samsung/phy-exynos-mipi-video.c
+ create mode 100644 drivers/phy/samsung/phy-exynos-pcie.c
+ create mode 100644 drivers/phy/samsung/phy-exynos4210-usb2.c
+ create mode 100644 drivers/phy/samsung/phy-exynos4x12-usb2.c
+ create mode 100644 drivers/phy/samsung/phy-exynos5-usbdrd.c
+ create mode 100644 drivers/phy/samsung/phy-exynos5250-sata.c
+ create mode 100644 drivers/phy/samsung/phy-exynos5250-usb2.c
+ create mode 100644 drivers/phy/samsung/phy-s5pv210-usb2.c
+ create mode 100644 drivers/phy/samsung/phy-samsung-usb2.c
+ create mode 100644 drivers/phy/samsung/phy-samsung-usb2.h
+ create mode 100644 drivers/phy/st/Kconfig
+ create mode 100644 drivers/phy/st/Makefile
+ create mode 100644 drivers/phy/st/phy-miphy28lp.c
+ create mode 100644 drivers/phy/st/phy-spear1310-miphy.c
+ create mode 100644 drivers/phy/st/phy-spear1340-miphy.c
+ create mode 100644 drivers/phy/st/phy-stih407-usb.c
+ create mode 100644 drivers/phy/ti/Kconfig
+ create mode 100644 drivers/phy/ti/Makefile
+ create mode 100644 drivers/phy/ti/phy-da8xx-usb.c
+ create mode 100644 drivers/phy/ti/phy-dm816x-usb.c
+ create mode 100644 drivers/phy/ti/phy-omap-control.c
+ create mode 100644 drivers/phy/ti/phy-omap-usb2.c
+ create mode 100644 drivers/phy/ti/phy-ti-pipe3.c
+ create mode 100644 drivers/phy/ti/phy-tusb1210.c
+ create mode 100644 drivers/phy/ti/phy-twl4030-usb.c
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 336eec0f140e..521fe1f094b1 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -1843,8 +1843,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
+@@ -10855,7 +10855,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>
+@@ -11257,12 +11257,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>
+diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
+index afaf7b643eeb..01009b2a7d74 100644
+--- a/drivers/phy/Kconfig
++++ b/drivers/phy/Kconfig
+@@ -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
+diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
+index f8047b4639fa..c1bd1fa3c853 100644
+--- a/drivers/phy/Makefile
++++ b/drivers/phy/Makefile
+@@ -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
+index 000000000000..cdc1e745ba47
+--- /dev/null
++++ b/drivers/phy/allwinner/Kconfig
+@@ -0,0 +1,31 @@
++#
++# Phy drivers for Allwinner platforms
++#
++config PHY_SUN4I_USB
++ tristate "Allwinner sunxi SoC USB PHY driver"
++ depends on ARCH_SUNXI && HAS_IOMEM && OF
++ depends on RESET_CONTROLLER
++ depends on EXTCON
++ depends on POWER_SUPPLY
++ depends on USB_SUPPORT
++ select GENERIC_PHY
++ select USB_COMMON
++ help
++ Enable this to support the transceiver that is part of Allwinner
++ sunxi SoCs.
++
++ This driver controls the entire USB PHY block, both the USB OTG
++ parts, as well as the 2 regular USB 2 host PHYs.
++
++config PHY_SUN9I_USB
++ tristate "Allwinner sun9i SoC USB PHY driver"
++ depends on ARCH_SUNXI && HAS_IOMEM && OF
++ depends on RESET_CONTROLLER
++ depends on USB_SUPPORT
++ select USB_COMMON
++ select GENERIC_PHY
++ help
++ Enable this to support the transceiver that is part of Allwinner
++ sun9i SoCs.
++
++ This driver controls each individual USB 2 host PHY.
+diff --git a/drivers/phy/allwinner/Makefile b/drivers/phy/allwinner/Makefile
+new file mode 100644
+index 000000000000..8605529c01a1
+--- /dev/null
++++ b/drivers/phy/allwinner/Makefile
+@@ -0,0 +1,2 @@
++obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o
++obj-$(CONFIG_PHY_SUN9I_USB) += phy-sun9i-usb.o
+diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
+new file mode 100644
+index 000000000000..bbf06cfe5898
+--- /dev/null
++++ b/drivers/phy/allwinner/phy-sun4i-usb.c
+@@ -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
+index 000000000000..28fce4bce638
+--- /dev/null
++++ b/drivers/phy/allwinner/phy-sun9i-usb.c
+@@ -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
+index 000000000000..edcd5b65179f
+--- /dev/null
++++ b/drivers/phy/amlogic/Kconfig
+@@ -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
+index 000000000000..47b6eecc3864
+--- /dev/null
++++ b/drivers/phy/amlogic/Makefile
+@@ -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
+index 000000000000..30f56a6a411f
+--- /dev/null
++++ b/drivers/phy/amlogic/phy-meson8b-usb2.c
+@@ -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
+index 000000000000..d2d99023ec50
+--- /dev/null
++++ b/drivers/phy/broadcom/Kconfig
+@@ -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
+index 000000000000..357a7d16529f
+--- /dev/null
++++ b/drivers/phy/broadcom/Makefile
+@@ -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
+index 000000000000..0f4ac5d63cff
+--- /dev/null
++++ b/drivers/phy/broadcom/phy-bcm-cygnus-pcie.c
+@@ -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
+index 000000000000..7b67fe49e30b
+--- /dev/null
++++ b/drivers/phy/broadcom/phy-bcm-kona-usb2.c
+@@ -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
+index 000000000000..58dff80e9386
+--- /dev/null
++++ b/drivers/phy/broadcom/phy-bcm-ns-usb2.c
+@@ -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
+index 000000000000..22b5e7047fa6
+--- /dev/null
++++ b/drivers/phy/broadcom/phy-bcm-ns-usb3.c
+@@ -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
+index 000000000000..4c7d11d2b378
+--- /dev/null
++++ b/drivers/phy/broadcom/phy-bcm-ns2-pcie.c
+@@ -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
+index 000000000000..ccbc3d994998
+--- /dev/null
++++ b/drivers/phy/broadcom/phy-brcm-sata.c
+@@ -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
+index 000000000000..6164c4cd0f65
+--- /dev/null
++++ b/drivers/phy/hisilicon/Kconfig
+@@ -0,0 +1,20 @@
++#
++# Phy drivers for Hisilicon platforms
++#
++config PHY_HI6220_USB
++ tristate "hi6220 USB PHY support"
++ depends on (ARCH_HISI && ARM64) || COMPILE_TEST
++ select GENERIC_PHY
++ select MFD_SYSCON
++ help
++ Enable this to support the HISILICON HI6220 USB PHY.
++
++ To compile this driver as a module, choose M here.
++
++config PHY_HIX5HD2_SATA
++ tristate "HIX5HD2 SATA PHY Driver"
++ depends on ARCH_HIX5HD2 && OF && HAS_IOMEM
++ select GENERIC_PHY
++ select MFD_SYSCON
++ help
++ Support for SATA PHY on Hisilicon hix5hd2 Soc.
+diff --git a/drivers/phy/hisilicon/Makefile b/drivers/phy/hisilicon/Makefile
+new file mode 100644
+index 000000000000..541b348187a8
+--- /dev/null
++++ b/drivers/phy/hisilicon/Makefile
+@@ -0,0 +1,2 @@
++obj-$(CONFIG_PHY_HI6220_USB) += phy-hi6220-usb.o
++obj-$(CONFIG_PHY_HIX5HD2_SATA) += phy-hix5hd2-sata.o
+diff --git a/drivers/phy/hisilicon/phy-hi6220-usb.c b/drivers/phy/hisilicon/phy-hi6220-usb.c
+new file mode 100644
+index 000000000000..398c1021deec
+--- /dev/null
++++ b/drivers/phy/hisilicon/phy-hi6220-usb.c
+@@ -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
+index 000000000000..e5ab3aa78b9d
+--- /dev/null
++++ b/drivers/phy/hisilicon/phy-hix5hd2-sata.c
+@@ -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
+index 000000000000..048d8893bc2e
+--- /dev/null
++++ b/drivers/phy/marvell/Kconfig
+@@ -0,0 +1,50 @@
++#
++# Phy drivers for Marvell platforms
++#
++config ARMADA375_USBCLUSTER_PHY
++ def_bool y
++ depends on MACH_ARMADA_375 || COMPILE_TEST
++ depends on OF && HAS_IOMEM
++ select GENERIC_PHY
++
++config PHY_BERLIN_SATA
++ tristate "Marvell Berlin SATA PHY driver"
++ depends on ARCH_BERLIN && HAS_IOMEM && OF
++ select GENERIC_PHY
++ help
++ Enable this to support the SATA PHY on Marvell Berlin SoCs.
++
++config PHY_BERLIN_USB
++ tristate "Marvell Berlin USB PHY Driver"
++ depends on ARCH_BERLIN && RESET_CONTROLLER && HAS_IOMEM && OF
++ select GENERIC_PHY
++ help
++ Enable this to support the USB PHY on Marvell Berlin SoCs.
++
++config PHY_MVEBU_SATA
++ def_bool y
++ depends on ARCH_DOVE || MACH_DOVE || MACH_KIRKWOOD
++ depends on OF
++ select GENERIC_PHY
++
++config PHY_PXA_28NM_HSIC
++ tristate "Marvell USB HSIC 28nm PHY Driver"
++ depends on HAS_IOMEM
++ select GENERIC_PHY
++ help
++ Enable this to support Marvell USB HSIC PHY driver for Marvell
++ SoC. This driver will do the PHY initialization and shutdown.
++ The PHY driver will be used by Marvell ehci driver.
++
++ To compile this driver as a module, choose M here.
++
++config PHY_PXA_28NM_USB2
++ tristate "Marvell USB 2.0 28nm PHY Driver"
++ depends on HAS_IOMEM
++ select GENERIC_PHY
++ help
++ Enable this to support Marvell USB 2.0 PHY driver for Marvell
++ SoC. This driver will do the PHY initialization and shutdown.
++ The PHY driver will be used by Marvell udc/ehci/otg driver.
++
++ To compile this driver as a module, choose M here.
+diff --git a/drivers/phy/marvell/Makefile b/drivers/phy/marvell/Makefile
+new file mode 100644
+index 000000000000..3fc188f59118
+--- /dev/null
++++ b/drivers/phy/marvell/Makefile
+@@ -0,0 +1,6 @@
++obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY) += phy-armada375-usb2.o
++obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o
++obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o
++obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o
++obj-$(CONFIG_PHY_PXA_28NM_HSIC) += phy-pxa-28nm-hsic.o
++obj-$(CONFIG_PHY_PXA_28NM_USB2) += phy-pxa-28nm-usb2.o
+diff --git a/drivers/phy/marvell/phy-armada375-usb2.c b/drivers/phy/marvell/phy-armada375-usb2.c
+new file mode 100644
+index 000000000000..1a3db288c0a9
+--- /dev/null
++++ b/drivers/phy/marvell/phy-armada375-usb2.c
+@@ -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
+index 000000000000..2c7a57f2d595
+--- /dev/null
++++ b/drivers/phy/marvell/phy-berlin-sata.c
+@@ -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
+index 000000000000..2017751ede26
+--- /dev/null
++++ b/drivers/phy/marvell/phy-berlin-usb.c
+@@ -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
+index 000000000000..768ce92e81ce
+--- /dev/null
++++ b/drivers/phy/marvell/phy-mvebu-sata.c
+@@ -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
+index 000000000000..234aacf4db20
+--- /dev/null
++++ b/drivers/phy/marvell/phy-pxa-28nm-hsic.c
+@@ -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
+index 000000000000..37e9c8ca4983
+--- /dev/null
++++ b/drivers/phy/marvell/phy-pxa-28nm-usb2.c
+@@ -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
+index 1a3db288c0a9..000000000000
+--- a/drivers/phy/phy-armada375-usb2.c
++++ /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
+index 0f4ac5d63cff..000000000000
+--- a/drivers/phy/phy-bcm-cygnus-pcie.c
++++ /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
+index 7b67fe49e30b..000000000000
+--- a/drivers/phy/phy-bcm-kona-usb2.c
++++ /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
+index 58dff80e9386..000000000000
+--- a/drivers/phy/phy-bcm-ns-usb2.c
++++ /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
+index 22b5e7047fa6..000000000000
+--- a/drivers/phy/phy-bcm-ns-usb3.c
++++ /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
+index 4c7d11d2b378..000000000000
+--- a/drivers/phy/phy-bcm-ns2-pcie.c
++++ /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
+index 2c7a57f2d595..000000000000
+--- a/drivers/phy/phy-berlin-sata.c
++++ /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
+index 2017751ede26..000000000000
+--- a/drivers/phy/phy-berlin-usb.c
++++ /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
+index ccbc3d994998..000000000000
+--- a/drivers/phy/phy-brcm-sata.c
++++ /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
+index 1b82bff6330f..000000000000
+--- a/drivers/phy/phy-da8xx-usb.c
++++ /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
+index cbcce7cf0028..000000000000
+--- a/drivers/phy/phy-dm816x-usb.c
++++ /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
+index bb3279dbf88c..000000000000
+--- a/drivers/phy/phy-exynos-dp-video.c
++++ /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
+index c198886f80a3..000000000000
+--- a/drivers/phy/phy-exynos-mipi-video.c
++++ /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
+index a89c12faff39..000000000000
+--- a/drivers/phy/phy-exynos-pcie.c
++++ /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
+index 1f50e1004828..000000000000
+--- a/drivers/phy/phy-exynos4210-usb2.c
++++ /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
+index 7f27a91acf87..000000000000
+--- a/drivers/phy/phy-exynos4x12-usb2.c
++++ /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
+index 7c41daa2c625..000000000000
+--- a/drivers/phy/phy-exynos5-usbdrd.c
++++ /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
+index 60e13afcd9b8..000000000000
+--- a/drivers/phy/phy-exynos5250-sata.c
++++ /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
+index aad806272305..000000000000
+--- a/drivers/phy/phy-exynos5250-usb2.c
++++ /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
+index 398c1021deec..000000000000
+--- a/drivers/phy/phy-hi6220-usb.c
++++ /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
+index e5ab3aa78b9d..000000000000
+--- a/drivers/phy/phy-hix5hd2-sata.c
++++ /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
+index 30f56a6a411f..000000000000
+--- a/drivers/phy/phy-meson8b-usb2.c
++++ /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
+index 213e2e15339c..000000000000
+--- a/drivers/phy/phy-miphy28lp.c
++++ /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
+index 768ce92e81ce..000000000000
+--- a/drivers/phy/phy-mvebu-sata.c
++++ /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
+index e9c41b3fa0ee..000000000000
+--- a/drivers/phy/phy-omap-control.c
++++ /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
+index fe909fd8144f..000000000000
+--- a/drivers/phy/phy-omap-usb2.c
++++ /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
+index 234aacf4db20..000000000000
+--- a/drivers/phy/phy-pxa-28nm-hsic.c
++++ /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
+index 37e9c8ca4983..000000000000
+--- a/drivers/phy/phy-pxa-28nm-usb2.c
++++ /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
+index 69ce2afac015..000000000000
+--- a/drivers/phy/phy-qcom-apq8064-sata.c
++++ /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);