aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/phy
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2020-12-15 14:10:09 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2020-12-15 14:10:09 -0800
commit2911ed9f47b47cb5ab87d03314b3b9fe008e607f (patch)
tree7357e609aac80001b12a3933122060a777e67578 /drivers/phy
parentMerge tag 'driver-core-5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core (diff)
parentMerge tag 'extcon-next-for-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon into char-misc-next (diff)
downloadlinux-dev-2911ed9f47b47cb5ab87d03314b3b9fe008e607f.tar.xz
linux-dev-2911ed9f47b47cb5ab87d03314b3b9fe008e607f.zip
Merge tag 'char-misc-5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char / misc driver updates from Greg KH: "Here is the big char/misc driver update for 5.11-rc1. Continuing the tradition of previous -rc1 pulls, there seems to be more and more tiny driver subsystems flowing through this tree. Lots of different things, all of which have been in linux-next for a while with no reported issues: - extcon driver updates - habannalab driver updates - mei driver updates - uio driver updates - binder fixes and features added - soundwire driver updates - mhi bus driver updates - phy driver updates - coresight driver updates - fpga driver updates - speakup driver updates - slimbus driver updates - various small char and misc driver updates" * tag 'char-misc-5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (305 commits) extcon: max77693: Fix modalias string extcon: fsa9480: Support TI TSU6111 variant extcon: fsa9480: Rewrite bindings in YAML and extend dt-bindings: extcon: add binding for TUSB320 extcon: Add driver for TI TUSB320 slimbus: qcom: fix potential NULL dereference in qcom_slim_prg_slew() siox: Make remove callback return void siox: Use bus_type functions for probe, remove and shutdown spmi: Add driver shutdown support spmi: fix some coding style issues at the spmi core spmi: get rid of a warning when built with W=1 uio: uio_hv_generic: use devm_kzalloc() for private data alloc uio: uio_fsl_elbc_gpcm: use device-managed allocators uio: uio_aec: use devm_kzalloc() for uio_info object uio: uio_cif: use devm_kzalloc() for uio_info object uio: uio_netx: use devm_kzalloc() for or uio_info object uio: uio_mf624: use devm_kzalloc() for uio_info object uio: uio_sercos3: use device-managed functions for simple allocs uio: uio_dmem_genirq: finalize conversion of probe to devm_ handlers uio: uio_dmem_genirq: convert simple allocations to device-managed ...
Diffstat (limited to 'drivers/phy')
-rw-r--r--drivers/phy/Kconfig1
-rw-r--r--drivers/phy/Makefile1
-rw-r--r--drivers/phy/allwinner/phy-sun4i-usb.c9
-rw-r--r--drivers/phy/allwinner/phy-sun50i-usb3.c4
-rw-r--r--drivers/phy/allwinner/phy-sun6i-mipi-dphy.c4
-rw-r--r--drivers/phy/allwinner/phy-sun9i-usb.c4
-rw-r--r--drivers/phy/amlogic/Kconfig13
-rw-r--r--drivers/phy/amlogic/Makefile1
-rw-r--r--drivers/phy/amlogic/phy-meson-axg-mipi-dphy.c413
-rw-r--r--drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c203
-rw-r--r--drivers/phy/amlogic/phy-meson-axg-pcie.c6
-rw-r--r--drivers/phy/amlogic/phy-meson-g12a-usb2.c4
-rw-r--r--drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c6
-rw-r--r--drivers/phy/amlogic/phy-meson-gxl-usb2.c7
-rw-r--r--drivers/phy/broadcom/phy-bcm-cygnus-pcie.c4
-rw-r--r--drivers/phy/broadcom/phy-bcm-kona-usb2.c4
-rw-r--r--drivers/phy/broadcom/phy-bcm-ns-usb2.c4
-rw-r--r--drivers/phy/broadcom/phy-bcm-ns-usb3.c159
-rw-r--r--drivers/phy/broadcom/phy-bcm-ns2-usbdrd.c13
-rw-r--r--drivers/phy/broadcom/phy-bcm-sr-pcie.c5
-rw-r--r--drivers/phy/broadcom/phy-bcm-sr-usb.c4
-rw-r--r--drivers/phy/broadcom/phy-brcm-sata.c40
-rw-r--r--drivers/phy/cadence/cdns-dphy.c4
-rw-r--r--drivers/phy/cadence/phy-cadence-salvo.c4
-rw-r--r--drivers/phy/cadence/phy-cadence-sierra.c4
-rw-r--r--drivers/phy/freescale/phy-fsl-imx8-mipi-dphy.c4
-rw-r--r--drivers/phy/freescale/phy-fsl-imx8mq-usb.c6
-rw-r--r--drivers/phy/ingenic/Kconfig13
-rw-r--r--drivers/phy/ingenic/Makefile2
-rw-r--r--drivers/phy/ingenic/phy-ingenic-usb.c412
-rw-r--r--drivers/phy/intel/Kconfig12
-rw-r--r--drivers/phy/intel/Makefile1
-rw-r--r--drivers/phy/intel/phy-intel-keembay-usb.c301
-rw-r--r--drivers/phy/lantiq/phy-lantiq-vrx200-pcie.c4
-rw-r--r--drivers/phy/marvell/Kconfig12
-rw-r--r--drivers/phy/marvell/Makefile1
-rw-r--r--drivers/phy/marvell/phy-armada375-usb2.c4
-rw-r--r--drivers/phy/marvell/phy-berlin-usb.c4
-rw-r--r--drivers/phy/marvell/phy-mmp3-hsic.c82
-rw-r--r--drivers/phy/marvell/phy-mmp3-usb.c4
-rw-r--r--drivers/phy/marvell/phy-mvebu-sata.c4
-rw-r--r--drivers/phy/marvell/phy-pxa-28nm-hsic.c4
-rw-r--r--drivers/phy/marvell/phy-pxa-28nm-usb2.c4
-rw-r--r--drivers/phy/marvell/phy-pxa-usb.c4
-rw-r--r--drivers/phy/mediatek/Kconfig10
-rw-r--r--drivers/phy/mediatek/phy-mtk-hdmi.c7
-rw-r--r--drivers/phy/mediatek/phy-mtk-ufs.c4
-rw-r--r--drivers/phy/phy-xgene.c4
-rw-r--r--drivers/phy/qualcomm/phy-qcom-apq8064-sata.c4
-rw-r--r--drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c4
-rw-r--r--drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c4
-rw-r--r--drivers/phy/qualcomm/phy-qcom-pcie2.c5
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp.c281
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp.h18
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qusb2.c4
-rw-r--r--drivers/phy/ralink/Kconfig8
-rw-r--r--drivers/phy/ralink/Makefile1
-rw-r--r--drivers/phy/ralink/phy-mt7621-pci.c352
-rw-r--r--drivers/phy/ralink/phy-ralink-usb.c4
-rw-r--r--drivers/phy/renesas/phy-rcar-gen2.c4
-rw-r--r--drivers/phy/renesas/phy-rcar-gen3-pcie.c4
-rw-r--r--drivers/phy/renesas/phy-rcar-gen3-usb2.c10
-rw-r--r--drivers/phy/renesas/phy-rcar-gen3-usb3.c4
-rw-r--r--drivers/phy/rockchip/Kconfig1
-rw-r--r--drivers/phy/rockchip/phy-rockchip-emmc.c29
-rw-r--r--drivers/phy/rockchip/phy-rockchip-inno-hdmi.c4
-rw-r--r--drivers/phy/samsung/phy-exynos-pcie.c304
-rw-r--r--drivers/phy/samsung/phy-exynos5-usbdrd.c4
-rw-r--r--drivers/phy/samsung/phy-exynos5250-sata.c5
-rw-r--r--drivers/phy/samsung/phy-exynos5250-usb2.c48
-rw-r--r--drivers/phy/samsung/phy-samsung-usb2.c8
-rw-r--r--drivers/phy/samsung/phy-samsung-usb2.h1
-rw-r--r--drivers/phy/st/phy-stm32-usbphyc.c15
-rw-r--r--drivers/phy/tegra/phy-tegra194-p2u.c4
-rw-r--r--drivers/phy/tegra/xusb.c12
-rw-r--r--drivers/phy/ti/phy-omap-control.c17
-rw-r--r--drivers/phy/ti/phy-omap-usb2.c4
-rw-r--r--drivers/phy/ti/phy-ti-pipe3.c15
78 files changed, 2365 insertions, 637 deletions
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 01b53f86004c..00dabe5fab8a 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -66,6 +66,7 @@ source "drivers/phy/broadcom/Kconfig"
source "drivers/phy/cadence/Kconfig"
source "drivers/phy/freescale/Kconfig"
source "drivers/phy/hisilicon/Kconfig"
+source "drivers/phy/ingenic/Kconfig"
source "drivers/phy/lantiq/Kconfig"
source "drivers/phy/marvell/Kconfig"
source "drivers/phy/mediatek/Kconfig"
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 6eb2916773c5..32261e164abd 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -15,6 +15,7 @@ obj-y += allwinner/ \
cadence/ \
freescale/ \
hisilicon/ \
+ ingenic/ \
intel/ \
lantiq/ \
marvell/ \
diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
index 651d5e2a25ce..788dd5cdbb7d 100644
--- a/drivers/phy/allwinner/phy-sun4i-usb.c
+++ b/drivers/phy/allwinner/phy-sun4i-usb.c
@@ -686,7 +686,6 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
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);
@@ -700,8 +699,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
if (!data->cfg)
return -EINVAL;
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl");
- data->base = devm_ioremap_resource(dev, res);
+ data->base = devm_platform_ioremap_resource_byname(pdev, "phy_ctrl");
if (IS_ERR(data->base))
return PTR_ERR(data->base);
@@ -796,9 +794,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
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);
+ phy->pmu = devm_platform_ioremap_resource_byname(pdev, name);
if (IS_ERR(phy->pmu))
return PTR_ERR(phy->pmu);
}
@@ -969,7 +965,6 @@ static const struct sun4i_usb_phy_cfg sun50i_h6_cfg = {
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A33,
.dedicated_clocks = true,
- .enable_pmu_unk1 = true,
.phy0_dual_route = true,
.missing_phys = BIT(1) | BIT(2),
};
diff --git a/drivers/phy/allwinner/phy-sun50i-usb3.c b/drivers/phy/allwinner/phy-sun50i-usb3.c
index b1c04f71a31d..84055b720016 100644
--- a/drivers/phy/allwinner/phy-sun50i-usb3.c
+++ b/drivers/phy/allwinner/phy-sun50i-usb3.c
@@ -134,7 +134,6 @@ static int sun50i_usb3_phy_probe(struct platform_device *pdev)
struct sun50i_usb3_phy *phy;
struct device *dev = &pdev->dev;
struct phy_provider *phy_provider;
- struct resource *res;
phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
if (!phy)
@@ -153,8 +152,7 @@ static int sun50i_usb3_phy_probe(struct platform_device *pdev)
return PTR_ERR(phy->reset);
}
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- phy->regs = devm_ioremap_resource(dev, res);
+ phy->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(phy->regs))
return PTR_ERR(phy->regs);
diff --git a/drivers/phy/allwinner/phy-sun6i-mipi-dphy.c b/drivers/phy/allwinner/phy-sun6i-mipi-dphy.c
index 1fa761ba6cbb..f0bc87d654d4 100644
--- a/drivers/phy/allwinner/phy-sun6i-mipi-dphy.c
+++ b/drivers/phy/allwinner/phy-sun6i-mipi-dphy.c
@@ -253,15 +253,13 @@ static int sun6i_dphy_probe(struct platform_device *pdev)
{
struct phy_provider *phy_provider;
struct sun6i_dphy *dphy;
- struct resource *res;
void __iomem *regs;
dphy = devm_kzalloc(&pdev->dev, sizeof(*dphy), GFP_KERNEL);
if (!dphy)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- regs = devm_ioremap_resource(&pdev->dev, res);
+ regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(regs)) {
dev_err(&pdev->dev, "Couldn't map the DPHY encoder registers\n");
return PTR_ERR(regs);
diff --git a/drivers/phy/allwinner/phy-sun9i-usb.c b/drivers/phy/allwinner/phy-sun9i-usb.c
index fc6784dd7fa0..2f9e60c188b8 100644
--- a/drivers/phy/allwinner/phy-sun9i-usb.c
+++ b/drivers/phy/allwinner/phy-sun9i-usb.c
@@ -117,7 +117,6 @@ static int sun9i_usb_phy_probe(struct platform_device *pdev)
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)
@@ -156,8 +155,7 @@ static int sun9i_usb_phy_probe(struct platform_device *pdev)
}
}
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- phy->pmu = devm_ioremap_resource(dev, res);
+ phy->pmu = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(phy->pmu))
return PTR_ERR(phy->pmu);
diff --git a/drivers/phy/amlogic/Kconfig b/drivers/phy/amlogic/Kconfig
index 617cf073e9aa..db5d0cd757e3 100644
--- a/drivers/phy/amlogic/Kconfig
+++ b/drivers/phy/amlogic/Kconfig
@@ -66,7 +66,20 @@ config PHY_MESON_AXG_MIPI_PCIE_ANALOG
depends on OF && (ARCH_MESON || COMPILE_TEST)
select GENERIC_PHY
select REGMAP_MMIO
+ select GENERIC_PHY_MIPI_DPHY
help
Enable this to support the Meson MIPI + PCIE analog PHY
found in Meson AXG SoCs.
If unsure, say N.
+
+config PHY_MESON_AXG_MIPI_DPHY
+ tristate "Meson AXG MIPI DPHY driver"
+ default ARCH_MESON
+ depends on OF && (ARCH_MESON || COMPILE_TEST)
+ select GENERIC_PHY
+ select REGMAP_MMIO
+ select GENERIC_PHY_MIPI_DPHY
+ help
+ Enable this to support the Meson MIPI DPHY found in Meson AXG
+ SoCs.
+ If unsure, say N.
diff --git a/drivers/phy/amlogic/Makefile b/drivers/phy/amlogic/Makefile
index 99702a45e9be..8fa07fbd0d92 100644
--- a/drivers/phy/amlogic/Makefile
+++ b/drivers/phy/amlogic/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_PHY_MESON_G12A_USB2) += phy-meson-g12a-usb2.o
obj-$(CONFIG_PHY_MESON_G12A_USB3_PCIE) += phy-meson-g12a-usb3-pcie.o
obj-$(CONFIG_PHY_MESON_AXG_PCIE) += phy-meson-axg-pcie.o
obj-$(CONFIG_PHY_MESON_AXG_MIPI_PCIE_ANALOG) += phy-meson-axg-mipi-pcie-analog.o
+obj-$(CONFIG_PHY_MESON_AXG_MIPI_DPHY) += phy-meson-axg-mipi-dphy.o
diff --git a/drivers/phy/amlogic/phy-meson-axg-mipi-dphy.c b/drivers/phy/amlogic/phy-meson-axg-mipi-dphy.c
new file mode 100644
index 000000000000..cd2332bf0e31
--- /dev/null
+++ b/drivers/phy/amlogic/phy-meson-axg-mipi-dphy.c
@@ -0,0 +1,413 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Meson AXG MIPI DPHY driver
+ *
+ * Copyright (C) 2018 Amlogic, Inc. All rights reserved
+ * Copyright (C) 2020 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+
+/* [31] soft reset for the phy.
+ * 1: reset. 0: dessert the reset.
+ * [30] clock lane soft reset.
+ * [29] data byte lane 3 soft reset.
+ * [28] data byte lane 2 soft reset.
+ * [27] data byte lane 1 soft reset.
+ * [26] data byte lane 0 soft reset.
+ * [25] mipi dsi pll clock selection.
+ * 1: clock from fixed 850Mhz clock source. 0: from VID2 PLL.
+ * [12] mipi HSbyteclk enable.
+ * [11] mipi divider clk selection.
+ * 1: select the mipi DDRCLKHS from clock divider.
+ * 0: from PLL clock.
+ * [10] mipi clock divider control.
+ * 1: /4. 0: /2.
+ * [9] mipi divider output enable.
+ * [8] mipi divider counter enable.
+ * [7] PLL clock enable.
+ * [5] LPDT data endian.
+ * 1 = transfer the high bit first. 0 : transfer the low bit first.
+ * [4] HS data endian.
+ * [3] force data byte lane in stop mode.
+ * [2] force data byte lane 0 in receiver mode.
+ * [1] write 1 to sync the txclkesc input. the internal logic have to
+ * use txclkesc to decide Txvalid and Txready.
+ * [0] enalbe the MIPI DPHY TxDDRClk.
+ */
+#define MIPI_DSI_PHY_CTRL 0x0
+
+/* [31] clk lane tx_hs_en control selection.
+ * 1: from register. 0: use clk lane state machine.
+ * [30] register bit for clock lane tx_hs_en.
+ * [29] clk lane tx_lp_en contrl selection.
+ * 1: from register. 0: from clk lane state machine.
+ * [28] register bit for clock lane tx_lp_en.
+ * [27] chan0 tx_hs_en control selection.
+ * 1: from register. 0: from chan0 state machine.
+ * [26] register bit for chan0 tx_hs_en.
+ * [25] chan0 tx_lp_en control selection.
+ * 1: from register. 0: from chan0 state machine.
+ * [24] register bit from chan0 tx_lp_en.
+ * [23] chan0 rx_lp_en control selection.
+ * 1: from register. 0: from chan0 state machine.
+ * [22] register bit from chan0 rx_lp_en.
+ * [21] chan0 contention detection enable control selection.
+ * 1: from register. 0: from chan0 state machine.
+ * [20] register bit from chan0 contention dectection enable.
+ * [19] chan1 tx_hs_en control selection.
+ * 1: from register. 0: from chan0 state machine.
+ * [18] register bit for chan1 tx_hs_en.
+ * [17] chan1 tx_lp_en control selection.
+ * 1: from register. 0: from chan0 state machine.
+ * [16] register bit from chan1 tx_lp_en.
+ * [15] chan2 tx_hs_en control selection.
+ * 1: from register. 0: from chan0 state machine.
+ * [14] register bit for chan2 tx_hs_en.
+ * [13] chan2 tx_lp_en control selection.
+ * 1: from register. 0: from chan0 state machine.
+ * [12] register bit from chan2 tx_lp_en.
+ * [11] chan3 tx_hs_en control selection.
+ * 1: from register. 0: from chan0 state machine.
+ * [10] register bit for chan3 tx_hs_en.
+ * [9] chan3 tx_lp_en control selection.
+ * 1: from register. 0: from chan0 state machine.
+ * [8] register bit from chan3 tx_lp_en.
+ * [4] clk chan power down. this bit is also used as the power down
+ * of the whole MIPI_DSI_PHY.
+ * [3] chan3 power down.
+ * [2] chan2 power down.
+ * [1] chan1 power down.
+ * [0] chan0 power down.
+ */
+#define MIPI_DSI_CHAN_CTRL 0x4
+
+/* [24] rx turn watch dog triggered.
+ * [23] rx esc watchdog triggered.
+ * [22] mbias ready.
+ * [21] txclkesc synced and ready.
+ * [20:17] clk lane state. {mbias_ready, tx_stop, tx_ulps, tx_hs_active}
+ * [16:13] chan3 state{0, tx_stop, tx_ulps, tx_hs_active}
+ * [12:9] chan2 state.{0, tx_stop, tx_ulps, tx_hs_active}
+ * [8:5] chan1 state. {0, tx_stop, tx_ulps, tx_hs_active}
+ * [4:0] chan0 state. {TX_STOP, tx_ULPS, hs_active, direction, rxulpsesc}
+ */
+#define MIPI_DSI_CHAN_STS 0x8
+
+/* [31:24] TCLK_PREPARE.
+ * [23:16] TCLK_ZERO.
+ * [15:8] TCLK_POST.
+ * [7:0] TCLK_TRAIL.
+ */
+#define MIPI_DSI_CLK_TIM 0xc
+
+/* [31:24] THS_PREPARE.
+ * [23:16] THS_ZERO.
+ * [15:8] THS_TRAIL.
+ * [7:0] THS_EXIT.
+ */
+#define MIPI_DSI_HS_TIM 0x10
+
+/* [31:24] tTA_GET.
+ * [23:16] tTA_GO.
+ * [15:8] tTA_SURE.
+ * [7:0] tLPX.
+ */
+#define MIPI_DSI_LP_TIM 0x14
+
+/* wait time to MIPI DIS analog ready. */
+#define MIPI_DSI_ANA_UP_TIM 0x18
+
+/* TINIT. */
+#define MIPI_DSI_INIT_TIM 0x1c
+
+/* TWAKEUP. */
+#define MIPI_DSI_WAKEUP_TIM 0x20
+
+/* when in RxULPS check state, after the the logic enable the analog,
+ * how long we should wait to check the lP state .
+ */
+#define MIPI_DSI_LPOK_TIM 0x24
+
+/* Watchdog for RX low power state no finished. */
+#define MIPI_DSI_LP_WCHDOG 0x28
+
+/* tMBIAS, after send power up signals to analog,
+ * how long we should wait for analog powered up.
+ */
+#define MIPI_DSI_ANA_CTRL 0x2c
+
+/* [31:8] reserved for future.
+ * [7:0] tCLK_PRE.
+ */
+#define MIPI_DSI_CLK_TIM1 0x30
+
+/* watchdog for turn around waiting time. */
+#define MIPI_DSI_TURN_WCHDOG 0x34
+
+/* When in RxULPS state, how frequency we should to check
+ * if the TX side out of ULPS state.
+ */
+#define MIPI_DSI_ULPS_CHECK 0x38
+#define MIPI_DSI_TEST_CTRL0 0x3c
+#define MIPI_DSI_TEST_CTRL1 0x40
+
+struct phy_meson_axg_mipi_dphy_priv {
+ struct device *dev;
+ struct regmap *regmap;
+ struct clk *clk;
+ struct reset_control *reset;
+ struct phy *analog;
+ struct phy_configure_opts_mipi_dphy config;
+};
+
+static const struct regmap_config phy_meson_axg_mipi_dphy_regmap_conf = {
+ .reg_bits = 8,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = MIPI_DSI_TEST_CTRL1,
+};
+
+static int phy_meson_axg_mipi_dphy_init(struct phy *phy)
+{
+ struct phy_meson_axg_mipi_dphy_priv *priv = phy_get_drvdata(phy);
+ int ret;
+
+ ret = phy_init(priv->analog);
+ if (ret)
+ return ret;
+
+ ret = reset_control_reset(priv->reset);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int phy_meson_axg_mipi_dphy_configure(struct phy *phy,
+ union phy_configure_opts *opts)
+{
+ struct phy_meson_axg_mipi_dphy_priv *priv = phy_get_drvdata(phy);
+ int ret;
+
+ ret = phy_mipi_dphy_config_validate(&opts->mipi_dphy);
+ if (ret)
+ return ret;
+
+ ret = phy_configure(priv->analog, opts);
+ if (ret)
+ return ret;
+
+ memcpy(&priv->config, opts, sizeof(priv->config));
+
+ return 0;
+}
+
+static int phy_meson_axg_mipi_dphy_power_on(struct phy *phy)
+{
+ struct phy_meson_axg_mipi_dphy_priv *priv = phy_get_drvdata(phy);
+ int ret;
+ unsigned long temp;
+
+ ret = phy_power_on(priv->analog);
+ if (ret)
+ return ret;
+
+ /* enable phy clock */
+ regmap_write(priv->regmap, MIPI_DSI_PHY_CTRL, 0x1);
+ regmap_write(priv->regmap, MIPI_DSI_PHY_CTRL,
+ BIT(0) | /* enable the DSI PLL clock . */
+ BIT(7) | /* enable pll clock which connected to DDR clock path */
+ BIT(8)); /* enable the clock divider counter */
+
+ /* enable the divider clock out */
+ regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(9), BIT(9));
+
+ /* enable the byte clock generation. */
+ regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(12), BIT(12));
+ regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(31), BIT(31));
+ regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(31), 0);
+
+ /* Calculate lanebyteclk period in ps */
+ temp = (1000000 * 100) / (priv->config.hs_clk_rate / 1000);
+ temp = temp * 8 * 10;
+
+ regmap_write(priv->regmap, MIPI_DSI_CLK_TIM,
+ DIV_ROUND_UP(priv->config.clk_trail, temp) |
+ (DIV_ROUND_UP(priv->config.clk_post +
+ priv->config.hs_trail, temp) << 8) |
+ (DIV_ROUND_UP(priv->config.clk_zero, temp) << 16) |
+ (DIV_ROUND_UP(priv->config.clk_prepare, temp) << 24));
+ regmap_write(priv->regmap, MIPI_DSI_CLK_TIM1,
+ DIV_ROUND_UP(priv->config.clk_pre, temp));
+
+ regmap_write(priv->regmap, MIPI_DSI_HS_TIM,
+ DIV_ROUND_UP(priv->config.hs_exit, temp) |
+ (DIV_ROUND_UP(priv->config.hs_trail, temp) << 8) |
+ (DIV_ROUND_UP(priv->config.hs_zero, temp) << 16) |
+ (DIV_ROUND_UP(priv->config.hs_prepare, temp) << 24));
+
+ regmap_write(priv->regmap, MIPI_DSI_LP_TIM,
+ DIV_ROUND_UP(priv->config.lpx, temp) |
+ (DIV_ROUND_UP(priv->config.ta_sure, temp) << 8) |
+ (DIV_ROUND_UP(priv->config.ta_go, temp) << 16) |
+ (DIV_ROUND_UP(priv->config.ta_get, temp) << 24));
+
+ regmap_write(priv->regmap, MIPI_DSI_ANA_UP_TIM, 0x0100);
+ regmap_write(priv->regmap, MIPI_DSI_INIT_TIM,
+ DIV_ROUND_UP(priv->config.init * NSEC_PER_MSEC, temp));
+ regmap_write(priv->regmap, MIPI_DSI_WAKEUP_TIM,
+ DIV_ROUND_UP(priv->config.wakeup * NSEC_PER_MSEC, temp));
+ regmap_write(priv->regmap, MIPI_DSI_LPOK_TIM, 0x7C);
+ regmap_write(priv->regmap, MIPI_DSI_ULPS_CHECK, 0x927C);
+ regmap_write(priv->regmap, MIPI_DSI_LP_WCHDOG, 0x1000);
+ regmap_write(priv->regmap, MIPI_DSI_TURN_WCHDOG, 0x1000);
+
+ /* Powerup the analog circuit */
+ switch (priv->config.lanes) {
+ case 1:
+ regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0xe);
+ break;
+ case 2:
+ regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0xc);
+ break;
+ case 3:
+ regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0x8);
+ break;
+ case 4:
+ default:
+ regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0);
+ break;
+ }
+
+ /* Trigger a sync active for esc_clk */
+ regmap_update_bits(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(1), BIT(1));
+
+ return 0;
+}
+
+static int phy_meson_axg_mipi_dphy_power_off(struct phy *phy)
+{
+ struct phy_meson_axg_mipi_dphy_priv *priv = phy_get_drvdata(phy);
+
+ regmap_write(priv->regmap, MIPI_DSI_CHAN_CTRL, 0xf);
+ regmap_write(priv->regmap, MIPI_DSI_PHY_CTRL, BIT(31));
+
+ phy_power_off(priv->analog);
+
+ return 0;
+}
+
+static int phy_meson_axg_mipi_dphy_exit(struct phy *phy)
+{
+ struct phy_meson_axg_mipi_dphy_priv *priv = phy_get_drvdata(phy);
+ int ret;
+
+ ret = phy_exit(priv->analog);
+ if (ret)
+ return ret;
+
+ return reset_control_reset(priv->reset);
+}
+
+static const struct phy_ops phy_meson_axg_mipi_dphy_ops = {
+ .configure = phy_meson_axg_mipi_dphy_configure,
+ .init = phy_meson_axg_mipi_dphy_init,
+ .exit = phy_meson_axg_mipi_dphy_exit,
+ .power_on = phy_meson_axg_mipi_dphy_power_on,
+ .power_off = phy_meson_axg_mipi_dphy_power_off,
+ .owner = THIS_MODULE,
+};
+
+static int phy_meson_axg_mipi_dphy_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct phy_provider *phy_provider;
+ struct resource *res;
+ struct phy_meson_axg_mipi_dphy_priv *priv;
+ struct phy *phy;
+ void __iomem *base;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->dev = dev;
+ platform_set_drvdata(pdev, priv);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ priv->regmap = devm_regmap_init_mmio(dev, base,
+ &phy_meson_axg_mipi_dphy_regmap_conf);
+ if (IS_ERR(priv->regmap))
+ return PTR_ERR(priv->regmap);
+
+ priv->clk = devm_clk_get(dev, "pclk");
+ if (IS_ERR(priv->clk))
+ return PTR_ERR(priv->clk);
+
+ priv->reset = devm_reset_control_get(dev, "phy");
+ if (IS_ERR(priv->reset))
+ return PTR_ERR(priv->reset);
+
+ priv->analog = devm_phy_get(dev, "analog");
+ if (IS_ERR(priv->analog))
+ return PTR_ERR(priv->analog);
+
+ ret = clk_prepare_enable(priv->clk);
+ if (ret)
+ return ret;
+
+ ret = reset_control_deassert(priv->reset);
+ if (ret)
+ return ret;
+
+ phy = devm_phy_create(dev, NULL, &phy_meson_axg_mipi_dphy_ops);
+ if (IS_ERR(phy)) {
+ ret = PTR_ERR(phy);
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "failed to create PHY\n");
+
+ return ret;
+ }
+
+ phy_set_drvdata(phy, priv);
+
+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id phy_meson_axg_mipi_dphy_of_match[] = {
+ { .compatible = "amlogic,axg-mipi-dphy", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, phy_meson_axg_mipi_dphy_of_match);
+
+static struct platform_driver phy_meson_axg_mipi_dphy_driver = {
+ .probe = phy_meson_axg_mipi_dphy_probe,
+ .driver = {
+ .name = "phy-meson-axg-mipi-dphy",
+ .of_match_table = phy_meson_axg_mipi_dphy_of_match,
+ },
+};
+module_platform_driver(phy_meson_axg_mipi_dphy_driver);
+
+MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
+MODULE_DESCRIPTION("Meson AXG MIPI DPHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c b/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c
index 1431cbf885e1..1027ece6ca12 100644
--- a/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c
+++ b/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c
@@ -4,9 +4,13 @@
*
* Copyright (C) 2019 Remi Pommarel <repk@triplefau.lt>
*/
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
#include <linux/module.h>
#include <linux/phy/phy.h>
#include <linux/regmap.h>
+#include <linux/delay.h>
+#include <linux/mfd/syscon.h>
#include <linux/platform_device.h>
#include <dt-bindings/phy/phy.h>
@@ -14,10 +18,10 @@
#define HHI_MIPI_CNTL0_COMMON_BLOCK GENMASK(31, 28)
#define HHI_MIPI_CNTL0_ENABLE BIT(29)
#define HHI_MIPI_CNTL0_BANDGAP BIT(26)
-#define HHI_MIPI_CNTL0_DECODE_TO_RTERM GENMASK(15, 12)
-#define HHI_MIPI_CNTL0_OUTPUT_EN BIT(3)
+#define HHI_MIPI_CNTL0_DIF_REF_CTL1 GENMASK(25, 16)
+#define HHI_MIPI_CNTL0_DIF_REF_CTL0 GENMASK(15, 0)
-#define HHI_MIPI_CNTL1 0x01
+#define HHI_MIPI_CNTL1 0x04
#define HHI_MIPI_CNTL1_CH0_CML_PDR_EN BIT(12)
#define HHI_MIPI_CNTL1_LP_ABILITY GENMASK(5, 4)
#define HHI_MIPI_CNTL1_LP_RESISTER BIT(3)
@@ -25,100 +29,169 @@
#define HHI_MIPI_CNTL1_INPUT_SEL BIT(1)
#define HHI_MIPI_CNTL1_PRBS7_EN BIT(0)
-#define HHI_MIPI_CNTL2 0x02
+#define HHI_MIPI_CNTL2 0x08
#define HHI_MIPI_CNTL2_CH_PU GENMASK(31, 25)
#define HHI_MIPI_CNTL2_CH_CTL GENMASK(24, 19)
#define HHI_MIPI_CNTL2_CH0_DIGDR_EN BIT(18)
#define HHI_MIPI_CNTL2_CH_DIGDR_EN BIT(17)
#define HHI_MIPI_CNTL2_LPULPS_EN BIT(16)
-#define HHI_MIPI_CNTL2_CH_EN(n) BIT(15 - (n))
+#define HHI_MIPI_CNTL2_CH_EN GENMASK(15, 11)
#define HHI_MIPI_CNTL2_CH0_LP_CTL GENMASK(10, 1)
+#define DSI_LANE_0 BIT(4)
+#define DSI_LANE_1 BIT(3)
+#define DSI_LANE_CLK BIT(2)
+#define DSI_LANE_2 BIT(1)
+#define DSI_LANE_3 BIT(0)
+
struct phy_axg_mipi_pcie_analog_priv {
struct phy *phy;
- unsigned int mode;
struct regmap *regmap;
+ bool dsi_configured;
+ bool dsi_enabled;
+ bool powered;
+ struct phy_configure_opts_mipi_dphy config;
};
-static const struct regmap_config phy_axg_mipi_pcie_analog_regmap_conf = {
- .reg_bits = 8,
- .val_bits = 32,
- .reg_stride = 4,
- .max_register = HHI_MIPI_CNTL2,
-};
+static void phy_bandgap_enable(struct phy_axg_mipi_pcie_analog_priv *priv)
+{
+ regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+ HHI_MIPI_CNTL0_BANDGAP, HHI_MIPI_CNTL0_BANDGAP);
-static int phy_axg_mipi_pcie_analog_power_on(struct phy *phy)
+ regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+ HHI_MIPI_CNTL0_ENABLE, HHI_MIPI_CNTL0_ENABLE);
+}
+
+static void phy_bandgap_disable(struct phy_axg_mipi_pcie_analog_priv *priv)
{
- struct phy_axg_mipi_pcie_analog_priv *priv = phy_get_drvdata(phy);
+ regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+ HHI_MIPI_CNTL0_BANDGAP, 0);
+ regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+ HHI_MIPI_CNTL0_ENABLE, 0);
+}
- /* MIPI not supported yet */
- if (priv->mode != PHY_TYPE_PCIE)
- return -EINVAL;
+static void phy_dsi_analog_enable(struct phy_axg_mipi_pcie_analog_priv *priv)
+{
+ u32 reg;
regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
- HHI_MIPI_CNTL0_BANDGAP, HHI_MIPI_CNTL0_BANDGAP);
+ HHI_MIPI_CNTL0_DIF_REF_CTL1,
+ FIELD_PREP(HHI_MIPI_CNTL0_DIF_REF_CTL1, 0x1b8));
+ regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+ BIT(31), BIT(31));
+ regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+ HHI_MIPI_CNTL0_DIF_REF_CTL0,
+ FIELD_PREP(HHI_MIPI_CNTL0_DIF_REF_CTL0, 0x8));
+
+ regmap_write(priv->regmap, HHI_MIPI_CNTL1, 0x001e);
+
+ regmap_write(priv->regmap, HHI_MIPI_CNTL2,
+ (0x26e0 << 16) | (0x459 << 0));
+
+ reg = DSI_LANE_CLK;
+ switch (priv->config.lanes) {
+ case 4:
+ reg |= DSI_LANE_3;
+ fallthrough;
+ case 3:
+ reg |= DSI_LANE_2;
+ fallthrough;
+ case 2:
+ reg |= DSI_LANE_1;
+ fallthrough;
+ case 1:
+ reg |= DSI_LANE_0;
+ break;
+ default:
+ reg = 0;
+ }
+
+ regmap_update_bits(priv->regmap, HHI_MIPI_CNTL2,
+ HHI_MIPI_CNTL2_CH_EN,
+ FIELD_PREP(HHI_MIPI_CNTL2_CH_EN, reg));
+
+ priv->dsi_enabled = true;
+}
+static void phy_dsi_analog_disable(struct phy_axg_mipi_pcie_analog_priv *priv)
+{
regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
- HHI_MIPI_CNTL0_ENABLE, HHI_MIPI_CNTL0_ENABLE);
- return 0;
+ HHI_MIPI_CNTL0_DIF_REF_CTL1,
+ FIELD_PREP(HHI_MIPI_CNTL0_DIF_REF_CTL1, 0));
+ regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0, BIT(31), 0);
+ regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
+ HHI_MIPI_CNTL0_DIF_REF_CTL1, 0);
+
+ regmap_write(priv->regmap, HHI_MIPI_CNTL1, 0x6);
+
+ regmap_write(priv->regmap, HHI_MIPI_CNTL2, 0x00200000);
+
+ priv->dsi_enabled = false;
}
-static int phy_axg_mipi_pcie_analog_power_off(struct phy *phy)
+static int phy_axg_mipi_pcie_analog_configure(struct phy *phy,
+ union phy_configure_opts *opts)
{
struct phy_axg_mipi_pcie_analog_priv *priv = phy_get_drvdata(phy);
+ int ret;
- /* MIPI not supported yet */
- if (priv->mode != PHY_TYPE_PCIE)
- return -EINVAL;
+ ret = phy_mipi_dphy_config_validate(&opts->mipi_dphy);
+ if (ret)
+ return ret;
+
+ memcpy(&priv->config, opts, sizeof(priv->config));
+
+ priv->dsi_configured = true;
+
+ /* If PHY was already powered on, setup the DSI analog part */
+ if (priv->powered) {
+ /* If reconfiguring, disable & reconfigure */
+ if (priv->dsi_enabled)
+ phy_dsi_analog_disable(priv);
+
+ usleep_range(100, 200);
+
+ phy_dsi_analog_enable(priv);
+ }
- regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
- HHI_MIPI_CNTL0_BANDGAP, 0);
- regmap_update_bits(priv->regmap, HHI_MIPI_CNTL0,
- HHI_MIPI_CNTL0_ENABLE, 0);
return 0;
}
-static int phy_axg_mipi_pcie_analog_init(struct phy *phy)
+static int phy_axg_mipi_pcie_analog_power_on(struct phy *phy)
{
+ struct phy_axg_mipi_pcie_analog_priv *priv = phy_get_drvdata(phy);
+
+ phy_bandgap_enable(priv);
+
+ if (priv->dsi_configured)
+ phy_dsi_analog_enable(priv);
+
+ priv->powered = true;
+
return 0;
}
-static int phy_axg_mipi_pcie_analog_exit(struct phy *phy)
+static int phy_axg_mipi_pcie_analog_power_off(struct phy *phy)
{
+ struct phy_axg_mipi_pcie_analog_priv *priv = phy_get_drvdata(phy);
+
+ phy_bandgap_disable(priv);
+
+ if (priv->dsi_enabled)
+ phy_dsi_analog_disable(priv);
+
+ priv->powered = false;
+
return 0;
}
static const struct phy_ops phy_axg_mipi_pcie_analog_ops = {
- .init = phy_axg_mipi_pcie_analog_init,
- .exit = phy_axg_mipi_pcie_analog_exit,
+ .configure = phy_axg_mipi_pcie_analog_configure,
.power_on = phy_axg_mipi_pcie_analog_power_on,
.power_off = phy_axg_mipi_pcie_analog_power_off,
.owner = THIS_MODULE,
};
-static struct phy *phy_axg_mipi_pcie_analog_xlate(struct device *dev,
- struct of_phandle_args *args)
-{
- struct phy_axg_mipi_pcie_analog_priv *priv = dev_get_drvdata(dev);
- unsigned int mode;
-
- if (args->args_count != 1) {
- dev_err(dev, "invalid number of arguments\n");
- return ERR_PTR(-EINVAL);
- }
-
- mode = args->args[0];
-
- /* MIPI mode is not supported yet */
- if (mode != PHY_TYPE_PCIE) {
- dev_err(dev, "invalid phy mode select argument\n");
- return ERR_PTR(-EINVAL);
- }
-
- priv->mode = mode;
- return priv->phy;
-}
-
static int phy_axg_mipi_pcie_analog_probe(struct platform_device *pdev)
{
struct phy_provider *phy;
@@ -126,27 +199,20 @@ static int phy_axg_mipi_pcie_analog_probe(struct platform_device *pdev)
struct phy_axg_mipi_pcie_analog_priv *priv;
struct device_node *np = dev->of_node;
struct regmap *map;
- struct resource *res;
- void __iomem *base;
int ret;
priv = devm_kmalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(dev, res);
- if (IS_ERR(base)) {
- dev_err(dev, "failed to get regmap base\n");
- return PTR_ERR(base);
- }
-
- map = devm_regmap_init_mmio(dev, base,
- &phy_axg_mipi_pcie_analog_regmap_conf);
+ /* Get the hhi system controller node */
+ map = syscon_node_to_regmap(of_get_parent(dev->of_node));
if (IS_ERR(map)) {
- dev_err(dev, "failed to get HHI regmap\n");
+ dev_err(dev,
+ "failed to get HHI regmap\n");
return PTR_ERR(map);
}
+
priv->regmap = map;
priv->phy = devm_phy_create(dev, np, &phy_axg_mipi_pcie_analog_ops);
@@ -160,8 +226,7 @@ static int phy_axg_mipi_pcie_analog_probe(struct platform_device *pdev)
phy_set_drvdata(priv->phy, priv);
dev_set_drvdata(dev, priv);
- phy = devm_of_phy_provider_register(dev,
- phy_axg_mipi_pcie_analog_xlate);
+ phy = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
return PTR_ERR_OR_ZERO(phy);
}
diff --git a/drivers/phy/amlogic/phy-meson-axg-pcie.c b/drivers/phy/amlogic/phy-meson-axg-pcie.c
index 377ed0dcd0d9..2299bab38e05 100644
--- a/drivers/phy/amlogic/phy-meson-axg-pcie.c
+++ b/drivers/phy/amlogic/phy-meson-axg-pcie.c
@@ -129,7 +129,6 @@ static int phy_axg_pcie_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct phy_axg_pcie_priv *priv;
struct device_node *np = dev->of_node;
- struct resource *res;
void __iomem *base;
int ret;
@@ -145,8 +144,7 @@ static int phy_axg_pcie_probe(struct platform_device *pdev)
return ret;
}
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(dev, res);
+ base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
@@ -155,7 +153,7 @@ static int phy_axg_pcie_probe(struct platform_device *pdev)
if (IS_ERR(priv->regmap))
return PTR_ERR(priv->regmap);
- priv->reset = devm_reset_control_array_get(dev, false, false);
+ priv->reset = devm_reset_control_array_get_exclusive(dev);
if (IS_ERR(priv->reset))
return PTR_ERR(priv->reset);
diff --git a/drivers/phy/amlogic/phy-meson-g12a-usb2.c b/drivers/phy/amlogic/phy-meson-g12a-usb2.c
index b26e30e1afaf..9d1efa0d9394 100644
--- a/drivers/phy/amlogic/phy-meson-g12a-usb2.c
+++ b/drivers/phy/amlogic/phy-meson-g12a-usb2.c
@@ -292,7 +292,6 @@ static int phy_meson_g12a_usb2_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct phy_provider *phy_provider;
- struct resource *res;
struct phy_meson_g12a_usb2_priv *priv;
struct phy *phy;
void __iomem *base;
@@ -305,8 +304,7 @@ static int phy_meson_g12a_usb2_probe(struct platform_device *pdev)
priv->dev = dev;
platform_set_drvdata(pdev, priv);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(dev, res);
+ base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
diff --git a/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c b/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c
index 08e322789e59..5b471ab80fe2 100644
--- a/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c
+++ b/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c
@@ -386,7 +386,6 @@ static int phy_g12a_usb3_pcie_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct phy_g12a_usb3_pcie_priv *priv;
- struct resource *res;
struct phy_provider *phy_provider;
void __iomem *base;
int ret;
@@ -395,8 +394,7 @@ static int phy_g12a_usb3_pcie_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(dev, res);
+ base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
@@ -418,7 +416,7 @@ static int phy_g12a_usb3_pcie_probe(struct platform_device *pdev)
if (ret)
goto err_disable_clk_ref;
- priv->reset = devm_reset_control_array_get(dev, false, false);
+ priv->reset = devm_reset_control_array_get_exclusive(dev);
if (IS_ERR(priv->reset))
return PTR_ERR(priv->reset);
diff --git a/drivers/phy/amlogic/phy-meson-gxl-usb2.c b/drivers/phy/amlogic/phy-meson-gxl-usb2.c
index 43ec9bf24abf..2b3c0d730f20 100644
--- a/drivers/phy/amlogic/phy-meson-gxl-usb2.c
+++ b/drivers/phy/amlogic/phy-meson-gxl-usb2.c
@@ -158,7 +158,8 @@ static int phy_meson_gxl_usb2_set_mode(struct phy *phy,
U2P_R0_DM_PULLDOWN);
regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DP_PULLDOWN,
U2P_R0_DP_PULLDOWN);
- regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_ID_PULLUP, 0);
+ regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_ID_PULLUP,
+ U2P_R0_ID_PULLUP);
break;
case PHY_MODE_USB_DEVICE:
@@ -230,7 +231,6 @@ static int phy_meson_gxl_usb2_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct phy_provider *phy_provider;
- struct resource *res;
struct phy_meson_gxl_usb2_priv *priv;
struct phy *phy;
void __iomem *base;
@@ -242,8 +242,7 @@ static int phy_meson_gxl_usb2_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, priv);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(dev, res);
+ base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
diff --git a/drivers/phy/broadcom/phy-bcm-cygnus-pcie.c b/drivers/phy/broadcom/phy-bcm-cygnus-pcie.c
index b074682d9dd8..548e46776100 100644
--- a/drivers/phy/broadcom/phy-bcm-cygnus-pcie.c
+++ b/drivers/phy/broadcom/phy-bcm-cygnus-pcie.c
@@ -126,7 +126,6 @@ static int cygnus_pcie_phy_probe(struct platform_device *pdev)
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;
@@ -141,8 +140,7 @@ static int cygnus_pcie_phy_probe(struct platform_device *pdev)
core->dev = dev;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- core->base = devm_ioremap_resource(dev, res);
+ core->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(core->base))
return PTR_ERR(core->base);
diff --git a/drivers/phy/broadcom/phy-bcm-kona-usb2.c b/drivers/phy/broadcom/phy-bcm-kona-usb2.c
index 6459296d9bf9..e9cc5f2cb89a 100644
--- a/drivers/phy/broadcom/phy-bcm-kona-usb2.c
+++ b/drivers/phy/broadcom/phy-bcm-kona-usb2.c
@@ -94,7 +94,6 @@ 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;
@@ -102,8 +101,7 @@ static int bcm_kona_usb2_probe(struct platform_device *pdev)
if (!phy)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- phy->regs = devm_ioremap_resource(&pdev->dev, res);
+ phy->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(phy->regs))
return PTR_ERR(phy->regs);
diff --git a/drivers/phy/broadcom/phy-bcm-ns-usb2.c b/drivers/phy/broadcom/phy-bcm-ns-usb2.c
index 9f2f84d65dcd..4b015b8a71c3 100644
--- a/drivers/phy/broadcom/phy-bcm-ns-usb2.c
+++ b/drivers/phy/broadcom/phy-bcm-ns-usb2.c
@@ -83,7 +83,6 @@ 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);
@@ -91,8 +90,7 @@ static int bcm_ns_usb2_probe(struct platform_device *pdev)
return -ENOMEM;
usb2->dev = dev;
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dmu");
- usb2->dmu = devm_ioremap_resource(dev, res);
+ usb2->dmu = devm_platform_ioremap_resource_byname(pdev, "dmu");
if (IS_ERR(usb2->dmu)) {
dev_err(dev, "Failed to map DMU regs\n");
return PTR_ERR(usb2->dmu);
diff --git a/drivers/phy/broadcom/phy-bcm-ns-usb3.c b/drivers/phy/broadcom/phy-bcm-ns-usb3.c
index 47b029fbebbd..eb10ffa13a62 100644
--- a/drivers/phy/broadcom/phy-bcm-ns-usb3.c
+++ b/drivers/phy/broadcom/phy-bcm-ns-usb3.c
@@ -22,8 +22,6 @@
#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
@@ -51,11 +49,8 @@ struct bcm_ns_usb3 {
struct device *dev;
enum bcm_ns_family family;
void __iomem *dmp;
- void __iomem *ccb_mii;
struct mdio_device *mdiodev;
struct phy *phy;
-
- int (*phy_write)(struct bcm_ns_usb3 *usb3, u16 reg, u16 value);
};
static const struct of_device_id bcm_ns_usb3_id_table[] = {
@@ -69,13 +64,9 @@ static const struct of_device_id bcm_ns_usb3_id_table[] = {
},
{},
};
-MODULE_DEVICE_TABLE(of, bcm_ns_usb3_id_table);
static int bcm_ns_usb3_mdio_phy_write(struct bcm_ns_usb3 *usb3, u16 reg,
- u16 value)
-{
- return usb3->phy_write(usb3, reg, value);
-}
+ u16 value);
static int bcm_ns_usb3_phy_init_ns_bx(struct bcm_ns_usb3 *usb3)
{
@@ -187,8 +178,8 @@ static const struct phy_ops ops = {
* MDIO driver code
**************************************************/
-static int bcm_ns_usb3_mdiodev_phy_write(struct bcm_ns_usb3 *usb3, u16 reg,
- u16 value)
+static int bcm_ns_usb3_mdio_phy_write(struct bcm_ns_usb3 *usb3, u16 reg,
+ u16 value)
{
struct mdio_device *mdiodev = usb3->mdiodev;
@@ -229,8 +220,6 @@ static int bcm_ns_usb3_mdio_probe(struct mdio_device *mdiodev)
return PTR_ERR(usb3->dmp);
}
- usb3->phy_write = bcm_ns_usb3_mdiodev_phy_write;
-
usb3->phy = devm_phy_create(dev, NULL, &ops);
if (IS_ERR(usb3->phy)) {
dev_err(dev, "Failed to create PHY\n");
@@ -254,145 +243,7 @@ static struct mdio_driver bcm_ns_usb3_mdio_driver = {
.probe = bcm_ns_usb3_mdio_probe,
};
-/**************************************************
- * Platform driver code
- **************************************************/
-
-static int bcm_ns_usb3_wait_reg(struct bcm_ns_usb3 *usb3, void __iomem *addr,
- u32 mask, u32 value, int usec)
-{
- u32 val;
- int ret;
-
- ret = readl_poll_timeout_atomic(addr, val, ((val & mask) == value),
- 10, usec);
- if (ret)
- dev_err(usb3->dev, "Timeout waiting for register %p\n", addr);
-
- return ret;
-}
-
-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,
- BCM_NS_USB3_MII_MNG_TIMEOUT_US);
-}
-
-static int bcm_ns_usb3_platform_phy_write(struct bcm_ns_usb3 *usb3, u16 reg,
- u16 value)
-{
- u32 tmp = 0;
- int err;
-
- err = bcm_ns_usb3_mii_mng_wait_idle(usb3);
- if (err < 0) {
- dev_err(usb3->dev, "Couldn't write 0x%08x value\n", value);
- return err;
- }
-
- /* TODO: Use a proper MDIO bus layer */
- tmp |= 0x58020000; /* Magic value for MDIO PHY write */
- tmp |= reg << 18;
- tmp |= value;
- writel(tmp, usb3->ccb_mii + BCMA_CCB_MII_MNG_CMD_DATA);
-
- return bcm_ns_usb3_mii_mng_wait_idle(usb3);
-}
-
-static int bcm_ns_usb3_probe(struct platform_device *pdev)
-{
- 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);
- }
-
- /* Enable MDIO. Setting MDCDIV as 26 */
- writel(0x0000009a, usb3->ccb_mii + BCMA_CCB_MII_MNG_CTL);
-
- /* Wait for MDIO? */
- udelay(2);
-
- usb3->phy_write = bcm_ns_usb3_platform_phy_write;
-
- usb3->phy = devm_phy_create(dev, NULL, &ops);
- 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,
- },
-};
-
-static int __init bcm_ns_usb3_module_init(void)
-{
- int err;
-
- /*
- * For backward compatibility we register as MDIO and platform driver.
- * After getting MDIO binding commonly used (e.g. switching all DT files
- * to use it) we should deprecate the old binding and eventually drop
- * support for it.
- */
-
- err = mdio_driver_register(&bcm_ns_usb3_mdio_driver);
- if (err)
- return err;
-
- err = platform_driver_register(&bcm_ns_usb3_driver);
- if (err)
- mdio_driver_unregister(&bcm_ns_usb3_mdio_driver);
-
- return err;
-}
-module_init(bcm_ns_usb3_module_init);
-
-static void __exit bcm_ns_usb3_module_exit(void)
-{
- platform_driver_unregister(&bcm_ns_usb3_driver);
- mdio_driver_unregister(&bcm_ns_usb3_mdio_driver);
-}
-module_exit(bcm_ns_usb3_module_exit)
+mdio_module_driver(bcm_ns_usb3_mdio_driver);
MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, bcm_ns_usb3_id_table);
diff --git a/drivers/phy/broadcom/phy-bcm-ns2-usbdrd.c b/drivers/phy/broadcom/phy-bcm-ns2-usbdrd.c
index 9630ac127366..65a399acc845 100644
--- a/drivers/phy/broadcom/phy-bcm-ns2-usbdrd.c
+++ b/drivers/phy/broadcom/phy-bcm-ns2-usbdrd.c
@@ -293,7 +293,6 @@ static int ns2_drd_phy_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct ns2_phy_driver *driver;
struct ns2_phy_data *data;
- struct resource *res;
int ret;
u32 val;
@@ -307,23 +306,19 @@ static int ns2_drd_phy_probe(struct platform_device *pdev)
if (!driver->data)
return -ENOMEM;
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "icfg");
- driver->icfgdrd_regs = devm_ioremap_resource(dev, res);
+ driver->icfgdrd_regs = devm_platform_ioremap_resource_byname(pdev, "icfg");
if (IS_ERR(driver->icfgdrd_regs))
return PTR_ERR(driver->icfgdrd_regs);
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rst-ctrl");
- driver->idmdrd_rst_ctrl = devm_ioremap_resource(dev, res);
+ driver->idmdrd_rst_ctrl = devm_platform_ioremap_resource_byname(pdev, "rst-ctrl");
if (IS_ERR(driver->idmdrd_rst_ctrl))
return PTR_ERR(driver->idmdrd_rst_ctrl);
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "crmu-ctrl");
- driver->crmu_usb2_ctrl = devm_ioremap_resource(dev, res);
+ driver->crmu_usb2_ctrl = devm_platform_ioremap_resource_byname(pdev, "crmu-ctrl");
if (IS_ERR(driver->crmu_usb2_ctrl))
return PTR_ERR(driver->crmu_usb2_ctrl);
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "usb2-strap");
- driver->usb2h_strap_reg = devm_ioremap_resource(dev, res);
+ driver->usb2h_strap_reg = devm_platform_ioremap_resource_byname(pdev, "usb2-strap");
if (IS_ERR(driver->usb2h_strap_reg))
return PTR_ERR(driver->usb2h_strap_reg);
diff --git a/drivers/phy/broadcom/phy-bcm-sr-pcie.c b/drivers/phy/broadcom/phy-bcm-sr-pcie.c
index 96a3af126a78..8a4aadf166cf 100644
--- a/drivers/phy/broadcom/phy-bcm-sr-pcie.c
+++ b/drivers/phy/broadcom/phy-bcm-sr-pcie.c
@@ -217,7 +217,6 @@ static int sr_pcie_phy_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
struct sr_pcie_phy_core *core;
- struct resource *res;
struct phy_provider *provider;
unsigned int phy_idx = 0;
@@ -226,9 +225,7 @@ static int sr_pcie_phy_probe(struct platform_device *pdev)
return -ENOMEM;
core->dev = dev;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- core->base = devm_ioremap_resource(core->dev, res);
+ core->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(core->base))
return PTR_ERR(core->base);
diff --git a/drivers/phy/broadcom/phy-bcm-sr-usb.c b/drivers/phy/broadcom/phy-bcm-sr-usb.c
index c3e99ad17487..0002da3b5b5d 100644
--- a/drivers/phy/broadcom/phy-bcm-sr-usb.c
+++ b/drivers/phy/broadcom/phy-bcm-sr-usb.c
@@ -300,14 +300,12 @@ static int bcm_usb_phy_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *dn = dev->of_node;
const struct of_device_id *of_id;
- struct resource *res;
void __iomem *regs;
int ret;
enum bcm_usb_phy_version version;
struct phy_provider *phy_provider;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- regs = devm_ioremap_resource(dev, res);
+ regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(regs))
return PTR_ERR(regs);
diff --git a/drivers/phy/broadcom/phy-brcm-sata.c b/drivers/phy/broadcom/phy-brcm-sata.c
index 18251f232172..3ecf41359591 100644
--- a/drivers/phy/broadcom/phy-brcm-sata.c
+++ b/drivers/phy/broadcom/phy-brcm-sata.c
@@ -65,6 +65,7 @@ struct brcm_sata_port {
bool ssc_en;
enum brcm_sata_phy_rxaeq_mode rxaeq_mode;
u32 rxaeq_val;
+ u32 tx_amplitude_val;
};
struct brcm_sata_phy {
@@ -84,6 +85,10 @@ enum sata_phy_regs {
BLOCK0_SPARE_OOB_CLK_SEL_MASK = 0x3,
BLOCK0_SPARE_OOB_CLK_SEL_REFBY2 = 0x1,
+ BLOCK1_REG_BANK = 0x10,
+ BLOCK1_TEST_TX = 0x83,
+ BLOCK1_TEST_TX_AMP_SHIFT = 12,
+
PLL_REG_BANK_0 = 0x050,
PLL_REG_BANK_0_PLLCONTROL_0 = 0x81,
PLLCONTROL_0_FREQ_DET_RESTART = BIT(13),
@@ -379,6 +384,29 @@ static int brcm_stb_sata_16nm_ssc_init(struct brcm_sata_port *port)
brcm_sata_phy_wr(port, RXPMD_REG_BANK, RXPMD_RX_FREQ_MON_CONTROL1,
~tmp, RXPMD_MON_CORRECT_EN | value);
+ tmp = GENMASK(15, 12);
+ switch (port->tx_amplitude_val) {
+ case 400:
+ value = BIT(12) | BIT(13);
+ break;
+ case 500:
+ value = BIT(13);
+ break;
+ case 600:
+ value = BIT(12);
+ break;
+ case 800:
+ value = 0;
+ break;
+ default:
+ value = tmp;
+ break;
+ }
+
+ if (value != tmp)
+ brcm_sata_phy_wr(port, BLOCK1_REG_BANK, BLOCK1_TEST_TX, ~tmp,
+ value);
+
/* Turn on/off SSC */
brcm_sata_phy_wr(port, TX_REG_BANK, TX_ACTRL5, ~TX_ACTRL5_SSC_EN,
port->ssc_en ? TX_ACTRL5_SSC_EN : 0);
@@ -726,7 +754,6 @@ static int brcm_sata_phy_probe(struct platform_device *pdev)
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;
@@ -739,8 +766,7 @@ static int brcm_sata_phy_probe(struct platform_device *pdev)
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);
+ priv->phy_base = devm_platform_ioremap_resource_byname(pdev, "phy");
if (IS_ERR(priv->phy_base))
return PTR_ERR(priv->phy_base);
@@ -751,9 +777,7 @@ static int brcm_sata_phy_probe(struct platform_device *pdev)
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);
+ priv->ctrl_base = devm_platform_ioremap_resource_byname(pdev, "phy-ctrl");
if (IS_ERR(priv->ctrl_base))
return PTR_ERR(priv->ctrl_base);
}
@@ -791,6 +815,10 @@ static int brcm_sata_phy_probe(struct platform_device *pdev)
if (port->rxaeq_mode == RXAEQ_MODE_MANUAL)
of_property_read_u32(child, "brcm,rxaeq-value",
&port->rxaeq_val);
+
+ of_property_read_u32(child, "brcm,tx-amplitude-millivolt",
+ &port->tx_amplitude_val);
+
port->ssc_en = of_property_read_bool(child, "brcm,enable-ssc");
if (IS_ERR(port->phy)) {
dev_err(dev, "failed to create PHY\n");
diff --git a/drivers/phy/cadence/cdns-dphy.c b/drivers/phy/cadence/cdns-dphy.c
index 90c4e9b5aac8..ba042e39cfaf 100644
--- a/drivers/phy/cadence/cdns-dphy.c
+++ b/drivers/phy/cadence/cdns-dphy.c
@@ -314,7 +314,6 @@ static int cdns_dphy_probe(struct platform_device *pdev)
{
struct phy_provider *phy_provider;
struct cdns_dphy *dphy;
- struct resource *res;
int ret;
dphy = devm_kzalloc(&pdev->dev, sizeof(*dphy), GFP_KERNEL);
@@ -326,8 +325,7 @@ static int cdns_dphy_probe(struct platform_device *pdev)
if (!dphy->ops)
return -EINVAL;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- dphy->regs = devm_ioremap_resource(&pdev->dev, res);
+ dphy->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(dphy->regs))
return PTR_ERR(dphy->regs);
diff --git a/drivers/phy/cadence/phy-cadence-salvo.c b/drivers/phy/cadence/phy-cadence-salvo.c
index 88e239adc3b8..51c0b98f5fd7 100644
--- a/drivers/phy/cadence/phy-cadence-salvo.c
+++ b/drivers/phy/cadence/phy-cadence-salvo.c
@@ -263,7 +263,6 @@ static int cdns_salvo_phy_probe(struct platform_device *pdev)
struct phy_provider *phy_provider;
struct device *dev = &pdev->dev;
struct cdns_salvo_phy *salvo_phy;
- struct resource *res;
const struct of_device_id *match;
struct cdns_salvo_data *data;
@@ -281,8 +280,7 @@ static int cdns_salvo_phy_probe(struct platform_device *pdev)
if (IS_ERR(salvo_phy->clk))
return PTR_ERR(salvo_phy->clk);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- salvo_phy->base = devm_ioremap_resource(dev, res);
+ salvo_phy->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(salvo_phy->base))
return PTR_ERR(salvo_phy->base);
diff --git a/drivers/phy/cadence/phy-cadence-sierra.c b/drivers/phy/cadence/phy-cadence-sierra.c
index 453ef26fa1c7..26a0badabe38 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -479,7 +479,6 @@ static int cdns_sierra_phy_probe(struct platform_device *pdev)
const struct of_device_id *match;
struct cdns_sierra_data *data;
unsigned int id_value;
- struct resource *res;
int i, ret, node = 0;
void __iomem *base;
struct clk *clk;
@@ -502,8 +501,7 @@ static int cdns_sierra_phy_probe(struct platform_device *pdev)
sp->dev = dev;
sp->init_data = data;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(dev, res);
+ base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base)) {
dev_err(dev, "missing \"reg\"\n");
return PTR_ERR(base);
diff --git a/drivers/phy/freescale/phy-fsl-imx8-mipi-dphy.c b/drivers/phy/freescale/phy-fsl-imx8-mipi-dphy.c
index 9f2c1da14f5a..a95572b397ca 100644
--- a/drivers/phy/freescale/phy-fsl-imx8-mipi-dphy.c
+++ b/drivers/phy/freescale/phy-fsl-imx8-mipi-dphy.c
@@ -434,7 +434,6 @@ static int mixel_dphy_probe(struct platform_device *pdev)
struct device_node *np = dev->of_node;
struct phy_provider *phy_provider;
struct mixel_dphy_priv *priv;
- struct resource *res;
struct phy *phy;
void __iomem *base;
@@ -449,8 +448,7 @@ static int mixel_dphy_probe(struct platform_device *pdev)
if (!priv->devdata)
return -EINVAL;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(dev, res);
+ base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
diff --git a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
index 62d6d6849ad6..a29b4a6f7c24 100644
--- a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
+++ b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
@@ -131,7 +131,7 @@ static const struct phy_ops imx8mq_usb_phy_ops = {
.owner = THIS_MODULE,
};
-static struct phy_ops imx8mp_usb_phy_ops = {
+static const struct phy_ops imx8mp_usb_phy_ops = {
.init = imx8mp_usb_phy_init,
.power_on = imx8mq_phy_power_on,
.power_off = imx8mq_phy_power_off,
@@ -152,7 +152,6 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev)
struct phy_provider *phy_provider;
struct device *dev = &pdev->dev;
struct imx8mq_usb_phy *imx_phy;
- struct resource *res;
const struct phy_ops *phy_ops;
imx_phy = devm_kzalloc(dev, sizeof(*imx_phy), GFP_KERNEL);
@@ -165,8 +164,7 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev)
return PTR_ERR(imx_phy->clk);
}
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- imx_phy->base = devm_ioremap_resource(dev, res);
+ imx_phy->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(imx_phy->base))
return PTR_ERR(imx_phy->base);
diff --git a/drivers/phy/ingenic/Kconfig b/drivers/phy/ingenic/Kconfig
new file mode 100644
index 000000000000..f23cc109324b
--- /dev/null
+++ b/drivers/phy/ingenic/Kconfig
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Phy drivers for Ingenic platforms
+#
+config PHY_INGENIC_USB
+ tristate "Ingenic SoCs USB PHY Driver"
+ depends on MIPS || COMPILE_TEST
+ depends on USB_SUPPORT
+ depends on HAS_IOMEM
+ select GENERIC_PHY
+ help
+ This driver provides USB PHY support for the USB controller found
+ on the JZ-series and X-series SoCs from Ingenic.
diff --git a/drivers/phy/ingenic/Makefile b/drivers/phy/ingenic/Makefile
new file mode 100644
index 000000000000..65d5ea00fc9d
--- /dev/null
+++ b/drivers/phy/ingenic/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-y += phy-ingenic-usb.o
diff --git a/drivers/phy/ingenic/phy-ingenic-usb.c b/drivers/phy/ingenic/phy-ingenic-usb.c
new file mode 100644
index 000000000000..4d1587d82286
--- /dev/null
+++ b/drivers/phy/ingenic/phy-ingenic-usb.c
@@ -0,0 +1,412 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Ingenic SoCs USB PHY driver
+ * Copyright (c) Paul Cercueil <paul@crapouillou.net>
+ * Copyright (c) 漆鹏振 (Qi Pengzhen) <aric.pzqi@ingenic.com>
+ * Copyright (c) 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+/* OTGPHY register offsets */
+#define REG_USBPCR_OFFSET 0x00
+#define REG_USBRDT_OFFSET 0x04
+#define REG_USBVBFIL_OFFSET 0x08
+#define REG_USBPCR1_OFFSET 0x0c
+
+/* bits within the USBPCR register */
+#define USBPCR_USB_MODE BIT(31)
+#define USBPCR_AVLD_REG BIT(30)
+#define USBPCR_COMMONONN BIT(25)
+#define USBPCR_VBUSVLDEXT BIT(24)
+#define USBPCR_VBUSVLDEXTSEL BIT(23)
+#define USBPCR_POR BIT(22)
+#define USBPCR_SIDDQ BIT(21)
+#define USBPCR_OTG_DISABLE BIT(20)
+#define USBPCR_TXPREEMPHTUNE BIT(6)
+
+#define USBPCR_IDPULLUP_MASK GENMASK(29, 28)
+#define USBPCR_IDPULLUP_ALWAYS 0x2
+#define USBPCR_IDPULLUP_SUSPEND 0x1
+#define USBPCR_IDPULLUP_OTG 0x0
+
+#define USBPCR_COMPDISTUNE_MASK GENMASK(19, 17)
+#define USBPCR_COMPDISTUNE_DFT 0x4
+
+#define USBPCR_OTGTUNE_MASK GENMASK(16, 14)
+#define USBPCR_OTGTUNE_DFT 0x4
+
+#define USBPCR_SQRXTUNE_MASK GENMASK(13, 11)
+#define USBPCR_SQRXTUNE_DCR_20PCT 0x7
+#define USBPCR_SQRXTUNE_DFT 0x3
+
+#define USBPCR_TXFSLSTUNE_MASK GENMASK(10, 7)
+#define USBPCR_TXFSLSTUNE_DCR_50PPT 0xf
+#define USBPCR_TXFSLSTUNE_DCR_25PPT 0x7
+#define USBPCR_TXFSLSTUNE_DFT 0x3
+#define USBPCR_TXFSLSTUNE_INC_25PPT 0x1
+#define USBPCR_TXFSLSTUNE_INC_50PPT 0x0
+
+#define USBPCR_TXHSXVTUNE_MASK GENMASK(5, 4)
+#define USBPCR_TXHSXVTUNE_DFT 0x3
+#define USBPCR_TXHSXVTUNE_DCR_15MV 0x1
+
+#define USBPCR_TXRISETUNE_MASK GENMASK(5, 4)
+#define USBPCR_TXRISETUNE_DFT 0x3
+
+#define USBPCR_TXVREFTUNE_MASK GENMASK(3, 0)
+#define USBPCR_TXVREFTUNE_INC_75PPT 0xb
+#define USBPCR_TXVREFTUNE_INC_25PPT 0x7
+#define USBPCR_TXVREFTUNE_DFT 0x5
+
+/* bits within the USBRDTR register */
+#define USBRDT_UTMI_RST BIT(27)
+#define USBRDT_HB_MASK BIT(26)
+#define USBRDT_VBFIL_LD_EN BIT(25)
+#define USBRDT_IDDIG_EN BIT(24)
+#define USBRDT_IDDIG_REG BIT(23)
+#define USBRDT_VBFIL_EN BIT(2)
+
+/* bits within the USBPCR1 register */
+#define USBPCR1_BVLD_REG BIT(31)
+#define USBPCR1_DPPD BIT(29)
+#define USBPCR1_DMPD BIT(28)
+#define USBPCR1_USB_SEL BIT(28)
+#define USBPCR1_PORT_RST BIT(21)
+#define USBPCR1_WORD_IF_16BIT BIT(19)
+
+enum ingenic_usb_phy_version {
+ ID_JZ4770,
+ ID_JZ4775,
+ ID_JZ4780,
+ ID_X1000,
+ ID_X1830,
+ ID_X2000,
+};
+
+struct ingenic_soc_info {
+ enum ingenic_usb_phy_version version;
+
+ void (*usb_phy_init)(struct phy *phy);
+};
+
+struct ingenic_usb_phy {
+ const struct ingenic_soc_info *soc_info;
+
+ struct phy *phy;
+ void __iomem *base;
+ struct clk *clk;
+ struct regulator *vcc_supply;
+};
+
+static int ingenic_usb_phy_init(struct phy *phy)
+{
+ struct ingenic_usb_phy *priv = phy_get_drvdata(phy);
+ int err;
+ u32 reg;
+
+ err = clk_prepare_enable(priv->clk);
+ if (err) {
+ dev_err(&phy->dev, "Unable to start clock: %d\n", err);
+ return err;
+ }
+
+ priv->soc_info->usb_phy_init(phy);
+
+ /* Wait for PHY to reset */
+ usleep_range(30, 300);
+ reg = readl(priv->base + REG_USBPCR_OFFSET);
+ writel(reg & ~USBPCR_POR, priv->base + REG_USBPCR_OFFSET);
+ usleep_range(300, 1000);
+
+ return 0;
+}
+
+static int ingenic_usb_phy_exit(struct phy *phy)
+{
+ struct ingenic_usb_phy *priv = phy_get_drvdata(phy);
+
+ clk_disable_unprepare(priv->clk);
+ regulator_disable(priv->vcc_supply);
+
+ return 0;
+}
+
+static int ingenic_usb_phy_power_on(struct phy *phy)
+{
+ struct ingenic_usb_phy *priv = phy_get_drvdata(phy);
+ int err;
+
+ err = regulator_enable(priv->vcc_supply);
+ if (err) {
+ dev_err(&phy->dev, "Unable to enable VCC: %d\n", err);
+ return err;
+ }
+
+ return 0;
+}
+
+static int ingenic_usb_phy_power_off(struct phy *phy)
+{
+ struct ingenic_usb_phy *priv = phy_get_drvdata(phy);
+
+ regulator_disable(priv->vcc_supply);
+
+ return 0;
+}
+
+static int ingenic_usb_phy_set_mode(struct phy *phy,
+ enum phy_mode mode, int submode)
+{
+ struct ingenic_usb_phy *priv = phy_get_drvdata(phy);
+ u32 reg;
+
+ switch (mode) {
+ case PHY_MODE_USB_HOST:
+ reg = readl(priv->base + REG_USBPCR_OFFSET);
+ u32p_replace_bits(&reg, 1, USBPCR_USB_MODE);
+ u32p_replace_bits(&reg, 0, USBPCR_VBUSVLDEXT);
+ u32p_replace_bits(&reg, 0, USBPCR_VBUSVLDEXTSEL);
+ u32p_replace_bits(&reg, 0, USBPCR_OTG_DISABLE);
+ writel(reg, priv->base + REG_USBPCR_OFFSET);
+
+ break;
+ case PHY_MODE_USB_DEVICE:
+ reg = readl(priv->base + REG_USBPCR_OFFSET);
+ u32p_replace_bits(&reg, 0, USBPCR_USB_MODE);
+ u32p_replace_bits(&reg, 1, USBPCR_VBUSVLDEXT);
+ u32p_replace_bits(&reg, 1, USBPCR_VBUSVLDEXTSEL);
+ u32p_replace_bits(&reg, 1, USBPCR_OTG_DISABLE);
+ writel(reg, priv->base + REG_USBPCR_OFFSET);
+
+ break;
+ case PHY_MODE_USB_OTG:
+ reg = readl(priv->base + REG_USBPCR_OFFSET);
+ u32p_replace_bits(&reg, 1, USBPCR_USB_MODE);
+ u32p_replace_bits(&reg, 1, USBPCR_VBUSVLDEXT);
+ u32p_replace_bits(&reg, 1, USBPCR_VBUSVLDEXTSEL);
+ u32p_replace_bits(&reg, 0, USBPCR_OTG_DISABLE);
+ writel(reg, priv->base + REG_USBPCR_OFFSET);
+
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct phy_ops ingenic_usb_phy_ops = {
+ .init = ingenic_usb_phy_init,
+ .exit = ingenic_usb_phy_exit,
+ .power_on = ingenic_usb_phy_power_on,
+ .power_off = ingenic_usb_phy_power_off,
+ .set_mode = ingenic_usb_phy_set_mode,
+ .owner = THIS_MODULE,
+};
+
+static void jz4770_usb_phy_init(struct phy *phy)
+{
+ struct ingenic_usb_phy *priv = phy_get_drvdata(phy);
+ u32 reg;
+
+ reg = USBPCR_AVLD_REG | USBPCR_COMMONONN | USBPCR_POR |
+ FIELD_PREP(USBPCR_IDPULLUP_MASK, USBPCR_IDPULLUP_ALWAYS) |
+ FIELD_PREP(USBPCR_COMPDISTUNE_MASK, USBPCR_COMPDISTUNE_DFT) |
+ FIELD_PREP(USBPCR_OTGTUNE_MASK, USBPCR_OTGTUNE_DFT) |
+ FIELD_PREP(USBPCR_SQRXTUNE_MASK, USBPCR_SQRXTUNE_DFT) |
+ FIELD_PREP(USBPCR_TXFSLSTUNE_MASK, USBPCR_TXFSLSTUNE_DFT) |
+ FIELD_PREP(USBPCR_TXRISETUNE_MASK, USBPCR_TXRISETUNE_DFT) |
+ FIELD_PREP(USBPCR_TXVREFTUNE_MASK, USBPCR_TXVREFTUNE_DFT);
+ writel(reg, priv->base + REG_USBPCR_OFFSET);
+}
+
+static void jz4775_usb_phy_init(struct phy *phy)
+{
+ struct ingenic_usb_phy *priv = phy_get_drvdata(phy);
+ u32 reg;
+
+ reg = readl(priv->base + REG_USBPCR1_OFFSET) | USBPCR1_USB_SEL |
+ USBPCR1_WORD_IF_16BIT;
+ writel(reg, priv->base + REG_USBPCR1_OFFSET);
+
+ reg = USBPCR_COMMONONN | USBPCR_POR |
+ FIELD_PREP(USBPCR_TXVREFTUNE_MASK, USBPCR_TXVREFTUNE_INC_75PPT);
+ writel(reg, priv->base + REG_USBPCR_OFFSET);
+}
+
+static void jz4780_usb_phy_init(struct phy *phy)
+{
+ struct ingenic_usb_phy *priv = phy_get_drvdata(phy);
+ u32 reg;
+
+ reg = readl(priv->base + REG_USBPCR1_OFFSET) | USBPCR1_USB_SEL |
+ USBPCR1_WORD_IF_16BIT;
+ writel(reg, priv->base + REG_USBPCR1_OFFSET);
+
+ reg = USBPCR_TXPREEMPHTUNE | USBPCR_COMMONONN | USBPCR_POR;
+ writel(reg, priv->base + REG_USBPCR_OFFSET);
+}
+
+static void x1000_usb_phy_init(struct phy *phy)
+{
+ struct ingenic_usb_phy *priv = phy_get_drvdata(phy);
+ u32 reg;
+
+ reg = readl(priv->base + REG_USBPCR1_OFFSET) | USBPCR1_WORD_IF_16BIT;
+ writel(reg, priv->base + REG_USBPCR1_OFFSET);
+
+ reg = USBPCR_TXPREEMPHTUNE | USBPCR_COMMONONN | USBPCR_POR |
+ FIELD_PREP(USBPCR_SQRXTUNE_MASK, USBPCR_SQRXTUNE_DCR_20PCT) |
+ FIELD_PREP(USBPCR_TXHSXVTUNE_MASK, USBPCR_TXHSXVTUNE_DCR_15MV) |
+ FIELD_PREP(USBPCR_TXVREFTUNE_MASK, USBPCR_TXVREFTUNE_INC_25PPT);
+ writel(reg, priv->base + REG_USBPCR_OFFSET);
+}
+
+static void x1830_usb_phy_init(struct phy *phy)
+{
+ struct ingenic_usb_phy *priv = phy_get_drvdata(phy);
+ u32 reg;
+
+ /* rdt */
+ writel(USBRDT_VBFIL_EN | USBRDT_UTMI_RST, priv->base + REG_USBRDT_OFFSET);
+
+ reg = readl(priv->base + REG_USBPCR1_OFFSET) | USBPCR1_WORD_IF_16BIT |
+ USBPCR1_DMPD | USBPCR1_DPPD;
+ writel(reg, priv->base + REG_USBPCR1_OFFSET);
+
+ reg = USBPCR_VBUSVLDEXT | USBPCR_TXPREEMPHTUNE | USBPCR_COMMONONN | USBPCR_POR |
+ FIELD_PREP(USBPCR_IDPULLUP_MASK, USBPCR_IDPULLUP_OTG);
+ writel(reg, priv->base + REG_USBPCR_OFFSET);
+}
+
+static void x2000_usb_phy_init(struct phy *phy)
+{
+ struct ingenic_usb_phy *priv = phy_get_drvdata(phy);
+ u32 reg;
+
+ reg = readl(priv->base + REG_USBPCR1_OFFSET) | USBPCR1_DPPD | USBPCR1_DMPD;
+ writel(reg & ~USBPCR1_PORT_RST, priv->base + REG_USBPCR1_OFFSET);
+
+ reg = USBPCR_POR | FIELD_PREP(USBPCR_IDPULLUP_MASK, USBPCR_IDPULLUP_OTG);
+ writel(reg, priv->base + REG_USBPCR_OFFSET);
+}
+
+static const struct ingenic_soc_info jz4770_soc_info = {
+ .version = ID_JZ4770,
+
+ .usb_phy_init = jz4770_usb_phy_init,
+};
+
+static const struct ingenic_soc_info jz4775_soc_info = {
+ .version = ID_JZ4775,
+
+ .usb_phy_init = jz4775_usb_phy_init,
+};
+
+static const struct ingenic_soc_info jz4780_soc_info = {
+ .version = ID_JZ4780,
+
+ .usb_phy_init = jz4780_usb_phy_init,
+};
+
+static const struct ingenic_soc_info x1000_soc_info = {
+ .version = ID_X1000,
+
+ .usb_phy_init = x1000_usb_phy_init,
+};
+
+static const struct ingenic_soc_info x1830_soc_info = {
+ .version = ID_X1830,
+
+ .usb_phy_init = x1830_usb_phy_init,
+};
+
+static const struct ingenic_soc_info x2000_soc_info = {
+ .version = ID_X2000,
+
+ .usb_phy_init = x2000_usb_phy_init,
+};
+
+static int ingenic_usb_phy_probe(struct platform_device *pdev)
+{
+ struct ingenic_usb_phy *priv;
+ struct phy_provider *provider;
+ struct device *dev = &pdev->dev;
+ int err;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->soc_info = device_get_match_data(dev);
+ if (!priv->soc_info) {
+ dev_err(dev, "Error: No device match found\n");
+ return -ENODEV;
+ }
+
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(priv->base)) {
+ dev_err(dev, "Failed to map registers\n");
+ return PTR_ERR(priv->base);
+ }
+
+ priv->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(priv->clk)) {
+ err = PTR_ERR(priv->clk);
+ if (err != -EPROBE_DEFER)
+ dev_err(dev, "Failed to get clock\n");
+ return err;
+ }
+
+ priv->vcc_supply = devm_regulator_get(dev, "vcc");
+ if (IS_ERR(priv->vcc_supply)) {
+ err = PTR_ERR(priv->vcc_supply);
+ if (err != -EPROBE_DEFER)
+ dev_err(dev, "Failed to get regulator\n");
+ return err;
+ }
+
+ priv->phy = devm_phy_create(dev, NULL, &ingenic_usb_phy_ops);
+ if (IS_ERR(priv))
+ return PTR_ERR(priv);
+
+ phy_set_drvdata(priv->phy, priv);
+
+ provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+ return PTR_ERR_OR_ZERO(provider);
+}
+
+static const struct of_device_id ingenic_usb_phy_of_matches[] = {
+ { .compatible = "ingenic,jz4770-phy", .data = &jz4770_soc_info },
+ { .compatible = "ingenic,jz4775-phy", .data = &jz4775_soc_info },
+ { .compatible = "ingenic,jz4780-phy", .data = &jz4780_soc_info },
+ { .compatible = "ingenic,x1000-phy", .data = &x1000_soc_info },
+ { .compatible = "ingenic,x1830-phy", .data = &x1830_soc_info },
+ { .compatible = "ingenic,x2000-phy", .data = &x2000_soc_info },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ingenic_usb_phy_of_matches);
+
+static struct platform_driver ingenic_usb_phy_driver = {
+ .probe = ingenic_usb_phy_probe,
+ .driver = {
+ .name = "ingenic-usb-phy",
+ .of_match_table = ingenic_usb_phy_of_matches,
+ },
+};
+module_platform_driver(ingenic_usb_phy_driver);
+
+MODULE_AUTHOR("周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>");
+MODULE_AUTHOR("漆鹏振 (Qi Pengzhen) <aric.pzqi@ingenic.com>");
+MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
+MODULE_DESCRIPTION("Ingenic SoCs USB PHY driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/intel/Kconfig b/drivers/phy/intel/Kconfig
index 62c24764654b..ac42bb2fb394 100644
--- a/drivers/phy/intel/Kconfig
+++ b/drivers/phy/intel/Kconfig
@@ -14,6 +14,18 @@ config PHY_INTEL_KEEMBAY_EMMC
To compile this driver as a module, choose M here: the module
will be called phy-keembay-emmc.ko.
+config PHY_INTEL_KEEMBAY_USB
+ tristate "Intel Keem Bay USB PHY driver"
+ depends on ARCH_KEEMBAY || COMPILE_TEST
+ depends on HAS_IOMEM
+ select GENERIC_PHY
+ select REGMAP_MMIO
+ help
+ Choose this option if you have an Intel Keem Bay SoC.
+
+ To compile this driver as a module, choose M here: the module
+ will be called phy-keembay-usb.ko.
+
config PHY_INTEL_LGM_COMBO
bool "Intel Lightning Mountain ComboPHY driver"
depends on X86 || COMPILE_TEST
diff --git a/drivers/phy/intel/Makefile b/drivers/phy/intel/Makefile
index a5e0af5ccd75..14550981a707 100644
--- a/drivers/phy/intel/Makefile
+++ b/drivers/phy/intel/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_PHY_INTEL_KEEMBAY_EMMC) += phy-intel-keembay-emmc.o
+obj-$(CONFIG_PHY_INTEL_KEEMBAY_USB) += phy-intel-keembay-usb.o
obj-$(CONFIG_PHY_INTEL_LGM_COMBO) += phy-intel-lgm-combo.o
obj-$(CONFIG_PHY_INTEL_LGM_EMMC) += phy-intel-lgm-emmc.o
diff --git a/drivers/phy/intel/phy-intel-keembay-usb.c b/drivers/phy/intel/phy-intel-keembay-usb.c
new file mode 100644
index 000000000000..c8b05f7b2445
--- /dev/null
+++ b/drivers/phy/intel/phy-intel-keembay-usb.c
@@ -0,0 +1,301 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Intel Keem Bay USB PHY driver
+ * Copyright (C) 2020 Intel Corporation
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+/* USS (USB Subsystem) clock control registers */
+#define USS_CPR_CLK_EN 0x00
+#define USS_CPR_CLK_SET 0x04
+#define USS_CPR_CLK_CLR 0x08
+#define USS_CPR_RST_EN 0x10
+#define USS_CPR_RST_SET 0x14
+#define USS_CPR_RST_CLR 0x18
+
+/* USS clock/reset bit fields */
+#define USS_CPR_PHY_TST BIT(6)
+#define USS_CPR_LOW_JIT BIT(5)
+#define USS_CPR_CORE BIT(4)
+#define USS_CPR_SUSPEND BIT(3)
+#define USS_CPR_ALT_REF BIT(2)
+#define USS_CPR_REF BIT(1)
+#define USS_CPR_SYS BIT(0)
+#define USS_CPR_MASK GENMASK(6, 0)
+
+/* USS APB slave registers */
+#define USS_USB_CTRL_CFG0 0x10
+#define VCC_RESET_N_MASK BIT(31)
+
+#define USS_USB_PHY_CFG0 0x30
+#define POR_MASK BIT(15)
+#define PHY_RESET_MASK BIT(14)
+#define PHY_REF_USE_PAD_MASK BIT(5)
+
+#define USS_USB_PHY_CFG6 0x64
+#define PHY0_SRAM_EXT_LD_DONE_MASK BIT(23)
+
+#define USS_USB_PARALLEL_IF_CTRL 0xa0
+#define USB_PHY_CR_PARA_SEL_MASK BIT(2)
+
+#define USS_USB_TSET_SIGNALS_AND_GLOB 0xac
+#define USB_PHY_CR_PARA_CLK_EN_MASK BIT(7)
+
+#define USS_USB_STATUS_REG 0xb8
+#define PHY0_SRAM_INIT_DONE_MASK BIT(3)
+
+#define USS_USB_TIEOFFS_CONSTANTS_REG1 0xc0
+#define IDDQ_ENABLE_MASK BIT(10)
+
+struct keembay_usb_phy {
+ struct device *dev;
+ struct regmap *regmap_cpr;
+ struct regmap *regmap_slv;
+};
+
+static const struct regmap_config keembay_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = USS_USB_TIEOFFS_CONSTANTS_REG1,
+};
+
+static int keembay_usb_clocks_on(struct keembay_usb_phy *priv)
+{
+ int ret;
+
+ ret = regmap_update_bits(priv->regmap_cpr, USS_CPR_CLK_SET,
+ USS_CPR_MASK, USS_CPR_MASK);
+ if (ret) {
+ dev_err(priv->dev, "error clock set: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_update_bits(priv->regmap_cpr, USS_CPR_RST_SET,
+ USS_CPR_MASK, USS_CPR_MASK);
+ if (ret) {
+ dev_err(priv->dev, "error reset set: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_update_bits(priv->regmap_slv,
+ USS_USB_TIEOFFS_CONSTANTS_REG1,
+ IDDQ_ENABLE_MASK,
+ FIELD_PREP(IDDQ_ENABLE_MASK, 0));
+ if (ret) {
+ dev_err(priv->dev, "error iddq disable: %d\n", ret);
+ return ret;
+ }
+
+ /* Wait 30us to ensure all analog blocks are powered up. */
+ usleep_range(30, 60);
+
+ ret = regmap_update_bits(priv->regmap_slv, USS_USB_PHY_CFG0,
+ PHY_REF_USE_PAD_MASK,
+ FIELD_PREP(PHY_REF_USE_PAD_MASK, 1));
+ if (ret)
+ dev_err(priv->dev, "error ref clock select: %d\n", ret);
+
+ return ret;
+}
+
+static int keembay_usb_core_off(struct keembay_usb_phy *priv)
+{
+ int ret;
+
+ ret = regmap_update_bits(priv->regmap_slv, USS_USB_CTRL_CFG0,
+ VCC_RESET_N_MASK,
+ FIELD_PREP(VCC_RESET_N_MASK, 0));
+ if (ret)
+ dev_err(priv->dev, "error core reset: %d\n", ret);
+
+ return ret;
+}
+
+static int keembay_usb_core_on(struct keembay_usb_phy *priv)
+{
+ int ret;
+
+ ret = regmap_update_bits(priv->regmap_slv, USS_USB_CTRL_CFG0,
+ VCC_RESET_N_MASK,
+ FIELD_PREP(VCC_RESET_N_MASK, 1));
+ if (ret)
+ dev_err(priv->dev, "error core on: %d\n", ret);
+
+ return ret;
+}
+
+static int keembay_usb_phys_on(struct keembay_usb_phy *priv)
+{
+ int ret;
+
+ ret = regmap_update_bits(priv->regmap_slv, USS_USB_PHY_CFG0,
+ POR_MASK | PHY_RESET_MASK,
+ FIELD_PREP(POR_MASK | PHY_RESET_MASK, 0));
+ if (ret)
+ dev_err(priv->dev, "error phys on: %d\n", ret);
+
+ return ret;
+}
+
+static int keembay_usb_phy_init(struct phy *phy)
+{
+ struct keembay_usb_phy *priv = phy_get_drvdata(phy);
+ u32 val;
+ int ret;
+
+ ret = keembay_usb_core_off(priv);
+ if (ret)
+ return ret;
+
+ /*
+ * According to Keem Bay datasheet, wait minimum 20us after clock
+ * enable before bringing PHYs out of reset.
+ */
+ usleep_range(20, 40);
+
+ ret = keembay_usb_phys_on(priv);
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(priv->regmap_slv,
+ USS_USB_TSET_SIGNALS_AND_GLOB,
+ USB_PHY_CR_PARA_CLK_EN_MASK,
+ FIELD_PREP(USB_PHY_CR_PARA_CLK_EN_MASK, 0));
+ if (ret) {
+ dev_err(priv->dev, "error cr clock disable: %d\n", ret);
+ return ret;
+ }
+
+ /*
+ * According to Keem Bay datasheet, wait 2us after disabling the
+ * clock into the USB 3.x parallel interface.
+ */
+ udelay(2);
+
+ ret = regmap_update_bits(priv->regmap_slv,
+ USS_USB_PARALLEL_IF_CTRL,
+ USB_PHY_CR_PARA_SEL_MASK,
+ FIELD_PREP(USB_PHY_CR_PARA_SEL_MASK, 1));
+ if (ret) {
+ dev_err(priv->dev, "error cr select: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_update_bits(priv->regmap_slv,
+ USS_USB_TSET_SIGNALS_AND_GLOB,
+ USB_PHY_CR_PARA_CLK_EN_MASK,
+ FIELD_PREP(USB_PHY_CR_PARA_CLK_EN_MASK, 1));
+ if (ret) {
+ dev_err(priv->dev, "error cr clock enable: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_read_poll_timeout(priv->regmap_slv, USS_USB_STATUS_REG,
+ val, val & PHY0_SRAM_INIT_DONE_MASK,
+ USEC_PER_MSEC, 10 * USEC_PER_MSEC);
+ if (ret) {
+ dev_err(priv->dev, "SRAM init not done: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_update_bits(priv->regmap_slv, USS_USB_PHY_CFG6,
+ PHY0_SRAM_EXT_LD_DONE_MASK,
+ FIELD_PREP(PHY0_SRAM_EXT_LD_DONE_MASK, 1));
+ if (ret) {
+ dev_err(priv->dev, "error SRAM init done set: %d\n", ret);
+ return ret;
+ }
+
+ /*
+ * According to Keem Bay datasheet, wait 20us after setting the
+ * SRAM load done bit, before releasing the controller reset.
+ */
+ usleep_range(20, 40);
+
+ return keembay_usb_core_on(priv);
+}
+
+static const struct phy_ops ops = {
+ .init = keembay_usb_phy_init,
+ .owner = THIS_MODULE,
+};
+
+static int keembay_usb_phy_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct keembay_usb_phy *priv;
+ struct phy *generic_phy;
+ struct phy_provider *phy_provider;
+ void __iomem *base;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ base = devm_platform_ioremap_resource_byname(pdev, "cpr-apb-base");
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ priv->regmap_cpr = devm_regmap_init_mmio(dev, base,
+ &keembay_regmap_config);
+ if (IS_ERR(priv->regmap_cpr))
+ return PTR_ERR(priv->regmap_cpr);
+
+ base = devm_platform_ioremap_resource_byname(pdev, "slv-apb-base");
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ priv->regmap_slv = devm_regmap_init_mmio(dev, base,
+ &keembay_regmap_config);
+ if (IS_ERR(priv->regmap_slv))
+ return PTR_ERR(priv->regmap_slv);
+
+ generic_phy = devm_phy_create(dev, dev->of_node, &ops);
+ if (IS_ERR(generic_phy))
+ return dev_err_probe(dev, PTR_ERR(generic_phy),
+ "failed to create PHY\n");
+
+ phy_set_drvdata(generic_phy, priv);
+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+ if (IS_ERR(phy_provider))
+ return dev_err_probe(dev, PTR_ERR(phy_provider),
+ "failed to register phy provider\n");
+
+ /* Setup USB subsystem clocks */
+ ret = keembay_usb_clocks_on(priv);
+ if (ret)
+ return ret;
+
+ /* and turn on the DWC3 core, prior to DWC3 driver init. */
+ return keembay_usb_core_on(priv);
+}
+
+static const struct of_device_id keembay_usb_phy_dt_ids[] = {
+ { .compatible = "intel,keembay-usb-phy" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, keembay_usb_phy_dt_ids);
+
+static struct platform_driver keembay_usb_phy_driver = {
+ .probe = keembay_usb_phy_probe,
+ .driver = {
+ .name = "keembay-usb-phy",
+ .of_match_table = keembay_usb_phy_dt_ids,
+ },
+};
+module_platform_driver(keembay_usb_phy_driver);
+
+MODULE_AUTHOR("Wan Ahmad Zainie <wan.ahmad.zainie.wan.mohamad@intel.com>");
+MODULE_DESCRIPTION("Intel Keem Bay USB PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/lantiq/phy-lantiq-vrx200-pcie.c b/drivers/phy/lantiq/phy-lantiq-vrx200-pcie.c
index 22c5698123cf..ef93bf2cba10 100644
--- a/drivers/phy/lantiq/phy-lantiq-vrx200-pcie.c
+++ b/drivers/phy/lantiq/phy-lantiq-vrx200-pcie.c
@@ -402,7 +402,6 @@ static int ltq_vrx200_pcie_phy_probe(struct platform_device *pdev)
struct ltq_vrx200_pcie_phy_priv *priv;
struct device *dev = &pdev->dev;
struct phy_provider *provider;
- struct resource *res;
void __iomem *base;
int ret;
@@ -410,8 +409,7 @@ static int ltq_vrx200_pcie_phy_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(dev, res);
+ base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
diff --git a/drivers/phy/marvell/Kconfig b/drivers/phy/marvell/Kconfig
index 8f6273c837ec..6c96f2bf5266 100644
--- a/drivers/phy/marvell/Kconfig
+++ b/drivers/phy/marvell/Kconfig
@@ -116,3 +116,15 @@ config PHY_MMP3_USB
The PHY driver will be used by Marvell udc/ehci/otg driver.
To compile this driver as a module, choose M here.
+
+config PHY_MMP3_HSIC
+ tristate "Marvell MMP3 USB HSIC PHY Driver"
+ depends on MACH_MMP3_DT || COMPILE_TEST
+ select GENERIC_PHY
+ help
+ Enable this to support Marvell MMP3 USB HSIC PHY driver for
+ Marvell MMP3 SoC. This driver will be used my the Marvell EHCI
+ driver to initialize the interface to internal USB HSIC
+ components on MMP3-based boards.
+
+ To compile this driver as a module, choose M here.
diff --git a/drivers/phy/marvell/Makefile b/drivers/phy/marvell/Makefile
index 5a106b1549f4..7f296ef02829 100644
--- a/drivers/phy/marvell/Makefile
+++ b/drivers/phy/marvell/Makefile
@@ -3,6 +3,7 @@ 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_MMP3_USB) += phy-mmp3-usb.o
+obj-$(CONFIG_PHY_MMP3_HSIC) += phy-mmp3-hsic.o
obj-$(CONFIG_PHY_MVEBU_A3700_COMPHY) += phy-mvebu-a3700-comphy.o
obj-$(CONFIG_PHY_MVEBU_A3700_UTMI) += phy-mvebu-a3700-utmi.o
obj-$(CONFIG_PHY_MVEBU_A38X_COMPHY) += phy-armada38x-comphy.o
diff --git a/drivers/phy/marvell/phy-armada375-usb2.c b/drivers/phy/marvell/phy-armada375-usb2.c
index fa5dc9462d09..b141e3cd8a94 100644
--- a/drivers/phy/marvell/phy-armada375-usb2.c
+++ b/drivers/phy/marvell/phy-armada375-usb2.c
@@ -105,15 +105,13 @@ static int armada375_usb_phy_probe(struct platform_device *pdev)
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);
+ usb_cluster_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(usb_cluster_base))
return PTR_ERR(usb_cluster_base);
diff --git a/drivers/phy/marvell/phy-berlin-usb.c b/drivers/phy/marvell/phy-berlin-usb.c
index a43df63007c5..78ef6ae72a9a 100644
--- a/drivers/phy/marvell/phy-berlin-usb.c
+++ b/drivers/phy/marvell/phy-berlin-usb.c
@@ -165,7 +165,6 @@ 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;
@@ -173,8 +172,7 @@ static int phy_berlin_usb_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->base = devm_ioremap_resource(&pdev->dev, res);
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
diff --git a/drivers/phy/marvell/phy-mmp3-hsic.c b/drivers/phy/marvell/phy-mmp3-hsic.c
new file mode 100644
index 000000000000..47c1e8894939
--- /dev/null
+++ b/drivers/phy/marvell/phy-mmp3-hsic.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2020 Lubomir Rintel <lkundrak@v3.sk>
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+
+#define HSIC_CTRL 0x08
+#define HSIC_ENABLE BIT(7)
+#define PLL_BYPASS BIT(4)
+
+static int mmp3_hsic_phy_init(struct phy *phy)
+{
+ void __iomem *base = (void __iomem *)phy_get_drvdata(phy);
+ u32 hsic_ctrl;
+
+ hsic_ctrl = readl_relaxed(base + HSIC_CTRL);
+ hsic_ctrl |= HSIC_ENABLE;
+ hsic_ctrl |= PLL_BYPASS;
+ writel_relaxed(hsic_ctrl, base + HSIC_CTRL);
+
+ return 0;
+}
+
+static const struct phy_ops mmp3_hsic_phy_ops = {
+ .init = mmp3_hsic_phy_init,
+ .owner = THIS_MODULE,
+};
+
+static const struct of_device_id mmp3_hsic_phy_of_match[] = {
+ { .compatible = "marvell,mmp3-hsic-phy", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, mmp3_hsic_phy_of_match);
+
+static int mmp3_hsic_phy_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct phy_provider *provider;
+ struct resource *resource;
+ void __iomem *base;
+ struct phy *phy;
+
+ resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(dev, resource);
+ if (IS_ERR(base)) {
+ dev_err(dev, "failed to remap PHY regs\n");
+ return PTR_ERR(base);
+ }
+
+ phy = devm_phy_create(dev, NULL, &mmp3_hsic_phy_ops);
+ if (IS_ERR(phy)) {
+ dev_err(dev, "failed to create PHY\n");
+ return PTR_ERR(phy);
+ }
+
+ phy_set_drvdata(phy, (void *)base);
+ 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);
+ }
+
+ return 0;
+}
+
+static struct platform_driver mmp3_hsic_phy_driver = {
+ .probe = mmp3_hsic_phy_probe,
+ .driver = {
+ .name = "mmp3-hsic-phy",
+ .of_match_table = mmp3_hsic_phy_of_match,
+ },
+};
+module_platform_driver(mmp3_hsic_phy_driver);
+
+MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>");
+MODULE_DESCRIPTION("Marvell MMP3 USB HSIC PHY Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/marvell/phy-mmp3-usb.c b/drivers/phy/marvell/phy-mmp3-usb.c
index 499869595a58..04c0bada3519 100644
--- a/drivers/phy/marvell/phy-mmp3-usb.c
+++ b/drivers/phy/marvell/phy-mmp3-usb.c
@@ -246,7 +246,6 @@ MODULE_DEVICE_TABLE(of, mmp3_usb_phy_of_match);
static int mmp3_usb_phy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct resource *resource;
struct mmp3_usb_phy *mmp3_usb_phy;
struct phy_provider *provider;
@@ -254,8 +253,7 @@ static int mmp3_usb_phy_probe(struct platform_device *pdev)
if (!mmp3_usb_phy)
return -ENOMEM;
- resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- mmp3_usb_phy->base = devm_ioremap_resource(dev, resource);
+ mmp3_usb_phy->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(mmp3_usb_phy->base)) {
dev_err(dev, "failed to remap PHY regs\n");
return PTR_ERR(mmp3_usb_phy->base);
diff --git a/drivers/phy/marvell/phy-mvebu-sata.c b/drivers/phy/marvell/phy-mvebu-sata.c
index 3c01b5dceaae..51a4646e2933 100644
--- a/drivers/phy/marvell/phy-mvebu-sata.c
+++ b/drivers/phy/marvell/phy-mvebu-sata.c
@@ -80,7 +80,6 @@ static const struct phy_ops phy_mvebu_sata_ops = {
static int phy_mvebu_sata_probe(struct platform_device *pdev)
{
struct phy_provider *phy_provider;
- struct resource *res;
struct priv *priv;
struct phy *phy;
@@ -88,8 +87,7 @@ static int phy_mvebu_sata_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->base = devm_ioremap_resource(&pdev->dev, res);
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
diff --git a/drivers/phy/marvell/phy-pxa-28nm-hsic.c b/drivers/phy/marvell/phy-pxa-28nm-hsic.c
index 31b43d2ee39a..c5c100563f55 100644
--- a/drivers/phy/marvell/phy-pxa-28nm-hsic.c
+++ b/drivers/phy/marvell/phy-pxa-28nm-hsic.c
@@ -162,7 +162,6 @@ 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)
@@ -176,8 +175,7 @@ static int mv_hsic_phy_probe(struct platform_device *pdev)
return PTR_ERR(mv_phy->clk);
}
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- mv_phy->base = devm_ioremap_resource(&pdev->dev, r);
+ mv_phy->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(mv_phy->base))
return PTR_ERR(mv_phy->base);
diff --git a/drivers/phy/marvell/phy-pxa-28nm-usb2.c b/drivers/phy/marvell/phy-pxa-28nm-usb2.c
index a175ae915f02..0b390b9d2ae1 100644
--- a/drivers/phy/marvell/phy-pxa-28nm-usb2.c
+++ b/drivers/phy/marvell/phy-pxa-28nm-usb2.c
@@ -294,7 +294,6 @@ 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)
@@ -308,8 +307,7 @@ static int mv_usb2_phy_probe(struct platform_device *pdev)
return PTR_ERR(mv_phy->clk);
}
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- mv_phy->base = devm_ioremap_resource(&pdev->dev, r);
+ mv_phy->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(mv_phy->base))
return PTR_ERR(mv_phy->base);
diff --git a/drivers/phy/marvell/phy-pxa-usb.c b/drivers/phy/marvell/phy-pxa-usb.c
index 87ff7550b912..ffe889893ff4 100644
--- a/drivers/phy/marvell/phy-pxa-usb.c
+++ b/drivers/phy/marvell/phy-pxa-usb.c
@@ -286,7 +286,6 @@ MODULE_DEVICE_TABLE(of, pxa_usb_phy_of_match);
static int pxa_usb_phy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct resource *resource;
struct pxa_usb_phy *pxa_usb_phy;
struct phy_provider *provider;
const struct of_device_id *of_id;
@@ -301,8 +300,7 @@ static int pxa_usb_phy_probe(struct platform_device *pdev)
else
pxa_usb_phy->version = PXA_USB_PHY_MMP2;
- resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- pxa_usb_phy->base = devm_ioremap_resource(dev, resource);
+ pxa_usb_phy->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(pxa_usb_phy->base)) {
dev_err(dev, "failed to remap PHY regs\n");
return PTR_ERR(pxa_usb_phy->base);
diff --git a/drivers/phy/mediatek/Kconfig b/drivers/phy/mediatek/Kconfig
index 01f2118633de..d38def43b1bf 100644
--- a/drivers/phy/mediatek/Kconfig
+++ b/drivers/phy/mediatek/Kconfig
@@ -5,7 +5,8 @@
config PHY_MTK_TPHY
tristate "MediaTek T-PHY Driver"
depends on ARCH_MEDIATEK || COMPILE_TEST
- depends on OF
+ depends on OF && OF_ADDRESS
+ depends on HAS_IOMEM
select GENERIC_PHY
help
Say 'Y' here to add support for MediaTek T-PHY driver,
@@ -29,7 +30,8 @@ config PHY_MTK_UFS
config PHY_MTK_XSPHY
tristate "MediaTek XS-PHY Driver"
depends on ARCH_MEDIATEK || COMPILE_TEST
- depends on OF
+ depends on OF && OF_ADDRESS
+ depends on HAS_IOMEM
select GENERIC_PHY
help
Enable this to support the SuperSpeedPlus XS-PHY transceiver for
@@ -38,7 +40,9 @@ config PHY_MTK_XSPHY
config PHY_MTK_HDMI
tristate "MediaTek HDMI-PHY Driver"
- depends on ARCH_MEDIATEK && OF
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+ depends on COMMON_CLK
+ depends on OF
select GENERIC_PHY
help
Support HDMI PHY for Mediatek SoCs.
diff --git a/drivers/phy/mediatek/phy-mtk-hdmi.c b/drivers/phy/mediatek/phy-mtk-hdmi.c
index 47c029d4b270..45be8aa724f3 100644
--- a/drivers/phy/mediatek/phy-mtk-hdmi.c
+++ b/drivers/phy/mediatek/phy-mtk-hdmi.c
@@ -84,8 +84,9 @@ mtk_hdmi_phy_dev_get_ops(const struct mtk_hdmi_phy *hdmi_phy)
hdmi_phy->conf->hdmi_phy_disable_tmds)
return &mtk_hdmi_phy_dev_ops;
- dev_err(hdmi_phy->dev, "Failed to get dev ops of phy\n");
- return NULL;
+ if (hdmi_phy)
+ dev_err(hdmi_phy->dev, "Failed to get dev ops of phy\n");
+ return NULL;
}
static void mtk_hdmi_phy_clk_get_data(struct mtk_hdmi_phy *hdmi_phy,
@@ -201,7 +202,7 @@ static const struct of_device_id mtk_hdmi_phy_match[] = {
{},
};
-struct platform_driver mtk_hdmi_phy_driver = {
+static struct platform_driver mtk_hdmi_phy_driver = {
.probe = mtk_hdmi_phy_probe,
.driver = {
.name = "mediatek-hdmi-phy",
diff --git a/drivers/phy/mediatek/phy-mtk-ufs.c b/drivers/phy/mediatek/phy-mtk-ufs.c
index cf94f5c35dc5..769b00b038d8 100644
--- a/drivers/phy/mediatek/phy-mtk-ufs.c
+++ b/drivers/phy/mediatek/phy-mtk-ufs.c
@@ -195,7 +195,6 @@ static int ufs_mtk_phy_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct phy *generic_phy;
struct phy_provider *phy_provider;
- struct resource *res;
struct ufs_mtk_phy *phy;
int ret;
@@ -203,8 +202,7 @@ static int ufs_mtk_phy_probe(struct platform_device *pdev)
if (!phy)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- phy->mmio = devm_ioremap_resource(dev, res);
+ phy->mmio = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(phy->mmio))
return PTR_ERR(phy->mmio);
diff --git a/drivers/phy/phy-xgene.c b/drivers/phy/phy-xgene.c
index b88922e7de1d..f4cd590fbde7 100644
--- a/drivers/phy/phy-xgene.c
+++ b/drivers/phy/phy-xgene.c
@@ -1644,7 +1644,6 @@ static int xgene_phy_probe(struct platform_device *pdev)
{
struct phy_provider *phy_provider;
struct xgene_phy_ctx *ctx;
- struct resource *res;
u32 default_spd[] = DEFAULT_SATA_SPD_SEL;
u32 default_txboost_gain[] = DEFAULT_SATA_TXBOOST_GAIN;
u32 default_txeye_direction[] = DEFAULT_SATA_TXEYEDIRECTION;
@@ -1661,8 +1660,7 @@ static int xgene_phy_probe(struct platform_device *pdev)
ctx->dev = &pdev->dev;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- ctx->sds_base = devm_ioremap_resource(&pdev->dev, res);
+ ctx->sds_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(ctx->sds_base))
return PTR_ERR(ctx->sds_base);
diff --git a/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c b/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c
index ce91ae7f8dbd..d437a249cd73 100644
--- a/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c
+++ b/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c
@@ -201,7 +201,6 @@ static int qcom_apq8064_sata_phy_probe(struct platform_device *pdev)
{
struct qcom_apq8064_sata_phy *phy;
struct device *dev = &pdev->dev;
- struct resource *res;
struct phy_provider *phy_provider;
struct phy *generic_phy;
int ret;
@@ -210,8 +209,7 @@ static int qcom_apq8064_sata_phy_probe(struct platform_device *pdev)
if (!phy)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- phy->mmio = devm_ioremap_resource(dev, res);
+ phy->mmio = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(phy->mmio))
return PTR_ERR(phy->mmio);
diff --git a/drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c b/drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c
index fc7f9df80a7b..d3e7d5e1d1b6 100644
--- a/drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c
+++ b/drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c
@@ -95,7 +95,6 @@ MODULE_DEVICE_TABLE(of, ipq4019_usb_phy_of_match);
static int ipq4019_usb_phy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct resource *res;
struct phy_provider *phy_provider;
struct ipq4019_usb_phy *phy;
@@ -104,8 +103,7 @@ static int ipq4019_usb_phy_probe(struct platform_device *pdev)
return -ENOMEM;
phy->dev = &pdev->dev;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- phy->base = devm_ioremap_resource(&pdev->dev, res);
+ phy->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(phy->base)) {
dev_err(dev, "failed to remap register memory\n");
return PTR_ERR(phy->base);
diff --git a/drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c b/drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c
index 41a69f56b346..0fc2a1ed39b3 100644
--- a/drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c
+++ b/drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c
@@ -128,7 +128,6 @@ static int qcom_ipq806x_sata_phy_probe(struct platform_device *pdev)
{
struct qcom_ipq806x_sata_phy *phy;
struct device *dev = &pdev->dev;
- struct resource *res;
struct phy_provider *phy_provider;
struct phy *generic_phy;
int ret;
@@ -137,8 +136,7 @@ static int qcom_ipq806x_sata_phy_probe(struct platform_device *pdev)
if (!phy)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- phy->mmio = devm_ioremap_resource(dev, res);
+ phy->mmio = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(phy->mmio))
return PTR_ERR(phy->mmio);
diff --git a/drivers/phy/qualcomm/phy-qcom-pcie2.c b/drivers/phy/qualcomm/phy-qcom-pcie2.c
index 9dba3594e6d9..5407e59bb185 100644
--- a/drivers/phy/qualcomm/phy-qcom-pcie2.c
+++ b/drivers/phy/qualcomm/phy-qcom-pcie2.c
@@ -250,7 +250,6 @@ static int qcom_pcie2_phy_probe(struct platform_device *pdev)
{
struct phy_provider *phy_provider;
struct qcom_phy *qphy;
- struct resource *res;
struct device *dev = &pdev->dev;
struct phy *phy;
int ret;
@@ -260,9 +259,7 @@ static int qcom_pcie2_phy_probe(struct platform_device *pdev)
return -ENOMEM;
qphy->dev = dev;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- qphy->base = devm_ioremap_resource(dev, res);
+ qphy->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(qphy->base))
return PTR_ERR(qphy->base);
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
index 0cda16846962..0939a9e9d448 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -217,6 +217,13 @@ static const unsigned int sdm845_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_PCS_READY_STATUS] = 0x160,
};
+static const unsigned int sm8250_pcie_regs_layout[QPHY_LAYOUT_SIZE] = {
+ [QPHY_SW_RESET] = 0x00,
+ [QPHY_START_CTRL] = 0x44,
+ [QPHY_PCS_STATUS] = 0x14,
+ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40,
+};
+
static const unsigned int sm8150_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_START_CTRL] = QPHY_V4_PCS_UFS_PHY_START,
[QPHY_PCS_READY_STATUS] = QPHY_V4_PCS_UFS_READY_STATUS,
@@ -1824,6 +1831,149 @@ static const struct qmp_phy_init_tbl sm8250_usb3_uniphy_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21),
};
+static const struct qmp_phy_init_tbl sm8250_qmp_pcie_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x34),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x42),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0xb4),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x55),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0x55),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x1a),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x68),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xaa),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x34),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x18),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xa2),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0x4c),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_ENABLE1, 0x90),
+};
+
+static const struct qmp_phy_init_tbl sm8250_qmp_gen3x1_pcie_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x07),
+};
+
+static const struct qmp_phy_init_tbl sm8250_qmp_pcie_tx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12),
+ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0x35),
+ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x11),
+};
+
+static const struct qmp_phy_init_tbl sm8250_qmp_pcie_rx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0c),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1b),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0x30),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x70),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0e),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_ENABLES, 0x1c),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x1e),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_LOW, 0xd4),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH, 0x54),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH2, 0xdb),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH3, 0x3b),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH4, 0x31),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0x24),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xe4),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xec),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x3b),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0x36),
+};
+
+static const struct qmp_phy_init_tbl sm8250_qmp_gen3x1_pcie_rx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RCLK_AUXDATA_SEL, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x30),
+};
+
+static const struct qmp_phy_init_tbl sm8250_qmp_pcie_pcs_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0x77),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RATE_SLEW_CNTRL1, 0x0b),
+};
+
+static const struct qmp_phy_init_tbl sm8250_qmp_gen3x1_pcie_pcs_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x0d),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x12),
+};
+
+static const struct qmp_phy_init_tbl sm8250_qmp_pcie_pcs_misc_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P6_P7_PRE, 0x33),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_PRE, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_POST, 0x58),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1),
+};
+
+static const struct qmp_phy_init_tbl sm8250_qmp_gen3x1_pcie_pcs_misc_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_INT_AUX_CLK_CONFIG1, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_EQ_CONFIG2, 0x0f),
+};
+
+static const struct qmp_phy_init_tbl sm8250_qmp_gen3x2_pcie_tx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x20),
+};
+
+static const struct qmp_phy_init_tbl sm8250_qmp_gen3x2_pcie_rx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0xbf),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x15),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38),
+};
+
+static const struct qmp_phy_init_tbl sm8250_qmp_gen3x2_pcie_pcs_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x05),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG2, 0x0f),
+};
+
+static const struct qmp_phy_init_tbl sm8250_qmp_gen3x2_pcie_pcs_misc_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG2, 0x0d),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG4, 0x07),
+};
+
/* struct qmp_phy_cfg - per-PHY initialization config */
struct qmp_phy_cfg {
/* phy-type - PCIE/UFS/USB */
@@ -1834,14 +1984,24 @@ struct qmp_phy_cfg {
/* Init sequence for PHY blocks - serdes, tx, rx, pcs */
const struct qmp_phy_init_tbl *serdes_tbl;
int serdes_tbl_num;
+ const struct qmp_phy_init_tbl *serdes_tbl_sec;
+ int serdes_tbl_num_sec;
const struct qmp_phy_init_tbl *tx_tbl;
int tx_tbl_num;
+ const struct qmp_phy_init_tbl *tx_tbl_sec;
+ int tx_tbl_num_sec;
const struct qmp_phy_init_tbl *rx_tbl;
int rx_tbl_num;
+ const struct qmp_phy_init_tbl *rx_tbl_sec;
+ int rx_tbl_num_sec;
const struct qmp_phy_init_tbl *pcs_tbl;
int pcs_tbl_num;
+ const struct qmp_phy_init_tbl *pcs_tbl_sec;
+ int pcs_tbl_num_sec;
const struct qmp_phy_init_tbl *pcs_misc_tbl;
int pcs_misc_tbl_num;
+ const struct qmp_phy_init_tbl *pcs_misc_tbl_sec;
+ int pcs_misc_tbl_num_sec;
/* Init sequence for DP PHY block link rates */
const struct qmp_phy_init_tbl *serdes_tbl_rbr;
@@ -2245,6 +2405,83 @@ static const struct qmp_phy_cfg sdm845_qhp_pciephy_cfg = {
.pwrdn_delay_max = 1005, /* us */
};
+static const struct qmp_phy_cfg sm8250_qmp_gen3x1_pciephy_cfg = {
+ .type = PHY_TYPE_PCIE,
+ .nlanes = 1,
+
+ .serdes_tbl = sm8250_qmp_pcie_serdes_tbl,
+ .serdes_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_serdes_tbl),
+ .serdes_tbl_sec = sm8250_qmp_gen3x1_pcie_serdes_tbl,
+ .serdes_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_serdes_tbl),
+ .tx_tbl = sm8250_qmp_pcie_tx_tbl,
+ .tx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_tx_tbl),
+ .rx_tbl = sm8250_qmp_pcie_rx_tbl,
+ .rx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_rx_tbl),
+ .rx_tbl_sec = sm8250_qmp_gen3x1_pcie_rx_tbl,
+ .rx_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_rx_tbl),
+ .pcs_tbl = sm8250_qmp_pcie_pcs_tbl,
+ .pcs_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_tbl),
+ .pcs_tbl_sec = sm8250_qmp_gen3x1_pcie_pcs_tbl,
+ .pcs_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_pcs_tbl),
+ .pcs_misc_tbl = sm8250_qmp_pcie_pcs_misc_tbl,
+ .pcs_misc_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_misc_tbl),
+ .pcs_misc_tbl_sec = sm8250_qmp_gen3x1_pcie_pcs_misc_tbl,
+ .pcs_misc_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_pcs_misc_tbl),
+ .clk_list = sdm845_pciephy_clk_l,
+ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l),
+ .reset_list = sdm845_pciephy_reset_l,
+ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
+ .vreg_list = qmp_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
+ .regs = sm8250_pcie_regs_layout,
+
+ .start_ctrl = PCS_START | SERDES_START,
+ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
+
+ .has_pwrdn_delay = true,
+ .pwrdn_delay_min = 995, /* us */
+ .pwrdn_delay_max = 1005, /* us */
+};
+
+static const struct qmp_phy_cfg sm8250_qmp_gen3x2_pciephy_cfg = {
+ .type = PHY_TYPE_PCIE,
+ .nlanes = 2,
+
+ .serdes_tbl = sm8250_qmp_pcie_serdes_tbl,
+ .serdes_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_serdes_tbl),
+ .tx_tbl = sm8250_qmp_pcie_tx_tbl,
+ .tx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_tx_tbl),
+ .tx_tbl_sec = sm8250_qmp_gen3x2_pcie_tx_tbl,
+ .tx_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_tx_tbl),
+ .rx_tbl = sm8250_qmp_pcie_rx_tbl,
+ .rx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_rx_tbl),
+ .rx_tbl_sec = sm8250_qmp_gen3x2_pcie_rx_tbl,
+ .rx_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_rx_tbl),
+ .pcs_tbl = sm8250_qmp_pcie_pcs_tbl,
+ .pcs_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_tbl),
+ .pcs_tbl_sec = sm8250_qmp_gen3x2_pcie_pcs_tbl,
+ .pcs_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_pcs_tbl),
+ .pcs_misc_tbl = sm8250_qmp_pcie_pcs_misc_tbl,
+ .pcs_misc_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_misc_tbl),
+ .pcs_misc_tbl_sec = sm8250_qmp_gen3x2_pcie_pcs_misc_tbl,
+ .pcs_misc_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_pcs_misc_tbl),
+ .clk_list = sdm845_pciephy_clk_l,
+ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l),
+ .reset_list = sdm845_pciephy_reset_l,
+ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
+ .vreg_list = qmp_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
+ .regs = sm8250_pcie_regs_layout,
+
+ .start_ctrl = PCS_START | SERDES_START,
+ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
+
+ .is_dual_lane_phy = true,
+ .has_pwrdn_delay = true,
+ .pwrdn_delay_min = 995, /* us */
+ .pwrdn_delay_max = 1005, /* us */
+};
+
static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = {
.type = PHY_TYPE_USB3,
.nlanes = 1,
@@ -2629,6 +2866,9 @@ static int qcom_qmp_phy_serdes_init(struct qmp_phy *qphy)
int ret;
qcom_qmp_phy_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num);
+ if (cfg->serdes_tbl_sec)
+ qcom_qmp_phy_configure(serdes, cfg->regs, cfg->serdes_tbl_sec,
+ cfg->serdes_tbl_num_sec);
if (cfg->type == PHY_TYPE_DP) {
switch (dp_opts->link_rate) {
@@ -3117,10 +3357,19 @@ static int qcom_qmp_phy_power_on(struct phy *phy)
/* Tx, Rx, and PCS configurations */
qcom_qmp_phy_configure_lane(tx, cfg->regs,
cfg->tx_tbl, cfg->tx_tbl_num, 1);
+ if (cfg->tx_tbl_sec)
+ qcom_qmp_phy_configure_lane(tx, cfg->regs, cfg->tx_tbl_sec,
+ cfg->tx_tbl_num_sec, 1);
+
/* Configuration for other LANE for USB-DP combo PHY */
- if (cfg->is_dual_lane_phy)
+ if (cfg->is_dual_lane_phy) {
qcom_qmp_phy_configure_lane(qphy->tx2, cfg->regs,
cfg->tx_tbl, cfg->tx_tbl_num, 2);
+ if (cfg->tx_tbl_sec)
+ qcom_qmp_phy_configure_lane(qphy->tx2, cfg->regs,
+ cfg->tx_tbl_sec,
+ cfg->tx_tbl_num_sec, 2);
+ }
/* Configure special DP tx tunings */
if (cfg->type == PHY_TYPE_DP)
@@ -3128,16 +3377,28 @@ static int qcom_qmp_phy_power_on(struct phy *phy)
qcom_qmp_phy_configure_lane(rx, cfg->regs,
cfg->rx_tbl, cfg->rx_tbl_num, 1);
+ if (cfg->rx_tbl_sec)
+ qcom_qmp_phy_configure_lane(rx, cfg->regs,
+ cfg->rx_tbl_sec, cfg->rx_tbl_num_sec, 1);
- if (cfg->is_dual_lane_phy)
+ if (cfg->is_dual_lane_phy) {
qcom_qmp_phy_configure_lane(qphy->rx2, cfg->regs,
cfg->rx_tbl, cfg->rx_tbl_num, 2);
+ if (cfg->rx_tbl_sec)
+ qcom_qmp_phy_configure_lane(qphy->rx2, cfg->regs,
+ cfg->rx_tbl_sec,
+ cfg->rx_tbl_num_sec, 2);
+ }
/* Configure link rate, swing, etc. */
- if (cfg->type == PHY_TYPE_DP)
+ if (cfg->type == PHY_TYPE_DP) {
qcom_qmp_phy_configure_dp_phy(qphy);
- else
+ } else {
qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num);
+ if (cfg->pcs_tbl_sec)
+ qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl_sec,
+ cfg->pcs_tbl_num_sec);
+ }
ret = reset_control_deassert(qmp->ufs_reset);
if (ret)
@@ -3145,6 +3406,9 @@ static int qcom_qmp_phy_power_on(struct phy *phy)
qcom_qmp_phy_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl,
cfg->pcs_misc_tbl_num);
+ if (cfg->pcs_misc_tbl_sec)
+ qcom_qmp_phy_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl_sec,
+ cfg->pcs_misc_tbl_num_sec);
/*
* Pull out PHY from POWER DOWN state.
@@ -3900,6 +4164,15 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = {
}, {
.compatible = "qcom,sm8250-qmp-usb3-uni-phy",
.data = &sm8250_usb3_uniphy_cfg,
+ }, {
+ .compatible = "qcom,sm8250-qmp-gen3x1-pcie-phy",
+ .data = &sm8250_qmp_gen3x1_pciephy_cfg,
+ }, {
+ .compatible = "qcom,sm8250-qmp-gen3x2-pcie-phy",
+ .data = &sm8250_qmp_gen3x2_pciephy_cfg,
+ }, {
+ .compatible = "qcom,sm8250-qmp-modem-pcie-phy",
+ .data = &sm8250_qmp_gen3x2_pciephy_cfg,
},
{ },
};
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h
index b7c530088a6c..db92a461dd2e 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.h
@@ -403,6 +403,7 @@
#define QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0 0x028
#define QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1 0x030
#define QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1 0x034
+#define QSERDES_V4_COM_CLK_ENABLE1 0x048
#define QSERDES_V4_COM_SYSCLK_BUF_ENABLE 0x050
#define QSERDES_V4_COM_PLL_IVCO 0x058
#define QSERDES_V4_COM_CMN_IPTRIM 0x060
@@ -432,6 +433,7 @@
#define QSERDES_V4_COM_VCO_TUNE1_MODE1 0x118
#define QSERDES_V4_COM_VCO_TUNE2_MODE1 0x11c
#define QSERDES_V4_COM_VCO_TUNE_INITVAL2 0x124
+#define QSERDES_V4_COM_CLK_SELECT 0x154
#define QSERDES_V4_COM_HSCLK_SEL 0x158
#define QSERDES_V4_COM_HSCLK_HS_SWITCH_SEL 0x15c
#define QSERDES_V4_COM_CORECLK_DIV_MODE1 0x16c
@@ -471,12 +473,14 @@
#define QSERDES_V4_RX_UCDR_SB2_GAIN1 0x054
#define QSERDES_V4_RX_UCDR_SB2_GAIN2 0x058
#define QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE 0x060
+#define QSERDES_V4_RX_RCLK_AUXDATA_SEL 0x064
#define QSERDES_V4_RX_AC_JTAG_ENABLE 0x068
#define QSERDES_V4_RX_AC_JTAG_MODE 0x078
#define QSERDES_V4_RX_RX_TERM_BW 0x080
#define QSERDES_V4_RX_VGA_CAL_CNTRL1 0x0d4
#define QSERDES_V4_RX_VGA_CAL_CNTRL2 0x0d8
#define QSERDES_V4_RX_GM_CAL 0x0dc
+#define QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL1 0x0e8
#define QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2 0x0ec
#define QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3 0x0f0
#define QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4 0x0f4
@@ -485,6 +489,7 @@
#define QSERDES_V4_RX_RX_IDAC_MEASURE_TIME 0x100
#define QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x110
#define QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2 0x114
+#define QSERDES_V4_RX_SIGDET_ENABLES 0x118
#define QSERDES_V4_RX_SIGDET_CNTRL 0x11c
#define QSERDES_V4_RX_SIGDET_LVL 0x120
#define QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL 0x124
@@ -806,4 +811,17 @@
#define QPHY_V4_PCS_MISC_TYPEC_STATUS 0x10
#define QPHY_V4_PCS_MISC_PLACEHOLDER_STATUS 0x14
+/* Only for QMP V4 PHY - PCS_PCIE registers (same as PCS_MISC?) */
+#define QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG2 0x0c
+#define QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG4 0x14
+#define QPHY_V4_PCS_PCIE_ENDPOINT_REFCLK_DRIVE 0x1c
+#define QPHY_V4_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L 0x40
+#define QPHY_V4_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L 0x48
+#define QPHY_V4_PCS_PCIE_INT_AUX_CLK_CONFIG1 0x50
+#define QPHY_V4_PCS_PCIE_OSC_DTCT_ACTIONS 0x90
+#define QPHY_V4_PCS_PCIE_EQ_CONFIG2 0xa4
+#define QPHY_V4_PCS_PCIE_PRESET_P6_P7_PRE 0xb4
+#define QPHY_V4_PCS_PCIE_PRESET_P10_PRE 0xbc
+#define QPHY_V4_PCS_PCIE_PRESET_P10_POST 0xe0
+
#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c
index 557547dabfd5..109792203baf 100644
--- a/drivers/phy/qualcomm/phy-qcom-qusb2.c
+++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c
@@ -844,7 +844,6 @@ static int qusb2_phy_probe(struct platform_device *pdev)
struct qusb2_phy *qphy;
struct phy_provider *phy_provider;
struct phy *generic_phy;
- struct resource *res;
int ret, i;
int num;
u32 value;
@@ -855,8 +854,7 @@ static int qusb2_phy_probe(struct platform_device *pdev)
return -ENOMEM;
or = &qphy->overrides;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- qphy->base = devm_ioremap_resource(dev, res);
+ qphy->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(qphy->base))
return PTR_ERR(qphy->base);
diff --git a/drivers/phy/ralink/Kconfig b/drivers/phy/ralink/Kconfig
index da982c9cffb3..ecc309ba9fee 100644
--- a/drivers/phy/ralink/Kconfig
+++ b/drivers/phy/ralink/Kconfig
@@ -2,6 +2,14 @@
#
# PHY drivers for Ralink platforms.
#
+config PHY_MT7621_PCI
+ tristate "MediaTek MT7621 PCI PHY Driver"
+ depends on RALINK && OF
+ select GENERIC_PHY
+ select REGMAP_MMIO
+ help
+ Say 'Y' here to add support for MediaTek MT7621 PCI PHY driver,
+
config PHY_RALINK_USB
tristate "Ralink USB PHY driver"
depends on RALINK || COMPILE_TEST
diff --git a/drivers/phy/ralink/Makefile b/drivers/phy/ralink/Makefile
index d8d3ffcf0a15..cda2a4a7ca5e 100644
--- a/drivers/phy/ralink/Makefile
+++ b/drivers/phy/ralink/Makefile
@@ -1,2 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_PHY_MT7621_PCI) += phy-mt7621-pci.o
obj-$(CONFIG_PHY_RALINK_USB) += phy-ralink-usb.o
diff --git a/drivers/phy/ralink/phy-mt7621-pci.c b/drivers/phy/ralink/phy-mt7621-pci.c
new file mode 100644
index 000000000000..9a610b414b1f
--- /dev/null
+++ b/drivers/phy/ralink/phy-mt7621-pci.c
@@ -0,0 +1,352 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Mediatek MT7621 PCI PHY Driver
+ * Author: Sergio Paracuellos <sergio.paracuellos@gmail.com>
+ */
+
+#include <dt-bindings/phy/phy.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/sys_soc.h>
+#include <mt7621.h>
+#include <ralink_regs.h>
+
+#define RG_PE1_PIPE_REG 0x02c
+#define RG_PE1_PIPE_RST BIT(12)
+#define RG_PE1_PIPE_CMD_FRC BIT(4)
+
+#define RG_P0_TO_P1_WIDTH 0x100
+#define RG_PE1_H_LCDDS_REG 0x49c
+#define RG_PE1_H_LCDDS_PCW GENMASK(30, 0)
+
+#define RG_PE1_FRC_H_XTAL_REG 0x400
+#define RG_PE1_FRC_H_XTAL_TYPE BIT(8)
+#define RG_PE1_H_XTAL_TYPE GENMASK(10, 9)
+
+#define RG_PE1_FRC_PHY_REG 0x000
+#define RG_PE1_FRC_PHY_EN BIT(4)
+#define RG_PE1_PHY_EN BIT(5)
+
+#define RG_PE1_H_PLL_REG 0x490
+#define RG_PE1_H_PLL_BC GENMASK(23, 22)
+#define RG_PE1_H_PLL_BP GENMASK(21, 18)
+#define RG_PE1_H_PLL_IR GENMASK(15, 12)
+#define RG_PE1_H_PLL_IC GENMASK(11, 8)
+#define RG_PE1_H_PLL_PREDIV GENMASK(7, 6)
+#define RG_PE1_PLL_DIVEN GENMASK(3, 1)
+
+#define RG_PE1_H_PLL_FBKSEL_REG 0x4bc
+#define RG_PE1_H_PLL_FBKSEL GENMASK(5, 4)
+
+#define RG_PE1_H_LCDDS_SSC_PRD_REG 0x4a4
+#define RG_PE1_H_LCDDS_SSC_PRD GENMASK(15, 0)
+
+#define RG_PE1_H_LCDDS_SSC_DELTA_REG 0x4a8
+#define RG_PE1_H_LCDDS_SSC_DELTA GENMASK(11, 0)
+#define RG_PE1_H_LCDDS_SSC_DELTA1 GENMASK(27, 16)
+
+#define RG_PE1_LCDDS_CLK_PH_INV_REG 0x4a0
+#define RG_PE1_LCDDS_CLK_PH_INV BIT(5)
+
+#define RG_PE1_H_PLL_BR_REG 0x4ac
+#define RG_PE1_H_PLL_BR GENMASK(18, 16)
+
+#define RG_PE1_MSTCKDIV_REG 0x414
+#define RG_PE1_MSTCKDIV GENMASK(7, 6)
+
+#define RG_PE1_FRC_MSTCKDIV BIT(5)
+
+#define XTAL_MASK GENMASK(7, 6)
+
+#define MAX_PHYS 2
+
+/**
+ * struct mt7621_pci_phy - Mt7621 Pcie PHY core
+ * @dev: pointer to device
+ * @regmap: kernel regmap pointer
+ * @phy: pointer to the kernel PHY device
+ * @port_base: base register
+ * @has_dual_port: if the phy has dual ports.
+ * @bypass_pipe_rst: mark if 'mt7621_bypass_pipe_rst'
+ * needs to be executed. Depends on chip revision.
+ */
+struct mt7621_pci_phy {
+ struct device *dev;
+ struct regmap *regmap;
+ struct phy *phy;
+ void __iomem *port_base;
+ bool has_dual_port;
+ bool bypass_pipe_rst;
+};
+
+static inline void mt7621_phy_rmw(struct mt7621_pci_phy *phy,
+ u32 reg, u32 clr, u32 set)
+{
+ u32 val;
+
+ /*
+ * We cannot use 'regmap_write_bits' here because internally
+ * 'set' is masked before is set to the value that will be
+ * written to the register. That way results in no reliable
+ * pci setup. Avoid to mask 'set' before set value to 'val'
+ * completely avoid the problem.
+ */
+ regmap_read(phy->regmap, reg, &val);
+ val &= ~clr;
+ val |= set;
+ regmap_write(phy->regmap, reg, val);
+}
+
+static void mt7621_bypass_pipe_rst(struct mt7621_pci_phy *phy)
+{
+ mt7621_phy_rmw(phy, RG_PE1_PIPE_REG, 0, RG_PE1_PIPE_RST);
+ mt7621_phy_rmw(phy, RG_PE1_PIPE_REG, 0, RG_PE1_PIPE_CMD_FRC);
+
+ if (phy->has_dual_port) {
+ mt7621_phy_rmw(phy, RG_PE1_PIPE_REG + RG_P0_TO_P1_WIDTH,
+ 0, RG_PE1_PIPE_RST);
+ mt7621_phy_rmw(phy, RG_PE1_PIPE_REG + RG_P0_TO_P1_WIDTH,
+ 0, RG_PE1_PIPE_CMD_FRC);
+ }
+}
+
+static void mt7621_set_phy_for_ssc(struct mt7621_pci_phy *phy)
+{
+ struct device *dev = phy->dev;
+ u32 xtal_mode;
+
+ xtal_mode = FIELD_GET(XTAL_MASK, rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG0));
+
+ /* Set PCIe Port PHY to disable SSC */
+ /* Debug Xtal Type */
+ mt7621_phy_rmw(phy, RG_PE1_FRC_H_XTAL_REG,
+ RG_PE1_FRC_H_XTAL_TYPE | RG_PE1_H_XTAL_TYPE,
+ RG_PE1_FRC_H_XTAL_TYPE |
+ FIELD_PREP(RG_PE1_H_XTAL_TYPE, 0x00));
+
+ /* disable port */
+ mt7621_phy_rmw(phy, RG_PE1_FRC_PHY_REG, RG_PE1_PHY_EN,
+ RG_PE1_FRC_PHY_EN);
+
+ if (phy->has_dual_port) {
+ mt7621_phy_rmw(phy, RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH,
+ RG_PE1_PHY_EN, RG_PE1_FRC_PHY_EN);
+ }
+
+ if (xtal_mode <= 5 && xtal_mode >= 3) { /* 40MHz Xtal */
+ /* Set Pre-divider ratio (for host mode) */
+ mt7621_phy_rmw(phy, RG_PE1_H_PLL_REG, RG_PE1_H_PLL_PREDIV,
+ FIELD_PREP(RG_PE1_H_PLL_PREDIV, 0x01));
+
+ dev_dbg(dev, "Xtal is 40MHz\n");
+ } else if (xtal_mode >= 6) { /* 25MHz Xal */
+ mt7621_phy_rmw(phy, RG_PE1_H_PLL_REG, RG_PE1_H_PLL_PREDIV,
+ FIELD_PREP(RG_PE1_H_PLL_PREDIV, 0x00));
+
+ /* Select feedback clock */
+ mt7621_phy_rmw(phy, RG_PE1_H_PLL_FBKSEL_REG,
+ RG_PE1_H_PLL_FBKSEL,
+ FIELD_PREP(RG_PE1_H_PLL_FBKSEL, 0x01));
+
+ /* DDS NCPO PCW (for host mode) */
+ mt7621_phy_rmw(phy, RG_PE1_H_LCDDS_SSC_PRD_REG,
+ RG_PE1_H_LCDDS_SSC_PRD,
+ FIELD_PREP(RG_PE1_H_LCDDS_SSC_PRD, 0x00));
+
+ /* DDS SSC dither period control */
+ mt7621_phy_rmw(phy, RG_PE1_H_LCDDS_SSC_PRD_REG,
+ RG_PE1_H_LCDDS_SSC_PRD,
+ FIELD_PREP(RG_PE1_H_LCDDS_SSC_PRD, 0x18d));
+
+ /* DDS SSC dither amplitude control */
+ mt7621_phy_rmw(phy, RG_PE1_H_LCDDS_SSC_DELTA_REG,
+ RG_PE1_H_LCDDS_SSC_DELTA |
+ RG_PE1_H_LCDDS_SSC_DELTA1,
+ FIELD_PREP(RG_PE1_H_LCDDS_SSC_DELTA, 0x4a) |
+ FIELD_PREP(RG_PE1_H_LCDDS_SSC_DELTA1, 0x4a));
+
+ dev_dbg(dev, "Xtal is 25MHz\n");
+ } else { /* 20MHz Xtal */
+ mt7621_phy_rmw(phy, RG_PE1_H_PLL_REG, RG_PE1_H_PLL_PREDIV,
+ FIELD_PREP(RG_PE1_H_PLL_PREDIV, 0x00));
+
+ dev_dbg(dev, "Xtal is 20MHz\n");
+ }
+
+ /* DDS clock inversion */
+ mt7621_phy_rmw(phy, RG_PE1_LCDDS_CLK_PH_INV_REG,
+ RG_PE1_LCDDS_CLK_PH_INV, RG_PE1_LCDDS_CLK_PH_INV);
+
+ /* Set PLL bits */
+ mt7621_phy_rmw(phy, RG_PE1_H_PLL_REG,
+ RG_PE1_H_PLL_BC | RG_PE1_H_PLL_BP | RG_PE1_H_PLL_IR |
+ RG_PE1_H_PLL_IC | RG_PE1_PLL_DIVEN,
+ FIELD_PREP(RG_PE1_H_PLL_BC, 0x02) |
+ FIELD_PREP(RG_PE1_H_PLL_BP, 0x06) |
+ FIELD_PREP(RG_PE1_H_PLL_IR, 0x02) |
+ FIELD_PREP(RG_PE1_H_PLL_IC, 0x01) |
+ FIELD_PREP(RG_PE1_PLL_DIVEN, 0x02));
+
+ mt7621_phy_rmw(phy, RG_PE1_H_PLL_BR_REG, RG_PE1_H_PLL_BR,
+ FIELD_PREP(RG_PE1_H_PLL_BR, 0x00));
+
+ if (xtal_mode <= 5 && xtal_mode >= 3) { /* 40MHz Xtal */
+ /* set force mode enable of da_pe1_mstckdiv */
+ mt7621_phy_rmw(phy, RG_PE1_MSTCKDIV_REG,
+ RG_PE1_MSTCKDIV | RG_PE1_FRC_MSTCKDIV,
+ FIELD_PREP(RG_PE1_MSTCKDIV, 0x01) |
+ RG_PE1_FRC_MSTCKDIV);
+ }
+}
+
+static int mt7621_pci_phy_init(struct phy *phy)
+{
+ struct mt7621_pci_phy *mphy = phy_get_drvdata(phy);
+
+ if (mphy->bypass_pipe_rst)
+ mt7621_bypass_pipe_rst(mphy);
+
+ mt7621_set_phy_for_ssc(mphy);
+
+ return 0;
+}
+
+static int mt7621_pci_phy_power_on(struct phy *phy)
+{
+ struct mt7621_pci_phy *mphy = phy_get_drvdata(phy);
+
+ /* Enable PHY and disable force mode */
+ mt7621_phy_rmw(mphy, RG_PE1_FRC_PHY_REG,
+ RG_PE1_FRC_PHY_EN, RG_PE1_PHY_EN);
+
+ if (mphy->has_dual_port) {
+ mt7621_phy_rmw(mphy, RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH,
+ RG_PE1_FRC_PHY_EN, RG_PE1_PHY_EN);
+ }
+
+ return 0;
+}
+
+static int mt7621_pci_phy_power_off(struct phy *phy)
+{
+ struct mt7621_pci_phy *mphy = phy_get_drvdata(phy);
+
+ /* Disable PHY */
+ mt7621_phy_rmw(mphy, RG_PE1_FRC_PHY_REG,
+ RG_PE1_PHY_EN, RG_PE1_FRC_PHY_EN);
+
+ if (mphy->has_dual_port) {
+ mt7621_phy_rmw(mphy, RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH,
+ RG_PE1_PHY_EN, RG_PE1_FRC_PHY_EN);
+ }
+
+ return 0;
+}
+
+static int mt7621_pci_phy_exit(struct phy *phy)
+{
+ return 0;
+}
+
+static const struct phy_ops mt7621_pci_phy_ops = {
+ .init = mt7621_pci_phy_init,
+ .exit = mt7621_pci_phy_exit,
+ .power_on = mt7621_pci_phy_power_on,
+ .power_off = mt7621_pci_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+static struct phy *mt7621_pcie_phy_of_xlate(struct device *dev,
+ struct of_phandle_args *args)
+{
+ struct mt7621_pci_phy *mt7621_phy = dev_get_drvdata(dev);
+
+ if (WARN_ON(args->args[0] >= MAX_PHYS))
+ return ERR_PTR(-ENODEV);
+
+ mt7621_phy->has_dual_port = args->args[0];
+
+ dev_info(dev, "PHY for 0x%08x (dual port = %d)\n",
+ (unsigned int)mt7621_phy->port_base, mt7621_phy->has_dual_port);
+
+ return mt7621_phy->phy;
+}
+
+static const struct soc_device_attribute mt7621_pci_quirks_match[] = {
+ { .soc_id = "mt7621", .revision = "E2" }
+};
+
+static const struct regmap_config mt7621_pci_phy_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = 0x700,
+};
+
+static int mt7621_pci_phy_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ const struct soc_device_attribute *attr;
+ struct phy_provider *provider;
+ struct mt7621_pci_phy *phy;
+
+ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+ if (!phy)
+ return -ENOMEM;
+
+ attr = soc_device_match(mt7621_pci_quirks_match);
+ if (attr)
+ phy->bypass_pipe_rst = true;
+
+ phy->dev = dev;
+ platform_set_drvdata(pdev, phy);
+
+ phy->port_base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(phy->port_base)) {
+ dev_err(dev, "failed to remap phy regs\n");
+ return PTR_ERR(phy->port_base);
+ }
+
+ phy->regmap = devm_regmap_init_mmio(phy->dev, phy->port_base,
+ &mt7621_pci_phy_regmap_config);
+ if (IS_ERR(phy->regmap))
+ return PTR_ERR(phy->regmap);
+
+ phy->phy = devm_phy_create(dev, dev->of_node, &mt7621_pci_phy_ops);
+ if (IS_ERR(phy)) {
+ dev_err(dev, "failed to create phy\n");
+ return PTR_ERR(phy);
+ }
+
+ phy_set_drvdata(phy->phy, phy);
+
+ provider = devm_of_phy_provider_register(dev, mt7621_pcie_phy_of_xlate);
+
+ return PTR_ERR_OR_ZERO(provider);
+}
+
+static const struct of_device_id mt7621_pci_phy_ids[] = {
+ { .compatible = "mediatek,mt7621-pci-phy" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mt7621_pci_phy_ids);
+
+static struct platform_driver mt7621_pci_phy_driver = {
+ .probe = mt7621_pci_phy_probe,
+ .driver = {
+ .name = "mt7621-pci-phy",
+ .of_match_table = of_match_ptr(mt7621_pci_phy_ids),
+ },
+};
+
+builtin_platform_driver(mt7621_pci_phy_driver);
+
+MODULE_AUTHOR("Sergio Paracuellos <sergio.paracuellos@gmail.com>");
+MODULE_DESCRIPTION("MediaTek MT7621 PCIe PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/ralink/phy-ralink-usb.c b/drivers/phy/ralink/phy-ralink-usb.c
index 95dfa9fd284d..2bd8ad2e76ed 100644
--- a/drivers/phy/ralink/phy-ralink-usb.c
+++ b/drivers/phy/ralink/phy-ralink-usb.c
@@ -170,7 +170,6 @@ MODULE_DEVICE_TABLE(of, ralink_usb_phy_of_match);
static int ralink_usb_phy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct resource *res;
struct phy_provider *phy_provider;
const struct of_device_id *match;
struct ralink_usb_phy *phy;
@@ -194,8 +193,7 @@ static int ralink_usb_phy_probe(struct platform_device *pdev)
/* The MT7628 and MT7688 require extra setup of PHY registers. */
if (of_device_is_compatible(dev->of_node, "mediatek,mt7628-usbphy")) {
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- phy->base = devm_ioremap_resource(&pdev->dev, res);
+ phy->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(phy->base)) {
dev_err(dev, "failed to remap register memory\n");
return PTR_ERR(phy->base);
diff --git a/drivers/phy/renesas/phy-rcar-gen2.c b/drivers/phy/renesas/phy-rcar-gen2.c
index 2e279ac0fa4d..c375a4676a3d 100644
--- a/drivers/phy/renesas/phy-rcar-gen2.c
+++ b/drivers/phy/renesas/phy-rcar-gen2.c
@@ -339,7 +339,6 @@ static int rcar_gen2_phy_probe(struct platform_device *pdev)
struct rcar_gen2_phy_driver *drv;
struct phy_provider *provider;
struct device_node *np;
- struct resource *res;
void __iomem *base;
struct clk *clk;
const struct rcar_gen2_phy_data *data;
@@ -357,8 +356,7 @@ static int rcar_gen2_phy_probe(struct platform_device *pdev)
return PTR_ERR(clk);
}
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(dev, res);
+ base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
diff --git a/drivers/phy/renesas/phy-rcar-gen3-pcie.c b/drivers/phy/renesas/phy-rcar-gen3-pcie.c
index c4e4aa216936..4dc721eb9577 100644
--- a/drivers/phy/renesas/phy-rcar-gen3-pcie.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-pcie.c
@@ -76,7 +76,6 @@ static int rcar_gen3_phy_pcie_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct phy_provider *provider;
struct rcar_gen3_phy *phy;
- struct resource *res;
void __iomem *base;
int error;
@@ -86,8 +85,7 @@ static int rcar_gen3_phy_pcie_probe(struct platform_device *pdev)
return -EINVAL;
}
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(dev, res);
+ base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
index e34e4475027c..fbc55232120e 100644
--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
@@ -611,7 +611,6 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct rcar_gen3_chan *channel;
struct phy_provider *provider;
- struct resource *res;
const struct phy_ops *phy_usb2_ops;
int ret = 0, i;
@@ -624,8 +623,7 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
if (!channel)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- channel->base = devm_ioremap_resource(dev, res);
+ channel->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(channel->base))
return PTR_ERR(channel->base);
@@ -656,8 +654,10 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
*/
pm_runtime_enable(dev);
phy_usb2_ops = of_device_get_match_data(dev);
- if (!phy_usb2_ops)
- return -EINVAL;
+ if (!phy_usb2_ops) {
+ ret = -EINVAL;
+ goto error;
+ }
mutex_init(&channel->lock);
for (i = 0; i < NUM_OF_PHYS; i++) {
diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb3.c b/drivers/phy/renesas/phy-rcar-gen3-usb3.c
index 566b4cf4ff38..f27d6f471629 100644
--- a/drivers/phy/renesas/phy-rcar-gen3-usb3.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-usb3.c
@@ -133,7 +133,6 @@ static int rcar_gen3_phy_usb3_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct rcar_gen3_usb3 *r;
struct phy_provider *provider;
- struct resource *res;
int ret = 0;
struct clk *clk;
@@ -146,8 +145,7 @@ static int rcar_gen3_phy_usb3_probe(struct platform_device *pdev)
if (!r)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- r->base = devm_ioremap_resource(dev, res);
+ r->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(r->base))
return PTR_ERR(r->base);
diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig
index c2f22f90736c..159285f42e5c 100644
--- a/drivers/phy/rockchip/Kconfig
+++ b/drivers/phy/rockchip/Kconfig
@@ -32,6 +32,7 @@ config PHY_ROCKCHIP_INNO_HDMI
tristate "Rockchip INNO HDMI PHY Driver"
depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF
depends on COMMON_CLK
+ depends on HAS_IOMEM
select GENERIC_PHY
help
Enable this to support the Rockchip Innosilicon HDMI PHY.
diff --git a/drivers/phy/rockchip/phy-rockchip-emmc.c b/drivers/phy/rockchip/phy-rockchip-emmc.c
index 2dc19ddd120f..1e424f263e7a 100644
--- a/drivers/phy/rockchip/phy-rockchip-emmc.c
+++ b/drivers/phy/rockchip/phy-rockchip-emmc.c
@@ -65,8 +65,14 @@
#define PHYCTRL_OTAPDLYENA 0x1
#define PHYCTRL_OTAPDLYENA_MASK 0x1
#define PHYCTRL_OTAPDLYENA_SHIFT 0xb
+#define PHYCTRL_OTAPDLYSEL_DEFAULT 0x4
+#define PHYCTRL_OTAPDLYSEL_MAXVALUE 0xf
#define PHYCTRL_OTAPDLYSEL_MASK 0xf
#define PHYCTRL_OTAPDLYSEL_SHIFT 0x7
+#define PHYCTRL_REN_STRB_DISABLE 0x0
+#define PHYCTRL_REN_STRB_ENABLE 0x1
+#define PHYCTRL_REN_STRB_MASK 0x1
+#define PHYCTRL_REN_STRB_SHIFT 0x9
#define PHYCTRL_IS_CALDONE(x) \
((((x) >> PHYCTRL_CALDONE_SHIFT) & \
@@ -80,6 +86,8 @@ struct rockchip_emmc_phy {
struct regmap *reg_base;
struct clk *emmcclk;
unsigned int drive_impedance;
+ unsigned int enable_strobe_pulldown;
+ unsigned int output_tapdelay_select;
};
static int rockchip_emmc_phy_power(struct phy *phy, bool on_off)
@@ -291,10 +299,17 @@ static int rockchip_emmc_phy_power_on(struct phy *phy)
/* Output tap delay */
regmap_write(rk_phy->reg_base,
rk_phy->reg_offset + GRF_EMMCPHY_CON0,
- HIWORD_UPDATE(4,
+ HIWORD_UPDATE(rk_phy->output_tapdelay_select,
PHYCTRL_OTAPDLYSEL_MASK,
PHYCTRL_OTAPDLYSEL_SHIFT));
+ /* Internal pull-down for strobe line */
+ regmap_write(rk_phy->reg_base,
+ rk_phy->reg_offset + GRF_EMMCPHY_CON2,
+ HIWORD_UPDATE(rk_phy->enable_strobe_pulldown,
+ PHYCTRL_REN_STRB_MASK,
+ PHYCTRL_REN_STRB_SHIFT));
+
/* Power up emmc phy analog blocks */
return rockchip_emmc_phy_power(phy, PHYCTRL_PDB_PWR_ON);
}
@@ -359,10 +374,22 @@ static int rockchip_emmc_phy_probe(struct platform_device *pdev)
rk_phy->reg_offset = reg_offset;
rk_phy->reg_base = grf;
rk_phy->drive_impedance = PHYCTRL_DR_50OHM;
+ rk_phy->enable_strobe_pulldown = PHYCTRL_REN_STRB_DISABLE;
+ rk_phy->output_tapdelay_select = PHYCTRL_OTAPDLYSEL_DEFAULT;
if (!of_property_read_u32(dev->of_node, "drive-impedance-ohm", &val))
rk_phy->drive_impedance = convert_drive_impedance_ohm(pdev, val);
+ if (of_property_read_bool(dev->of_node, "enable-strobe-pulldown"))
+ rk_phy->enable_strobe_pulldown = PHYCTRL_REN_STRB_ENABLE;
+
+ if (!of_property_read_u32(dev->of_node, "output-tapdelay-select", &val)) {
+ if (val <= PHYCTRL_OTAPDLYSEL_MAXVALUE)
+ rk_phy->output_tapdelay_select = val;
+ else
+ dev_err(dev, "output-tapdelay-select exceeds limit, apply default\n");
+ }
+
generic_phy = devm_phy_create(dev, dev->of_node, &ops);
if (IS_ERR(generic_phy)) {
dev_err(dev, "failed to create PHY\n");
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
index 9ca20c947283..a37f3f342642 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
@@ -1144,7 +1144,6 @@ static int inno_hdmi_phy_probe(struct platform_device *pdev)
{
struct inno_hdmi_phy *inno;
struct phy_provider *phy_provider;
- struct resource *res;
void __iomem *regs;
int ret;
@@ -1158,8 +1157,7 @@ static int inno_hdmi_phy_probe(struct platform_device *pdev)
if (!inno->plat_data || !inno->plat_data->ops)
return -EINVAL;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- regs = devm_ioremap_resource(inno->dev, res);
+ regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(regs))
return PTR_ERR(regs);
diff --git a/drivers/phy/samsung/phy-exynos-pcie.c b/drivers/phy/samsung/phy-exynos-pcie.c
index 7e28b1aea0d1..578cfe07d07a 100644
--- a/drivers/phy/samsung/phy-exynos-pcie.c
+++ b/drivers/phy/samsung/phy-exynos-pcie.c
@@ -4,70 +4,41 @@
*
* Phy provider for PCIe controller on Exynos SoC series
*
- * Copyright (C) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (C) 2017-2020 Samsung Electronics Co., Ltd.
* Jaehoon Chung <jh80.chung@samsung.com>
*/
-#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;
-};
+#define PCIE_PHY_OFFSET(x) ((x) * 0x4)
+
+/* Sysreg FSYS register offsets and bits for Exynos5433 */
+#define PCIE_EXYNOS5433_PHY_MAC_RESET 0x0208
+#define PCIE_MAC_RESET_MASK 0xFF
+#define PCIE_MAC_RESET BIT(4)
+#define PCIE_EXYNOS5433_PHY_L1SUB_CM_CON 0x1010
+#define PCIE_REFCLK_GATING_EN BIT(0)
+#define PCIE_EXYNOS5433_PHY_COMMON_RESET 0x1020
+#define PCIE_PHY_RESET BIT(0)
+#define PCIE_EXYNOS5433_PHY_GLOBAL_RESET 0x1040
+#define PCIE_GLOBAL_RESET BIT(0)
+#define PCIE_REFCLK BIT(1)
+#define PCIE_REFCLK_MASK 0x16
+#define PCIE_APP_REQ_EXIT_L1_MODE BIT(5)
+
+/* PMU PCIE PHY isolation control */
+#define EXYNOS5433_PMU_PCIE_PHY_OFFSET 0x730
/* 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 */
+ void __iomem *base;
+ struct regmap *pmureg;
+ struct regmap *fsysreg;
};
static void exynos_pcie_phy_writel(void __iomem *base, u32 val, u32 offset)
@@ -75,153 +46,103 @@ 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)
+/* Exynos5433 specific functions */
+static int exynos5433_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);
-
+ regmap_update_bits(ep->fsysreg, PCIE_EXYNOS5433_PHY_COMMON_RESET,
+ PCIE_PHY_RESET, 1);
+ regmap_update_bits(ep->fsysreg, PCIE_EXYNOS5433_PHY_MAC_RESET,
+ PCIE_MAC_RESET, 0);
+
+ /* PHY refclk 24MHz */
+ regmap_update_bits(ep->fsysreg, PCIE_EXYNOS5433_PHY_GLOBAL_RESET,
+ PCIE_REFCLK_MASK, PCIE_REFCLK);
+ regmap_update_bits(ep->fsysreg, PCIE_EXYNOS5433_PHY_GLOBAL_RESET,
+ PCIE_GLOBAL_RESET, 0);
+
+
+ exynos_pcie_phy_writel(ep->base, 0x11, PCIE_PHY_OFFSET(0x3));
+
+ /* band gap reference on */
+ exynos_pcie_phy_writel(ep->base, 0, PCIE_PHY_OFFSET(0x20));
+ exynos_pcie_phy_writel(ep->base, 0, PCIE_PHY_OFFSET(0x4b));
+
+ /* jitter tuning */
+ exynos_pcie_phy_writel(ep->base, 0x34, PCIE_PHY_OFFSET(0x4));
+ exynos_pcie_phy_writel(ep->base, 0x02, PCIE_PHY_OFFSET(0x7));
+ exynos_pcie_phy_writel(ep->base, 0x41, PCIE_PHY_OFFSET(0x21));
+ exynos_pcie_phy_writel(ep->base, 0x7F, PCIE_PHY_OFFSET(0x14));
+ exynos_pcie_phy_writel(ep->base, 0xC0, PCIE_PHY_OFFSET(0x15));
+ exynos_pcie_phy_writel(ep->base, 0x61, PCIE_PHY_OFFSET(0x36));
+
+ /* D0 uninit.. */
+ exynos_pcie_phy_writel(ep->base, 0x44, PCIE_PHY_OFFSET(0x3D));
+
+ /* 24MHz */
+ exynos_pcie_phy_writel(ep->base, 0x94, PCIE_PHY_OFFSET(0x8));
+ exynos_pcie_phy_writel(ep->base, 0xA7, PCIE_PHY_OFFSET(0x9));
+ exynos_pcie_phy_writel(ep->base, 0x93, PCIE_PHY_OFFSET(0xA));
+ exynos_pcie_phy_writel(ep->base, 0x6B, PCIE_PHY_OFFSET(0xC));
+ exynos_pcie_phy_writel(ep->base, 0xA5, PCIE_PHY_OFFSET(0xF));
+ exynos_pcie_phy_writel(ep->base, 0x34, PCIE_PHY_OFFSET(0x16));
+ exynos_pcie_phy_writel(ep->base, 0xA3, PCIE_PHY_OFFSET(0x17));
+ exynos_pcie_phy_writel(ep->base, 0xA7, PCIE_PHY_OFFSET(0x1A));
+ exynos_pcie_phy_writel(ep->base, 0x71, PCIE_PHY_OFFSET(0x23));
+ exynos_pcie_phy_writel(ep->base, 0x4C, PCIE_PHY_OFFSET(0x24));
+
+ exynos_pcie_phy_writel(ep->base, 0x0E, PCIE_PHY_OFFSET(0x26));
+ exynos_pcie_phy_writel(ep->base, 0x14, PCIE_PHY_OFFSET(0x7));
+ exynos_pcie_phy_writel(ep->base, 0x48, PCIE_PHY_OFFSET(0x43));
+ exynos_pcie_phy_writel(ep->base, 0x44, PCIE_PHY_OFFSET(0x44));
+ exynos_pcie_phy_writel(ep->base, 0x03, PCIE_PHY_OFFSET(0x45));
+ exynos_pcie_phy_writel(ep->base, 0xA7, PCIE_PHY_OFFSET(0x48));
+ exynos_pcie_phy_writel(ep->base, 0x13, PCIE_PHY_OFFSET(0x54));
+ exynos_pcie_phy_writel(ep->base, 0x04, PCIE_PHY_OFFSET(0x31));
+ exynos_pcie_phy_writel(ep->base, 0, PCIE_PHY_OFFSET(0x32));
+
+ regmap_update_bits(ep->fsysreg, PCIE_EXYNOS5433_PHY_COMMON_RESET,
+ PCIE_PHY_RESET, 0);
+ regmap_update_bits(ep->fsysreg, PCIE_EXYNOS5433_PHY_MAC_RESET,
+ PCIE_MAC_RESET_MASK, PCIE_MAC_RESET);
return 0;
}
-static int exynos5440_pcie_phy_power_on(struct phy *phy)
+static int exynos5433_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);
+ regmap_update_bits(ep->pmureg, EXYNOS5433_PMU_PCIE_PHY_OFFSET,
+ BIT(0), 1);
+ regmap_update_bits(ep->fsysreg, PCIE_EXYNOS5433_PHY_GLOBAL_RESET,
+ PCIE_APP_REQ_EXIT_L1_MODE, 0);
+ regmap_update_bits(ep->fsysreg, PCIE_EXYNOS5433_PHY_L1SUB_CM_CON,
+ PCIE_REFCLK_GATING_EN, 0);
return 0;
}
-static int exynos5440_pcie_phy_power_off(struct phy *phy)
+static int exynos5433_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);
+ regmap_update_bits(ep->fsysreg, PCIE_EXYNOS5433_PHY_L1SUB_CM_CON,
+ PCIE_REFCLK_GATING_EN, PCIE_REFCLK_GATING_EN);
+ regmap_update_bits(ep->pmureg, EXYNOS5433_PMU_PCIE_PHY_OFFSET,
+ BIT(0), 0);
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,
+static const struct phy_ops exynos5433_phy_ops = {
+ .init = exynos5433_pcie_phy_init,
+ .power_on = exynos5433_pcie_phy_power_on,
+ .power_off = exynos5433_pcie_phy_power_off,
.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,
+ .compatible = "samsung,exynos5433-pcie-phy",
},
{},
};
@@ -232,30 +153,30 @@ static int exynos_pcie_phy_probe(struct platform_device *pdev)
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);
+ exynos_phy->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(exynos_phy->base))
+ return PTR_ERR(exynos_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->pmureg = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "samsung,pmu-syscon");
+ if (IS_ERR(exynos_phy->pmureg)) {
+ dev_err(&pdev->dev, "PMU regmap lookup failed.\n");
+ return PTR_ERR(exynos_phy->pmureg);
+ }
- exynos_phy->drv_data = drv_data;
+ exynos_phy->fsysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "samsung,fsys-sysreg");
+ if (IS_ERR(exynos_phy->fsysreg)) {
+ dev_err(&pdev->dev, "FSYS sysreg regmap lookup failed.\n");
+ return PTR_ERR(exynos_phy->fsysreg);
+ }
- generic_phy = devm_phy_create(dev, dev->of_node, drv_data->ops);
+ generic_phy = devm_phy_create(dev, dev->of_node, &exynos5433_phy_ops);
if (IS_ERR(generic_phy)) {
dev_err(dev, "failed to create PHY\n");
return PTR_ERR(generic_phy);
@@ -275,5 +196,4 @@ static struct platform_driver exynos_pcie_phy_driver = {
.suppress_bind_attrs = true,
}
};
-
builtin_platform_driver(exynos_pcie_phy_driver);
diff --git a/drivers/phy/samsung/phy-exynos5-usbdrd.c b/drivers/phy/samsung/phy-exynos5-usbdrd.c
index cfa9b8b7e5ac..ee0848fe8432 100644
--- a/drivers/phy/samsung/phy-exynos5-usbdrd.c
+++ b/drivers/phy/samsung/phy-exynos5-usbdrd.c
@@ -829,7 +829,6 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
struct device_node *node = dev->of_node;
struct exynos5_usbdrd_phy *phy_drd;
struct phy_provider *phy_provider;
- struct resource *res;
const struct exynos5_usbdrd_phy_drvdata *drv_data;
struct regmap *reg_pmu;
u32 pmu_offset;
@@ -843,8 +842,7 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
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);
+ phy_drd->reg_phy = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(phy_drd->reg_phy))
return PTR_ERR(phy_drd->reg_phy);
diff --git a/drivers/phy/samsung/phy-exynos5250-sata.c b/drivers/phy/samsung/phy-exynos5250-sata.c
index 4dd7324d91b2..9ec234243f7c 100644
--- a/drivers/phy/samsung/phy-exynos5250-sata.c
+++ b/drivers/phy/samsung/phy-exynos5250-sata.c
@@ -162,7 +162,6 @@ 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;
@@ -171,9 +170,7 @@ static int exynos_sata_phy_probe(struct platform_device *pdev)
if (!sata_phy)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
- sata_phy->regs = devm_ioremap_resource(dev, res);
+ sata_phy->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(sata_phy->regs))
return PTR_ERR(sata_phy->regs);
diff --git a/drivers/phy/samsung/phy-exynos5250-usb2.c b/drivers/phy/samsung/phy-exynos5250-usb2.c
index 4f53b711fd6f..e198010e1bfd 100644
--- a/drivers/phy/samsung/phy-exynos5250-usb2.c
+++ b/drivers/phy/samsung/phy-exynos5250-usb2.c
@@ -117,9 +117,9 @@
/* 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)
+#define EXYNOS_5420_USB_ISOL_HOST_OFFSET 0x70C
+#define EXYNOS_5250_USB_ISOL_ENABLE BIT(0)
/* Mode swtich register */
#define EXYNOS_5250_MODE_SWITCH_OFFSET 0x230
@@ -132,7 +132,6 @@ enum exynos4x12_phy_id {
EXYNOS5250_HOST,
EXYNOS5250_HSIC0,
EXYNOS5250_HSIC1,
- EXYNOS5250_NUM_PHYS,
};
/*
@@ -176,20 +175,19 @@ static void exynos5250_isol(struct samsung_usb2_phy_instance *inst, bool on)
{
struct samsung_usb2_phy_driver *drv = inst->drv;
u32 offset;
- u32 mask;
+ u32 mask = EXYNOS_5250_USB_ISOL_ENABLE;
- switch (inst->cfg->id) {
- case EXYNOS5250_DEVICE:
+ if (drv->cfg == &exynos5250_usb2_phy_config &&
+ inst->cfg->id == EXYNOS5250_DEVICE)
offset = EXYNOS_5250_USB_ISOL_OTG_OFFSET;
- mask = EXYNOS_5250_USB_ISOL_OTG;
- break;
- case EXYNOS5250_HOST:
+ else if (drv->cfg == &exynos5250_usb2_phy_config &&
+ inst->cfg->id == EXYNOS5250_HOST)
offset = EXYNOS_5250_USB_ISOL_HOST_OFFSET;
- mask = EXYNOS_5250_USB_ISOL_HOST;
- break;
- default:
+ else if (drv->cfg == &exynos5420_usb2_phy_config &&
+ inst->cfg->id == EXYNOS5250_HOST)
+ offset = EXYNOS_5420_USB_ISOL_HOST_OFFSET;
+ else
return;
- }
regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask);
}
@@ -390,9 +388,31 @@ static const struct samsung_usb2_common_phy exynos5250_phys[] = {
},
};
+static const struct samsung_usb2_common_phy exynos5420_phys[] = {
+ {
+ .label = "host",
+ .id = EXYNOS5250_HOST,
+ .power_on = exynos5250_power_on,
+ .power_off = exynos5250_power_off,
+ },
+ {
+ .label = "hsic",
+ .id = EXYNOS5250_HSIC0,
+ .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,
+ .num_phys = ARRAY_SIZE(exynos5250_phys),
.phys = exynos5250_phys,
.rate_to_clk = exynos5250_rate_to_clk,
};
+
+const struct samsung_usb2_phy_config exynos5420_usb2_phy_config = {
+ .has_mode_switch = 1,
+ .num_phys = ARRAY_SIZE(exynos5420_phys),
+ .phys = exynos5420_phys,
+ .rate_to_clk = exynos5250_rate_to_clk,
+};
diff --git a/drivers/phy/samsung/phy-samsung-usb2.c b/drivers/phy/samsung/phy-samsung-usb2.c
index a3ed3ff04690..ec2befabeea6 100644
--- a/drivers/phy/samsung/phy-samsung-usb2.c
+++ b/drivers/phy/samsung/phy-samsung-usb2.c
@@ -127,6 +127,10 @@ static const struct of_device_id samsung_usb2_phy_of_match[] = {
.compatible = "samsung,exynos5250-usb2-phy",
.data = &exynos5250_usb2_phy_config,
},
+ {
+ .compatible = "samsung,exynos5420-usb2-phy",
+ .data = &exynos5420_usb2_phy_config,
+ },
#endif
#ifdef CONFIG_PHY_S5PV210_USB2
{
@@ -143,7 +147,6 @@ static int samsung_usb2_phy_probe(struct platform_device *pdev)
const struct samsung_usb2_phy_config *cfg;
struct device *dev = &pdev->dev;
struct phy_provider *phy_provider;
- struct resource *mem;
struct samsung_usb2_phy_driver *drv;
int i, ret;
@@ -167,8 +170,7 @@ static int samsung_usb2_phy_probe(struct platform_device *pdev)
drv->cfg = cfg;
drv->dev = dev;
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- drv->reg_phy = devm_ioremap_resource(dev, mem);
+ drv->reg_phy = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(drv->reg_phy)) {
dev_err(dev, "Failed to map register memory (phy)\n");
return PTR_ERR(drv->reg_phy);
diff --git a/drivers/phy/samsung/phy-samsung-usb2.h b/drivers/phy/samsung/phy-samsung-usb2.h
index 77fb23bc218f..ebaf43bfc5a2 100644
--- a/drivers/phy/samsung/phy-samsung-usb2.h
+++ b/drivers/phy/samsung/phy-samsung-usb2.h
@@ -66,5 +66,6 @@ extern const struct samsung_usb2_phy_config exynos3250_usb2_phy_config;
extern const struct samsung_usb2_phy_config exynos4210_usb2_phy_config;
extern const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config;
extern const struct samsung_usb2_phy_config exynos5250_usb2_phy_config;
+extern const struct samsung_usb2_phy_config exynos5420_usb2_phy_config;
extern const struct samsung_usb2_phy_config s5pv210_usb2_phy_config;
#endif
diff --git a/drivers/phy/st/phy-stm32-usbphyc.c b/drivers/phy/st/phy-stm32-usbphyc.c
index 2b3639cba51a..a54317e96c41 100644
--- a/drivers/phy/st/phy-stm32-usbphyc.c
+++ b/drivers/phy/st/phy-stm32-usbphyc.c
@@ -311,7 +311,6 @@ static int stm32_usbphyc_probe(struct platform_device *pdev)
struct stm32_usbphyc *usbphyc;
struct device *dev = &pdev->dev;
struct device_node *child, *np = dev->of_node;
- struct resource *res;
struct phy_provider *phy_provider;
u32 version;
int ret, port = 0;
@@ -322,17 +321,13 @@ static int stm32_usbphyc_probe(struct platform_device *pdev)
usbphyc->dev = dev;
dev_set_drvdata(dev, usbphyc);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- usbphyc->base = devm_ioremap_resource(dev, res);
+ usbphyc->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(usbphyc->base))
return PTR_ERR(usbphyc->base);
usbphyc->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(usbphyc->clk)) {
- ret = PTR_ERR(usbphyc->clk);
- dev_err(dev, "clk get failed: %d\n", ret);
- return ret;
- }
+ if (IS_ERR(usbphyc->clk))
+ return dev_err_probe(dev, PTR_ERR(usbphyc->clk), "clk get_failed\n");
ret = clk_prepare_enable(usbphyc->clk);
if (ret) {
@@ -345,6 +340,10 @@ static int stm32_usbphyc_probe(struct platform_device *pdev)
reset_control_assert(usbphyc->rst);
udelay(2);
reset_control_deassert(usbphyc->rst);
+ } else {
+ ret = PTR_ERR(usbphyc->rst);
+ if (ret == -EPROBE_DEFER)
+ goto clk_disable;
}
usbphyc->switch_setup = -EINVAL;
diff --git a/drivers/phy/tegra/phy-tegra194-p2u.c b/drivers/phy/tegra/phy-tegra194-p2u.c
index 7042bed9feaa..3ee02b9eb04f 100644
--- a/drivers/phy/tegra/phy-tegra194-p2u.c
+++ b/drivers/phy/tegra/phy-tegra194-p2u.c
@@ -72,14 +72,12 @@ static int tegra_p2u_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct phy *generic_phy;
struct tegra_p2u *phy;
- struct resource *res;
phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
if (!phy)
return -ENOMEM;
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctl");
- phy->base = devm_ioremap_resource(dev, res);
+ phy->base = devm_platform_ioremap_resource_byname(pdev, "ctl");
if (IS_ERR(phy->base))
return PTR_ERR(phy->base);
diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c
index ad88d74c1884..941006f503e4 100644
--- a/drivers/phy/tegra/xusb.c
+++ b/drivers/phy/tegra/xusb.c
@@ -146,7 +146,7 @@ static void tegra_xusb_pad_release(struct device *dev)
pad->soc->ops->remove(pad);
}
-static struct device_type tegra_xusb_pad_type = {
+static const struct device_type tegra_xusb_pad_type = {
.release = tegra_xusb_pad_release,
};
@@ -513,7 +513,7 @@ static void tegra_xusb_port_release(struct device *dev)
port->ops->release(port);
}
-static struct device_type tegra_xusb_port_type = {
+static const struct device_type tegra_xusb_port_type = {
.release = tegra_xusb_port_release,
};
@@ -688,7 +688,7 @@ static int tegra_xusb_setup_usb_role_switch(struct tegra_xusb_port *port)
* reference to retrieve usb-phy details.
*/
port->usb_phy.dev = &lane->pad->lanes[port->index]->dev;
- port->usb_phy.dev->driver = port->padctl->dev->driver;
+ port->usb_phy.dev->driver = port->dev.driver;
port->usb_phy.otg->usb_phy = &port->usb_phy;
port->usb_phy.otg->set_peripheral = tegra_xusb_set_peripheral;
port->usb_phy.otg->set_host = tegra_xusb_set_host;
@@ -1148,7 +1148,6 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev)
const struct tegra_xusb_padctl_soc *soc;
struct tegra_xusb_padctl *padctl;
const struct of_device_id *match;
- struct resource *res;
int err;
/* for backwards compatibility with old device trees */
@@ -1173,8 +1172,7 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&padctl->pads);
mutex_init(&padctl->lock);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- padctl->regs = devm_ioremap_resource(&pdev->dev, res);
+ padctl->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(padctl->regs)) {
err = PTR_ERR(padctl->regs);
goto remove;
@@ -1200,7 +1198,7 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev)
err = devm_regulator_bulk_get(&pdev->dev, padctl->soc->num_supplies,
padctl->supplies);
if (err < 0) {
- dev_err(&pdev->dev, "failed to get regulators: %d\n", err);
+ dev_err_probe(&pdev->dev, err, "failed to get regulators\n");
goto remove;
}
diff --git a/drivers/phy/ti/phy-omap-control.c b/drivers/phy/ti/phy-omap-control.c
index ccd0e4e00451..47482f106fab 100644
--- a/drivers/phy/ti/phy-omap-control.c
+++ b/drivers/phy/ti/phy-omap-control.c
@@ -268,7 +268,6 @@ 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;
@@ -285,16 +284,13 @@ static int omap_control_phy_probe(struct platform_device *pdev)
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);
+ control_phy->otghs_control =
+ devm_platform_ioremap_resource_byname(pdev, "otghs_control");
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);
+ control_phy->power =
+ devm_platform_ioremap_resource_byname(pdev, "power");
if (IS_ERR(control_phy->power)) {
dev_err(&pdev->dev, "Couldn't get power register\n");
return PTR_ERR(control_phy->power);
@@ -312,9 +308,8 @@ static int omap_control_phy_probe(struct platform_device *pdev)
}
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);
+ control_phy->pcie_pcs =
+ devm_platform_ioremap_resource_byname(pdev, "pcie_pcs");
if (IS_ERR(control_phy->pcie_pcs))
return PTR_ERR(control_phy->pcie_pcs);
}
diff --git a/drivers/phy/ti/phy-omap-usb2.c b/drivers/phy/ti/phy-omap-usb2.c
index 4fec90d2624f..ebceb1520ce8 100644
--- a/drivers/phy/ti/phy-omap-usb2.c
+++ b/drivers/phy/ti/phy-omap-usb2.c
@@ -366,7 +366,6 @@ 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;
@@ -403,8 +402,7 @@ static int omap_usb2_probe(struct platform_device *pdev)
omap_usb2_init_errata(phy);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- phy->phy_base = devm_ioremap_resource(&pdev->dev, res);
+ phy->phy_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(phy->phy_base))
return PTR_ERR(phy->phy_base);
diff --git a/drivers/phy/ti/phy-ti-pipe3.c b/drivers/phy/ti/phy-ti-pipe3.c
index e9332c90f75f..2cbc91e535d4 100644
--- a/drivers/phy/ti/phy-ti-pipe3.c
+++ b/drivers/phy/ti/phy-ti-pipe3.c
@@ -745,35 +745,28 @@ static int ti_pipe3_get_sysctrl(struct ti_pipe3 *phy)
static int ti_pipe3_get_tx_rx_base(struct ti_pipe3 *phy)
{
- struct resource *res;
struct device *dev = phy->dev;
struct platform_device *pdev = to_platform_device(dev);
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "phy_rx");
- phy->phy_rx = devm_ioremap_resource(dev, res);
+ phy->phy_rx = devm_platform_ioremap_resource_byname(pdev, "phy_rx");
if (IS_ERR(phy->phy_rx))
return PTR_ERR(phy->phy_rx);
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "phy_tx");
- phy->phy_tx = devm_ioremap_resource(dev, res);
+ phy->phy_tx = devm_platform_ioremap_resource_byname(pdev, "phy_tx");
return PTR_ERR_OR_ZERO(phy->phy_tx);
}
static int ti_pipe3_get_pll_base(struct ti_pipe3 *phy)
{
- struct resource *res;
struct device *dev = phy->dev;
struct platform_device *pdev = to_platform_device(dev);
if (phy->mode == PIPE3_MODE_PCIE)
return 0;
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "pll_ctrl");
- phy->pll_ctrl_base = devm_ioremap_resource(dev, res);
+ phy->pll_ctrl_base =
+ devm_platform_ioremap_resource_byname(pdev, "pll_ctrl");
return PTR_ERR_OR_ZERO(phy->pll_ctrl_base);
}