summaryrefslogtreecommitdiff
path: root/drivers/phy
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/phy')
-rw-r--r--drivers/phy/Kconfig23
-rw-r--r--drivers/phy/Makefile4
-rw-r--r--drivers/phy/allwinner/phy-sun4i-usb.c11
-rw-r--r--drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c2
-rw-r--r--drivers/phy/broadcom/phy-bcm-cygnus-pcie.c20
-rw-r--r--drivers/phy/broadcom/phy-bcm-ns-usb2.c55
-rw-r--r--drivers/phy/broadcom/phy-bcm-ns-usb3.c1
-rw-r--r--drivers/phy/broadcom/phy-bcm-sr-pcie.c2
-rw-r--r--drivers/phy/broadcom/phy-bcm-sr-usb.c2
-rw-r--r--drivers/phy/broadcom/phy-bcm63xx-usbh.c2
-rw-r--r--drivers/phy/broadcom/phy-brcm-sata.c21
-rw-r--r--drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c18
-rw-r--r--drivers/phy/broadcom/phy-brcm-usb-init.c433
-rw-r--r--drivers/phy/broadcom/phy-brcm-usb.c4
-rw-r--r--drivers/phy/cadence/cdns-dphy.c2
-rw-r--r--drivers/phy/cadence/phy-cadence-sierra.c118
-rw-r--r--drivers/phy/cadence/phy-cadence-torrent.c1476
-rw-r--r--drivers/phy/freescale/Kconfig13
-rw-r--r--drivers/phy/freescale/Makefile2
-rw-r--r--drivers/phy/freescale/phy-fsl-imx8m-pcie.c16
-rw-r--r--drivers/phy/freescale/phy-fsl-imx8mq-usb.c2
-rw-r--r--drivers/phy/freescale/phy-fsl-imx8qm-hsio.c611
-rw-r--r--drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c8
-rw-r--r--drivers/phy/freescale/phy-fsl-lynx-28g.c8
-rw-r--r--drivers/phy/freescale/phy-fsl-samsung-hdmi.c765
-rw-r--r--drivers/phy/hisilicon/phy-hi3670-pcie.c11
-rw-r--r--drivers/phy/hisilicon/phy-hisi-inno-usb2.c12
-rw-r--r--drivers/phy/hisilicon/phy-histb-combphy.c2
-rw-r--r--drivers/phy/intel/phy-intel-lgm-combo.c4
-rw-r--r--drivers/phy/lantiq/phy-lantiq-vrx200-pcie.c2
-rw-r--r--drivers/phy/marvell/phy-armada375-usb2.c2
-rw-r--r--drivers/phy/marvell/phy-armada38x-comphy.c9
-rw-r--r--drivers/phy/marvell/phy-berlin-sata.c2
-rw-r--r--drivers/phy/marvell/phy-mvebu-a3700-comphy.c11
-rw-r--r--drivers/phy/marvell/phy-mvebu-cp110-comphy.c8
-rw-r--r--drivers/phy/marvell/phy-mvebu-cp110-utmi.c16
-rw-r--r--drivers/phy/mediatek/Kconfig24
-rw-r--r--drivers/phy/mediatek/Makefile3
-rw-r--r--drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c44
-rw-r--r--drivers/phy/mediatek/phy-mtk-hdmi-mt8195.h3
-rw-r--r--drivers/phy/mediatek/phy-mtk-hdmi.c28
-rw-r--r--drivers/phy/mediatek/phy-mtk-hdmi.h4
-rw-r--r--drivers/phy/mediatek/phy-mtk-mipi-csi-0-5-rx-reg.h62
-rw-r--r--drivers/phy/mediatek/phy-mtk-mipi-csi-0-5.c294
-rw-r--r--drivers/phy/mediatek/phy-mtk-tphy.c72
-rw-r--r--drivers/phy/mediatek/phy-mtk-xfi-tphy.c451
-rw-r--r--drivers/phy/mediatek/phy-mtk-xsphy.c29
-rw-r--r--drivers/phy/microchip/lan966x_serdes.c2
-rw-r--r--drivers/phy/microchip/sparx5_serdes.c197
-rw-r--r--drivers/phy/microchip/sparx5_serdes.h44
-rw-r--r--drivers/phy/microchip/sparx5_serdes_regs.h746
-rw-r--r--drivers/phy/motorola/phy-cpcap-usb.c2
-rw-r--r--drivers/phy/motorola/phy-mapphone-mdm6600.c2
-rw-r--r--drivers/phy/mscc/phy-ocelot-serdes.c2
-rw-r--r--drivers/phy/nuvoton/Kconfig12
-rw-r--r--drivers/phy/nuvoton/Makefile3
-rw-r--r--drivers/phy/nuvoton/phy-ma35d1-usb2.c143
-rw-r--r--drivers/phy/phy-airoha-pcie-regs.h494
-rw-r--r--drivers/phy/phy-airoha-pcie.c1290
-rw-r--r--drivers/phy/phy-core.c125
-rw-r--r--drivers/phy/phy-lgm-usb.c2
-rw-r--r--drivers/phy/phy-nxp-ptn3222.c123
-rw-r--r--drivers/phy/phy-xgene.c2
-rw-r--r--drivers/phy/qualcomm/Makefile2
-rw-r--r--drivers/phy/qualcomm/phy-qcom-apq8064-sata.c10
-rw-r--r--drivers/phy/qualcomm/phy-qcom-edp.c450
-rw-r--r--drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c19
-rw-r--r--drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c8
-rw-r--r--drivers/phy/qualcomm/phy-qcom-m31.c2
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-combo.c483
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-common.h62
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-dp-com-v3.h18
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-dp-phy-v3.h21
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-dp-phy-v4.h19
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-dp-phy-v5.h14
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-dp-phy-v6.h14
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-dp-phy.h62
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c81
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-pcie.c1259
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v4_20.h5
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v5.h14
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v5_20.h5
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6.h5
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6_20.h2
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6_30.h25
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-pcs-sgmii.h20
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-pcs-ufs-v6.h6
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-pcs-v2.h1
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6-n4.h32
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6.h2
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6_20.h1
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6_30.h19
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v6.h2
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-qserdes-pll.h3
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-ufs-v6.h14
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v6.h1
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v6_20.h2
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v6_n4.h13
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-ufs.c447
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-usb-legacy.c77
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-usb.c539
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-usbc.c1151
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp.h113
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qusb2.c55
-rw-r--r--drivers/phy/qualcomm/phy-qcom-sgmii-eth.c441
-rw-r--r--drivers/phy/ralink/phy-mt7621-pci.c2
-rw-r--r--drivers/phy/realtek/Kconfig32
-rw-r--r--drivers/phy/realtek/Makefile3
-rw-r--r--drivers/phy/realtek/phy-rtk-usb2.c1314
-rw-r--r--drivers/phy/realtek/phy-rtk-usb3.c750
-rw-r--r--drivers/phy/renesas/phy-rcar-gen2.c2
-rw-r--r--drivers/phy/renesas/phy-rcar-gen3-pcie.c8
-rw-r--r--drivers/phy/renesas/phy-rcar-gen3-usb2.c72
-rw-r--r--drivers/phy/renesas/phy-rcar-gen3-usb3.c8
-rw-r--r--drivers/phy/renesas/r8a779f0-ether-serdes.c4
-rw-r--r--drivers/phy/rockchip/Kconfig25
-rw-r--r--drivers/phy/rockchip/Makefile2
-rw-r--r--drivers/phy/rockchip/phy-rockchip-inno-csidphy.c2
-rw-r--r--drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c2
-rw-r--r--drivers/phy/rockchip/phy-rockchip-inno-hdmi.c4
-rw-r--r--drivers/phy/rockchip/phy-rockchip-inno-usb2.c200
-rw-r--r--drivers/phy/rockchip/phy-rockchip-naneng-combphy.c326
-rw-r--r--drivers/phy/rockchip/phy-rockchip-pcie.c150
-rw-r--r--drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c1154
-rw-r--r--drivers/phy/rockchip/phy-rockchip-snps-pcie3.c80
-rw-r--r--drivers/phy/rockchip/phy-rockchip-typec.c4
-rw-r--r--drivers/phy/rockchip/phy-rockchip-usbdp.c1649
-rw-r--r--drivers/phy/samsung/Kconfig1
-rw-r--r--drivers/phy/samsung/Makefile1
-rw-r--r--drivers/phy/samsung/phy-exynos-mipi-video.c2
-rw-r--r--drivers/phy/samsung/phy-exynos5-usbdrd.c1070
-rw-r--r--drivers/phy/samsung/phy-exynos5250-usb2.c2
-rw-r--r--drivers/phy/samsung/phy-exynos7-ufs.c1
-rw-r--r--drivers/phy/samsung/phy-exynosautov9-ufs.c1
-rw-r--r--drivers/phy/samsung/phy-fsd-ufs.c1
-rw-r--r--drivers/phy/samsung/phy-gs101-ufs.c182
-rw-r--r--drivers/phy/samsung/phy-samsung-ufs.c26
-rw-r--r--drivers/phy/samsung/phy-samsung-ufs.h6
-rw-r--r--drivers/phy/samsung/phy-samsung-usb2.c2
-rw-r--r--drivers/phy/socionext/phy-uniphier-usb2.c2
-rw-r--r--drivers/phy/st/Kconfig11
-rw-r--r--drivers/phy/st/Makefile1
-rw-r--r--drivers/phy/st/phy-miphy28lp.c7
-rw-r--r--drivers/phy/st/phy-spear1310-miphy.c2
-rw-r--r--drivers/phy/st/phy-spear1340-miphy.c2
-rw-r--r--drivers/phy/st/phy-stm32-combophy.c605
-rw-r--r--drivers/phy/st/phy-stm32-usbphyc.c4
-rw-r--r--drivers/phy/starfive/Kconfig10
-rw-r--r--drivers/phy/starfive/Makefile1
-rw-r--r--drivers/phy/starfive/phy-jh7110-dphy-rx.c5
-rw-r--r--drivers/phy/starfive/phy-jh7110-dphy-tx.c461
-rw-r--r--drivers/phy/starfive/phy-jh7110-usb.c16
-rw-r--r--drivers/phy/tegra/Kconfig5
-rw-r--r--drivers/phy/tegra/xusb-tegra186.c11
-rw-r--r--drivers/phy/tegra/xusb.c21
-rw-r--r--drivers/phy/ti/phy-am654-serdes.c55
-rw-r--r--drivers/phy/ti/phy-da8xx-usb.c55
-rw-r--r--drivers/phy/ti/phy-dm816x-usb.c2
-rw-r--r--drivers/phy/ti/phy-gmii-sel.c58
-rw-r--r--drivers/phy/ti/phy-j721e-wiz.c155
-rw-r--r--drivers/phy/ti/phy-omap-usb2.c2
-rw-r--r--drivers/phy/ti/phy-ti-pipe3.c2
-rw-r--r--drivers/phy/ti/phy-tusb1210.c91
-rw-r--r--drivers/phy/ti/phy-twl4030-usb.c2
-rw-r--r--drivers/phy/xilinx/phy-zynqmp.c262
165 files changed, 19191 insertions, 3165 deletions
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 4cef568231bf..8d58efe998ec 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -72,6 +72,27 @@ config PHY_CAN_TRANSCEIVER
functional modes using gpios and sets the attribute max link
rate, for CAN drivers.
+config PHY_AIROHA_PCIE
+ tristate "Airoha PCIe-PHY Driver"
+ depends on ARCH_AIROHA || COMPILE_TEST
+ depends on OF
+ select GENERIC_PHY
+ help
+ Say Y here to add support for Airoha PCIe PHY driver.
+ This driver create the basic PHY instance and provides initialize
+ callback for PCIe GEN3 port.
+
+config PHY_NXP_PTN3222
+ tristate "NXP PTN3222 1-port eUSB2 to USB2 redriver"
+ depends on I2C
+ depends on OF
+ select GENERIC_PHY
+ help
+ Enable this to support NXP PTN3222 1-port eUSB2 to USB2 Redriver.
+ This redriver performs translation between eUSB2 and USB2 signalling
+ schemes. It supports all three USB 2.0 data rates: Low Speed, Full
+ Speed and High Speed.
+
source "drivers/phy/allwinner/Kconfig"
source "drivers/phy/amlogic/Kconfig"
source "drivers/phy/broadcom/Kconfig"
@@ -85,8 +106,10 @@ source "drivers/phy/mediatek/Kconfig"
source "drivers/phy/microchip/Kconfig"
source "drivers/phy/motorola/Kconfig"
source "drivers/phy/mscc/Kconfig"
+source "drivers/phy/nuvoton/Kconfig"
source "drivers/phy/qualcomm/Kconfig"
source "drivers/phy/ralink/Kconfig"
+source "drivers/phy/realtek/Kconfig"
source "drivers/phy/renesas/Kconfig"
source "drivers/phy/rockchip/Kconfig"
source "drivers/phy/samsung/Kconfig"
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index fb3dc9de6111..e281442acc75 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -10,6 +10,8 @@ obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o
obj-$(CONFIG_PHY_XGENE) += phy-xgene.o
obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o
obj-$(CONFIG_USB_LGM_PHY) += phy-lgm-usb.o
+obj-$(CONFIG_PHY_AIROHA_PCIE) += phy-airoha-pcie.o
+obj-$(CONFIG_PHY_NXP_PTN3222) += phy-nxp-ptn3222.o
obj-y += allwinner/ \
amlogic/ \
broadcom/ \
@@ -24,8 +26,10 @@ obj-y += allwinner/ \
microchip/ \
motorola/ \
mscc/ \
+ nuvoton/ \
qualcomm/ \
ralink/ \
+ realtek/ \
renesas/ \
rockchip/ \
samsung/ \
diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
index e53a9a9317bc..29b8fd4b9351 100644
--- a/drivers/phy/allwinner/phy-sun4i-usb.c
+++ b/drivers/phy/allwinner/phy-sun4i-usb.c
@@ -23,7 +23,6 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
-#include <linux/of_gpio.h>
#include <linux/phy/phy.h>
#include <linux/phy/phy-sun4i-usb.h>
#include <linux/platform_device.h>
@@ -683,7 +682,7 @@ static int sun4i_usb_phy0_vbus_notify(struct notifier_block *nb,
}
static struct phy *sun4i_usb_phy_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct sun4i_usb_phy_data *data = dev_get_drvdata(dev);
@@ -1049,11 +1048,11 @@ static const struct of_device_id sun4i_usb_phy_of_match[] = {
MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match);
static struct platform_driver sun4i_usb_phy_driver = {
- .probe = sun4i_usb_phy_probe,
- .remove_new = sun4i_usb_phy_remove,
+ .probe = sun4i_usb_phy_probe,
+ .remove = sun4i_usb_phy_remove,
.driver = {
- .of_match_table = sun4i_usb_phy_of_match,
- .name = "sun4i-usb-phy",
+ .of_match_table= sun4i_usb_phy_of_match,
+ .name = "sun4i-usb-phy",
}
};
module_platform_driver(sun4i_usb_phy_driver);
diff --git a/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c b/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c
index 2712c4bd549d..5468831d6ab9 100644
--- a/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c
+++ b/drivers/phy/amlogic/phy-meson-g12a-usb3-pcie.c
@@ -350,7 +350,7 @@ static int phy_g12a_usb3_pcie_exit(struct phy *phy)
}
static struct phy *phy_g12a_usb3_pcie_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct phy_g12a_usb3_pcie_priv *priv = dev_get_drvdata(dev);
unsigned int mode;
diff --git a/drivers/phy/broadcom/phy-bcm-cygnus-pcie.c b/drivers/phy/broadcom/phy-bcm-cygnus-pcie.c
index cc29b08e49eb..462c61a24ec5 100644
--- a/drivers/phy/broadcom/phy-bcm-cygnus-pcie.c
+++ b/drivers/phy/broadcom/phy-bcm-cygnus-pcie.c
@@ -113,11 +113,10 @@ static const struct phy_ops cygnus_pcie_phy_ops = {
static int cygnus_pcie_phy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct device_node *node = dev->of_node, *child;
+ struct device_node *node = dev->of_node;
struct cygnus_pcie_phy_core *core;
struct phy_provider *provider;
unsigned cnt = 0;
- int ret;
if (of_get_child_count(node) == 0) {
dev_err(dev, "PHY no child node\n");
@@ -136,35 +135,31 @@ static int cygnus_pcie_phy_probe(struct platform_device *pdev)
mutex_init(&core->lock);
- for_each_available_child_of_node(node, child) {
+ for_each_available_child_of_node_scoped(node, child) {
unsigned int id;
struct cygnus_pcie_phy *p;
if (of_property_read_u32(child, "reg", &id)) {
dev_err(dev, "missing reg property for %pOFn\n",
child);
- ret = -EINVAL;
- goto put_child;
+ return -EINVAL;
}
if (id >= MAX_NUM_PHYS) {
dev_err(dev, "invalid PHY id: %u\n", id);
- ret = -EINVAL;
- goto put_child;
+ return -EINVAL;
}
if (core->phys[id].phy) {
dev_err(dev, "duplicated PHY id: %u\n", id);
- ret = -EINVAL;
- goto put_child;
+ return -EINVAL;
}
p = &core->phys[id];
p->phy = devm_phy_create(dev, child, &cygnus_pcie_phy_ops);
if (IS_ERR(p->phy)) {
dev_err(dev, "failed to create PHY\n");
- ret = PTR_ERR(p->phy);
- goto put_child;
+ return PTR_ERR(p->phy);
}
p->core = core;
@@ -184,9 +179,6 @@ static int cygnus_pcie_phy_probe(struct platform_device *pdev)
dev_dbg(dev, "registered %u PCIe PHY(s)\n", cnt);
return 0;
-put_child:
- of_node_put(child);
- return ret;
}
static const struct of_device_id cygnus_pcie_phy_match_table[] = {
diff --git a/drivers/phy/broadcom/phy-bcm-ns-usb2.c b/drivers/phy/broadcom/phy-bcm-ns-usb2.c
index 269564bdf687..c5d35031b398 100644
--- a/drivers/phy/broadcom/phy-bcm-ns-usb2.c
+++ b/drivers/phy/broadcom/phy-bcm-ns-usb2.c
@@ -24,9 +24,6 @@ struct bcm_ns_usb2 {
struct phy *phy;
struct regmap *clkset;
void __iomem *base;
-
- /* Deprecated binding */
- void __iomem *dmu;
};
static int bcm_ns_usb2_phy_init(struct phy *phy)
@@ -49,10 +46,7 @@ static int bcm_ns_usb2_phy_init(struct phy *phy)
goto err_clk_off;
}
- if (usb2->base)
- usb2ctl = readl(usb2->base);
- else
- usb2ctl = readl(usb2->dmu + BCMA_DMU_CRU_USB2_CONTROL);
+ usb2ctl = readl(usb2->base);
if (usb2ctl & BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_PDIV_MASK) {
usb_pll_pdiv = usb2ctl;
@@ -66,24 +60,16 @@ static int bcm_ns_usb2_phy_init(struct phy *phy)
usb_pll_ndiv = (1920000000 * usb_pll_pdiv) / ref_clk_rate;
/* Unlock DMU PLL settings with some magic value */
- if (usb2->clkset)
- regmap_write(usb2->clkset, 0, 0x0000ea68);
- else
- writel(0x0000ea68, usb2->dmu + BCMA_DMU_CRU_CLKSET_KEY);
+ regmap_write(usb2->clkset, 0, 0x0000ea68);
/* Write USB 2.0 PLL control setting */
usb2ctl &= ~BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_NDIV_MASK;
usb2ctl |= usb_pll_ndiv << BCMA_DMU_CRU_USB2_CONTROL_USB_PLL_NDIV_SHIFT;
- if (usb2->base)
- writel(usb2ctl, usb2->base);
- else
- writel(usb2ctl, usb2->dmu + BCMA_DMU_CRU_USB2_CONTROL);
+
+ writel(usb2ctl, usb2->base);
/* Lock DMU PLL settings */
- if (usb2->clkset)
- regmap_write(usb2->clkset, 0, 0x00000000);
- else
- writel(0x00000000, usb2->dmu + BCMA_DMU_CRU_CLKSET_KEY);
+ regmap_write(usb2->clkset, 0, 0x00000000);
err_clk_off:
clk_disable_unprepare(usb2->ref_clk);
@@ -107,27 +93,17 @@ static int bcm_ns_usb2_probe(struct platform_device *pdev)
return -ENOMEM;
usb2->dev = dev;
- if (of_property_present(dev->of_node, "brcm,syscon-clkset")) {
- usb2->base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(usb2->base)) {
- dev_err(dev, "Failed to map control reg\n");
- return PTR_ERR(usb2->base);
- }
-
- usb2->clkset = syscon_regmap_lookup_by_phandle(dev->of_node,
- "brcm,syscon-clkset");
- if (IS_ERR(usb2->clkset)) {
- dev_err(dev, "Failed to lookup clkset regmap\n");
- return PTR_ERR(usb2->clkset);
- }
- } else {
- 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);
- }
+ usb2->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(usb2->base)) {
+ dev_err(dev, "Failed to map control reg\n");
+ return PTR_ERR(usb2->base);
+ }
- dev_warn(dev, "using deprecated DT binding\n");
+ usb2->clkset = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "brcm,syscon-clkset");
+ if (IS_ERR(usb2->clkset)) {
+ dev_err(dev, "Failed to lookup clkset regmap\n");
+ return PTR_ERR(usb2->clkset);
}
usb2->ref_clk = devm_clk_get(dev, "phy-ref-clk");
@@ -162,4 +138,5 @@ static struct platform_driver bcm_ns_usb2_driver = {
};
module_platform_driver(bcm_ns_usb2_driver);
+MODULE_DESCRIPTION("Broadcom Northstar USB 2.0 PHY Driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/broadcom/phy-bcm-ns-usb3.c b/drivers/phy/broadcom/phy-bcm-ns-usb3.c
index 2c8b1b7dda5b..9f995e156f75 100644
--- a/drivers/phy/broadcom/phy-bcm-ns-usb3.c
+++ b/drivers/phy/broadcom/phy-bcm-ns-usb3.c
@@ -240,5 +240,6 @@ static struct mdio_driver bcm_ns_usb3_mdio_driver = {
mdio_module_driver(bcm_ns_usb3_mdio_driver);
+MODULE_DESCRIPTION("Broadcom Northstar USB 3.0 PHY Driver");
MODULE_LICENSE("GPL v2");
MODULE_DEVICE_TABLE(of, bcm_ns_usb3_id_table);
diff --git a/drivers/phy/broadcom/phy-bcm-sr-pcie.c b/drivers/phy/broadcom/phy-bcm-sr-pcie.c
index 8a4aadf166cf..ff9b3862bf7a 100644
--- a/drivers/phy/broadcom/phy-bcm-sr-pcie.c
+++ b/drivers/phy/broadcom/phy-bcm-sr-pcie.c
@@ -195,7 +195,7 @@ static const struct phy_ops sr_paxc_phy_ops = {
};
static struct phy *sr_pcie_phy_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct sr_pcie_phy_core *core;
int phy_idx;
diff --git a/drivers/phy/broadcom/phy-bcm-sr-usb.c b/drivers/phy/broadcom/phy-bcm-sr-usb.c
index b0bd18a5df87..6bcfe83609c8 100644
--- a/drivers/phy/broadcom/phy-bcm-sr-usb.c
+++ b/drivers/phy/broadcom/phy-bcm-sr-usb.c
@@ -209,7 +209,7 @@ static const struct phy_ops sr_phy_ops = {
};
static struct phy *bcm_usb_phy_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct bcm_usb_phy_cfg *phy_cfg;
int phy_idx;
diff --git a/drivers/phy/broadcom/phy-bcm63xx-usbh.c b/drivers/phy/broadcom/phy-bcm63xx-usbh.c
index f8183dea774b..647644de041b 100644
--- a/drivers/phy/broadcom/phy-bcm63xx-usbh.c
+++ b/drivers/phy/broadcom/phy-bcm63xx-usbh.c
@@ -366,7 +366,7 @@ static const struct phy_ops bcm63xx_usbh_phy_ops = {
};
static struct phy *bcm63xx_usbh_phy_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct bcm63xx_usbh_phy *usbh = dev_get_drvdata(dev);
diff --git a/drivers/phy/broadcom/phy-brcm-sata.c b/drivers/phy/broadcom/phy-brcm-sata.c
index ed9e18791ec9..228100357054 100644
--- a/drivers/phy/broadcom/phy-brcm-sata.c
+++ b/drivers/phy/broadcom/phy-brcm-sata.c
@@ -751,11 +751,11 @@ static int brcm_sata_phy_probe(struct platform_device *pdev)
{
const char *rxaeq_mode;
struct device *dev = &pdev->dev;
- struct device_node *dn = dev->of_node, *child;
+ struct device_node *dn = dev->of_node;
const struct of_device_id *of_id;
struct brcm_sata_phy *priv;
struct phy_provider *provider;
- int ret, count = 0;
+ int count = 0;
if (of_get_child_count(dn) == 0)
return -ENODEV;
@@ -782,26 +782,23 @@ static int brcm_sata_phy_probe(struct platform_device *pdev)
return PTR_ERR(priv->ctrl_base);
}
- for_each_available_child_of_node(dn, child) {
+ for_each_available_child_of_node_scoped(dn, child) {
unsigned int id;
struct brcm_sata_port *port;
if (of_property_read_u32(child, "reg", &id)) {
dev_err(dev, "missing reg property in node %pOFn\n",
child);
- ret = -EINVAL;
- goto put_child;
+ return -EINVAL;
}
if (id >= MAX_PORTS) {
dev_err(dev, "invalid reg: %u\n", id);
- ret = -EINVAL;
- goto put_child;
+ return -EINVAL;
}
if (priv->phys[id].phy) {
dev_err(dev, "already registered port %u\n", id);
- ret = -EINVAL;
- goto put_child;
+ return -EINVAL;
}
port = &priv->phys[id];
@@ -822,8 +819,7 @@ static int brcm_sata_phy_probe(struct platform_device *pdev)
port->ssc_en = of_property_read_bool(child, "brcm,enable-ssc");
if (IS_ERR(port->phy)) {
dev_err(dev, "failed to create PHY\n");
- ret = PTR_ERR(port->phy);
- goto put_child;
+ return PTR_ERR(port->phy);
}
phy_set_drvdata(port->phy, port);
@@ -839,9 +835,6 @@ static int brcm_sata_phy_probe(struct platform_device *pdev)
dev_info(dev, "registered %d port(s)\n", count);
return 0;
-put_child:
- of_node_put(child);
- return ret;
}
static struct platform_driver brcm_sata_phy_driver = {
diff --git a/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c b/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c
index 4c10cafded4e..dc452610934a 100644
--- a/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c
+++ b/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c
@@ -153,7 +153,9 @@ static void xhci_soft_reset(struct brcm_usb_init_params *params,
} else {
USB_CTRL_SET(ctrl, USB_PM, XHC_SOFT_RESETB);
/* Required for COMMONONN to be set */
- USB_XHCI_GBL_UNSET(xhci_gbl, GUSB2PHYCFG, U2_FREECLK_EXISTS);
+ if (params->supported_port_modes != USB_CTLR_MODE_DRD)
+ USB_XHCI_GBL_UNSET(xhci_gbl, GUSB2PHYCFG,
+ U2_FREECLK_EXISTS);
}
}
@@ -323,13 +325,23 @@ static void usb_init_common_7216(struct brcm_usb_init_params *params)
void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
USB_CTRL_UNSET(ctrl, USB_PM, XHC_S2_CLK_SWITCH_EN);
+
+ /*
+ * The PHY might be in a bad state if it is already powered
+ * up. Toggle the power just in case.
+ */
+ USB_CTRL_SET(ctrl, USB_PM, USB_PWRDN);
USB_CTRL_UNSET(ctrl, USB_PM, USB_PWRDN);
/* 1 millisecond - for USB clocks to settle down */
usleep_range(1000, 2000);
- /* Disable PHY when port is suspended */
- USB_CTRL_SET(ctrl, P0_U2PHY_CFG1, COMMONONN);
+ /*
+ * Disable PHY when port is suspended
+ * Does not work in DRD mode
+ */
+ if (params->supported_port_modes != USB_CTLR_MODE_DRD)
+ USB_CTRL_SET(ctrl, P0_U2PHY_CFG1, COMMONONN);
usb_wake_enable_7216(params, false);
usb_init_common(params);
diff --git a/drivers/phy/broadcom/phy-brcm-usb-init.c b/drivers/phy/broadcom/phy-brcm-usb-init.c
index 39536b6d96a9..da23078878a9 100644
--- a/drivers/phy/broadcom/phy-brcm-usb-init.c
+++ b/drivers/phy/broadcom/phy-brcm-usb-init.c
@@ -193,254 +193,251 @@ static const u32
usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = {
/* 3390B0 */
[BRCM_FAMILY_3390A0] = {
- USB_CTRL_SETUP_SCB1_EN_MASK,
- USB_CTRL_SETUP_SCB2_EN_MASK,
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
- USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
- 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_USB_PWRDN_MASK,
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
- 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SCB1_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB1_EN_MASK,
+ [USB_CTRL_SETUP_SCB2_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB2_EN_MASK,
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+ [USB_CTRL_SETUP_STRAP_IPP_SEL_SELECTOR] =
+ USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_USB_PWRDN_SELECTOR] =
+ USB_CTRL_USB_PM_USB_PWRDN_MASK,
+ [USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_SELECTOR] =
+ USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
+ [USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 4908 */
[BRCM_FAMILY_4908] = {
- 0, /* USB_CTRL_SETUP_SCB1_EN_MASK */
- 0, /* USB_CTRL_SETUP_SCB2_EN_MASK */
- 0, /* USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
- 0, /* USB_CTRL_SETUP_OC3_DISABLE_MASK */
- 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
- 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_USB_PWRDN_MASK,
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- 0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
- 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- 0, /* USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK */
- 0, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_USB_PWRDN_SELECTOR] =
+ USB_CTRL_USB_PM_USB_PWRDN_MASK,
},
/* 7250b0 */
[BRCM_FAMILY_7250B0] = {
- USB_CTRL_SETUP_SCB1_EN_MASK,
- USB_CTRL_SETUP_SCB2_EN_MASK,
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
- 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
- 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK,
- 0, /* USB_CTRL_USB_PM_USB_PWRDN_MASK */
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- 0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
- 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- USB_CTRL_USB_PM_USB20_HC_RESETB_MASK,
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SCB1_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB1_EN_MASK,
+ [USB_CTRL_SETUP_SCB2_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB2_EN_MASK,
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_SELECTOR] =
+ USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK,
+ [USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_USB20_HC_RESETB_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 7271a0 */
[BRCM_FAMILY_7271A0] = {
- 0, /* USB_CTRL_SETUP_SCB1_EN_MASK */
- 0, /* USB_CTRL_SETUP_SCB2_EN_MASK */
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
- USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
- USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_USB_PWRDN_MASK,
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
- USB_CTRL_USB_PM_SOFT_RESET_MASK,
- USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK,
- USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK,
- USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+ [USB_CTRL_SETUP_STRAP_IPP_SEL_SELECTOR] =
+ USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_USB_PM_BDC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_USB_PWRDN_SELECTOR] =
+ USB_CTRL_USB_PM_USB_PWRDN_MASK,
+ [USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_SELECTOR] =
+ USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
+ [USB_CTRL_USB_PM_SOFT_RESET_SELECTOR] =
+ USB_CTRL_USB_PM_SOFT_RESET_MASK,
+ [USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_SELECTOR] =
+ USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK,
+ [USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_SELECTOR] =
+ USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK,
+ [USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 7364a0 */
[BRCM_FAMILY_7364A0] = {
- USB_CTRL_SETUP_SCB1_EN_MASK,
- USB_CTRL_SETUP_SCB2_EN_MASK,
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
- 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
- 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK,
- 0, /* USB_CTRL_USB_PM_USB_PWRDN_MASK */
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- 0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
- 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- USB_CTRL_USB_PM_USB20_HC_RESETB_MASK,
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SCB1_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB1_EN_MASK,
+ [USB_CTRL_SETUP_SCB2_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB2_EN_MASK,
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_SELECTOR] =
+ USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK,
+ [USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_USB20_HC_RESETB_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 7366c0 */
[BRCM_FAMILY_7366C0] = {
- USB_CTRL_SETUP_SCB1_EN_MASK,
- USB_CTRL_SETUP_SCB2_EN_MASK,
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
- 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
- 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK,
- USB_CTRL_USB_PM_USB_PWRDN_MASK,
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- 0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
- 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- USB_CTRL_USB_PM_USB20_HC_RESETB_MASK,
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SCB1_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB1_EN_MASK,
+ [USB_CTRL_SETUP_SCB2_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB2_EN_MASK,
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK,
+ [USB_CTRL_USB_PM_USB_PWRDN_SELECTOR] =
+ USB_CTRL_USB_PM_USB_PWRDN_MASK,
+ [USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_USB20_HC_RESETB_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 74371A0 */
[BRCM_FAMILY_74371A0] = {
- USB_CTRL_SETUP_SCB1_EN_MASK,
- USB_CTRL_SETUP_SCB2_EN_MASK,
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK,
- 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
- 0, /* USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK */
- 0, /* USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK */
- 0, /* USB_CTRL_SETUP_OC3_DISABLE_MASK */
- USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
- 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB_PM_USB_PWRDN_MASK */
- USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK,
- USB_CTRL_USB30_CTL1_USB3_IOC_MASK,
- USB_CTRL_USB30_CTL1_USB3_IPP_MASK,
- 0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
- 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- 0, /* USB_CTRL_USB_PM_USB20_HC_RESETB_MASK */
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SCB1_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB1_EN_MASK,
+ [USB_CTRL_SETUP_SCB2_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB2_EN_MASK,
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK,
+ [USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_SELECTOR] =
+ USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
+ [USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB30_CTL1_USB3_IOC_SELECTOR] =
+ USB_CTRL_USB30_CTL1_USB3_IOC_MASK,
+ [USB_CTRL_USB30_CTL1_USB3_IPP_SELECTOR] =
+ USB_CTRL_USB30_CTL1_USB3_IPP_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 7439B0 */
[BRCM_FAMILY_7439B0] = {
- USB_CTRL_SETUP_SCB1_EN_MASK,
- USB_CTRL_SETUP_SCB2_EN_MASK,
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
- USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
- USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_USB_PWRDN_MASK,
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
- 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SCB1_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB1_EN_MASK,
+ [USB_CTRL_SETUP_SCB2_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB2_EN_MASK,
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+ [USB_CTRL_SETUP_STRAP_IPP_SEL_SELECTOR] =
+ USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_USB_PM_BDC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_USB_PWRDN_SELECTOR] =
+ USB_CTRL_USB_PM_USB_PWRDN_MASK,
+ [USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_SELECTOR] =
+ USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
+ [USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 7445d0 */
[BRCM_FAMILY_7445D0] = {
- USB_CTRL_SETUP_SCB1_EN_MASK,
- USB_CTRL_SETUP_SCB2_EN_MASK,
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK,
- 0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
- 0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB_PM_USB_PWRDN_MASK */
- USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK,
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- 0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
- 0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SCB1_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB1_EN_MASK,
+ [USB_CTRL_SETUP_SCB2_EN_SELECTOR] =
+ USB_CTRL_SETUP_SCB2_EN_MASK,
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_SELECTOR] =
+ USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
+ [USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 7260a0 */
[BRCM_FAMILY_7260A0] = {
- 0, /* USB_CTRL_SETUP_SCB1_EN_MASK */
- 0, /* USB_CTRL_SETUP_SCB2_EN_MASK */
- USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
- USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
- USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_USB_PWRDN_MASK,
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
- USB_CTRL_USB_PM_SOFT_RESET_MASK,
- USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK,
- USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK,
- USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
- ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR] =
+ USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+ [USB_CTRL_SETUP_STRAP_IPP_SEL_SELECTOR] =
+ USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_USB_PM_BDC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_USB_PWRDN_SELECTOR] =
+ USB_CTRL_USB_PM_USB_PWRDN_MASK,
+ [USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_SELECTOR] =
+ USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
+ [USB_CTRL_USB_PM_SOFT_RESET_SELECTOR] =
+ USB_CTRL_USB_PM_SOFT_RESET_MASK,
+ [USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_SELECTOR] =
+ USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK,
+ [USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_SELECTOR] =
+ USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK,
+ [USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
+ [USB_CTRL_SETUP_ENDIAN_SELECTOR] = ENDIAN_SETTINGS,
},
/* 7278a0 */
[BRCM_FAMILY_7278A0] = {
- 0, /* USB_CTRL_SETUP_SCB1_EN_MASK */
- 0, /* USB_CTRL_SETUP_SCB2_EN_MASK */
- 0, /*USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK */
- USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
- USB_CTRL_SETUP_OC3_DISABLE_MASK,
- 0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
- USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
- USB_CTRL_USB_PM_USB_PWRDN_MASK,
- 0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
- 0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
- USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
- USB_CTRL_USB_PM_SOFT_RESET_MASK,
- 0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
- 0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
- 0, /* USB_CTRL_USB_PM_USB20_HC_RESETB_MASK */
- 0, /* USB_CTRL_SETUP ENDIAN bits */
+ [USB_CTRL_SETUP_STRAP_IPP_SEL_SELECTOR] =
+ USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT0_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT0_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_PORT1_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_PORT1_MASK,
+ [USB_CTRL_SETUP_OC3_DISABLE_SELECTOR] =
+ USB_CTRL_SETUP_OC3_DISABLE_MASK,
+ [USB_CTRL_USB_PM_BDC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR] =
+ USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
+ [USB_CTRL_USB_PM_USB_PWRDN_SELECTOR] =
+ USB_CTRL_USB_PM_USB_PWRDN_MASK,
+ [USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_SELECTOR] =
+ USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
+ [USB_CTRL_USB_PM_SOFT_RESET_SELECTOR] =
+ USB_CTRL_USB_PM_SOFT_RESET_MASK,
},
};
diff --git a/drivers/phy/broadcom/phy-brcm-usb.c b/drivers/phy/broadcom/phy-brcm-usb.c
index a16f0b58eb74..6362ca5b7fb6 100644
--- a/drivers/phy/broadcom/phy-brcm-usb.c
+++ b/drivers/phy/broadcom/phy-brcm-usb.c
@@ -175,7 +175,7 @@ static const struct phy_ops brcm_usb_phy_ops = {
};
static struct phy *brcm_usb_phy_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct brcm_usb_phy_data *data = dev_get_drvdata(dev);
@@ -667,7 +667,7 @@ MODULE_DEVICE_TABLE(of, brcm_usb_dt_ids);
static struct platform_driver brcm_usb_driver = {
.probe = brcm_usb_phy_probe,
- .remove_new = brcm_usb_phy_remove,
+ .remove = brcm_usb_phy_remove,
.driver = {
.name = "brcmstb-usb-phy",
.pm = &brcm_usb_phy_pm_ops,
diff --git a/drivers/phy/cadence/cdns-dphy.c b/drivers/phy/cadence/cdns-dphy.c
index dddb66de6dba..ed87a3970f83 100644
--- a/drivers/phy/cadence/cdns-dphy.c
+++ b/drivers/phy/cadence/cdns-dphy.c
@@ -472,7 +472,7 @@ MODULE_DEVICE_TABLE(of, cdns_dphy_of_match);
static struct platform_driver cdns_dphy_platform_driver = {
.probe = cdns_dphy_probe,
- .remove_new = cdns_dphy_remove,
+ .remove = cdns_dphy_remove,
.driver = {
.name = "cdns-mipi-dphy",
.of_match_table = cdns_dphy_of_match,
diff --git a/drivers/phy/cadence/phy-cadence-sierra.c b/drivers/phy/cadence/phy-cadence-sierra.c
index d4eb93ce8232..45a5c00843bf 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -174,8 +174,9 @@
#define SIERRA_DEQ_TAU_CTRL1_SLOW_MAINT_PREG 0x150
#define SIERRA_DEQ_TAU_CTRL2_PREG 0x151
#define SIERRA_DEQ_TAU_CTRL3_PREG 0x152
-#define SIERRA_DEQ_OPENEYE_CTRL_PREG 0x158
+#define SIERRA_DEQ_TAU_EPIOFFSET_MODE_PREG 0x158
#define SIERRA_DEQ_CONCUR_EPIOFFSET_MODE_PREG 0x159
+#define SIERRA_DEQ_OPENEYE_CTRL_PREG 0x15C
#define SIERRA_DEQ_PICTRL_PREG 0x161
#define SIERRA_CPICAL_TMRVAL_MODE1_PREG 0x170
#define SIERRA_CPICAL_TMRVAL_MODE0_PREG 0x171
@@ -310,7 +311,7 @@ static const struct clk_parent_data pll_mux_parent_data[][SIERRA_NUM_CMN_PLLC_PA
},
};
-static u32 cdns_sierra_pll_mux_table[][SIERRA_NUM_CMN_PLLC_PARENTS] = {
+static const u32 cdns_sierra_pll_mux_table[][SIERRA_NUM_CMN_PLLC_PARENTS] = {
[CMN_PLLLC] = { 0, 1 },
[CMN_PLLLC1] = { 1, 0 },
};
@@ -362,14 +363,14 @@ struct cdns_sierra_data {
u32 id_value;
u8 block_offset_shift;
u8 reg_offset_shift;
- struct cdns_sierra_vals *pcs_cmn_vals[NUM_PHY_TYPE][NUM_PHY_TYPE]
- [NUM_SSC_MODE];
- struct cdns_sierra_vals *phy_pma_ln_vals[NUM_PHY_TYPE][NUM_PHY_TYPE]
- [NUM_SSC_MODE];
- struct cdns_sierra_vals *pma_cmn_vals[NUM_PHY_TYPE][NUM_PHY_TYPE]
- [NUM_SSC_MODE];
- struct cdns_sierra_vals *pma_ln_vals[NUM_PHY_TYPE][NUM_PHY_TYPE]
- [NUM_SSC_MODE];
+ const struct cdns_sierra_vals *pcs_cmn_vals[NUM_PHY_TYPE][NUM_PHY_TYPE]
+ [NUM_SSC_MODE];
+ const struct cdns_sierra_vals *phy_pma_ln_vals[NUM_PHY_TYPE][NUM_PHY_TYPE]
+ [NUM_SSC_MODE];
+ const struct cdns_sierra_vals *pma_cmn_vals[NUM_PHY_TYPE][NUM_PHY_TYPE]
+ [NUM_SSC_MODE];
+ const struct cdns_sierra_vals *pma_ln_vals[NUM_PHY_TYPE][NUM_PHY_TYPE]
+ [NUM_SSC_MODE];
};
struct cdns_regmap_cdb_context {
@@ -539,12 +540,12 @@ static int cdns_sierra_phy_init(struct phy *gphy)
struct cdns_sierra_inst *ins = phy_get_drvdata(gphy);
struct cdns_sierra_phy *phy = dev_get_drvdata(gphy->dev.parent);
const struct cdns_sierra_data *init_data = phy->init_data;
- struct cdns_sierra_vals *pma_cmn_vals, *pma_ln_vals;
+ const struct cdns_sierra_vals *pma_cmn_vals, *pma_ln_vals;
enum cdns_sierra_phy_type phy_type = ins->phy_type;
+ const struct cdns_sierra_vals *phy_pma_ln_vals;
enum cdns_sierra_ssc_mode ssc = ins->ssc_mode;
- struct cdns_sierra_vals *phy_pma_ln_vals;
+ const struct cdns_sierra_vals *pcs_cmn_vals;
const struct cdns_reg_pairs *reg_pairs;
- struct cdns_sierra_vals *pcs_cmn_vals;
struct regmap *regmap;
u32 num_regs;
int i, j;
@@ -1244,12 +1245,12 @@ static int cdns_sierra_phy_get_resets(struct cdns_sierra_phy *sp,
static int cdns_sierra_phy_configure_multilink(struct cdns_sierra_phy *sp)
{
+ const struct cdns_sierra_vals *pma_cmn_vals, *pma_ln_vals;
const struct cdns_sierra_data *init_data = sp->init_data;
- struct cdns_sierra_vals *pma_cmn_vals, *pma_ln_vals;
+ const struct cdns_sierra_vals *phy_pma_ln_vals;
+ const struct cdns_sierra_vals *pcs_cmn_vals;
enum cdns_sierra_phy_type phy_t1, phy_t2;
- struct cdns_sierra_vals *phy_pma_ln_vals;
const struct cdns_reg_pairs *reg_pairs;
- struct cdns_sierra_vals *pcs_cmn_vals;
int i, j, node, mlane, num_lanes, ret;
enum cdns_sierra_ssc_mode ssc;
struct regmap *regmap;
@@ -1366,7 +1367,7 @@ static int cdns_sierra_phy_probe(struct platform_device *pdev)
unsigned int id_value;
int ret, node = 0;
void __iomem *base;
- struct device_node *dn = dev->of_node, *child;
+ struct device_node *dn = dev->of_node;
if (of_get_child_count(dn) == 0)
return -ENODEV;
@@ -1438,7 +1439,7 @@ static int cdns_sierra_phy_probe(struct platform_device *pdev)
sp->autoconf = of_property_read_bool(dn, "cdns,autoconf");
- for_each_available_child_of_node(dn, child) {
+ for_each_available_child_of_node_scoped(dn, child) {
struct phy *gphy;
if (!(of_node_name_eq(child, "phy") ||
@@ -1452,7 +1453,6 @@ static int cdns_sierra_phy_probe(struct platform_device *pdev)
dev_err(dev, "failed to get reset %s\n",
child->full_name);
ret = PTR_ERR(sp->phys[node].lnk_rst);
- of_node_put(child);
goto put_control;
}
@@ -1461,7 +1461,6 @@ static int cdns_sierra_phy_probe(struct platform_device *pdev)
if (ret) {
dev_err(dev, "missing property in node %s\n",
child->name);
- of_node_put(child);
reset_control_put(sp->phys[node].lnk_rst);
goto put_control;
}
@@ -1475,7 +1474,6 @@ static int cdns_sierra_phy_probe(struct platform_device *pdev)
gphy = devm_phy_create(dev, child, &noop_ops);
if (IS_ERR(gphy)) {
ret = PTR_ERR(gphy);
- of_node_put(child);
reset_control_put(sp->phys[node].lnk_rst);
goto put_control;
}
@@ -1544,11 +1542,11 @@ static void cdns_sierra_phy_remove(struct platform_device *pdev)
}
/* SGMII PHY PMA lane configuration */
-static struct cdns_reg_pairs sgmii_phy_pma_ln_regs[] = {
+static const struct cdns_reg_pairs sgmii_phy_pma_ln_regs[] = {
{0x9010, SIERRA_PHY_PMA_XCVR_CTRL}
};
-static struct cdns_sierra_vals sgmii_phy_pma_ln_vals = {
+static const struct cdns_sierra_vals sgmii_phy_pma_ln_vals = {
.reg_pairs = sgmii_phy_pma_ln_regs,
.num_regs = ARRAY_SIZE(sgmii_phy_pma_ln_regs),
};
@@ -1598,22 +1596,22 @@ static const struct cdns_reg_pairs sgmii_100_no_ssc_plllc1_opt3_ln_regs[] = {
{0x0002, SIERRA_RXBUFFER_RCDFECTRL_PREG}
};
-static struct cdns_sierra_vals sgmii_100_no_ssc_plllc1_opt3_cmn_vals = {
+static const struct cdns_sierra_vals sgmii_100_no_ssc_plllc1_opt3_cmn_vals = {
.reg_pairs = sgmii_100_no_ssc_plllc1_opt3_cmn_regs,
.num_regs = ARRAY_SIZE(sgmii_100_no_ssc_plllc1_opt3_cmn_regs),
};
-static struct cdns_sierra_vals sgmii_100_no_ssc_plllc1_opt3_ln_vals = {
+static const struct cdns_sierra_vals sgmii_100_no_ssc_plllc1_opt3_ln_vals = {
.reg_pairs = sgmii_100_no_ssc_plllc1_opt3_ln_regs,
.num_regs = ARRAY_SIZE(sgmii_100_no_ssc_plllc1_opt3_ln_regs),
};
/* QSGMII PHY PMA lane configuration */
-static struct cdns_reg_pairs qsgmii_phy_pma_ln_regs[] = {
+static const struct cdns_reg_pairs qsgmii_phy_pma_ln_regs[] = {
{0x9010, SIERRA_PHY_PMA_XCVR_CTRL}
};
-static struct cdns_sierra_vals qsgmii_phy_pma_ln_vals = {
+static const struct cdns_sierra_vals qsgmii_phy_pma_ln_vals = {
.reg_pairs = qsgmii_phy_pma_ln_regs,
.num_regs = ARRAY_SIZE(qsgmii_phy_pma_ln_regs),
};
@@ -1664,22 +1662,22 @@ static const struct cdns_reg_pairs qsgmii_100_no_ssc_plllc1_ln_regs[] = {
{0x0002, SIERRA_RXBUFFER_RCDFECTRL_PREG}
};
-static struct cdns_sierra_vals qsgmii_100_no_ssc_plllc1_cmn_vals = {
+static const struct cdns_sierra_vals qsgmii_100_no_ssc_plllc1_cmn_vals = {
.reg_pairs = qsgmii_100_no_ssc_plllc1_cmn_regs,
.num_regs = ARRAY_SIZE(qsgmii_100_no_ssc_plllc1_cmn_regs),
};
-static struct cdns_sierra_vals qsgmii_100_no_ssc_plllc1_ln_vals = {
+static const struct cdns_sierra_vals qsgmii_100_no_ssc_plllc1_ln_vals = {
.reg_pairs = qsgmii_100_no_ssc_plllc1_ln_regs,
.num_regs = ARRAY_SIZE(qsgmii_100_no_ssc_plllc1_ln_regs),
};
/* PCIE PHY PCS common configuration */
-static struct cdns_reg_pairs pcie_phy_pcs_cmn_regs[] = {
+static const struct cdns_reg_pairs pcie_phy_pcs_cmn_regs[] = {
{0x0430, SIERRA_PHY_PIPE_CMN_CTRL1}
};
-static struct cdns_sierra_vals pcie_phy_pcs_cmn_vals = {
+static const struct cdns_sierra_vals pcie_phy_pcs_cmn_vals = {
.reg_pairs = pcie_phy_pcs_cmn_regs,
.num_regs = ARRAY_SIZE(pcie_phy_pcs_cmn_regs),
};
@@ -1736,7 +1734,7 @@ static const struct cdns_reg_pairs ml_pcie_100_no_ssc_ln_regs[] = {
{0x3C0F, SIERRA_DEQ_TAU_CTRL1_SLOW_MAINT_PREG},
{0x1C0C, SIERRA_DEQ_TAU_CTRL2_PREG},
{0x0100, SIERRA_DEQ_TAU_CTRL3_PREG},
- {0x5E82, SIERRA_DEQ_OPENEYE_CTRL_PREG},
+ {0x5E82, SIERRA_DEQ_TAU_EPIOFFSET_MODE_PREG},
{0x002B, SIERRA_CPI_TRIM_PREG},
{0x0003, SIERRA_EPI_CTRL_PREG},
{0x803F, SIERRA_SDFILT_H2L_A_PREG},
@@ -1745,12 +1743,12 @@ static const struct cdns_reg_pairs ml_pcie_100_no_ssc_ln_regs[] = {
{0x4432, SIERRA_RXBUFFER_DFECTRL_PREG}
};
-static struct cdns_sierra_vals pcie_100_no_ssc_plllc_cmn_vals = {
+static const struct cdns_sierra_vals pcie_100_no_ssc_plllc_cmn_vals = {
.reg_pairs = pcie_100_no_ssc_plllc_cmn_regs,
.num_regs = ARRAY_SIZE(pcie_100_no_ssc_plllc_cmn_regs),
};
-static struct cdns_sierra_vals ml_pcie_100_no_ssc_ln_vals = {
+static const struct cdns_sierra_vals ml_pcie_100_no_ssc_ln_vals = {
.reg_pairs = ml_pcie_100_no_ssc_ln_regs,
.num_regs = ARRAY_SIZE(ml_pcie_100_no_ssc_ln_regs),
};
@@ -1800,7 +1798,7 @@ static const struct cdns_reg_pairs ti_ml_pcie_100_no_ssc_ln_regs[] = {
{0x3C0F, SIERRA_DEQ_TAU_CTRL1_SLOW_MAINT_PREG},
{0x1C0C, SIERRA_DEQ_TAU_CTRL2_PREG},
{0x0100, SIERRA_DEQ_TAU_CTRL3_PREG},
- {0x5E82, SIERRA_DEQ_OPENEYE_CTRL_PREG},
+ {0x5E82, SIERRA_DEQ_TAU_EPIOFFSET_MODE_PREG},
{0x002B, SIERRA_CPI_TRIM_PREG},
{0x0003, SIERRA_EPI_CTRL_PREG},
{0x803F, SIERRA_SDFILT_H2L_A_PREG},
@@ -1810,7 +1808,7 @@ static const struct cdns_reg_pairs ti_ml_pcie_100_no_ssc_ln_regs[] = {
{0x0002, SIERRA_TX_RCVDET_OVRD_PREG}
};
-static struct cdns_sierra_vals ti_ml_pcie_100_no_ssc_ln_vals = {
+static const struct cdns_sierra_vals ti_ml_pcie_100_no_ssc_ln_vals = {
.reg_pairs = ti_ml_pcie_100_no_ssc_ln_regs,
.num_regs = ARRAY_SIZE(ti_ml_pcie_100_no_ssc_ln_regs),
};
@@ -1877,7 +1875,7 @@ static const struct cdns_reg_pairs ml_pcie_100_int_ssc_ln_regs[] = {
{0x3C0F, SIERRA_DEQ_TAU_CTRL1_SLOW_MAINT_PREG},
{0x1C0C, SIERRA_DEQ_TAU_CTRL2_PREG},
{0x0100, SIERRA_DEQ_TAU_CTRL3_PREG},
- {0x5E82, SIERRA_DEQ_OPENEYE_CTRL_PREG},
+ {0x5E82, SIERRA_DEQ_TAU_EPIOFFSET_MODE_PREG},
{0x002B, SIERRA_CPI_TRIM_PREG},
{0x0003, SIERRA_EPI_CTRL_PREG},
{0x803F, SIERRA_SDFILT_H2L_A_PREG},
@@ -1886,12 +1884,12 @@ static const struct cdns_reg_pairs ml_pcie_100_int_ssc_ln_regs[] = {
{0x4432, SIERRA_RXBUFFER_DFECTRL_PREG}
};
-static struct cdns_sierra_vals pcie_100_int_ssc_plllc_cmn_vals = {
+static const struct cdns_sierra_vals pcie_100_int_ssc_plllc_cmn_vals = {
.reg_pairs = pcie_100_int_ssc_plllc_cmn_regs,
.num_regs = ARRAY_SIZE(pcie_100_int_ssc_plllc_cmn_regs),
};
-static struct cdns_sierra_vals ml_pcie_100_int_ssc_ln_vals = {
+static const struct cdns_sierra_vals ml_pcie_100_int_ssc_ln_vals = {
.reg_pairs = ml_pcie_100_int_ssc_ln_regs,
.num_regs = ARRAY_SIZE(ml_pcie_100_int_ssc_ln_regs),
};
@@ -1944,7 +1942,7 @@ static const struct cdns_reg_pairs ti_ml_pcie_100_int_ssc_ln_regs[] = {
{0x3C0F, SIERRA_DEQ_TAU_CTRL1_SLOW_MAINT_PREG},
{0x1C0C, SIERRA_DEQ_TAU_CTRL2_PREG},
{0x0100, SIERRA_DEQ_TAU_CTRL3_PREG},
- {0x5E82, SIERRA_DEQ_OPENEYE_CTRL_PREG},
+ {0x5E82, SIERRA_DEQ_TAU_EPIOFFSET_MODE_PREG},
{0x002B, SIERRA_CPI_TRIM_PREG},
{0x0003, SIERRA_EPI_CTRL_PREG},
{0x803F, SIERRA_SDFILT_H2L_A_PREG},
@@ -1954,7 +1952,7 @@ static const struct cdns_reg_pairs ti_ml_pcie_100_int_ssc_ln_regs[] = {
{0x0002, SIERRA_TX_RCVDET_OVRD_PREG}
};
-static struct cdns_sierra_vals ti_ml_pcie_100_int_ssc_ln_vals = {
+static const struct cdns_sierra_vals ti_ml_pcie_100_int_ssc_ln_vals = {
.reg_pairs = ti_ml_pcie_100_int_ssc_ln_regs,
.num_regs = ARRAY_SIZE(ti_ml_pcie_100_int_ssc_ln_regs),
};
@@ -2015,7 +2013,7 @@ static const struct cdns_reg_pairs ml_pcie_100_ext_ssc_ln_regs[] = {
{0x3C0F, SIERRA_DEQ_TAU_CTRL1_SLOW_MAINT_PREG},
{0x1C0C, SIERRA_DEQ_TAU_CTRL2_PREG},
{0x0100, SIERRA_DEQ_TAU_CTRL3_PREG},
- {0x5E82, SIERRA_DEQ_OPENEYE_CTRL_PREG},
+ {0x5E82, SIERRA_DEQ_TAU_EPIOFFSET_MODE_PREG},
{0x002B, SIERRA_CPI_TRIM_PREG},
{0x0003, SIERRA_EPI_CTRL_PREG},
{0x803F, SIERRA_SDFILT_H2L_A_PREG},
@@ -2024,12 +2022,12 @@ static const struct cdns_reg_pairs ml_pcie_100_ext_ssc_ln_regs[] = {
{0x4432, SIERRA_RXBUFFER_DFECTRL_PREG}
};
-static struct cdns_sierra_vals pcie_100_ext_ssc_plllc_cmn_vals = {
+static const struct cdns_sierra_vals pcie_100_ext_ssc_plllc_cmn_vals = {
.reg_pairs = pcie_100_ext_ssc_plllc_cmn_regs,
.num_regs = ARRAY_SIZE(pcie_100_ext_ssc_plllc_cmn_regs),
};
-static struct cdns_sierra_vals ml_pcie_100_ext_ssc_ln_vals = {
+static const struct cdns_sierra_vals ml_pcie_100_ext_ssc_ln_vals = {
.reg_pairs = ml_pcie_100_ext_ssc_ln_regs,
.num_regs = ARRAY_SIZE(ml_pcie_100_ext_ssc_ln_regs),
};
@@ -2082,7 +2080,7 @@ static const struct cdns_reg_pairs ti_ml_pcie_100_ext_ssc_ln_regs[] = {
{0x3C0F, SIERRA_DEQ_TAU_CTRL1_SLOW_MAINT_PREG},
{0x1C0C, SIERRA_DEQ_TAU_CTRL2_PREG},
{0x0100, SIERRA_DEQ_TAU_CTRL3_PREG},
- {0x5E82, SIERRA_DEQ_OPENEYE_CTRL_PREG},
+ {0x5E82, SIERRA_DEQ_TAU_EPIOFFSET_MODE_PREG},
{0x002B, SIERRA_CPI_TRIM_PREG},
{0x0003, SIERRA_EPI_CTRL_PREG},
{0x803F, SIERRA_SDFILT_H2L_A_PREG},
@@ -2092,7 +2090,7 @@ static const struct cdns_reg_pairs ti_ml_pcie_100_ext_ssc_ln_regs[] = {
{0x0002, SIERRA_TX_RCVDET_OVRD_PREG}
};
-static struct cdns_sierra_vals ti_ml_pcie_100_ext_ssc_ln_vals = {
+static const struct cdns_sierra_vals ti_ml_pcie_100_ext_ssc_ln_vals = {
.reg_pairs = ti_ml_pcie_100_ext_ssc_ln_regs,
.num_regs = ARRAY_SIZE(ti_ml_pcie_100_ext_ssc_ln_regs),
};
@@ -2143,7 +2141,7 @@ static const struct cdns_reg_pairs cdns_pcie_ln_regs_no_ssc[] = {
{0x3C0F, SIERRA_DEQ_TAU_CTRL1_SLOW_MAINT_PREG},
{0x1C0C, SIERRA_DEQ_TAU_CTRL2_PREG},
{0x0100, SIERRA_DEQ_TAU_CTRL3_PREG},
- {0x5E82, SIERRA_DEQ_OPENEYE_CTRL_PREG},
+ {0x5E82, SIERRA_DEQ_TAU_EPIOFFSET_MODE_PREG},
{0x002B, SIERRA_CPI_TRIM_PREG},
{0x0003, SIERRA_EPI_CTRL_PREG},
{0x803F, SIERRA_SDFILT_H2L_A_PREG},
@@ -2152,12 +2150,12 @@ static const struct cdns_reg_pairs cdns_pcie_ln_regs_no_ssc[] = {
{0x4432, SIERRA_RXBUFFER_DFECTRL_PREG}
};
-static struct cdns_sierra_vals pcie_100_no_ssc_cmn_vals = {
+static const struct cdns_sierra_vals pcie_100_no_ssc_cmn_vals = {
.reg_pairs = cdns_pcie_cmn_regs_no_ssc,
.num_regs = ARRAY_SIZE(cdns_pcie_cmn_regs_no_ssc),
};
-static struct cdns_sierra_vals pcie_100_no_ssc_ln_vals = {
+static const struct cdns_sierra_vals pcie_100_no_ssc_ln_vals = {
.reg_pairs = cdns_pcie_ln_regs_no_ssc,
.num_regs = ARRAY_SIZE(cdns_pcie_ln_regs_no_ssc),
};
@@ -2218,7 +2216,7 @@ static const struct cdns_reg_pairs cdns_pcie_ln_regs_int_ssc[] = {
{0x3C0F, SIERRA_DEQ_TAU_CTRL1_SLOW_MAINT_PREG},
{0x1C0C, SIERRA_DEQ_TAU_CTRL2_PREG},
{0x0100, SIERRA_DEQ_TAU_CTRL3_PREG},
- {0x5E82, SIERRA_DEQ_OPENEYE_CTRL_PREG},
+ {0x5E82, SIERRA_DEQ_TAU_EPIOFFSET_MODE_PREG},
{0x002B, SIERRA_CPI_TRIM_PREG},
{0x0003, SIERRA_EPI_CTRL_PREG},
{0x803F, SIERRA_SDFILT_H2L_A_PREG},
@@ -2227,12 +2225,12 @@ static const struct cdns_reg_pairs cdns_pcie_ln_regs_int_ssc[] = {
{0x4432, SIERRA_RXBUFFER_DFECTRL_PREG}
};
-static struct cdns_sierra_vals pcie_100_int_ssc_cmn_vals = {
+static const struct cdns_sierra_vals pcie_100_int_ssc_cmn_vals = {
.reg_pairs = cdns_pcie_cmn_regs_int_ssc,
.num_regs = ARRAY_SIZE(cdns_pcie_cmn_regs_int_ssc),
};
-static struct cdns_sierra_vals pcie_100_int_ssc_ln_vals = {
+static const struct cdns_sierra_vals pcie_100_int_ssc_ln_vals = {
.reg_pairs = cdns_pcie_ln_regs_int_ssc,
.num_regs = ARRAY_SIZE(cdns_pcie_ln_regs_int_ssc),
};
@@ -2287,7 +2285,7 @@ static const struct cdns_reg_pairs cdns_pcie_ln_regs_ext_ssc[] = {
{0x3C0F, SIERRA_DEQ_TAU_CTRL1_SLOW_MAINT_PREG},
{0x1C0C, SIERRA_DEQ_TAU_CTRL2_PREG},
{0x0100, SIERRA_DEQ_TAU_CTRL3_PREG},
- {0x5E82, SIERRA_DEQ_OPENEYE_CTRL_PREG},
+ {0x5E82, SIERRA_DEQ_TAU_EPIOFFSET_MODE_PREG},
{0x002B, SIERRA_CPI_TRIM_PREG},
{0x0003, SIERRA_EPI_CTRL_PREG},
{0x803F, SIERRA_SDFILT_H2L_A_PREG},
@@ -2296,12 +2294,12 @@ static const struct cdns_reg_pairs cdns_pcie_ln_regs_ext_ssc[] = {
{0x4432, SIERRA_RXBUFFER_DFECTRL_PREG}
};
-static struct cdns_sierra_vals pcie_100_ext_ssc_cmn_vals = {
+static const struct cdns_sierra_vals pcie_100_ext_ssc_cmn_vals = {
.reg_pairs = cdns_pcie_cmn_regs_ext_ssc,
.num_regs = ARRAY_SIZE(cdns_pcie_cmn_regs_ext_ssc),
};
-static struct cdns_sierra_vals pcie_100_ext_ssc_ln_vals = {
+static const struct cdns_sierra_vals pcie_100_ext_ssc_ln_vals = {
.reg_pairs = cdns_pcie_ln_regs_ext_ssc,
.num_regs = ARRAY_SIZE(cdns_pcie_ln_regs_ext_ssc),
};
@@ -2413,12 +2411,12 @@ static const struct cdns_reg_pairs cdns_usb_ln_regs_ext_ssc[] = {
{0x4243, SIERRA_RXBUFFER_DFECTRL_PREG}
};
-static struct cdns_sierra_vals usb_100_ext_ssc_cmn_vals = {
+static const struct cdns_sierra_vals usb_100_ext_ssc_cmn_vals = {
.reg_pairs = cdns_usb_cmn_regs_ext_ssc,
.num_regs = ARRAY_SIZE(cdns_usb_cmn_regs_ext_ssc),
};
-static struct cdns_sierra_vals usb_100_ext_ssc_ln_vals = {
+static const struct cdns_sierra_vals usb_100_ext_ssc_ln_vals = {
.reg_pairs = cdns_usb_ln_regs_ext_ssc,
.num_regs = ARRAY_SIZE(cdns_usb_ln_regs_ext_ssc),
};
@@ -2443,7 +2441,7 @@ static const struct cdns_reg_pairs sgmii_pma_cmn_vals[] = {
{0x0013, SIERRA_CMN_PLLLC1_DCOCAL_CTRL_PREG},
};
-static struct cdns_sierra_vals sgmii_cmn_vals = {
+static const struct cdns_sierra_vals sgmii_cmn_vals = {
.reg_pairs = sgmii_pma_cmn_vals,
.num_regs = ARRAY_SIZE(sgmii_pma_cmn_vals),
};
@@ -2489,7 +2487,7 @@ static const struct cdns_reg_pairs sgmii_ln_regs[] = {
{0x321F, SIERRA_CPICAL_RES_STARTCODE_MODE01_PREG},
};
-static struct cdns_sierra_vals sgmii_pma_ln_vals = {
+static const struct cdns_sierra_vals sgmii_pma_ln_vals = {
.reg_pairs = sgmii_ln_regs,
.num_regs = ARRAY_SIZE(sgmii_ln_regs),
};
@@ -2733,7 +2731,7 @@ MODULE_DEVICE_TABLE(of, cdns_sierra_id_table);
static struct platform_driver cdns_sierra_driver = {
.probe = cdns_sierra_phy_probe,
- .remove_new = cdns_sierra_phy_remove,
+ .remove = cdns_sierra_phy_remove,
.driver = {
.name = "cdns-sierra-phy",
.of_match_table = cdns_sierra_id_table,
diff --git a/drivers/phy/cadence/phy-cadence-torrent.c b/drivers/phy/cadence/phy-cadence-torrent.c
index a75c96385c57..a281c0dfae97 100644
--- a/drivers/phy/cadence/phy-cadence-torrent.c
+++ b/drivers/phy/cadence/phy-cadence-torrent.c
@@ -285,7 +285,7 @@ static const int refclk_driver_parent_index[] = {
CDNS_TORRENT_RECEIVED_REFCLK
};
-static u32 cdns_torrent_refclk_driver_mux_table[] = { 1, 0 };
+static const u32 cdns_torrent_refclk_driver_mux_table[] = { 1, 0 };
enum cdns_torrent_phy_type {
TYPE_NONE,
@@ -351,13 +351,17 @@ struct cdns_torrent_phy {
void __iomem *sd_base; /* SD0801 registers base */
u32 max_bit_rate; /* Maximum link bit rate to use (in Mbps) */
u32 dp_pll;
+ u32 protocol_bitmask;
struct reset_control *phy_rst;
struct reset_control *apb_rst;
struct device *dev;
struct clk *clk;
+ struct clk *clk1;
enum cdns_torrent_ref_clk ref_clk_rate;
+ enum cdns_torrent_ref_clk ref_clk1_rate;
struct cdns_torrent_inst phys[MAX_NUM_LANES];
int nsubnodes;
+ int already_configured;
const struct cdns_torrent_data *init_data;
struct regmap *regmap_common_cdb;
struct regmap *regmap_phy_pcs_common_cdb;
@@ -419,17 +423,17 @@ struct cdns_reg_pairs {
};
struct cdns_torrent_vals {
- struct cdns_reg_pairs *reg_pairs;
+ const struct cdns_reg_pairs *reg_pairs;
u32 num_regs;
};
struct cdns_torrent_vals_entry {
u32 key;
- struct cdns_torrent_vals *vals;
+ const struct cdns_torrent_vals *vals;
};
struct cdns_torrent_vals_table {
- struct cdns_torrent_vals_entry *entries;
+ const struct cdns_torrent_vals_entry *entries;
u32 num_entries;
};
@@ -451,12 +455,12 @@ struct cdns_regmap_cdb_context {
u8 reg_offset_shift;
};
-static struct cdns_torrent_vals *cdns_torrent_get_tbl_vals(const struct cdns_torrent_vals_table *tbl,
- enum cdns_torrent_ref_clk refclk0,
- enum cdns_torrent_ref_clk refclk1,
- enum cdns_torrent_phy_type link0,
- enum cdns_torrent_phy_type link1,
- enum cdns_torrent_ssc_mode ssc)
+static const struct cdns_torrent_vals *cdns_torrent_get_tbl_vals(const struct cdns_torrent_vals_table *tbl,
+ enum cdns_torrent_ref_clk refclk0,
+ enum cdns_torrent_ref_clk refclk1,
+ enum cdns_torrent_phy_type link0,
+ enum cdns_torrent_phy_type link1,
+ enum cdns_torrent_ssc_mode ssc)
{
int i;
u32 key = CDNS_TORRENT_KEY(refclk0, refclk1, link0, link1, ssc);
@@ -1154,6 +1158,9 @@ static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy,
ret = regmap_read_poll_timeout(regmap, PHY_PMA_XCVR_POWER_STATE_ACK,
read_val, (read_val & mask) == value, 0,
POLL_TIMEOUT_US);
+ if (ret)
+ return ret;
+
cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, 0x00000000);
ndelay(100);
@@ -1592,6 +1599,9 @@ static int cdns_torrent_dp_configure(struct phy *phy,
struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent);
int ret;
+ if (cdns_phy->already_configured)
+ return 0;
+
ret = cdns_torrent_dp_verify_config(inst, &opts->dp);
if (ret) {
dev_err(&phy->dev, "invalid params for phy configure\n");
@@ -1627,6 +1637,12 @@ static int cdns_torrent_phy_on(struct phy *phy)
u32 read_val;
int ret;
+ if (cdns_phy->already_configured) {
+ /* Give 5ms to 10ms delay for the PIPE clock to be stable */
+ usleep_range(5000, 10000);
+ return 0;
+ }
+
if (cdns_phy->nsubnodes == 1) {
/* Take the PHY lane group out of reset */
reset_control_deassert(inst->lnk_rst);
@@ -2291,20 +2307,23 @@ static int cdns_torrent_regmap_init(struct cdns_torrent_phy *cdns_phy)
static int cdns_torrent_phy_init(struct phy *phy)
{
struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent);
+ const struct cdns_torrent_vals *cmn_vals, *tx_ln_vals, *rx_ln_vals;
const struct cdns_torrent_data *init_data = cdns_phy->init_data;
- struct cdns_torrent_vals *cmn_vals, *tx_ln_vals, *rx_ln_vals;
+ const struct cdns_torrent_vals *link_cmn_vals, *xcvr_diag_vals;
enum cdns_torrent_ref_clk ref_clk = cdns_phy->ref_clk_rate;
- struct cdns_torrent_vals *link_cmn_vals, *xcvr_diag_vals;
struct cdns_torrent_inst *inst = phy_get_drvdata(phy);
enum cdns_torrent_phy_type phy_type = inst->phy_type;
+ const struct cdns_torrent_vals *phy_pma_cmn_vals;
enum cdns_torrent_ssc_mode ssc = inst->ssc_mode;
- struct cdns_torrent_vals *phy_pma_cmn_vals;
- struct cdns_torrent_vals *pcs_cmn_vals;
- struct cdns_reg_pairs *reg_pairs;
+ const struct cdns_torrent_vals *pcs_cmn_vals;
+ const struct cdns_reg_pairs *reg_pairs;
struct regmap *regmap;
u32 num_regs;
int i, j;
+ if (cdns_phy->already_configured)
+ return 0;
+
if (cdns_phy->nsubnodes > 1) {
if (phy_type == TYPE_DP)
return cdns_torrent_dp_multilink_init(cdns_phy, inst, phy);
@@ -2442,166 +2461,219 @@ static const struct phy_ops cdns_torrent_phy_ops = {
.owner = THIS_MODULE,
};
-static int cdns_torrent_noop_phy_on(struct phy *phy)
-{
- /* Give 5ms to 10ms delay for the PIPE clock to be stable */
- usleep_range(5000, 10000);
-
- return 0;
-}
-
-static const struct phy_ops noop_ops = {
- .power_on = cdns_torrent_noop_phy_on,
- .owner = THIS_MODULE,
-};
-
static
int cdns_torrent_phy_configure_multilink(struct cdns_torrent_phy *cdns_phy)
{
+ const struct cdns_torrent_vals *cmn_vals, *tx_ln_vals, *rx_ln_vals;
const struct cdns_torrent_data *init_data = cdns_phy->init_data;
- struct cdns_torrent_vals *cmn_vals, *tx_ln_vals, *rx_ln_vals;
+ const struct cdns_torrent_vals *link_cmn_vals, *xcvr_diag_vals;
+ enum cdns_torrent_ref_clk ref_clk1 = cdns_phy->ref_clk1_rate;
enum cdns_torrent_ref_clk ref_clk = cdns_phy->ref_clk_rate;
- struct cdns_torrent_vals *link_cmn_vals, *xcvr_diag_vals;
+ const struct cdns_torrent_vals *phy_pma_cmn_vals;
+ const struct cdns_torrent_vals *pcs_cmn_vals;
enum cdns_torrent_phy_type phy_t1, phy_t2;
- struct cdns_torrent_vals *pcs_cmn_vals;
+ const struct cdns_reg_pairs *reg_pairs;
int i, j, node, mlane, num_lanes, ret;
- struct cdns_reg_pairs *reg_pairs;
+ struct device *dev = cdns_phy->dev;
enum cdns_torrent_ssc_mode ssc;
struct regmap *regmap;
- u32 num_regs;
+ u32 num_regs, num_protocols, protocol;
- /* Maximum 2 links (subnodes) are supported */
- if (cdns_phy->nsubnodes != 2)
+ num_protocols = hweight32(cdns_phy->protocol_bitmask);
+ /* Maximum 2 protocols are supported */
+ if (num_protocols > 2) {
+ dev_err(dev, "at most 2 protocols are supported\n");
return -EINVAL;
+ }
- phy_t1 = cdns_phy->phys[0].phy_type;
- phy_t2 = cdns_phy->phys[1].phy_type;
/**
- * First configure the PHY for first link with phy_t1. Get the array
- * values as [phy_t1][phy_t2][ssc].
+ * Get PHY types directly from subnodes if only 2 subnodes exist.
+ * It is possible for phy_t1 to be the same as phy_t2 for special
+ * configurations such as PCIe Multilink.
*/
- for (node = 0; node < cdns_phy->nsubnodes; node++) {
- if (node == 1) {
+ if (cdns_phy->nsubnodes == 2) {
+ phy_t1 = cdns_phy->phys[0].phy_type;
+ phy_t2 = cdns_phy->phys[1].phy_type;
+ } else {
+ /**
+ * Both PHY types / protocols should be unique.
+ * If they are the same, it should be expressed with either
+ * a) Single-Link (1 Sub-node) - handled via PHY APIs
+ * OR
+ * b) Double-Link (2 Sub-nodes) - handled above
+ */
+ if (num_protocols != 2) {
+ dev_err(dev, "incorrect representation of link\n");
+ return -EINVAL;
+ }
+
+ phy_t1 = fns(cdns_phy->protocol_bitmask, 0);
+ phy_t2 = fns(cdns_phy->protocol_bitmask, 1);
+ }
+
+ /**
+ * Configure all links with the protocol phy_t1 first followed by
+ * configuring all links with the protocol phy_t2.
+ *
+ * When phy_t1 = phy_t2, it is a single protocol and configuration
+ * is performed with a single iteration of the protocol and multiple
+ * iterations over the sub-nodes (links).
+ *
+ * When phy_t1 != phy_t2, there are two protocols and configuration
+ * is performed by iterating over all sub-nodes matching the first
+ * protocol and configuring them first, followed by iterating over
+ * all sub-nodes matching the second protocol and configuring them
+ * next.
+ */
+ for (protocol = 0; protocol < num_protocols; protocol++) {
+ /**
+ * For the case where num_protocols is 1,
+ * phy_t1 = phy_t2 and the swap is unnecessary.
+ *
+ * Swapping phy_t1 and phy_t2 is only required when the
+ * number of protocols is 2 and there are 2 or more links.
+ */
+ if (protocol == 1) {
/**
- * If first link with phy_t1 is configured, then
- * configure the PHY for second link with phy_t2.
+ * If first protocol with phy_t1 is configured, then
+ * configure the PHY for second protocol with phy_t2.
* Get the array values as [phy_t2][phy_t1][ssc].
*/
swap(phy_t1, phy_t2);
+ swap(ref_clk, ref_clk1);
}
- mlane = cdns_phy->phys[node].mlane;
- ssc = cdns_phy->phys[node].ssc_mode;
- num_lanes = cdns_phy->phys[node].num_lanes;
+ for (node = 0; node < cdns_phy->nsubnodes; node++) {
+ if (cdns_phy->phys[node].phy_type != phy_t1)
+ continue;
- /**
- * PHY configuration specific registers:
- * link_cmn_vals depend on combination of PHY types being
- * configured and are common for both PHY types, so array
- * values should be same for [phy_t1][phy_t2][ssc] and
- * [phy_t2][phy_t1][ssc].
- * xcvr_diag_vals also depend on combination of PHY types
- * being configured, but these can be different for particular
- * PHY type and are per lane.
- */
- link_cmn_vals = cdns_torrent_get_tbl_vals(&init_data->link_cmn_vals_tbl,
- CLK_ANY, CLK_ANY,
- phy_t1, phy_t2, ANY_SSC);
- if (link_cmn_vals) {
- reg_pairs = link_cmn_vals->reg_pairs;
- num_regs = link_cmn_vals->num_regs;
- regmap = cdns_phy->regmap_common_cdb;
+ mlane = cdns_phy->phys[node].mlane;
+ ssc = cdns_phy->phys[node].ssc_mode;
+ num_lanes = cdns_phy->phys[node].num_lanes;
/**
- * First array value in link_cmn_vals must be of
- * PHY_PLL_CFG register
+ * PHY configuration specific registers:
+ * link_cmn_vals depend on combination of PHY types being
+ * configured and are common for both PHY types, so array
+ * values should be same for [phy_t1][phy_t2][ssc] and
+ * [phy_t2][phy_t1][ssc].
+ * xcvr_diag_vals also depend on combination of PHY types
+ * being configured, but these can be different for particular
+ * PHY type and are per lane.
*/
- regmap_field_write(cdns_phy->phy_pll_cfg,
- reg_pairs[0].val);
+ link_cmn_vals = cdns_torrent_get_tbl_vals(&init_data->link_cmn_vals_tbl,
+ CLK_ANY, CLK_ANY,
+ phy_t1, phy_t2, ANY_SSC);
+ if (link_cmn_vals) {
+ reg_pairs = link_cmn_vals->reg_pairs;
+ num_regs = link_cmn_vals->num_regs;
+ regmap = cdns_phy->regmap_common_cdb;
+
+ /**
+ * First array value in link_cmn_vals must be of
+ * PHY_PLL_CFG register
+ */
+ regmap_field_write(cdns_phy->phy_pll_cfg,
+ reg_pairs[0].val);
+
+ for (i = 1; i < num_regs; i++)
+ regmap_write(regmap, reg_pairs[i].off,
+ reg_pairs[i].val);
+ }
- for (i = 1; i < num_regs; i++)
- regmap_write(regmap, reg_pairs[i].off,
- reg_pairs[i].val);
- }
+ xcvr_diag_vals = cdns_torrent_get_tbl_vals(&init_data->xcvr_diag_vals_tbl,
+ CLK_ANY, CLK_ANY,
+ phy_t1, phy_t2, ANY_SSC);
+ if (xcvr_diag_vals) {
+ reg_pairs = xcvr_diag_vals->reg_pairs;
+ num_regs = xcvr_diag_vals->num_regs;
+ for (i = 0; i < num_lanes; i++) {
+ regmap = cdns_phy->regmap_tx_lane_cdb[i + mlane];
+ for (j = 0; j < num_regs; j++)
+ regmap_write(regmap, reg_pairs[j].off,
+ reg_pairs[j].val);
+ }
+ }
- xcvr_diag_vals = cdns_torrent_get_tbl_vals(&init_data->xcvr_diag_vals_tbl,
- CLK_ANY, CLK_ANY,
- phy_t1, phy_t2, ANY_SSC);
- if (xcvr_diag_vals) {
- reg_pairs = xcvr_diag_vals->reg_pairs;
- num_regs = xcvr_diag_vals->num_regs;
- for (i = 0; i < num_lanes; i++) {
- regmap = cdns_phy->regmap_tx_lane_cdb[i + mlane];
- for (j = 0; j < num_regs; j++)
- regmap_write(regmap, reg_pairs[j].off,
- reg_pairs[j].val);
+ /* PHY PCS common registers configurations */
+ pcs_cmn_vals = cdns_torrent_get_tbl_vals(&init_data->pcs_cmn_vals_tbl,
+ CLK_ANY, CLK_ANY,
+ phy_t1, phy_t2, ANY_SSC);
+ if (pcs_cmn_vals) {
+ reg_pairs = pcs_cmn_vals->reg_pairs;
+ num_regs = pcs_cmn_vals->num_regs;
+ regmap = cdns_phy->regmap_phy_pcs_common_cdb;
+ for (i = 0; i < num_regs; i++)
+ regmap_write(regmap, reg_pairs[i].off,
+ reg_pairs[i].val);
}
- }
- /* PHY PCS common registers configurations */
- pcs_cmn_vals = cdns_torrent_get_tbl_vals(&init_data->pcs_cmn_vals_tbl,
- CLK_ANY, CLK_ANY,
- phy_t1, phy_t2, ANY_SSC);
- if (pcs_cmn_vals) {
- reg_pairs = pcs_cmn_vals->reg_pairs;
- num_regs = pcs_cmn_vals->num_regs;
- regmap = cdns_phy->regmap_phy_pcs_common_cdb;
- for (i = 0; i < num_regs; i++)
- regmap_write(regmap, reg_pairs[i].off,
- reg_pairs[i].val);
- }
+ /* PHY PMA common registers configurations */
+ phy_pma_cmn_vals =
+ cdns_torrent_get_tbl_vals(&init_data->phy_pma_cmn_vals_tbl,
+ CLK_ANY, CLK_ANY, phy_t1, phy_t2,
+ ANY_SSC);
+ if (phy_pma_cmn_vals) {
+ reg_pairs = phy_pma_cmn_vals->reg_pairs;
+ num_regs = phy_pma_cmn_vals->num_regs;
+ regmap = cdns_phy->regmap_phy_pma_common_cdb;
+ for (i = 0; i < num_regs; i++)
+ regmap_write(regmap, reg_pairs[i].off,
+ reg_pairs[i].val);
+ }
- /* PMA common registers configurations */
- cmn_vals = cdns_torrent_get_tbl_vals(&init_data->cmn_vals_tbl,
- ref_clk, ref_clk,
- phy_t1, phy_t2, ssc);
- if (cmn_vals) {
- reg_pairs = cmn_vals->reg_pairs;
- num_regs = cmn_vals->num_regs;
- regmap = cdns_phy->regmap_common_cdb;
- for (i = 0; i < num_regs; i++)
- regmap_write(regmap, reg_pairs[i].off,
- reg_pairs[i].val);
- }
+ /* PMA common registers configurations */
+ cmn_vals = cdns_torrent_get_tbl_vals(&init_data->cmn_vals_tbl,
+ ref_clk, ref_clk1,
+ phy_t1, phy_t2, ssc);
+ if (cmn_vals) {
+ reg_pairs = cmn_vals->reg_pairs;
+ num_regs = cmn_vals->num_regs;
+ regmap = cdns_phy->regmap_common_cdb;
+ for (i = 0; i < num_regs; i++)
+ regmap_write(regmap, reg_pairs[i].off,
+ reg_pairs[i].val);
+ }
- /* PMA TX lane registers configurations */
- tx_ln_vals = cdns_torrent_get_tbl_vals(&init_data->tx_ln_vals_tbl,
- ref_clk, ref_clk,
- phy_t1, phy_t2, ssc);
- if (tx_ln_vals) {
- reg_pairs = tx_ln_vals->reg_pairs;
- num_regs = tx_ln_vals->num_regs;
- for (i = 0; i < num_lanes; i++) {
- regmap = cdns_phy->regmap_tx_lane_cdb[i + mlane];
- for (j = 0; j < num_regs; j++)
- regmap_write(regmap, reg_pairs[j].off,
- reg_pairs[j].val);
+ /* PMA TX lane registers configurations */
+ tx_ln_vals = cdns_torrent_get_tbl_vals(&init_data->tx_ln_vals_tbl,
+ ref_clk, ref_clk1,
+ phy_t1, phy_t2, ssc);
+ if (tx_ln_vals) {
+ reg_pairs = tx_ln_vals->reg_pairs;
+ num_regs = tx_ln_vals->num_regs;
+ for (i = 0; i < num_lanes; i++) {
+ regmap = cdns_phy->regmap_tx_lane_cdb[i + mlane];
+ for (j = 0; j < num_regs; j++)
+ regmap_write(regmap, reg_pairs[j].off,
+ reg_pairs[j].val);
+ }
}
- }
- /* PMA RX lane registers configurations */
- rx_ln_vals = cdns_torrent_get_tbl_vals(&init_data->rx_ln_vals_tbl,
- ref_clk, ref_clk,
- phy_t1, phy_t2, ssc);
- if (rx_ln_vals) {
- reg_pairs = rx_ln_vals->reg_pairs;
- num_regs = rx_ln_vals->num_regs;
- for (i = 0; i < num_lanes; i++) {
- regmap = cdns_phy->regmap_rx_lane_cdb[i + mlane];
- for (j = 0; j < num_regs; j++)
- regmap_write(regmap, reg_pairs[j].off,
- reg_pairs[j].val);
+ /* PMA RX lane registers configurations */
+ rx_ln_vals = cdns_torrent_get_tbl_vals(&init_data->rx_ln_vals_tbl,
+ ref_clk, ref_clk1,
+ phy_t1, phy_t2, ssc);
+ if (rx_ln_vals) {
+ reg_pairs = rx_ln_vals->reg_pairs;
+ num_regs = rx_ln_vals->num_regs;
+ for (i = 0; i < num_lanes; i++) {
+ regmap = cdns_phy->regmap_rx_lane_cdb[i + mlane];
+ for (j = 0; j < num_regs; j++)
+ regmap_write(regmap, reg_pairs[j].off,
+ reg_pairs[j].val);
+ }
}
- }
- if (phy_t1 == TYPE_DP) {
- ret = cdns_torrent_dp_get_pll(cdns_phy, phy_t2);
- if (ret)
- return ret;
- }
+ if (phy_t1 == TYPE_DP) {
+ ret = cdns_torrent_dp_get_pll(cdns_phy, phy_t2);
+ if (ret)
+ return ret;
+ }
- reset_control_deassert(cdns_phy->phys[node].lnk_rst);
+ reset_control_deassert(cdns_phy->phys[node].lnk_rst);
+ }
}
/* Take the PHY out of reset */
@@ -2660,7 +2732,7 @@ static int cdns_torrent_clk_register(struct cdns_torrent_phy *cdns_phy)
return 0;
}
-static int cdns_torrent_reset(struct cdns_torrent_phy *cdns_phy)
+static int cdns_torrent_of_get_reset(struct cdns_torrent_phy *cdns_phy)
{
struct device *dev = cdns_phy->dev;
@@ -2681,29 +2753,40 @@ static int cdns_torrent_reset(struct cdns_torrent_phy *cdns_phy)
return 0;
}
+static int cdns_torrent_of_get_clk(struct cdns_torrent_phy *cdns_phy)
+{
+ /* refclk: Input reference clock for PLL0 */
+ cdns_phy->clk = devm_clk_get(cdns_phy->dev, "refclk");
+ if (IS_ERR(cdns_phy->clk))
+ return dev_err_probe(cdns_phy->dev, PTR_ERR(cdns_phy->clk),
+ "phy ref clock not found\n");
+
+ /* refclk1: Input reference clock for PLL1 */
+ cdns_phy->clk1 = devm_clk_get_optional(cdns_phy->dev, "pll1_refclk");
+ if (IS_ERR(cdns_phy->clk1))
+ return dev_err_probe(cdns_phy->dev, PTR_ERR(cdns_phy->clk1),
+ "phy PLL1 ref clock not found\n");
+
+ return 0;
+}
+
static int cdns_torrent_clk(struct cdns_torrent_phy *cdns_phy)
{
- struct device *dev = cdns_phy->dev;
+ unsigned long ref_clk1_rate;
unsigned long ref_clk_rate;
int ret;
- cdns_phy->clk = devm_clk_get(dev, "refclk");
- if (IS_ERR(cdns_phy->clk)) {
- dev_err(dev, "phy ref clock not found\n");
- return PTR_ERR(cdns_phy->clk);
- }
-
ret = clk_prepare_enable(cdns_phy->clk);
if (ret) {
- dev_err(cdns_phy->dev, "Failed to prepare ref clock\n");
+ dev_err(cdns_phy->dev, "Failed to prepare ref clock: %d\n", ret);
return ret;
}
ref_clk_rate = clk_get_rate(cdns_phy->clk);
if (!ref_clk_rate) {
dev_err(cdns_phy->dev, "Failed to get ref clock rate\n");
- clk_disable_unprepare(cdns_phy->clk);
- return -EINVAL;
+ ret = -EINVAL;
+ goto disable_clk;
}
switch (ref_clk_rate) {
@@ -2720,12 +2803,54 @@ static int cdns_torrent_clk(struct cdns_torrent_phy *cdns_phy)
cdns_phy->ref_clk_rate = CLK_156_25_MHZ;
break;
default:
- dev_err(cdns_phy->dev, "Invalid Ref Clock Rate\n");
- clk_disable_unprepare(cdns_phy->clk);
- return -EINVAL;
+ dev_err(cdns_phy->dev, "Invalid ref clock rate\n");
+ ret = -EINVAL;
+ goto disable_clk;
+ }
+
+ if (cdns_phy->clk1) {
+ ret = clk_prepare_enable(cdns_phy->clk1);
+ if (ret) {
+ dev_err(cdns_phy->dev, "Failed to prepare PLL1 ref clock: %d\n", ret);
+ goto disable_clk;
+ }
+
+ ref_clk1_rate = clk_get_rate(cdns_phy->clk1);
+ if (!ref_clk1_rate) {
+ dev_err(cdns_phy->dev, "Failed to get PLL1 ref clock rate\n");
+ ret = -EINVAL;
+ goto disable_clk1;
+ }
+
+ switch (ref_clk1_rate) {
+ case REF_CLK_19_2MHZ:
+ cdns_phy->ref_clk1_rate = CLK_19_2_MHZ;
+ break;
+ case REF_CLK_25MHZ:
+ cdns_phy->ref_clk1_rate = CLK_25_MHZ;
+ break;
+ case REF_CLK_100MHZ:
+ cdns_phy->ref_clk1_rate = CLK_100_MHZ;
+ break;
+ case REF_CLK_156_25MHZ:
+ cdns_phy->ref_clk1_rate = CLK_156_25_MHZ;
+ break;
+ default:
+ dev_err(cdns_phy->dev, "Invalid PLL1 ref clock rate\n");
+ ret = -EINVAL;
+ goto disable_clk1;
+ }
+ } else {
+ cdns_phy->ref_clk1_rate = cdns_phy->ref_clk_rate;
}
return 0;
+
+disable_clk1:
+ clk_disable_unprepare(cdns_phy->clk1);
+disable_clk:
+ clk_disable_unprepare(cdns_phy->clk);
+ return ret;
}
static int cdns_torrent_phy_probe(struct platform_device *pdev)
@@ -2737,7 +2862,6 @@ static int cdns_torrent_phy_probe(struct platform_device *pdev)
struct device_node *child;
int ret, subnodes, node = 0, i;
u32 total_num_lanes = 0;
- int already_configured;
u8 init_dp_regmap = 0;
u32 phy_type;
@@ -2753,6 +2877,7 @@ static int cdns_torrent_phy_probe(struct platform_device *pdev)
dev_set_drvdata(dev, cdns_phy);
cdns_phy->dev = dev;
cdns_phy->init_data = data;
+ cdns_phy->protocol_bitmask = 0;
cdns_phy->sd_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(cdns_phy->sd_base))
@@ -2776,13 +2901,17 @@ static int cdns_torrent_phy_probe(struct platform_device *pdev)
if (ret)
return ret;
- regmap_field_read(cdns_phy->phy_pma_cmn_ctrl_1, &already_configured);
+ ret = cdns_torrent_of_get_reset(cdns_phy);
+ if (ret)
+ goto clk_cleanup;
- if (!already_configured) {
- ret = cdns_torrent_reset(cdns_phy);
- if (ret)
- goto clk_cleanup;
+ ret = cdns_torrent_of_get_clk(cdns_phy);
+ if (ret)
+ goto clk_cleanup;
+
+ regmap_field_read(cdns_phy->phy_pma_cmn_ctrl_1, &cdns_phy->already_configured);
+ if (!cdns_phy->already_configured) {
ret = cdns_torrent_clk(cdns_phy);
if (ret)
goto clk_cleanup;
@@ -2862,10 +2991,7 @@ static int cdns_torrent_phy_probe(struct platform_device *pdev)
of_property_read_u32(child, "cdns,ssc-mode",
&cdns_phy->phys[node].ssc_mode);
- if (!already_configured)
- gphy = devm_phy_create(dev, child, &cdns_torrent_phy_ops);
- else
- gphy = devm_phy_create(dev, child, &noop_ops);
+ gphy = devm_phy_create(dev, child, &cdns_torrent_phy_ops);
if (IS_ERR(gphy)) {
ret = PTR_ERR(gphy);
goto put_child;
@@ -2936,6 +3062,7 @@ static int cdns_torrent_phy_probe(struct platform_device *pdev)
}
cdns_phy->phys[node].phy = gphy;
+ cdns_phy->protocol_bitmask |= BIT(cdns_phy->phys[node].phy_type);
phy_set_drvdata(gphy, &cdns_phy->phys[node]);
node++;
@@ -2948,7 +3075,7 @@ static int cdns_torrent_phy_probe(struct platform_device *pdev)
goto put_lnk_rst;
}
- if (cdns_phy->nsubnodes > 1 && !already_configured) {
+ if (cdns_phy->nsubnodes > 1 && !cdns_phy->already_configured) {
ret = cdns_torrent_phy_configure_multilink(cdns_phy);
if (ret)
goto put_lnk_rst;
@@ -2980,6 +3107,7 @@ put_lnk_rst:
reset_control_put(cdns_phy->phys[i].lnk_rst);
of_node_put(child);
reset_control_assert(cdns_phy->apb_rst);
+ clk_disable_unprepare(cdns_phy->clk1);
clk_disable_unprepare(cdns_phy->clk);
clk_cleanup:
cdns_torrent_clk_cleanup(cdns_phy);
@@ -2998,76 +3126,363 @@ static void cdns_torrent_phy_remove(struct platform_device *pdev)
reset_control_put(cdns_phy->phys[i].lnk_rst);
}
+ clk_disable_unprepare(cdns_phy->clk1);
clk_disable_unprepare(cdns_phy->clk);
cdns_torrent_clk_cleanup(cdns_phy);
}
+/* SGMII and QSGMII link configuration */
+static const struct cdns_reg_pairs sgmii_qsgmii_link_cmn_regs[] = {
+ {0x0002, PHY_PLL_CFG}
+};
+
+static const struct cdns_reg_pairs sgmii_qsgmii_xcvr_diag_ln_regs[] = {
+ {0x0003, XCVR_DIAG_HSCLK_DIV},
+ {0x0113, XCVR_DIAG_PLLDRC_CTRL}
+};
+
+static const struct cdns_torrent_vals sgmii_qsgmii_link_cmn_vals = {
+ .reg_pairs = sgmii_qsgmii_link_cmn_regs,
+ .num_regs = ARRAY_SIZE(sgmii_qsgmii_link_cmn_regs),
+};
+
+static const struct cdns_torrent_vals sgmii_qsgmii_xcvr_diag_ln_vals = {
+ .reg_pairs = sgmii_qsgmii_xcvr_diag_ln_regs,
+ .num_regs = ARRAY_SIZE(sgmii_qsgmii_xcvr_diag_ln_regs),
+};
+
+static int cdns_torrent_phy_suspend_noirq(struct device *dev)
+{
+ struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(dev);
+ int i;
+
+ reset_control_assert(cdns_phy->phy_rst);
+ reset_control_assert(cdns_phy->apb_rst);
+ for (i = 0; i < cdns_phy->nsubnodes; i++)
+ reset_control_assert(cdns_phy->phys[i].lnk_rst);
+
+ if (cdns_phy->already_configured)
+ cdns_phy->already_configured = 0;
+ else {
+ clk_disable_unprepare(cdns_phy->clk1);
+ clk_disable_unprepare(cdns_phy->clk);
+ }
+
+ return 0;
+}
+
+static int cdns_torrent_phy_resume_noirq(struct device *dev)
+{
+ struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(dev);
+ int node = cdns_phy->nsubnodes;
+ int ret, i;
+
+ ret = cdns_torrent_clk(cdns_phy);
+ if (ret)
+ return ret;
+
+ /* Enable APB */
+ reset_control_deassert(cdns_phy->apb_rst);
+
+ if (cdns_phy->nsubnodes > 1) {
+ ret = cdns_torrent_phy_configure_multilink(cdns_phy);
+ if (ret)
+ goto put_lnk_rst;
+ }
+
+ return 0;
+
+put_lnk_rst:
+ for (i = 0; i < node; i++)
+ reset_control_assert(cdns_phy->phys[i].lnk_rst);
+ reset_control_assert(cdns_phy->apb_rst);
+
+ clk_disable_unprepare(cdns_phy->clk1);
+ clk_disable_unprepare(cdns_phy->clk);
+
+ return ret;
+}
+
+static DEFINE_NOIRQ_DEV_PM_OPS(cdns_torrent_phy_pm_ops,
+ cdns_torrent_phy_suspend_noirq,
+ cdns_torrent_phy_resume_noirq);
+
/* USB and DP link configuration */
-static struct cdns_reg_pairs usb_dp_link_cmn_regs[] = {
+static const struct cdns_reg_pairs usb_dp_link_cmn_regs[] = {
{0x0002, PHY_PLL_CFG},
{0x8600, CMN_PDIAG_PLL0_CLK_SEL_M0}
};
-static struct cdns_reg_pairs usb_dp_xcvr_diag_ln_regs[] = {
+static const struct cdns_reg_pairs usb_dp_xcvr_diag_ln_regs[] = {
{0x0000, XCVR_DIAG_HSCLK_SEL},
{0x0001, XCVR_DIAG_HSCLK_DIV},
{0x0041, XCVR_DIAG_PLLDRC_CTRL}
};
-static struct cdns_reg_pairs dp_usb_xcvr_diag_ln_regs[] = {
+static const struct cdns_reg_pairs dp_usb_xcvr_diag_ln_regs[] = {
{0x0001, XCVR_DIAG_HSCLK_SEL},
{0x0009, XCVR_DIAG_PLLDRC_CTRL}
};
-static struct cdns_torrent_vals usb_dp_link_cmn_vals = {
+static const struct cdns_torrent_vals usb_dp_link_cmn_vals = {
.reg_pairs = usb_dp_link_cmn_regs,
.num_regs = ARRAY_SIZE(usb_dp_link_cmn_regs),
};
-static struct cdns_torrent_vals usb_dp_xcvr_diag_ln_vals = {
+static const struct cdns_torrent_vals usb_dp_xcvr_diag_ln_vals = {
.reg_pairs = usb_dp_xcvr_diag_ln_regs,
.num_regs = ARRAY_SIZE(usb_dp_xcvr_diag_ln_regs),
};
-static struct cdns_torrent_vals dp_usb_xcvr_diag_ln_vals = {
+static const struct cdns_torrent_vals dp_usb_xcvr_diag_ln_vals = {
.reg_pairs = dp_usb_xcvr_diag_ln_regs,
.num_regs = ARRAY_SIZE(dp_usb_xcvr_diag_ln_regs),
};
+/* USXGMII and SGMII/QSGMII link configuration */
+static const struct cdns_reg_pairs usxgmii_sgmii_link_cmn_regs[] = {
+ {0x0002, PHY_PLL_CFG},
+ {0x0400, CMN_PDIAG_PLL0_CLK_SEL_M0},
+ {0x0601, CMN_PDIAG_PLL1_CLK_SEL_M0}
+};
+
+static const struct cdns_reg_pairs usxgmii_sgmii_xcvr_diag_ln_regs[] = {
+ {0x0000, XCVR_DIAG_HSCLK_SEL},
+ {0x0001, XCVR_DIAG_HSCLK_DIV},
+ {0x0001, XCVR_DIAG_PLLDRC_CTRL}
+};
+
+static const struct cdns_reg_pairs sgmii_usxgmii_xcvr_diag_ln_regs[] = {
+ {0x0111, XCVR_DIAG_HSCLK_SEL},
+ {0x0103, XCVR_DIAG_HSCLK_DIV},
+ {0x0A9B, XCVR_DIAG_PLLDRC_CTRL}
+};
+
+static const struct cdns_torrent_vals usxgmii_sgmii_link_cmn_vals = {
+ .reg_pairs = usxgmii_sgmii_link_cmn_regs,
+ .num_regs = ARRAY_SIZE(usxgmii_sgmii_link_cmn_regs),
+};
+
+static const struct cdns_torrent_vals usxgmii_sgmii_xcvr_diag_ln_vals = {
+ .reg_pairs = usxgmii_sgmii_xcvr_diag_ln_regs,
+ .num_regs = ARRAY_SIZE(usxgmii_sgmii_xcvr_diag_ln_regs),
+};
+
+static const struct cdns_torrent_vals sgmii_usxgmii_xcvr_diag_ln_vals = {
+ .reg_pairs = sgmii_usxgmii_xcvr_diag_ln_regs,
+ .num_regs = ARRAY_SIZE(sgmii_usxgmii_xcvr_diag_ln_regs),
+};
+
+/* Multilink USXGMII, using PLL0, 156.25 MHz Ref clk, no SSC */
+static const struct cdns_reg_pairs ml_usxgmii_pll0_156_25_no_ssc_cmn_regs[] = {
+ {0x0014, CMN_PLL0_DSM_FBH_OVRD_M0},
+ {0x0005, CMN_PLL0_DSM_FBL_OVRD_M0},
+ {0x061B, CMN_PLL0_VCOCAL_INIT_TMR},
+ {0x0019, CMN_PLL0_VCOCAL_ITER_TMR},
+ {0x1354, CMN_PLL0_VCOCAL_REFTIM_START},
+ {0x1354, CMN_PLL0_VCOCAL_PLLCNT_START},
+ {0x0003, CMN_PLL0_VCOCAL_TCTRL},
+ {0x0138, CMN_PLL0_LOCK_REFCNT_START},
+ {0x0138, CMN_PLL0_LOCK_PLLCNT_START}
+};
+
+static const struct cdns_torrent_vals ml_usxgmii_pll0_156_25_no_ssc_cmn_vals = {
+ .reg_pairs = ml_usxgmii_pll0_156_25_no_ssc_cmn_regs,
+ .num_regs = ARRAY_SIZE(ml_usxgmii_pll0_156_25_no_ssc_cmn_regs),
+};
+
+/* Multilink SGMII/QSGMII, using PLL1, 100 MHz Ref clk, no SSC */
+static const struct cdns_reg_pairs ml_sgmii_pll1_100_no_ssc_cmn_regs[] = {
+ {0x0028, CMN_PDIAG_PLL1_CP_PADJ_M0},
+ {0x001E, CMN_PLL1_DSM_FBH_OVRD_M0},
+ {0x000C, CMN_PLL1_DSM_FBL_OVRD_M0},
+ {0x0003, CMN_PLL1_VCOCAL_TCTRL},
+ {0x007F, CMN_TXPUCAL_TUNE},
+ {0x007F, CMN_TXPDCAL_TUNE}
+};
+
+static const struct cdns_torrent_vals ml_sgmii_pll1_100_no_ssc_cmn_vals = {
+ .reg_pairs = ml_sgmii_pll1_100_no_ssc_cmn_regs,
+ .num_regs = ARRAY_SIZE(ml_sgmii_pll1_100_no_ssc_cmn_regs),
+};
+
+/* TI J7200, Multilink USXGMII, using PLL0, 156.25 MHz Ref clk, no SSC */
+static const struct cdns_reg_pairs j7200_ml_usxgmii_pll0_156_25_no_ssc_cmn_regs[] = {
+ {0x0014, CMN_SSM_BIAS_TMR},
+ {0x0028, CMN_PLLSM0_PLLPRE_TMR},
+ {0x00A4, CMN_PLLSM0_PLLLOCK_TMR},
+ {0x0062, CMN_BGCAL_INIT_TMR},
+ {0x0062, CMN_BGCAL_ITER_TMR},
+ {0x0014, CMN_IBCAL_INIT_TMR},
+ {0x0018, CMN_TXPUCAL_INIT_TMR},
+ {0x0005, CMN_TXPUCAL_ITER_TMR},
+ {0x0018, CMN_TXPDCAL_INIT_TMR},
+ {0x0005, CMN_TXPDCAL_ITER_TMR},
+ {0x024A, CMN_RXCAL_INIT_TMR},
+ {0x0005, CMN_RXCAL_ITER_TMR},
+ {0x000B, CMN_SD_CAL_REFTIM_START},
+ {0x0132, CMN_SD_CAL_PLLCNT_START},
+ {0x0014, CMN_PLL0_DSM_FBH_OVRD_M0},
+ {0x0005, CMN_PLL0_DSM_FBL_OVRD_M0},
+ {0x061B, CMN_PLL0_VCOCAL_INIT_TMR},
+ {0x0019, CMN_PLL0_VCOCAL_ITER_TMR},
+ {0x1354, CMN_PLL0_VCOCAL_REFTIM_START},
+ {0x1354, CMN_PLL0_VCOCAL_PLLCNT_START},
+ {0x0003, CMN_PLL0_VCOCAL_TCTRL},
+ {0x0138, CMN_PLL0_LOCK_REFCNT_START},
+ {0x0138, CMN_PLL0_LOCK_PLLCNT_START}
+};
+
+static const struct cdns_torrent_vals j7200_ml_usxgmii_pll0_156_25_no_ssc_cmn_vals = {
+ .reg_pairs = j7200_ml_usxgmii_pll0_156_25_no_ssc_cmn_regs,
+ .num_regs = ARRAY_SIZE(j7200_ml_usxgmii_pll0_156_25_no_ssc_cmn_regs),
+};
+
+/* TI J7200, Multilink SGMII/QSGMII, using PLL1, 100 MHz Ref clk, no SSC */
+static const struct cdns_reg_pairs j7200_ml_sgmii_pll1_100_no_ssc_cmn_regs[] = {
+ {0x0028, CMN_PLLSM1_PLLPRE_TMR},
+ {0x00A4, CMN_PLLSM1_PLLLOCK_TMR},
+ {0x0028, CMN_PDIAG_PLL1_CP_PADJ_M0},
+ {0x001E, CMN_PLL1_DSM_FBH_OVRD_M0},
+ {0x000C, CMN_PLL1_DSM_FBL_OVRD_M0},
+ {0x0003, CMN_PLL1_VCOCAL_TCTRL},
+ {0x007F, CMN_TXPUCAL_TUNE},
+ {0x007F, CMN_TXPDCAL_TUNE}
+};
+
+static const struct cdns_torrent_vals j7200_ml_sgmii_pll1_100_no_ssc_cmn_vals = {
+ .reg_pairs = j7200_ml_sgmii_pll1_100_no_ssc_cmn_regs,
+ .num_regs = ARRAY_SIZE(j7200_ml_sgmii_pll1_100_no_ssc_cmn_regs),
+};
+
+/* PCIe and USXGMII link configuration */
+static const struct cdns_reg_pairs pcie_usxgmii_link_cmn_regs[] = {
+ {0x0003, PHY_PLL_CFG},
+ {0x0601, CMN_PDIAG_PLL0_CLK_SEL_M0},
+ {0x0400, CMN_PDIAG_PLL0_CLK_SEL_M1},
+ {0x0400, CMN_PDIAG_PLL1_CLK_SEL_M0}
+};
+
+static const struct cdns_reg_pairs pcie_usxgmii_xcvr_diag_ln_regs[] = {
+ {0x0000, XCVR_DIAG_HSCLK_SEL},
+ {0x0001, XCVR_DIAG_HSCLK_DIV},
+ {0x0012, XCVR_DIAG_PLLDRC_CTRL}
+};
+
+static const struct cdns_reg_pairs usxgmii_pcie_xcvr_diag_ln_regs[] = {
+ {0x0011, XCVR_DIAG_HSCLK_SEL},
+ {0x0001, XCVR_DIAG_HSCLK_DIV},
+ {0x0089, XCVR_DIAG_PLLDRC_CTRL}
+};
+
+static const struct cdns_torrent_vals pcie_usxgmii_link_cmn_vals = {
+ .reg_pairs = pcie_usxgmii_link_cmn_regs,
+ .num_regs = ARRAY_SIZE(pcie_usxgmii_link_cmn_regs),
+};
+
+static const struct cdns_torrent_vals pcie_usxgmii_xcvr_diag_ln_vals = {
+ .reg_pairs = pcie_usxgmii_xcvr_diag_ln_regs,
+ .num_regs = ARRAY_SIZE(pcie_usxgmii_xcvr_diag_ln_regs),
+};
+
+static const struct cdns_torrent_vals usxgmii_pcie_xcvr_diag_ln_vals = {
+ .reg_pairs = usxgmii_pcie_xcvr_diag_ln_regs,
+ .num_regs = ARRAY_SIZE(usxgmii_pcie_xcvr_diag_ln_regs),
+};
+
+/*
+ * Multilink USXGMII, using PLL1, 156.25 MHz Ref clk, no SSC
+ */
+static const struct cdns_reg_pairs ml_usxgmii_pll1_156_25_no_ssc_cmn_regs[] = {
+ {0x0028, CMN_PDIAG_PLL1_CP_PADJ_M0},
+ {0x0014, CMN_PLL1_DSM_FBH_OVRD_M0},
+ {0x0005, CMN_PLL1_DSM_FBL_OVRD_M0},
+ {0x061B, CMN_PLL1_VCOCAL_INIT_TMR},
+ {0x0019, CMN_PLL1_VCOCAL_ITER_TMR},
+ {0x1354, CMN_PLL1_VCOCAL_REFTIM_START},
+ {0x1354, CMN_PLL1_VCOCAL_PLLCNT_START},
+ {0x0003, CMN_PLL1_VCOCAL_TCTRL},
+ {0x0138, CMN_PLL1_LOCK_REFCNT_START},
+ {0x0138, CMN_PLL1_LOCK_PLLCNT_START},
+ {0x007F, CMN_TXPUCAL_TUNE},
+ {0x007F, CMN_TXPDCAL_TUNE}
+};
+
+static const struct cdns_reg_pairs ml_usxgmii_156_25_no_ssc_tx_ln_regs[] = {
+ {0x00F3, TX_PSC_A0},
+ {0x04A2, TX_PSC_A2},
+ {0x04A2, TX_PSC_A3 },
+ {0x0000, TX_TXCC_CPOST_MULT_00},
+ {0x0000, XCVR_DIAG_PSC_OVRD}
+};
+
+static const struct cdns_reg_pairs ml_usxgmii_156_25_no_ssc_rx_ln_regs[] = {
+ {0x091D, RX_PSC_A0},
+ {0x0900, RX_PSC_A2},
+ {0x0100, RX_PSC_A3},
+ {0x0030, RX_REE_SMGM_CTRL1},
+ {0x03C7, RX_REE_GCSM1_EQENM_PH1},
+ {0x01C7, RX_REE_GCSM1_EQENM_PH2},
+ {0x0000, RX_DIAG_DFE_CTRL},
+ {0x0019, RX_REE_TAP1_CLIP},
+ {0x0019, RX_REE_TAP2TON_CLIP},
+ {0x00B9, RX_DIAG_NQST_CTRL},
+ {0x0C21, RX_DIAG_DFE_AMP_TUNE_2},
+ {0x0002, RX_DIAG_DFE_AMP_TUNE_3},
+ {0x0033, RX_DIAG_PI_RATE},
+ {0x0001, RX_DIAG_ACYA},
+ {0x018C, RX_CDRLF_CNFG}
+};
+
+static const struct cdns_torrent_vals ml_usxgmii_pll1_156_25_no_ssc_cmn_vals = {
+ .reg_pairs = ml_usxgmii_pll1_156_25_no_ssc_cmn_regs,
+ .num_regs = ARRAY_SIZE(ml_usxgmii_pll1_156_25_no_ssc_cmn_regs),
+};
+
+static const struct cdns_torrent_vals ml_usxgmii_156_25_no_ssc_tx_ln_vals = {
+ .reg_pairs = ml_usxgmii_156_25_no_ssc_tx_ln_regs,
+ .num_regs = ARRAY_SIZE(ml_usxgmii_156_25_no_ssc_tx_ln_regs),
+};
+
+static const struct cdns_torrent_vals ml_usxgmii_156_25_no_ssc_rx_ln_vals = {
+ .reg_pairs = ml_usxgmii_156_25_no_ssc_rx_ln_regs,
+ .num_regs = ARRAY_SIZE(ml_usxgmii_156_25_no_ssc_rx_ln_regs),
+};
+
/* TI USXGMII configuration: Enable cmn_refclk_rcv_out_en */
-static struct cdns_reg_pairs ti_usxgmii_phy_pma_cmn_regs[] = {
+static const struct cdns_reg_pairs ti_usxgmii_phy_pma_cmn_regs[] = {
{0x0040, PHY_PMA_CMN_CTRL1},
};
-static struct cdns_torrent_vals ti_usxgmii_phy_pma_cmn_vals = {
+static const struct cdns_torrent_vals ti_usxgmii_phy_pma_cmn_vals = {
.reg_pairs = ti_usxgmii_phy_pma_cmn_regs,
.num_regs = ARRAY_SIZE(ti_usxgmii_phy_pma_cmn_regs),
};
/* Single USXGMII link configuration */
-static struct cdns_reg_pairs sl_usxgmii_link_cmn_regs[] = {
+static const struct cdns_reg_pairs sl_usxgmii_link_cmn_regs[] = {
{0x0000, PHY_PLL_CFG},
{0x0400, CMN_PDIAG_PLL0_CLK_SEL_M0}
};
-static struct cdns_reg_pairs sl_usxgmii_xcvr_diag_ln_regs[] = {
+static const struct cdns_reg_pairs sl_usxgmii_xcvr_diag_ln_regs[] = {
{0x0000, XCVR_DIAG_HSCLK_SEL},
{0x0001, XCVR_DIAG_HSCLK_DIV},
{0x0001, XCVR_DIAG_PLLDRC_CTRL}
};
-static struct cdns_torrent_vals sl_usxgmii_link_cmn_vals = {
+static const struct cdns_torrent_vals sl_usxgmii_link_cmn_vals = {
.reg_pairs = sl_usxgmii_link_cmn_regs,
.num_regs = ARRAY_SIZE(sl_usxgmii_link_cmn_regs),
};
-static struct cdns_torrent_vals sl_usxgmii_xcvr_diag_ln_vals = {
+static const struct cdns_torrent_vals sl_usxgmii_xcvr_diag_ln_vals = {
.reg_pairs = sl_usxgmii_xcvr_diag_ln_regs,
.num_regs = ARRAY_SIZE(sl_usxgmii_xcvr_diag_ln_regs),
};
/* Single link USXGMII, 156.25 MHz Ref clk, no SSC */
-static struct cdns_reg_pairs sl_usxgmii_156_25_no_ssc_cmn_regs[] = {
+static const struct cdns_reg_pairs sl_usxgmii_156_25_no_ssc_cmn_regs[] = {
{0x0014, CMN_SSM_BIAS_TMR},
{0x0028, CMN_PLLSM0_PLLPRE_TMR},
{0x00A4, CMN_PLLSM0_PLLLOCK_TMR},
@@ -3105,7 +3520,7 @@ static struct cdns_reg_pairs sl_usxgmii_156_25_no_ssc_cmn_regs[] = {
{0x0138, CMN_PLL1_LOCK_PLLCNT_START}
};
-static struct cdns_reg_pairs usxgmii_156_25_no_ssc_tx_ln_regs[] = {
+static const struct cdns_reg_pairs usxgmii_156_25_no_ssc_tx_ln_regs[] = {
{0x07A2, TX_RCVDET_ST_TMR},
{0x00F3, TX_PSC_A0},
{0x04A2, TX_PSC_A2},
@@ -3114,7 +3529,7 @@ static struct cdns_reg_pairs usxgmii_156_25_no_ssc_tx_ln_regs[] = {
{0x0000, XCVR_DIAG_PSC_OVRD}
};
-static struct cdns_reg_pairs usxgmii_156_25_no_ssc_rx_ln_regs[] = {
+static const struct cdns_reg_pairs usxgmii_156_25_no_ssc_rx_ln_regs[] = {
{0x0014, RX_SDCAL0_INIT_TMR},
{0x0062, RX_SDCAL0_ITER_TMR},
{0x0014, RX_SDCAL1_INIT_TMR},
@@ -3136,68 +3551,68 @@ static struct cdns_reg_pairs usxgmii_156_25_no_ssc_rx_ln_regs[] = {
{0x018C, RX_CDRLF_CNFG}
};
-static struct cdns_torrent_vals sl_usxgmii_156_25_no_ssc_cmn_vals = {
+static const struct cdns_torrent_vals sl_usxgmii_156_25_no_ssc_cmn_vals = {
.reg_pairs = sl_usxgmii_156_25_no_ssc_cmn_regs,
.num_regs = ARRAY_SIZE(sl_usxgmii_156_25_no_ssc_cmn_regs),
};
-static struct cdns_torrent_vals usxgmii_156_25_no_ssc_tx_ln_vals = {
+static const struct cdns_torrent_vals usxgmii_156_25_no_ssc_tx_ln_vals = {
.reg_pairs = usxgmii_156_25_no_ssc_tx_ln_regs,
.num_regs = ARRAY_SIZE(usxgmii_156_25_no_ssc_tx_ln_regs),
};
-static struct cdns_torrent_vals usxgmii_156_25_no_ssc_rx_ln_vals = {
+static const struct cdns_torrent_vals usxgmii_156_25_no_ssc_rx_ln_vals = {
.reg_pairs = usxgmii_156_25_no_ssc_rx_ln_regs,
.num_regs = ARRAY_SIZE(usxgmii_156_25_no_ssc_rx_ln_regs),
};
/* PCIe and DP link configuration */
-static struct cdns_reg_pairs pcie_dp_link_cmn_regs[] = {
+static const struct cdns_reg_pairs pcie_dp_link_cmn_regs[] = {
{0x0003, PHY_PLL_CFG},
{0x0601, CMN_PDIAG_PLL0_CLK_SEL_M0},
{0x0400, CMN_PDIAG_PLL0_CLK_SEL_M1}
};
-static struct cdns_reg_pairs pcie_dp_xcvr_diag_ln_regs[] = {
+static const struct cdns_reg_pairs pcie_dp_xcvr_diag_ln_regs[] = {
{0x0000, XCVR_DIAG_HSCLK_SEL},
{0x0001, XCVR_DIAG_HSCLK_DIV},
{0x0012, XCVR_DIAG_PLLDRC_CTRL}
};
-static struct cdns_reg_pairs dp_pcie_xcvr_diag_ln_regs[] = {
+static const struct cdns_reg_pairs dp_pcie_xcvr_diag_ln_regs[] = {
{0x0001, XCVR_DIAG_HSCLK_SEL},
{0x0009, XCVR_DIAG_PLLDRC_CTRL}
};
-static struct cdns_torrent_vals pcie_dp_link_cmn_vals = {
+static const struct cdns_torrent_vals pcie_dp_link_cmn_vals = {
.reg_pairs = pcie_dp_link_cmn_regs,
.num_regs = ARRAY_SIZE(pcie_dp_link_cmn_regs),
};
-static struct cdns_torrent_vals pcie_dp_xcvr_diag_ln_vals = {
+static const struct cdns_torrent_vals pcie_dp_xcvr_diag_ln_vals = {
.reg_pairs = pcie_dp_xcvr_diag_ln_regs,
.num_regs = ARRAY_SIZE(pcie_dp_xcvr_diag_ln_regs),
};
-static struct cdns_torrent_vals dp_pcie_xcvr_diag_ln_vals = {
+static const struct cdns_torrent_vals dp_pcie_xcvr_diag_ln_vals = {
.reg_pairs = dp_pcie_xcvr_diag_ln_regs,
.num_regs = ARRAY_SIZE(dp_pcie_xcvr_diag_ln_regs),
};
/* DP Multilink, 100 MHz Ref clk, no SSC */
-static struct cdns_reg_pairs dp_100_no_ssc_cmn_regs[] = {
+static const struct cdns_reg_pairs dp_100_no_ssc_cmn_regs[] = {
{0x007F, CMN_TXPUCAL_TUNE},
{0x007F, CMN_TXPDCAL_TUNE}
};
-static struct cdns_reg_pairs dp_100_no_ssc_tx_ln_regs[] = {
+static const struct cdns_reg_pairs dp_100_no_ssc_tx_ln_regs[] = {
{0x00FB, TX_PSC_A0},
{0x04AA, TX_PSC_A2},
{0x04AA, TX_PSC_A3},
{0x000F, XCVR_DIAG_BIDI_CTRL}
};
-static struct cdns_reg_pairs dp_100_no_ssc_rx_ln_regs[] = {
+static const struct cdns_reg_pairs dp_100_no_ssc_rx_ln_regs[] = {
{0x0000, RX_PSC_A0},
{0x0000, RX_PSC_A2},
{0x0000, RX_PSC_A3},
@@ -3207,43 +3622,43 @@ static struct cdns_reg_pairs dp_100_no_ssc_rx_ln_regs[] = {
{0x0000, RX_REE_PERGCSM_CTRL}
};
-static struct cdns_torrent_vals dp_100_no_ssc_cmn_vals = {
+static const struct cdns_torrent_vals dp_100_no_ssc_cmn_vals = {
.reg_pairs = dp_100_no_ssc_cmn_regs,
.num_regs = ARRAY_SIZE(dp_100_no_ssc_cmn_regs),
};
-static struct cdns_torrent_vals dp_100_no_ssc_tx_ln_vals = {
+static const struct cdns_torrent_vals dp_100_no_ssc_tx_ln_vals = {
.reg_pairs = dp_100_no_ssc_tx_ln_regs,
.num_regs = ARRAY_SIZE(dp_100_no_ssc_tx_ln_regs),
};
-static struct cdns_torrent_vals dp_100_no_ssc_rx_ln_vals = {
+static const struct cdns_torrent_vals dp_100_no_ssc_rx_ln_vals = {
.reg_pairs = dp_100_no_ssc_rx_ln_regs,
.num_regs = ARRAY_SIZE(dp_100_no_ssc_rx_ln_regs),
};
/* Single DisplayPort(DP) link configuration */
-static struct cdns_reg_pairs sl_dp_link_cmn_regs[] = {
+static const struct cdns_reg_pairs sl_dp_link_cmn_regs[] = {
{0x0000, PHY_PLL_CFG},
};
-static struct cdns_reg_pairs sl_dp_xcvr_diag_ln_regs[] = {
+static const struct cdns_reg_pairs sl_dp_xcvr_diag_ln_regs[] = {
{0x0000, XCVR_DIAG_HSCLK_SEL},
{0x0001, XCVR_DIAG_PLLDRC_CTRL}
};
-static struct cdns_torrent_vals sl_dp_link_cmn_vals = {
+static const struct cdns_torrent_vals sl_dp_link_cmn_vals = {
.reg_pairs = sl_dp_link_cmn_regs,
.num_regs = ARRAY_SIZE(sl_dp_link_cmn_regs),
};
-static struct cdns_torrent_vals sl_dp_xcvr_diag_ln_vals = {
+static const struct cdns_torrent_vals sl_dp_xcvr_diag_ln_vals = {
.reg_pairs = sl_dp_xcvr_diag_ln_regs,
.num_regs = ARRAY_SIZE(sl_dp_xcvr_diag_ln_regs),
};
/* Single DP, 19.2 MHz Ref clk, no SSC */
-static struct cdns_reg_pairs sl_dp_19_2_no_ssc_cmn_regs[] = {
+static const struct cdns_reg_pairs sl_dp_19_2_no_ssc_cmn_regs[] = {
{0x0014, CMN_SSM_BIAS_TMR},
{0x0027, CMN_PLLSM0_PLLPRE_TMR},
{0x00A1, CMN_PLLSM0_PLLLOCK_TMR},
@@ -3280,7 +3695,7 @@ static struct cdns_reg_pairs sl_dp_19_2_no_ssc_cmn_regs[] = {
{0x0003, CMN_PLL1_VCOCAL_TCTRL}
};
-static struct cdns_reg_pairs sl_dp_19_2_no_ssc_tx_ln_regs[] = {
+static const struct cdns_reg_pairs sl_dp_19_2_no_ssc_tx_ln_regs[] = {
{0x0780, TX_RCVDET_ST_TMR},
{0x00FB, TX_PSC_A0},
{0x04AA, TX_PSC_A2},
@@ -3288,7 +3703,7 @@ static struct cdns_reg_pairs sl_dp_19_2_no_ssc_tx_ln_regs[] = {
{0x000F, XCVR_DIAG_BIDI_CTRL}
};
-static struct cdns_reg_pairs sl_dp_19_2_no_ssc_rx_ln_regs[] = {
+static const struct cdns_reg_pairs sl_dp_19_2_no_ssc_rx_ln_regs[] = {
{0x0000, RX_PSC_A0},
{0x0000, RX_PSC_A2},
{0x0000, RX_PSC_A3},
@@ -3298,23 +3713,23 @@ static struct cdns_reg_pairs sl_dp_19_2_no_ssc_rx_ln_regs[] = {
{0x0000, RX_REE_PERGCSM_CTRL}
};
-static struct cdns_torrent_vals sl_dp_19_2_no_ssc_cmn_vals = {
+static const struct cdns_torrent_vals sl_dp_19_2_no_ssc_cmn_vals = {
.reg_pairs = sl_dp_19_2_no_ssc_cmn_regs,
.num_regs = ARRAY_SIZE(sl_dp_19_2_no_ssc_cmn_regs),
};
-static struct cdns_torrent_vals sl_dp_19_2_no_ssc_tx_ln_vals = {
+static const struct cdns_torrent_vals sl_dp_19_2_no_ssc_tx_ln_vals = {
.reg_pairs = sl_dp_19_2_no_ssc_tx_ln_regs,
.num_regs = ARRAY_SIZE(sl_dp_19_2_no_ssc_tx_ln_regs),
};
-static struct cdns_torrent_vals sl_dp_19_2_no_ssc_rx_ln_vals = {
+static const struct cdns_torrent_vals sl_dp_19_2_no_ssc_rx_ln_vals = {
.reg_pairs = sl_dp_19_2_no_ssc_rx_ln_regs,
.num_regs = ARRAY_SIZE(sl_dp_19_2_no_ssc_rx_ln_regs),
};
/* Single DP, 25 MHz Ref clk, no SSC */
-static struct cdns_reg_pairs sl_dp_25_no_ssc_cmn_regs[] = {
+static const struct cdns_reg_pairs sl_dp_25_no_ssc_cmn_regs[] = {
{0x0019, CMN_SSM_BIAS_TMR},
{0x0032, CMN_PLLSM0_PLLPRE_TMR},
{0x00D1, CMN_PLLSM0_PLLLOCK_TMR},
@@ -3351,7 +3766,7 @@ static struct cdns_reg_pairs sl_dp_25_no_ssc_cmn_regs[] = {
{0x0003, CMN_PLL1_VCOCAL_TCTRL}
};
-static struct cdns_reg_pairs sl_dp_25_no_ssc_tx_ln_regs[] = {
+static const struct cdns_reg_pairs sl_dp_25_no_ssc_tx_ln_regs[] = {
{0x09C4, TX_RCVDET_ST_TMR},
{0x00FB, TX_PSC_A0},
{0x04AA, TX_PSC_A2},
@@ -3359,7 +3774,7 @@ static struct cdns_reg_pairs sl_dp_25_no_ssc_tx_ln_regs[] = {
{0x000F, XCVR_DIAG_BIDI_CTRL}
};
-static struct cdns_reg_pairs sl_dp_25_no_ssc_rx_ln_regs[] = {
+static const struct cdns_reg_pairs sl_dp_25_no_ssc_rx_ln_regs[] = {
{0x0000, RX_PSC_A0},
{0x0000, RX_PSC_A2},
{0x0000, RX_PSC_A3},
@@ -3369,35 +3784,35 @@ static struct cdns_reg_pairs sl_dp_25_no_ssc_rx_ln_regs[] = {
{0x0000, RX_REE_PERGCSM_CTRL}
};
-static struct cdns_torrent_vals sl_dp_25_no_ssc_cmn_vals = {
+static const struct cdns_torrent_vals sl_dp_25_no_ssc_cmn_vals = {
.reg_pairs = sl_dp_25_no_ssc_cmn_regs,
.num_regs = ARRAY_SIZE(sl_dp_25_no_ssc_cmn_regs),
};
-static struct cdns_torrent_vals sl_dp_25_no_ssc_tx_ln_vals = {
+static const struct cdns_torrent_vals sl_dp_25_no_ssc_tx_ln_vals = {
.reg_pairs = sl_dp_25_no_ssc_tx_ln_regs,
.num_regs = ARRAY_SIZE(sl_dp_25_no_ssc_tx_ln_regs),
};
-static struct cdns_torrent_vals sl_dp_25_no_ssc_rx_ln_vals = {
+static const struct cdns_torrent_vals sl_dp_25_no_ssc_rx_ln_vals = {
.reg_pairs = sl_dp_25_no_ssc_rx_ln_regs,
.num_regs = ARRAY_SIZE(sl_dp_25_no_ssc_rx_ln_regs),
};
/* Single DP, 100 MHz Ref clk, no SSC */
-static struct cdns_reg_pairs sl_dp_100_no_ssc_cmn_regs[] = {
+static const struct cdns_reg_pairs sl_dp_100_no_ssc_cmn_regs[] = {
{0x0003, CMN_PLL0_VCOCAL_TCTRL},
{0x0003, CMN_PLL1_VCOCAL_TCTRL}
};
-static struct cdns_reg_pairs sl_dp_100_no_ssc_tx_ln_regs[] = {
+static const struct cdns_reg_pairs sl_dp_100_no_ssc_tx_ln_regs[] = {
{0x00FB, TX_PSC_A0},
{0x04AA, TX_PSC_A2},
{0x04AA, TX_PSC_A3},
{0x000F, XCVR_DIAG_BIDI_CTRL}
};
-static struct cdns_reg_pairs sl_dp_100_no_ssc_rx_ln_regs[] = {
+static const struct cdns_reg_pairs sl_dp_100_no_ssc_rx_ln_regs[] = {
{0x0000, RX_PSC_A0},
{0x0000, RX_PSC_A2},
{0x0000, RX_PSC_A3},
@@ -3407,92 +3822,92 @@ static struct cdns_reg_pairs sl_dp_100_no_ssc_rx_ln_regs[] = {
{0x0000, RX_REE_PERGCSM_CTRL}
};
-static struct cdns_torrent_vals sl_dp_100_no_ssc_cmn_vals = {
+static const struct cdns_torrent_vals sl_dp_100_no_ssc_cmn_vals = {
.reg_pairs = sl_dp_100_no_ssc_cmn_regs,
.num_regs = ARRAY_SIZE(sl_dp_100_no_ssc_cmn_regs),
};
-static struct cdns_torrent_vals sl_dp_100_no_ssc_tx_ln_vals = {
+static const struct cdns_torrent_vals sl_dp_100_no_ssc_tx_ln_vals = {
.reg_pairs = sl_dp_100_no_ssc_tx_ln_regs,
.num_regs = ARRAY_SIZE(sl_dp_100_no_ssc_tx_ln_regs),
};
-static struct cdns_torrent_vals sl_dp_100_no_ssc_rx_ln_vals = {
+static const struct cdns_torrent_vals sl_dp_100_no_ssc_rx_ln_vals = {
.reg_pairs = sl_dp_100_no_ssc_rx_ln_regs,
.num_regs = ARRAY_SIZE(sl_dp_100_no_ssc_rx_ln_regs),
};
/* USB and SGMII/QSGMII link configuration */
-static struct cdns_reg_pairs usb_sgmii_link_cmn_regs[] = {
+static const struct cdns_reg_pairs usb_sgmii_link_cmn_regs[] = {
{0x0002, PHY_PLL_CFG},
{0x8600, CMN_PDIAG_PLL0_CLK_SEL_M0},
{0x0601, CMN_PDIAG_PLL1_CLK_SEL_M0}
};
-static struct cdns_reg_pairs usb_sgmii_xcvr_diag_ln_regs[] = {
+static const struct cdns_reg_pairs usb_sgmii_xcvr_diag_ln_regs[] = {
{0x0000, XCVR_DIAG_HSCLK_SEL},
{0x0001, XCVR_DIAG_HSCLK_DIV},
{0x0041, XCVR_DIAG_PLLDRC_CTRL}
};
-static struct cdns_reg_pairs sgmii_usb_xcvr_diag_ln_regs[] = {
+static const struct cdns_reg_pairs sgmii_usb_xcvr_diag_ln_regs[] = {
{0x0011, XCVR_DIAG_HSCLK_SEL},
{0x0003, XCVR_DIAG_HSCLK_DIV},
{0x009B, XCVR_DIAG_PLLDRC_CTRL}
};
-static struct cdns_torrent_vals usb_sgmii_link_cmn_vals = {
+static const struct cdns_torrent_vals usb_sgmii_link_cmn_vals = {
.reg_pairs = usb_sgmii_link_cmn_regs,
.num_regs = ARRAY_SIZE(usb_sgmii_link_cmn_regs),
};
-static struct cdns_torrent_vals usb_sgmii_xcvr_diag_ln_vals = {
+static const struct cdns_torrent_vals usb_sgmii_xcvr_diag_ln_vals = {
.reg_pairs = usb_sgmii_xcvr_diag_ln_regs,
.num_regs = ARRAY_SIZE(usb_sgmii_xcvr_diag_ln_regs),
};
-static struct cdns_torrent_vals sgmii_usb_xcvr_diag_ln_vals = {
+static const struct cdns_torrent_vals sgmii_usb_xcvr_diag_ln_vals = {
.reg_pairs = sgmii_usb_xcvr_diag_ln_regs,
.num_regs = ARRAY_SIZE(sgmii_usb_xcvr_diag_ln_regs),
};
/* PCIe and USB Unique SSC link configuration */
-static struct cdns_reg_pairs pcie_usb_link_cmn_regs[] = {
+static const struct cdns_reg_pairs pcie_usb_link_cmn_regs[] = {
{0x0003, PHY_PLL_CFG},
{0x0601, CMN_PDIAG_PLL0_CLK_SEL_M0},
{0x0400, CMN_PDIAG_PLL0_CLK_SEL_M1},
{0x8600, CMN_PDIAG_PLL1_CLK_SEL_M0}
};
-static struct cdns_reg_pairs pcie_usb_xcvr_diag_ln_regs[] = {
+static const struct cdns_reg_pairs pcie_usb_xcvr_diag_ln_regs[] = {
{0x0000, XCVR_DIAG_HSCLK_SEL},
{0x0001, XCVR_DIAG_HSCLK_DIV},
{0x0012, XCVR_DIAG_PLLDRC_CTRL}
};
-static struct cdns_reg_pairs usb_pcie_xcvr_diag_ln_regs[] = {
+static const struct cdns_reg_pairs usb_pcie_xcvr_diag_ln_regs[] = {
{0x0011, XCVR_DIAG_HSCLK_SEL},
{0x0001, XCVR_DIAG_HSCLK_DIV},
{0x00C9, XCVR_DIAG_PLLDRC_CTRL}
};
-static struct cdns_torrent_vals pcie_usb_link_cmn_vals = {
+static const struct cdns_torrent_vals pcie_usb_link_cmn_vals = {
.reg_pairs = pcie_usb_link_cmn_regs,
.num_regs = ARRAY_SIZE(pcie_usb_link_cmn_regs),
};
-static struct cdns_torrent_vals pcie_usb_xcvr_diag_ln_vals = {
+static const struct cdns_torrent_vals pcie_usb_xcvr_diag_ln_vals = {
.reg_pairs = pcie_usb_xcvr_diag_ln_regs,
.num_regs = ARRAY_SIZE(pcie_usb_xcvr_diag_ln_regs),
};
-static struct cdns_torrent_vals usb_pcie_xcvr_diag_ln_vals = {
+static const struct cdns_torrent_vals usb_pcie_xcvr_diag_ln_vals = {
.reg_pairs = usb_pcie_xcvr_diag_ln_regs,
.num_regs = ARRAY_SIZE(usb_pcie_xcvr_diag_ln_regs),
};
/* USB 100 MHz Ref clk, internal SSC */
-static struct cdns_reg_pairs usb_100_int_ssc_cmn_regs[] = {
+static const struct cdns_reg_pairs usb_100_int_ssc_cmn_regs[] = {
{0x0004, CMN_PLL0_DSM_DIAG_M0},
{0x0004, CMN_PLL0_DSM_DIAG_M1},
{0x0004, CMN_PLL1_DSM_DIAG_M0},
@@ -3545,47 +3960,47 @@ static struct cdns_reg_pairs usb_100_int_ssc_cmn_regs[] = {
{0x007F, CMN_TXPDCAL_TUNE}
};
-static struct cdns_torrent_vals usb_100_int_ssc_cmn_vals = {
+static const struct cdns_torrent_vals usb_100_int_ssc_cmn_vals = {
.reg_pairs = usb_100_int_ssc_cmn_regs,
.num_regs = ARRAY_SIZE(usb_100_int_ssc_cmn_regs),
};
/* Single USB link configuration */
-static struct cdns_reg_pairs sl_usb_link_cmn_regs[] = {
+static const struct cdns_reg_pairs sl_usb_link_cmn_regs[] = {
{0x0000, PHY_PLL_CFG},
{0x8600, CMN_PDIAG_PLL0_CLK_SEL_M0}
};
-static struct cdns_reg_pairs sl_usb_xcvr_diag_ln_regs[] = {
+static const struct cdns_reg_pairs sl_usb_xcvr_diag_ln_regs[] = {
{0x0000, XCVR_DIAG_HSCLK_SEL},
{0x0001, XCVR_DIAG_HSCLK_DIV},
{0x0041, XCVR_DIAG_PLLDRC_CTRL}
};
-static struct cdns_torrent_vals sl_usb_link_cmn_vals = {
+static const struct cdns_torrent_vals sl_usb_link_cmn_vals = {
.reg_pairs = sl_usb_link_cmn_regs,
.num_regs = ARRAY_SIZE(sl_usb_link_cmn_regs),
};
-static struct cdns_torrent_vals sl_usb_xcvr_diag_ln_vals = {
+static const struct cdns_torrent_vals sl_usb_xcvr_diag_ln_vals = {
.reg_pairs = sl_usb_xcvr_diag_ln_regs,
.num_regs = ARRAY_SIZE(sl_usb_xcvr_diag_ln_regs),
};
/* USB PHY PCS common configuration */
-static struct cdns_reg_pairs usb_phy_pcs_cmn_regs[] = {
+static const struct cdns_reg_pairs usb_phy_pcs_cmn_regs[] = {
{0x0A0A, PHY_PIPE_USB3_GEN2_PRE_CFG0},
{0x1000, PHY_PIPE_USB3_GEN2_POST_CFG0},
{0x0010, PHY_PIPE_USB3_GEN2_POST_CFG1}
};
-static struct cdns_torrent_vals usb_phy_pcs_cmn_vals = {
+static const struct cdns_torrent_vals usb_phy_pcs_cmn_vals = {
.reg_pairs = usb_phy_pcs_cmn_regs,
.num_regs = ARRAY_SIZE(usb_phy_pcs_cmn_regs),
};
/* USB 100 MHz Ref clk, no SSC */
-static struct cdns_reg_pairs sl_usb_100_no_ssc_cmn_regs[] = {
+static const struct cdns_reg_pairs sl_usb_100_no_ssc_cmn_regs[] = {
{0x0028, CMN_PDIAG_PLL1_CP_PADJ_M0},
{0x001E, CMN_PLL1_DSM_FBH_OVRD_M0},
{0x000C, CMN_PLL1_DSM_FBL_OVRD_M0},
@@ -3595,19 +4010,19 @@ static struct cdns_reg_pairs sl_usb_100_no_ssc_cmn_regs[] = {
{0x8200, CMN_CDIAG_XCVRC_PWRI_OVRD}
};
-static struct cdns_torrent_vals sl_usb_100_no_ssc_cmn_vals = {
+static const struct cdns_torrent_vals sl_usb_100_no_ssc_cmn_vals = {
.reg_pairs = sl_usb_100_no_ssc_cmn_regs,
.num_regs = ARRAY_SIZE(sl_usb_100_no_ssc_cmn_regs),
};
-static struct cdns_reg_pairs usb_100_no_ssc_cmn_regs[] = {
+static const struct cdns_reg_pairs usb_100_no_ssc_cmn_regs[] = {
{0x8200, CMN_CDIAG_CDB_PWRI_OVRD},
{0x8200, CMN_CDIAG_XCVRC_PWRI_OVRD},
{0x007F, CMN_TXPUCAL_TUNE},
{0x007F, CMN_TXPDCAL_TUNE}
};
-static struct cdns_reg_pairs usb_100_no_ssc_tx_ln_regs[] = {
+static const struct cdns_reg_pairs usb_100_no_ssc_tx_ln_regs[] = {
{0x02FF, TX_PSC_A0},
{0x06AF, TX_PSC_A1},
{0x06AE, TX_PSC_A2},
@@ -3617,7 +4032,7 @@ static struct cdns_reg_pairs usb_100_no_ssc_tx_ln_regs[] = {
{0x0003, XCVR_DIAG_PSC_OVRD}
};
-static struct cdns_reg_pairs usb_100_no_ssc_rx_ln_regs[] = {
+static const struct cdns_reg_pairs usb_100_no_ssc_rx_ln_regs[] = {
{0x0D1D, RX_PSC_A0},
{0x0D1D, RX_PSC_A1},
{0x0D00, RX_PSC_A2},
@@ -3640,23 +4055,23 @@ static struct cdns_reg_pairs usb_100_no_ssc_rx_ln_regs[] = {
{0x0003, RX_CDRLF_CNFG3}
};
-static struct cdns_torrent_vals usb_100_no_ssc_cmn_vals = {
+static const struct cdns_torrent_vals usb_100_no_ssc_cmn_vals = {
.reg_pairs = usb_100_no_ssc_cmn_regs,
.num_regs = ARRAY_SIZE(usb_100_no_ssc_cmn_regs),
};
-static struct cdns_torrent_vals usb_100_no_ssc_tx_ln_vals = {
+static const struct cdns_torrent_vals usb_100_no_ssc_tx_ln_vals = {
.reg_pairs = usb_100_no_ssc_tx_ln_regs,
.num_regs = ARRAY_SIZE(usb_100_no_ssc_tx_ln_regs),
};
-static struct cdns_torrent_vals usb_100_no_ssc_rx_ln_vals = {
+static const struct cdns_torrent_vals usb_100_no_ssc_rx_ln_vals = {
.reg_pairs = usb_100_no_ssc_rx_ln_regs,
.num_regs = ARRAY_SIZE(usb_100_no_ssc_rx_ln_regs),
};
/* Single link USB, 100 MHz Ref clk, internal SSC */
-static struct cdns_reg_pairs sl_usb_100_int_ssc_cmn_regs[] = {
+static const struct cdns_reg_pairs sl_usb_100_int_ssc_cmn_regs[] = {
{0x0004, CMN_PLL0_DSM_DIAG_M0},
{0x0004, CMN_PLL1_DSM_DIAG_M0},
{0x0509, CMN_PDIAG_PLL0_CP_PADJ_M0},
@@ -3697,48 +4112,48 @@ static struct cdns_reg_pairs sl_usb_100_int_ssc_cmn_regs[] = {
{0x8200, CMN_CDIAG_XCVRC_PWRI_OVRD}
};
-static struct cdns_torrent_vals sl_usb_100_int_ssc_cmn_vals = {
+static const struct cdns_torrent_vals sl_usb_100_int_ssc_cmn_vals = {
.reg_pairs = sl_usb_100_int_ssc_cmn_regs,
.num_regs = ARRAY_SIZE(sl_usb_100_int_ssc_cmn_regs),
};
/* PCIe and SGMII/QSGMII Unique SSC link configuration */
-static struct cdns_reg_pairs pcie_sgmii_link_cmn_regs[] = {
+static const struct cdns_reg_pairs pcie_sgmii_link_cmn_regs[] = {
{0x0003, PHY_PLL_CFG},
{0x0601, CMN_PDIAG_PLL0_CLK_SEL_M0},
{0x0400, CMN_PDIAG_PLL0_CLK_SEL_M1},
{0x0601, CMN_PDIAG_PLL1_CLK_SEL_M0}
};
-static struct cdns_reg_pairs pcie_sgmii_xcvr_diag_ln_regs[] = {
+static const struct cdns_reg_pairs pcie_sgmii_xcvr_diag_ln_regs[] = {
{0x0000, XCVR_DIAG_HSCLK_SEL},
{0x0001, XCVR_DIAG_HSCLK_DIV},
{0x0012, XCVR_DIAG_PLLDRC_CTRL}
};
-static struct cdns_reg_pairs sgmii_pcie_xcvr_diag_ln_regs[] = {
+static const struct cdns_reg_pairs sgmii_pcie_xcvr_diag_ln_regs[] = {
{0x0011, XCVR_DIAG_HSCLK_SEL},
{0x0003, XCVR_DIAG_HSCLK_DIV},
{0x009B, XCVR_DIAG_PLLDRC_CTRL}
};
-static struct cdns_torrent_vals pcie_sgmii_link_cmn_vals = {
+static const struct cdns_torrent_vals pcie_sgmii_link_cmn_vals = {
.reg_pairs = pcie_sgmii_link_cmn_regs,
.num_regs = ARRAY_SIZE(pcie_sgmii_link_cmn_regs),
};
-static struct cdns_torrent_vals pcie_sgmii_xcvr_diag_ln_vals = {
+static const struct cdns_torrent_vals pcie_sgmii_xcvr_diag_ln_vals = {
.reg_pairs = pcie_sgmii_xcvr_diag_ln_regs,
.num_regs = ARRAY_SIZE(pcie_sgmii_xcvr_diag_ln_regs),
};
-static struct cdns_torrent_vals sgmii_pcie_xcvr_diag_ln_vals = {
+static const struct cdns_torrent_vals sgmii_pcie_xcvr_diag_ln_vals = {
.reg_pairs = sgmii_pcie_xcvr_diag_ln_regs,
.num_regs = ARRAY_SIZE(sgmii_pcie_xcvr_diag_ln_regs),
};
/* SGMII 100 MHz Ref clk, no SSC */
-static struct cdns_reg_pairs sl_sgmii_100_no_ssc_cmn_regs[] = {
+static const struct cdns_reg_pairs sl_sgmii_100_no_ssc_cmn_regs[] = {
{0x0028, CMN_PDIAG_PLL1_CP_PADJ_M0},
{0x001E, CMN_PLL1_DSM_FBH_OVRD_M0},
{0x000C, CMN_PLL1_DSM_FBL_OVRD_M0},
@@ -3746,34 +4161,36 @@ static struct cdns_reg_pairs sl_sgmii_100_no_ssc_cmn_regs[] = {
{0x0003, CMN_PLL1_VCOCAL_TCTRL}
};
-static struct cdns_torrent_vals sl_sgmii_100_no_ssc_cmn_vals = {
+static const struct cdns_torrent_vals sl_sgmii_100_no_ssc_cmn_vals = {
.reg_pairs = sl_sgmii_100_no_ssc_cmn_regs,
.num_regs = ARRAY_SIZE(sl_sgmii_100_no_ssc_cmn_regs),
};
-static struct cdns_reg_pairs sgmii_100_no_ssc_cmn_regs[] = {
+static const struct cdns_reg_pairs sgmii_100_no_ssc_cmn_regs[] = {
{0x007F, CMN_TXPUCAL_TUNE},
{0x007F, CMN_TXPDCAL_TUNE}
};
-static struct cdns_reg_pairs sgmii_100_no_ssc_tx_ln_regs[] = {
+static const struct cdns_reg_pairs sgmii_100_no_ssc_tx_ln_regs[] = {
{0x00F3, TX_PSC_A0},
{0x04A2, TX_PSC_A2},
{0x04A2, TX_PSC_A3},
{0x0000, TX_TXCC_CPOST_MULT_00},
- {0x00B3, DRV_DIAG_TX_DRV}
+ {0x00B3, DRV_DIAG_TX_DRV},
+ {0x0002, XCVR_DIAG_PSC_OVRD}
};
-static struct cdns_reg_pairs ti_sgmii_100_no_ssc_tx_ln_regs[] = {
+static const struct cdns_reg_pairs ti_sgmii_100_no_ssc_tx_ln_regs[] = {
{0x00F3, TX_PSC_A0},
{0x04A2, TX_PSC_A2},
{0x04A2, TX_PSC_A3},
{0x0000, TX_TXCC_CPOST_MULT_00},
{0x00B3, DRV_DIAG_TX_DRV},
- {0x4000, XCVR_DIAG_RXCLK_CTRL},
+ {0x0002, XCVR_DIAG_PSC_OVRD},
+ {0x4000, XCVR_DIAG_RXCLK_CTRL}
};
-static struct cdns_reg_pairs sgmii_100_no_ssc_rx_ln_regs[] = {
+static const struct cdns_reg_pairs sgmii_100_no_ssc_rx_ln_regs[] = {
{0x091D, RX_PSC_A0},
{0x0900, RX_PSC_A2},
{0x0100, RX_PSC_A3},
@@ -3791,28 +4208,72 @@ static struct cdns_reg_pairs sgmii_100_no_ssc_rx_ln_regs[] = {
{0x018C, RX_CDRLF_CNFG},
};
-static struct cdns_torrent_vals sgmii_100_no_ssc_cmn_vals = {
+static const struct cdns_torrent_vals sgmii_100_no_ssc_cmn_vals = {
.reg_pairs = sgmii_100_no_ssc_cmn_regs,
.num_regs = ARRAY_SIZE(sgmii_100_no_ssc_cmn_regs),
};
-static struct cdns_torrent_vals sgmii_100_no_ssc_tx_ln_vals = {
+static const struct cdns_torrent_vals sgmii_100_no_ssc_tx_ln_vals = {
.reg_pairs = sgmii_100_no_ssc_tx_ln_regs,
.num_regs = ARRAY_SIZE(sgmii_100_no_ssc_tx_ln_regs),
};
-static struct cdns_torrent_vals ti_sgmii_100_no_ssc_tx_ln_vals = {
+static const struct cdns_torrent_vals ti_sgmii_100_no_ssc_tx_ln_vals = {
.reg_pairs = ti_sgmii_100_no_ssc_tx_ln_regs,
.num_regs = ARRAY_SIZE(ti_sgmii_100_no_ssc_tx_ln_regs),
};
-static struct cdns_torrent_vals sgmii_100_no_ssc_rx_ln_vals = {
+static const struct cdns_torrent_vals sgmii_100_no_ssc_rx_ln_vals = {
.reg_pairs = sgmii_100_no_ssc_rx_ln_regs,
.num_regs = ARRAY_SIZE(sgmii_100_no_ssc_rx_ln_regs),
};
+/* TI J7200, multilink SGMII */
+static const struct cdns_reg_pairs j7200_sgmii_100_no_ssc_tx_ln_regs[] = {
+ {0x07A2, TX_RCVDET_ST_TMR},
+ {0x00F3, TX_PSC_A0},
+ {0x04A2, TX_PSC_A2},
+ {0x04A2, TX_PSC_A3 },
+ {0x0000, TX_TXCC_CPOST_MULT_00},
+ {0x00B3, DRV_DIAG_TX_DRV},
+ {0x0002, XCVR_DIAG_PSC_OVRD},
+ {0x4000, XCVR_DIAG_RXCLK_CTRL}
+};
+
+static const struct cdns_torrent_vals j7200_sgmii_100_no_ssc_tx_ln_vals = {
+ .reg_pairs = j7200_sgmii_100_no_ssc_tx_ln_regs,
+ .num_regs = ARRAY_SIZE(j7200_sgmii_100_no_ssc_tx_ln_regs),
+};
+
+static const struct cdns_reg_pairs j7200_sgmii_100_no_ssc_rx_ln_regs[] = {
+ {0x0014, RX_SDCAL0_INIT_TMR},
+ {0x0062, RX_SDCAL0_ITER_TMR},
+ {0x0014, RX_SDCAL1_INIT_TMR},
+ {0x0062, RX_SDCAL1_ITER_TMR},
+ {0x091D, RX_PSC_A0},
+ {0x0900, RX_PSC_A2},
+ {0x0100, RX_PSC_A3},
+ {0x03C7, RX_REE_GCSM1_EQENM_PH1},
+ {0x01C7, RX_REE_GCSM1_EQENM_PH2},
+ {0x0000, RX_DIAG_DFE_CTRL},
+ {0x0019, RX_REE_TAP1_CLIP},
+ {0x0019, RX_REE_TAP2TON_CLIP},
+ {0x0098, RX_DIAG_NQST_CTRL},
+ {0x0C01, RX_DIAG_DFE_AMP_TUNE_2},
+ {0x0000, RX_DIAG_DFE_AMP_TUNE_3},
+ {0x0000, RX_DIAG_PI_CAP},
+ {0x0010, RX_DIAG_PI_RATE},
+ {0x0001, RX_DIAG_ACYA},
+ {0x018C, RX_CDRLF_CNFG}
+};
+
+static const struct cdns_torrent_vals j7200_sgmii_100_no_ssc_rx_ln_vals = {
+ .reg_pairs = j7200_sgmii_100_no_ssc_rx_ln_regs,
+ .num_regs = ARRAY_SIZE(j7200_sgmii_100_no_ssc_rx_ln_regs),
+};
+
/* SGMII 100 MHz Ref clk, internal SSC */
-static struct cdns_reg_pairs sgmii_100_int_ssc_cmn_regs[] = {
+static const struct cdns_reg_pairs sgmii_100_int_ssc_cmn_regs[] = {
{0x0004, CMN_PLL0_DSM_DIAG_M0},
{0x0004, CMN_PLL0_DSM_DIAG_M1},
{0x0004, CMN_PLL1_DSM_DIAG_M0},
@@ -3863,13 +4324,13 @@ static struct cdns_reg_pairs sgmii_100_int_ssc_cmn_regs[] = {
{0x007F, CMN_TXPDCAL_TUNE}
};
-static struct cdns_torrent_vals sgmii_100_int_ssc_cmn_vals = {
+static const struct cdns_torrent_vals sgmii_100_int_ssc_cmn_vals = {
.reg_pairs = sgmii_100_int_ssc_cmn_regs,
.num_regs = ARRAY_SIZE(sgmii_100_int_ssc_cmn_regs),
};
/* QSGMII 100 MHz Ref clk, no SSC */
-static struct cdns_reg_pairs sl_qsgmii_100_no_ssc_cmn_regs[] = {
+static const struct cdns_reg_pairs sl_qsgmii_100_no_ssc_cmn_regs[] = {
{0x0028, CMN_PDIAG_PLL1_CP_PADJ_M0},
{0x001E, CMN_PLL1_DSM_FBH_OVRD_M0},
{0x000C, CMN_PLL1_DSM_FBL_OVRD_M0},
@@ -3877,36 +4338,38 @@ static struct cdns_reg_pairs sl_qsgmii_100_no_ssc_cmn_regs[] = {
{0x0003, CMN_PLL1_VCOCAL_TCTRL}
};
-static struct cdns_torrent_vals sl_qsgmii_100_no_ssc_cmn_vals = {
+static const struct cdns_torrent_vals sl_qsgmii_100_no_ssc_cmn_vals = {
.reg_pairs = sl_qsgmii_100_no_ssc_cmn_regs,
.num_regs = ARRAY_SIZE(sl_qsgmii_100_no_ssc_cmn_regs),
};
-static struct cdns_reg_pairs qsgmii_100_no_ssc_cmn_regs[] = {
+static const struct cdns_reg_pairs qsgmii_100_no_ssc_cmn_regs[] = {
{0x007F, CMN_TXPUCAL_TUNE},
{0x007F, CMN_TXPDCAL_TUNE}
};
-static struct cdns_reg_pairs qsgmii_100_no_ssc_tx_ln_regs[] = {
+static const struct cdns_reg_pairs qsgmii_100_no_ssc_tx_ln_regs[] = {
{0x00F3, TX_PSC_A0},
{0x04A2, TX_PSC_A2},
{0x04A2, TX_PSC_A3},
{0x0000, TX_TXCC_CPOST_MULT_00},
{0x0011, TX_TXCC_MGNFS_MULT_100},
- {0x0003, DRV_DIAG_TX_DRV}
+ {0x0003, DRV_DIAG_TX_DRV},
+ {0x0002, XCVR_DIAG_PSC_OVRD}
};
-static struct cdns_reg_pairs ti_qsgmii_100_no_ssc_tx_ln_regs[] = {
+static const struct cdns_reg_pairs ti_qsgmii_100_no_ssc_tx_ln_regs[] = {
{0x00F3, TX_PSC_A0},
{0x04A2, TX_PSC_A2},
{0x04A2, TX_PSC_A3},
{0x0000, TX_TXCC_CPOST_MULT_00},
{0x0011, TX_TXCC_MGNFS_MULT_100},
{0x0003, DRV_DIAG_TX_DRV},
- {0x4000, XCVR_DIAG_RXCLK_CTRL},
+ {0x0002, XCVR_DIAG_PSC_OVRD},
+ {0x4000, XCVR_DIAG_RXCLK_CTRL}
};
-static struct cdns_reg_pairs qsgmii_100_no_ssc_rx_ln_regs[] = {
+static const struct cdns_reg_pairs qsgmii_100_no_ssc_rx_ln_regs[] = {
{0x091D, RX_PSC_A0},
{0x0900, RX_PSC_A2},
{0x0100, RX_PSC_A3},
@@ -3924,28 +4387,73 @@ static struct cdns_reg_pairs qsgmii_100_no_ssc_rx_ln_regs[] = {
{0x018C, RX_CDRLF_CNFG},
};
-static struct cdns_torrent_vals qsgmii_100_no_ssc_cmn_vals = {
+static const struct cdns_torrent_vals qsgmii_100_no_ssc_cmn_vals = {
.reg_pairs = qsgmii_100_no_ssc_cmn_regs,
.num_regs = ARRAY_SIZE(qsgmii_100_no_ssc_cmn_regs),
};
-static struct cdns_torrent_vals qsgmii_100_no_ssc_tx_ln_vals = {
+static const struct cdns_torrent_vals qsgmii_100_no_ssc_tx_ln_vals = {
.reg_pairs = qsgmii_100_no_ssc_tx_ln_regs,
.num_regs = ARRAY_SIZE(qsgmii_100_no_ssc_tx_ln_regs),
};
-static struct cdns_torrent_vals ti_qsgmii_100_no_ssc_tx_ln_vals = {
+static const struct cdns_torrent_vals ti_qsgmii_100_no_ssc_tx_ln_vals = {
.reg_pairs = ti_qsgmii_100_no_ssc_tx_ln_regs,
.num_regs = ARRAY_SIZE(ti_qsgmii_100_no_ssc_tx_ln_regs),
};
-static struct cdns_torrent_vals qsgmii_100_no_ssc_rx_ln_vals = {
+static const struct cdns_torrent_vals qsgmii_100_no_ssc_rx_ln_vals = {
.reg_pairs = qsgmii_100_no_ssc_rx_ln_regs,
.num_regs = ARRAY_SIZE(qsgmii_100_no_ssc_rx_ln_regs),
};
+/* TI J7200, multilink QSGMII */
+static const struct cdns_reg_pairs j7200_qsgmii_100_no_ssc_tx_ln_regs[] = {
+ {0x07A2, TX_RCVDET_ST_TMR},
+ {0x00F3, TX_PSC_A0},
+ {0x04A2, TX_PSC_A2},
+ {0x04A2, TX_PSC_A3 },
+ {0x0000, TX_TXCC_CPOST_MULT_00},
+ {0x0011, TX_TXCC_MGNFS_MULT_100},
+ {0x0003, DRV_DIAG_TX_DRV},
+ {0x0002, XCVR_DIAG_PSC_OVRD},
+ {0x4000, XCVR_DIAG_RXCLK_CTRL}
+};
+
+static const struct cdns_torrent_vals j7200_qsgmii_100_no_ssc_tx_ln_vals = {
+ .reg_pairs = j7200_qsgmii_100_no_ssc_tx_ln_regs,
+ .num_regs = ARRAY_SIZE(j7200_qsgmii_100_no_ssc_tx_ln_regs),
+};
+
+static const struct cdns_reg_pairs j7200_qsgmii_100_no_ssc_rx_ln_regs[] = {
+ {0x0014, RX_SDCAL0_INIT_TMR},
+ {0x0062, RX_SDCAL0_ITER_TMR},
+ {0x0014, RX_SDCAL1_INIT_TMR},
+ {0x0062, RX_SDCAL1_ITER_TMR},
+ {0x091D, RX_PSC_A0},
+ {0x0900, RX_PSC_A2},
+ {0x0100, RX_PSC_A3},
+ {0x03C7, RX_REE_GCSM1_EQENM_PH1},
+ {0x01C7, RX_REE_GCSM1_EQENM_PH2},
+ {0x0000, RX_DIAG_DFE_CTRL},
+ {0x0019, RX_REE_TAP1_CLIP},
+ {0x0019, RX_REE_TAP2TON_CLIP},
+ {0x0098, RX_DIAG_NQST_CTRL},
+ {0x0C01, RX_DIAG_DFE_AMP_TUNE_2},
+ {0x0000, RX_DIAG_DFE_AMP_TUNE_3},
+ {0x0000, RX_DIAG_PI_CAP},
+ {0x0010, RX_DIAG_PI_RATE},
+ {0x0001, RX_DIAG_ACYA},
+ {0x018C, RX_CDRLF_CNFG}
+};
+
+static const struct cdns_torrent_vals j7200_qsgmii_100_no_ssc_rx_ln_vals = {
+ .reg_pairs = j7200_qsgmii_100_no_ssc_rx_ln_regs,
+ .num_regs = ARRAY_SIZE(j7200_qsgmii_100_no_ssc_rx_ln_regs),
+};
+
/* QSGMII 100 MHz Ref clk, internal SSC */
-static struct cdns_reg_pairs qsgmii_100_int_ssc_cmn_regs[] = {
+static const struct cdns_reg_pairs qsgmii_100_int_ssc_cmn_regs[] = {
{0x0004, CMN_PLL0_DSM_DIAG_M0},
{0x0004, CMN_PLL0_DSM_DIAG_M1},
{0x0004, CMN_PLL1_DSM_DIAG_M0},
@@ -3996,35 +4504,35 @@ static struct cdns_reg_pairs qsgmii_100_int_ssc_cmn_regs[] = {
{0x007F, CMN_TXPDCAL_TUNE}
};
-static struct cdns_torrent_vals qsgmii_100_int_ssc_cmn_vals = {
+static const struct cdns_torrent_vals qsgmii_100_int_ssc_cmn_vals = {
.reg_pairs = qsgmii_100_int_ssc_cmn_regs,
.num_regs = ARRAY_SIZE(qsgmii_100_int_ssc_cmn_regs),
};
/* Single SGMII/QSGMII link configuration */
-static struct cdns_reg_pairs sl_sgmii_link_cmn_regs[] = {
+static const struct cdns_reg_pairs sl_sgmii_link_cmn_regs[] = {
{0x0000, PHY_PLL_CFG},
{0x0601, CMN_PDIAG_PLL0_CLK_SEL_M0}
};
-static struct cdns_reg_pairs sl_sgmii_xcvr_diag_ln_regs[] = {
+static const struct cdns_reg_pairs sl_sgmii_xcvr_diag_ln_regs[] = {
{0x0000, XCVR_DIAG_HSCLK_SEL},
{0x0003, XCVR_DIAG_HSCLK_DIV},
{0x0013, XCVR_DIAG_PLLDRC_CTRL}
};
-static struct cdns_torrent_vals sl_sgmii_link_cmn_vals = {
+static const struct cdns_torrent_vals sl_sgmii_link_cmn_vals = {
.reg_pairs = sl_sgmii_link_cmn_regs,
.num_regs = ARRAY_SIZE(sl_sgmii_link_cmn_regs),
};
-static struct cdns_torrent_vals sl_sgmii_xcvr_diag_ln_vals = {
+static const struct cdns_torrent_vals sl_sgmii_xcvr_diag_ln_vals = {
.reg_pairs = sl_sgmii_xcvr_diag_ln_regs,
.num_regs = ARRAY_SIZE(sl_sgmii_xcvr_diag_ln_regs),
};
/* Multi link PCIe, 100 MHz Ref clk, internal SSC */
-static struct cdns_reg_pairs pcie_100_int_ssc_cmn_regs[] = {
+static const struct cdns_reg_pairs pcie_100_int_ssc_cmn_regs[] = {
{0x0004, CMN_PLL0_DSM_DIAG_M0},
{0x0004, CMN_PLL0_DSM_DIAG_M1},
{0x0004, CMN_PLL1_DSM_DIAG_M0},
@@ -4073,13 +4581,13 @@ static struct cdns_reg_pairs pcie_100_int_ssc_cmn_regs[] = {
{0x0005, CMN_PLL1_LOCK_PLLCNT_THR}
};
-static struct cdns_torrent_vals pcie_100_int_ssc_cmn_vals = {
+static const struct cdns_torrent_vals pcie_100_int_ssc_cmn_vals = {
.reg_pairs = pcie_100_int_ssc_cmn_regs,
.num_regs = ARRAY_SIZE(pcie_100_int_ssc_cmn_regs),
};
/* Single link PCIe, 100 MHz Ref clk, internal SSC */
-static struct cdns_reg_pairs sl_pcie_100_int_ssc_cmn_regs[] = {
+static const struct cdns_reg_pairs sl_pcie_100_int_ssc_cmn_regs[] = {
{0x0004, CMN_PLL0_DSM_DIAG_M0},
{0x0004, CMN_PLL0_DSM_DIAG_M1},
{0x0004, CMN_PLL1_DSM_DIAG_M0},
@@ -4128,35 +4636,35 @@ static struct cdns_reg_pairs sl_pcie_100_int_ssc_cmn_regs[] = {
{0x0005, CMN_PLL1_LOCK_PLLCNT_THR}
};
-static struct cdns_torrent_vals sl_pcie_100_int_ssc_cmn_vals = {
+static const struct cdns_torrent_vals sl_pcie_100_int_ssc_cmn_vals = {
.reg_pairs = sl_pcie_100_int_ssc_cmn_regs,
.num_regs = ARRAY_SIZE(sl_pcie_100_int_ssc_cmn_regs),
};
/* PCIe, 100 MHz Ref clk, no SSC & external SSC */
-static struct cdns_reg_pairs pcie_100_ext_no_ssc_cmn_regs[] = {
+static const struct cdns_reg_pairs pcie_100_ext_no_ssc_cmn_regs[] = {
{0x0028, CMN_PDIAG_PLL1_CP_PADJ_M0},
{0x001E, CMN_PLL1_DSM_FBH_OVRD_M0},
{0x000C, CMN_PLL1_DSM_FBL_OVRD_M0}
};
-static struct cdns_reg_pairs pcie_100_ext_no_ssc_rx_ln_regs[] = {
+static const struct cdns_reg_pairs pcie_100_ext_no_ssc_rx_ln_regs[] = {
{0x0019, RX_REE_TAP1_CLIP},
{0x0019, RX_REE_TAP2TON_CLIP},
{0x0001, RX_DIAG_ACYA}
};
-static struct cdns_torrent_vals pcie_100_no_ssc_cmn_vals = {
+static const struct cdns_torrent_vals pcie_100_no_ssc_cmn_vals = {
.reg_pairs = pcie_100_ext_no_ssc_cmn_regs,
.num_regs = ARRAY_SIZE(pcie_100_ext_no_ssc_cmn_regs),
};
-static struct cdns_torrent_vals pcie_100_no_ssc_rx_ln_vals = {
+static const struct cdns_torrent_vals pcie_100_no_ssc_rx_ln_vals = {
.reg_pairs = pcie_100_ext_no_ssc_rx_ln_regs,
.num_regs = ARRAY_SIZE(pcie_100_ext_no_ssc_rx_ln_regs),
};
-static struct cdns_torrent_vals_entry link_cmn_vals_entries[] = {
+static const struct cdns_torrent_vals_entry link_cmn_vals_entries[] = {
{CDNS_TORRENT_KEY_ANYCLK(TYPE_DP, TYPE_NONE), &sl_dp_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_DP, TYPE_PCIE), &pcie_dp_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_DP, TYPE_USB), &usb_dp_link_cmn_vals},
@@ -4166,14 +4674,19 @@ static struct cdns_torrent_vals_entry link_cmn_vals_entries[] = {
{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_QSGMII), &pcie_sgmii_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_USB), &pcie_usb_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_DP), &pcie_dp_link_cmn_vals},
+ {CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_USXGMII), &pcie_usxgmii_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_NONE), &sl_sgmii_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_PCIE), &pcie_sgmii_link_cmn_vals},
+ {CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_QSGMII), &sgmii_qsgmii_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_USB), &usb_sgmii_link_cmn_vals},
+ {CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_USXGMII), &usxgmii_sgmii_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_NONE), &sl_sgmii_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_PCIE), &pcie_sgmii_link_cmn_vals},
+ {CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_SGMII), &sgmii_qsgmii_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_USB), &usb_sgmii_link_cmn_vals},
+ {CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_USXGMII), &usxgmii_sgmii_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_USB, TYPE_NONE), &sl_usb_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_USB, TYPE_PCIE), &pcie_usb_link_cmn_vals},
@@ -4182,9 +4695,12 @@ static struct cdns_torrent_vals_entry link_cmn_vals_entries[] = {
{CDNS_TORRENT_KEY_ANYCLK(TYPE_USB, TYPE_DP), &usb_dp_link_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_NONE), &sl_usxgmii_link_cmn_vals},
+ {CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_PCIE), &pcie_usxgmii_link_cmn_vals},
+ {CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_SGMII), &usxgmii_sgmii_link_cmn_vals},
+ {CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_QSGMII), &usxgmii_sgmii_link_cmn_vals},
};
-static struct cdns_torrent_vals_entry xcvr_diag_vals_entries[] = {
+static const struct cdns_torrent_vals_entry xcvr_diag_vals_entries[] = {
{CDNS_TORRENT_KEY_ANYCLK(TYPE_DP, TYPE_NONE), &sl_dp_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_DP, TYPE_PCIE), &dp_pcie_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_DP, TYPE_USB), &dp_usb_xcvr_diag_ln_vals},
@@ -4194,14 +4710,19 @@ static struct cdns_torrent_vals_entry xcvr_diag_vals_entries[] = {
{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_QSGMII), &pcie_sgmii_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_USB), &pcie_usb_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_DP), &pcie_dp_xcvr_diag_ln_vals},
+ {CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_USXGMII), &pcie_usxgmii_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_NONE), &sl_sgmii_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_PCIE), &sgmii_pcie_xcvr_diag_ln_vals},
+ {CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_QSGMII), &sgmii_qsgmii_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_USB), &sgmii_usb_xcvr_diag_ln_vals},
+ {CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_USXGMII), &sgmii_usxgmii_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_NONE), &sl_sgmii_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_PCIE), &sgmii_pcie_xcvr_diag_ln_vals},
+ {CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_SGMII), &sgmii_qsgmii_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_USB), &sgmii_usb_xcvr_diag_ln_vals},
+ {CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_USXGMII), &sgmii_usxgmii_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_USB, TYPE_NONE), &sl_usb_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_USB, TYPE_PCIE), &usb_pcie_xcvr_diag_ln_vals},
@@ -4210,9 +4731,12 @@ static struct cdns_torrent_vals_entry xcvr_diag_vals_entries[] = {
{CDNS_TORRENT_KEY_ANYCLK(TYPE_USB, TYPE_DP), &usb_dp_xcvr_diag_ln_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_NONE), &sl_usxgmii_xcvr_diag_ln_vals},
+ {CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_PCIE), &usxgmii_pcie_xcvr_diag_ln_vals},
+ {CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_SGMII), &usxgmii_sgmii_xcvr_diag_ln_vals},
+ {CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_QSGMII), &usxgmii_sgmii_xcvr_diag_ln_vals},
};
-static struct cdns_torrent_vals_entry pcs_cmn_vals_entries[] = {
+static const struct cdns_torrent_vals_entry pcs_cmn_vals_entries[] = {
{CDNS_TORRENT_KEY_ANYCLK(TYPE_USB, TYPE_NONE), &usb_phy_pcs_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_USB, TYPE_PCIE), &usb_phy_pcs_cmn_vals},
{CDNS_TORRENT_KEY_ANYCLK(TYPE_USB, TYPE_SGMII), &usb_phy_pcs_cmn_vals},
@@ -4220,7 +4744,7 @@ static struct cdns_torrent_vals_entry pcs_cmn_vals_entries[] = {
{CDNS_TORRENT_KEY_ANYCLK(TYPE_USB, TYPE_DP), &usb_phy_pcs_cmn_vals},
};
-static struct cdns_torrent_vals_entry cmn_vals_entries[] = {
+static const struct cdns_torrent_vals_entry cmn_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_19_2_MHZ, CLK_19_2_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_19_2_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_25_MHZ, CLK_25_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_25_no_ssc_cmn_vals},
@@ -4252,6 +4776,8 @@ static struct cdns_torrent_vals_entry cmn_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, EXTERNAL_SSC), &sgmii_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, INTERNAL_SSC), &sgmii_100_int_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_QSGMII, NO_SSC), &sl_sgmii_100_no_ssc_cmn_vals},
+
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, NO_SSC), &sgmii_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, EXTERNAL_SSC), &sgmii_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, INTERNAL_SSC), &sgmii_100_no_ssc_cmn_vals},
@@ -4262,6 +4788,8 @@ static struct cdns_torrent_vals_entry cmn_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, EXTERNAL_SSC), &qsgmii_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, INTERNAL_SSC), &qsgmii_100_int_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_SGMII, NO_SSC), &sl_qsgmii_100_no_ssc_cmn_vals},
+
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, NO_SSC), &qsgmii_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, EXTERNAL_SSC), &qsgmii_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, INTERNAL_SSC), &qsgmii_100_no_ssc_cmn_vals},
@@ -4285,9 +4813,20 @@ static struct cdns_torrent_vals_entry cmn_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_DP, NO_SSC), &usb_100_no_ssc_cmn_vals},
{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_156_25_MHZ, TYPE_USXGMII, TYPE_NONE, NO_SSC), &sl_usxgmii_156_25_no_ssc_cmn_vals},
+
+ /* Dual refclk */
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_PCIE, TYPE_USXGMII, NO_SSC), NULL},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_SGMII, TYPE_USXGMII, NO_SSC), &ml_sgmii_pll1_100_no_ssc_cmn_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_QSGMII, TYPE_USXGMII, NO_SSC), &ml_sgmii_pll1_100_no_ssc_cmn_vals},
+
+ {CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_PCIE, NO_SSC), &ml_usxgmii_pll1_156_25_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_SGMII, NO_SSC), &ml_usxgmii_pll0_156_25_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_QSGMII, NO_SSC), &ml_usxgmii_pll0_156_25_no_ssc_cmn_vals},
};
-static struct cdns_torrent_vals_entry cdns_tx_ln_vals_entries[] = {
+static const struct cdns_torrent_vals_entry cdns_tx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_19_2_MHZ, CLK_19_2_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_19_2_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_25_MHZ, CLK_25_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_25_no_ssc_tx_ln_vals},
@@ -4319,6 +4858,8 @@ static struct cdns_torrent_vals_entry cdns_tx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, EXTERNAL_SSC), &sgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, INTERNAL_SSC), &sgmii_100_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_QSGMII, NO_SSC), &sgmii_100_no_ssc_tx_ln_vals},
+
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, NO_SSC), &sgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, EXTERNAL_SSC), &sgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, INTERNAL_SSC), &sgmii_100_no_ssc_tx_ln_vals},
@@ -4329,6 +4870,8 @@ static struct cdns_torrent_vals_entry cdns_tx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, EXTERNAL_SSC), &qsgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, INTERNAL_SSC), &qsgmii_100_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_SGMII, NO_SSC), &qsgmii_100_no_ssc_tx_ln_vals},
+
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, NO_SSC), &qsgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, EXTERNAL_SSC), &qsgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, INTERNAL_SSC), &qsgmii_100_no_ssc_tx_ln_vals},
@@ -4352,9 +4895,20 @@ static struct cdns_torrent_vals_entry cdns_tx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_DP, NO_SSC), &usb_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_156_25_MHZ, TYPE_USXGMII, TYPE_NONE, NO_SSC), &usxgmii_156_25_no_ssc_tx_ln_vals},
+
+ /* Dual refclk */
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_PCIE, TYPE_USXGMII, NO_SSC), NULL},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_SGMII, TYPE_USXGMII, NO_SSC), &sgmii_100_no_ssc_tx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_QSGMII, TYPE_USXGMII, NO_SSC), &qsgmii_100_no_ssc_tx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_PCIE, NO_SSC), &ml_usxgmii_156_25_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_SGMII, NO_SSC), &ml_usxgmii_156_25_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_QSGMII, NO_SSC), &ml_usxgmii_156_25_no_ssc_tx_ln_vals},
};
-static struct cdns_torrent_vals_entry cdns_rx_ln_vals_entries[] = {
+static const struct cdns_torrent_vals_entry cdns_rx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_19_2_MHZ, CLK_19_2_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_19_2_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_25_MHZ, CLK_25_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_25_no_ssc_rx_ln_vals},
@@ -4386,6 +4940,8 @@ static struct cdns_torrent_vals_entry cdns_rx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, EXTERNAL_SSC), &sgmii_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, INTERNAL_SSC), &sgmii_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_QSGMII, NO_SSC), &sgmii_100_no_ssc_rx_ln_vals},
+
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, NO_SSC), &sgmii_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, EXTERNAL_SSC), &sgmii_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, INTERNAL_SSC), &sgmii_100_no_ssc_rx_ln_vals},
@@ -4396,6 +4952,8 @@ static struct cdns_torrent_vals_entry cdns_rx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, EXTERNAL_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, INTERNAL_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_SGMII, NO_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
+
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, NO_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, EXTERNAL_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, INTERNAL_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
@@ -4419,6 +4977,17 @@ static struct cdns_torrent_vals_entry cdns_rx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_DP, NO_SSC), &usb_100_no_ssc_rx_ln_vals},
{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_156_25_MHZ, TYPE_USXGMII, TYPE_NONE, NO_SSC), &usxgmii_156_25_no_ssc_rx_ln_vals},
+
+ /* Dual refclk */
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_PCIE, TYPE_USXGMII, NO_SSC), &pcie_100_no_ssc_rx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_SGMII, TYPE_USXGMII, NO_SSC), &sgmii_100_no_ssc_rx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_QSGMII, TYPE_USXGMII, NO_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_PCIE, NO_SSC), &ml_usxgmii_156_25_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_SGMII, NO_SSC), &ml_usxgmii_156_25_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_QSGMII, NO_SSC), &ml_usxgmii_156_25_no_ssc_rx_ln_vals},
};
static const struct cdns_torrent_data cdns_map_torrent = {
@@ -4450,11 +5019,14 @@ static const struct cdns_torrent_data cdns_map_torrent = {
},
};
-static struct cdns_torrent_vals_entry j721e_phy_pma_cmn_vals_entries[] = {
+static const struct cdns_torrent_vals_entry j721e_phy_pma_cmn_vals_entries[] = {
{CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_NONE), &ti_usxgmii_phy_pma_cmn_vals},
+ {CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_PCIE), &ti_usxgmii_phy_pma_cmn_vals},
+ {CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_SGMII), &ti_usxgmii_phy_pma_cmn_vals},
+ {CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_QSGMII), &ti_usxgmii_phy_pma_cmn_vals},
};
-static struct cdns_torrent_vals_entry ti_tx_ln_vals_entries[] = {
+static const struct cdns_torrent_vals_entry ti_tx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_19_2_MHZ, CLK_19_2_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_19_2_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_25_MHZ, CLK_25_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_25_no_ssc_tx_ln_vals},
@@ -4486,6 +5058,8 @@ static struct cdns_torrent_vals_entry ti_tx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, EXTERNAL_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, INTERNAL_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_QSGMII, NO_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
+
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, NO_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, EXTERNAL_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, INTERNAL_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
@@ -4496,6 +5070,8 @@ static struct cdns_torrent_vals_entry ti_tx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, EXTERNAL_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, INTERNAL_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_SGMII, NO_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
+
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, NO_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, EXTERNAL_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, INTERNAL_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
@@ -4519,6 +5095,17 @@ static struct cdns_torrent_vals_entry ti_tx_ln_vals_entries[] = {
{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_DP, NO_SSC), &usb_100_no_ssc_tx_ln_vals},
{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_156_25_MHZ, TYPE_USXGMII, TYPE_NONE, NO_SSC), &usxgmii_156_25_no_ssc_tx_ln_vals},
+
+ /* Dual refclk */
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_PCIE, TYPE_USXGMII, NO_SSC), NULL},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_SGMII, TYPE_USXGMII, NO_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_QSGMII, TYPE_USXGMII, NO_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_PCIE, NO_SSC), &ml_usxgmii_156_25_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_SGMII, NO_SSC), &ml_usxgmii_156_25_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_QSGMII, NO_SSC), &ml_usxgmii_156_25_no_ssc_tx_ln_vals},
};
static const struct cdns_torrent_data ti_j721e_map_torrent = {
@@ -4554,6 +5141,286 @@ static const struct cdns_torrent_data ti_j721e_map_torrent = {
},
};
+/* TI J7200 (Torrent SD0805) */
+static const struct cdns_torrent_vals_entry ti_j7200_cmn_vals_entries[] = {
+ {CDNS_TORRENT_KEY(CLK_19_2_MHZ, CLK_19_2_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_19_2_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_25_MHZ, CLK_25_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_25_no_ssc_cmn_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_100_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_PCIE, NO_SSC), &dp_100_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_USB, NO_SSC), &sl_dp_100_no_ssc_cmn_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, NO_SSC), NULL},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, EXTERNAL_SSC), NULL},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, INTERNAL_SSC), &sl_pcie_100_int_ssc_cmn_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, NO_SSC), &pcie_100_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, EXTERNAL_SSC), &pcie_100_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, INTERNAL_SSC), &pcie_100_int_ssc_cmn_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, NO_SSC), &pcie_100_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, EXTERNAL_SSC), &pcie_100_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, INTERNAL_SSC), &pcie_100_int_ssc_cmn_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, NO_SSC), &pcie_100_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, EXTERNAL_SSC), &pcie_100_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, INTERNAL_SSC), &pcie_100_int_ssc_cmn_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_DP, NO_SSC), NULL},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_NONE, NO_SSC), &sl_sgmii_100_no_ssc_cmn_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, NO_SSC), &sgmii_100_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, EXTERNAL_SSC), &sgmii_100_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, INTERNAL_SSC), &sgmii_100_int_ssc_cmn_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_QSGMII, NO_SSC), &sl_sgmii_100_no_ssc_cmn_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, NO_SSC), &sgmii_100_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, EXTERNAL_SSC), &sgmii_100_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, INTERNAL_SSC), &sgmii_100_no_ssc_cmn_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_NONE, NO_SSC), &sl_qsgmii_100_no_ssc_cmn_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, NO_SSC), &qsgmii_100_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, EXTERNAL_SSC), &qsgmii_100_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, INTERNAL_SSC), &qsgmii_100_int_ssc_cmn_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_SGMII, NO_SSC), &sl_qsgmii_100_no_ssc_cmn_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, NO_SSC), &qsgmii_100_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, EXTERNAL_SSC), &qsgmii_100_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, INTERNAL_SSC), &qsgmii_100_no_ssc_cmn_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, NO_SSC), &sl_usb_100_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, EXTERNAL_SSC), &sl_usb_100_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, INTERNAL_SSC), &sl_usb_100_int_ssc_cmn_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, NO_SSC), &usb_100_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, EXTERNAL_SSC), &usb_100_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, INTERNAL_SSC), &usb_100_int_ssc_cmn_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, NO_SSC), &sl_usb_100_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, EXTERNAL_SSC), &sl_usb_100_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, INTERNAL_SSC), &sl_usb_100_int_ssc_cmn_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, NO_SSC), &sl_usb_100_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, EXTERNAL_SSC), &sl_usb_100_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, INTERNAL_SSC), &sl_usb_100_int_ssc_cmn_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_DP, NO_SSC), &usb_100_no_ssc_cmn_vals},
+
+ {CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_156_25_MHZ, TYPE_USXGMII, TYPE_NONE, NO_SSC), &sl_usxgmii_156_25_no_ssc_cmn_vals},
+
+ /* Dual refclk */
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_PCIE, TYPE_USXGMII, NO_SSC), NULL},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_SGMII, TYPE_USXGMII, NO_SSC), &j7200_ml_sgmii_pll1_100_no_ssc_cmn_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_QSGMII, TYPE_USXGMII, NO_SSC), &j7200_ml_sgmii_pll1_100_no_ssc_cmn_vals},
+
+ {CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_PCIE, NO_SSC), &ml_usxgmii_pll1_156_25_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_SGMII, NO_SSC), &j7200_ml_usxgmii_pll0_156_25_no_ssc_cmn_vals},
+ {CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_QSGMII, NO_SSC), &j7200_ml_usxgmii_pll0_156_25_no_ssc_cmn_vals},
+};
+
+static const struct cdns_torrent_vals_entry ti_j7200_tx_ln_vals_entries[] = {
+ {CDNS_TORRENT_KEY(CLK_19_2_MHZ, CLK_19_2_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_19_2_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_25_MHZ, CLK_25_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_25_no_ssc_tx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_100_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_PCIE, NO_SSC), &dp_100_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_USB, NO_SSC), &dp_100_no_ssc_tx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, NO_SSC), NULL},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, EXTERNAL_SSC), NULL},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, INTERNAL_SSC), NULL},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, NO_SSC), NULL},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, EXTERNAL_SSC), NULL},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, INTERNAL_SSC), NULL},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, NO_SSC), NULL},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, EXTERNAL_SSC), NULL},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, INTERNAL_SSC), NULL},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, NO_SSC), NULL},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, EXTERNAL_SSC), NULL},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, INTERNAL_SSC), NULL},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_DP, NO_SSC), NULL},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_NONE, NO_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, NO_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, EXTERNAL_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, INTERNAL_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_QSGMII, NO_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, NO_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, EXTERNAL_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, INTERNAL_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_NONE, NO_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, NO_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, EXTERNAL_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, INTERNAL_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_SGMII, NO_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, NO_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, EXTERNAL_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, INTERNAL_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, NO_SSC), &usb_100_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, EXTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, INTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, NO_SSC), &usb_100_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, EXTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, INTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, NO_SSC), &usb_100_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, EXTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, INTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, NO_SSC), &usb_100_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, EXTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, INTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_DP, NO_SSC), &usb_100_no_ssc_tx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_156_25_MHZ, TYPE_USXGMII, TYPE_NONE, NO_SSC), &usxgmii_156_25_no_ssc_tx_ln_vals},
+
+ /* Dual refclk */
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_PCIE, TYPE_USXGMII, NO_SSC), NULL},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_SGMII, TYPE_USXGMII, NO_SSC), &j7200_sgmii_100_no_ssc_tx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_QSGMII, TYPE_USXGMII, NO_SSC), &j7200_qsgmii_100_no_ssc_tx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_PCIE, NO_SSC), &ml_usxgmii_156_25_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_SGMII, NO_SSC), &usxgmii_156_25_no_ssc_tx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_QSGMII, NO_SSC), &usxgmii_156_25_no_ssc_tx_ln_vals},
+};
+
+static const struct cdns_torrent_vals_entry ti_j7200_rx_ln_vals_entries[] = {
+ {CDNS_TORRENT_KEY(CLK_19_2_MHZ, CLK_19_2_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_19_2_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_25_MHZ, CLK_25_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_25_no_ssc_rx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_PCIE, NO_SSC), &dp_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_USB, NO_SSC), &dp_100_no_ssc_rx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, NO_SSC), &pcie_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, EXTERNAL_SSC), &pcie_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, INTERNAL_SSC), &pcie_100_no_ssc_rx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, NO_SSC), &pcie_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, EXTERNAL_SSC), &pcie_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, INTERNAL_SSC), &pcie_100_no_ssc_rx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, NO_SSC), &pcie_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, EXTERNAL_SSC), &pcie_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, INTERNAL_SSC), &pcie_100_no_ssc_rx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, NO_SSC), &pcie_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, EXTERNAL_SSC), &pcie_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, INTERNAL_SSC), &pcie_100_no_ssc_rx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_DP, NO_SSC), &pcie_100_no_ssc_rx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_NONE, NO_SSC), &sgmii_100_no_ssc_rx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, NO_SSC), &sgmii_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, EXTERNAL_SSC), &sgmii_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, INTERNAL_SSC), &sgmii_100_no_ssc_rx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_QSGMII, NO_SSC), &sgmii_100_no_ssc_rx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, NO_SSC), &sgmii_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, EXTERNAL_SSC), &sgmii_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, INTERNAL_SSC), &sgmii_100_no_ssc_rx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_NONE, NO_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, NO_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, EXTERNAL_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, INTERNAL_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_SGMII, NO_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, NO_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, EXTERNAL_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, INTERNAL_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, NO_SSC), &usb_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, EXTERNAL_SSC), &usb_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, INTERNAL_SSC), &usb_100_no_ssc_rx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, NO_SSC), &usb_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, EXTERNAL_SSC), &usb_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, INTERNAL_SSC), &usb_100_no_ssc_rx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, NO_SSC), &usb_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, EXTERNAL_SSC), &usb_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, INTERNAL_SSC), &usb_100_no_ssc_rx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, NO_SSC), &usb_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, EXTERNAL_SSC), &usb_100_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, INTERNAL_SSC), &usb_100_no_ssc_rx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_DP, NO_SSC), &usb_100_no_ssc_rx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_156_25_MHZ, TYPE_USXGMII, TYPE_NONE, NO_SSC), &usxgmii_156_25_no_ssc_rx_ln_vals},
+
+ /* Dual refclk */
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_PCIE, TYPE_USXGMII, NO_SSC), &pcie_100_no_ssc_rx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_SGMII, TYPE_USXGMII, NO_SSC), &j7200_sgmii_100_no_ssc_rx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_QSGMII, TYPE_USXGMII, NO_SSC), &j7200_qsgmii_100_no_ssc_rx_ln_vals},
+
+ {CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_PCIE, NO_SSC), &ml_usxgmii_156_25_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_SGMII, NO_SSC), &usxgmii_156_25_no_ssc_rx_ln_vals},
+ {CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_QSGMII, NO_SSC), &usxgmii_156_25_no_ssc_rx_ln_vals},
+};
+
+static const struct cdns_torrent_data ti_j7200_map_torrent = {
+ .block_offset_shift = 0x0,
+ .reg_offset_shift = 0x1,
+ .link_cmn_vals_tbl = {
+ .entries = link_cmn_vals_entries,
+ .num_entries = ARRAY_SIZE(link_cmn_vals_entries),
+ },
+ .xcvr_diag_vals_tbl = {
+ .entries = xcvr_diag_vals_entries,
+ .num_entries = ARRAY_SIZE(xcvr_diag_vals_entries),
+ },
+ .pcs_cmn_vals_tbl = {
+ .entries = pcs_cmn_vals_entries,
+ .num_entries = ARRAY_SIZE(pcs_cmn_vals_entries),
+ },
+ .phy_pma_cmn_vals_tbl = {
+ .entries = j721e_phy_pma_cmn_vals_entries,
+ .num_entries = ARRAY_SIZE(j721e_phy_pma_cmn_vals_entries),
+ },
+ .cmn_vals_tbl = {
+ .entries = ti_j7200_cmn_vals_entries,
+ .num_entries = ARRAY_SIZE(ti_j7200_cmn_vals_entries),
+ },
+ .tx_ln_vals_tbl = {
+ .entries = ti_j7200_tx_ln_vals_entries,
+ .num_entries = ARRAY_SIZE(ti_j7200_tx_ln_vals_entries),
+ },
+ .rx_ln_vals_tbl = {
+ .entries = ti_j7200_rx_ln_vals_entries,
+ .num_entries = ARRAY_SIZE(ti_j7200_rx_ln_vals_entries),
+ },
+};
+
static const struct of_device_id cdns_torrent_phy_of_match[] = {
{
.compatible = "cdns,torrent-phy",
@@ -4563,16 +5430,21 @@ static const struct of_device_id cdns_torrent_phy_of_match[] = {
.compatible = "ti,j721e-serdes-10g",
.data = &ti_j721e_map_torrent,
},
+ {
+ .compatible = "ti,j7200-serdes-10g",
+ .data = &ti_j7200_map_torrent,
+ },
{}
};
MODULE_DEVICE_TABLE(of, cdns_torrent_phy_of_match);
static struct platform_driver cdns_torrent_phy_driver = {
.probe = cdns_torrent_phy_probe,
- .remove_new = cdns_torrent_phy_remove,
- .driver = {
+ .remove = cdns_torrent_phy_remove,
+ .driver = {
.name = "cdns-torrent-phy",
.of_match_table = cdns_torrent_phy_of_match,
+ .pm = pm_sleep_ptr(&cdns_torrent_phy_pm_ops),
}
};
module_platform_driver(cdns_torrent_phy_driver);
diff --git a/drivers/phy/freescale/Kconfig b/drivers/phy/freescale/Kconfig
index 853958fb2c06..dcd9acff6d01 100644
--- a/drivers/phy/freescale/Kconfig
+++ b/drivers/phy/freescale/Kconfig
@@ -35,6 +35,19 @@ config PHY_FSL_IMX8M_PCIE
Enable this to add support for the PCIE PHY as found on
i.MX8M family of SOCs.
+config PHY_FSL_IMX8QM_HSIO
+ tristate "Freescale i.MX8QM HSIO PHY"
+ depends on OF && HAS_IOMEM
+ select GENERIC_PHY
+ help
+ Enable this to add support for the HSIO PHY as found on
+ i.MX8QM family of SOCs.
+
+config PHY_FSL_SAMSUNG_HDMI_PHY
+ tristate "Samsung HDMI PHY support"
+ depends on OF && HAS_IOMEM && COMMON_CLK
+ help
+ Enable this to add support for the Samsung HDMI PHY in i.MX8MP.
endif
config PHY_FSL_LYNX_28G
diff --git a/drivers/phy/freescale/Makefile b/drivers/phy/freescale/Makefile
index cedb328bc4d2..658eac7d0a62 100644
--- a/drivers/phy/freescale/Makefile
+++ b/drivers/phy/freescale/Makefile
@@ -3,4 +3,6 @@ obj-$(CONFIG_PHY_FSL_IMX8MQ_USB) += phy-fsl-imx8mq-usb.o
obj-$(CONFIG_PHY_MIXEL_LVDS_PHY) += phy-fsl-imx8qm-lvds-phy.o
obj-$(CONFIG_PHY_MIXEL_MIPI_DPHY) += phy-fsl-imx8-mipi-dphy.o
obj-$(CONFIG_PHY_FSL_IMX8M_PCIE) += phy-fsl-imx8m-pcie.o
+obj-$(CONFIG_PHY_FSL_IMX8QM_HSIO) += phy-fsl-imx8qm-hsio.o
obj-$(CONFIG_PHY_FSL_LYNX_28G) += phy-fsl-lynx-28g.o
+obj-$(CONFIG_PHY_FSL_SAMSUNG_HDMI_PHY) += phy-fsl-samsung-hdmi.o
diff --git a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
index b700f52b7b67..e98361dcdead 100644
--- a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
+++ b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
@@ -110,8 +110,10 @@ static int imx8_pcie_phy_power_on(struct phy *phy)
/* Source clock from SoC internal PLL */
writel(ANA_PLL_CLK_OUT_TO_EXT_IO_SEL,
imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG062);
- writel(AUX_PLL_REFCLK_SEL_SYS_PLL,
- imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG063);
+ if (imx8_phy->drvdata->variant != IMX8MM) {
+ writel(AUX_PLL_REFCLK_SEL_SYS_PLL,
+ imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG063);
+ }
val = ANA_AUX_RX_TX_SEL_TX | ANA_AUX_TX_TERM;
writel(val | ANA_AUX_RX_TERM_GND_EN,
imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG064);
@@ -139,11 +141,6 @@ static int imx8_pcie_phy_power_on(struct phy *phy)
IMX8MM_GPR_PCIE_REF_CLK_PLL);
usleep_range(100, 200);
- /* Do the PHY common block reset */
- regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
- IMX8MM_GPR_PCIE_CMN_RST,
- IMX8MM_GPR_PCIE_CMN_RST);
-
switch (imx8_phy->drvdata->variant) {
case IMX8MP:
reset_control_deassert(imx8_phy->perst);
@@ -154,6 +151,11 @@ static int imx8_pcie_phy_power_on(struct phy *phy)
break;
}
+ /* Do the PHY common block reset */
+ regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
+ IMX8MM_GPR_PCIE_CMN_RST,
+ IMX8MM_GPR_PCIE_CMN_RST);
+
/* Polling to check the phy is ready or not. */
ret = readl_poll_timeout(imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG075,
val, val == ANA_PLL_DONE, 10, 20000);
diff --git a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
index 0b9a59d5b8f0..adc6394626ce 100644
--- a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
+++ b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c
@@ -176,7 +176,7 @@ static void imx8m_get_phy_tuning_data(struct imx8mq_usb_phy *imx_phy)
imx_phy->comp_dis_tune =
phy_comp_dis_tune_from_property(imx_phy->comp_dis_tune);
- if (device_property_read_u32(dev, "fsl,pcs-tx-deemph-3p5db-attenuation-db",
+ if (device_property_read_u32(dev, "fsl,phy-pcs-tx-deemph-3p5db-attenuation-db",
&imx_phy->pcs_tx_deemph_3p5db))
imx_phy->pcs_tx_deemph_3p5db = PHY_TUNE_DEFAULT;
else
diff --git a/drivers/phy/freescale/phy-fsl-imx8qm-hsio.c b/drivers/phy/freescale/phy-fsl-imx8qm-hsio.c
new file mode 100644
index 000000000000..5dca93cd325c
--- /dev/null
+++ b/drivers/phy/freescale/phy-fsl-imx8qm-hsio.c
@@ -0,0 +1,611 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2024 NXP
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pci_regs.h>
+#include <linux/phy/phy.h>
+#include <linux/phy/pcie.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/phy/phy-imx8-pcie.h>
+
+#define MAX_NUM_LANE 3
+#define LANE_NUM_CLKS 5
+
+/* Parameters for the waiting for PCIe PHY PLL to lock */
+#define PHY_INIT_WAIT_USLEEP_MAX 10
+#define PHY_INIT_WAIT_TIMEOUT (1000 * PHY_INIT_WAIT_USLEEP_MAX)
+
+/* i.MX8Q HSIO registers */
+#define HSIO_CTRL0 0x0
+#define HSIO_APB_RSTN_0 BIT(0)
+#define HSIO_APB_RSTN_1 BIT(1)
+#define HSIO_PIPE_RSTN_0_MASK GENMASK(25, 24)
+#define HSIO_PIPE_RSTN_1_MASK GENMASK(27, 26)
+#define HSIO_MODE_MASK GENMASK(20, 17)
+#define HSIO_MODE_PCIE 0x0
+#define HSIO_MODE_SATA 0x4
+#define HSIO_DEVICE_TYPE_MASK GENMASK(27, 24)
+#define HSIO_EPCS_TXDEEMP BIT(5)
+#define HSIO_EPCS_TXDEEMP_SEL BIT(6)
+#define HSIO_EPCS_PHYRESET_N BIT(7)
+#define HSIO_RESET_N BIT(12)
+
+#define HSIO_IOB_RXENA BIT(0)
+#define HSIO_IOB_TXENA BIT(1)
+#define HSIO_IOB_A_0_TXOE BIT(2)
+#define HSIO_IOB_A_0_M1M0_2 BIT(4)
+#define HSIO_IOB_A_0_M1M0_MASK GENMASK(4, 3)
+#define HSIO_PHYX1_EPCS_SEL BIT(12)
+#define HSIO_PCIE_AB_SELECT BIT(13)
+
+#define HSIO_PHY_STS0 0x4
+#define HSIO_LANE0_TX_PLL_LOCK BIT(4)
+#define HSIO_LANE1_TX_PLL_LOCK BIT(12)
+
+#define HSIO_CTRL2 0x8
+#define HSIO_LTSSM_ENABLE BIT(4)
+#define HSIO_BUTTON_RST_N BIT(21)
+#define HSIO_PERST_N BIT(22)
+#define HSIO_POWER_UP_RST_N BIT(23)
+
+#define HSIO_PCIE_STS0 0xc
+#define HSIO_PM_REQ_CORE_RST BIT(19)
+
+#define HSIO_REG48_PMA_STATUS 0x30
+#define HSIO_REG48_PMA_RDY BIT(7)
+
+struct imx_hsio_drvdata {
+ int lane_num;
+};
+
+struct imx_hsio_lane {
+ u32 ctrl_index;
+ u32 ctrl_off;
+ u32 idx;
+ u32 phy_off;
+ u32 phy_type;
+ const char * const *clk_names;
+ struct clk_bulk_data clks[LANE_NUM_CLKS];
+ struct imx_hsio_priv *priv;
+ struct phy *phy;
+ enum phy_mode phy_mode;
+};
+
+struct imx_hsio_priv {
+ void __iomem *base;
+ struct device *dev;
+ struct mutex lock;
+ const char *hsio_cfg;
+ const char *refclk_pad;
+ u32 open_cnt;
+ struct regmap *phy;
+ struct regmap *ctrl;
+ struct regmap *misc;
+ const struct imx_hsio_drvdata *drvdata;
+ struct imx_hsio_lane lane[MAX_NUM_LANE];
+};
+
+static const char * const lan0_pcie_clks[] = {"apb_pclk0", "pclk0", "ctl0_crr",
+ "phy0_crr", "misc_crr"};
+static const char * const lan1_pciea_clks[] = {"apb_pclk1", "pclk1", "ctl0_crr",
+ "phy0_crr", "misc_crr"};
+static const char * const lan1_pcieb_clks[] = {"apb_pclk1", "pclk1", "ctl1_crr",
+ "phy0_crr", "misc_crr"};
+static const char * const lan2_pcieb_clks[] = {"apb_pclk2", "pclk2", "ctl1_crr",
+ "phy1_crr", "misc_crr"};
+static const char * const lan2_sata_clks[] = {"pclk2", "epcs_tx", "epcs_rx",
+ "phy1_crr", "misc_crr"};
+
+static const struct regmap_config regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
+static int imx_hsio_init(struct phy *phy)
+{
+ int ret, i;
+ struct imx_hsio_lane *lane = phy_get_drvdata(phy);
+ struct imx_hsio_priv *priv = lane->priv;
+ struct device *dev = priv->dev;
+
+ /* Assign clocks refer to different modes */
+ switch (lane->phy_type) {
+ case PHY_TYPE_PCIE:
+ lane->phy_mode = PHY_MODE_PCIE;
+ if (lane->ctrl_index == 0) { /* PCIEA */
+ lane->ctrl_off = 0;
+ lane->phy_off = 0;
+
+ for (i = 0; i < LANE_NUM_CLKS; i++) {
+ if (lane->idx == 0)
+ lane->clks[i].id = lan0_pcie_clks[i];
+ else
+ lane->clks[i].id = lan1_pciea_clks[i];
+ }
+ } else { /* PCIEB */
+ if (lane->idx == 0) { /* i.MX8QXP */
+ lane->ctrl_off = 0;
+ lane->phy_off = 0;
+ } else {
+ /*
+ * On i.MX8QM, only second or third lane can be
+ * bound to PCIEB.
+ */
+ lane->ctrl_off = SZ_64K;
+ if (lane->idx == 1)
+ lane->phy_off = 0;
+ else /* the third lane is bound to PCIEB */
+ lane->phy_off = SZ_64K;
+ }
+
+ for (i = 0; i < LANE_NUM_CLKS; i++) {
+ if (lane->idx == 1)
+ lane->clks[i].id = lan1_pcieb_clks[i];
+ else if (lane->idx == 2)
+ lane->clks[i].id = lan2_pcieb_clks[i];
+ else /* i.MX8QXP only has PCIEB, idx is 0 */
+ lane->clks[i].id = lan0_pcie_clks[i];
+ }
+ }
+ break;
+ case PHY_TYPE_SATA:
+ /* On i.MX8QM, only the third lane can be bound to SATA */
+ lane->phy_mode = PHY_MODE_SATA;
+ lane->ctrl_off = SZ_128K;
+ lane->phy_off = SZ_64K;
+
+ for (i = 0; i < LANE_NUM_CLKS; i++)
+ lane->clks[i].id = lan2_sata_clks[i];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Fetch clocks and enable them */
+ ret = devm_clk_bulk_get(dev, LANE_NUM_CLKS, lane->clks);
+ if (ret)
+ return ret;
+ ret = clk_bulk_prepare_enable(LANE_NUM_CLKS, lane->clks);
+ if (ret)
+ return ret;
+
+ /* allow the clocks to stabilize */
+ usleep_range(200, 500);
+ return 0;
+}
+
+static int imx_hsio_exit(struct phy *phy)
+{
+ struct imx_hsio_lane *lane = phy_get_drvdata(phy);
+
+ clk_bulk_disable_unprepare(LANE_NUM_CLKS, lane->clks);
+
+ return 0;
+}
+
+static void imx_hsio_pcie_phy_resets(struct phy *phy)
+{
+ struct imx_hsio_lane *lane = phy_get_drvdata(phy);
+ struct imx_hsio_priv *priv = lane->priv;
+
+ regmap_clear_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL2,
+ HSIO_BUTTON_RST_N);
+ regmap_clear_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL2,
+ HSIO_PERST_N);
+ regmap_clear_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL2,
+ HSIO_POWER_UP_RST_N);
+ regmap_set_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL2,
+ HSIO_BUTTON_RST_N);
+ regmap_set_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL2,
+ HSIO_PERST_N);
+ regmap_set_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL2,
+ HSIO_POWER_UP_RST_N);
+
+ if (lane->idx == 1) {
+ regmap_set_bits(priv->phy, lane->phy_off + HSIO_CTRL0,
+ HSIO_APB_RSTN_1);
+ regmap_set_bits(priv->phy, lane->phy_off + HSIO_CTRL0,
+ HSIO_PIPE_RSTN_1_MASK);
+ } else {
+ regmap_set_bits(priv->phy, lane->phy_off + HSIO_CTRL0,
+ HSIO_APB_RSTN_0);
+ regmap_set_bits(priv->phy, lane->phy_off + HSIO_CTRL0,
+ HSIO_PIPE_RSTN_0_MASK);
+ }
+}
+
+static void imx_hsio_sata_phy_resets(struct phy *phy)
+{
+ struct imx_hsio_lane *lane = phy_get_drvdata(phy);
+ struct imx_hsio_priv *priv = lane->priv;
+
+ /* clear PHY RST, then set it */
+ regmap_clear_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL0,
+ HSIO_EPCS_PHYRESET_N);
+ regmap_set_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL0,
+ HSIO_EPCS_PHYRESET_N);
+
+ /* CTRL RST: SET -> delay 1 us -> CLEAR -> SET */
+ regmap_set_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL0, HSIO_RESET_N);
+ udelay(1);
+ regmap_clear_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL0,
+ HSIO_RESET_N);
+ regmap_set_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL0, HSIO_RESET_N);
+}
+
+static void imx_hsio_configure_clk_pad(struct phy *phy)
+{
+ bool pll = false;
+ struct imx_hsio_lane *lane = phy_get_drvdata(phy);
+ struct imx_hsio_priv *priv = lane->priv;
+
+ if (strncmp(priv->refclk_pad, "output", 6) == 0) {
+ pll = true;
+ regmap_update_bits(priv->misc, HSIO_CTRL0,
+ HSIO_IOB_A_0_TXOE | HSIO_IOB_A_0_M1M0_MASK,
+ HSIO_IOB_A_0_TXOE | HSIO_IOB_A_0_M1M0_2);
+ } else {
+ regmap_update_bits(priv->misc, HSIO_CTRL0,
+ HSIO_IOB_A_0_TXOE | HSIO_IOB_A_0_M1M0_MASK,
+ 0);
+ }
+
+ regmap_update_bits(priv->misc, HSIO_CTRL0, HSIO_IOB_RXENA,
+ pll ? 0 : HSIO_IOB_RXENA);
+ regmap_update_bits(priv->misc, HSIO_CTRL0, HSIO_IOB_TXENA,
+ pll ? HSIO_IOB_TXENA : 0);
+}
+
+static void imx_hsio_pre_set(struct phy *phy)
+{
+ struct imx_hsio_lane *lane = phy_get_drvdata(phy);
+ struct imx_hsio_priv *priv = lane->priv;
+
+ if (strncmp(priv->hsio_cfg, "pciea-x2-pcieb", 14) == 0) {
+ regmap_set_bits(priv->misc, HSIO_CTRL0, HSIO_PCIE_AB_SELECT);
+ } else if (strncmp(priv->hsio_cfg, "pciea-x2-sata", 13) == 0) {
+ regmap_set_bits(priv->misc, HSIO_CTRL0, HSIO_PHYX1_EPCS_SEL);
+ } else if (strncmp(priv->hsio_cfg, "pciea-pcieb-sata", 16) == 0) {
+ regmap_set_bits(priv->misc, HSIO_CTRL0, HSIO_PCIE_AB_SELECT);
+ regmap_set_bits(priv->misc, HSIO_CTRL0, HSIO_PHYX1_EPCS_SEL);
+ }
+
+ imx_hsio_configure_clk_pad(phy);
+}
+
+static int imx_hsio_pcie_power_on(struct phy *phy)
+{
+ int ret;
+ u32 val, addr, cond;
+ struct imx_hsio_lane *lane = phy_get_drvdata(phy);
+ struct imx_hsio_priv *priv = lane->priv;
+
+ imx_hsio_pcie_phy_resets(phy);
+
+ /* Toggle apb_pclk to make sure PM_REQ_CORE_RST is cleared. */
+ clk_disable_unprepare(lane->clks[0].clk);
+ mdelay(1);
+ ret = clk_prepare_enable(lane->clks[0].clk);
+ if (ret) {
+ dev_err(priv->dev, "unable to enable phy apb_pclk\n");
+ return ret;
+ }
+
+ addr = lane->ctrl_off + HSIO_PCIE_STS0;
+ cond = HSIO_PM_REQ_CORE_RST;
+ ret = regmap_read_poll_timeout(priv->ctrl, addr, val,
+ (val & cond) == 0,
+ PHY_INIT_WAIT_USLEEP_MAX,
+ PHY_INIT_WAIT_TIMEOUT);
+ if (ret)
+ dev_err(priv->dev, "HSIO_PM_REQ_CORE_RST is set\n");
+ return ret;
+}
+
+static int imx_hsio_sata_power_on(struct phy *phy)
+{
+ int ret;
+ u32 val, cond;
+ struct imx_hsio_lane *lane = phy_get_drvdata(phy);
+ struct imx_hsio_priv *priv = lane->priv;
+
+ regmap_set_bits(priv->phy, lane->phy_off + HSIO_CTRL0, HSIO_APB_RSTN_0);
+ regmap_set_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL0,
+ HSIO_EPCS_TXDEEMP);
+ regmap_set_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL0,
+ HSIO_EPCS_TXDEEMP_SEL);
+
+ imx_hsio_sata_phy_resets(phy);
+
+ cond = HSIO_REG48_PMA_RDY;
+ ret = read_poll_timeout(readb, val, ((val & cond) == cond),
+ PHY_INIT_WAIT_USLEEP_MAX,
+ PHY_INIT_WAIT_TIMEOUT, false,
+ priv->base + HSIO_REG48_PMA_STATUS);
+ if (ret)
+ dev_err(priv->dev, "PHY calibration is timeout\n");
+ else
+ dev_dbg(priv->dev, "PHY calibration is done\n");
+
+ return ret;
+}
+
+static int imx_hsio_power_on(struct phy *phy)
+{
+ int ret;
+ u32 val, cond;
+ struct imx_hsio_lane *lane = phy_get_drvdata(phy);
+ struct imx_hsio_priv *priv = lane->priv;
+
+ scoped_guard(mutex, &priv->lock) {
+ if (!priv->open_cnt)
+ imx_hsio_pre_set(phy);
+ priv->open_cnt++;
+ }
+
+ if (lane->phy_mode == PHY_MODE_PCIE)
+ ret = imx_hsio_pcie_power_on(phy);
+ else /* SATA */
+ ret = imx_hsio_sata_power_on(phy);
+ if (ret)
+ return ret;
+
+ /* Polling to check the PHY is ready or not. */
+ if (lane->idx == 1)
+ cond = HSIO_LANE1_TX_PLL_LOCK;
+ else
+ /*
+ * Except the phy_off, the bit-offset of lane2 is same to lane0.
+ * Merge the lane0 and lane2 bit-operations together.
+ */
+ cond = HSIO_LANE0_TX_PLL_LOCK;
+
+ ret = regmap_read_poll_timeout(priv->phy, lane->phy_off + HSIO_PHY_STS0,
+ val, ((val & cond) == cond),
+ PHY_INIT_WAIT_USLEEP_MAX,
+ PHY_INIT_WAIT_TIMEOUT);
+ if (ret) {
+ dev_err(priv->dev, "IMX8Q PHY%d PLL lock timeout\n", lane->idx);
+ return ret;
+ }
+ dev_dbg(priv->dev, "IMX8Q PHY%d PLL is locked\n", lane->idx);
+
+ return ret;
+}
+
+static int imx_hsio_power_off(struct phy *phy)
+{
+ struct imx_hsio_lane *lane = phy_get_drvdata(phy);
+ struct imx_hsio_priv *priv = lane->priv;
+
+ scoped_guard(mutex, &priv->lock) {
+ priv->open_cnt--;
+ if (priv->open_cnt == 0) {
+ regmap_clear_bits(priv->misc, HSIO_CTRL0,
+ HSIO_PCIE_AB_SELECT);
+ regmap_clear_bits(priv->misc, HSIO_CTRL0,
+ HSIO_PHYX1_EPCS_SEL);
+
+ if (lane->phy_mode == PHY_MODE_PCIE) {
+ regmap_clear_bits(priv->ctrl,
+ lane->ctrl_off + HSIO_CTRL2,
+ HSIO_BUTTON_RST_N);
+ regmap_clear_bits(priv->ctrl,
+ lane->ctrl_off + HSIO_CTRL2,
+ HSIO_PERST_N);
+ regmap_clear_bits(priv->ctrl,
+ lane->ctrl_off + HSIO_CTRL2,
+ HSIO_POWER_UP_RST_N);
+ } else {
+ regmap_clear_bits(priv->ctrl,
+ lane->ctrl_off + HSIO_CTRL0,
+ HSIO_EPCS_TXDEEMP);
+ regmap_clear_bits(priv->ctrl,
+ lane->ctrl_off + HSIO_CTRL0,
+ HSIO_EPCS_TXDEEMP_SEL);
+ regmap_clear_bits(priv->ctrl,
+ lane->ctrl_off + HSIO_CTRL0,
+ HSIO_RESET_N);
+ }
+
+ if (lane->idx == 1) {
+ regmap_clear_bits(priv->phy,
+ lane->phy_off + HSIO_CTRL0,
+ HSIO_APB_RSTN_1);
+ regmap_clear_bits(priv->phy,
+ lane->phy_off + HSIO_CTRL0,
+ HSIO_PIPE_RSTN_1_MASK);
+ } else {
+ /*
+ * Except the phy_off, the bit-offset of lane2 is same
+ * to lane0. Merge the lane0 and lane2 bit-operations
+ * together.
+ */
+ regmap_clear_bits(priv->phy,
+ lane->phy_off + HSIO_CTRL0,
+ HSIO_APB_RSTN_0);
+ regmap_clear_bits(priv->phy,
+ lane->phy_off + HSIO_CTRL0,
+ HSIO_PIPE_RSTN_0_MASK);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int imx_hsio_set_mode(struct phy *phy, enum phy_mode mode,
+ int submode)
+{
+ u32 val;
+ struct imx_hsio_lane *lane = phy_get_drvdata(phy);
+ struct imx_hsio_priv *priv = lane->priv;
+
+ if (lane->phy_mode != mode)
+ return -EINVAL;
+
+ val = (mode == PHY_MODE_PCIE) ? HSIO_MODE_PCIE : HSIO_MODE_SATA;
+ val = FIELD_PREP(HSIO_MODE_MASK, val);
+ regmap_update_bits(priv->phy, lane->phy_off + HSIO_CTRL0,
+ HSIO_MODE_MASK, val);
+
+ switch (submode) {
+ case PHY_MODE_PCIE_RC:
+ val = FIELD_PREP(HSIO_DEVICE_TYPE_MASK, PCI_EXP_TYPE_ROOT_PORT);
+ break;
+ case PHY_MODE_PCIE_EP:
+ val = FIELD_PREP(HSIO_DEVICE_TYPE_MASK, PCI_EXP_TYPE_ENDPOINT);
+ break;
+ default: /* Support only PCIe EP and RC now. */
+ return 0;
+ }
+ if (submode)
+ regmap_update_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL0,
+ HSIO_DEVICE_TYPE_MASK, val);
+
+ return 0;
+}
+
+static int imx_hsio_set_speed(struct phy *phy, int speed)
+{
+ struct imx_hsio_lane *lane = phy_get_drvdata(phy);
+ struct imx_hsio_priv *priv = lane->priv;
+
+ regmap_update_bits(priv->ctrl, lane->ctrl_off + HSIO_CTRL2,
+ HSIO_LTSSM_ENABLE,
+ speed ? HSIO_LTSSM_ENABLE : 0);
+ return 0;
+}
+
+static const struct phy_ops imx_hsio_ops = {
+ .init = imx_hsio_init,
+ .exit = imx_hsio_exit,
+ .power_on = imx_hsio_power_on,
+ .power_off = imx_hsio_power_off,
+ .set_mode = imx_hsio_set_mode,
+ .set_speed = imx_hsio_set_speed,
+ .owner = THIS_MODULE,
+};
+
+static const struct imx_hsio_drvdata imx8qxp_hsio_drvdata = {
+ .lane_num = 0x1,
+};
+
+static const struct imx_hsio_drvdata imx8qm_hsio_drvdata = {
+ .lane_num = 0x3,
+};
+
+static const struct of_device_id imx_hsio_of_match[] = {
+ {.compatible = "fsl,imx8qm-hsio", .data = &imx8qm_hsio_drvdata},
+ {.compatible = "fsl,imx8qxp-hsio", .data = &imx8qxp_hsio_drvdata},
+ { },
+};
+MODULE_DEVICE_TABLE(of, imx_hsio_of_match);
+
+static struct phy *imx_hsio_xlate(struct device *dev,
+ const struct of_phandle_args *args)
+{
+ struct imx_hsio_priv *priv = dev_get_drvdata(dev);
+ int idx = args->args[0];
+ int phy_type = args->args[1];
+ int ctrl_index = args->args[2];
+
+ if (idx < 0 || idx >= priv->drvdata->lane_num)
+ return ERR_PTR(-EINVAL);
+ priv->lane[idx].idx = idx;
+ priv->lane[idx].phy_type = phy_type;
+ priv->lane[idx].ctrl_index = ctrl_index;
+
+ return priv->lane[idx].phy;
+}
+
+static int imx_hsio_probe(struct platform_device *pdev)
+{
+ int i;
+ void __iomem *off;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct imx_hsio_priv *priv;
+ struct phy_provider *provider;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+ priv->dev = &pdev->dev;
+ priv->drvdata = of_device_get_match_data(dev);
+
+ /* Get HSIO configuration mode */
+ if (of_property_read_string(np, "fsl,hsio-cfg", &priv->hsio_cfg))
+ priv->hsio_cfg = "pciea-pcieb-sata";
+ /* Get PHY refclk pad mode */
+ if (of_property_read_string(np, "fsl,refclk-pad-mode",
+ &priv->refclk_pad))
+ priv->refclk_pad = NULL;
+
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ off = devm_platform_ioremap_resource_byname(pdev, "phy");
+ priv->phy = devm_regmap_init_mmio(dev, off, &regmap_config);
+ if (IS_ERR(priv->phy))
+ return dev_err_probe(dev, PTR_ERR(priv->phy),
+ "unable to find phy csr registers\n");
+
+ off = devm_platform_ioremap_resource_byname(pdev, "ctrl");
+ priv->ctrl = devm_regmap_init_mmio(dev, off, &regmap_config);
+ if (IS_ERR(priv->ctrl))
+ return dev_err_probe(dev, PTR_ERR(priv->ctrl),
+ "unable to find ctrl csr registers\n");
+
+ off = devm_platform_ioremap_resource_byname(pdev, "misc");
+ priv->misc = devm_regmap_init_mmio(dev, off, &regmap_config);
+ if (IS_ERR(priv->misc))
+ return dev_err_probe(dev, PTR_ERR(priv->misc),
+ "unable to find misc csr registers\n");
+
+ for (i = 0; i < priv->drvdata->lane_num; i++) {
+ struct imx_hsio_lane *lane = &priv->lane[i];
+ struct phy *phy;
+
+ phy = devm_phy_create(&pdev->dev, NULL, &imx_hsio_ops);
+ if (IS_ERR(phy))
+ return PTR_ERR(phy);
+
+ lane->priv = priv;
+ lane->phy = phy;
+ lane->idx = i;
+ phy_set_drvdata(phy, lane);
+ }
+
+ dev_set_drvdata(dev, priv);
+ dev_set_drvdata(&pdev->dev, priv);
+
+ provider = devm_of_phy_provider_register(&pdev->dev, imx_hsio_xlate);
+
+ return PTR_ERR_OR_ZERO(provider);
+}
+
+static struct platform_driver imx_hsio_driver = {
+ .probe = imx_hsio_probe,
+ .driver = {
+ .name = "imx8qm-hsio-phy",
+ .of_match_table = imx_hsio_of_match,
+ }
+};
+module_platform_driver(imx_hsio_driver);
+
+MODULE_DESCRIPTION("FSL IMX8QM HSIO SERDES PHY driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c b/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c
index 0ae052df3765..7aef2f59e8eb 100644
--- a/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c
+++ b/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c
@@ -294,7 +294,7 @@ static int mixel_lvds_phy_reset(struct device *dev)
}
static struct phy *mixel_lvds_phy_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct mixel_lvds_phy_priv *priv = dev_get_drvdata(dev);
unsigned int phy_id;
@@ -433,12 +433,12 @@ static const struct of_device_id mixel_lvds_phy_of_match[] = {
MODULE_DEVICE_TABLE(of, mixel_lvds_phy_of_match);
static struct platform_driver mixel_lvds_phy_driver = {
- .probe = mixel_lvds_phy_probe,
- .remove_new = mixel_lvds_phy_remove,
+ .probe = mixel_lvds_phy_probe,
+ .remove = mixel_lvds_phy_remove,
.driver = {
.pm = &mixel_lvds_phy_pm_ops,
.name = "mixel-lvds-phy",
- .of_match_table = mixel_lvds_phy_of_match,
+ .of_match_table = mixel_lvds_phy_of_match,
}
};
module_platform_driver(mixel_lvds_phy_driver);
diff --git a/drivers/phy/freescale/phy-fsl-lynx-28g.c b/drivers/phy/freescale/phy-fsl-lynx-28g.c
index e2187767ce00..f7994e8983c8 100644
--- a/drivers/phy/freescale/phy-fsl-lynx-28g.c
+++ b/drivers/phy/freescale/phy-fsl-lynx-28g.c
@@ -556,7 +556,7 @@ static void lynx_28g_lane_read_configuration(struct lynx_28g_lane *lane)
}
static struct phy *lynx_28g_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct lynx_28g_priv *priv = dev_get_drvdata(dev);
int idx = args->args[0];
@@ -631,9 +631,9 @@ static const struct of_device_id lynx_28g_of_match_table[] = {
MODULE_DEVICE_TABLE(of, lynx_28g_of_match_table);
static struct platform_driver lynx_28g_driver = {
- .probe = lynx_28g_probe,
- .remove_new = lynx_28g_remove,
- .driver = {
+ .probe = lynx_28g_probe,
+ .remove = lynx_28g_remove,
+ .driver = {
.name = "lynx-28g",
.of_match_table = lynx_28g_of_match_table,
},
diff --git a/drivers/phy/freescale/phy-fsl-samsung-hdmi.c b/drivers/phy/freescale/phy-fsl-samsung-hdmi.c
new file mode 100644
index 000000000000..e4c0a82d16d9
--- /dev/null
+++ b/drivers/phy/freescale/phy-fsl-samsung-hdmi.c
@@ -0,0 +1,765 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020 NXP
+ * Copyright 2022 Pengutronix, Lucas Stach <kernel@pengutronix.de>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+#define PHY_REG(reg) (reg * 4)
+
+#define REG01_PMS_P_MASK GENMASK(3, 0)
+#define REG03_PMS_S_MASK GENMASK(7, 4)
+#define REG12_CK_DIV_MASK GENMASK(5, 4)
+
+#define REG13_TG_CODE_LOW_MASK GENMASK(7, 0)
+
+#define REG14_TOL_MASK GENMASK(7, 4)
+#define REG14_RP_CODE_MASK GENMASK(3, 1)
+#define REG14_TG_CODE_HIGH_MASK GENMASK(0, 0)
+
+#define REG21_SEL_TX_CK_INV BIT(7)
+#define REG21_PMS_S_MASK GENMASK(3, 0)
+/*
+ * REG33 does not match the ref manual. According to Sandor Yu from NXP,
+ * "There is a doc issue on the i.MX8MP latest RM"
+ * REG33 is being used per guidance from Sandor
+ */
+#define REG33_MODE_SET_DONE BIT(7)
+#define REG33_FIX_DA BIT(1)
+
+#define REG34_PHY_READY BIT(7)
+#define REG34_PLL_LOCK BIT(6)
+#define REG34_PHY_CLK_READY BIT(5)
+
+#ifndef MHZ
+#define MHZ (1000UL * 1000UL)
+#endif
+
+#define PHY_PLL_DIV_REGS_NUM 7
+
+struct phy_config {
+ u32 pixclk;
+ u8 pll_div_regs[PHY_PLL_DIV_REGS_NUM];
+};
+
+/*
+ * The calculated_phy_pll_cfg only handles integer divider for PMS,
+ * meaning the last four entries will be fixed, but the first three will
+ * be calculated by the PMS calculator.
+ */
+static struct phy_config calculated_phy_pll_cfg = {
+ .pixclk = 0,
+ .pll_div_regs = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 },
+};
+
+/* The lookup table contains values for which the fractional divder is used */
+static const struct phy_config phy_pll_cfg[] = {
+ {
+ .pixclk = 22250000,
+ .pll_div_regs = { 0xd1, 0x4b, 0xf1, 0x89, 0x88, 0x80, 0x40 },
+ }, {
+ .pixclk = 23750000,
+ .pll_div_regs = { 0xd1, 0x50, 0xf1, 0x86, 0x85, 0x80, 0x40 },
+ }, {
+ .pixclk = 24024000,
+ .pll_div_regs = { 0xd1, 0x50, 0xf1, 0x99, 0x02, 0x80, 0x40 },
+ }, {
+ .pixclk = 25175000,
+ .pll_div_regs = { 0xd1, 0x54, 0xfc, 0xcc, 0x91, 0x80, 0x40 },
+ }, {
+ .pixclk = 26750000,
+ .pll_div_regs = { 0xd1, 0x5a, 0xf2, 0x89, 0x88, 0x80, 0x40 },
+ }, {
+ .pixclk = 27027000,
+ .pll_div_regs = { 0xd1, 0x5a, 0xf2, 0xfd, 0x0c, 0x80, 0x40 },
+ }, {
+ .pixclk = 29500000,
+ .pll_div_regs = { 0xd1, 0x62, 0xf4, 0x95, 0x08, 0x80, 0x40 },
+ }, {
+ .pixclk = 30750000,
+ .pll_div_regs = { 0xd1, 0x66, 0xf4, 0x82, 0x01, 0x88, 0x45 },
+ }, {
+ .pixclk = 30888000,
+ .pll_div_regs = { 0xd1, 0x66, 0xf4, 0x99, 0x18, 0x88, 0x45 },
+ }, {
+ .pixclk = 33750000,
+ .pll_div_regs = { 0xd1, 0x70, 0xf4, 0x82, 0x01, 0x80, 0x40 },
+ }, {
+ .pixclk = 35000000,
+ .pll_div_regs = { 0xd1, 0x58, 0xb8, 0x8b, 0x88, 0x80, 0x40 },
+ }, {
+ .pixclk = 36036000,
+ .pll_div_regs = { 0xd1, 0x5a, 0xb2, 0xfd, 0x0c, 0x80, 0x40 },
+ }, {
+ .pixclk = 43243200,
+ .pll_div_regs = { 0xd1, 0x5a, 0x92, 0xfd, 0x0c, 0x80, 0x40 },
+ }, {
+ .pixclk = 44500000,
+ .pll_div_regs = { 0xd1, 0x5c, 0x92, 0x98, 0x11, 0x84, 0x41 },
+ }, {
+ .pixclk = 47000000,
+ .pll_div_regs = { 0xd1, 0x62, 0x94, 0x95, 0x82, 0x80, 0x40 },
+ }, {
+ .pixclk = 47500000,
+ .pll_div_regs = { 0xd1, 0x63, 0x96, 0xa1, 0x82, 0x80, 0x40 },
+ }, {
+ .pixclk = 50349650,
+ .pll_div_regs = { 0xd1, 0x54, 0x7c, 0xc3, 0x8f, 0x80, 0x40 },
+ }, {
+ .pixclk = 53250000,
+ .pll_div_regs = { 0xd1, 0x58, 0x72, 0x84, 0x03, 0x82, 0x41 },
+ }, {
+ .pixclk = 53500000,
+ .pll_div_regs = { 0xd1, 0x5a, 0x72, 0x89, 0x88, 0x80, 0x40 },
+ }, {
+ .pixclk = 54054000,
+ .pll_div_regs = { 0xd1, 0x5a, 0x72, 0xfd, 0x0c, 0x80, 0x40 },
+ }, {
+ .pixclk = 59000000,
+ .pll_div_regs = { 0xd1, 0x62, 0x74, 0x95, 0x08, 0x80, 0x40 },
+ }, {
+ .pixclk = 59340659,
+ .pll_div_regs = { 0xd1, 0x62, 0x74, 0xdb, 0x52, 0x88, 0x47 },
+ }, {
+ .pixclk = 61500000,
+ .pll_div_regs = { 0xd1, 0x66, 0x74, 0x82, 0x01, 0x88, 0x45 },
+ }, {
+ .pixclk = 63500000,
+ .pll_div_regs = { 0xd1, 0x69, 0x74, 0x89, 0x08, 0x80, 0x40 },
+ }, {
+ .pixclk = 67500000,
+ .pll_div_regs = { 0xd1, 0x54, 0x52, 0x87, 0x03, 0x80, 0x40 },
+ }, {
+ .pixclk = 70000000,
+ .pll_div_regs = { 0xd1, 0x58, 0x58, 0x8b, 0x88, 0x80, 0x40 },
+ }, {
+ .pixclk = 72072000,
+ .pll_div_regs = { 0xd1, 0x5a, 0x52, 0xfd, 0x0c, 0x80, 0x40 },
+ }, {
+ .pixclk = 74176000,
+ .pll_div_regs = { 0xd1, 0x5d, 0x58, 0xdb, 0xA2, 0x88, 0x41 },
+ }, {
+ .pixclk = 74250000,
+ .pll_div_regs = { 0xd1, 0x5c, 0x52, 0x90, 0x0d, 0x84, 0x41 },
+ }, {
+ .pixclk = 78500000,
+ .pll_div_regs = { 0xd1, 0x62, 0x54, 0x87, 0x01, 0x80, 0x40 },
+ }, {
+ .pixclk = 82000000,
+ .pll_div_regs = { 0xd1, 0x66, 0x54, 0x82, 0x01, 0x88, 0x45 },
+ }, {
+ .pixclk = 82500000,
+ .pll_div_regs = { 0xd1, 0x67, 0x54, 0x88, 0x01, 0x90, 0x49 },
+ }, {
+ .pixclk = 89000000,
+ .pll_div_regs = { 0xd1, 0x70, 0x54, 0x84, 0x83, 0x80, 0x40 },
+ }, {
+ .pixclk = 90000000,
+ .pll_div_regs = { 0xd1, 0x70, 0x54, 0x82, 0x01, 0x80, 0x40 },
+ }, {
+ .pixclk = 94000000,
+ .pll_div_regs = { 0xd1, 0x4e, 0x32, 0xa7, 0x10, 0x80, 0x40 },
+ }, {
+ .pixclk = 95000000,
+ .pll_div_regs = { 0xd1, 0x50, 0x31, 0x86, 0x85, 0x80, 0x40 },
+ }, {
+ .pixclk = 98901099,
+ .pll_div_regs = { 0xd1, 0x52, 0x3a, 0xdb, 0x4c, 0x88, 0x47 },
+ }, {
+ .pixclk = 99000000,
+ .pll_div_regs = { 0xd1, 0x52, 0x32, 0x82, 0x01, 0x88, 0x47 },
+ }, {
+ .pixclk = 100699300,
+ .pll_div_regs = { 0xd1, 0x54, 0x3c, 0xc3, 0x8f, 0x80, 0x40 },
+ }, {
+ .pixclk = 102500000,
+ .pll_div_regs = { 0xd1, 0x55, 0x32, 0x8c, 0x05, 0x90, 0x4b },
+ }, {
+ .pixclk = 104750000,
+ .pll_div_regs = { 0xd1, 0x57, 0x32, 0x98, 0x07, 0x90, 0x49 },
+ }, {
+ .pixclk = 106500000,
+ .pll_div_regs = { 0xd1, 0x58, 0x32, 0x84, 0x03, 0x82, 0x41 },
+ }, {
+ .pixclk = 107000000,
+ .pll_div_regs = { 0xd1, 0x5a, 0x32, 0x89, 0x88, 0x80, 0x40 },
+ }, {
+ .pixclk = 108108000,
+ .pll_div_regs = { 0xd1, 0x5a, 0x32, 0xfd, 0x0c, 0x80, 0x40 },
+ }, {
+ .pixclk = 118000000,
+ .pll_div_regs = { 0xd1, 0x62, 0x34, 0x95, 0x08, 0x80, 0x40 },
+ }, {
+ .pixclk = 123000000,
+ .pll_div_regs = { 0xd1, 0x66, 0x34, 0x82, 0x01, 0x88, 0x45 },
+ }, {
+ .pixclk = 127000000,
+ .pll_div_regs = { 0xd1, 0x69, 0x34, 0x89, 0x08, 0x80, 0x40 },
+ }, {
+ .pixclk = 135000000,
+ .pll_div_regs = { 0xd1, 0x70, 0x34, 0x82, 0x01, 0x80, 0x40 },
+ }, {
+ .pixclk = 135580000,
+ .pll_div_regs = { 0xd1, 0x71, 0x39, 0xe9, 0x82, 0x9c, 0x5b },
+ }, {
+ .pixclk = 137520000,
+ .pll_div_regs = { 0xd1, 0x72, 0x38, 0x99, 0x10, 0x85, 0x41 },
+ }, {
+ .pixclk = 138750000,
+ .pll_div_regs = { 0xd1, 0x73, 0x35, 0x88, 0x05, 0x90, 0x4d },
+ }, {
+ .pixclk = 140000000,
+ .pll_div_regs = { 0xd1, 0x75, 0x36, 0xa7, 0x90, 0x80, 0x40 },
+ }, {
+ .pixclk = 148352000,
+ .pll_div_regs = { 0xd1, 0x7b, 0x35, 0xdb, 0x39, 0x90, 0x45 },
+ }, {
+ .pixclk = 148500000,
+ .pll_div_regs = { 0xd1, 0x7b, 0x35, 0x84, 0x03, 0x90, 0x45 },
+ }, {
+ .pixclk = 154000000,
+ .pll_div_regs = { 0xd1, 0x40, 0x18, 0x83, 0x01, 0x00, 0x40 },
+ }, {
+ .pixclk = 157000000,
+ .pll_div_regs = { 0xd1, 0x41, 0x11, 0xa7, 0x14, 0x80, 0x40 },
+ }, {
+ .pixclk = 160000000,
+ .pll_div_regs = { 0xd1, 0x42, 0x12, 0xa1, 0x20, 0x80, 0x40 },
+ }, {
+ .pixclk = 162000000,
+ .pll_div_regs = { 0xd1, 0x43, 0x18, 0x8b, 0x08, 0x96, 0x55 },
+ }, {
+ .pixclk = 164000000,
+ .pll_div_regs = { 0xd1, 0x45, 0x11, 0x83, 0x82, 0x90, 0x4b },
+ }, {
+ .pixclk = 165000000,
+ .pll_div_regs = { 0xd1, 0x45, 0x11, 0x84, 0x81, 0x90, 0x4b },
+ }, {
+ .pixclk = 185625000,
+ .pll_div_regs = { 0xd1, 0x4e, 0x12, 0x9a, 0x95, 0x80, 0x40 },
+ }, {
+ .pixclk = 188000000,
+ .pll_div_regs = { 0xd1, 0x4e, 0x12, 0xa7, 0x10, 0x80, 0x40 },
+ }, {
+ .pixclk = 198000000,
+ .pll_div_regs = { 0xd1, 0x52, 0x12, 0x82, 0x01, 0x88, 0x47 },
+ }, {
+ .pixclk = 205000000,
+ .pll_div_regs = { 0xd1, 0x55, 0x12, 0x8c, 0x05, 0x90, 0x4b },
+ }, {
+ .pixclk = 209500000,
+ .pll_div_regs = { 0xd1, 0x57, 0x12, 0x98, 0x07, 0x90, 0x49 },
+ }, {
+ .pixclk = 213000000,
+ .pll_div_regs = { 0xd1, 0x58, 0x12, 0x84, 0x03, 0x82, 0x41 },
+ }, {
+ .pixclk = 216216000,
+ .pll_div_regs = { 0xd1, 0x5a, 0x12, 0xfd, 0x0c, 0x80, 0x40 },
+ }, {
+ .pixclk = 254000000,
+ .pll_div_regs = { 0xd1, 0x69, 0x14, 0x89, 0x08, 0x80, 0x40 },
+ }, {
+ .pixclk = 277500000,
+ .pll_div_regs = { 0xd1, 0x73, 0x15, 0x88, 0x05, 0x90, 0x4d },
+ }, {
+ .pixclk = 297000000,
+ .pll_div_regs = { 0xd1, 0x7b, 0x15, 0x84, 0x03, 0x90, 0x45 },
+ },
+};
+
+struct reg_settings {
+ u8 reg;
+ u8 val;
+};
+
+static const struct reg_settings common_phy_cfg[] = {
+ { PHY_REG(0), 0x00 },
+ /* PHY_REG(1-7) pix clk specific */
+ { PHY_REG(8), 0x4f }, { PHY_REG(9), 0x30 },
+ { PHY_REG(10), 0x33 }, { PHY_REG(11), 0x65 },
+ /* REG12 pixclk specific */
+ /* REG13 pixclk specific */
+ /* REG14 pixclk specific */
+ { PHY_REG(15), 0x80 }, { PHY_REG(16), 0x6c },
+ { PHY_REG(17), 0xf2 }, { PHY_REG(18), 0x67 },
+ { PHY_REG(19), 0x00 }, { PHY_REG(20), 0x10 },
+ /* REG21 pixclk specific */
+ { PHY_REG(22), 0x30 }, { PHY_REG(23), 0x32 },
+ { PHY_REG(24), 0x60 }, { PHY_REG(25), 0x8f },
+ { PHY_REG(26), 0x00 }, { PHY_REG(27), 0x00 },
+ { PHY_REG(28), 0x08 }, { PHY_REG(29), 0x00 },
+ { PHY_REG(30), 0x00 }, { PHY_REG(31), 0x00 },
+ { PHY_REG(32), 0x00 }, { PHY_REG(33), 0x80 },
+ { PHY_REG(34), 0x00 }, { PHY_REG(35), 0x00 },
+ { PHY_REG(36), 0x00 }, { PHY_REG(37), 0x00 },
+ { PHY_REG(38), 0x00 }, { PHY_REG(39), 0x00 },
+ { PHY_REG(40), 0x00 }, { PHY_REG(41), 0xe0 },
+ { PHY_REG(42), 0x83 }, { PHY_REG(43), 0x0f },
+ { PHY_REG(44), 0x3E }, { PHY_REG(45), 0xf8 },
+ { PHY_REG(46), 0x00 }, { PHY_REG(47), 0x00 }
+};
+
+struct fsl_samsung_hdmi_phy {
+ struct device *dev;
+ void __iomem *regs;
+ struct clk *apbclk;
+ struct clk *refclk;
+
+ /* clk provider */
+ struct clk_hw hw;
+ const struct phy_config *cur_cfg;
+};
+
+static inline struct fsl_samsung_hdmi_phy *
+to_fsl_samsung_hdmi_phy(struct clk_hw *hw)
+{
+ return container_of(hw, struct fsl_samsung_hdmi_phy, hw);
+}
+
+static int
+fsl_samsung_hdmi_phy_configure_pll_lock_det(struct fsl_samsung_hdmi_phy *phy,
+ const struct phy_config *cfg)
+{
+ u32 pclk = cfg->pixclk;
+ u32 fld_tg_code;
+ u32 int_pllclk;
+ u8 div;
+
+ /* Find int_pllclk speed */
+ for (div = 0; div < 4; div++) {
+ int_pllclk = pclk / (1 << div);
+ if (int_pllclk < (50 * MHZ))
+ break;
+ }
+
+ if (unlikely(div == 4))
+ return -EINVAL;
+
+ writeb(FIELD_PREP(REG12_CK_DIV_MASK, div), phy->regs + PHY_REG(12));
+
+ /*
+ * Calculation for the frequency lock detector target code (fld_tg_code)
+ * is based on reference manual register description of PHY_REG13
+ * (13.10.3.1.14.2):
+ * 1st) Calculate int_pllclk which is determinded by FLD_CK_DIV
+ * 2nd) Increase resolution to avoid rounding issues
+ * 3th) Do the div (256 / Freq. of int_pllclk) * 24
+ * 4th) Reduce the resolution and always round up since the NXP
+ * settings rounding up always too. TODO: Check if that is
+ * correct.
+ */
+
+ fld_tg_code = DIV_ROUND_UP(24 * MHZ * 256, int_pllclk);
+
+ /* FLD_TOL and FLD_RP_CODE taken from downstream driver */
+ writeb(FIELD_PREP(REG13_TG_CODE_LOW_MASK, fld_tg_code),
+ phy->regs + PHY_REG(13));
+ writeb(FIELD_PREP(REG14_TOL_MASK, 2) |
+ FIELD_PREP(REG14_RP_CODE_MASK, 2) |
+ FIELD_PREP(REG14_TG_CODE_HIGH_MASK, fld_tg_code >> 8),
+ phy->regs + PHY_REG(14));
+
+ return 0;
+}
+
+static unsigned long fsl_samsung_hdmi_phy_find_pms(unsigned long fout, u8 *p, u16 *m, u8 *s)
+{
+ unsigned long best_freq = 0;
+ u32 min_delta = 0xffffffff;
+ u8 _p, best_p;
+ u16 _m, best_m;
+ u8 _s, best_s;
+
+ /*
+ * Figure 13-78 of the reference manual states the PLL should be TMDS x 5
+ * while the TMDS_CLKO should be the PLL / 5. So to calculate the PLL,
+ * take the pix clock x 5, then return the value of the PLL / 5.
+ */
+ fout *= 5;
+
+ /* The ref manual states the values of 'P' range from 1 to 11 */
+ for (_p = 1; _p <= 11; ++_p) {
+ for (_s = 1; _s <= 16; ++_s) {
+ u64 tmp;
+ u32 delta;
+
+ /* s must be one or even */
+ if (_s > 1 && (_s & 0x01) == 1)
+ _s++;
+
+ /* _s cannot be 14 per the TRM */
+ if (_s == 14)
+ continue;
+
+ /*
+ * The Ref manual doesn't explicitly state the range of M,
+ * but it does show it as an 8-bit value, so reject
+ * any value above 255.
+ */
+ tmp = (u64)fout * (_p * _s);
+ do_div(tmp, 24 * MHZ);
+ if (tmp > 255)
+ continue;
+ _m = tmp;
+
+ /*
+ * Rev 2 of the Ref Manual states the
+ * VCO can range between 750MHz and
+ * 3GHz. The VCO is assumed to be
+ * Fvco = (M * f_ref) / P,
+ * where f_ref is 24MHz.
+ */
+ tmp = div64_ul((u64)_m * 24 * MHZ, _p);
+ if (tmp < 750 * MHZ ||
+ tmp > 3000 * MHZ)
+ continue;
+
+ /* Final frequency after post-divider */
+ do_div(tmp, _s);
+
+ delta = abs(fout - tmp);
+ if (delta < min_delta) {
+ best_p = _p;
+ best_s = _s;
+ best_m = _m;
+ min_delta = delta;
+ best_freq = tmp;
+ }
+
+ /* If we have an exact match, stop looking for a better value */
+ if (!delta)
+ goto done;
+ }
+ }
+done:
+ if (best_freq) {
+ *p = best_p;
+ *m = best_m;
+ *s = best_s;
+ }
+
+ return best_freq / 5;
+}
+
+static int fsl_samsung_hdmi_phy_configure(struct fsl_samsung_hdmi_phy *phy,
+ const struct phy_config *cfg)
+{
+ int i, ret;
+ u8 val;
+
+ /* HDMI PHY init */
+ writeb(REG33_FIX_DA, phy->regs + PHY_REG(33));
+
+ /* common PHY registers */
+ for (i = 0; i < ARRAY_SIZE(common_phy_cfg); i++)
+ writeb(common_phy_cfg[i].val, phy->regs + common_phy_cfg[i].reg);
+
+ /* set individual PLL registers PHY_REG1 ... PHY_REG7 */
+ for (i = 0; i < PHY_PLL_DIV_REGS_NUM; i++)
+ writeb(cfg->pll_div_regs[i], phy->regs + PHY_REG(1) + i * 4);
+
+ /* High nibble of PHY_REG3 and low nibble of PHY_REG21 both contain 'S' */
+ writeb(REG21_SEL_TX_CK_INV | FIELD_PREP(REG21_PMS_S_MASK,
+ cfg->pll_div_regs[2] >> 4), phy->regs + PHY_REG(21));
+
+ ret = fsl_samsung_hdmi_phy_configure_pll_lock_det(phy, cfg);
+ if (ret) {
+ dev_err(phy->dev, "pixclock too large\n");
+ return ret;
+ }
+
+ writeb(REG33_FIX_DA | REG33_MODE_SET_DONE, phy->regs + PHY_REG(33));
+
+ ret = readb_poll_timeout(phy->regs + PHY_REG(34), val,
+ val & REG34_PLL_LOCK, 50, 20000);
+ if (ret)
+ dev_err(phy->dev, "PLL failed to lock\n");
+
+ return ret;
+}
+
+static unsigned long phy_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct fsl_samsung_hdmi_phy *phy = to_fsl_samsung_hdmi_phy(hw);
+
+ if (!phy->cur_cfg)
+ return 74250000;
+
+ return phy->cur_cfg->pixclk;
+}
+
+/* Helper function to lookup the available fractional-divider rate */
+static const struct phy_config *fsl_samsung_hdmi_phy_lookup_rate(unsigned long rate)
+{
+ int i;
+
+ /* Search the lookup table */
+ for (i = ARRAY_SIZE(phy_pll_cfg) - 1; i >= 0; i--)
+ if (phy_pll_cfg[i].pixclk <= rate)
+ break;
+
+ return &phy_pll_cfg[i];
+}
+
+static void fsl_samsung_hdmi_calculate_phy(struct phy_config *cal_phy, unsigned long rate,
+ u8 p, u16 m, u8 s)
+{
+ cal_phy->pixclk = rate;
+ cal_phy->pll_div_regs[0] = FIELD_PREP(REG01_PMS_P_MASK, p);
+ cal_phy->pll_div_regs[1] = m;
+ cal_phy->pll_div_regs[2] = FIELD_PREP(REG03_PMS_S_MASK, s-1);
+ /* pll_div_regs 3-6 are fixed and pre-defined already */
+}
+
+static u32 fsl_samsung_hdmi_phy_get_closest_rate(unsigned long rate,
+ u32 int_div_clk, u32 frac_div_clk)
+{
+ /* Calculate the absolute value of the differences and return whichever is closest */
+ if (abs((long)rate - (long)int_div_clk) < abs((long)(rate - (long)frac_div_clk)))
+ return int_div_clk;
+
+ return frac_div_clk;
+}
+
+static long phy_clk_round_rate(struct clk_hw *hw,
+ unsigned long rate, unsigned long *parent_rate)
+{
+ const struct phy_config *fract_div_phy;
+ u32 int_div_clk;
+ u16 m;
+ u8 p, s;
+
+ /* If the clock is out of range return error instead of searching */
+ if (rate > 297000000 || rate < 22250000)
+ return -EINVAL;
+
+ /* Search the fractional divider lookup table */
+ fract_div_phy = fsl_samsung_hdmi_phy_lookup_rate(rate);
+
+ /* If the rate is an exact match, return that value */
+ if (rate == fract_div_phy->pixclk)
+ return fract_div_phy->pixclk;
+
+ /* If the exact match isn't found, calculate the integer divider */
+ int_div_clk = fsl_samsung_hdmi_phy_find_pms(rate, &p, &m, &s);
+
+ /* If the int_div_clk rate is an exact match, return that value */
+ if (int_div_clk == rate)
+ return int_div_clk;
+
+ /* If neither rate is an exact match, use the value from the LUT */
+ return fract_div_phy->pixclk;
+}
+
+static int phy_use_fract_div(struct fsl_samsung_hdmi_phy *phy, const struct phy_config *fract_div_phy)
+{
+ phy->cur_cfg = fract_div_phy;
+ dev_dbg(phy->dev, "fsl_samsung_hdmi_phy: using fractional divider rate = %u\n",
+ phy->cur_cfg->pixclk);
+ return fsl_samsung_hdmi_phy_configure(phy, phy->cur_cfg);
+}
+
+static int phy_use_integer_div(struct fsl_samsung_hdmi_phy *phy,
+ const struct phy_config *int_div_clk)
+{
+ phy->cur_cfg = &calculated_phy_pll_cfg;
+ dev_dbg(phy->dev, "fsl_samsung_hdmi_phy: integer divider rate = %u\n",
+ phy->cur_cfg->pixclk);
+ return fsl_samsung_hdmi_phy_configure(phy, phy->cur_cfg);
+}
+
+static int phy_clk_set_rate(struct clk_hw *hw,
+ unsigned long rate, unsigned long parent_rate)
+{
+ struct fsl_samsung_hdmi_phy *phy = to_fsl_samsung_hdmi_phy(hw);
+ const struct phy_config *fract_div_phy;
+ u32 int_div_clk;
+ u16 m;
+ u8 p, s;
+
+ /* Search the fractional divider lookup table */
+ fract_div_phy = fsl_samsung_hdmi_phy_lookup_rate(rate);
+
+ /* If the rate is an exact match, use that value */
+ if (fract_div_phy->pixclk == rate)
+ return phy_use_fract_div(phy, fract_div_phy);
+
+ /*
+ * If the rate from the fractional divider is not exact, check the integer divider,
+ * and use it if that value is an exact match.
+ */
+ int_div_clk = fsl_samsung_hdmi_phy_find_pms(rate, &p, &m, &s);
+ fsl_samsung_hdmi_calculate_phy(&calculated_phy_pll_cfg, int_div_clk, p, m, s);
+ if (int_div_clk == rate)
+ return phy_use_integer_div(phy, &calculated_phy_pll_cfg);
+
+ /*
+ * Compare the difference between the integer clock and the fractional clock against
+ * the desired clock and which whichever is closest.
+ */
+ if (fsl_samsung_hdmi_phy_get_closest_rate(rate, int_div_clk,
+ fract_div_phy->pixclk) == fract_div_phy->pixclk)
+ return phy_use_fract_div(phy, fract_div_phy);
+ else
+ return phy_use_integer_div(phy, &calculated_phy_pll_cfg);
+}
+
+static const struct clk_ops phy_clk_ops = {
+ .recalc_rate = phy_clk_recalc_rate,
+ .round_rate = phy_clk_round_rate,
+ .set_rate = phy_clk_set_rate,
+};
+
+static int phy_clk_register(struct fsl_samsung_hdmi_phy *phy)
+{
+ struct device *dev = phy->dev;
+ struct device_node *np = dev->of_node;
+ struct clk_init_data init;
+ const char *parent_name;
+ struct clk *phyclk;
+ int ret;
+
+ parent_name = __clk_get_name(phy->refclk);
+
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ init.flags = 0;
+ init.name = "hdmi_pclk";
+ init.ops = &phy_clk_ops;
+
+ phy->hw.init = &init;
+
+ phyclk = devm_clk_register(dev, &phy->hw);
+ if (IS_ERR(phyclk))
+ return dev_err_probe(dev, PTR_ERR(phyclk),
+ "failed to register clock\n");
+
+ ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, phyclk);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to register clock provider\n");
+
+ return 0;
+}
+
+static int fsl_samsung_hdmi_phy_probe(struct platform_device *pdev)
+{
+ struct fsl_samsung_hdmi_phy *phy;
+ int ret;
+
+ phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
+ if (!phy)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, phy);
+ phy->dev = &pdev->dev;
+
+ phy->regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(phy->regs))
+ return PTR_ERR(phy->regs);
+
+ phy->apbclk = devm_clk_get(phy->dev, "apb");
+ if (IS_ERR(phy->apbclk))
+ return dev_err_probe(phy->dev, PTR_ERR(phy->apbclk),
+ "failed to get apb clk\n");
+
+ phy->refclk = devm_clk_get(phy->dev, "ref");
+ if (IS_ERR(phy->refclk))
+ return dev_err_probe(phy->dev, PTR_ERR(phy->refclk),
+ "failed to get ref clk\n");
+
+ ret = clk_prepare_enable(phy->apbclk);
+ if (ret) {
+ dev_err(phy->dev, "failed to enable apbclk\n");
+ return ret;
+ }
+
+ pm_runtime_get_noresume(phy->dev);
+ pm_runtime_set_active(phy->dev);
+ pm_runtime_enable(phy->dev);
+
+ ret = phy_clk_register(phy);
+ if (ret) {
+ dev_err(&pdev->dev, "register clk failed\n");
+ goto register_clk_failed;
+ }
+
+ pm_runtime_put(phy->dev);
+
+ return 0;
+
+register_clk_failed:
+ clk_disable_unprepare(phy->apbclk);
+
+ return ret;
+}
+
+static void fsl_samsung_hdmi_phy_remove(struct platform_device *pdev)
+{
+ of_clk_del_provider(pdev->dev.of_node);
+}
+
+static int __maybe_unused fsl_samsung_hdmi_phy_suspend(struct device *dev)
+{
+ struct fsl_samsung_hdmi_phy *phy = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(phy->apbclk);
+
+ return 0;
+}
+
+static int __maybe_unused fsl_samsung_hdmi_phy_resume(struct device *dev)
+{
+ struct fsl_samsung_hdmi_phy *phy = dev_get_drvdata(dev);
+ int ret = 0;
+
+ ret = clk_prepare_enable(phy->apbclk);
+ if (ret) {
+ dev_err(phy->dev, "failed to enable apbclk\n");
+ return ret;
+ }
+
+ if (phy->cur_cfg)
+ ret = fsl_samsung_hdmi_phy_configure(phy, phy->cur_cfg);
+
+ return ret;
+
+}
+
+static DEFINE_RUNTIME_DEV_PM_OPS(fsl_samsung_hdmi_phy_pm_ops,
+ fsl_samsung_hdmi_phy_suspend,
+ fsl_samsung_hdmi_phy_resume, NULL);
+
+static const struct of_device_id fsl_samsung_hdmi_phy_of_match[] = {
+ {
+ .compatible = "fsl,imx8mp-hdmi-phy",
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(of, fsl_samsung_hdmi_phy_of_match);
+
+static struct platform_driver fsl_samsung_hdmi_phy_driver = {
+ .probe = fsl_samsung_hdmi_phy_probe,
+ .remove = fsl_samsung_hdmi_phy_remove,
+ .driver = {
+ .name = "fsl-samsung-hdmi-phy",
+ .of_match_table = fsl_samsung_hdmi_phy_of_match,
+ .pm = pm_ptr(&fsl_samsung_hdmi_phy_pm_ops),
+ },
+};
+module_platform_driver(fsl_samsung_hdmi_phy_driver);
+
+MODULE_AUTHOR("Sandor Yu <Sandor.yu@nxp.com>");
+MODULE_DESCRIPTION("SAMSUNG HDMI 2.0 Transmitter PHY Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/hisilicon/phy-hi3670-pcie.c b/drivers/phy/hisilicon/phy-hi3670-pcie.c
index 0ac9634b398d..dbc7dcce682b 100644
--- a/drivers/phy/hisilicon/phy-hi3670-pcie.c
+++ b/drivers/phy/hisilicon/phy-hi3670-pcie.c
@@ -16,15 +16,20 @@
*/
#include <linux/bitfield.h>
+#include <linux/bits.h>
#include <linux/clk.h>
-#include <linux/gpio.h>
-#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
#include <linux/mfd/syscon.h>
+#include <linux/mod_devicetable.h>
#include <linux/module.h>
-#include <linux/of_gpio.h>
+#include <linux/of.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
+#include <linux/types.h>
#define AXI_CLK_FREQ 207500000
#define REF_CLK_FREQ 100000000
diff --git a/drivers/phy/hisilicon/phy-hisi-inno-usb2.c b/drivers/phy/hisilicon/phy-hisi-inno-usb2.c
index c138cd4807d6..c843923252aa 100644
--- a/drivers/phy/hisilicon/phy-hisi-inno-usb2.c
+++ b/drivers/phy/hisilicon/phy-hisi-inno-usb2.c
@@ -138,7 +138,6 @@ static int hisi_inno_phy_probe(struct platform_device *pdev)
struct device_node *np = dev->of_node;
struct hisi_inno_phy_priv *priv;
struct phy_provider *provider;
- struct device_node *child;
int i = 0;
int ret;
@@ -162,24 +161,20 @@ static int hisi_inno_phy_probe(struct platform_device *pdev)
priv->type = (uintptr_t) of_device_get_match_data(dev);
- for_each_child_of_node(np, child) {
+ for_each_child_of_node_scoped(np, child) {
struct reset_control *rst;
struct phy *phy;
rst = of_reset_control_get_exclusive(child, NULL);
- if (IS_ERR(rst)) {
- of_node_put(child);
+ if (IS_ERR(rst))
return PTR_ERR(rst);
- }
priv->ports[i].utmi_rst = rst;
priv->ports[i].priv = priv;
phy = devm_phy_create(dev, child, &hisi_inno_phy_ops);
- if (IS_ERR(phy)) {
- of_node_put(child);
+ if (IS_ERR(phy))
return PTR_ERR(phy);
- }
phy_set_bus_width(phy, 8);
phy_set_drvdata(phy, &priv->ports[i]);
@@ -187,7 +182,6 @@ static int hisi_inno_phy_probe(struct platform_device *pdev)
if (i >= INNO_PHY_PORT_NUM) {
dev_warn(dev, "Support %d ports in maximum\n", i);
- of_node_put(child);
break;
}
}
diff --git a/drivers/phy/hisilicon/phy-histb-combphy.c b/drivers/phy/hisilicon/phy-histb-combphy.c
index c44588fd5a53..7436dcae3981 100644
--- a/drivers/phy/hisilicon/phy-histb-combphy.c
+++ b/drivers/phy/hisilicon/phy-histb-combphy.c
@@ -163,7 +163,7 @@ static const struct phy_ops histb_combphy_ops = {
};
static struct phy *histb_combphy_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct histb_combphy_priv *priv = dev_get_drvdata(dev);
struct histb_combphy_mode *mode = &priv->mode;
diff --git a/drivers/phy/intel/phy-intel-lgm-combo.c b/drivers/phy/intel/phy-intel-lgm-combo.c
index d32e267c0001..9ee3cf61cdd0 100644
--- a/drivers/phy/intel/phy-intel-lgm-combo.c
+++ b/drivers/phy/intel/phy-intel-lgm-combo.c
@@ -508,7 +508,7 @@ static const struct phy_ops intel_cbphy_ops = {
};
static struct phy *intel_cbphy_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct intel_combo_phy *cbphy = dev_get_drvdata(dev);
u32 iphy_id;
@@ -605,7 +605,7 @@ static const struct of_device_id of_intel_cbphy_match[] = {
static struct platform_driver intel_cbphy_driver = {
.probe = intel_cbphy_probe,
- .remove_new = intel_cbphy_remove,
+ .remove = intel_cbphy_remove,
.driver = {
.name = "intel-combo-phy",
.of_match_table = of_intel_cbphy_match,
diff --git a/drivers/phy/lantiq/phy-lantiq-vrx200-pcie.c b/drivers/phy/lantiq/phy-lantiq-vrx200-pcie.c
index ef93bf2cba10..406a87c8b759 100644
--- a/drivers/phy/lantiq/phy-lantiq-vrx200-pcie.c
+++ b/drivers/phy/lantiq/phy-lantiq-vrx200-pcie.c
@@ -358,7 +358,7 @@ static const struct phy_ops ltq_vrx200_pcie_phy_ops = {
};
static struct phy *ltq_vrx200_pcie_phy_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct ltq_vrx200_pcie_phy_priv *priv = dev_get_drvdata(dev);
unsigned int mode;
diff --git a/drivers/phy/marvell/phy-armada375-usb2.c b/drivers/phy/marvell/phy-armada375-usb2.c
index b141e3cd8a94..3731f9b25655 100644
--- a/drivers/phy/marvell/phy-armada375-usb2.c
+++ b/drivers/phy/marvell/phy-armada375-usb2.c
@@ -61,7 +61,7 @@ static const struct phy_ops armada375_usb_phy_ops = {
* USB3 case it still optional and we use ENODEV.
*/
static struct phy *armada375_usb_phy_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct armada375_cluster_phy *cluster_phy = dev_get_drvdata(dev);
diff --git a/drivers/phy/marvell/phy-armada38x-comphy.c b/drivers/phy/marvell/phy-armada38x-comphy.c
index a0066e86bb42..a4533c924edd 100644
--- a/drivers/phy/marvell/phy-armada38x-comphy.c
+++ b/drivers/phy/marvell/phy-armada38x-comphy.c
@@ -64,8 +64,13 @@ struct a38x_comphy {
struct a38x_comphy_lane lane[MAX_A38X_COMPHY];
};
+/*
+ * Map serdes lanes and gbe ports to serdes mux configuration values:
+ * row index = serdes lane,
+ * column index = gbe port number.
+ */
static const u8 gbe_mux[MAX_A38X_COMPHY][MAX_A38X_PORTS] = {
- { 0, 0, 0 },
+ { 3, 0, 0 },
{ 4, 5, 0 },
{ 0, 4, 0 },
{ 0, 0, 4 },
@@ -254,7 +259,7 @@ static const struct phy_ops a38x_comphy_ops = {
};
static struct phy *a38x_comphy_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct a38x_comphy_lane *lane;
struct phy *phy;
diff --git a/drivers/phy/marvell/phy-berlin-sata.c b/drivers/phy/marvell/phy-berlin-sata.c
index f972d78372ea..c90e2867900c 100644
--- a/drivers/phy/marvell/phy-berlin-sata.c
+++ b/drivers/phy/marvell/phy-berlin-sata.c
@@ -155,7 +155,7 @@ static int phy_berlin_sata_power_off(struct phy *phy)
}
static struct phy *phy_berlin_sata_phy_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct phy_berlin_priv *priv = dev_get_drvdata(dev);
int i;
diff --git a/drivers/phy/marvell/phy-mvebu-a3700-comphy.c b/drivers/phy/marvell/phy-mvebu-a3700-comphy.c
index 24c3371e2bb2..1d1db1737422 100644
--- a/drivers/phy/marvell/phy-mvebu-a3700-comphy.c
+++ b/drivers/phy/marvell/phy-mvebu-a3700-comphy.c
@@ -603,7 +603,7 @@ static void comphy_gbe_phy_init(struct mvebu_a3700_comphy_lane *lane,
u16 val;
fix_idx = 0;
- for (addr = 0; addr < 512; addr++) {
+ for (addr = 0; addr < ARRAY_SIZE(gbe_phy_init); addr++) {
/*
* All PHY register values are defined in full for 3.125Gbps
* SERDES speed. The values required for 1.25 Gbps are almost
@@ -611,11 +611,12 @@ static void comphy_gbe_phy_init(struct mvebu_a3700_comphy_lane *lane,
* comparison to 3.125 Gbps values. These register values are
* stored in "gbe_phy_init_fix" array.
*/
- if (!is_1gbps && gbe_phy_init_fix[fix_idx].addr == addr) {
+ if (!is_1gbps &&
+ fix_idx < ARRAY_SIZE(gbe_phy_init_fix) &&
+ gbe_phy_init_fix[fix_idx].addr == addr) {
/* Use new value */
val = gbe_phy_init_fix[fix_idx].value;
- if (fix_idx < ARRAY_SIZE(gbe_phy_init_fix))
- fix_idx++;
+ fix_idx++;
} else {
val = gbe_phy_init[addr];
}
@@ -1213,7 +1214,7 @@ static const struct phy_ops mvebu_a3700_comphy_ops = {
};
static struct phy *mvebu_a3700_comphy_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct mvebu_a3700_comphy_lane *lane;
unsigned int port;
diff --git a/drivers/phy/marvell/phy-mvebu-cp110-comphy.c b/drivers/phy/marvell/phy-mvebu-cp110-comphy.c
index b0dd13366598..71f9c14fb50d 100644
--- a/drivers/phy/marvell/phy-mvebu-cp110-comphy.c
+++ b/drivers/phy/marvell/phy-mvebu-cp110-comphy.c
@@ -244,8 +244,8 @@ static const struct mvebu_comphy_conf mvebu_comphy_cp110_modes[] = {
GEN_CONF(4, 1, PHY_MODE_USB_HOST_SS, COMPHY_FW_MODE_USB3H),
GEN_CONF(4, 1, PHY_MODE_PCIE, COMPHY_FW_MODE_PCIE),
ETH_CONF(4, 1, PHY_INTERFACE_MODE_SGMII, 0x1, COMPHY_FW_MODE_SGMII),
- ETH_CONF(4, 1, PHY_INTERFACE_MODE_2500BASEX, -1, COMPHY_FW_MODE_2500BASEX),
- ETH_CONF(4, 1, PHY_INTERFACE_MODE_5GBASER, -1, COMPHY_FW_MODE_XFI),
+ ETH_CONF(4, 1, PHY_INTERFACE_MODE_2500BASEX, 0x1, COMPHY_FW_MODE_2500BASEX),
+ ETH_CONF(4, 1, PHY_INTERFACE_MODE_5GBASER, 0x1, COMPHY_FW_MODE_XFI),
ETH_CONF(4, 1, PHY_INTERFACE_MODE_10GBASER, -1, COMPHY_FW_MODE_XFI),
/* lane 5 */
ETH_CONF(5, 1, PHY_INTERFACE_MODE_RXAUI, 0x2, COMPHY_FW_MODE_RXAUI),
@@ -422,7 +422,7 @@ static int mvebu_comphy_ethernet_init_reset(struct mvebu_comphy_lane *lane)
/* wait until clocks are ready */
mdelay(1);
- /* exlicitly disable 40B, the bits isn't clear on reset */
+ /* explicitly disable 40B, the bits isn't clear on reset */
regmap_read(priv->regmap, MVEBU_COMPHY_CONF6(lane->id), &val);
val &= ~MVEBU_COMPHY_CONF6_40B;
regmap_write(priv->regmap, MVEBU_COMPHY_CONF6(lane->id), val);
@@ -917,7 +917,7 @@ static const struct phy_ops mvebu_comphy_ops = {
};
static struct phy *mvebu_comphy_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct mvebu_comphy_lane *lane;
struct phy *phy;
diff --git a/drivers/phy/marvell/phy-mvebu-cp110-utmi.c b/drivers/phy/marvell/phy-mvebu-cp110-utmi.c
index 4922a5f3327d..59903f86b13f 100644
--- a/drivers/phy/marvell/phy-mvebu-cp110-utmi.c
+++ b/drivers/phy/marvell/phy-mvebu-cp110-utmi.c
@@ -62,6 +62,8 @@
#define SQ_AMP_CAL_MASK GENMASK(2, 0)
#define SQ_AMP_CAL_VAL 1
#define SQ_AMP_CAL_EN BIT(3)
+#define UTMI_DIG_CTRL1_REG 0x20
+#define SWAP_DPDM BIT(15)
#define UTMI_CTRL_STATUS0_REG 0x24
#define SUSPENDM BIT(22)
#define TEST_SEL BIT(25)
@@ -99,11 +101,13 @@ struct mvebu_cp110_utmi {
* @priv: PHY driver data
* @id: PHY port ID
* @dr_mode: PHY connection: USB_DR_MODE_HOST or USB_DR_MODE_PERIPHERAL
+ * @swap_dx: whether to swap d+/d- signals
*/
struct mvebu_cp110_utmi_port {
struct mvebu_cp110_utmi *priv;
u32 id;
enum usb_dr_mode dr_mode;
+ bool swap_dx;
};
static void mvebu_cp110_utmi_port_setup(struct mvebu_cp110_utmi_port *port)
@@ -159,6 +163,13 @@ static void mvebu_cp110_utmi_port_setup(struct mvebu_cp110_utmi_port *port)
reg &= ~(VDAT_MASK | VSRC_MASK);
reg |= (VDAT_VAL << VDAT_OFFSET) | (VSRC_VAL << VSRC_OFFSET);
writel(reg, PORT_REGS(port) + UTMI_CHGDTC_CTRL_REG);
+
+ /* Swap D+/D- */
+ reg = readl(PORT_REGS(port) + UTMI_DIG_CTRL1_REG);
+ reg &= ~(SWAP_DPDM);
+ if (port->swap_dx)
+ reg |= SWAP_DPDM;
+ writel(reg, PORT_REGS(port) + UTMI_DIG_CTRL1_REG);
}
static int mvebu_cp110_utmi_phy_power_off(struct phy *phy)
@@ -286,6 +297,7 @@ static int mvebu_cp110_utmi_phy_probe(struct platform_device *pdev)
struct phy_provider *provider;
struct device_node *child;
u32 usb_devices = 0;
+ u32 swap_dx = 0;
utmi = devm_kzalloc(dev, sizeof(*utmi), GFP_KERNEL);
if (!utmi)
@@ -345,6 +357,10 @@ static int mvebu_cp110_utmi_phy_probe(struct platform_device *pdev)
}
}
+ of_property_for_each_u32(dev->of_node, "swap-dx-lanes", swap_dx)
+ if (swap_dx == port_id)
+ port->swap_dx = 1;
+
/* Retrieve PHY capabilities */
utmi->ops = &mvebu_cp110_utmi_phy_ops;
diff --git a/drivers/phy/mediatek/Kconfig b/drivers/phy/mediatek/Kconfig
index 3125ecb5d119..ba6461350951 100644
--- a/drivers/phy/mediatek/Kconfig
+++ b/drivers/phy/mediatek/Kconfig
@@ -13,6 +13,17 @@ config PHY_MTK_PCIE
callback for PCIe GEN3 port, it supports software efuse
initialization.
+config PHY_MTK_XFI_TPHY
+ tristate "MediaTek 10GE SerDes XFI T-PHY driver"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+ depends on OF
+ select GENERIC_PHY
+ help
+ Say 'Y' here to add support for MediaTek XFI T-PHY driver.
+ The driver provides access to the Ethernet SerDes T-PHY supporting
+ 1GE and 2.5GE modes via the LynxI PCS, and 5GE and 10GE modes
+ via the USXGMII PCS found in MediaTek SoCs with 10G Ethernet.
+
config PHY_MTK_TPHY
tristate "MediaTek T-PHY Driver"
depends on ARCH_MEDIATEK || COMPILE_TEST
@@ -54,10 +65,23 @@ config PHY_MTK_HDMI
depends on ARCH_MEDIATEK || COMPILE_TEST
depends on COMMON_CLK
depends on OF
+ depends on REGULATOR
select GENERIC_PHY
help
Support HDMI PHY for Mediatek SoCs.
+config PHY_MTK_MIPI_CSI_0_5
+ tristate "MediaTek MIPI CSI CD-PHY v0.5 Driver"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+ depends on OF
+ select GENERIC_PHY
+ help
+ Enable this to support the MIPI CSI CD-PHY receiver version 0.5.
+ The driver supports multiple CSI cdphy ports simultaneously.
+
+ To compile this driver as a module, choose M here: the
+ module will be called phy-mtk-mipi-csi-0-5.
+
config PHY_MTK_MIPI_DSI
tristate "MediaTek MIPI-DSI Driver"
depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/phy/mediatek/Makefile b/drivers/phy/mediatek/Makefile
index c9a50395533e..1b8088df71e8 100644
--- a/drivers/phy/mediatek/Makefile
+++ b/drivers/phy/mediatek/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_PHY_MTK_PCIE) += phy-mtk-pcie.o
obj-$(CONFIG_PHY_MTK_TPHY) += phy-mtk-tphy.o
obj-$(CONFIG_PHY_MTK_UFS) += phy-mtk-ufs.o
obj-$(CONFIG_PHY_MTK_XSPHY) += phy-mtk-xsphy.o
+obj-$(CONFIG_PHY_MTK_XFI_TPHY) += phy-mtk-xfi-tphy.o
phy-mtk-hdmi-drv-y := phy-mtk-hdmi.o
phy-mtk-hdmi-drv-y += phy-mtk-hdmi-mt2701.o
@@ -15,6 +16,8 @@ phy-mtk-hdmi-drv-y += phy-mtk-hdmi-mt8173.o
phy-mtk-hdmi-drv-y += phy-mtk-hdmi-mt8195.o
obj-$(CONFIG_PHY_MTK_HDMI) += phy-mtk-hdmi-drv.o
+obj-$(CONFIG_PHY_MTK_MIPI_CSI_0_5) += phy-mtk-mipi-csi-0-5.o
+
phy-mtk-mipi-dsi-drv-y := phy-mtk-mipi-dsi.o
phy-mtk-mipi-dsi-drv-y += phy-mtk-mipi-dsi-mt8173.o
phy-mtk-mipi-dsi-drv-y += phy-mtk-mipi-dsi-mt8183.o
diff --git a/drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c b/drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c
index bbfe11d6a69d..b38f3ae26b3f 100644
--- a/drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c
+++ b/drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c
@@ -9,6 +9,8 @@
#include <linux/module.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
#include <linux/types.h>
#include <linux/units.h>
#include <linux/nvmem-consumer.h>
@@ -478,8 +480,50 @@ static int mtk_hdmi_phy_configure(struct phy *phy, union phy_configure_opts *opt
return ret;
}
+static int mtk_hdmi_phy_pwr5v_enable(struct regulator_dev *rdev)
+{
+ struct mtk_hdmi_phy *hdmi_phy = rdev_get_drvdata(rdev);
+
+ mtk_phy_set_bits(hdmi_phy->regs + HDMI_CTL_1, RG_HDMITX_PWR5V_O);
+
+ return 0;
+}
+
+static int mtk_hdmi_phy_pwr5v_disable(struct regulator_dev *rdev)
+{
+ struct mtk_hdmi_phy *hdmi_phy = rdev_get_drvdata(rdev);
+
+ mtk_phy_clear_bits(hdmi_phy->regs + HDMI_CTL_1, RG_HDMITX_PWR5V_O);
+
+ return 0;
+}
+
+static int mtk_hdmi_phy_pwr5v_is_enabled(struct regulator_dev *rdev)
+{
+ struct mtk_hdmi_phy *hdmi_phy = rdev_get_drvdata(rdev);
+
+ return !!(readl(hdmi_phy->regs + HDMI_CTL_1) & RG_HDMITX_PWR5V_O);
+}
+
+static const struct regulator_ops mtk_hdmi_pwr5v_regulator_ops = {
+ .enable = mtk_hdmi_phy_pwr5v_enable,
+ .disable = mtk_hdmi_phy_pwr5v_disable,
+ .is_enabled = mtk_hdmi_phy_pwr5v_is_enabled
+};
+
+static const struct regulator_desc mtk_hdmi_phy_pwr5v_desc = {
+ .name = "hdmi-pwr5v",
+ .id = -1,
+ .n_voltages = 1,
+ .fixed_uV = 5000000,
+ .ops = &mtk_hdmi_pwr5v_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+};
+
struct mtk_hdmi_phy_conf mtk_hdmi_phy_8195_conf = {
.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE,
+ .hdmi_phy_regulator_desc = &mtk_hdmi_phy_pwr5v_desc,
.hdmi_phy_clk_ops = &mtk_hdmi_pll_ops,
.hdmi_phy_enable_tmds = mtk_hdmi_phy_enable_tmds,
.hdmi_phy_disable_tmds = mtk_hdmi_phy_disable_tmds,
diff --git a/drivers/phy/mediatek/phy-mtk-hdmi-mt8195.h b/drivers/phy/mediatek/phy-mtk-hdmi-mt8195.h
index 22a68dc9550c..e26caaf4d104 100644
--- a/drivers/phy/mediatek/phy-mtk-hdmi-mt8195.h
+++ b/drivers/phy/mediatek/phy-mtk-hdmi-mt8195.h
@@ -103,6 +103,9 @@
#define HDMI_ANA_CTL 0x7c
#define REG_ANA_HDMI20_FIFO_EN BIT(16)
+#define HDMI_CTL_1 0xc4
+#define RG_HDMITX_PWR5V_O BIT(9)
+
#define HDMI_CTL_3 0xcc
#define REG_HDMITXPLL_DIV GENMASK(4, 0)
#define REG_HDMITX_REF_XTAL_SEL BIT(7)
diff --git a/drivers/phy/mediatek/phy-mtk-hdmi.c b/drivers/phy/mediatek/phy-mtk-hdmi.c
index d2e824771f9d..52a7d525ff9b 100644
--- a/drivers/phy/mediatek/phy-mtk-hdmi.c
+++ b/drivers/phy/mediatek/phy-mtk-hdmi.c
@@ -75,6 +75,28 @@ static void mtk_hdmi_phy_clk_get_data(struct mtk_hdmi_phy *hdmi_phy,
clk_init->ops = hdmi_phy->conf->hdmi_phy_clk_ops;
}
+static int mtk_hdmi_phy_register_regulators(struct mtk_hdmi_phy *hdmi_phy)
+{
+ const struct regulator_desc *vreg_desc = hdmi_phy->conf->hdmi_phy_regulator_desc;
+ const struct regulator_init_data vreg_init_data = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ }
+ };
+ struct regulator_config vreg_config = {
+ .dev = hdmi_phy->dev,
+ .driver_data = hdmi_phy,
+ .init_data = &vreg_init_data,
+ .of_node = hdmi_phy->dev->of_node
+ };
+
+ hdmi_phy->rdev = devm_regulator_register(hdmi_phy->dev, vreg_desc, &vreg_config);
+ if (IS_ERR(hdmi_phy->rdev))
+ return PTR_ERR(hdmi_phy->rdev);
+
+ return 0;
+}
+
static int mtk_hdmi_phy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -150,6 +172,12 @@ static int mtk_hdmi_phy_probe(struct platform_device *pdev)
if (hdmi_phy->conf->pll_default_off)
hdmi_phy->conf->hdmi_phy_disable_tmds(hdmi_phy);
+ if (hdmi_phy->conf->hdmi_phy_regulator_desc) {
+ ret = mtk_hdmi_phy_register_regulators(hdmi_phy);
+ if (ret)
+ return ret;
+ }
+
return of_clk_add_provider(dev->of_node, of_clk_src_simple_get,
hdmi_phy->pll);
}
diff --git a/drivers/phy/mediatek/phy-mtk-hdmi.h b/drivers/phy/mediatek/phy-mtk-hdmi.h
index 71c02d043485..99d917e0036a 100644
--- a/drivers/phy/mediatek/phy-mtk-hdmi.h
+++ b/drivers/phy/mediatek/phy-mtk-hdmi.h
@@ -13,6 +13,8 @@
#include <linux/module.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
#include <linux/types.h>
struct mtk_hdmi_phy;
@@ -20,6 +22,7 @@ struct mtk_hdmi_phy;
struct mtk_hdmi_phy_conf {
unsigned long flags;
bool pll_default_off;
+ const struct regulator_desc *hdmi_phy_regulator_desc;
const struct clk_ops *hdmi_phy_clk_ops;
void (*hdmi_phy_enable_tmds)(struct mtk_hdmi_phy *hdmi_phy);
void (*hdmi_phy_disable_tmds)(struct mtk_hdmi_phy *hdmi_phy);
@@ -32,6 +35,7 @@ struct mtk_hdmi_phy {
struct mtk_hdmi_phy_conf *conf;
struct clk *pll;
struct clk_hw pll_hw;
+ struct regulator_dev *rdev;
unsigned long pll_rate;
unsigned char drv_imp_clk;
unsigned char drv_imp_d2;
diff --git a/drivers/phy/mediatek/phy-mtk-mipi-csi-0-5-rx-reg.h b/drivers/phy/mediatek/phy-mtk-mipi-csi-0-5-rx-reg.h
new file mode 100644
index 000000000000..97b4c27a1699
--- /dev/null
+++ b/drivers/phy/mediatek/phy-mtk-mipi-csi-0-5-rx-reg.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2023, MediaTek Inc.
+ * Copyright (c) 2023, BayLibre Inc.
+ */
+
+#ifndef __PHY_MTK_MIPI_CSI_V_0_5_RX_REG_H__
+#define __PHY_MTK_MIPI_CSI_V_0_5_RX_REG_H__
+
+/*
+ * CSI1 and CSI2 are identical, and similar to CSI0. All CSIX macros are
+ * applicable to the three PHYs. Where differences exist, they are denoted by
+ * macro names using CSI0 and CSI1, the latter being applicable to CSI1 and
+ * CSI2 alike.
+ */
+
+#define MIPI_RX_ANA00_CSIXA 0x0000
+#define RG_CSI0A_CPHY_EN BIT(0)
+#define RG_CSIXA_EQ_PROTECT_EN BIT(1)
+#define RG_CSIXA_BG_LPF_EN BIT(2)
+#define RG_CSIXA_BG_CORE_EN BIT(3)
+#define RG_CSIXA_DPHY_L0_CKMODE_EN BIT(5)
+#define RG_CSIXA_DPHY_L0_CKSEL BIT(6)
+#define RG_CSIXA_DPHY_L1_CKMODE_EN BIT(8)
+#define RG_CSIXA_DPHY_L1_CKSEL BIT(9)
+#define RG_CSIXA_DPHY_L2_CKMODE_EN BIT(11)
+#define RG_CSIXA_DPHY_L2_CKSEL BIT(12)
+
+#define MIPI_RX_ANA18_CSIXA 0x0018
+#define RG_CSI0A_L0_T0AB_EQ_IS GENMASK(5, 4)
+#define RG_CSI0A_L0_T0AB_EQ_BW GENMASK(7, 6)
+#define RG_CSI0A_L1_T1AB_EQ_IS GENMASK(21, 20)
+#define RG_CSI0A_L1_T1AB_EQ_BW GENMASK(23, 22)
+#define RG_CSI0A_L2_T1BC_EQ_IS GENMASK(21, 20)
+#define RG_CSI0A_L2_T1BC_EQ_BW GENMASK(23, 22)
+#define RG_CSI1A_L0_EQ_IS GENMASK(5, 4)
+#define RG_CSI1A_L0_EQ_BW GENMASK(7, 6)
+#define RG_CSI1A_L1_EQ_IS GENMASK(21, 20)
+#define RG_CSI1A_L1_EQ_BW GENMASK(23, 22)
+#define RG_CSI1A_L2_EQ_IS GENMASK(5, 4)
+#define RG_CSI1A_L2_EQ_BW GENMASK(7, 6)
+
+#define MIPI_RX_ANA1C_CSIXA 0x001c
+#define MIPI_RX_ANA20_CSI0A 0x0020
+
+#define MIPI_RX_ANA24_CSIXA 0x0024
+#define RG_CSIXA_RESERVE GENMASK(31, 24)
+
+#define MIPI_RX_ANA40_CSIXA 0x0040
+#define RG_CSIXA_CPHY_FMCK_SEL GENMASK(1, 0)
+#define RG_CSIXA_ASYNC_OPTION GENMASK(7, 4)
+#define RG_CSIXA_CPHY_SPARE GENMASK(31, 16)
+
+#define MIPI_RX_WRAPPER80_CSIXA 0x0080
+#define CSR_CSI_RST_MODE GENMASK(17, 16)
+
+#define MIPI_RX_ANAA8_CSIXA 0x00a8
+#define RG_CSIXA_CDPHY_L0_T0_BYTECK_INVERT BIT(0)
+#define RG_CSIXA_DPHY_L1_BYTECK_INVERT BIT(1)
+#define RG_CSIXA_CDPHY_L2_T1_BYTECK_INVERT BIT(2)
+
+#endif
diff --git a/drivers/phy/mediatek/phy-mtk-mipi-csi-0-5.c b/drivers/phy/mediatek/phy-mtk-mipi-csi-0-5.c
new file mode 100644
index 000000000000..058e1d926630
--- /dev/null
+++ b/drivers/phy/mediatek/phy-mtk-mipi-csi-0-5.c
@@ -0,0 +1,294 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek MIPI CSI v0.5 driver
+ *
+ * Copyright (c) 2023, MediaTek Inc.
+ * Copyright (c) 2023, BayLibre Inc.
+ */
+
+#include <dt-bindings/phy/phy.h>
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "phy-mtk-io.h"
+#include "phy-mtk-mipi-csi-0-5-rx-reg.h"
+
+#define CSIXB_OFFSET 0x1000
+
+struct mtk_mipi_cdphy_port {
+ struct device *dev;
+ void __iomem *base;
+ struct phy *phy;
+ u32 type;
+ u32 mode;
+ u32 num_lanes;
+};
+
+enum PHY_TYPE {
+ DPHY = 0,
+ CPHY,
+ CDPHY,
+};
+
+static void mtk_phy_csi_cdphy_ana_eq_tune(void __iomem *base)
+{
+ mtk_phy_update_field(base + MIPI_RX_ANA18_CSIXA, RG_CSI0A_L0_T0AB_EQ_IS, 1);
+ mtk_phy_update_field(base + MIPI_RX_ANA18_CSIXA, RG_CSI0A_L0_T0AB_EQ_BW, 1);
+ mtk_phy_update_field(base + MIPI_RX_ANA1C_CSIXA, RG_CSI0A_L1_T1AB_EQ_IS, 1);
+ mtk_phy_update_field(base + MIPI_RX_ANA1C_CSIXA, RG_CSI0A_L1_T1AB_EQ_BW, 1);
+ mtk_phy_update_field(base + MIPI_RX_ANA20_CSI0A, RG_CSI0A_L2_T1BC_EQ_IS, 1);
+ mtk_phy_update_field(base + MIPI_RX_ANA20_CSI0A, RG_CSI0A_L2_T1BC_EQ_BW, 1);
+
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA18_CSIXA, RG_CSI0A_L0_T0AB_EQ_IS, 1);
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA18_CSIXA, RG_CSI0A_L0_T0AB_EQ_BW, 1);
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA1C_CSIXA, RG_CSI0A_L1_T1AB_EQ_IS, 1);
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA1C_CSIXA, RG_CSI0A_L1_T1AB_EQ_BW, 1);
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA20_CSI0A, RG_CSI0A_L2_T1BC_EQ_IS, 1);
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA20_CSI0A, RG_CSI0A_L2_T1BC_EQ_BW, 1);
+}
+
+static void mtk_phy_csi_dphy_ana_eq_tune(void __iomem *base)
+{
+ mtk_phy_update_field(base + MIPI_RX_ANA18_CSIXA, RG_CSI1A_L0_EQ_IS, 1);
+ mtk_phy_update_field(base + MIPI_RX_ANA18_CSIXA, RG_CSI1A_L0_EQ_BW, 1);
+ mtk_phy_update_field(base + MIPI_RX_ANA18_CSIXA, RG_CSI1A_L1_EQ_IS, 1);
+ mtk_phy_update_field(base + MIPI_RX_ANA18_CSIXA, RG_CSI1A_L1_EQ_BW, 1);
+ mtk_phy_update_field(base + MIPI_RX_ANA1C_CSIXA, RG_CSI1A_L2_EQ_IS, 1);
+ mtk_phy_update_field(base + MIPI_RX_ANA1C_CSIXA, RG_CSI1A_L2_EQ_BW, 1);
+
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA18_CSIXA, RG_CSI1A_L0_EQ_IS, 1);
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA18_CSIXA, RG_CSI1A_L0_EQ_BW, 1);
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA18_CSIXA, RG_CSI1A_L1_EQ_IS, 1);
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA18_CSIXA, RG_CSI1A_L1_EQ_BW, 1);
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA1C_CSIXA, RG_CSI1A_L2_EQ_IS, 1);
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA1C_CSIXA, RG_CSI1A_L2_EQ_BW, 1);
+}
+
+static int mtk_mipi_phy_power_on(struct phy *phy)
+{
+ struct mtk_mipi_cdphy_port *port = phy_get_drvdata(phy);
+ void __iomem *base = port->base;
+
+ /*
+ * The driver currently supports DPHY and CD-PHY phys,
+ * but the only mode supported is DPHY,
+ * so CD-PHY capable phys must be configured in DPHY mode
+ */
+ if (port->type == CDPHY) {
+ mtk_phy_update_field(base + MIPI_RX_ANA00_CSIXA, RG_CSI0A_CPHY_EN, 0);
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA00_CSIXA,
+ RG_CSI0A_CPHY_EN, 0);
+ }
+
+ /*
+ * Lane configuration:
+ *
+ * Only 4 data + 1 clock is supported for now with the following mapping:
+ *
+ * CSIXA_LNR0 --> D2
+ * CSIXA_LNR1 --> D0
+ * CSIXA_LNR2 --> C
+ * CSIXB_LNR0 --> D1
+ * CSIXB_LNR1 --> D3
+ */
+ mtk_phy_update_field(base + MIPI_RX_ANA00_CSIXA, RG_CSIXA_DPHY_L0_CKMODE_EN, 0);
+ mtk_phy_update_field(base + MIPI_RX_ANA00_CSIXA, RG_CSIXA_DPHY_L0_CKSEL, 1);
+ mtk_phy_update_field(base + MIPI_RX_ANA00_CSIXA, RG_CSIXA_DPHY_L1_CKMODE_EN, 0);
+ mtk_phy_update_field(base + MIPI_RX_ANA00_CSIXA, RG_CSIXA_DPHY_L1_CKSEL, 1);
+ mtk_phy_update_field(base + MIPI_RX_ANA00_CSIXA, RG_CSIXA_DPHY_L2_CKMODE_EN, 1);
+ mtk_phy_update_field(base + MIPI_RX_ANA00_CSIXA, RG_CSIXA_DPHY_L2_CKSEL, 1);
+
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA00_CSIXA,
+ RG_CSIXA_DPHY_L0_CKMODE_EN, 0);
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA00_CSIXA, RG_CSIXA_DPHY_L0_CKSEL, 1);
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA00_CSIXA,
+ RG_CSIXA_DPHY_L1_CKMODE_EN, 0);
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA00_CSIXA, RG_CSIXA_DPHY_L1_CKSEL, 1);
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA00_CSIXA,
+ RG_CSIXA_DPHY_L2_CKMODE_EN, 0);
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA00_CSIXA, RG_CSIXA_DPHY_L2_CKSEL, 1);
+
+ /* Byte clock invert */
+ mtk_phy_update_field(base + MIPI_RX_ANAA8_CSIXA, RG_CSIXA_CDPHY_L0_T0_BYTECK_INVERT, 1);
+ mtk_phy_update_field(base + MIPI_RX_ANAA8_CSIXA, RG_CSIXA_DPHY_L1_BYTECK_INVERT, 1);
+ mtk_phy_update_field(base + MIPI_RX_ANAA8_CSIXA, RG_CSIXA_CDPHY_L2_T1_BYTECK_INVERT, 1);
+
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANAA8_CSIXA,
+ RG_CSIXA_CDPHY_L0_T0_BYTECK_INVERT, 1);
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANAA8_CSIXA,
+ RG_CSIXA_DPHY_L1_BYTECK_INVERT, 1);
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANAA8_CSIXA,
+ RG_CSIXA_CDPHY_L2_T1_BYTECK_INVERT, 1);
+
+ /* Start ANA EQ tuning */
+ if (port->type == CDPHY)
+ mtk_phy_csi_cdphy_ana_eq_tune(base);
+ else
+ mtk_phy_csi_dphy_ana_eq_tune(base);
+
+ /* End ANA EQ tuning */
+ mtk_phy_set_bits(base + MIPI_RX_ANA40_CSIXA, 0x90);
+
+ mtk_phy_update_field(base + MIPI_RX_ANA24_CSIXA, RG_CSIXA_RESERVE, 0x40);
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA24_CSIXA, RG_CSIXA_RESERVE, 0x40);
+ mtk_phy_update_field(base + MIPI_RX_WRAPPER80_CSIXA, CSR_CSI_RST_MODE, 0);
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_WRAPPER80_CSIXA, CSR_CSI_RST_MODE, 0);
+ /* ANA power on */
+ mtk_phy_update_field(base + MIPI_RX_ANA00_CSIXA, RG_CSIXA_BG_CORE_EN, 1);
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA00_CSIXA, RG_CSIXA_BG_CORE_EN, 1);
+ usleep_range(20, 40);
+ mtk_phy_update_field(base + MIPI_RX_ANA00_CSIXA, RG_CSIXA_BG_LPF_EN, 1);
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA00_CSIXA, RG_CSIXA_BG_LPF_EN, 1);
+
+ return 0;
+}
+
+static int mtk_mipi_phy_power_off(struct phy *phy)
+{
+ struct mtk_mipi_cdphy_port *port = phy_get_drvdata(phy);
+ void __iomem *base = port->base;
+
+ /* Disable MIPI BG. */
+ mtk_phy_update_field(base + MIPI_RX_ANA00_CSIXA, RG_CSIXA_BG_CORE_EN, 0);
+ mtk_phy_update_field(base + MIPI_RX_ANA00_CSIXA, RG_CSIXA_BG_LPF_EN, 0);
+
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA00_CSIXA, RG_CSIXA_BG_CORE_EN, 0);
+ mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA00_CSIXA, RG_CSIXA_BG_LPF_EN, 0);
+
+ return 0;
+}
+
+static struct phy *mtk_mipi_cdphy_xlate(struct device *dev,
+ const struct of_phandle_args *args)
+{
+ struct mtk_mipi_cdphy_port *priv = dev_get_drvdata(dev);
+
+ /*
+ * If PHY is CD-PHY then we need to get the operating mode
+ * For now only D-PHY mode is supported
+ */
+ if (priv->type == CDPHY) {
+ if (args->args_count != 1) {
+ dev_err(dev, "invalid number of arguments\n");
+ return ERR_PTR(-EINVAL);
+ }
+ switch (args->args[0]) {
+ case PHY_TYPE_DPHY:
+ priv->mode = DPHY;
+ if (priv->num_lanes != 4) {
+ dev_err(dev, "Only 4D1C mode is supported for now!\n");
+ return ERR_PTR(-EINVAL);
+ }
+ break;
+ default:
+ dev_err(dev, "Unsupported PHY type: %i\n", args->args[0]);
+ return ERR_PTR(-EINVAL);
+ }
+ } else {
+ if (args->args_count) {
+ dev_err(dev, "invalid number of arguments\n");
+ return ERR_PTR(-EINVAL);
+ }
+ priv->mode = DPHY;
+ }
+
+ return priv->phy;
+}
+
+static const struct phy_ops mtk_cdphy_ops = {
+ .power_on = mtk_mipi_phy_power_on,
+ .power_off = mtk_mipi_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+static int mtk_mipi_cdphy_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct phy_provider *phy_provider;
+ struct mtk_mipi_cdphy_port *port;
+ struct phy *phy;
+ int ret;
+ u32 phy_type;
+
+ port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
+ if (!port)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, port);
+
+ port->dev = dev;
+
+ port->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(port->base))
+ return PTR_ERR(port->base);
+
+ ret = of_property_read_u32(dev->of_node, "num-lanes", &port->num_lanes);
+ if (ret) {
+ dev_err(dev, "Failed to read num-lanes property: %i\n", ret);
+ return ret;
+ }
+
+ /*
+ * phy-type is optional, if not present, PHY is considered to be CD-PHY
+ */
+ if (device_property_present(dev, "phy-type")) {
+ ret = of_property_read_u32(dev->of_node, "phy-type", &phy_type);
+ if (ret) {
+ dev_err(dev, "Failed to read phy-type property: %i\n", ret);
+ return ret;
+ }
+ switch (phy_type) {
+ case PHY_TYPE_DPHY:
+ port->type = DPHY;
+ break;
+ default:
+ dev_err(dev, "Unsupported PHY type: %i\n", phy_type);
+ return -EINVAL;
+ }
+ } else {
+ port->type = CDPHY;
+ }
+
+ phy = devm_phy_create(dev, NULL, &mtk_cdphy_ops);
+ if (IS_ERR(phy)) {
+ dev_err(dev, "Failed to create PHY: %ld\n", PTR_ERR(phy));
+ return PTR_ERR(phy);
+ }
+
+ port->phy = phy;
+ phy_set_drvdata(phy, port);
+
+ phy_provider = devm_of_phy_provider_register(dev, mtk_mipi_cdphy_xlate);
+ if (IS_ERR(phy_provider)) {
+ dev_err(dev, "Failed to register PHY provider: %ld\n",
+ PTR_ERR(phy_provider));
+ return PTR_ERR(phy_provider);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id mtk_mipi_cdphy_of_match[] = {
+ { .compatible = "mediatek,mt8365-csi-rx" },
+ { /* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, mtk_mipi_cdphy_of_match);
+
+static struct platform_driver mipi_cdphy_pdrv = {
+ .probe = mtk_mipi_cdphy_probe,
+ .driver = {
+ .name = "mtk-mipi-csi-0-5",
+ .of_match_table = mtk_mipi_cdphy_of_match,
+ },
+};
+module_platform_driver(mipi_cdphy_pdrv);
+
+MODULE_DESCRIPTION("MediaTek MIPI CSI CD-PHY v0.5 Driver");
+MODULE_AUTHOR("Louis Kuo <louis.kuo@mediatek.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c
index a4746f6cb8a1..a496fbe3352b 100644
--- a/drivers/phy/mediatek/phy-mtk-tphy.c
+++ b/drivers/phy/mediatek/phy-mtk-tphy.c
@@ -381,17 +381,12 @@ static const char *const u3_phy_files[] = {
static int u2_phy_params_show(struct seq_file *sf, void *unused)
{
struct mtk_phy_instance *inst = sf->private;
- const char *fname = file_dentry(sf->file)->d_iname;
struct u2phy_banks *u2_banks = &inst->u2_banks;
void __iomem *com = u2_banks->com;
u32 max = 0;
u32 tmp = 0;
u32 val = 0;
- int ret;
-
- ret = match_string(u2_phy_files, ARRAY_SIZE(u2_phy_files), fname);
- if (ret < 0)
- return ret;
+ int ret = debugfs_get_aux_num(sf->file);
switch (ret) {
case U2P_EYE_VRT:
@@ -438,7 +433,7 @@ static int u2_phy_params_show(struct seq_file *sf, void *unused)
break;
}
- seq_printf(sf, "%s : %d [0, %d]\n", fname, val, max);
+ seq_printf(sf, "%s : %d [0, %d]\n", u2_phy_files[ret], val, max);
return 0;
}
@@ -451,23 +446,18 @@ static int u2_phy_params_open(struct inode *inode, struct file *file)
static ssize_t u2_phy_params_write(struct file *file, const char __user *ubuf,
size_t count, loff_t *ppos)
{
- const char *fname = file_dentry(file)->d_iname;
struct seq_file *sf = file->private_data;
struct mtk_phy_instance *inst = sf->private;
struct u2phy_banks *u2_banks = &inst->u2_banks;
void __iomem *com = u2_banks->com;
ssize_t rc;
u32 val;
- int ret;
+ int ret = debugfs_get_aux_num(file);
rc = kstrtouint_from_user(ubuf, USER_BUF_LEN(count), 0, &val);
if (rc)
return rc;
- ret = match_string(u2_phy_files, ARRAY_SIZE(u2_phy_files), fname);
- if (ret < 0)
- return (ssize_t)ret;
-
switch (ret) {
case U2P_EYE_VRT:
mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_VRT_SEL, val);
@@ -516,23 +506,18 @@ static void u2_phy_dbgfs_files_create(struct mtk_phy_instance *inst)
int i;
for (i = 0; i < count; i++)
- debugfs_create_file(u2_phy_files[i], 0644, inst->phy->debugfs,
- inst, &u2_phy_fops);
+ debugfs_create_file_aux_num(u2_phy_files[i], 0644, inst->phy->debugfs,
+ inst, i, &u2_phy_fops);
}
static int u3_phy_params_show(struct seq_file *sf, void *unused)
{
struct mtk_phy_instance *inst = sf->private;
- const char *fname = file_dentry(sf->file)->d_iname;
struct u3phy_banks *u3_banks = &inst->u3_banks;
u32 val = 0;
u32 max = 0;
u32 tmp;
- int ret;
-
- ret = match_string(u3_phy_files, ARRAY_SIZE(u3_phy_files), fname);
- if (ret < 0)
- return ret;
+ int ret = debugfs_get_aux_num(sf->file);
switch (ret) {
case U3P_EFUSE_EN:
@@ -564,7 +549,7 @@ static int u3_phy_params_show(struct seq_file *sf, void *unused)
break;
}
- seq_printf(sf, "%s : %d [0, %d]\n", fname, val, max);
+ seq_printf(sf, "%s : %d [0, %d]\n", u3_phy_files[ret], val, max);
return 0;
}
@@ -577,23 +562,18 @@ static int u3_phy_params_open(struct inode *inode, struct file *file)
static ssize_t u3_phy_params_write(struct file *file, const char __user *ubuf,
size_t count, loff_t *ppos)
{
- const char *fname = file_dentry(file)->d_iname;
struct seq_file *sf = file->private_data;
struct mtk_phy_instance *inst = sf->private;
struct u3phy_banks *u3_banks = &inst->u3_banks;
void __iomem *phyd = u3_banks->phyd;
ssize_t rc;
u32 val;
- int ret;
+ int ret = debugfs_get_aux_num(sf->file);
rc = kstrtouint_from_user(ubuf, USER_BUF_LEN(count), 0, &val);
if (rc)
return rc;
- ret = match_string(u3_phy_files, ARRAY_SIZE(u3_phy_files), fname);
- if (ret < 0)
- return (ssize_t)ret;
-
switch (ret) {
case U3P_EFUSE_EN:
mtk_phy_update_field(phyd + U3P_U3_PHYD_RSV,
@@ -636,8 +616,8 @@ static void u3_phy_dbgfs_files_create(struct mtk_phy_instance *inst)
int i;
for (i = 0; i < count; i++)
- debugfs_create_file(u3_phy_files[i], 0644, inst->phy->debugfs,
- inst, &u3_phy_fops);
+ debugfs_create_file_aux_num(u3_phy_files[i], 0644, inst->phy->debugfs,
+ inst, i, &u3_phy_fops);
}
static int phy_type_show(struct seq_file *sf, void *unused)
@@ -1467,7 +1447,7 @@ static int mtk_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
}
static struct phy *mtk_phy_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct mtk_tphy *tphy = dev_get_drvdata(dev);
struct mtk_phy_instance *instance = NULL;
@@ -1577,12 +1557,11 @@ static int mtk_tphy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
- struct device_node *child_np;
struct phy_provider *provider;
struct resource *sif_res;
struct mtk_tphy *tphy;
struct resource res;
- int port, retval;
+ int port;
tphy = devm_kzalloc(dev, sizeof(*tphy), GFP_KERNEL);
if (!tphy)
@@ -1623,25 +1602,23 @@ static int mtk_tphy_probe(struct platform_device *pdev)
}
port = 0;
- for_each_child_of_node(np, child_np) {
+ for_each_child_of_node_scoped(np, child_np) {
struct mtk_phy_instance *instance;
struct clk_bulk_data *clks;
struct device *subdev;
struct phy *phy;
+ int retval;
instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
- if (!instance) {
- retval = -ENOMEM;
- goto put_child;
- }
+ if (!instance)
+ return -ENOMEM;
tphy->phys[port] = instance;
phy = devm_phy_create(dev, child_np, &mtk_tphy_ops);
if (IS_ERR(phy)) {
dev_err(dev, "failed to create phy\n");
- retval = PTR_ERR(phy);
- goto put_child;
+ return PTR_ERR(phy);
}
subdev = &phy->dev;
@@ -1649,14 +1626,12 @@ static int mtk_tphy_probe(struct platform_device *pdev)
if (retval) {
dev_err(subdev, "failed to get address resource(id-%d)\n",
port);
- goto put_child;
+ return retval;
}
instance->port_base = devm_ioremap_resource(subdev, &res);
- if (IS_ERR(instance->port_base)) {
- retval = PTR_ERR(instance->port_base);
- goto put_child;
- }
+ if (IS_ERR(instance->port_base))
+ return PTR_ERR(instance->port_base);
instance->phy = phy;
instance->index = port;
@@ -1668,19 +1643,16 @@ static int mtk_tphy_probe(struct platform_device *pdev)
clks[1].id = "da_ref"; /* analog clock */
retval = devm_clk_bulk_get_optional(subdev, TPHY_CLKS_CNT, clks);
if (retval)
- goto put_child;
+ return retval;
retval = phy_type_syscon_get(instance, child_np);
if (retval)
- goto put_child;
+ return retval;
}
provider = devm_of_phy_provider_register(dev, mtk_phy_xlate);
return PTR_ERR_OR_ZERO(provider);
-put_child:
- of_node_put(child_np);
- return retval;
}
static struct platform_driver mtk_tphy_driver = {
diff --git a/drivers/phy/mediatek/phy-mtk-xfi-tphy.c b/drivers/phy/mediatek/phy-mtk-xfi-tphy.c
new file mode 100644
index 000000000000..1a0b7484f525
--- /dev/null
+++ b/drivers/phy/mediatek/phy-mtk-xfi-tphy.c
@@ -0,0 +1,451 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * MediaTek 10GE SerDes XFI T-PHY driver
+ *
+ * Copyright (c) 2024 Daniel Golle <daniel@makrotopia.org>
+ * Bc-bocun Chen <bc-bocun.chen@mediatek.com>
+ * based on mtk_usxgmii.c and mtk_sgmii.c found in MediaTek's SDK (GPL-2.0)
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Henry Yen <henry.yen@mediatek.com>
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+#include <linux/phy.h>
+#include <linux/phy/phy.h>
+
+#include "phy-mtk-io.h"
+
+#define MTK_XFI_TPHY_NUM_CLOCKS 2
+
+#define REG_DIG_GLB_70 0x0070
+#define XTP_PCS_RX_EQ_IN_PROGRESS(x) FIELD_PREP(GENMASK(25, 24), (x))
+#define XTP_PCS_MODE_MASK GENMASK(17, 16)
+#define XTP_PCS_MODE(x) FIELD_PREP(GENMASK(17, 16), (x))
+#define XTP_PCS_RST_B BIT(15)
+#define XTP_FRC_PCS_RST_B BIT(14)
+#define XTP_PCS_PWD_SYNC_MASK GENMASK(13, 12)
+#define XTP_PCS_PWD_SYNC(x) FIELD_PREP(XTP_PCS_PWD_SYNC_MASK, (x))
+#define XTP_PCS_PWD_ASYNC_MASK GENMASK(11, 10)
+#define XTP_PCS_PWD_ASYNC(x) FIELD_PREP(XTP_PCS_PWD_ASYNC_MASK, (x))
+#define XTP_FRC_PCS_PWD_ASYNC BIT(8)
+#define XTP_PCS_UPDT BIT(4)
+#define XTP_PCS_IN_FR_RG BIT(0)
+
+#define REG_DIG_GLB_F4 0x00f4
+#define XFI_DPHY_PCS_SEL BIT(0)
+#define XFI_DPHY_PCS_SEL_SGMII FIELD_PREP(XFI_DPHY_PCS_SEL, 1)
+#define XFI_DPHY_PCS_SEL_USXGMII FIELD_PREP(XFI_DPHY_PCS_SEL, 0)
+#define XFI_DPHY_AD_SGDT_FRC_EN BIT(5)
+
+#define REG_DIG_LN_TRX_40 0x3040
+#define XTP_LN_FRC_TX_DATA_EN BIT(29)
+#define XTP_LN_TX_DATA_EN BIT(28)
+
+#define REG_DIG_LN_TRX_B0 0x30b0
+#define XTP_LN_FRC_TX_MACCK_EN BIT(5)
+#define XTP_LN_TX_MACCK_EN BIT(4)
+
+#define REG_ANA_GLB_D0 0x90d0
+#define XTP_GLB_USXGMII_SEL_MASK GENMASK(3, 1)
+#define XTP_GLB_USXGMII_SEL(x) FIELD_PREP(GENMASK(3, 1), (x))
+#define XTP_GLB_USXGMII_EN BIT(0)
+
+/**
+ * struct mtk_xfi_tphy - run-time data of the XFI phy instance
+ * @base: IO memory area to access phy registers.
+ * @dev: Kernel device used to output prefixed debug info.
+ * @reset: Reset control corresponding to the phy instance.
+ * @clocks: All clocks required for the phy to operate.
+ * @da_war: Enables work-around for 10GBase-R mode.
+ */
+struct mtk_xfi_tphy {
+ void __iomem *base;
+ struct device *dev;
+ struct reset_control *reset;
+ struct clk_bulk_data clocks[MTK_XFI_TPHY_NUM_CLOCKS];
+ bool da_war;
+};
+
+/**
+ * mtk_xfi_tphy_setup() - Setup phy for specified interface mode.
+ * @xfi_tphy: XFI phy instance.
+ * @interface: Ethernet interface mode
+ *
+ * The setup function is the condensed result of combining the 5 functions which
+ * setup the phy in MediaTek's GPL licensed public SDK sources. They can be found
+ * in mtk_sgmii.c[1] as well as mtk_usxgmii.c[2].
+ *
+ * Many magic values have been replaced by register and bit definitions, however,
+ * that has not been possible in all cases. While the vendor driver uses a
+ * sequence of 32-bit writes, here we try to only modify the actually required
+ * bits.
+ *
+ * [1]: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/b72d6cba92bf9e29fb035c03052fa1e86664a25b/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c
+ *
+ * [2]: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/dec96a1d9b82cdcda4a56453fd0b453d4cab4b85/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+ */
+static void mtk_xfi_tphy_setup(struct mtk_xfi_tphy *xfi_tphy,
+ phy_interface_t interface)
+{
+ bool is_1g, is_2p5g, is_5g, is_10g, da_war, use_lynxi_pcs;
+
+ /* shorthands for specific clock speeds depending on interface mode */
+ is_1g = interface == PHY_INTERFACE_MODE_1000BASEX ||
+ interface == PHY_INTERFACE_MODE_SGMII;
+ is_2p5g = interface == PHY_INTERFACE_MODE_2500BASEX;
+ is_5g = interface == PHY_INTERFACE_MODE_5GBASER;
+ is_10g = interface == PHY_INTERFACE_MODE_10GBASER ||
+ interface == PHY_INTERFACE_MODE_USXGMII;
+
+ /* Is overriding 10GBase-R tuning value required? */
+ da_war = xfi_tphy->da_war && (interface == PHY_INTERFACE_MODE_10GBASER);
+
+ /* configure input mux to either
+ * - USXGMII PCS (64b/66b coding) for 5G/10G
+ * - LynxI PCS (8b/10b coding) for 1G/2.5G
+ */
+ use_lynxi_pcs = is_1g || is_2p5g;
+
+ dev_dbg(xfi_tphy->dev, "setting up for mode %s\n", phy_modes(interface));
+
+ /* Setup PLL setting */
+ mtk_phy_update_bits(xfi_tphy->base + 0x9024, 0x100000, is_10g ? 0x0 : 0x100000);
+ mtk_phy_update_bits(xfi_tphy->base + 0x2020, 0x202000, is_5g ? 0x202000 : 0x0);
+ mtk_phy_update_bits(xfi_tphy->base + 0x2030, 0x500, is_1g ? 0x0 : 0x500);
+ mtk_phy_update_bits(xfi_tphy->base + 0x2034, 0xa00, is_1g ? 0x0 : 0xa00);
+ mtk_phy_update_bits(xfi_tphy->base + 0x2040, 0x340000, is_1g ? 0x200000 : 0x140000);
+
+ /* Setup RXFE BW setting */
+ mtk_phy_update_bits(xfi_tphy->base + 0x50f0, 0xc10, is_1g ? 0x410 : is_5g ? 0x800 : 0x400);
+ mtk_phy_update_bits(xfi_tphy->base + 0x50e0, 0x4000, is_5g ? 0x0 : 0x4000);
+
+ /* Setup RX CDR setting */
+ mtk_phy_update_bits(xfi_tphy->base + 0x506c, 0x30000, is_5g ? 0x0 : 0x30000);
+ mtk_phy_update_bits(xfi_tphy->base + 0x5070, 0x670000, is_5g ? 0x620000 : 0x50000);
+ mtk_phy_update_bits(xfi_tphy->base + 0x5074, 0x180000, is_5g ? 0x180000 : 0x0);
+ mtk_phy_update_bits(xfi_tphy->base + 0x5078, 0xf000400, is_5g ? 0x8000000 :
+ 0x7000400);
+ mtk_phy_update_bits(xfi_tphy->base + 0x507c, 0x5000500, is_5g ? 0x4000400 :
+ 0x1000100);
+ mtk_phy_update_bits(xfi_tphy->base + 0x5080, 0x1410, is_1g ? 0x400 : is_5g ? 0x1010 : 0x0);
+ mtk_phy_update_bits(xfi_tphy->base + 0x5084, 0x30300, is_1g ? 0x30300 :
+ is_5g ? 0x30100 :
+ 0x100);
+ mtk_phy_update_bits(xfi_tphy->base + 0x5088, 0x60200, is_1g ? 0x20200 :
+ is_5g ? 0x40000 :
+ 0x20000);
+
+ /* Setting RXFE adaptation range setting */
+ mtk_phy_update_bits(xfi_tphy->base + 0x50e4, 0xc0000, is_5g ? 0x0 : 0xc0000);
+ mtk_phy_update_bits(xfi_tphy->base + 0x50e8, 0x40000, is_5g ? 0x0 : 0x40000);
+ mtk_phy_update_bits(xfi_tphy->base + 0x50ec, 0xa00, is_1g ? 0x200 : 0x800);
+ mtk_phy_update_bits(xfi_tphy->base + 0x50a8, 0xee0000, is_5g ? 0x800000 :
+ 0x6e0000);
+ mtk_phy_update_bits(xfi_tphy->base + 0x6004, 0x190000, is_5g ? 0x0 : 0x190000);
+
+ if (is_10g)
+ writel(0x01423342, xfi_tphy->base + 0x00f8);
+ else if (is_5g)
+ writel(0x00a132a1, xfi_tphy->base + 0x00f8);
+ else if (is_2p5g)
+ writel(0x009c329c, xfi_tphy->base + 0x00f8);
+ else
+ writel(0x00fa32fa, xfi_tphy->base + 0x00f8);
+
+ /* Force SGDT_OUT off and select PCS */
+ mtk_phy_update_bits(xfi_tphy->base + REG_DIG_GLB_F4,
+ XFI_DPHY_AD_SGDT_FRC_EN | XFI_DPHY_PCS_SEL,
+ XFI_DPHY_AD_SGDT_FRC_EN |
+ (use_lynxi_pcs ? XFI_DPHY_PCS_SEL_SGMII :
+ XFI_DPHY_PCS_SEL_USXGMII));
+
+ /* Force GLB_CKDET_OUT */
+ mtk_phy_set_bits(xfi_tphy->base + 0x0030, 0xc00);
+
+ /* Force AEQ on */
+ writel(XTP_PCS_RX_EQ_IN_PROGRESS(2) | XTP_PCS_PWD_SYNC(2) | XTP_PCS_PWD_ASYNC(2),
+ xfi_tphy->base + REG_DIG_GLB_70);
+
+ usleep_range(1, 5);
+ writel(XTP_LN_FRC_TX_DATA_EN, xfi_tphy->base + REG_DIG_LN_TRX_40);
+
+ /* Setup TX DA default value */
+ mtk_phy_update_bits(xfi_tphy->base + 0x30b0, 0x30, 0x20);
+ writel(0x00008a01, xfi_tphy->base + 0x3028);
+ writel(0x0000a884, xfi_tphy->base + 0x302c);
+ writel(0x00083002, xfi_tphy->base + 0x3024);
+
+ /* Setup RG default value */
+ if (use_lynxi_pcs) {
+ writel(0x00011110, xfi_tphy->base + 0x3010);
+ writel(0x40704000, xfi_tphy->base + 0x3048);
+ } else {
+ writel(0x00022220, xfi_tphy->base + 0x3010);
+ writel(0x0f020a01, xfi_tphy->base + 0x5064);
+ writel(0x06100600, xfi_tphy->base + 0x50b4);
+ if (interface == PHY_INTERFACE_MODE_USXGMII)
+ writel(0x40704000, xfi_tphy->base + 0x3048);
+ else
+ writel(0x47684100, xfi_tphy->base + 0x3048);
+ }
+
+ if (is_1g)
+ writel(0x0000c000, xfi_tphy->base + 0x3064);
+
+ /* Setup RX EQ initial value */
+ mtk_phy_update_bits(xfi_tphy->base + 0x3050, 0xa8000000,
+ (interface != PHY_INTERFACE_MODE_10GBASER) ? 0xa8000000 : 0x0);
+ mtk_phy_update_bits(xfi_tphy->base + 0x3054, 0xaa,
+ (interface != PHY_INTERFACE_MODE_10GBASER) ? 0xaa : 0x0);
+
+ if (!use_lynxi_pcs)
+ writel(0x00000f00, xfi_tphy->base + 0x306c);
+ else if (is_2p5g)
+ writel(0x22000f00, xfi_tphy->base + 0x306c);
+ else
+ writel(0x20200f00, xfi_tphy->base + 0x306c);
+
+ mtk_phy_update_bits(xfi_tphy->base + 0xa008, 0x10000, da_war ? 0x10000 : 0x0);
+
+ mtk_phy_update_bits(xfi_tphy->base + 0xa060, 0x50000, use_lynxi_pcs ? 0x50000 : 0x40000);
+
+ /* Setup PHYA speed */
+ mtk_phy_update_bits(xfi_tphy->base + REG_ANA_GLB_D0,
+ XTP_GLB_USXGMII_SEL_MASK | XTP_GLB_USXGMII_EN,
+ is_10g ? XTP_GLB_USXGMII_SEL(0) :
+ is_5g ? XTP_GLB_USXGMII_SEL(1) :
+ is_2p5g ? XTP_GLB_USXGMII_SEL(2) :
+ XTP_GLB_USXGMII_SEL(3));
+ mtk_phy_set_bits(xfi_tphy->base + REG_ANA_GLB_D0, XTP_GLB_USXGMII_EN);
+
+ /* Release reset */
+ mtk_phy_set_bits(xfi_tphy->base + REG_DIG_GLB_70,
+ XTP_PCS_RST_B | XTP_FRC_PCS_RST_B);
+ usleep_range(150, 500);
+
+ /* Switch to P0 */
+ mtk_phy_update_bits(xfi_tphy->base + REG_DIG_GLB_70,
+ XTP_PCS_IN_FR_RG |
+ XTP_FRC_PCS_PWD_ASYNC |
+ XTP_PCS_PWD_ASYNC_MASK |
+ XTP_PCS_PWD_SYNC_MASK |
+ XTP_PCS_UPDT,
+ XTP_PCS_IN_FR_RG |
+ XTP_FRC_PCS_PWD_ASYNC |
+ XTP_PCS_UPDT);
+ usleep_range(1, 5);
+
+ mtk_phy_clear_bits(xfi_tphy->base + REG_DIG_GLB_70, XTP_PCS_UPDT);
+ usleep_range(15, 50);
+
+ if (use_lynxi_pcs) {
+ /* Switch to Gen2 */
+ mtk_phy_update_bits(xfi_tphy->base + REG_DIG_GLB_70,
+ XTP_PCS_MODE_MASK | XTP_PCS_UPDT,
+ XTP_PCS_MODE(1) | XTP_PCS_UPDT);
+ } else {
+ /* Switch to Gen3 */
+ mtk_phy_update_bits(xfi_tphy->base + REG_DIG_GLB_70,
+ XTP_PCS_MODE_MASK | XTP_PCS_UPDT,
+ XTP_PCS_MODE(2) | XTP_PCS_UPDT);
+ }
+ usleep_range(1, 5);
+
+ mtk_phy_clear_bits(xfi_tphy->base + REG_DIG_GLB_70, XTP_PCS_UPDT);
+
+ usleep_range(100, 500);
+
+ /* Enable MAC CK */
+ mtk_phy_set_bits(xfi_tphy->base + REG_DIG_LN_TRX_B0, XTP_LN_TX_MACCK_EN);
+ mtk_phy_clear_bits(xfi_tphy->base + REG_DIG_GLB_F4, XFI_DPHY_AD_SGDT_FRC_EN);
+
+ /* Enable TX data */
+ mtk_phy_set_bits(xfi_tphy->base + REG_DIG_LN_TRX_40,
+ XTP_LN_FRC_TX_DATA_EN | XTP_LN_TX_DATA_EN);
+ usleep_range(400, 1000);
+}
+
+/**
+ * mtk_xfi_tphy_set_mode() - Setup phy for specified interface mode.
+ *
+ * @phy: Phy instance.
+ * @mode: Only PHY_MODE_ETHERNET is supported.
+ * @submode: An Ethernet interface mode.
+ *
+ * Validate selected mode and call function mtk_xfi_tphy_setup().
+ *
+ * Return:
+ * * %0 - OK
+ * * %-EINVAL - invalid mode
+ */
+static int mtk_xfi_tphy_set_mode(struct phy *phy, enum phy_mode mode, int
+ submode)
+{
+ struct mtk_xfi_tphy *xfi_tphy = phy_get_drvdata(phy);
+
+ if (mode != PHY_MODE_ETHERNET)
+ return -EINVAL;
+
+ switch (submode) {
+ case PHY_INTERFACE_MODE_1000BASEX:
+ case PHY_INTERFACE_MODE_2500BASEX:
+ case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_5GBASER:
+ case PHY_INTERFACE_MODE_10GBASER:
+ case PHY_INTERFACE_MODE_USXGMII:
+ mtk_xfi_tphy_setup(xfi_tphy, submode);
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+/**
+ * mtk_xfi_tphy_reset() - Reset the phy.
+ *
+ * @phy: Phy instance.
+ *
+ * Reset the phy using the external reset controller.
+ *
+ * Return:
+ * %0 - OK
+ */
+static int mtk_xfi_tphy_reset(struct phy *phy)
+{
+ struct mtk_xfi_tphy *xfi_tphy = phy_get_drvdata(phy);
+
+ reset_control_assert(xfi_tphy->reset);
+ usleep_range(100, 500);
+ reset_control_deassert(xfi_tphy->reset);
+ usleep_range(1, 10);
+
+ return 0;
+}
+
+/**
+ * mtk_xfi_tphy_power_on() - Power-on the phy.
+ *
+ * @phy: Phy instance.
+ *
+ * Prepare and enable all clocks required for the phy to operate.
+ *
+ * Return:
+ * See clk_bulk_prepare_enable().
+ */
+static int mtk_xfi_tphy_power_on(struct phy *phy)
+{
+ struct mtk_xfi_tphy *xfi_tphy = phy_get_drvdata(phy);
+
+ return clk_bulk_prepare_enable(MTK_XFI_TPHY_NUM_CLOCKS, xfi_tphy->clocks);
+}
+
+/**
+ * mtk_xfi_tphy_power_off() - Power-off the phy.
+ *
+ * @phy: Phy instance.
+ *
+ * Disable and unprepare all clocks previously enabled.
+ *
+ * Return:
+ * See clk_bulk_prepare_disable().
+ */
+static int mtk_xfi_tphy_power_off(struct phy *phy)
+{
+ struct mtk_xfi_tphy *xfi_tphy = phy_get_drvdata(phy);
+
+ clk_bulk_disable_unprepare(MTK_XFI_TPHY_NUM_CLOCKS, xfi_tphy->clocks);
+
+ return 0;
+}
+
+static const struct phy_ops mtk_xfi_tphy_ops = {
+ .power_on = mtk_xfi_tphy_power_on,
+ .power_off = mtk_xfi_tphy_power_off,
+ .set_mode = mtk_xfi_tphy_set_mode,
+ .reset = mtk_xfi_tphy_reset,
+ .owner = THIS_MODULE,
+};
+
+/**
+ * mtk_xfi_tphy_probe() - Probe phy instance from Device Tree.
+ * @pdev: Matching platform device.
+ *
+ * The probe function gets IO resource, clocks, reset controller and
+ * whether the DA work-around for 10GBase-R is required from Device Tree and
+ * allocates memory for holding that information in a struct mtk_xfi_tphy.
+ *
+ * Return:
+ * * %0 - OK
+ * * %-ENODEV - Missing associated Device Tree node (should never happen).
+ * * %-ENOMEM - Out of memory.
+ * * Any error value which devm_platform_ioremap_resource(),
+ * devm_clk_bulk_get(), devm_reset_control_get_exclusive(),
+ * devm_phy_create() or devm_of_phy_provider_register() may return.
+ */
+static int mtk_xfi_tphy_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct phy_provider *phy_provider;
+ struct mtk_xfi_tphy *xfi_tphy;
+ struct phy *phy;
+ int ret;
+
+ if (!np)
+ return -ENODEV;
+
+ xfi_tphy = devm_kzalloc(&pdev->dev, sizeof(*xfi_tphy), GFP_KERNEL);
+ if (!xfi_tphy)
+ return -ENOMEM;
+
+ xfi_tphy->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(xfi_tphy->base))
+ return PTR_ERR(xfi_tphy->base);
+
+ xfi_tphy->dev = &pdev->dev;
+ xfi_tphy->clocks[0].id = "topxtal";
+ xfi_tphy->clocks[1].id = "xfipll";
+ ret = devm_clk_bulk_get(&pdev->dev, MTK_XFI_TPHY_NUM_CLOCKS, xfi_tphy->clocks);
+ if (ret)
+ return ret;
+
+ xfi_tphy->reset = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+ if (IS_ERR(xfi_tphy->reset))
+ return PTR_ERR(xfi_tphy->reset);
+
+ xfi_tphy->da_war = of_property_read_bool(np, "mediatek,usxgmii-performance-errata");
+
+ phy = devm_phy_create(&pdev->dev, NULL, &mtk_xfi_tphy_ops);
+ if (IS_ERR(phy))
+ return PTR_ERR(phy);
+
+ phy_set_drvdata(phy, xfi_tphy);
+ phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
+
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id mtk_xfi_tphy_match[] = {
+ { .compatible = "mediatek,mt7988-xfi-tphy", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mtk_xfi_tphy_match);
+
+static struct platform_driver mtk_xfi_tphy_driver = {
+ .probe = mtk_xfi_tphy_probe,
+ .driver = {
+ .name = "mtk-xfi-tphy",
+ .of_match_table = mtk_xfi_tphy_match,
+ },
+};
+module_platform_driver(mtk_xfi_tphy_driver);
+
+MODULE_DESCRIPTION("MediaTek 10GE SerDes XFI T-PHY driver");
+MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
+MODULE_AUTHOR("Bc-bocun Chen <bc-bocun.chen@mediatek.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/mediatek/phy-mtk-xsphy.c b/drivers/phy/mediatek/phy-mtk-xsphy.c
index b222fbbd71d1..7c248f5cfca5 100644
--- a/drivers/phy/mediatek/phy-mtk-xsphy.c
+++ b/drivers/phy/mediatek/phy-mtk-xsphy.c
@@ -378,7 +378,7 @@ static int mtk_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
}
static struct phy *mtk_phy_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct mtk_xsphy *xsphy = dev_get_drvdata(dev);
struct xsphy_instance *inst = NULL;
@@ -432,12 +432,11 @@ static int mtk_xsphy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
- struct device_node *child_np;
struct phy_provider *provider;
struct resource *glb_res;
struct mtk_xsphy *xsphy;
struct resource res;
- int port, retval;
+ int port;
xsphy = devm_kzalloc(dev, sizeof(*xsphy), GFP_KERNEL);
if (!xsphy)
@@ -471,37 +470,34 @@ static int mtk_xsphy_probe(struct platform_device *pdev)
device_property_read_u32(dev, "mediatek,src-coef", &xsphy->src_coef);
port = 0;
- for_each_child_of_node(np, child_np) {
+ for_each_child_of_node_scoped(np, child_np) {
struct xsphy_instance *inst;
struct phy *phy;
+ int retval;
inst = devm_kzalloc(dev, sizeof(*inst), GFP_KERNEL);
- if (!inst) {
- retval = -ENOMEM;
- goto put_child;
- }
+ if (!inst)
+ return -ENOMEM;
xsphy->phys[port] = inst;
phy = devm_phy_create(dev, child_np, &mtk_xsphy_ops);
if (IS_ERR(phy)) {
dev_err(dev, "failed to create phy\n");
- retval = PTR_ERR(phy);
- goto put_child;
+ return PTR_ERR(phy);
}
retval = of_address_to_resource(child_np, 0, &res);
if (retval) {
dev_err(dev, "failed to get address resource(id-%d)\n",
port);
- goto put_child;
+ return retval;
}
inst->port_base = devm_ioremap_resource(&phy->dev, &res);
if (IS_ERR(inst->port_base)) {
dev_err(dev, "failed to remap phy regs\n");
- retval = PTR_ERR(inst->port_base);
- goto put_child;
+ return PTR_ERR(inst->port_base);
}
inst->phy = phy;
@@ -512,17 +508,12 @@ static int mtk_xsphy_probe(struct platform_device *pdev)
inst->ref_clk = devm_clk_get(&phy->dev, "ref");
if (IS_ERR(inst->ref_clk)) {
dev_err(dev, "failed to get ref_clk(id-%d)\n", port);
- retval = PTR_ERR(inst->ref_clk);
- goto put_child;
+ return PTR_ERR(inst->ref_clk);
}
}
provider = devm_of_phy_provider_register(dev, mtk_phy_xlate);
return PTR_ERR_OR_ZERO(provider);
-
-put_child:
- of_node_put(child_np);
- return retval;
}
static struct platform_driver mtk_xsphy_driver = {
diff --git a/drivers/phy/microchip/lan966x_serdes.c b/drivers/phy/microchip/lan966x_serdes.c
index b5ac2b7995e7..835e369cdfc5 100644
--- a/drivers/phy/microchip/lan966x_serdes.c
+++ b/drivers/phy/microchip/lan966x_serdes.c
@@ -518,7 +518,7 @@ static const struct phy_ops serdes_ops = {
};
static struct phy *serdes_simple_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct serdes_ctrl *ctrl = dev_get_drvdata(dev);
unsigned int port, idx, i;
diff --git a/drivers/phy/microchip/sparx5_serdes.c b/drivers/phy/microchip/sparx5_serdes.c
index 01bd5ea620c5..320cf5b50a8c 100644
--- a/drivers/phy/microchip/sparx5_serdes.c
+++ b/drivers/phy/microchip/sparx5_serdes.c
@@ -21,23 +21,33 @@
#include "sparx5_serdes.h"
-#define SPX5_CMU_MAX 14
-
#define SPX5_SERDES_10G_START 13
#define SPX5_SERDES_25G_START 25
#define SPX5_SERDES_6G10G_CNT SPX5_SERDES_25G_START
+#define LAN969X_SERDES_10G_CNT 10
+
/* Optimal power settings from GUC */
#define SPX5_SERDES_QUIET_MODE_VAL 0x01ef4e0c
-enum sparx5_10g28cmu_mode {
- SPX5_SD10G28_CMU_MAIN = 0,
- SPX5_SD10G28_CMU_AUX1 = 1,
- SPX5_SD10G28_CMU_AUX2 = 3,
- SPX5_SD10G28_CMU_NONE = 4,
- SPX5_SD10G28_CMU_MAX,
+/* Register target sizes */
+const unsigned int sparx5_serdes_tsize[TSIZE_LAST] = {
+ [TC_SD10G_LANE] = 12,
+ [TC_SD_CMU] = 14,
+ [TC_SD_CMU_CFG] = 14,
+ [TC_SD_LANE] = 25,
+};
+
+const unsigned int lan969x_serdes_tsize[TSIZE_LAST] = {
+ [TC_SD10G_LANE] = 10,
+ [TC_SD_CMU] = 6,
+ [TC_SD_CMU_CFG] = 6,
+ [TC_SD_LANE] = 10,
};
+/* Pointer to the register target size table */
+const unsigned int *tsize;
+
enum sparx5_sd25g28_mode_preset_type {
SPX5_SD25G28_MODE_PRESET_25000,
SPX5_SD25G28_MODE_PRESET_10000,
@@ -1095,13 +1105,31 @@ static int sparx5_serdes_cmu_get(enum sparx5_10g28cmu_mode mode, int sd_index)
return sparx5_serdes_cmu_map[mode][sd_index];
}
+/* Map of 6G/10G serdes mode and index to CMU index. */
+static const int
+lan969x_serdes_cmu_map[SPX5_SD10G28_CMU_MAX][LAN969X_SERDES_10G_CNT] = {
+ [SPX5_SD10G28_CMU_MAIN] = { 2, 2, 2, 2, 2,
+ 2, 2, 2, 5, 5 },
+ [SPX5_SD10G28_CMU_AUX1] = { 0, 0, 3, 3, 3,
+ 3, 3, 3, 3, 3 },
+ [SPX5_SD10G28_CMU_AUX2] = { 1, 1, 1, 1, 4,
+ 4, 4, 4, 4, 4 },
+ [SPX5_SD10G28_CMU_NONE] = { 1, 1, 1, 1, 4,
+ 4, 4, 4, 4, 4 },
+};
+
+static int lan969x_serdes_cmu_get(enum sparx5_10g28cmu_mode mode, int sd_index)
+{
+ return lan969x_serdes_cmu_map[mode][sd_index];
+}
+
static void sparx5_serdes_cmu_power_off(struct sparx5_serdes_private *priv)
{
void __iomem *cmu_inst, *cmu_cfg_inst;
int i;
/* Power down each CMU */
- for (i = 0; i < SPX5_CMU_MAX; i++) {
+ for (i = 0; i < priv->data->consts.cmu_max; i++) {
cmu_inst = sdx5_inst_get(priv, TARGET_SD_CMU, i);
cmu_cfg_inst = sdx5_inst_get(priv, TARGET_SD_CMU_CFG, i);
@@ -1650,7 +1678,7 @@ static int sparx5_sd10g28_apply_params(struct sparx5_serdes_macro *macro,
if (params->skip_cmu_cfg)
return 0;
- cmu_idx = sparx5_serdes_cmu_get(params->cmu_sel, lane_index);
+ cmu_idx = priv->data->ops.serdes_cmu_get(params->cmu_sel, macro->sidx);
err = sparx5_cmu_cfg(priv, cmu_idx);
if (err)
return err;
@@ -2183,6 +2211,10 @@ static int sparx5_serdes_clock_config(struct sparx5_serdes_macro *macro)
{
struct sparx5_serdes_private *priv = macro->priv;
+ /* Clock is auto-detected in 100Base-FX mode on lan969x */
+ if (priv->data->type == SPX5_TARGET_LAN969X)
+ return 0;
+
if (macro->serdesmode == SPX5_SD_MODE_100FX) {
u32 freq = priv->coreclock == 250000000 ? 2 :
priv->coreclock == 500000000 ? 1 : 0;
@@ -2297,10 +2329,12 @@ static int sparx5_serdes_set_speed(struct phy *phy, int speed)
{
struct sparx5_serdes_macro *macro = phy_get_drvdata(phy);
- if (macro->sidx < SPX5_SERDES_10G_START && speed > SPEED_5000)
- return -EINVAL;
- if (macro->sidx < SPX5_SERDES_25G_START && speed > SPEED_10000)
- return -EINVAL;
+ if (macro->priv->data->type == SPX5_TARGET_SPARX5) {
+ if (macro->sidx < SPX5_SERDES_10G_START && speed > SPEED_5000)
+ return -EINVAL;
+ if (macro->sidx < SPX5_SERDES_25G_START && speed > SPEED_10000)
+ return -EINVAL;
+ }
if (speed != macro->speed) {
macro->speed = speed;
if (macro->serdesmode != SPX5_SD_MODE_NONE)
@@ -2337,11 +2371,14 @@ static int sparx5_serdes_validate(struct phy *phy, enum phy_mode mode,
if (macro->speed == 0)
return -EINVAL;
- if (macro->sidx < SPX5_SERDES_10G_START && macro->speed > SPEED_5000)
- return -EINVAL;
- if (macro->sidx < SPX5_SERDES_25G_START && macro->speed > SPEED_10000)
- return -EINVAL;
-
+ if (macro->priv->data->type == SPX5_TARGET_SPARX5) {
+ if (macro->sidx < SPX5_SERDES_10G_START &&
+ macro->speed > SPEED_5000)
+ return -EINVAL;
+ if (macro->sidx < SPX5_SERDES_25G_START &&
+ macro->speed > SPEED_10000)
+ return -EINVAL;
+ }
switch (submode) {
case PHY_INTERFACE_MODE_1000BASEX:
if (macro->speed != SPEED_100 && /* This is for 100BASE-FX */
@@ -2375,6 +2412,26 @@ static const struct phy_ops sparx5_serdes_ops = {
.owner = THIS_MODULE,
};
+static void sparx5_serdes_type_set(struct sparx5_serdes_macro *macro, int sidx)
+{
+ if (sidx < SPX5_SERDES_10G_START) {
+ macro->serdestype = SPX5_SDT_6G;
+ macro->stpidx = macro->sidx;
+ } else if (sidx < SPX5_SERDES_25G_START) {
+ macro->serdestype = SPX5_SDT_10G;
+ macro->stpidx = macro->sidx - SPX5_SERDES_10G_START;
+ } else {
+ macro->serdestype = SPX5_SDT_25G;
+ macro->stpidx = macro->sidx - SPX5_SERDES_25G_START;
+ }
+}
+
+static void lan969x_serdes_type_set(struct sparx5_serdes_macro *macro, int sidx)
+{
+ macro->serdestype = SPX5_SDT_10G;
+ macro->stpidx = macro->sidx;
+}
+
static int sparx5_phy_create(struct sparx5_serdes_private *priv,
int idx, struct phy **phy)
{
@@ -2391,16 +2448,8 @@ static int sparx5_phy_create(struct sparx5_serdes_private *priv,
macro->sidx = idx;
macro->priv = priv;
macro->speed = SPEED_UNKNOWN;
- if (idx < SPX5_SERDES_10G_START) {
- macro->serdestype = SPX5_SDT_6G;
- macro->stpidx = macro->sidx;
- } else if (idx < SPX5_SERDES_25G_START) {
- macro->serdestype = SPX5_SDT_10G;
- macro->stpidx = macro->sidx - SPX5_SERDES_10G_START;
- } else {
- macro->serdestype = SPX5_SDT_25G;
- macro->stpidx = macro->sidx - SPX5_SERDES_25G_START;
- }
+
+ priv->data->ops.serdes_type_set(macro, idx);
phy_set_drvdata(*phy, macro);
@@ -2507,9 +2556,74 @@ static struct sparx5_serdes_io_resource sparx5_serdes_iomap[] = {
{ TARGET_SD_LANE_25G + 7, 0x5c8000 }, /* 0x610dd0000: sd_lane_25g_32 */
};
+static const struct sparx5_serdes_io_resource lan969x_serdes_iomap[] = {
+ { TARGET_SD_CMU, 0x0 }, /* 0xe3410000 */
+ { TARGET_SD_CMU + 1, 0x8000 }, /* 0xe3418000 */
+ { TARGET_SD_CMU + 2, 0x10000 }, /* 0xe3420000 */
+ { TARGET_SD_CMU + 3, 0x18000 }, /* 0xe3428000 */
+ { TARGET_SD_CMU + 4, 0x20000 }, /* 0xe3430000 */
+ { TARGET_SD_CMU + 5, 0x28000 }, /* 0xe3438000 */
+ { TARGET_SD_CMU_CFG, 0x30000 }, /* 0xe3440000 */
+ { TARGET_SD_CMU_CFG + 1, 0x38000 }, /* 0xe3448000 */
+ { TARGET_SD_CMU_CFG + 2, 0x40000 }, /* 0xe3450000 */
+ { TARGET_SD_CMU_CFG + 3, 0x48000 }, /* 0xe3458000 */
+ { TARGET_SD_CMU_CFG + 4, 0x50000 }, /* 0xe3460000 */
+ { TARGET_SD_CMU_CFG + 5, 0x58000 }, /* 0xe3468000 */
+ { TARGET_SD10G_LANE, 0x60000 }, /* 0xe3470000 */
+ { TARGET_SD10G_LANE + 1, 0x68000 }, /* 0xe3478000 */
+ { TARGET_SD10G_LANE + 2, 0x70000 }, /* 0xe3480000 */
+ { TARGET_SD10G_LANE + 3, 0x78000 }, /* 0xe3488000 */
+ { TARGET_SD10G_LANE + 4, 0x80000 }, /* 0xe3490000 */
+ { TARGET_SD10G_LANE + 5, 0x88000 }, /* 0xe3498000 */
+ { TARGET_SD10G_LANE + 6, 0x90000 }, /* 0xe34a0000 */
+ { TARGET_SD10G_LANE + 7, 0x98000 }, /* 0xe34a8000 */
+ { TARGET_SD10G_LANE + 8, 0xa0000 }, /* 0xe34b0000 */
+ { TARGET_SD10G_LANE + 9, 0xa8000 }, /* 0xe34b8000 */
+ { TARGET_SD_LANE, 0x100000 }, /* 0xe3510000 */
+ { TARGET_SD_LANE + 1, 0x108000 }, /* 0xe3518000 */
+ { TARGET_SD_LANE + 2, 0x110000 }, /* 0xe3520000 */
+ { TARGET_SD_LANE + 3, 0x118000 }, /* 0xe3528000 */
+ { TARGET_SD_LANE + 4, 0x120000 }, /* 0xe3530000 */
+ { TARGET_SD_LANE + 5, 0x128000 }, /* 0xe3538000 */
+ { TARGET_SD_LANE + 6, 0x130000 }, /* 0xe3540000 */
+ { TARGET_SD_LANE + 7, 0x138000 }, /* 0xe3548000 */
+ { TARGET_SD_LANE + 8, 0x140000 }, /* 0xe3550000 */
+ { TARGET_SD_LANE + 9, 0x148000 }, /* 0xe3558000 */
+};
+
+static const struct sparx5_serdes_match_data sparx5_desc = {
+ .type = SPX5_TARGET_SPARX5,
+ .iomap = sparx5_serdes_iomap,
+ .iomap_size = ARRAY_SIZE(sparx5_serdes_iomap),
+ .tsize = sparx5_serdes_tsize,
+ .consts = {
+ .sd_max = 33,
+ .cmu_max = 14,
+ },
+ .ops = {
+ .serdes_type_set = &sparx5_serdes_type_set,
+ .serdes_cmu_get = &sparx5_serdes_cmu_get,
+ },
+};
+
+static const struct sparx5_serdes_match_data lan969x_desc = {
+ .type = SPX5_TARGET_LAN969X,
+ .iomap = lan969x_serdes_iomap,
+ .iomap_size = ARRAY_SIZE(lan969x_serdes_iomap),
+ .tsize = lan969x_serdes_tsize,
+ .consts = {
+ .sd_max = 10,
+ .cmu_max = 6,
+ },
+ .ops = {
+ .serdes_type_set = &lan969x_serdes_type_set,
+ .serdes_cmu_get = &lan969x_serdes_cmu_get,
+ }
+};
+
/* Client lookup function, uses serdes index */
static struct phy *sparx5_serdes_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct sparx5_serdes_private *priv = dev_get_drvdata(dev);
int idx;
@@ -2521,7 +2635,7 @@ static struct phy *sparx5_serdes_xlate(struct device *dev,
sidx = args->args[0];
/* Check validity: ERR_PTR(-ENODEV) if not valid */
- for (idx = 0; idx < SPX5_SERDES_MAX; idx++) {
+ for (idx = 0; idx < priv->data->consts.sd_max; idx++) {
struct sparx5_serdes_macro *macro =
phy_get_drvdata(priv->phys[idx]);
@@ -2555,6 +2669,12 @@ static int sparx5_serdes_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, priv);
priv->dev = &pdev->dev;
+ priv->data = device_get_match_data(priv->dev);
+ if (!priv->data)
+ return -EINVAL;
+
+ tsize = priv->data->tsize;
+
/* Get coreclock */
clk = devm_clk_get(priv->dev, NULL);
if (IS_ERR(clk)) {
@@ -2579,19 +2699,21 @@ static int sparx5_serdes_probe(struct platform_device *pdev)
iores->name);
return -ENOMEM;
}
- for (idx = 0; idx < ARRAY_SIZE(sparx5_serdes_iomap); idx++) {
- struct sparx5_serdes_io_resource *iomap = &sparx5_serdes_iomap[idx];
+ for (idx = 0; idx < priv->data->iomap_size; idx++) {
+ const struct sparx5_serdes_io_resource *iomap =
+ &priv->data->iomap[idx];
priv->regs[iomap->id] = iomem + iomap->offset;
}
- for (idx = 0; idx < SPX5_SERDES_MAX; idx++) {
+ for (idx = 0; idx < priv->data->consts.sd_max; idx++) {
err = sparx5_phy_create(priv, idx, &priv->phys[idx]);
if (err)
return err;
}
- /* Power down all CMUs by default */
- sparx5_serdes_cmu_power_off(priv);
+ /* Power down all CMU's by default */
+ if (priv->data->type == SPX5_TARGET_SPARX5)
+ sparx5_serdes_cmu_power_off(priv);
provider = devm_of_phy_provider_register(priv->dev, sparx5_serdes_xlate);
@@ -2599,7 +2721,8 @@ static int sparx5_serdes_probe(struct platform_device *pdev)
}
static const struct of_device_id sparx5_serdes_match[] = {
- { .compatible = "microchip,sparx5-serdes" },
+ { .compatible = "microchip,sparx5-serdes", .data = &sparx5_desc },
+ { .compatible = "microchip,lan9691-serdes", .data = &lan969x_desc },
{ }
};
MODULE_DEVICE_TABLE(of, sparx5_serdes_match);
diff --git a/drivers/phy/microchip/sparx5_serdes.h b/drivers/phy/microchip/sparx5_serdes.h
index 13f94a29225a..d7093d0b09c0 100644
--- a/drivers/phy/microchip/sparx5_serdes.h
+++ b/drivers/phy/microchip/sparx5_serdes.h
@@ -26,11 +26,18 @@ enum sparx5_serdes_mode {
SPX5_SD_MODE_SFI,
};
-struct sparx5_serdes_private {
- struct device *dev;
- void __iomem *regs[NUM_TARGETS];
- struct phy *phys[SPX5_SERDES_MAX];
- unsigned long coreclock;
+enum sparx5_10g28cmu_mode {
+ SPX5_SD10G28_CMU_MAIN = 0,
+ SPX5_SD10G28_CMU_AUX1 = 1,
+ SPX5_SD10G28_CMU_AUX2 = 3,
+ SPX5_SD10G28_CMU_NONE = 4,
+ SPX5_SD10G28_CMU_MAX,
+};
+
+enum sparx5_target {
+ SPX5_TARGET_SPARX5,
+ SPX5_TARGET_LAN969X,
+
};
struct sparx5_serdes_macro {
@@ -44,6 +51,33 @@ struct sparx5_serdes_macro {
enum phy_media media;
};
+struct sparx5_serdes_consts {
+ int sd_max;
+ int cmu_max;
+};
+
+struct sparx5_serdes_ops {
+ void (*serdes_type_set)(struct sparx5_serdes_macro *macro, int sidx);
+ int (*serdes_cmu_get)(enum sparx5_10g28cmu_mode mode, int sd_index);
+};
+
+struct sparx5_serdes_match_data {
+ enum sparx5_target type;
+ const struct sparx5_serdes_consts consts;
+ const struct sparx5_serdes_ops ops;
+ const struct sparx5_serdes_io_resource *iomap;
+ int iomap_size;
+ const unsigned int *tsize;
+};
+
+struct sparx5_serdes_private {
+ struct device *dev;
+ void __iomem *regs[NUM_TARGETS];
+ struct phy *phys[SPX5_SERDES_MAX];
+ unsigned long coreclock;
+ const struct sparx5_serdes_match_data *data;
+};
+
/* Read, Write and modify registers content.
* The register definition macros start at the id
*/
diff --git a/drivers/phy/microchip/sparx5_serdes_regs.h b/drivers/phy/microchip/sparx5_serdes_regs.h
index d0543fd3dc94..11c4fdc593fa 100644
--- a/drivers/phy/microchip/sparx5_serdes_regs.h
+++ b/drivers/phy/microchip/sparx5_serdes_regs.h
@@ -1,11 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0+
* Microchip Sparx5 SerDes driver
*
- * Copyright (c) 2020 Microchip Technology Inc.
+ * Copyright (c) 2024 Microchip Technology Inc.
*/
-/* This file is autogenerated by cml-utils 2020-11-16 13:11:27 +0100.
- * Commit ID: 13bdf073131d8bf40c54901df6988ae4e9c8f29f
+/* This file is autogenerated by cml-utils 2023-04-13 15:02:00 +0200.
+ * Commit ID: 5ac560288d46048f872ecdb8add53717f1efc0e1
*/
#ifndef _SPARX5_SERDES_REGS_H_
@@ -26,10 +26,25 @@ enum sparx5_serdes_target {
NUM_TARGETS = 332
};
+enum sparx5_serdes_tsize_enum {
+ TC_SD10G_LANE,
+ TC_SD_CMU,
+ TC_SD_CMU_CFG,
+ TC_SD_LANE,
+ TSIZE_LAST,
+};
+
+/* sparx5_serdes.c */
+extern const unsigned int *tsize;
+
+#define TSIZE(o) tsize[o]
+
#define __REG(...) __VA_ARGS__
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_01 */
-#define SD10G_LANE_LANE_01(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 4, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_01 */
+#define SD10G_LANE_LANE_01(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 4, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_01_CFG_PMA_TX_CK_BITWIDTH_2_0 GENMASK(2, 0)
#define SD10G_LANE_LANE_01_CFG_PMA_TX_CK_BITWIDTH_2_0_SET(x)\
@@ -49,8 +64,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_01_CFG_RXDET_STR_GET(x)\
FIELD_GET(SD10G_LANE_LANE_01_CFG_RXDET_STR, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_02 */
-#define SD10G_LANE_LANE_02(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 8, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_02 */
+#define SD10G_LANE_LANE_02(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 8, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_02_CFG_EN_ADV BIT(0)
#define SD10G_LANE_LANE_02_CFG_EN_ADV_SET(x)\
@@ -82,8 +99,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_02_CFG_TAP_ADV_3_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_02_CFG_TAP_ADV_3_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_03 */
-#define SD10G_LANE_LANE_03(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 12, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_03 */
+#define SD10G_LANE_LANE_03(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 12, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_03_CFG_TAP_MAIN BIT(0)
#define SD10G_LANE_LANE_03_CFG_TAP_MAIN_SET(x)\
@@ -91,8 +110,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_03_CFG_TAP_MAIN_GET(x)\
FIELD_GET(SD10G_LANE_LANE_03_CFG_TAP_MAIN, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_04 */
-#define SD10G_LANE_LANE_04(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 16, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_04 */
+#define SD10G_LANE_LANE_04(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 16, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_04_CFG_TAP_DLY_4_0 GENMASK(4, 0)
#define SD10G_LANE_LANE_04_CFG_TAP_DLY_4_0_SET(x)\
@@ -100,8 +121,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_04_CFG_TAP_DLY_4_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_04_CFG_TAP_DLY_4_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_06 */
-#define SD10G_LANE_LANE_06(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 24, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_06 */
+#define SD10G_LANE_LANE_06(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 24, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_06_CFG_PD_DRIVER BIT(0)
#define SD10G_LANE_LANE_06_CFG_PD_DRIVER_SET(x)\
@@ -139,8 +162,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_06_CFG_EN_PREEMPH_GET(x)\
FIELD_GET(SD10G_LANE_LANE_06_CFG_EN_PREEMPH, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0B */
-#define SD10G_LANE_LANE_0B(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 44, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0B */
+#define SD10G_LANE_LANE_0B(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 44, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_0B_CFG_EQ_RES_3_0 GENMASK(3, 0)
#define SD10G_LANE_LANE_0B_CFG_EQ_RES_3_0_SET(x)\
@@ -172,8 +197,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_0B_CFG_RESETB_OSCAL_SQ_GET(x)\
FIELD_GET(SD10G_LANE_LANE_0B_CFG_RESETB_OSCAL_SQ, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0C */
-#define SD10G_LANE_LANE_0C(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 48, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0C */
+#define SD10G_LANE_LANE_0C(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 48, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_0C_CFG_OSCAL_AFE BIT(0)
#define SD10G_LANE_LANE_0C_CFG_OSCAL_AFE_SET(x)\
@@ -223,8 +250,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_0C_CFG_RX_PCIE_GEN12_GET(x)\
FIELD_GET(SD10G_LANE_LANE_0C_CFG_RX_PCIE_GEN12, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0D */
-#define SD10G_LANE_LANE_0D(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 52, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0D */
+#define SD10G_LANE_LANE_0D(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 52, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_0D_CFG_CTLE_M_THR_1_0 GENMASK(1, 0)
#define SD10G_LANE_LANE_0D_CFG_CTLE_M_THR_1_0_SET(x)\
@@ -238,8 +267,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_0D_CFG_EQR_BYP_GET(x)\
FIELD_GET(SD10G_LANE_LANE_0D_CFG_EQR_BYP, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0E */
-#define SD10G_LANE_LANE_0E(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 56, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0E */
+#define SD10G_LANE_LANE_0E(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 56, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_0E_CFG_EQC_FORCE_3_0 GENMASK(3, 0)
#define SD10G_LANE_LANE_0E_CFG_EQC_FORCE_3_0_SET(x)\
@@ -265,8 +296,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_0E_CFG_SUM_SETCM_EN_GET(x)\
FIELD_GET(SD10G_LANE_LANE_0E_CFG_SUM_SETCM_EN, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0F */
-#define SD10G_LANE_LANE_0F(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 60, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_0F */
+#define SD10G_LANE_LANE_0F(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 60, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_0F_R_CDR_M_GEN1_7_0 GENMASK(7, 0)
#define SD10G_LANE_LANE_0F_R_CDR_M_GEN1_7_0_SET(x)\
@@ -274,8 +307,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_0F_R_CDR_M_GEN1_7_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_0F_R_CDR_M_GEN1_7_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_13 */
-#define SD10G_LANE_LANE_13(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 76, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_13 */
+#define SD10G_LANE_LANE_13(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 76, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_13_CFG_DCDR_PD BIT(0)
#define SD10G_LANE_LANE_13_CFG_DCDR_PD_SET(x)\
@@ -295,8 +330,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_13_CFG_CDRCK_EN_GET(x)\
FIELD_GET(SD10G_LANE_LANE_13_CFG_CDRCK_EN, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_14 */
-#define SD10G_LANE_LANE_14(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 80, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_14 */
+#define SD10G_LANE_LANE_14(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 80, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_14_CFG_PI_EXT_DAC_7_0 GENMASK(7, 0)
#define SD10G_LANE_LANE_14_CFG_PI_EXT_DAC_7_0_SET(x)\
@@ -304,8 +341,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_14_CFG_PI_EXT_DAC_7_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_14_CFG_PI_EXT_DAC_7_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_15 */
-#define SD10G_LANE_LANE_15(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 84, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_15 */
+#define SD10G_LANE_LANE_15(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 84, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_15_CFG_PI_EXT_DAC_15_8 GENMASK(7, 0)
#define SD10G_LANE_LANE_15_CFG_PI_EXT_DAC_15_8_SET(x)\
@@ -313,8 +352,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_15_CFG_PI_EXT_DAC_15_8_GET(x)\
FIELD_GET(SD10G_LANE_LANE_15_CFG_PI_EXT_DAC_15_8, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_16 */
-#define SD10G_LANE_LANE_16(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 88, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_16 */
+#define SD10G_LANE_LANE_16(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 88, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_16_CFG_PI_EXT_DAC_23_16 GENMASK(7, 0)
#define SD10G_LANE_LANE_16_CFG_PI_EXT_DAC_23_16_SET(x)\
@@ -322,8 +363,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_16_CFG_PI_EXT_DAC_23_16_GET(x)\
FIELD_GET(SD10G_LANE_LANE_16_CFG_PI_EXT_DAC_23_16, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_1A */
-#define SD10G_LANE_LANE_1A(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 104, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_1A */
+#define SD10G_LANE_LANE_1A(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 104, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_1A_CFG_PI_R_SCAN_EN BIT(0)
#define SD10G_LANE_LANE_1A_CFG_PI_R_SCAN_EN_SET(x)\
@@ -355,8 +398,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_1A_CFG_PI_FLOOP_STEPS_1_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_1A_CFG_PI_FLOOP_STEPS_1_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_22 */
-#define SD10G_LANE_LANE_22(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 136, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_22 */
+#define SD10G_LANE_LANE_22(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 136, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_22_CFG_DFETAP_EN_5_1 GENMASK(4, 0)
#define SD10G_LANE_LANE_22_CFG_DFETAP_EN_5_1_SET(x)\
@@ -364,8 +409,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_22_CFG_DFETAP_EN_5_1_GET(x)\
FIELD_GET(SD10G_LANE_LANE_22_CFG_DFETAP_EN_5_1, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_23 */
-#define SD10G_LANE_LANE_23(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 140, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_23 */
+#define SD10G_LANE_LANE_23(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 140, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_23_CFG_DFE_PD BIT(0)
#define SD10G_LANE_LANE_23_CFG_DFE_PD_SET(x)\
@@ -397,8 +444,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_23_CFG_DFEDIG_M_2_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_23_CFG_DFEDIG_M_2_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_24 */
-#define SD10G_LANE_LANE_24(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 144, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_24 */
+#define SD10G_LANE_LANE_24(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 144, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_24_CFG_PI_BW_GEN1_3_0 GENMASK(3, 0)
#define SD10G_LANE_LANE_24_CFG_PI_BW_GEN1_3_0_SET(x)\
@@ -412,8 +461,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_24_CFG_PI_BW_GEN2_3_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_24_CFG_PI_BW_GEN2_3_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_26 */
-#define SD10G_LANE_LANE_26(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 152, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_26 */
+#define SD10G_LANE_LANE_26(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 152, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_26_CFG_ISCAN_EXT_DAC_7_0 GENMASK(7, 0)
#define SD10G_LANE_LANE_26_CFG_ISCAN_EXT_DAC_7_0_SET(x)\
@@ -421,8 +472,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_26_CFG_ISCAN_EXT_DAC_7_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_26_CFG_ISCAN_EXT_DAC_7_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_2F */
-#define SD10G_LANE_LANE_2F(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 188, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_2F */
+#define SD10G_LANE_LANE_2F(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 188, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_2F_CFG_VGA_CP_2_0 GENMASK(2, 0)
#define SD10G_LANE_LANE_2F_CFG_VGA_CP_2_0_SET(x)\
@@ -436,8 +489,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_2F_CFG_VGA_CTRL_3_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_2F_CFG_VGA_CTRL_3_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_30 */
-#define SD10G_LANE_LANE_30(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 192, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_30 */
+#define SD10G_LANE_LANE_30(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 192, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_30_CFG_SUMMER_EN BIT(0)
#define SD10G_LANE_LANE_30_CFG_SUMMER_EN_SET(x)\
@@ -451,8 +506,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_30_CFG_RXDIV_SEL_2_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_30_CFG_RXDIV_SEL_2_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_31 */
-#define SD10G_LANE_LANE_31(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 196, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_31 */
+#define SD10G_LANE_LANE_31(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 196, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_31_CFG_PI_RSTN BIT(0)
#define SD10G_LANE_LANE_31_CFG_PI_RSTN_SET(x)\
@@ -490,8 +547,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_31_CFG_R50_EN_GET(x)\
FIELD_GET(SD10G_LANE_LANE_31_CFG_R50_EN, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_32 */
-#define SD10G_LANE_LANE_32(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 200, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_32 */
+#define SD10G_LANE_LANE_32(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 200, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_32_CFG_ITX_IPCLK_BASE_1_0 GENMASK(1, 0)
#define SD10G_LANE_LANE_32_CFG_ITX_IPCLK_BASE_1_0_SET(x)\
@@ -505,8 +564,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_32_CFG_ITX_IPCML_BASE_1_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_32_CFG_ITX_IPCML_BASE_1_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_33 */
-#define SD10G_LANE_LANE_33(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 204, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_33 */
+#define SD10G_LANE_LANE_33(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 204, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_33_CFG_ITX_IPDRIVER_BASE_2_0 GENMASK(2, 0)
#define SD10G_LANE_LANE_33_CFG_ITX_IPDRIVER_BASE_2_0_SET(x)\
@@ -520,8 +581,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_33_CFG_ITX_IPPREEMP_BASE_1_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_33_CFG_ITX_IPPREEMP_BASE_1_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_35 */
-#define SD10G_LANE_LANE_35(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 212, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_35 */
+#define SD10G_LANE_LANE_35(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 212, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_35_CFG_TXRATE_1_0 GENMASK(1, 0)
#define SD10G_LANE_LANE_35_CFG_TXRATE_1_0_SET(x)\
@@ -535,8 +598,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_35_CFG_RXRATE_1_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_35_CFG_RXRATE_1_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_36 */
-#define SD10G_LANE_LANE_36(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 216, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_36 */
+#define SD10G_LANE_LANE_36(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 216, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_36_CFG_PREDRV_SLEWRATE_1_0 GENMASK(1, 0)
#define SD10G_LANE_LANE_36_CFG_PREDRV_SLEWRATE_1_0_SET(x)\
@@ -568,8 +633,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_36_CFG_PRBS_SETB_GET(x)\
FIELD_GET(SD10G_LANE_LANE_36_CFG_PRBS_SETB, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_37 */
-#define SD10G_LANE_LANE_37(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 220, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_37 */
+#define SD10G_LANE_LANE_37(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 220, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_37_CFG_RXDET_COMP_PD BIT(0)
#define SD10G_LANE_LANE_37_CFG_RXDET_COMP_PD_SET(x)\
@@ -595,8 +662,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_37_CFG_IP_PRE_BASE_1_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_37_CFG_IP_PRE_BASE_1_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_39 */
-#define SD10G_LANE_LANE_39(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 228, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_39 */
+#define SD10G_LANE_LANE_39(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 228, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_39_CFG_RXFILT_Y_2_0 GENMASK(2, 0)
#define SD10G_LANE_LANE_39_CFG_RXFILT_Y_2_0_SET(x)\
@@ -610,8 +679,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_39_CFG_RX_SSC_LH_GET(x)\
FIELD_GET(SD10G_LANE_LANE_39_CFG_RX_SSC_LH, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_3A */
-#define SD10G_LANE_LANE_3A(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 232, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_3A */
+#define SD10G_LANE_LANE_3A(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 232, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_3A_CFG_MP_MIN_3_0 GENMASK(3, 0)
#define SD10G_LANE_LANE_3A_CFG_MP_MIN_3_0_SET(x)\
@@ -625,8 +696,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_3A_CFG_MP_MAX_3_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_3A_CFG_MP_MAX_3_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_3C */
-#define SD10G_LANE_LANE_3C(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 240, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_3C */
+#define SD10G_LANE_LANE_3C(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 240, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_3C_CFG_DIS_ACC BIT(0)
#define SD10G_LANE_LANE_3C_CFG_DIS_ACC_SET(x)\
@@ -640,8 +713,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_3C_CFG_DIS_2NDORDER_GET(x)\
FIELD_GET(SD10G_LANE_LANE_3C_CFG_DIS_2NDORDER, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_40 */
-#define SD10G_LANE_LANE_40(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 256, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_40 */
+#define SD10G_LANE_LANE_40(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 256, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_40_CFG_LANE_RESERVE_7_0 GENMASK(7, 0)
#define SD10G_LANE_LANE_40_CFG_LANE_RESERVE_7_0_SET(x)\
@@ -649,8 +724,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_40_CFG_LANE_RESERVE_7_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_40_CFG_LANE_RESERVE_7_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_41 */
-#define SD10G_LANE_LANE_41(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 260, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_41 */
+#define SD10G_LANE_LANE_41(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 260, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_41_CFG_LANE_RESERVE_15_8 GENMASK(7, 0)
#define SD10G_LANE_LANE_41_CFG_LANE_RESERVE_15_8_SET(x)\
@@ -658,8 +735,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_41_CFG_LANE_RESERVE_15_8_GET(x)\
FIELD_GET(SD10G_LANE_LANE_41_CFG_LANE_RESERVE_15_8, x)
-/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_42 */
-#define SD10G_LANE_LANE_42(t) __REG(TARGET_SD10G_LANE, t, 12, 0, 0, 1, 288, 264, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_0:LANE_42 */
+#define SD10G_LANE_LANE_42(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 0, 0, 1, 288, 264, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_42_CFG_CDR_KF_GEN1_2_0 GENMASK(2, 0)
#define SD10G_LANE_LANE_42_CFG_CDR_KF_GEN1_2_0_SET(x)\
@@ -673,8 +752,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_42_CFG_CDR_KF_GEN2_2_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_42_CFG_CDR_KF_GEN2_2_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_1:LANE_48 */
-#define SD10G_LANE_LANE_48(t) __REG(TARGET_SD10G_LANE, t, 12, 288, 0, 1, 40, 0, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_1:LANE_48 */
+#define SD10G_LANE_LANE_48(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 288, 0, 1, 40, 0, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_48_CFG_ALOS_THR_3_0 GENMASK(3, 0)
#define SD10G_LANE_LANE_48_CFG_ALOS_THR_3_0_SET(x)\
@@ -694,8 +775,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_48_CFG_CLK_ENQ_GET(x)\
FIELD_GET(SD10G_LANE_LANE_48_CFG_CLK_ENQ, x)
-/* SD10G_LANE_TARGET:LANE_GRP_1:LANE_50 */
-#define SD10G_LANE_LANE_50(t) __REG(TARGET_SD10G_LANE, t, 12, 288, 0, 1, 40, 32, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_1:LANE_50 */
+#define SD10G_LANE_LANE_50(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 288, 0, 1, 40, 32, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_50_CFG_SSC_PI_STEP_1_0 GENMASK(1, 0)
#define SD10G_LANE_LANE_50_CFG_SSC_PI_STEP_1_0_SET(x)\
@@ -727,8 +810,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_50_CFG_JT_EN_GET(x)\
FIELD_GET(SD10G_LANE_LANE_50_CFG_JT_EN, x)
-/* SD10G_LANE_TARGET:LANE_GRP_2:LANE_52 */
-#define SD10G_LANE_LANE_52(t) __REG(TARGET_SD10G_LANE, t, 12, 328, 0, 1, 24, 0, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_2:LANE_52 */
+#define SD10G_LANE_LANE_52(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 328, 0, 1, 24, 0, 0, \
+ 1, 4)
#define SD10G_LANE_LANE_52_CFG_IBIAS_TUNE_RESERVE_5_0 GENMASK(5, 0)
#define SD10G_LANE_LANE_52_CFG_IBIAS_TUNE_RESERVE_5_0_SET(x)\
@@ -736,8 +821,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_52_CFG_IBIAS_TUNE_RESERVE_5_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_52_CFG_IBIAS_TUNE_RESERVE_5_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_4:LANE_83 */
-#define SD10G_LANE_LANE_83(t) __REG(TARGET_SD10G_LANE, t, 12, 464, 0, 1, 112, 60, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_4:LANE_83 */
+#define SD10G_LANE_LANE_83(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 464, 0, 1, 112, 60, \
+ 0, 1, 4)
#define SD10G_LANE_LANE_83_R_TX_BIT_REVERSE BIT(0)
#define SD10G_LANE_LANE_83_R_TX_BIT_REVERSE_SET(x)\
@@ -781,8 +868,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_83_R_CTLE_RSTN_GET(x)\
FIELD_GET(SD10G_LANE_LANE_83_R_CTLE_RSTN, x)
-/* SD10G_LANE_TARGET:LANE_GRP_5:LANE_93 */
-#define SD10G_LANE_LANE_93(t) __REG(TARGET_SD10G_LANE, t, 12, 576, 0, 1, 64, 12, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_5:LANE_93 */
+#define SD10G_LANE_LANE_93(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 576, 0, 1, 64, 12, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_93_R_RXEI_FIFO_RST_EN BIT(0)
#define SD10G_LANE_LANE_93_R_RXEI_FIFO_RST_EN_SET(x)\
@@ -832,8 +921,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_93_R_RX_PCIE_GEN12_FROM_HWT_GET(x)\
FIELD_GET(SD10G_LANE_LANE_93_R_RX_PCIE_GEN12_FROM_HWT, x)
-/* SD10G_LANE_TARGET:LANE_GRP_5:LANE_94 */
-#define SD10G_LANE_LANE_94(t) __REG(TARGET_SD10G_LANE, t, 12, 576, 0, 1, 64, 16, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_5:LANE_94 */
+#define SD10G_LANE_LANE_94(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 576, 0, 1, 64, 16, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_94_R_DWIDTHCTRL_2_0 GENMASK(2, 0)
#define SD10G_LANE_LANE_94_R_DWIDTHCTRL_2_0_SET(x)\
@@ -865,8 +956,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_94_R_SWING_REG_GET(x)\
FIELD_GET(SD10G_LANE_LANE_94_R_SWING_REG, x)
-/* SD10G_LANE_TARGET:LANE_GRP_5:LANE_9E */
-#define SD10G_LANE_LANE_9E(t) __REG(TARGET_SD10G_LANE, t, 12, 576, 0, 1, 64, 56, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_5:LANE_9E */
+#define SD10G_LANE_LANE_9E(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 576, 0, 1, 64, 56, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_9E_R_RXEQ_REG BIT(0)
#define SD10G_LANE_LANE_9E_R_RXEQ_REG_SET(x)\
@@ -886,8 +979,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_9E_R_EN_AUTO_CDR_RSTN_GET(x)\
FIELD_GET(SD10G_LANE_LANE_9E_R_EN_AUTO_CDR_RSTN, x)
-/* SD10G_LANE_TARGET:LANE_GRP_6:LANE_A1 */
-#define SD10G_LANE_LANE_A1(t) __REG(TARGET_SD10G_LANE, t, 12, 640, 0, 1, 128, 4, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_6:LANE_A1 */
+#define SD10G_LANE_LANE_A1(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 640, 0, 1, 128, 4, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_A1_R_PMA_TXCK_DIV_SEL_1_0 GENMASK(1, 0)
#define SD10G_LANE_LANE_A1_R_PMA_TXCK_DIV_SEL_1_0_SET(x)\
@@ -919,8 +1014,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_A1_R_PCLK_GATING_GET(x)\
FIELD_GET(SD10G_LANE_LANE_A1_R_PCLK_GATING, x)
-/* SD10G_LANE_TARGET:LANE_GRP_6:LANE_A2 */
-#define SD10G_LANE_LANE_A2(t) __REG(TARGET_SD10G_LANE, t, 12, 640, 0, 1, 128, 8, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_6:LANE_A2 */
+#define SD10G_LANE_LANE_A2(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 640, 0, 1, 128, 8, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_A2_R_PCS2PMA_PHYMODE_4_0 GENMASK(4, 0)
#define SD10G_LANE_LANE_A2_R_PCS2PMA_PHYMODE_4_0_SET(x)\
@@ -928,8 +1025,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_A2_R_PCS2PMA_PHYMODE_4_0_GET(x)\
FIELD_GET(SD10G_LANE_LANE_A2_R_PCS2PMA_PHYMODE_4_0, x)
-/* SD10G_LANE_TARGET:LANE_GRP_8:LANE_DF */
-#define SD10G_LANE_LANE_DF(t) __REG(TARGET_SD10G_LANE, t, 12, 832, 0, 1, 84, 60, 0, 1, 4)
+/* SD10G_LANE_TARGET:LANE_GRP_8:LANE_DF */
+#define SD10G_LANE_LANE_DF(t) \
+ __REG(TARGET_SD10G_LANE, t, TSIZE(TC_SD10G_LANE), 832, 0, 1, 84, 60, 0,\
+ 1, 4)
#define SD10G_LANE_LANE_DF_LOL_UDL BIT(0)
#define SD10G_LANE_LANE_DF_LOL_UDL_SET(x)\
@@ -955,8 +1054,10 @@ enum sparx5_serdes_target {
#define SD10G_LANE_LANE_DF_SQUELCH_GET(x)\
FIELD_GET(SD10G_LANE_LANE_DF_SQUELCH, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_09 */
-#define SD25G_LANE_CMU_09(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 36, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_09 */
+#define SD25G_LANE_CMU_09(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 36, 0, 1, 4)
#define SD25G_LANE_CMU_09_CFG_REFCK_TERM_EN BIT(0)
#define SD25G_LANE_CMU_09_CFG_REFCK_TERM_EN_SET(x)\
@@ -988,8 +1089,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_09_CFG_PLL_TP_SEL_1_0_GET(x)\
FIELD_GET(SD25G_LANE_CMU_09_CFG_PLL_TP_SEL_1_0, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_0B */
-#define SD25G_LANE_CMU_0B(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 44, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_0B */
+#define SD25G_LANE_CMU_0B(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 44, 0, 1, 4)
#define SD25G_LANE_CMU_0B_CFG_FORCE_RX_FILT BIT(0)
#define SD25G_LANE_CMU_0B_CFG_FORCE_RX_FILT_SET(x)\
@@ -1039,8 +1142,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_0B_CFG_RST_TREE_PD_MAN_GET(x)\
FIELD_GET(SD25G_LANE_CMU_0B_CFG_RST_TREE_PD_MAN, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_0C */
-#define SD25G_LANE_CMU_0C(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 48, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_0C */
+#define SD25G_LANE_CMU_0C(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 48, 0, 1, 4)
#define SD25G_LANE_CMU_0C_CFG_PLL_LOL_SET BIT(0)
#define SD25G_LANE_CMU_0C_CFG_PLL_LOL_SET_SET(x)\
@@ -1072,8 +1177,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_0C_CFG_VCO_DIV_MODE_1_0_GET(x)\
FIELD_GET(SD25G_LANE_CMU_0C_CFG_VCO_DIV_MODE_1_0, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_0D */
-#define SD25G_LANE_CMU_0D(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 52, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_0D */
+#define SD25G_LANE_CMU_0D(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 52, 0, 1, 4)
#define SD25G_LANE_CMU_0D_CFG_CK_TREE_PD BIT(0)
#define SD25G_LANE_CMU_0D_CFG_CK_TREE_PD_SET(x)\
@@ -1105,8 +1212,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_0D_CFG_PRE_DIVSEL_1_0_GET(x)\
FIELD_GET(SD25G_LANE_CMU_0D_CFG_PRE_DIVSEL_1_0, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_0E */
-#define SD25G_LANE_CMU_0E(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 56, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_0E */
+#define SD25G_LANE_CMU_0E(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 56, 0, 1, 4)
#define SD25G_LANE_CMU_0E_CFG_SEL_DIV_3_0 GENMASK(3, 0)
#define SD25G_LANE_CMU_0E_CFG_SEL_DIV_3_0_SET(x)\
@@ -1120,8 +1229,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_0E_CFG_PMAA_CENTR_CK_PD_GET(x)\
FIELD_GET(SD25G_LANE_CMU_0E_CFG_PMAA_CENTR_CK_PD, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_13 */
-#define SD25G_LANE_CMU_13(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 76, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_13 */
+#define SD25G_LANE_CMU_13(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 76, 0, 1, 4)
#define SD25G_LANE_CMU_13_CFG_PLL_RESERVE_3_0 GENMASK(3, 0)
#define SD25G_LANE_CMU_13_CFG_PLL_RESERVE_3_0_SET(x)\
@@ -1135,8 +1246,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_13_CFG_JT_EN_GET(x)\
FIELD_GET(SD25G_LANE_CMU_13_CFG_JT_EN, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_18 */
-#define SD25G_LANE_CMU_18(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 96, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_18 */
+#define SD25G_LANE_CMU_18(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 96, 0, 1, 4)
#define SD25G_LANE_CMU_18_R_PLL_RSTN BIT(0)
#define SD25G_LANE_CMU_18_R_PLL_RSTN_SET(x)\
@@ -1162,8 +1275,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_18_R_PLL_TP_SEL_1_0_GET(x)\
FIELD_GET(SD25G_LANE_CMU_18_R_PLL_TP_SEL_1_0, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_19 */
-#define SD25G_LANE_CMU_19(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 100, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_19 */
+#define SD25G_LANE_CMU_19(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 100, 0, 1, 4)
#define SD25G_LANE_CMU_19_R_CK_RESETB BIT(0)
#define SD25G_LANE_CMU_19_R_CK_RESETB_SET(x)\
@@ -1177,8 +1292,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_19_R_PLL_DLOL_EN_GET(x)\
FIELD_GET(SD25G_LANE_CMU_19_R_PLL_DLOL_EN, x)
-/* SD25G_TARGET:CMU_GRP_0:CMU_1A */
-#define SD25G_LANE_CMU_1A(t) __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 104, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_0:CMU_1A */
+#define SD25G_LANE_CMU_1A(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 0, 0, 1, 132, 104, 0, 1, 4)
#define SD25G_LANE_CMU_1A_R_DWIDTHCTRL_2_0 GENMASK(2, 0)
#define SD25G_LANE_CMU_1A_R_DWIDTHCTRL_2_0_SET(x)\
@@ -1204,8 +1321,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_1A_R_REG_MANUAL_GET(x)\
FIELD_GET(SD25G_LANE_CMU_1A_R_REG_MANUAL, x)
-/* SD25G_TARGET:CMU_GRP_1:CMU_2A */
-#define SD25G_LANE_CMU_2A(t) __REG(TARGET_SD25G_LANE, t, 8, 132, 0, 1, 124, 36, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_1:CMU_2A */
+#define SD25G_LANE_CMU_2A(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 132, 0, 1, 124, 36, 0, 1, 4)
#define SD25G_LANE_CMU_2A_R_DBG_SEL_1_0 GENMASK(1, 0)
#define SD25G_LANE_CMU_2A_R_DBG_SEL_1_0_SET(x)\
@@ -1225,8 +1344,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_2A_R_DBG_LOL_STATUS_GET(x)\
FIELD_GET(SD25G_LANE_CMU_2A_R_DBG_LOL_STATUS, x)
-/* SD25G_TARGET:CMU_GRP_1:CMU_30 */
-#define SD25G_LANE_CMU_30(t) __REG(TARGET_SD25G_LANE, t, 8, 132, 0, 1, 124, 60, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_1:CMU_30 */
+#define SD25G_LANE_CMU_30(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 132, 0, 1, 124, 60, 0, 1, 4)
#define SD25G_LANE_CMU_30_R_TXFIFO_CK_DIV_PMAD_2_0 GENMASK(2, 0)
#define SD25G_LANE_CMU_30_R_TXFIFO_CK_DIV_PMAD_2_0_SET(x)\
@@ -1240,8 +1361,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_30_R_RXFIFO_CK_DIV_PMAD_2_0_GET(x)\
FIELD_GET(SD25G_LANE_CMU_30_R_RXFIFO_CK_DIV_PMAD_2_0, x)
-/* SD25G_TARGET:CMU_GRP_1:CMU_31 */
-#define SD25G_LANE_CMU_31(t) __REG(TARGET_SD25G_LANE, t, 8, 132, 0, 1, 124, 64, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_1:CMU_31 */
+#define SD25G_LANE_CMU_31(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 132, 0, 1, 124, 64, 0, 1, 4)
#define SD25G_LANE_CMU_31_CFG_COMMON_RESERVE_7_0 GENMASK(7, 0)
#define SD25G_LANE_CMU_31_CFG_COMMON_RESERVE_7_0_SET(x)\
@@ -1249,8 +1372,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_31_CFG_COMMON_RESERVE_7_0_GET(x)\
FIELD_GET(SD25G_LANE_CMU_31_CFG_COMMON_RESERVE_7_0, x)
-/* SD25G_TARGET:CMU_GRP_2:CMU_40 */
-#define SD25G_LANE_CMU_40(t) __REG(TARGET_SD25G_LANE, t, 8, 256, 0, 1, 512, 0, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_2:CMU_40 */
+#define SD25G_LANE_CMU_40(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 256, 0, 1, 512, 0, 0, 1, 4)
#define SD25G_LANE_CMU_40_L0_CFG_CKSKEW_CTRL BIT(0)
#define SD25G_LANE_CMU_40_L0_CFG_CKSKEW_CTRL_SET(x)\
@@ -1288,8 +1413,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_40_L0_CFG_TXCAL_RST_GET(x)\
FIELD_GET(SD25G_LANE_CMU_40_L0_CFG_TXCAL_RST, x)
-/* SD25G_TARGET:CMU_GRP_2:CMU_45 */
-#define SD25G_LANE_CMU_45(t) __REG(TARGET_SD25G_LANE, t, 8, 256, 0, 1, 512, 20, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_2:CMU_45 */
+#define SD25G_LANE_CMU_45(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 256, 0, 1, 512, 20, 0, 1, 4)
#define SD25G_LANE_CMU_45_L0_CFG_TX_RESERVE_7_0 GENMASK(7, 0)
#define SD25G_LANE_CMU_45_L0_CFG_TX_RESERVE_7_0_SET(x)\
@@ -1297,8 +1424,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_45_L0_CFG_TX_RESERVE_7_0_GET(x)\
FIELD_GET(SD25G_LANE_CMU_45_L0_CFG_TX_RESERVE_7_0, x)
-/* SD25G_TARGET:CMU_GRP_2:CMU_46 */
-#define SD25G_LANE_CMU_46(t) __REG(TARGET_SD25G_LANE, t, 8, 256, 0, 1, 512, 24, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_2:CMU_46 */
+#define SD25G_LANE_CMU_46(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 256, 0, 1, 512, 24, 0, 1, 4)
#define SD25G_LANE_CMU_46_L0_CFG_TX_RESERVE_15_8 GENMASK(7, 0)
#define SD25G_LANE_CMU_46_L0_CFG_TX_RESERVE_15_8_SET(x)\
@@ -1306,8 +1435,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_46_L0_CFG_TX_RESERVE_15_8_GET(x)\
FIELD_GET(SD25G_LANE_CMU_46_L0_CFG_TX_RESERVE_15_8, x)
-/* SD25G_TARGET:CMU_GRP_3:CMU_C0 */
-#define SD25G_LANE_CMU_C0(t) __REG(TARGET_SD25G_LANE, t, 8, 768, 0, 1, 252, 0, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_3:CMU_C0 */
+#define SD25G_LANE_CMU_C0(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 768, 0, 1, 252, 0, 0, 1, 4)
#define SD25G_LANE_CMU_C0_READ_VCO_CTUNE_3_0 GENMASK(3, 0)
#define SD25G_LANE_CMU_C0_READ_VCO_CTUNE_3_0_SET(x)\
@@ -1321,8 +1452,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_C0_PLL_LOL_UDL_GET(x)\
FIELD_GET(SD25G_LANE_CMU_C0_PLL_LOL_UDL, x)
-/* SD25G_TARGET:CMU_GRP_4:CMU_FF */
-#define SD25G_LANE_CMU_FF(t) __REG(TARGET_SD25G_LANE, t, 8, 1020, 0, 1, 4, 0, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:CMU_GRP_4:CMU_FF */
+#define SD25G_LANE_CMU_FF(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1020, 0, 1, 4, 0, 0, 1, 4)
#define SD25G_LANE_CMU_FF_REGISTER_TABLE_INDEX GENMASK(7, 0)
#define SD25G_LANE_CMU_FF_REGISTER_TABLE_INDEX_SET(x)\
@@ -1330,8 +1463,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_CMU_FF_REGISTER_TABLE_INDEX_GET(x)\
FIELD_GET(SD25G_LANE_CMU_FF_REGISTER_TABLE_INDEX, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_00 */
-#define SD25G_LANE_LANE_00(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 0, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_00 */
+#define SD25G_LANE_LANE_00(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 0, 0, 1, 4)
#define SD25G_LANE_LANE_00_LN_CFG_ITX_VC_DRIVER_3_0 GENMASK(3, 0)
#define SD25G_LANE_LANE_00_LN_CFG_ITX_VC_DRIVER_3_0_SET(x)\
@@ -1345,8 +1480,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_00_LN_CFG_ITX_IPCML_BASE_1_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_00_LN_CFG_ITX_IPCML_BASE_1_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_01 */
-#define SD25G_LANE_LANE_01(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 4, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_01 */
+#define SD25G_LANE_LANE_01(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 4, 0, 1, 4)
#define SD25G_LANE_LANE_01_LN_CFG_ITX_IPDRIVER_BASE_2_0 GENMASK(2, 0)
#define SD25G_LANE_LANE_01_LN_CFG_ITX_IPDRIVER_BASE_2_0_SET(x)\
@@ -1360,8 +1497,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_01_LN_CFG_TX_PREDIV_1_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_01_LN_CFG_TX_PREDIV_1_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_03 */
-#define SD25G_LANE_LANE_03(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 12, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_03 */
+#define SD25G_LANE_LANE_03(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 12, 0, 1, 4)
#define SD25G_LANE_LANE_03_LN_CFG_TAP_DLY_4_0 GENMASK(4, 0)
#define SD25G_LANE_LANE_03_LN_CFG_TAP_DLY_4_0_SET(x)\
@@ -1369,8 +1508,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_03_LN_CFG_TAP_DLY_4_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_03_LN_CFG_TAP_DLY_4_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_04 */
-#define SD25G_LANE_LANE_04(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 16, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_04 */
+#define SD25G_LANE_LANE_04(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 16, 0, 1, 4)
#define SD25G_LANE_LANE_04_LN_CFG_TX2RX_LP_EN BIT(0)
#define SD25G_LANE_LANE_04_LN_CFG_TX2RX_LP_EN_SET(x)\
@@ -1408,8 +1549,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_04_LN_CFG_TAP_MAIN_GET(x)\
FIELD_GET(SD25G_LANE_LANE_04_LN_CFG_TAP_MAIN, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_05 */
-#define SD25G_LANE_LANE_05(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 20, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_05 */
+#define SD25G_LANE_LANE_05(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 20, 0, 1, 4)
#define SD25G_LANE_LANE_05_LN_CFG_TAP_DLY2_3_0 GENMASK(3, 0)
#define SD25G_LANE_LANE_05_LN_CFG_TAP_DLY2_3_0_SET(x)\
@@ -1423,8 +1566,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_05_LN_CFG_BW_1_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_05_LN_CFG_BW_1_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_06 */
-#define SD25G_LANE_LANE_06(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 24, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_06 */
+#define SD25G_LANE_LANE_06(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 24, 0, 1, 4)
#define SD25G_LANE_LANE_06_LN_CFG_EN_MAIN BIT(0)
#define SD25G_LANE_LANE_06_LN_CFG_EN_MAIN_SET(x)\
@@ -1438,8 +1583,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_06_LN_CFG_TAP_ADV_3_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_06_LN_CFG_TAP_ADV_3_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_07 */
-#define SD25G_LANE_LANE_07(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 28, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_07 */
+#define SD25G_LANE_LANE_07(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 28, 0, 1, 4)
#define SD25G_LANE_LANE_07_LN_CFG_EN_ADV BIT(0)
#define SD25G_LANE_LANE_07_LN_CFG_EN_ADV_SET(x)\
@@ -1459,8 +1606,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_07_LN_CFG_EN_DLY_GET(x)\
FIELD_GET(SD25G_LANE_LANE_07_LN_CFG_EN_DLY, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_09 */
-#define SD25G_LANE_LANE_09(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 36, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_09 */
+#define SD25G_LANE_LANE_09(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 36, 0, 1, 4)
#define SD25G_LANE_LANE_09_LN_CFG_TXCAL_VALID_SEL_3_0 GENMASK(3, 0)
#define SD25G_LANE_LANE_09_LN_CFG_TXCAL_VALID_SEL_3_0_SET(x)\
@@ -1468,8 +1617,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_09_LN_CFG_TXCAL_VALID_SEL_3_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_09_LN_CFG_TXCAL_VALID_SEL_3_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_0A */
-#define SD25G_LANE_LANE_0A(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 40, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_0A */
+#define SD25G_LANE_LANE_0A(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 40, 0, 1, 4)
#define SD25G_LANE_LANE_0A_LN_CFG_TXCAL_SHIFT_CODE_5_0 GENMASK(5, 0)
#define SD25G_LANE_LANE_0A_LN_CFG_TXCAL_SHIFT_CODE_5_0_SET(x)\
@@ -1477,8 +1628,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_0A_LN_CFG_TXCAL_SHIFT_CODE_5_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_0A_LN_CFG_TXCAL_SHIFT_CODE_5_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_0B */
-#define SD25G_LANE_LANE_0B(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 44, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_0B */
+#define SD25G_LANE_LANE_0B(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 44, 0, 1, 4)
#define SD25G_LANE_LANE_0B_LN_CFG_TXCAL_MAN_EN BIT(0)
#define SD25G_LANE_LANE_0B_LN_CFG_TXCAL_MAN_EN_SET(x)\
@@ -1498,8 +1651,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_0B_LN_CFG_QUAD_MAN_1_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_0B_LN_CFG_QUAD_MAN_1_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_0C */
-#define SD25G_LANE_LANE_0C(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 48, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_0C */
+#define SD25G_LANE_LANE_0C(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 48, 0, 1, 4)
#define SD25G_LANE_LANE_0C_LN_CFG_PMA_TX_CK_BITWIDTH_2_0 GENMASK(2, 0)
#define SD25G_LANE_LANE_0C_LN_CFG_PMA_TX_CK_BITWIDTH_2_0_SET(x)\
@@ -1519,8 +1674,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_0C_LN_CFG_RXTERM_PD_GET(x)\
FIELD_GET(SD25G_LANE_LANE_0C_LN_CFG_RXTERM_PD, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_0D */
-#define SD25G_LANE_LANE_0D(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 52, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_0D */
+#define SD25G_LANE_LANE_0D(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 52, 0, 1, 4)
#define SD25G_LANE_LANE_0D_LN_CFG_RXTERM_2_0 GENMASK(2, 0)
#define SD25G_LANE_LANE_0D_LN_CFG_RXTERM_2_0_SET(x)\
@@ -1552,8 +1709,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_0D_LN_CFG_DFECK_EN_GET(x)\
FIELD_GET(SD25G_LANE_LANE_0D_LN_CFG_DFECK_EN, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_0E */
-#define SD25G_LANE_LANE_0E(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 56, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_0E */
+#define SD25G_LANE_LANE_0E(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 56, 0, 1, 4)
#define SD25G_LANE_LANE_0E_LN_CFG_ISCAN_EN BIT(0)
#define SD25G_LANE_LANE_0E_LN_CFG_ISCAN_EN_SET(x)\
@@ -1579,8 +1738,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_0E_LN_CFG_DFEDIG_M_2_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_0E_LN_CFG_DFEDIG_M_2_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_0F */
-#define SD25G_LANE_LANE_0F(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 60, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_0F */
+#define SD25G_LANE_LANE_0F(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 60, 0, 1, 4)
#define SD25G_LANE_LANE_0F_LN_CFG_DFETAP_EN_5_1 GENMASK(4, 0)
#define SD25G_LANE_LANE_0F_LN_CFG_DFETAP_EN_5_1_SET(x)\
@@ -1588,8 +1749,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_0F_LN_CFG_DFETAP_EN_5_1_GET(x)\
FIELD_GET(SD25G_LANE_LANE_0F_LN_CFG_DFETAP_EN_5_1, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_18 */
-#define SD25G_LANE_LANE_18(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 96, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_18 */
+#define SD25G_LANE_LANE_18(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 96, 0, 1, 4)
#define SD25G_LANE_LANE_18_LN_CFG_CDRCK_EN BIT(0)
#define SD25G_LANE_LANE_18_LN_CFG_CDRCK_EN_SET(x)\
@@ -1621,8 +1784,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_18_LN_CFG_RXDIV_SEL_2_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_18_LN_CFG_RXDIV_SEL_2_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_19 */
-#define SD25G_LANE_LANE_19(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 100, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_19 */
+#define SD25G_LANE_LANE_19(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 100, 0, 1, 4)
#define SD25G_LANE_LANE_19_LN_CFG_DCDR_PD BIT(0)
#define SD25G_LANE_LANE_19_LN_CFG_DCDR_PD_SET(x)\
@@ -1672,8 +1837,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_19_LN_CFG_PD_CTLE_GET(x)\
FIELD_GET(SD25G_LANE_LANE_19_LN_CFG_PD_CTLE, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_1A */
-#define SD25G_LANE_LANE_1A(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 104, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_1A */
+#define SD25G_LANE_LANE_1A(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 104, 0, 1, 4)
#define SD25G_LANE_LANE_1A_LN_CFG_CTLE_TP_EN BIT(0)
#define SD25G_LANE_LANE_1A_LN_CFG_CTLE_TP_EN_SET(x)\
@@ -1687,8 +1854,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_1A_LN_CFG_CDR_KF_2_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_1A_LN_CFG_CDR_KF_2_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_1B */
-#define SD25G_LANE_LANE_1B(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 108, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_1B */
+#define SD25G_LANE_LANE_1B(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 108, 0, 1, 4)
#define SD25G_LANE_LANE_1B_LN_CFG_CDR_M_7_0 GENMASK(7, 0)
#define SD25G_LANE_LANE_1B_LN_CFG_CDR_M_7_0_SET(x)\
@@ -1696,8 +1865,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_1B_LN_CFG_CDR_M_7_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_1B_LN_CFG_CDR_M_7_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_1C */
-#define SD25G_LANE_LANE_1C(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 112, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_1C */
+#define SD25G_LANE_LANE_1C(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 112, 0, 1, 4)
#define SD25G_LANE_LANE_1C_LN_CFG_CDR_RSTN BIT(0)
#define SD25G_LANE_LANE_1C_LN_CFG_CDR_RSTN_SET(x)\
@@ -1723,8 +1894,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_1C_LN_CFG_EQC_FORCE_3_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_1C_LN_CFG_EQC_FORCE_3_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_1D */
-#define SD25G_LANE_LANE_1D(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 116, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_1D */
+#define SD25G_LANE_LANE_1D(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 116, 0, 1, 4)
#define SD25G_LANE_LANE_1D_LN_CFG_ISCAN_EXT_OVR BIT(0)
#define SD25G_LANE_LANE_1D_LN_CFG_ISCAN_EXT_OVR_SET(x)\
@@ -1774,8 +1947,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_1D_LN_CFG_PI_HOLD_GET(x)\
FIELD_GET(SD25G_LANE_LANE_1D_LN_CFG_PI_HOLD, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_1E */
-#define SD25G_LANE_LANE_1E(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 120, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_1E */
+#define SD25G_LANE_LANE_1E(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 120, 0, 1, 4)
#define SD25G_LANE_LANE_1E_LN_CFG_PI_STEPS_1_0 GENMASK(1, 0)
#define SD25G_LANE_LANE_1E_LN_CFG_PI_STEPS_1_0_SET(x)\
@@ -1807,8 +1982,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_1E_LN_CFG_PMAD_CK_PD_GET(x)\
FIELD_GET(SD25G_LANE_LANE_1E_LN_CFG_PMAD_CK_PD, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_21 */
-#define SD25G_LANE_LANE_21(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 132, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_21 */
+#define SD25G_LANE_LANE_21(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 132, 0, 1, 4)
#define SD25G_LANE_LANE_21_LN_CFG_VGA_CTRL_BYP_4_0 GENMASK(4, 0)
#define SD25G_LANE_LANE_21_LN_CFG_VGA_CTRL_BYP_4_0_SET(x)\
@@ -1816,8 +1993,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_21_LN_CFG_VGA_CTRL_BYP_4_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_21_LN_CFG_VGA_CTRL_BYP_4_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_22 */
-#define SD25G_LANE_LANE_22(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 136, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_22 */
+#define SD25G_LANE_LANE_22(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 136, 0, 1, 4)
#define SD25G_LANE_LANE_22_LN_CFG_EQR_FORCE_3_0 GENMASK(3, 0)
#define SD25G_LANE_LANE_22_LN_CFG_EQR_FORCE_3_0_SET(x)\
@@ -1825,8 +2004,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_22_LN_CFG_EQR_FORCE_3_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_22_LN_CFG_EQR_FORCE_3_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_25 */
-#define SD25G_LANE_LANE_25(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 148, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_25 */
+#define SD25G_LANE_LANE_25(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 148, 0, 1, 4)
#define SD25G_LANE_LANE_25_LN_CFG_INIT_POS_ISCAN_6_0 GENMASK(6, 0)
#define SD25G_LANE_LANE_25_LN_CFG_INIT_POS_ISCAN_6_0_SET(x)\
@@ -1834,8 +2015,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_25_LN_CFG_INIT_POS_ISCAN_6_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_25_LN_CFG_INIT_POS_ISCAN_6_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_26 */
-#define SD25G_LANE_LANE_26(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 152, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_26 */
+#define SD25G_LANE_LANE_26(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 152, 0, 1, 4)
#define SD25G_LANE_LANE_26_LN_CFG_INIT_POS_IPI_6_0 GENMASK(6, 0)
#define SD25G_LANE_LANE_26_LN_CFG_INIT_POS_IPI_6_0_SET(x)\
@@ -1843,8 +2026,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_26_LN_CFG_INIT_POS_IPI_6_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_26_LN_CFG_INIT_POS_IPI_6_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_28 */
-#define SD25G_LANE_LANE_28(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 160, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_28 */
+#define SD25G_LANE_LANE_28(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 160, 0, 1, 4)
#define SD25G_LANE_LANE_28_LN_CFG_ISCAN_MODE_EN BIT(0)
#define SD25G_LANE_LANE_28_LN_CFG_ISCAN_MODE_EN_SET(x)\
@@ -1870,8 +2055,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_28_LN_CFG_RX_SUBRATE_2_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_28_LN_CFG_RX_SUBRATE_2_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_2B */
-#define SD25G_LANE_LANE_2B(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 172, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_2B */
+#define SD25G_LANE_LANE_2B(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 172, 0, 1, 4)
#define SD25G_LANE_LANE_2B_LN_CFG_PI_BW_3_0 GENMASK(3, 0)
#define SD25G_LANE_LANE_2B_LN_CFG_PI_BW_3_0_SET(x)\
@@ -1891,8 +2078,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_2B_LN_CFG_RSTN_TXDUPU_GET(x)\
FIELD_GET(SD25G_LANE_LANE_2B_LN_CFG_RSTN_TXDUPU, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_2C */
-#define SD25G_LANE_LANE_2C(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 176, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_2C */
+#define SD25G_LANE_LANE_2C(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 176, 0, 1, 4)
#define SD25G_LANE_LANE_2C_LN_CFG_TX_SUBRATE_2_0 GENMASK(2, 0)
#define SD25G_LANE_LANE_2C_LN_CFG_TX_SUBRATE_2_0_SET(x)\
@@ -1906,8 +2095,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_2C_LN_CFG_DIS_2NDORDER_GET(x)\
FIELD_GET(SD25G_LANE_LANE_2C_LN_CFG_DIS_2NDORDER, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_2D */
-#define SD25G_LANE_LANE_2D(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 180, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_2D */
+#define SD25G_LANE_LANE_2D(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 180, 0, 1, 4)
#define SD25G_LANE_LANE_2D_LN_CFG_ALOS_THR_2_0 GENMASK(2, 0)
#define SD25G_LANE_LANE_2D_LN_CFG_ALOS_THR_2_0_SET(x)\
@@ -1921,8 +2112,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_2D_LN_CFG_SAT_CNTSEL_2_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_2D_LN_CFG_SAT_CNTSEL_2_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_2E */
-#define SD25G_LANE_LANE_2E(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 184, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_2E */
+#define SD25G_LANE_LANE_2E(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 184, 0, 1, 4)
#define SD25G_LANE_LANE_2E_LN_CFG_EN_FAST_ISCAN BIT(0)
#define SD25G_LANE_LANE_2E_LN_CFG_EN_FAST_ISCAN_SET(x)\
@@ -1972,8 +2165,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_2E_LN_CFG_CTLE_RSTN_GET(x)\
FIELD_GET(SD25G_LANE_LANE_2E_LN_CFG_CTLE_RSTN, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_40 */
-#define SD25G_LANE_LANE_40(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 256, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_40 */
+#define SD25G_LANE_LANE_40(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 256, 0, 1, 4)
#define SD25G_LANE_LANE_40_LN_R_TX_BIT_REVERSE BIT(0)
#define SD25G_LANE_LANE_40_LN_R_TX_BIT_REVERSE_SET(x)\
@@ -2017,8 +2212,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_40_LN_R_CTLE_RSTN_GET(x)\
FIELD_GET(SD25G_LANE_LANE_40_LN_R_CTLE_RSTN, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_42 */
-#define SD25G_LANE_LANE_42(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 264, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_42 */
+#define SD25G_LANE_LANE_42(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 264, 0, 1, 4)
#define SD25G_LANE_LANE_42_LN_CFG_TX_RESERVE_7_0 GENMASK(7, 0)
#define SD25G_LANE_LANE_42_LN_CFG_TX_RESERVE_7_0_SET(x)\
@@ -2026,8 +2223,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_42_LN_CFG_TX_RESERVE_7_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_42_LN_CFG_TX_RESERVE_7_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_43 */
-#define SD25G_LANE_LANE_43(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 268, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_43 */
+#define SD25G_LANE_LANE_43(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 268, 0, 1, 4)
#define SD25G_LANE_LANE_43_LN_CFG_TX_RESERVE_15_8 GENMASK(7, 0)
#define SD25G_LANE_LANE_43_LN_CFG_TX_RESERVE_15_8_SET(x)\
@@ -2035,8 +2234,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_43_LN_CFG_TX_RESERVE_15_8_GET(x)\
FIELD_GET(SD25G_LANE_LANE_43_LN_CFG_TX_RESERVE_15_8, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_44 */
-#define SD25G_LANE_LANE_44(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 272, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_44 */
+#define SD25G_LANE_LANE_44(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 272, 0, 1, 4)
#define SD25G_LANE_LANE_44_LN_CFG_RX_RESERVE_7_0 GENMASK(7, 0)
#define SD25G_LANE_LANE_44_LN_CFG_RX_RESERVE_7_0_SET(x)\
@@ -2044,8 +2245,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_44_LN_CFG_RX_RESERVE_7_0_GET(x)\
FIELD_GET(SD25G_LANE_LANE_44_LN_CFG_RX_RESERVE_7_0, x)
-/* SD25G_TARGET:LANE_GRP_0:LANE_45 */
-#define SD25G_LANE_LANE_45(t) __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 276, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_0:LANE_45 */
+#define SD25G_LANE_LANE_45(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1024, 0, 1, 768, 276, 0, 1, 4)
#define SD25G_LANE_LANE_45_LN_CFG_RX_RESERVE_15_8 GENMASK(7, 0)
#define SD25G_LANE_LANE_45_LN_CFG_RX_RESERVE_15_8_SET(x)\
@@ -2053,8 +2256,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_45_LN_CFG_RX_RESERVE_15_8_GET(x)\
FIELD_GET(SD25G_LANE_LANE_45_LN_CFG_RX_RESERVE_15_8, x)
-/* SD25G_TARGET:LANE_GRP_1:LANE_DE */
-#define SD25G_LANE_LANE_DE(t) __REG(TARGET_SD25G_LANE, t, 8, 1792, 0, 1, 128, 120, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_TARGET:LANE_GRP_1:LANE_DE */
+#define SD25G_LANE_LANE_DE(t) \
+ __REG(TARGET_SD25G_LANE, t, 8, 1792, 0, 1, 128, 120, 0, 1, 4)
#define SD25G_LANE_LANE_DE_LN_LOL_UDL BIT(0)
#define SD25G_LANE_LANE_DE_LN_LOL_UDL_SET(x)\
@@ -2080,8 +2285,10 @@ enum sparx5_serdes_target {
#define SD25G_LANE_LANE_DE_LN_PMA_RXEI_GET(x)\
FIELD_GET(SD25G_LANE_LANE_DE_LN_PMA_RXEI, x)
-/* SD10G_LANE_TARGET:LANE_GRP_8:LANE_DF */
-#define SD6G_LANE_LANE_DF(t) __REG(TARGET_SD6G_LANE, t, 13, 832, 0, 1, 84, 60, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD10G_LANE_TARGET:LANE_GRP_8:LANE_DF */
+#define SD6G_LANE_LANE_DF(t) \
+ __REG(TARGET_SD6G_LANE, t, 13, 832, 0, 1, 84, 60, 0, 1, 4)
#define SD6G_LANE_LANE_DF_LOL_UDL BIT(0)
#define SD6G_LANE_LANE_DF_LOL_UDL_SET(x)\
@@ -2107,8 +2314,9 @@ enum sparx5_serdes_target {
#define SD6G_LANE_LANE_DF_SQUELCH_GET(x)\
FIELD_GET(SD6G_LANE_LANE_DF_SQUELCH, x)
-/* SD10G_CMU_TARGET:CMU_GRP_0:CMU_00 */
-#define SD_CMU_CMU_00(t) __REG(TARGET_SD_CMU, t, 14, 0, 0, 1, 20, 0, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_0:CMU_00 */
+#define SD_CMU_CMU_00(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 0, 0, 1, 20, 0, 0, 1, 4)
#define SD_CMU_CMU_00_R_HWT_SIMULATION_MODE BIT(0)
#define SD_CMU_CMU_00_R_HWT_SIMULATION_MODE_SET(x)\
@@ -2134,8 +2342,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_00_CFG_PLL_TP_SEL_1_0_GET(x)\
FIELD_GET(SD_CMU_CMU_00_CFG_PLL_TP_SEL_1_0, x)
-/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_05 */
-#define SD_CMU_CMU_05(t) __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 0, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_05 */
+#define SD_CMU_CMU_05(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 20, 0, 1, 72, 0, 0, 1, 4)
#define SD_CMU_CMU_05_CFG_REFCK_TERM_EN BIT(0)
#define SD_CMU_CMU_05_CFG_REFCK_TERM_EN_SET(x)\
@@ -2149,9 +2358,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0_GET(x)\
FIELD_GET(SD_CMU_CMU_05_CFG_BIAS_TP_SEL_1_0, x)
-/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_06 */
-#define SD_CMU_CMU_06(t) \
- __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 4, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_06 */
+#define SD_CMU_CMU_06(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 20, 0, 1, 72, 4, 0, 1, 4)
#define SD_CMU_CMU_06_CFG_DISLOS BIT(0)
#define SD_CMU_CMU_06_CFG_DISLOS_SET(x)\
@@ -2201,9 +2410,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_06_CFG_VCO_CAL_BYP_GET(x)\
FIELD_GET(SD_CMU_CMU_06_CFG_VCO_CAL_BYP, x)
-/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_08 */
-#define SD_CMU_CMU_08(t) \
- __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 12, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_08 */
+#define SD_CMU_CMU_08(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 20, 0, 1, 72, 12, 0, 1, 4)
#define SD_CMU_CMU_08_CFG_VFILT2PAD BIT(0)
#define SD_CMU_CMU_08_CFG_VFILT2PAD_SET(x)\
@@ -2235,8 +2444,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_EN_GET(x)\
FIELD_GET(SD_CMU_CMU_08_CFG_RST_TREE_PD_MAN_EN, x)
-/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_09 */
-#define SD_CMU_CMU_09(t) __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 16, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_09 */
+#define SD_CMU_CMU_09(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 20, 0, 1, 72, 16, 0, 1, 4)
#define SD_CMU_CMU_09_CFG_EN_TX_CK_UP BIT(0)
#define SD_CMU_CMU_09_CFG_EN_TX_CK_UP_SET(x)\
@@ -2262,8 +2472,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_09_CFG_SW_10G_GET(x)\
FIELD_GET(SD_CMU_CMU_09_CFG_SW_10G, x)
-/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_0D */
-#define SD_CMU_CMU_0D(t) __REG(TARGET_SD_CMU, t, 14, 20, 0, 1, 72, 32, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_1:CMU_0D */
+#define SD_CMU_CMU_0D(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 20, 0, 1, 72, 32, 0, 1, 4)
#define SD_CMU_CMU_0D_CFG_PD_DIV64 BIT(0)
#define SD_CMU_CMU_0D_CFG_PD_DIV64_SET(x)\
@@ -2295,8 +2506,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_0D_CFG_REFCK_PD_GET(x)\
FIELD_GET(SD_CMU_CMU_0D_CFG_REFCK_PD, x)
-/* SD10G_CMU_TARGET:CMU_GRP_3:CMU_1B */
-#define SD_CMU_CMU_1B(t) __REG(TARGET_SD_CMU, t, 14, 104, 0, 1, 20, 4, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_3:CMU_1B */
+#define SD_CMU_CMU_1B(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 104, 0, 1, 20, 4, 0, 1, 4)
#define SD_CMU_CMU_1B_CFG_RESERVE_7_0 GENMASK(7, 0)
#define SD_CMU_CMU_1B_CFG_RESERVE_7_0_SET(x)\
@@ -2304,8 +2516,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_1B_CFG_RESERVE_7_0_GET(x)\
FIELD_GET(SD_CMU_CMU_1B_CFG_RESERVE_7_0, x)
-/* SD10G_CMU_TARGET:CMU_GRP_4:CMU_1F */
-#define SD_CMU_CMU_1F(t) __REG(TARGET_SD_CMU, t, 14, 124, 0, 1, 68, 0, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_4:CMU_1F */
+#define SD_CMU_CMU_1F(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 124, 0, 1, 68, 0, 0, 1, 4)
#define SD_CMU_CMU_1F_CFG_BIAS_DN_EN BIT(0)
#define SD_CMU_CMU_1F_CFG_BIAS_DN_EN_SET(x)\
@@ -2331,8 +2544,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_1F_CFG_VTUNE_SEL_GET(x)\
FIELD_GET(SD_CMU_CMU_1F_CFG_VTUNE_SEL, x)
-/* SD10G_CMU_TARGET:CMU_GRP_5:CMU_30 */
-#define SD_CMU_CMU_30(t) __REG(TARGET_SD_CMU, t, 14, 192, 0, 1, 72, 0, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_5:CMU_30 */
+#define SD_CMU_CMU_30(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 192, 0, 1, 72, 0, 0, 1, 4)
#define SD_CMU_CMU_30_R_PLL_DLOL_EN BIT(0)
#define SD_CMU_CMU_30_R_PLL_DLOL_EN_SET(x)\
@@ -2340,8 +2554,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_30_R_PLL_DLOL_EN_GET(x)\
FIELD_GET(SD_CMU_CMU_30_R_PLL_DLOL_EN, x)
-/* SD10G_CMU_TARGET:CMU_GRP_6:CMU_44 */
-#define SD_CMU_CMU_44(t) __REG(TARGET_SD_CMU, t, 14, 264, 0, 1, 632, 8, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_6:CMU_44 */
+#define SD_CMU_CMU_44(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 264, 0, 1, 632, 8, 0, 1, 4)
#define SD_CMU_CMU_44_R_PLL_RSTN BIT(0)
#define SD_CMU_CMU_44_R_PLL_RSTN_SET(x)\
@@ -2355,8 +2570,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_44_R_CK_RESETB_GET(x)\
FIELD_GET(SD_CMU_CMU_44_R_CK_RESETB, x)
-/* SD10G_CMU_TARGET:CMU_GRP_6:CMU_45 */
-#define SD_CMU_CMU_45(t) __REG(TARGET_SD_CMU, t, 14, 264, 0, 1, 632, 12, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_6:CMU_45 */
+#define SD_CMU_CMU_45(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 264, 0, 1, 632, 12, 0, 1, 4)
#define SD_CMU_CMU_45_R_EN_RATECHG_CTRL BIT(0)
#define SD_CMU_CMU_45_R_EN_RATECHG_CTRL_SET(x)\
@@ -2406,8 +2622,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_45_R_AUTO_RST_TREE_PD_MAN_GET(x)\
FIELD_GET(SD_CMU_CMU_45_R_AUTO_RST_TREE_PD_MAN, x)
-/* SD10G_CMU_TARGET:CMU_GRP_6:CMU_47 */
-#define SD_CMU_CMU_47(t) __REG(TARGET_SD_CMU, t, 14, 264, 0, 1, 632, 20, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_6:CMU_47 */
+#define SD_CMU_CMU_47(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 264, 0, 1, 632, 20, 0, 1, 4)
#define SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0 GENMASK(4, 0)
#define SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0_SET(x)\
@@ -2415,8 +2632,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0_GET(x)\
FIELD_GET(SD_CMU_CMU_47_R_PCS2PMA_PHYMODE_4_0, x)
-/* SD10G_CMU_TARGET:CMU_GRP_7:CMU_E0 */
-#define SD_CMU_CMU_E0(t) __REG(TARGET_SD_CMU, t, 14, 896, 0, 1, 8, 0, 0, 1, 4)
+/* SD10G_CMU_TARGET:CMU_GRP_7:CMU_E0 */
+#define SD_CMU_CMU_E0(t) \
+ __REG(TARGET_SD_CMU, t, TSIZE(TC_SD_CMU), 896, 0, 1, 8, 0, 0, 1, 4)
#define SD_CMU_CMU_E0_READ_VCO_CTUNE_3_0 GENMASK(3, 0)
#define SD_CMU_CMU_E0_READ_VCO_CTUNE_3_0_SET(x)\
@@ -2430,8 +2648,10 @@ enum sparx5_serdes_target {
#define SD_CMU_CMU_E0_PLL_LOL_UDL_GET(x)\
FIELD_GET(SD_CMU_CMU_E0_PLL_LOL_UDL, x)
-/* SD_CMU_TARGET:SD_CMU_CFG:SD_CMU_CFG */
-#define SD_CMU_CFG_SD_CMU_CFG(t) __REG(TARGET_SD_CMU_CFG, t, 14, 0, 0, 1, 8, 0, 0, 1, 4)
+/* SD_CMU_TARGET:SD_CMU_CFG:SD_CMU_CFG */
+#define SD_CMU_CFG_SD_CMU_CFG(t) \
+ __REG(TARGET_SD_CMU_CFG, t, TSIZE(TC_SD_CMU_CFG), 0, 0, 1, 8, 0, 0, 1, \
+ 4)
#define SD_CMU_CFG_SD_CMU_CFG_CMU_RST BIT(0)
#define SD_CMU_CFG_SD_CMU_CFG_CMU_RST_SET(x)\
@@ -2445,8 +2665,9 @@ enum sparx5_serdes_target {
#define SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST_GET(x)\
FIELD_GET(SD_CMU_CFG_SD_CMU_CFG_EXT_CFG_RST, x)
-/* SD_LANE_TARGET:SD_RESET:SD_SER_RST */
-#define SD_LANE_SD_SER_RST(t) __REG(TARGET_SD_LANE, t, 25, 0, 0, 1, 8, 0, 0, 1, 4)
+/* SD_LANE_TARGET:SD_RESET:SD_SER_RST */
+#define SD_LANE_SD_SER_RST(t) \
+ __REG(TARGET_SD_LANE, t, TSIZE(TC_SD_LANE), 0, 0, 1, 8, 0, 0, 1, 4)
#define SD_LANE_SD_SER_RST_SER_RST BIT(0)
#define SD_LANE_SD_SER_RST_SER_RST_SET(x)\
@@ -2454,8 +2675,9 @@ enum sparx5_serdes_target {
#define SD_LANE_SD_SER_RST_SER_RST_GET(x)\
FIELD_GET(SD_LANE_SD_SER_RST_SER_RST, x)
-/* SD_LANE_TARGET:SD_RESET:SD_DES_RST */
-#define SD_LANE_SD_DES_RST(t) __REG(TARGET_SD_LANE, t, 25, 0, 0, 1, 8, 4, 0, 1, 4)
+/* SD_LANE_TARGET:SD_RESET:SD_DES_RST */
+#define SD_LANE_SD_DES_RST(t) \
+ __REG(TARGET_SD_LANE, t, TSIZE(TC_SD_LANE), 0, 0, 1, 8, 4, 0, 1, 4)
#define SD_LANE_SD_DES_RST_DES_RST BIT(0)
#define SD_LANE_SD_DES_RST_DES_RST_SET(x)\
@@ -2463,8 +2685,9 @@ enum sparx5_serdes_target {
#define SD_LANE_SD_DES_RST_DES_RST_GET(x)\
FIELD_GET(SD_LANE_SD_DES_RST_DES_RST, x)
-/* SD_LANE_TARGET:SD_LANE_CFG_STAT:SD_LANE_CFG */
-#define SD_LANE_SD_LANE_CFG(t) __REG(TARGET_SD_LANE, t, 25, 8, 0, 1, 8, 0, 0, 1, 4)
+/* SD_LANE_TARGET:SD_LANE_CFG_STAT:SD_LANE_CFG */
+#define SD_LANE_SD_LANE_CFG(t) \
+ __REG(TARGET_SD_LANE, t, TSIZE(TC_SD_LANE), 8, 0, 1, 8, 0, 0, 1, 4)
#define SD_LANE_SD_LANE_CFG_MACRO_RST BIT(0)
#define SD_LANE_SD_LANE_CFG_MACRO_RST_SET(x)\
@@ -2508,8 +2731,9 @@ enum sparx5_serdes_target {
#define SD_LANE_SD_LANE_CFG_LANE_RX_RST_GET(x)\
FIELD_GET(SD_LANE_SD_LANE_CFG_LANE_RX_RST, x)
-/* SD_LANE_TARGET:SD_LANE_CFG_STAT:SD_LANE_STAT */
-#define SD_LANE_SD_LANE_STAT(t) __REG(TARGET_SD_LANE, t, 25, 8, 0, 1, 8, 4, 0, 1, 4)
+/* SD_LANE_TARGET:SD_LANE_CFG_STAT:SD_LANE_STAT */
+#define SD_LANE_SD_LANE_STAT(t) \
+ __REG(TARGET_SD_LANE, t, TSIZE(TC_SD_LANE), 8, 0, 1, 8, 4, 0, 1, 4)
#define SD_LANE_SD_LANE_STAT_PMA_RST_DONE BIT(0)
#define SD_LANE_SD_LANE_STAT_PMA_RST_DONE_SET(x)\
@@ -2529,9 +2753,9 @@ enum sparx5_serdes_target {
#define SD_LANE_SD_LANE_STAT_DBG_OBS_GET(x)\
FIELD_GET(SD_LANE_SD_LANE_STAT_DBG_OBS, x)
-/* SD_LANE_TARGET:SD_PWR_CFG:QUIET_MODE_6G */
-#define SD_LANE_QUIET_MODE_6G(t) \
- __REG(TARGET_SD_LANE, t, 25, 24, 0, 1, 8, 4, 0, 1, 4)
+/* SD_LANE_TARGET:SD_PWR_CFG:QUIET_MODE_6G */
+#define SD_LANE_QUIET_MODE_6G(t) \
+ __REG(TARGET_SD_LANE, t, TSIZE(TC_SD_LANE), 24, 0, 1, 8, 4, 0, 1, 4)
#define SD_LANE_QUIET_MODE_6G_QUIET_MODE GENMASK(24, 0)
#define SD_LANE_QUIET_MODE_6G_QUIET_MODE_SET(x)\
@@ -2539,8 +2763,9 @@ enum sparx5_serdes_target {
#define SD_LANE_QUIET_MODE_6G_QUIET_MODE_GET(x)\
FIELD_GET(SD_LANE_QUIET_MODE_6G_QUIET_MODE, x)
-/* SD_LANE_TARGET:CFG_STAT_FX100:MISC */
-#define SD_LANE_MISC(t) __REG(TARGET_SD_LANE, t, 25, 56, 0, 1, 56, 0, 0, 1, 4)
+/* SD_LANE_TARGET:CFG_STAT_FX100:MISC */
+#define SD_LANE_MISC(t) \
+ __REG(TARGET_SD_LANE, t, TSIZE(TC_SD_LANE), 56, 0, 1, 56, 0, 0, 1, 4)
#define SD_LANE_MISC_SD_125_RST_DIS BIT(0)
#define SD_LANE_MISC_SD_125_RST_DIS_SET(x)\
@@ -2560,14 +2785,16 @@ enum sparx5_serdes_target {
#define SD_LANE_MISC_MUX_ENA_GET(x)\
FIELD_GET(SD_LANE_MISC_MUX_ENA, x)
+/* SPARX5 ONLY */
#define SD_LANE_MISC_CORE_CLK_FREQ GENMASK(5, 4)
#define SD_LANE_MISC_CORE_CLK_FREQ_SET(x)\
FIELD_PREP(SD_LANE_MISC_CORE_CLK_FREQ, x)
#define SD_LANE_MISC_CORE_CLK_FREQ_GET(x)\
FIELD_GET(SD_LANE_MISC_CORE_CLK_FREQ, x)
-/* SD_LANE_TARGET:CFG_STAT_FX100:M_STAT_MISC */
-#define SD_LANE_M_STAT_MISC(t) __REG(TARGET_SD_LANE, t, 25, 56, 0, 1, 56, 36, 0, 1, 4)
+/* SD_LANE_TARGET:CFG_STAT_FX100:M_STAT_MISC */
+#define SD_LANE_M_STAT_MISC(t) \
+ __REG(TARGET_SD_LANE, t, TSIZE(TC_SD_LANE), 56, 0, 1, 56, 36, 0, 1, 4)
#define SD_LANE_M_STAT_MISC_M_RIS_EDGE_PTR_ADJ_SUM GENMASK(21, 0)
#define SD_LANE_M_STAT_MISC_M_RIS_EDGE_PTR_ADJ_SUM_SET(x)\
@@ -2581,8 +2808,10 @@ enum sparx5_serdes_target {
#define SD_LANE_M_STAT_MISC_M_LOCK_CNT_GET(x)\
FIELD_GET(SD_LANE_M_STAT_MISC_M_LOCK_CNT, x)
-/* SD25G_CFG_TARGET:SD_RESET:SD_SER_RST */
-#define SD_LANE_25G_SD_SER_RST(t) __REG(TARGET_SD_LANE_25G, t, 8, 0, 0, 1, 8, 0, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_CFG_TARGET:SD_RESET:SD_SER_RST */
+#define SD_LANE_25G_SD_SER_RST(t) \
+ __REG(TARGET_SD_LANE_25G, t, 8, 0, 0, 1, 8, 0, 0, 1, 4)
#define SD_LANE_25G_SD_SER_RST_SER_RST BIT(0)
#define SD_LANE_25G_SD_SER_RST_SER_RST_SET(x)\
@@ -2590,8 +2819,10 @@ enum sparx5_serdes_target {
#define SD_LANE_25G_SD_SER_RST_SER_RST_GET(x)\
FIELD_GET(SD_LANE_25G_SD_SER_RST_SER_RST, x)
-/* SD25G_CFG_TARGET:SD_RESET:SD_DES_RST */
-#define SD_LANE_25G_SD_DES_RST(t) __REG(TARGET_SD_LANE_25G, t, 8, 0, 0, 1, 8, 4, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_CFG_TARGET:SD_RESET:SD_DES_RST */
+#define SD_LANE_25G_SD_DES_RST(t) \
+ __REG(TARGET_SD_LANE_25G, t, 8, 0, 0, 1, 8, 4, 0, 1, 4)
#define SD_LANE_25G_SD_DES_RST_DES_RST BIT(0)
#define SD_LANE_25G_SD_DES_RST_DES_RST_SET(x)\
@@ -2599,8 +2830,10 @@ enum sparx5_serdes_target {
#define SD_LANE_25G_SD_DES_RST_DES_RST_GET(x)\
FIELD_GET(SD_LANE_25G_SD_DES_RST_DES_RST, x)
-/* SD25G_CFG_TARGET:SD_LANE_CFG_STAT:SD_LANE_CFG */
-#define SD_LANE_25G_SD_LANE_CFG(t) __REG(TARGET_SD_LANE_25G, t, 8, 8, 0, 1, 12, 0, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_CFG_TARGET:SD_LANE_CFG_STAT:SD_LANE_CFG */
+#define SD_LANE_25G_SD_LANE_CFG(t) \
+ __REG(TARGET_SD_LANE_25G, t, 8, 8, 0, 1, 12, 0, 0, 1, 4)
#define SD_LANE_25G_SD_LANE_CFG_MACRO_RST BIT(0)
#define SD_LANE_25G_SD_LANE_CFG_MACRO_RST_SET(x)\
@@ -2698,8 +2931,10 @@ enum sparx5_serdes_target {
#define SD_LANE_25G_SD_LANE_CFG_PCS2PMA_TXMARGIN_GET(x)\
FIELD_GET(SD_LANE_25G_SD_LANE_CFG_PCS2PMA_TXMARGIN, x)
-/* SD25G_CFG_TARGET:SD_LANE_CFG_STAT:SD_LANE_CFG2 */
-#define SD_LANE_25G_SD_LANE_CFG2(t) __REG(TARGET_SD_LANE_25G, t, 8, 8, 0, 1, 12, 4, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_CFG_TARGET:SD_LANE_CFG_STAT:SD_LANE_CFG2 */
+#define SD_LANE_25G_SD_LANE_CFG2(t) \
+ __REG(TARGET_SD_LANE_25G, t, 8, 8, 0, 1, 12, 4, 0, 1, 4)
#define SD_LANE_25G_SD_LANE_CFG2_DATA_WIDTH_SEL GENMASK(2, 0)
#define SD_LANE_25G_SD_LANE_CFG2_DATA_WIDTH_SEL_SET(x)\
@@ -2767,8 +3002,10 @@ enum sparx5_serdes_target {
#define SD_LANE_25G_SD_LANE_CFG2_RXRATE_SEL_GET(x)\
FIELD_GET(SD_LANE_25G_SD_LANE_CFG2_RXRATE_SEL, x)
-/* SD25G_CFG_TARGET:SD_LANE_CFG_STAT:SD_LANE_STAT */
-#define SD_LANE_25G_SD_LANE_STAT(t) __REG(TARGET_SD_LANE_25G, t, 8, 8, 0, 1, 12, 8, 0, 1, 4)
+/* SPARX5 ONLY */
+/* SD25G_CFG_TARGET:SD_LANE_CFG_STAT:SD_LANE_STAT */
+#define SD_LANE_25G_SD_LANE_STAT(t) \
+ __REG(TARGET_SD_LANE_25G, t, 8, 8, 0, 1, 12, 8, 0, 1, 4)
#define SD_LANE_25G_SD_LANE_STAT_PMA_RST_DONE BIT(0)
#define SD_LANE_25G_SD_LANE_STAT_PMA_RST_DONE_SET(x)\
@@ -2788,8 +3025,9 @@ enum sparx5_serdes_target {
#define SD_LANE_25G_SD_LANE_STAT_DBG_OBS_GET(x)\
FIELD_GET(SD_LANE_25G_SD_LANE_STAT_DBG_OBS, x)
-/* SD25G_CFG_TARGET:SD_PWR_CFG:QUIET_MODE_6G */
-#define SD_LANE_25G_QUIET_MODE_6G(t) \
+/* SPARX5 ONLY */
+/* SD25G_CFG_TARGET:SD_PWR_CFG:QUIET_MODE_6G */
+#define SD_LANE_25G_QUIET_MODE_6G(t) \
__REG(TARGET_SD_LANE_25G, t, 8, 28, 0, 1, 8, 4, 0, 1, 4)
#define SD_LANE_25G_QUIET_MODE_6G_QUIET_MODE GENMASK(24, 0)
diff --git a/drivers/phy/motorola/phy-cpcap-usb.c b/drivers/phy/motorola/phy-cpcap-usb.c
index 7bbf729a7c90..7cb020dd3423 100644
--- a/drivers/phy/motorola/phy-cpcap-usb.c
+++ b/drivers/phy/motorola/phy-cpcap-usb.c
@@ -704,7 +704,7 @@ static void cpcap_usb_phy_remove(struct platform_device *pdev)
static struct platform_driver cpcap_usb_phy_driver = {
.probe = cpcap_usb_phy_probe,
- .remove_new = cpcap_usb_phy_remove,
+ .remove = cpcap_usb_phy_remove,
.driver = {
.name = "cpcap-usb-phy",
.of_match_table = of_match_ptr(cpcap_usb_phy_id_table),
diff --git a/drivers/phy/motorola/phy-mapphone-mdm6600.c b/drivers/phy/motorola/phy-mapphone-mdm6600.c
index 376d023a0aa9..152344e4f7e4 100644
--- a/drivers/phy/motorola/phy-mapphone-mdm6600.c
+++ b/drivers/phy/motorola/phy-mapphone-mdm6600.c
@@ -655,7 +655,7 @@ static void phy_mdm6600_remove(struct platform_device *pdev)
static struct platform_driver phy_mdm6600_driver = {
.probe = phy_mdm6600_probe,
- .remove_new = phy_mdm6600_remove,
+ .remove = phy_mdm6600_remove,
.driver = {
.name = "phy-mapphone-mdm6600",
.pm = &phy_mdm6600_pm_ops,
diff --git a/drivers/phy/mscc/phy-ocelot-serdes.c b/drivers/phy/mscc/phy-ocelot-serdes.c
index d9443e865a78..1cd1b5db2ad7 100644
--- a/drivers/phy/mscc/phy-ocelot-serdes.c
+++ b/drivers/phy/mscc/phy-ocelot-serdes.c
@@ -441,7 +441,7 @@ static const struct phy_ops serdes_ops = {
};
static struct phy *serdes_simple_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct serdes_ctrl *ctrl = dev_get_drvdata(dev);
unsigned int port, idx, i;
diff --git a/drivers/phy/nuvoton/Kconfig b/drivers/phy/nuvoton/Kconfig
new file mode 100644
index 000000000000..d02cae2db315
--- /dev/null
+++ b/drivers/phy/nuvoton/Kconfig
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# PHY drivers for Nuvoton MA35 platforms
+#
+config PHY_MA35_USB
+ tristate "Nuvoton MA35 USB2.0 PHY driver"
+ depends on ARCH_MA35 || COMPILE_TEST
+ depends on OF
+ select GENERIC_PHY
+ help
+ Enable this to support the USB2.0 PHY on the Nuvoton MA35
+ series SoCs.
diff --git a/drivers/phy/nuvoton/Makefile b/drivers/phy/nuvoton/Makefile
new file mode 100644
index 000000000000..2937e3921898
--- /dev/null
+++ b/drivers/phy/nuvoton/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_PHY_MA35_USB) += phy-ma35d1-usb2.o
diff --git a/drivers/phy/nuvoton/phy-ma35d1-usb2.c b/drivers/phy/nuvoton/phy-ma35d1-usb2.c
new file mode 100644
index 000000000000..9a459b700ed4
--- /dev/null
+++ b/drivers/phy/nuvoton/phy-ma35d1-usb2.c
@@ -0,0 +1,143 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2024 Nuvoton Technology Corp.
+ */
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+/* USB PHY Miscellaneous Control Register */
+#define MA35_SYS_REG_USBPMISCR 0x60
+#define PHY0POR BIT(0) /* PHY Power-On Reset Control Bit */
+#define PHY0SUSPEND BIT(1) /* PHY Suspend; 0: suspend, 1: operaion */
+#define PHY0COMN BIT(2) /* PHY Common Block Power-Down Control */
+#define PHY0DEVCKSTB BIT(10) /* PHY 60 MHz UTMI clock stable bit */
+
+struct ma35_usb_phy {
+ struct clk *clk;
+ struct device *dev;
+ struct regmap *sysreg;
+};
+
+static int ma35_usb_phy_power_on(struct phy *phy)
+{
+ struct ma35_usb_phy *p_phy = phy_get_drvdata(phy);
+ unsigned int val;
+ int ret;
+
+ ret = clk_prepare_enable(p_phy->clk);
+ if (ret < 0) {
+ dev_err(p_phy->dev, "Failed to enable PHY clock: %d\n", ret);
+ return ret;
+ }
+
+ regmap_read(p_phy->sysreg, MA35_SYS_REG_USBPMISCR, &val);
+ if (val & PHY0SUSPEND) {
+ /*
+ * USB PHY0 is in operation mode already
+ * make sure USB PHY 60 MHz UTMI Interface Clock ready
+ */
+ ret = regmap_read_poll_timeout(p_phy->sysreg, MA35_SYS_REG_USBPMISCR, val,
+ val & PHY0DEVCKSTB, 10, 1000);
+ if (ret == 0)
+ return 0;
+ }
+
+ /*
+ * reset USB PHY0.
+ * wait until USB PHY0 60 MHz UTMI Interface Clock ready
+ */
+ regmap_update_bits(p_phy->sysreg, MA35_SYS_REG_USBPMISCR, 0x7, (PHY0POR | PHY0SUSPEND));
+ udelay(20);
+
+ /* make USB PHY0 enter operation mode */
+ regmap_update_bits(p_phy->sysreg, MA35_SYS_REG_USBPMISCR, 0x7, PHY0SUSPEND);
+
+ /* make sure USB PHY 60 MHz UTMI Interface Clock ready */
+ ret = regmap_read_poll_timeout(p_phy->sysreg, MA35_SYS_REG_USBPMISCR, val,
+ val & PHY0DEVCKSTB, 10, 1000);
+ if (ret == -ETIMEDOUT) {
+ dev_err(p_phy->dev, "Check PHY clock, Timeout: %d\n", ret);
+ clk_disable_unprepare(p_phy->clk);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ma35_usb_phy_power_off(struct phy *phy)
+{
+ struct ma35_usb_phy *p_phy = phy_get_drvdata(phy);
+
+ clk_disable_unprepare(p_phy->clk);
+ return 0;
+}
+
+static const struct phy_ops ma35_usb_phy_ops = {
+ .power_on = ma35_usb_phy_power_on,
+ .power_off = ma35_usb_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+static int ma35_usb_phy_probe(struct platform_device *pdev)
+{
+ struct phy_provider *provider;
+ struct ma35_usb_phy *p_phy;
+ struct phy *phy;
+
+ p_phy = devm_kzalloc(&pdev->dev, sizeof(*p_phy), GFP_KERNEL);
+ if (!p_phy)
+ return -ENOMEM;
+
+ p_phy->dev = &pdev->dev;
+ platform_set_drvdata(pdev, p_phy);
+
+ p_phy->sysreg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "nuvoton,sys");
+ if (IS_ERR(p_phy->sysreg))
+ return dev_err_probe(&pdev->dev, PTR_ERR(p_phy->sysreg),
+ "Failed to get SYS registers\n");
+
+ p_phy->clk = of_clk_get(pdev->dev.of_node, 0);
+ if (IS_ERR(p_phy->clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(p_phy->clk),
+ "failed to find usb_phy clock\n");
+
+ phy = devm_phy_create(&pdev->dev, NULL, &ma35_usb_phy_ops);
+ if (IS_ERR(phy))
+ return dev_err_probe(&pdev->dev, PTR_ERR(phy), "Failed to create PHY\n");
+
+ phy_set_drvdata(phy, p_phy);
+
+ provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
+ if (IS_ERR(provider))
+ return dev_err_probe(&pdev->dev, PTR_ERR(provider),
+ "Failed to register PHY provider\n");
+ return 0;
+}
+
+static const struct of_device_id ma35_usb_phy_of_match[] = {
+ { .compatible = "nuvoton,ma35d1-usb2-phy", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, ma35_usb_phy_of_match);
+
+static struct platform_driver ma35_usb_phy_driver = {
+ .probe = ma35_usb_phy_probe,
+ .driver = {
+ .name = "ma35d1-usb2-phy",
+ .of_match_table = ma35_usb_phy_of_match,
+ },
+};
+module_platform_driver(ma35_usb_phy_driver);
+
+MODULE_DESCRIPTION("Nuvoton ma35d1 USB2.0 PHY driver");
+MODULE_AUTHOR("Hui-Ping Chen <hpchen0nvt@gmail.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/phy-airoha-pcie-regs.h b/drivers/phy/phy-airoha-pcie-regs.h
new file mode 100644
index 000000000000..b938a7b468fe
--- /dev/null
+++ b/drivers/phy/phy-airoha-pcie-regs.h
@@ -0,0 +1,494 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024 AIROHA Inc
+ * Author: Lorenzo Bianconi <lorenzo@kernel.org>
+ */
+
+#ifndef _PHY_AIROHA_PCIE_H
+#define _PHY_AIROHA_PCIE_H
+
+/* CSR_2L */
+#define REG_CSR_2L_CMN 0x0000
+#define CSR_2L_PXP_CMN_LANE_EN BIT(0)
+#define CSR_2L_PXP_CMN_TRIM_MASK GENMASK(28, 24)
+
+#define REG_CSR_2L_JCPLL_IB_EXT 0x0004
+#define REG_CSR_2L_JCPLL_LPF_SHCK_EN BIT(8)
+#define CSR_2L_PXP_JCPLL_CHP_IBIAS GENMASK(21, 16)
+#define CSR_2L_PXP_JCPLL_CHP_IOFST GENMASK(29, 24)
+
+#define REG_CSR_2L_JCPLL_LPF_BR 0x0008
+#define CSR_2L_PXP_JCPLL_LPF_BR GENMASK(4, 0)
+#define CSR_2L_PXP_JCPLL_LPF_BC GENMASK(12, 8)
+#define CSR_2L_PXP_JCPLL_LPF_BP GENMASK(20, 16)
+#define CSR_2L_PXP_JCPLL_LPF_BWR GENMASK(28, 24)
+
+#define REG_CSR_2L_JCPLL_LPF_BWC 0x000c
+#define CSR_2L_PXP_JCPLL_LPF_BWC GENMASK(4, 0)
+#define CSR_2L_PXP_JCPLL_KBAND_CODE GENMASK(23, 16)
+#define CSR_2L_PXP_JCPLL_KBAND_DIV GENMASK(26, 24)
+
+#define REG_CSR_2L_JCPLL_KBAND_KFC 0x0010
+#define CSR_2L_PXP_JCPLL_KBAND_KFC GENMASK(1, 0)
+#define CSR_2L_PXP_JCPLL_KBAND_KF GENMASK(9, 8)
+#define CSR_2L_PXP_JCPLL_KBAND_KS GENMASK(17, 16)
+#define CSR_2L_PXP_JCPLL_POSTDIV_EN BIT(24)
+
+#define REG_CSR_2L_JCPLL_MMD_PREDIV_MODE 0x0014
+#define CSR_2L_PXP_JCPLL_MMD_PREDIV_MODE GENMASK(1, 0)
+#define CSR_2L_PXP_JCPLL_POSTDIV_D2 BIT(16)
+#define CSR_2L_PXP_JCPLL_POSTDIV_D5 BIT(24)
+
+#define CSR_2L_PXP_JCPLL_MONCK 0x0018
+#define CSR_2L_PXP_JCPLL_REFIN_DIV GENMASK(25, 24)
+
+#define REG_CSR_2L_JCPLL_RST_DLY 0x001c
+#define CSR_2L_PXP_JCPLL_RST_DLY GENMASK(2, 0)
+#define CSR_2L_PXP_JCPLL_RST BIT(8)
+#define CSR_2L_PXP_JCPLL_SDM_DI_EN BIT(16)
+#define CSR_2L_PXP_JCPLL_SDM_DI_LS GENMASK(25, 24)
+
+#define REG_CSR_2L_JCPLL_SDM_IFM 0x0020
+#define CSR_2L_PXP_JCPLL_SDM_IFM BIT(0)
+
+#define REG_CSR_2L_JCPLL_SDM_HREN 0x0024
+#define CSR_2L_PXP_JCPLL_SDM_HREN BIT(0)
+#define CSR_2L_PXP_JCPLL_TCL_AMP_EN BIT(8)
+#define CSR_2L_PXP_JCPLL_TCL_AMP_GAIN GENMASK(18, 16)
+#define CSR_2L_PXP_JCPLL_TCL_AMP_VREF GENMASK(28, 24)
+
+#define REG_CSR_2L_JCPLL_TCL_CMP 0x0028
+#define CSR_2L_PXP_JCPLL_TCL_LPF_EN BIT(16)
+#define CSR_2L_PXP_JCPLL_TCL_LPF_BW GENMASK(26, 24)
+
+#define REG_CSR_2L_JCPLL_VCODIV 0x002c
+#define CSR_2L_PXP_JCPLL_VCO_CFIX GENMASK(9, 8)
+#define CSR_2L_PXP_JCPLL_VCO_HALFLSB_EN BIT(16)
+#define CSR_2L_PXP_JCPLL_VCO_SCAPWR GENMASK(26, 24)
+
+#define REG_CSR_2L_JCPLL_VCO_TCLVAR 0x0030
+#define CSR_2L_PXP_JCPLL_VCO_TCLVAR GENMASK(2, 0)
+
+#define REG_CSR_2L_JCPLL_SSC 0x0038
+#define CSR_2L_PXP_JCPLL_SSC_EN BIT(0)
+#define CSR_2L_PXP_JCPLL_SSC_PHASE_INI BIT(8)
+#define CSR_2L_PXP_JCPLL_SSC_TRI_EN BIT(16)
+
+#define REG_CSR_2L_JCPLL_SSC_DELTA1 0x003c
+#define CSR_2L_PXP_JCPLL_SSC_DELTA1 GENMASK(15, 0)
+#define CSR_2L_PXP_JCPLL_SSC_DELTA GENMASK(31, 16)
+
+#define REG_CSR_2L_JCPLL_SSC_PERIOD 0x0040
+#define CSR_2L_PXP_JCPLL_SSC_PERIOD GENMASK(15, 0)
+
+#define REG_CSR_2L_JCPLL_TCL_VTP_EN 0x004c
+#define CSR_2L_PXP_JCPLL_SPARE_LOW GENMASK(31, 24)
+
+#define REG_CSR_2L_JCPLL_TCL_KBAND_VREF 0x0050
+#define CSR_2L_PXP_JCPLL_TCL_KBAND_VREF GENMASK(4, 0)
+#define CSR_2L_PXP_JCPLL_VCO_KBAND_MEAS_EN BIT(24)
+
+#define REG_CSR_2L_750M_SYS_CK 0x0054
+#define CSR_2L_PXP_TXPLL_LPF_SHCK_EN BIT(16)
+#define CSR_2L_PXP_TXPLL_CHP_IBIAS GENMASK(29, 24)
+
+#define REG_CSR_2L_TXPLL_CHP_IOFST 0x0058
+#define CSR_2L_PXP_TXPLL_CHP_IOFST GENMASK(5, 0)
+#define CSR_2L_PXP_TXPLL_LPF_BR GENMASK(12, 8)
+#define CSR_2L_PXP_TXPLL_LPF_BC GENMASK(20, 16)
+#define CSR_2L_PXP_TXPLL_LPF_BP GENMASK(28, 24)
+
+#define REG_CSR_2L_TXPLL_LPF_BWR 0x005c
+#define CSR_2L_PXP_TXPLL_LPF_BWR GENMASK(4, 0)
+#define CSR_2L_PXP_TXPLL_LPF_BWC GENMASK(12, 8)
+#define CSR_2L_PXP_TXPLL_KBAND_CODE GENMASK(31, 24)
+
+#define REG_CSR_2L_TXPLL_KBAND_DIV 0x0060
+#define CSR_2L_PXP_TXPLL_KBAND_DIV GENMASK(2, 0)
+#define CSR_2L_PXP_TXPLL_KBAND_KFC GENMASK(9, 8)
+#define CSR_2L_PXP_TXPLL_KBAND_KF GENMASK(17, 16)
+#define CSR_2L_PXP_txpll_KBAND_KS GENMASK(25, 24)
+
+#define REG_CSR_2L_TXPLL_POSTDIV 0x0064
+#define CSR_2L_PXP_TXPLL_POSTDIV_EN BIT(0)
+#define CSR_2L_PXP_TXPLL_MMD_PREDIV_MODE GENMASK(9, 8)
+#define CSR_2L_PXP_TXPLL_PHY_CK1_EN BIT(24)
+
+#define REG_CSR_2L_TXPLL_PHY_CK2 0x0068
+#define CSR_2L_PXP_TXPLL_REFIN_INTERNAL BIT(24)
+
+#define REG_CSR_2L_TXPLL_REFIN_DIV 0x006c
+#define CSR_2L_PXP_TXPLL_REFIN_DIV GENMASK(1, 0)
+#define CSR_2L_PXP_TXPLL_RST_DLY GENMASK(10, 8)
+#define CSR_2L_PXP_TXPLL_PLL_RSTB BIT(16)
+
+#define REG_CSR_2L_TXPLL_SDM_DI_LS 0x0070
+#define CSR_2L_PXP_TXPLL_SDM_DI_LS GENMASK(1, 0)
+#define CSR_2L_PXP_TXPLL_SDM_IFM BIT(8)
+#define CSR_2L_PXP_TXPLL_SDM_ORD GENMASK(25, 24)
+
+#define REG_CSR_2L_TXPLL_SDM_OUT 0x0074
+#define CSR_2L_PXP_TXPLL_TCL_AMP_EN BIT(16)
+#define CSR_2L_PXP_TXPLL_TCL_AMP_GAIN GENMASK(26, 24)
+
+#define REG_CSR_2L_TXPLL_TCL_AMP_VREF 0x0078
+#define CSR_2L_PXP_TXPLL_TCL_AMP_VREF GENMASK(4, 0)
+#define CSR_2L_PXP_TXPLL_TCL_LPF_EN BIT(24)
+
+#define REG_CSR_2L_TXPLL_TCL_LPF_BW 0x007c
+#define CSR_2L_PXP_TXPLL_TCL_LPF_BW GENMASK(2, 0)
+#define CSR_2L_PXP_TXPLL_VCO_CFIX GENMASK(17, 16)
+#define CSR_2L_PXP_TXPLL_VCO_HALFLSB_EN BIT(24)
+
+#define REG_CSR_2L_TXPLL_VCO_SCAPWR 0x0080
+#define CSR_2L_PXP_TXPLL_VCO_SCAPWR GENMASK(2, 0)
+
+#define REG_CSR_2L_TXPLL_SSC 0x0084
+#define CSR_2L_PXP_TXPLL_SSC_EN BIT(0)
+#define CSR_2L_PXP_TXPLL_SSC_PHASE_INI BIT(8)
+
+#define REG_CSR_2L_TXPLL_SSC_DELTA1 0x0088
+#define CSR_2L_PXP_TXPLL_SSC_DELTA1 GENMASK(15, 0)
+#define CSR_2L_PXP_TXPLL_SSC_DELTA GENMASK(31, 16)
+
+#define REG_CSR_2L_TXPLL_SSC_PERIOD 0x008c
+#define CSR_2L_PXP_txpll_SSC_PERIOD GENMASK(15, 0)
+
+#define REG_CSR_2L_TXPLL_VTP 0x0090
+#define CSR_2L_PXP_TXPLL_VTP_EN BIT(0)
+
+#define REG_CSR_2L_TXPLL_TCL_VTP 0x0098
+#define CSR_2L_PXP_TXPLL_SPARE_L GENMASK(31, 24)
+
+#define REG_CSR_2L_TXPLL_TCL_KBAND_VREF 0x009c
+#define CSR_2L_PXP_TXPLL_TCL_KBAND_VREF GENMASK(4, 0)
+#define CSR_2L_PXP_TXPLL_VCO_KBAND_MEAS_EN BIT(24)
+
+#define REG_CSR_2L_TXPLL_POSTDIV_D256 0x00a0
+#define CSR_2L_PXP_CLKTX0_AMP GENMASK(10, 8)
+#define CSR_2L_PXP_CLKTX0_OFFSET GENMASK(17, 16)
+#define CSR_2L_PXP_CLKTX0_SR GENMASK(25, 24)
+
+#define REG_CSR_2L_CLKTX0_FORCE_OUT1 0x00a4
+#define CSR_2L_PXP_CLKTX0_HZ BIT(8)
+#define CSR_2L_PXP_CLKTX0_IMP_SEL GENMASK(20, 16)
+#define CSR_2L_PXP_CLKTX1_AMP GENMASK(26, 24)
+
+#define REG_CSR_2L_CLKTX1_OFFSET 0x00a8
+#define CSR_2L_PXP_CLKTX1_OFFSET GENMASK(1, 0)
+#define CSR_2L_PXP_CLKTX1_SR GENMASK(9, 8)
+#define CSR_2L_PXP_CLKTX1_HZ BIT(24)
+
+#define REG_CSR_2L_CLKTX1_IMP_SEL 0x00ac
+#define CSR_2L_PXP_CLKTX1_IMP_SEL GENMASK(4, 0)
+
+#define REG_CSR_2L_PLL_CMN_RESERVE0 0x00b0
+#define CSR_2L_PXP_PLL_RESERVE_MASK GENMASK(15, 0)
+
+#define REG_CSR_2L_TX0_CKLDO 0x00cc
+#define CSR_2L_PXP_TX0_CKLDO_EN BIT(0)
+#define CSR_2L_PXP_TX0_DMEDGEGEN_EN BIT(24)
+
+#define REG_CSR_2L_TX1_CKLDO 0x00e8
+#define CSR_2L_PXP_TX1_CKLDO_EN BIT(0)
+#define CSR_2L_PXP_TX1_DMEDGEGEN_EN BIT(24)
+
+#define REG_CSR_2L_TX1_MULTLANE 0x00ec
+#define CSR_2L_PXP_TX1_MULTLANE_EN BIT(0)
+
+#define REG_CSR_2L_RX0_REV0 0x00fc
+#define CSR_2L_PXP_VOS_PNINV GENMASK(19, 18)
+#define CSR_2L_PXP_FE_GAIN_NORMAL_MODE GENMASK(22, 20)
+#define CSR_2L_PXP_FE_GAIN_TRAIN_MODE GENMASK(26, 24)
+
+#define REG_CSR_2L_RX0_PHYCK_DIV 0x0100
+#define CSR_2L_PXP_RX0_PHYCK_SEL GENMASK(9, 8)
+#define CSR_2L_PXP_RX0_PHYCK_RSTB BIT(16)
+#define CSR_2L_PXP_RX0_TDC_CK_SEL BIT(24)
+
+#define REG_CSR_2L_CDR0_PD_PICAL_CKD8_INV 0x0104
+#define CSR_2L_PXP_CDR0_PD_EDGE_DISABLE BIT(8)
+
+#define REG_CSR_2L_CDR0_LPF_RATIO 0x0110
+#define CSR_2L_PXP_CDR0_LPF_TOP_LIM GENMASK(26, 8)
+
+#define REG_CSR_2L_CDR0_PR_INJ_MODE 0x011c
+#define CSR_2L_PXP_CDR0_INJ_FORCE_OFF BIT(24)
+
+#define REG_CSR_2L_CDR0_PR_BETA_DAC 0x0120
+#define CSR_2L_PXP_CDR0_PR_BETA_SEL GENMASK(19, 16)
+#define CSR_2L_PXP_CDR0_PR_KBAND_DIV GENMASK(26, 24)
+
+#define REG_CSR_2L_CDR0_PR_VREG_IBAND 0x0124
+#define CSR_2L_PXP_CDR0_PR_VREG_IBAND GENMASK(2, 0)
+#define CSR_2L_PXP_CDR0_PR_VREG_CKBUF GENMASK(10, 8)
+
+#define REG_CSR_2L_CDR0_PR_CKREF_DIV 0x0128
+#define CSR_2L_PXP_CDR0_PR_CKREF_DIV GENMASK(1, 0)
+
+#define REG_CSR_2L_CDR0_PR_MONCK 0x012c
+#define CSR_2L_PXP_CDR0_PR_MONCK_ENABLE BIT(0)
+#define CSR_2L_PXP_CDR0_PR_RESERVE0 GENMASK(19, 16)
+
+#define REG_CSR_2L_CDR0_PR_COR_HBW 0x0130
+#define CSR_2L_PXP_CDR0_PR_LDO_FORCE_ON BIT(8)
+#define CSR_2L_PXP_CDR0_PR_CKREF_DIV1 GENMASK(17, 16)
+
+#define REG_CSR_2L_CDR0_PR_MONPI 0x0134
+#define CSR_2L_PXP_CDR0_PR_XFICK_EN BIT(8)
+
+#define REG_CSR_2L_RX0_SIGDET_DCTEST 0x0140
+#define CSR_2L_PXP_RX0_SIGDET_LPF_CTRL GENMASK(9, 8)
+#define CSR_2L_PXP_RX0_SIGDET_PEAK GENMASK(25, 24)
+
+#define REG_CSR_2L_RX0_SIGDET_VTH_SEL 0x0144
+#define CSR_2L_PXP_RX0_SIGDET_VTH_SEL GENMASK(4, 0)
+#define CSR_2L_PXP_RX0_FE_VB_EQ1_EN BIT(24)
+
+#define REG_CSR_2L_PXP_RX0_FE_VB_EQ2 0x0148
+#define CSR_2L_PXP_RX0_FE_VB_EQ2_EN BIT(0)
+#define CSR_2L_PXP_RX0_FE_VB_EQ3_EN BIT(8)
+#define CSR_2L_PXP_RX0_FE_VCM_GEN_PWDB BIT(16)
+
+#define REG_CSR_2L_PXP_RX0_OSCAL_CTLE1IOS 0x0158
+#define CSR_2L_PXP_RX0_PR_OSCAL_VGA1IOS GENMASK(29, 24)
+
+#define REG_CSR_2L_PXP_RX0_OSCA_VGA1VOS 0x015c
+#define CSR_2L_PXP_RX0_PR_OSCAL_VGA1VOS GENMASK(5, 0)
+#define CSR_2L_PXP_RX0_PR_OSCAL_VGA2IOS GENMASK(13, 8)
+
+#define REG_CSR_2L_RX1_REV0 0x01b4
+
+#define REG_CSR_2L_RX1_PHYCK_DIV 0x01b8
+#define CSR_2L_PXP_RX1_PHYCK_SEL GENMASK(9, 8)
+#define CSR_2L_PXP_RX1_PHYCK_RSTB BIT(16)
+#define CSR_2L_PXP_RX1_TDC_CK_SEL BIT(24)
+
+#define REG_CSR_2L_CDR1_PD_PICAL_CKD8_INV 0x01bc
+#define CSR_2L_PXP_CDR1_PD_EDGE_DISABLE BIT(8)
+
+#define REG_CSR_2L_CDR1_PR_BETA_DAC 0x01d8
+#define CSR_2L_PXP_CDR1_PR_BETA_SEL GENMASK(19, 16)
+#define CSR_2L_PXP_CDR1_PR_KBAND_DIV GENMASK(26, 24)
+
+#define REG_CSR_2L_CDR1_PR_MONCK 0x01e4
+#define CSR_2L_PXP_CDR1_PR_MONCK_ENABLE BIT(0)
+#define CSR_2L_PXP_CDR1_PR_RESERVE0 GENMASK(19, 16)
+
+#define REG_CSR_2L_CDR1_LPF_RATIO 0x01c8
+#define CSR_2L_PXP_CDR1_LPF_TOP_LIM GENMASK(26, 8)
+
+#define REG_CSR_2L_CDR1_PR_INJ_MODE 0x01d4
+#define CSR_2L_PXP_CDR1_INJ_FORCE_OFF BIT(24)
+
+#define REG_CSR_2L_CDR1_PR_VREG_IBAND_VAL 0x01dc
+#define CSR_2L_PXP_CDR1_PR_VREG_IBAND GENMASK(2, 0)
+#define CSR_2L_PXP_CDR1_PR_VREG_CKBUF GENMASK(10, 8)
+
+#define REG_CSR_2L_CDR1_PR_CKREF_DIV 0x01e0
+#define CSR_2L_PXP_CDR1_PR_CKREF_DIV GENMASK(1, 0)
+
+#define REG_CSR_2L_CDR1_PR_COR_HBW 0x01e8
+#define CSR_2L_PXP_CDR1_PR_LDO_FORCE_ON BIT(8)
+#define CSR_2L_PXP_CDR1_PR_CKREF_DIV1 GENMASK(17, 16)
+
+#define REG_CSR_2L_CDR1_PR_MONPI 0x01ec
+#define CSR_2L_PXP_CDR1_PR_XFICK_EN BIT(8)
+
+#define REG_CSR_2L_RX1_DAC_RANGE_EYE 0x01f4
+#define CSR_2L_PXP_RX1_SIGDET_LPF_CTRL GENMASK(25, 24)
+
+#define REG_CSR_2L_RX1_SIGDET_NOVTH 0x01f8
+#define CSR_2L_PXP_RX1_SIGDET_PEAK GENMASK(9, 8)
+#define CSR_2L_PXP_RX1_SIGDET_VTH_SEL GENMASK(20, 16)
+
+#define REG_CSR_2L_RX1_FE_VB_EQ1 0x0200
+#define CSR_2L_PXP_RX1_FE_VB_EQ1_EN BIT(0)
+#define CSR_2L_PXP_RX1_FE_VB_EQ2_EN BIT(8)
+#define CSR_2L_PXP_RX1_FE_VB_EQ3_EN BIT(16)
+#define CSR_2L_PXP_RX1_FE_VCM_GEN_PWDB BIT(24)
+
+#define REG_CSR_2L_RX1_OSCAL_VGA1IOS 0x0214
+#define CSR_2L_PXP_RX1_PR_OSCAL_VGA1IOS GENMASK(5, 0)
+#define CSR_2L_PXP_RX1_PR_OSCAL_VGA1VOS GENMASK(13, 8)
+#define CSR_2L_PXP_RX1_PR_OSCAL_VGA2IOS GENMASK(21, 16)
+
+/* PMA */
+#define REG_PCIE_PMA_SS_LCPLL_PWCTL_SETTING_1 0x0004
+#define PCIE_LCPLL_MAN_PWDB BIT(0)
+
+#define REG_PCIE_PMA_SEQUENCE_DISB_CTRL1 0x010c
+#define PCIE_DISB_RX_SDCAL_EN BIT(0)
+
+#define REG_PCIE_PMA_CTRL_SEQUENCE_FORCE_CTRL1 0x0114
+#define PCIE_FORCE_RX_SDCAL_EN BIT(0)
+
+#define REG_PCIE_PMA_SS_RX_FREQ_DET1 0x014c
+#define PCIE_PLL_FT_LOCK_CYCLECNT GENMASK(15, 0)
+#define PCIE_PLL_FT_UNLOCK_CYCLECNT GENMASK(31, 16)
+
+#define REG_PCIE_PMA_SS_RX_FREQ_DET2 0x0150
+#define PCIE_LOCK_TARGET_BEG GENMASK(15, 0)
+#define PCIE_LOCK_TARGET_END GENMASK(31, 16)
+
+#define REG_PCIE_PMA_SS_RX_FREQ_DET3 0x0154
+#define PCIE_UNLOCK_TARGET_BEG GENMASK(15, 0)
+#define PCIE_UNLOCK_TARGET_END GENMASK(31, 16)
+
+#define REG_PCIE_PMA_SS_RX_FREQ_DET4 0x0158
+#define PCIE_FREQLOCK_DET_EN GENMASK(2, 0)
+#define PCIE_LOCK_LOCKTH GENMASK(11, 8)
+#define PCIE_UNLOCK_LOCKTH GENMASK(15, 12)
+
+#define REG_PCIE_PMA_SS_RX_CAL1 0x0160
+#define REG_PCIE_PMA_SS_RX_CAL2 0x0164
+#define PCIE_CAL_OUT_OS GENMASK(11, 8)
+
+#define REG_PCIE_PMA_SS_RX_SIGDET0 0x0168
+#define PCIE_SIGDET_WIN_NONVLD_TIMES GENMASK(28, 24)
+
+#define REG_PCIE_PMA_TX_RESET 0x0260
+#define PCIE_TX_TOP_RST BIT(0)
+#define PCIE_TX_CAL_RST BIT(8)
+
+#define REG_PCIE_PMA_RX_FORCE_MODE0 0x0294
+#define PCIE_FORCE_DA_XPON_RX_FE_GAIN_CTRL GENMASK(1, 0)
+
+#define REG_PCIE_PMA_SS_DA_XPON_PWDB0 0x034c
+#define PCIE_DA_XPON_CDR_PR_PWDB BIT(8)
+
+#define REG_PCIE_PMA_SW_RESET 0x0460
+#define PCIE_SW_RX_FIFO_RST BIT(0)
+#define PCIE_SW_RX_RST BIT(1)
+#define PCIE_SW_TX_RST BIT(2)
+#define PCIE_SW_PMA_RST BIT(3)
+#define PCIE_SW_ALLPCS_RST BIT(4)
+#define PCIE_SW_REF_RST BIT(5)
+#define PCIE_SW_TX_FIFO_RST BIT(6)
+#define PCIE_SW_XFI_TXPCS_RST BIT(7)
+#define PCIE_SW_XFI_RXPCS_RST BIT(8)
+#define PCIE_SW_XFI_RXPCS_BIST_RST BIT(9)
+#define PCIE_SW_HSG_TXPCS_RST BIT(10)
+#define PCIE_SW_HSG_RXPCS_RST BIT(11)
+#define PCIE_PMA_SW_RST (PCIE_SW_RX_FIFO_RST | \
+ PCIE_SW_RX_RST | \
+ PCIE_SW_TX_RST | \
+ PCIE_SW_PMA_RST | \
+ PCIE_SW_ALLPCS_RST | \
+ PCIE_SW_REF_RST | \
+ PCIE_SW_TX_FIFO_RST | \
+ PCIE_SW_XFI_TXPCS_RST | \
+ PCIE_SW_XFI_RXPCS_RST | \
+ PCIE_SW_XFI_RXPCS_BIST_RST | \
+ PCIE_SW_HSG_TXPCS_RST | \
+ PCIE_SW_HSG_RXPCS_RST)
+
+#define REG_PCIE_PMA_RO_RX_FREQDET 0x0530
+#define PCIE_RO_FBCK_LOCK BIT(0)
+#define PCIE_RO_FL_OUT GENMASK(31, 16)
+
+#define REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC 0x0794
+#define PCIE_FORCE_DA_PXP_CDR_PR_IDAC GENMASK(10, 0)
+#define PCIE_FORCE_SEL_DA_PXP_CDR_PR_IDAC BIT(16)
+#define PCIE_FORCE_SEL_DA_PXP_TXPLL_SDM_PCW BIT(24)
+
+#define REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_SDM_PCW 0x0798
+#define PCIE_FORCE_DA_PXP_TXPLL_SDM_PCW GENMASK(30, 0)
+
+#define REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_VOS 0x079c
+#define PCIE_FORCE_SEL_DA_PXP_JCPLL_SDM_PCW BIT(16)
+
+#define REG_PCIE_PMA_FORCE_DA_PXP_JCPLL_SDM_PCW 0x0800
+#define PCIE_FORCE_DA_PXP_JCPLL_SDM_PCW GENMASK(30, 0)
+
+#define REG_PCIE_PMA_FORCE_DA_PXP_CDR_PD_PWDB 0x081c
+#define PCIE_FORCE_DA_PXP_CDR_PD_PWDB BIT(0)
+#define PCIE_FORCE_SEL_DA_PXP_CDR_PD_PWDB BIT(8)
+
+#define REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C 0x0820
+#define PCIE_FORCE_DA_PXP_CDR_PR_LPF_C_EN BIT(0)
+#define PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_C_EN BIT(8)
+#define PCIE_FORCE_DA_PXP_CDR_PR_LPF_R_EN BIT(16)
+#define PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_R_EN BIT(24)
+
+#define REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB 0x0824
+#define PCIE_FORCE_DA_PXP_CDR_PR_PWDB BIT(16)
+#define PCIE_FORCE_SEL_DA_PXP_CDR_PR_PWDB BIT(24)
+
+#define REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT 0x0828
+#define PCIE_FORCE_DA_PXP_JCPLL_CKOUT_EN BIT(0)
+#define PCIE_FORCE_SEL_DA_PXP_JCPLL_CKOUT_EN BIT(8)
+#define PCIE_FORCE_DA_PXP_JCPLL_EN BIT(16)
+#define PCIE_FORCE_SEL_DA_PXP_JCPLL_EN BIT(24)
+
+#define REG_PCIE_PMA_FORCE_DA_PXP_RX_SCAN_RST 0x0084c
+#define PCIE_FORCE_DA_PXP_RX_SIGDET_PWDB BIT(16)
+#define PCIE_FORCE_SEL_DA_PXP_RX_SIGDET_PWDB BIT(24)
+
+#define REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT 0x0854
+#define PCIE_FORCE_DA_PXP_TXPLL_CKOUT_EN BIT(0)
+#define PCIE_FORCE_SEL_DA_PXP_TXPLL_CKOUT_EN BIT(8)
+#define PCIE_FORCE_DA_PXP_TXPLL_EN BIT(16)
+#define PCIE_FORCE_SEL_DA_PXP_TXPLL_EN BIT(24)
+
+#define REG_PCIE_PMA_SCAN_MODE 0x0884
+#define PCIE_FORCE_DA_PXP_JCPLL_KBAND_LOAD_EN BIT(0)
+#define PCIE_FORCE_SEL_DA_PXP_JCPLL_KBAND_LOAD_EN BIT(8)
+
+#define REG_PCIE_PMA_DIG_RESERVE_13 0x08bc
+#define PCIE_FLL_IDAC_PCIEG1 GENMASK(10, 0)
+#define PCIE_FLL_IDAC_PCIEG2 GENMASK(26, 16)
+
+#define REG_PCIE_PMA_DIG_RESERVE_14 0x08c0
+#define PCIE_FLL_IDAC_PCIEG3 GENMASK(10, 0)
+#define PCIE_FLL_LOAD_EN BIT(16)
+
+#define REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_GAIN_CTRL 0x088c
+#define PCIE_FORCE_DA_PXP_RX_FE_GAIN_CTRL GENMASK(1, 0)
+#define PCIE_FORCE_SEL_DA_PXP_RX_FE_GAIN_CTRL BIT(8)
+
+#define REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_PWDB 0x0894
+#define PCIE_FORCE_DA_PXP_RX_FE_PWDB BIT(0)
+#define PCIE_FORCE_SEL_DA_PXP_RX_FE_PWDB BIT(8)
+
+#define REG_PCIE_PMA_DIG_RESERVE_12 0x08b8
+#define PCIE_FORCE_PMA_RX_SPEED GENMASK(7, 4)
+#define PCIE_FORCE_SEL_PMA_RX_SPEED BIT(7)
+
+#define REG_PCIE_PMA_DIG_RESERVE_17 0x08e0
+
+#define REG_PCIE_PMA_DIG_RESERVE_18 0x08e4
+#define PCIE_PXP_RX_VTH_SEL_PCIE_G1 GENMASK(4, 0)
+#define PCIE_PXP_RX_VTH_SEL_PCIE_G2 GENMASK(12, 8)
+#define PCIE_PXP_RX_VTH_SEL_PCIE_G3 GENMASK(20, 16)
+
+#define REG_PCIE_PMA_DIG_RESERVE_19 0x08e8
+#define PCIE_PCP_RX_REV0_PCIE_GEN1 GENMASK(31, 16)
+
+#define REG_PCIE_PMA_DIG_RESERVE_20 0x08ec
+#define PCIE_PCP_RX_REV0_PCIE_GEN2 GENMASK(15, 0)
+#define PCIE_PCP_RX_REV0_PCIE_GEN3 GENMASK(31, 16)
+
+#define REG_PCIE_PMA_DIG_RESERVE_21 0x08f0
+#define REG_PCIE_PMA_DIG_RESERVE_22 0x08f4
+#define REG_PCIE_PMA_DIG_RESERVE_27 0x0908
+#define REG_PCIE_PMA_DIG_RESERVE_30 0x0914
+
+/* DTIME */
+#define REG_PCIE_PEXTP_DIG_GLB44 0x00
+#define PCIE_XTP_RXDET_VCM_OFF_STB_T_SEL GENMASK(7, 0)
+#define PCIE_XTP_RXDET_EN_STB_T_SEL GENMASK(15, 8)
+#define PCIE_XTP_RXDET_FINISH_STB_T_SEL GENMASK(23, 16)
+#define PCIE_XTP_TXPD_TX_DATA_EN_DLY GENMASK(27, 24)
+#define PCIE_XTP_TXPD_RXDET_DONE_CDT BIT(28)
+#define PCIE_XTP_RXDET_LATCH_STB_T_SEL GENMASK(31, 29)
+
+/* RX AEQ */
+#define REG_PCIE_PEXTP_DIG_LN_RX30_P0 0x0000
+#define PCIE_XTP_LN_RX_PDOWN_L1P2_EXIT_WAIT GENMASK(7, 0)
+#define PCIE_XTP_LN_RX_PDOWN_T2RLB_DIG_EN BIT(8)
+#define PCIE_XTP_LN_RX_PDOWN_E0_AEQEN_WAIT GENMASK(31, 16)
+
+#define REG_PCIE_PEXTP_DIG_LN_RX30_P1 0x0100
+
+#endif /* _PHY_AIROHA_PCIE_H */
diff --git a/drivers/phy/phy-airoha-pcie.c b/drivers/phy/phy-airoha-pcie.c
new file mode 100644
index 000000000000..56e9ade8a9fd
--- /dev/null
+++ b/drivers/phy/phy-airoha-pcie.c
@@ -0,0 +1,1290 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024 AIROHA Inc
+ * Author: Lorenzo Bianconi <lorenzo@kernel.org>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "phy-airoha-pcie-regs.h"
+
+#define LEQ_LEN_CTRL_MAX_VAL 7
+#define FREQ_LOCK_MAX_ATTEMPT 10
+
+/* PCIe-PHY initialization time in ms needed by the hw to complete */
+#define PHY_HW_INIT_TIME_MS 30
+
+enum airoha_pcie_port_gen {
+ PCIE_PORT_GEN1 = 1,
+ PCIE_PORT_GEN2,
+ PCIE_PORT_GEN3,
+};
+
+/**
+ * struct airoha_pcie_phy - PCIe phy driver main structure
+ * @dev: pointer to device
+ * @phy: pointer to generic phy
+ * @csr_2l: Analogic lane IO mapped register base address
+ * @pma0: IO mapped register base address of PMA0-PCIe
+ * @pma1: IO mapped register base address of PMA1-PCIe
+ * @p0_xr_dtime: IO mapped register base address of port0 Tx-Rx detection time
+ * @p1_xr_dtime: IO mapped register base address of port1 Tx-Rx detection time
+ * @rx_aeq: IO mapped register base address of Rx AEQ training
+ */
+struct airoha_pcie_phy {
+ struct device *dev;
+ struct phy *phy;
+ void __iomem *csr_2l;
+ void __iomem *pma0;
+ void __iomem *pma1;
+ void __iomem *p0_xr_dtime;
+ void __iomem *p1_xr_dtime;
+ void __iomem *rx_aeq;
+};
+
+static void airoha_phy_clear_bits(void __iomem *reg, u32 mask)
+{
+ u32 val = readl(reg) & ~mask;
+
+ writel(val, reg);
+}
+
+static void airoha_phy_set_bits(void __iomem *reg, u32 mask)
+{
+ u32 val = readl(reg) | mask;
+
+ writel(val, reg);
+}
+
+static void airoha_phy_update_bits(void __iomem *reg, u32 mask, u32 val)
+{
+ u32 tmp = readl(reg);
+
+ tmp &= ~mask;
+ tmp |= val & mask;
+ writel(tmp, reg);
+}
+
+#define airoha_phy_update_field(reg, mask, val) \
+ do { \
+ BUILD_BUG_ON_MSG(!__builtin_constant_p((mask)), \
+ "mask is not constant"); \
+ airoha_phy_update_bits((reg), (mask), \
+ FIELD_PREP((mask), (val))); \
+ } while (0)
+
+#define airoha_phy_csr_2l_clear_bits(pcie_phy, reg, mask) \
+ airoha_phy_clear_bits((pcie_phy)->csr_2l + (reg), (mask))
+#define airoha_phy_csr_2l_set_bits(pcie_phy, reg, mask) \
+ airoha_phy_set_bits((pcie_phy)->csr_2l + (reg), (mask))
+#define airoha_phy_csr_2l_update_field(pcie_phy, reg, mask, val) \
+ airoha_phy_update_field((pcie_phy)->csr_2l + (reg), (mask), (val))
+#define airoha_phy_pma0_clear_bits(pcie_phy, reg, mask) \
+ airoha_phy_clear_bits((pcie_phy)->pma0 + (reg), (mask))
+#define airoha_phy_pma1_clear_bits(pcie_phy, reg, mask) \
+ airoha_phy_clear_bits((pcie_phy)->pma1 + (reg), (mask))
+#define airoha_phy_pma0_set_bits(pcie_phy, reg, mask) \
+ airoha_phy_set_bits((pcie_phy)->pma0 + (reg), (mask))
+#define airoha_phy_pma1_set_bits(pcie_phy, reg, mask) \
+ airoha_phy_set_bits((pcie_phy)->pma1 + (reg), (mask))
+#define airoha_phy_pma0_update_field(pcie_phy, reg, mask, val) \
+ airoha_phy_update_field((pcie_phy)->pma0 + (reg), (mask), (val))
+#define airoha_phy_pma1_update_field(pcie_phy, reg, mask, val) \
+ airoha_phy_update_field((pcie_phy)->pma1 + (reg), (mask), (val))
+
+static void
+airoha_phy_init_lane0_rx_fw_pre_calib(struct airoha_pcie_phy *pcie_phy,
+ enum airoha_pcie_port_gen gen)
+{
+ u32 fl_out_target = gen == PCIE_PORT_GEN3 ? 41600 : 41941;
+ u32 lock_cyclecnt = gen == PCIE_PORT_GEN3 ? 26000 : 32767;
+ u32 pr_idac, val, cdr_pr_idac_tmp = 0;
+ int i;
+
+ airoha_phy_pma0_set_bits(pcie_phy,
+ REG_PCIE_PMA_SS_LCPLL_PWCTL_SETTING_1,
+ PCIE_LCPLL_MAN_PWDB);
+ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET2,
+ PCIE_LOCK_TARGET_BEG,
+ fl_out_target - 100);
+ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET2,
+ PCIE_LOCK_TARGET_END,
+ fl_out_target + 100);
+ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET1,
+ PCIE_PLL_FT_LOCK_CYCLECNT, lock_cyclecnt);
+ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET4,
+ PCIE_LOCK_LOCKTH, 0x3);
+ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET3,
+ PCIE_UNLOCK_TARGET_BEG,
+ fl_out_target - 100);
+ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET3,
+ PCIE_UNLOCK_TARGET_END,
+ fl_out_target + 100);
+ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET1,
+ PCIE_PLL_FT_UNLOCK_CYCLECNT,
+ lock_cyclecnt);
+ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET4,
+ PCIE_UNLOCK_LOCKTH, 0x3);
+
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CDR0_PR_INJ_MODE,
+ CSR_2L_PXP_CDR0_INJ_FORCE_OFF);
+
+ airoha_phy_pma0_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
+ PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_R_EN);
+ airoha_phy_pma0_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
+ PCIE_FORCE_DA_PXP_CDR_PR_LPF_R_EN);
+ airoha_phy_pma0_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
+ PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_C_EN);
+ airoha_phy_pma0_clear_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
+ PCIE_FORCE_DA_PXP_CDR_PR_LPF_C_EN);
+ airoha_phy_pma0_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+ PCIE_FORCE_SEL_DA_PXP_CDR_PR_IDAC);
+
+ airoha_phy_pma0_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB,
+ PCIE_FORCE_SEL_DA_PXP_CDR_PR_PWDB);
+ airoha_phy_pma0_clear_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB,
+ PCIE_FORCE_DA_PXP_CDR_PR_PWDB);
+ airoha_phy_pma0_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB,
+ PCIE_FORCE_DA_PXP_CDR_PR_PWDB);
+
+ for (i = 0; i < LEQ_LEN_CTRL_MAX_VAL; i++) {
+ airoha_phy_pma0_update_field(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+ PCIE_FORCE_DA_PXP_CDR_PR_IDAC, i << 8);
+ airoha_phy_pma0_clear_bits(pcie_phy,
+ REG_PCIE_PMA_SS_RX_FREQ_DET4,
+ PCIE_FREQLOCK_DET_EN);
+ airoha_phy_pma0_update_field(pcie_phy,
+ REG_PCIE_PMA_SS_RX_FREQ_DET4,
+ PCIE_FREQLOCK_DET_EN, 0x3);
+
+ usleep_range(10000, 15000);
+
+ val = FIELD_GET(PCIE_RO_FL_OUT,
+ readl(pcie_phy->pma0 +
+ REG_PCIE_PMA_RO_RX_FREQDET));
+ if (val > fl_out_target)
+ cdr_pr_idac_tmp = i << 8;
+ }
+
+ for (i = LEQ_LEN_CTRL_MAX_VAL; i >= 0; i--) {
+ pr_idac = cdr_pr_idac_tmp | (0x1 << i);
+ airoha_phy_pma0_update_field(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+ PCIE_FORCE_DA_PXP_CDR_PR_IDAC, pr_idac);
+ airoha_phy_pma0_clear_bits(pcie_phy,
+ REG_PCIE_PMA_SS_RX_FREQ_DET4,
+ PCIE_FREQLOCK_DET_EN);
+ airoha_phy_pma0_update_field(pcie_phy,
+ REG_PCIE_PMA_SS_RX_FREQ_DET4,
+ PCIE_FREQLOCK_DET_EN, 0x3);
+
+ usleep_range(10000, 15000);
+
+ val = FIELD_GET(PCIE_RO_FL_OUT,
+ readl(pcie_phy->pma0 +
+ REG_PCIE_PMA_RO_RX_FREQDET));
+ if (val < fl_out_target)
+ pr_idac &= ~(0x1 << i);
+
+ cdr_pr_idac_tmp = pr_idac;
+ }
+
+ airoha_phy_pma0_update_field(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+ PCIE_FORCE_DA_PXP_CDR_PR_IDAC,
+ cdr_pr_idac_tmp);
+
+ for (i = 0; i < FREQ_LOCK_MAX_ATTEMPT; i++) {
+ u32 val;
+
+ airoha_phy_pma0_clear_bits(pcie_phy,
+ REG_PCIE_PMA_SS_RX_FREQ_DET4,
+ PCIE_FREQLOCK_DET_EN);
+ airoha_phy_pma0_update_field(pcie_phy,
+ REG_PCIE_PMA_SS_RX_FREQ_DET4,
+ PCIE_FREQLOCK_DET_EN, 0x3);
+
+ usleep_range(10000, 15000);
+
+ val = readl(pcie_phy->pma0 + REG_PCIE_PMA_RO_RX_FREQDET);
+ if (val & PCIE_RO_FBCK_LOCK)
+ break;
+ }
+
+ /* turn off force mode and update band values */
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR0_PR_INJ_MODE,
+ CSR_2L_PXP_CDR0_INJ_FORCE_OFF);
+
+ airoha_phy_pma0_clear_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
+ PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_R_EN);
+ airoha_phy_pma0_clear_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
+ PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_C_EN);
+ airoha_phy_pma0_clear_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB,
+ PCIE_FORCE_SEL_DA_PXP_CDR_PR_PWDB);
+ airoha_phy_pma0_clear_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+ PCIE_FORCE_SEL_DA_PXP_CDR_PR_IDAC);
+ if (gen == PCIE_PORT_GEN3) {
+ airoha_phy_pma0_update_field(pcie_phy,
+ REG_PCIE_PMA_DIG_RESERVE_14,
+ PCIE_FLL_IDAC_PCIEG3,
+ cdr_pr_idac_tmp);
+ } else {
+ airoha_phy_pma0_update_field(pcie_phy,
+ REG_PCIE_PMA_DIG_RESERVE_13,
+ PCIE_FLL_IDAC_PCIEG1,
+ cdr_pr_idac_tmp);
+ airoha_phy_pma0_update_field(pcie_phy,
+ REG_PCIE_PMA_DIG_RESERVE_13,
+ PCIE_FLL_IDAC_PCIEG2,
+ cdr_pr_idac_tmp);
+ }
+}
+
+static void
+airoha_phy_init_lane1_rx_fw_pre_calib(struct airoha_pcie_phy *pcie_phy,
+ enum airoha_pcie_port_gen gen)
+{
+ u32 fl_out_target = gen == PCIE_PORT_GEN3 ? 41600 : 41941;
+ u32 lock_cyclecnt = gen == PCIE_PORT_GEN3 ? 26000 : 32767;
+ u32 pr_idac, val, cdr_pr_idac_tmp = 0;
+ int i;
+
+ airoha_phy_pma1_set_bits(pcie_phy,
+ REG_PCIE_PMA_SS_LCPLL_PWCTL_SETTING_1,
+ PCIE_LCPLL_MAN_PWDB);
+ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET2,
+ PCIE_LOCK_TARGET_BEG,
+ fl_out_target - 100);
+ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET2,
+ PCIE_LOCK_TARGET_END,
+ fl_out_target + 100);
+ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET1,
+ PCIE_PLL_FT_LOCK_CYCLECNT, lock_cyclecnt);
+ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET4,
+ PCIE_LOCK_LOCKTH, 0x3);
+ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET3,
+ PCIE_UNLOCK_TARGET_BEG,
+ fl_out_target - 100);
+ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET3,
+ PCIE_UNLOCK_TARGET_END,
+ fl_out_target + 100);
+ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET1,
+ PCIE_PLL_FT_UNLOCK_CYCLECNT,
+ lock_cyclecnt);
+ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET4,
+ PCIE_UNLOCK_LOCKTH, 0x3);
+
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CDR1_PR_INJ_MODE,
+ CSR_2L_PXP_CDR1_INJ_FORCE_OFF);
+
+ airoha_phy_pma1_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
+ PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_R_EN);
+ airoha_phy_pma1_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
+ PCIE_FORCE_DA_PXP_CDR_PR_LPF_R_EN);
+ airoha_phy_pma1_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
+ PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_C_EN);
+ airoha_phy_pma1_clear_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
+ PCIE_FORCE_DA_PXP_CDR_PR_LPF_C_EN);
+ airoha_phy_pma1_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+ PCIE_FORCE_SEL_DA_PXP_CDR_PR_IDAC);
+ airoha_phy_pma1_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB,
+ PCIE_FORCE_SEL_DA_PXP_CDR_PR_PWDB);
+ airoha_phy_pma1_clear_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB,
+ PCIE_FORCE_DA_PXP_CDR_PR_PWDB);
+ airoha_phy_pma1_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB,
+ PCIE_FORCE_DA_PXP_CDR_PR_PWDB);
+
+ for (i = 0; i < LEQ_LEN_CTRL_MAX_VAL; i++) {
+ airoha_phy_pma1_update_field(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+ PCIE_FORCE_DA_PXP_CDR_PR_IDAC, i << 8);
+ airoha_phy_pma1_clear_bits(pcie_phy,
+ REG_PCIE_PMA_SS_RX_FREQ_DET4,
+ PCIE_FREQLOCK_DET_EN);
+ airoha_phy_pma1_update_field(pcie_phy,
+ REG_PCIE_PMA_SS_RX_FREQ_DET4,
+ PCIE_FREQLOCK_DET_EN, 0x3);
+
+ usleep_range(10000, 15000);
+
+ val = FIELD_GET(PCIE_RO_FL_OUT,
+ readl(pcie_phy->pma1 +
+ REG_PCIE_PMA_RO_RX_FREQDET));
+ if (val > fl_out_target)
+ cdr_pr_idac_tmp = i << 8;
+ }
+
+ for (i = LEQ_LEN_CTRL_MAX_VAL; i >= 0; i--) {
+ pr_idac = cdr_pr_idac_tmp | (0x1 << i);
+ airoha_phy_pma1_update_field(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+ PCIE_FORCE_DA_PXP_CDR_PR_IDAC, pr_idac);
+ airoha_phy_pma1_clear_bits(pcie_phy,
+ REG_PCIE_PMA_SS_RX_FREQ_DET4,
+ PCIE_FREQLOCK_DET_EN);
+ airoha_phy_pma1_update_field(pcie_phy,
+ REG_PCIE_PMA_SS_RX_FREQ_DET4,
+ PCIE_FREQLOCK_DET_EN, 0x3);
+
+ usleep_range(10000, 15000);
+
+ val = FIELD_GET(PCIE_RO_FL_OUT,
+ readl(pcie_phy->pma1 +
+ REG_PCIE_PMA_RO_RX_FREQDET));
+ if (val < fl_out_target)
+ pr_idac &= ~(0x1 << i);
+
+ cdr_pr_idac_tmp = pr_idac;
+ }
+
+ airoha_phy_pma1_update_field(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+ PCIE_FORCE_DA_PXP_CDR_PR_IDAC,
+ cdr_pr_idac_tmp);
+
+ for (i = 0; i < FREQ_LOCK_MAX_ATTEMPT; i++) {
+ u32 val;
+
+ airoha_phy_pma1_clear_bits(pcie_phy,
+ REG_PCIE_PMA_SS_RX_FREQ_DET4,
+ PCIE_FREQLOCK_DET_EN);
+ airoha_phy_pma1_update_field(pcie_phy,
+ REG_PCIE_PMA_SS_RX_FREQ_DET4,
+ PCIE_FREQLOCK_DET_EN, 0x3);
+
+ usleep_range(10000, 15000);
+
+ val = readl(pcie_phy->pma1 + REG_PCIE_PMA_RO_RX_FREQDET);
+ if (val & PCIE_RO_FBCK_LOCK)
+ break;
+ }
+
+ /* turn off force mode and update band values */
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR1_PR_INJ_MODE,
+ CSR_2L_PXP_CDR1_INJ_FORCE_OFF);
+
+ airoha_phy_pma1_clear_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
+ PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_R_EN);
+ airoha_phy_pma1_clear_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
+ PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_C_EN);
+ airoha_phy_pma1_clear_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB,
+ PCIE_FORCE_SEL_DA_PXP_CDR_PR_PWDB);
+ airoha_phy_pma1_clear_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+ PCIE_FORCE_SEL_DA_PXP_CDR_PR_IDAC);
+ if (gen == PCIE_PORT_GEN3) {
+ airoha_phy_pma1_update_field(pcie_phy,
+ REG_PCIE_PMA_DIG_RESERVE_14,
+ PCIE_FLL_IDAC_PCIEG3,
+ cdr_pr_idac_tmp);
+ } else {
+ airoha_phy_pma1_update_field(pcie_phy,
+ REG_PCIE_PMA_DIG_RESERVE_13,
+ PCIE_FLL_IDAC_PCIEG1,
+ cdr_pr_idac_tmp);
+ airoha_phy_pma1_update_field(pcie_phy,
+ REG_PCIE_PMA_DIG_RESERVE_13,
+ PCIE_FLL_IDAC_PCIEG2,
+ cdr_pr_idac_tmp);
+ }
+}
+
+static void airoha_pcie_phy_init_default(struct airoha_pcie_phy *pcie_phy)
+{
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CMN,
+ CSR_2L_PXP_CMN_TRIM_MASK, 0x10);
+ writel(0xcccbcccb, pcie_phy->pma0 + REG_PCIE_PMA_DIG_RESERVE_21);
+ writel(0xcccb, pcie_phy->pma0 + REG_PCIE_PMA_DIG_RESERVE_22);
+ writel(0xcccbcccb, pcie_phy->pma1 + REG_PCIE_PMA_DIG_RESERVE_21);
+ writel(0xcccb, pcie_phy->pma1 + REG_PCIE_PMA_DIG_RESERVE_22);
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CMN,
+ CSR_2L_PXP_CMN_LANE_EN);
+}
+
+static void airoha_pcie_phy_init_clk_out(struct airoha_pcie_phy *pcie_phy)
+{
+ airoha_phy_csr_2l_update_field(pcie_phy,
+ REG_CSR_2L_TXPLL_POSTDIV_D256,
+ CSR_2L_PXP_CLKTX0_AMP, 0x5);
+ airoha_phy_csr_2l_update_field(pcie_phy,
+ REG_CSR_2L_CLKTX0_FORCE_OUT1,
+ CSR_2L_PXP_CLKTX1_AMP, 0x5);
+ airoha_phy_csr_2l_update_field(pcie_phy,
+ REG_CSR_2L_TXPLL_POSTDIV_D256,
+ CSR_2L_PXP_CLKTX0_OFFSET, 0x2);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CLKTX1_OFFSET,
+ CSR_2L_PXP_CLKTX1_OFFSET, 0x2);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CLKTX0_FORCE_OUT1,
+ CSR_2L_PXP_CLKTX0_HZ);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CLKTX1_OFFSET,
+ CSR_2L_PXP_CLKTX1_HZ);
+ airoha_phy_csr_2l_update_field(pcie_phy,
+ REG_CSR_2L_CLKTX0_FORCE_OUT1,
+ CSR_2L_PXP_CLKTX0_IMP_SEL, 0x12);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CLKTX1_IMP_SEL,
+ CSR_2L_PXP_CLKTX1_IMP_SEL, 0x12);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_POSTDIV_D256,
+ CSR_2L_PXP_CLKTX0_SR);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CLKTX1_OFFSET,
+ CSR_2L_PXP_CLKTX1_SR);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_PLL_CMN_RESERVE0,
+ CSR_2L_PXP_PLL_RESERVE_MASK, 0xd0d);
+}
+
+static void airoha_pcie_phy_init_csr_2l(struct airoha_pcie_phy *pcie_phy)
+{
+ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_SW_RESET,
+ PCIE_SW_XFI_RXPCS_RST | PCIE_SW_REF_RST |
+ PCIE_SW_RX_RST);
+ airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_SW_RESET,
+ PCIE_SW_XFI_RXPCS_RST | PCIE_SW_REF_RST |
+ PCIE_SW_RX_RST);
+ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_TX_RESET,
+ PCIE_TX_TOP_RST | PCIE_TX_CAL_RST);
+ airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_TX_RESET,
+ PCIE_TX_TOP_RST | PCIE_TX_CAL_RST);
+}
+
+static void airoha_pcie_phy_init_rx(struct airoha_pcie_phy *pcie_phy)
+{
+ writel(0x2a00090b, pcie_phy->pma0 + REG_PCIE_PMA_DIG_RESERVE_17);
+ writel(0x2a00090b, pcie_phy->pma1 + REG_PCIE_PMA_DIG_RESERVE_17);
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CDR0_PR_MONPI,
+ CSR_2L_PXP_CDR0_PR_XFICK_EN);
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CDR1_PR_MONPI,
+ CSR_2L_PXP_CDR1_PR_XFICK_EN);
+ airoha_phy_csr_2l_clear_bits(pcie_phy,
+ REG_CSR_2L_CDR0_PD_PICAL_CKD8_INV,
+ CSR_2L_PXP_CDR0_PD_EDGE_DISABLE);
+ airoha_phy_csr_2l_clear_bits(pcie_phy,
+ REG_CSR_2L_CDR1_PD_PICAL_CKD8_INV,
+ CSR_2L_PXP_CDR1_PD_EDGE_DISABLE);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_PHYCK_DIV,
+ CSR_2L_PXP_RX0_PHYCK_SEL, 0x1);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_PHYCK_DIV,
+ CSR_2L_PXP_RX1_PHYCK_SEL, 0x1);
+}
+
+static void airoha_pcie_phy_init_jcpll(struct airoha_pcie_phy *pcie_phy)
+{
+ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
+ PCIE_FORCE_SEL_DA_PXP_JCPLL_EN);
+ airoha_phy_pma0_clear_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
+ PCIE_FORCE_DA_PXP_JCPLL_EN);
+ airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
+ PCIE_FORCE_SEL_DA_PXP_JCPLL_EN);
+ airoha_phy_pma1_clear_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
+ PCIE_FORCE_DA_PXP_JCPLL_EN);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_TCL_VTP_EN,
+ CSR_2L_PXP_JCPLL_SPARE_LOW, 0x20);
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_RST_DLY,
+ CSR_2L_PXP_JCPLL_RST);
+ writel(0x0, pcie_phy->csr_2l + REG_CSR_2L_JCPLL_SSC_DELTA1);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC_PERIOD,
+ CSR_2L_PXP_JCPLL_SSC_PERIOD);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC,
+ CSR_2L_PXP_JCPLL_SSC_PHASE_INI);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC,
+ CSR_2L_PXP_JCPLL_SSC_TRI_EN);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BR,
+ CSR_2L_PXP_JCPLL_LPF_BR, 0xa);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BR,
+ CSR_2L_PXP_JCPLL_LPF_BP, 0xc);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BR,
+ CSR_2L_PXP_JCPLL_LPF_BC, 0x1f);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BWC,
+ CSR_2L_PXP_JCPLL_LPF_BWC, 0x1e);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BR,
+ CSR_2L_PXP_JCPLL_LPF_BWR, 0xa);
+ airoha_phy_csr_2l_update_field(pcie_phy,
+ REG_CSR_2L_JCPLL_MMD_PREDIV_MODE,
+ CSR_2L_PXP_JCPLL_MMD_PREDIV_MODE,
+ 0x1);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, CSR_2L_PXP_JCPLL_MONCK,
+ CSR_2L_PXP_JCPLL_REFIN_DIV);
+
+ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_VOS,
+ PCIE_FORCE_SEL_DA_PXP_JCPLL_SDM_PCW);
+ airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_VOS,
+ PCIE_FORCE_SEL_DA_PXP_JCPLL_SDM_PCW);
+ airoha_phy_pma0_update_field(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_JCPLL_SDM_PCW,
+ PCIE_FORCE_DA_PXP_JCPLL_SDM_PCW,
+ 0x50000000);
+ airoha_phy_pma1_update_field(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_JCPLL_SDM_PCW,
+ PCIE_FORCE_DA_PXP_JCPLL_SDM_PCW,
+ 0x50000000);
+
+ airoha_phy_csr_2l_set_bits(pcie_phy,
+ REG_CSR_2L_JCPLL_MMD_PREDIV_MODE,
+ CSR_2L_PXP_JCPLL_POSTDIV_D5);
+ airoha_phy_csr_2l_set_bits(pcie_phy,
+ REG_CSR_2L_JCPLL_MMD_PREDIV_MODE,
+ CSR_2L_PXP_JCPLL_POSTDIV_D2);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_RST_DLY,
+ CSR_2L_PXP_JCPLL_RST_DLY, 0x4);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_RST_DLY,
+ CSR_2L_PXP_JCPLL_SDM_DI_LS);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_TCL_KBAND_VREF,
+ CSR_2L_PXP_JCPLL_VCO_KBAND_MEAS_EN);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_IB_EXT,
+ CSR_2L_PXP_JCPLL_CHP_IOFST);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_IB_EXT,
+ CSR_2L_PXP_JCPLL_CHP_IBIAS, 0xc);
+ airoha_phy_csr_2l_update_field(pcie_phy,
+ REG_CSR_2L_JCPLL_MMD_PREDIV_MODE,
+ CSR_2L_PXP_JCPLL_MMD_PREDIV_MODE,
+ 0x1);
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_VCODIV,
+ CSR_2L_PXP_JCPLL_VCO_HALFLSB_EN);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_VCODIV,
+ CSR_2L_PXP_JCPLL_VCO_CFIX, 0x1);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_VCODIV,
+ CSR_2L_PXP_JCPLL_VCO_SCAPWR, 0x4);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_IB_EXT,
+ REG_CSR_2L_JCPLL_LPF_SHCK_EN);
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_KBAND_KFC,
+ CSR_2L_PXP_JCPLL_POSTDIV_EN);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_KBAND_KFC,
+ CSR_2L_PXP_JCPLL_KBAND_KFC);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_KBAND_KFC,
+ CSR_2L_PXP_JCPLL_KBAND_KF, 0x3);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_KBAND_KFC,
+ CSR_2L_PXP_JCPLL_KBAND_KS);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BWC,
+ CSR_2L_PXP_JCPLL_KBAND_DIV, 0x1);
+
+ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_SCAN_MODE,
+ PCIE_FORCE_SEL_DA_PXP_JCPLL_KBAND_LOAD_EN);
+ airoha_phy_pma0_clear_bits(pcie_phy, REG_PCIE_PMA_SCAN_MODE,
+ PCIE_FORCE_DA_PXP_JCPLL_KBAND_LOAD_EN);
+
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BWC,
+ CSR_2L_PXP_JCPLL_KBAND_CODE, 0xe4);
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SDM_HREN,
+ CSR_2L_PXP_JCPLL_TCL_AMP_EN);
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_TCL_CMP,
+ CSR_2L_PXP_JCPLL_TCL_LPF_EN);
+ airoha_phy_csr_2l_update_field(pcie_phy,
+ REG_CSR_2L_JCPLL_TCL_KBAND_VREF,
+ CSR_2L_PXP_JCPLL_TCL_KBAND_VREF, 0xf);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_SDM_HREN,
+ CSR_2L_PXP_JCPLL_TCL_AMP_GAIN, 0x1);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_SDM_HREN,
+ CSR_2L_PXP_JCPLL_TCL_AMP_VREF, 0x5);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_TCL_CMP,
+ CSR_2L_PXP_JCPLL_TCL_LPF_BW, 0x1);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_VCO_TCLVAR,
+ CSR_2L_PXP_JCPLL_VCO_TCLVAR, 0x3);
+
+ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
+ PCIE_FORCE_SEL_DA_PXP_JCPLL_CKOUT_EN);
+ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
+ PCIE_FORCE_DA_PXP_JCPLL_CKOUT_EN);
+ airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
+ PCIE_FORCE_SEL_DA_PXP_JCPLL_CKOUT_EN);
+ airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
+ PCIE_FORCE_DA_PXP_JCPLL_CKOUT_EN);
+ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
+ PCIE_FORCE_SEL_DA_PXP_JCPLL_EN);
+ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
+ PCIE_FORCE_DA_PXP_JCPLL_EN);
+ airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
+ PCIE_FORCE_SEL_DA_PXP_JCPLL_EN);
+ airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
+ PCIE_FORCE_DA_PXP_JCPLL_EN);
+}
+
+static void airoha_pcie_phy_txpll(struct airoha_pcie_phy *pcie_phy)
+{
+ airoha_phy_pma0_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
+ PCIE_FORCE_SEL_DA_PXP_TXPLL_EN);
+ airoha_phy_pma0_clear_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
+ PCIE_FORCE_DA_PXP_TXPLL_EN);
+ airoha_phy_pma1_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
+ PCIE_FORCE_SEL_DA_PXP_TXPLL_EN);
+ airoha_phy_pma1_clear_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
+ PCIE_FORCE_DA_PXP_TXPLL_EN);
+
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TXPLL_REFIN_DIV,
+ CSR_2L_PXP_TXPLL_PLL_RSTB);
+ writel(0x0, pcie_phy->csr_2l + REG_CSR_2L_TXPLL_SSC_DELTA1);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_SSC_PERIOD,
+ CSR_2L_PXP_txpll_SSC_PERIOD);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_CHP_IOFST,
+ CSR_2L_PXP_TXPLL_CHP_IOFST, 0x1);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_750M_SYS_CK,
+ CSR_2L_PXP_TXPLL_CHP_IBIAS, 0x2d);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_REFIN_DIV,
+ CSR_2L_PXP_TXPLL_REFIN_DIV);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_TCL_LPF_BW,
+ CSR_2L_PXP_TXPLL_VCO_CFIX, 0x3);
+
+ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+ PCIE_FORCE_SEL_DA_PXP_TXPLL_SDM_PCW);
+ airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+ PCIE_FORCE_SEL_DA_PXP_TXPLL_SDM_PCW);
+ airoha_phy_pma0_update_field(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_SDM_PCW,
+ PCIE_FORCE_DA_PXP_TXPLL_SDM_PCW,
+ 0xc800000);
+ airoha_phy_pma1_update_field(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_SDM_PCW,
+ PCIE_FORCE_DA_PXP_TXPLL_SDM_PCW,
+ 0xc800000);
+
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_SDM_DI_LS,
+ CSR_2L_PXP_TXPLL_SDM_IFM);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_SSC,
+ CSR_2L_PXP_TXPLL_SSC_PHASE_INI);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_REFIN_DIV,
+ CSR_2L_PXP_TXPLL_RST_DLY, 0x4);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_SDM_DI_LS,
+ CSR_2L_PXP_TXPLL_SDM_DI_LS);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_SDM_DI_LS,
+ CSR_2L_PXP_TXPLL_SDM_ORD, 0x3);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_TCL_KBAND_VREF,
+ CSR_2L_PXP_TXPLL_VCO_KBAND_MEAS_EN);
+ writel(0x0, pcie_phy->csr_2l + REG_CSR_2L_TXPLL_SSC_DELTA1);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_CHP_IOFST,
+ CSR_2L_PXP_TXPLL_LPF_BP, 0x1);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_CHP_IOFST,
+ CSR_2L_PXP_TXPLL_LPF_BC, 0x18);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_CHP_IOFST,
+ CSR_2L_PXP_TXPLL_LPF_BR, 0x5);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_CHP_IOFST,
+ CSR_2L_PXP_TXPLL_CHP_IOFST, 0x1);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_750M_SYS_CK,
+ CSR_2L_PXP_TXPLL_CHP_IBIAS, 0x2d);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_TCL_VTP,
+ CSR_2L_PXP_TXPLL_SPARE_L, 0x1);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_LPF_BWR,
+ CSR_2L_PXP_TXPLL_LPF_BWC);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_POSTDIV,
+ CSR_2L_PXP_TXPLL_MMD_PREDIV_MODE);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_REFIN_DIV,
+ CSR_2L_PXP_TXPLL_REFIN_DIV);
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TXPLL_TCL_LPF_BW,
+ CSR_2L_PXP_TXPLL_VCO_HALFLSB_EN);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_VCO_SCAPWR,
+ CSR_2L_PXP_TXPLL_VCO_SCAPWR, 0x7);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_TCL_LPF_BW,
+ CSR_2L_PXP_TXPLL_VCO_CFIX, 0x3);
+
+ airoha_phy_pma0_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+ PCIE_FORCE_SEL_DA_PXP_TXPLL_SDM_PCW);
+ airoha_phy_pma1_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
+ PCIE_FORCE_SEL_DA_PXP_TXPLL_SDM_PCW);
+
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_SSC,
+ CSR_2L_PXP_TXPLL_SSC_PHASE_INI);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_LPF_BWR,
+ CSR_2L_PXP_TXPLL_LPF_BWR);
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TXPLL_PHY_CK2,
+ CSR_2L_PXP_TXPLL_REFIN_INTERNAL);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_TCL_KBAND_VREF,
+ CSR_2L_PXP_TXPLL_VCO_KBAND_MEAS_EN);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_VTP,
+ CSR_2L_PXP_TXPLL_VTP_EN);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_POSTDIV,
+ CSR_2L_PXP_TXPLL_PHY_CK1_EN);
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TXPLL_PHY_CK2,
+ CSR_2L_PXP_TXPLL_REFIN_INTERNAL);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_SSC,
+ CSR_2L_PXP_TXPLL_SSC_EN);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_750M_SYS_CK,
+ CSR_2L_PXP_TXPLL_LPF_SHCK_EN);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_POSTDIV,
+ CSR_2L_PXP_TXPLL_POSTDIV_EN);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_KBAND_DIV,
+ CSR_2L_PXP_TXPLL_KBAND_KFC);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_KBAND_DIV,
+ CSR_2L_PXP_TXPLL_KBAND_KF, 0x3);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_KBAND_DIV,
+ CSR_2L_PXP_txpll_KBAND_KS, 0x1);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_KBAND_DIV,
+ CSR_2L_PXP_TXPLL_KBAND_DIV, 0x4);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_LPF_BWR,
+ CSR_2L_PXP_TXPLL_KBAND_CODE, 0xe4);
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TXPLL_SDM_OUT,
+ CSR_2L_PXP_TXPLL_TCL_AMP_EN);
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TXPLL_TCL_AMP_VREF,
+ CSR_2L_PXP_TXPLL_TCL_LPF_EN);
+ airoha_phy_csr_2l_update_field(pcie_phy,
+ REG_CSR_2L_TXPLL_TCL_KBAND_VREF,
+ CSR_2L_PXP_TXPLL_TCL_KBAND_VREF, 0xf);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_SDM_OUT,
+ CSR_2L_PXP_TXPLL_TCL_AMP_GAIN, 0x3);
+ airoha_phy_csr_2l_update_field(pcie_phy,
+ REG_CSR_2L_TXPLL_TCL_AMP_VREF,
+ CSR_2L_PXP_TXPLL_TCL_AMP_VREF, 0xb);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_TCL_LPF_BW,
+ CSR_2L_PXP_TXPLL_TCL_LPF_BW, 0x3);
+
+ airoha_phy_pma0_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
+ PCIE_FORCE_SEL_DA_PXP_TXPLL_CKOUT_EN);
+ airoha_phy_pma0_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
+ PCIE_FORCE_DA_PXP_TXPLL_CKOUT_EN);
+ airoha_phy_pma1_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
+ PCIE_FORCE_SEL_DA_PXP_TXPLL_CKOUT_EN);
+ airoha_phy_pma1_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
+ PCIE_FORCE_DA_PXP_TXPLL_CKOUT_EN);
+ airoha_phy_pma0_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
+ PCIE_FORCE_SEL_DA_PXP_TXPLL_EN);
+ airoha_phy_pma0_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
+ PCIE_FORCE_DA_PXP_TXPLL_EN);
+ airoha_phy_pma1_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
+ PCIE_FORCE_SEL_DA_PXP_TXPLL_EN);
+ airoha_phy_pma1_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
+ PCIE_FORCE_DA_PXP_TXPLL_EN);
+}
+
+static void airoha_pcie_phy_init_ssc_jcpll(struct airoha_pcie_phy *pcie_phy)
+{
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_SSC_DELTA1,
+ CSR_2L_PXP_JCPLL_SSC_DELTA1, 0x106);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_SSC_DELTA1,
+ CSR_2L_PXP_JCPLL_SSC_DELTA, 0x106);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_SSC_PERIOD,
+ CSR_2L_PXP_JCPLL_SSC_PERIOD, 0x31b);
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC,
+ CSR_2L_PXP_JCPLL_SSC_PHASE_INI);
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC,
+ CSR_2L_PXP_JCPLL_SSC_EN);
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SDM_IFM,
+ CSR_2L_PXP_JCPLL_SDM_IFM);
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SDM_HREN,
+ CSR_2L_PXP_JCPLL_SDM_HREN);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_RST_DLY,
+ CSR_2L_PXP_JCPLL_SDM_DI_EN);
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC,
+ CSR_2L_PXP_JCPLL_SSC_TRI_EN);
+}
+
+static void
+airoha_pcie_phy_set_rxlan0_signal_detect(struct airoha_pcie_phy *pcie_phy)
+{
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CDR0_PR_COR_HBW,
+ CSR_2L_PXP_CDR0_PR_LDO_FORCE_ON);
+
+ usleep_range(100, 200);
+
+ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_19,
+ PCIE_PCP_RX_REV0_PCIE_GEN1, 0x18b0);
+ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_20,
+ PCIE_PCP_RX_REV0_PCIE_GEN2, 0x18b0);
+ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_20,
+ PCIE_PCP_RX_REV0_PCIE_GEN3, 0x1030);
+
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_SIGDET_DCTEST,
+ CSR_2L_PXP_RX0_SIGDET_PEAK, 0x2);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_SIGDET_VTH_SEL,
+ CSR_2L_PXP_RX0_SIGDET_VTH_SEL, 0x5);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_REV0,
+ CSR_2L_PXP_VOS_PNINV, 0x2);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_SIGDET_DCTEST,
+ CSR_2L_PXP_RX0_SIGDET_LPF_CTRL, 0x1);
+
+ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_CAL2,
+ PCIE_CAL_OUT_OS, 0x0);
+
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_PXP_RX0_FE_VB_EQ2,
+ CSR_2L_PXP_RX0_FE_VCM_GEN_PWDB);
+
+ airoha_phy_pma0_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_GAIN_CTRL,
+ PCIE_FORCE_SEL_DA_PXP_RX_FE_PWDB);
+ airoha_phy_pma0_update_field(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_GAIN_CTRL,
+ PCIE_FORCE_DA_PXP_RX_FE_GAIN_CTRL, 0x3);
+ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_RX_FORCE_MODE0,
+ PCIE_FORCE_DA_XPON_RX_FE_GAIN_CTRL, 0x1);
+ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_SIGDET0,
+ PCIE_SIGDET_WIN_NONVLD_TIMES, 0x3);
+ airoha_phy_pma0_clear_bits(pcie_phy, REG_PCIE_PMA_SEQUENCE_DISB_CTRL1,
+ PCIE_DISB_RX_SDCAL_EN);
+
+ airoha_phy_pma0_set_bits(pcie_phy,
+ REG_PCIE_PMA_CTRL_SEQUENCE_FORCE_CTRL1,
+ PCIE_FORCE_RX_SDCAL_EN);
+ usleep_range(150, 200);
+ airoha_phy_pma0_clear_bits(pcie_phy,
+ REG_PCIE_PMA_CTRL_SEQUENCE_FORCE_CTRL1,
+ PCIE_FORCE_RX_SDCAL_EN);
+}
+
+static void
+airoha_pcie_phy_set_rxlan1_signal_detect(struct airoha_pcie_phy *pcie_phy)
+{
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CDR1_PR_COR_HBW,
+ CSR_2L_PXP_CDR1_PR_LDO_FORCE_ON);
+
+ usleep_range(100, 200);
+
+ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_19,
+ PCIE_PCP_RX_REV0_PCIE_GEN1, 0x18b0);
+ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_20,
+ PCIE_PCP_RX_REV0_PCIE_GEN2, 0x18b0);
+ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_20,
+ PCIE_PCP_RX_REV0_PCIE_GEN3, 0x1030);
+
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_SIGDET_NOVTH,
+ CSR_2L_PXP_RX1_SIGDET_PEAK, 0x2);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_SIGDET_NOVTH,
+ CSR_2L_PXP_RX1_SIGDET_VTH_SEL, 0x5);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_REV0,
+ CSR_2L_PXP_VOS_PNINV, 0x2);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_DAC_RANGE_EYE,
+ CSR_2L_PXP_RX1_SIGDET_LPF_CTRL, 0x1);
+
+ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_CAL2,
+ PCIE_CAL_OUT_OS, 0x0);
+
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_RX1_FE_VB_EQ1,
+ CSR_2L_PXP_RX1_FE_VCM_GEN_PWDB);
+
+ airoha_phy_pma1_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_GAIN_CTRL,
+ PCIE_FORCE_SEL_DA_PXP_RX_FE_PWDB);
+ airoha_phy_pma1_update_field(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_GAIN_CTRL,
+ PCIE_FORCE_DA_PXP_RX_FE_GAIN_CTRL, 0x3);
+ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_RX_FORCE_MODE0,
+ PCIE_FORCE_DA_XPON_RX_FE_GAIN_CTRL, 0x1);
+ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_SIGDET0,
+ PCIE_SIGDET_WIN_NONVLD_TIMES, 0x3);
+ airoha_phy_pma1_clear_bits(pcie_phy, REG_PCIE_PMA_SEQUENCE_DISB_CTRL1,
+ PCIE_DISB_RX_SDCAL_EN);
+
+ airoha_phy_pma1_set_bits(pcie_phy,
+ REG_PCIE_PMA_CTRL_SEQUENCE_FORCE_CTRL1,
+ PCIE_FORCE_RX_SDCAL_EN);
+ usleep_range(150, 200);
+ airoha_phy_pma1_clear_bits(pcie_phy,
+ REG_PCIE_PMA_CTRL_SEQUENCE_FORCE_CTRL1,
+ PCIE_FORCE_RX_SDCAL_EN);
+}
+
+static void airoha_pcie_phy_set_rxflow(struct airoha_pcie_phy *pcie_phy)
+{
+ airoha_phy_pma0_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_RX_SCAN_RST,
+ PCIE_FORCE_DA_PXP_RX_SIGDET_PWDB |
+ PCIE_FORCE_SEL_DA_PXP_RX_SIGDET_PWDB);
+ airoha_phy_pma1_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_RX_SCAN_RST,
+ PCIE_FORCE_DA_PXP_RX_SIGDET_PWDB |
+ PCIE_FORCE_SEL_DA_PXP_RX_SIGDET_PWDB);
+
+ airoha_phy_pma0_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PD_PWDB,
+ PCIE_FORCE_DA_PXP_CDR_PD_PWDB |
+ PCIE_FORCE_SEL_DA_PXP_CDR_PD_PWDB);
+ airoha_phy_pma0_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_PWDB,
+ PCIE_FORCE_DA_PXP_RX_FE_PWDB |
+ PCIE_FORCE_SEL_DA_PXP_RX_FE_PWDB);
+ airoha_phy_pma1_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PD_PWDB,
+ PCIE_FORCE_DA_PXP_CDR_PD_PWDB |
+ PCIE_FORCE_SEL_DA_PXP_CDR_PD_PWDB);
+ airoha_phy_pma1_set_bits(pcie_phy,
+ REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_PWDB,
+ PCIE_FORCE_DA_PXP_RX_FE_PWDB |
+ PCIE_FORCE_SEL_DA_PXP_RX_FE_PWDB);
+
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_RX0_PHYCK_DIV,
+ CSR_2L_PXP_RX0_PHYCK_RSTB |
+ CSR_2L_PXP_RX0_TDC_CK_SEL);
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_RX1_PHYCK_DIV,
+ CSR_2L_PXP_RX1_PHYCK_RSTB |
+ CSR_2L_PXP_RX1_TDC_CK_SEL);
+
+ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_SW_RESET,
+ PCIE_SW_RX_FIFO_RST | PCIE_SW_TX_RST |
+ PCIE_SW_PMA_RST | PCIE_SW_ALLPCS_RST |
+ PCIE_SW_TX_FIFO_RST);
+ airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_SW_RESET,
+ PCIE_SW_RX_FIFO_RST | PCIE_SW_TX_RST |
+ PCIE_SW_PMA_RST | PCIE_SW_ALLPCS_RST |
+ PCIE_SW_TX_FIFO_RST);
+
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_PXP_RX0_FE_VB_EQ2,
+ CSR_2L_PXP_RX0_FE_VB_EQ2_EN |
+ CSR_2L_PXP_RX0_FE_VB_EQ3_EN);
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_RX0_SIGDET_VTH_SEL,
+ CSR_2L_PXP_RX0_FE_VB_EQ1_EN);
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_RX1_FE_VB_EQ1,
+ CSR_2L_PXP_RX1_FE_VB_EQ1_EN |
+ CSR_2L_PXP_RX1_FE_VB_EQ2_EN |
+ CSR_2L_PXP_RX1_FE_VB_EQ3_EN);
+
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_REV0,
+ CSR_2L_PXP_FE_GAIN_NORMAL_MODE, 0x4);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_REV0,
+ CSR_2L_PXP_FE_GAIN_TRAIN_MODE, 0x4);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_REV0,
+ CSR_2L_PXP_FE_GAIN_NORMAL_MODE, 0x4);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_REV0,
+ CSR_2L_PXP_FE_GAIN_TRAIN_MODE, 0x4);
+}
+
+static void airoha_pcie_phy_set_pr(struct airoha_pcie_phy *pcie_phy)
+{
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR0_PR_VREG_IBAND,
+ CSR_2L_PXP_CDR0_PR_VREG_IBAND, 0x5);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR0_PR_VREG_IBAND,
+ CSR_2L_PXP_CDR0_PR_VREG_CKBUF, 0x5);
+
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR0_PR_CKREF_DIV,
+ CSR_2L_PXP_CDR0_PR_CKREF_DIV);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR0_PR_COR_HBW,
+ CSR_2L_PXP_CDR0_PR_CKREF_DIV1);
+
+ airoha_phy_csr_2l_update_field(pcie_phy,
+ REG_CSR_2L_CDR1_PR_VREG_IBAND_VAL,
+ CSR_2L_PXP_CDR1_PR_VREG_IBAND, 0x5);
+ airoha_phy_csr_2l_update_field(pcie_phy,
+ REG_CSR_2L_CDR1_PR_VREG_IBAND_VAL,
+ CSR_2L_PXP_CDR1_PR_VREG_CKBUF, 0x5);
+
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR1_PR_CKREF_DIV,
+ CSR_2L_PXP_CDR1_PR_CKREF_DIV);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR1_PR_COR_HBW,
+ CSR_2L_PXP_CDR1_PR_CKREF_DIV1);
+
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR0_LPF_RATIO,
+ CSR_2L_PXP_CDR0_LPF_TOP_LIM, 0x20000);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR1_LPF_RATIO,
+ CSR_2L_PXP_CDR1_LPF_TOP_LIM, 0x20000);
+
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR0_PR_BETA_DAC,
+ CSR_2L_PXP_CDR0_PR_BETA_SEL, 0x2);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR1_PR_BETA_DAC,
+ CSR_2L_PXP_CDR1_PR_BETA_SEL, 0x2);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR0_PR_BETA_DAC,
+ CSR_2L_PXP_CDR0_PR_KBAND_DIV, 0x4);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR1_PR_BETA_DAC,
+ CSR_2L_PXP_CDR1_PR_KBAND_DIV, 0x4);
+}
+
+static void airoha_pcie_phy_set_txflow(struct airoha_pcie_phy *pcie_phy)
+{
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TX0_CKLDO,
+ CSR_2L_PXP_TX0_CKLDO_EN);
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TX1_CKLDO,
+ CSR_2L_PXP_TX1_CKLDO_EN);
+
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TX0_CKLDO,
+ CSR_2L_PXP_TX0_DMEDGEGEN_EN);
+ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TX1_CKLDO,
+ CSR_2L_PXP_TX1_DMEDGEGEN_EN);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TX1_MULTLANE,
+ CSR_2L_PXP_TX1_MULTLANE_EN);
+}
+
+static void airoha_pcie_phy_set_rx_mode(struct airoha_pcie_phy *pcie_phy)
+{
+ writel(0x804000, pcie_phy->pma0 + REG_PCIE_PMA_DIG_RESERVE_27);
+ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_18,
+ PCIE_PXP_RX_VTH_SEL_PCIE_G1, 0x5);
+ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_18,
+ PCIE_PXP_RX_VTH_SEL_PCIE_G2, 0x5);
+ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_18,
+ PCIE_PXP_RX_VTH_SEL_PCIE_G3, 0x5);
+ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_30,
+ 0x77700);
+
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR0_PR_MONCK,
+ CSR_2L_PXP_CDR0_PR_MONCK_ENABLE);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR0_PR_MONCK,
+ CSR_2L_PXP_CDR0_PR_RESERVE0, 0x2);
+ airoha_phy_csr_2l_update_field(pcie_phy,
+ REG_CSR_2L_PXP_RX0_OSCAL_CTLE1IOS,
+ CSR_2L_PXP_RX0_PR_OSCAL_VGA1IOS, 0x19);
+ airoha_phy_csr_2l_update_field(pcie_phy,
+ REG_CSR_2L_PXP_RX0_OSCA_VGA1VOS,
+ CSR_2L_PXP_RX0_PR_OSCAL_VGA1VOS, 0x19);
+ airoha_phy_csr_2l_update_field(pcie_phy,
+ REG_CSR_2L_PXP_RX0_OSCA_VGA1VOS,
+ CSR_2L_PXP_RX0_PR_OSCAL_VGA2IOS, 0x14);
+
+ writel(0x804000, pcie_phy->pma1 + REG_PCIE_PMA_DIG_RESERVE_27);
+ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_18,
+ PCIE_PXP_RX_VTH_SEL_PCIE_G1, 0x5);
+ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_18,
+ PCIE_PXP_RX_VTH_SEL_PCIE_G2, 0x5);
+ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_18,
+ PCIE_PXP_RX_VTH_SEL_PCIE_G3, 0x5);
+
+ airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_30,
+ 0x77700);
+
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR1_PR_MONCK,
+ CSR_2L_PXP_CDR1_PR_MONCK_ENABLE);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR1_PR_MONCK,
+ CSR_2L_PXP_CDR1_PR_RESERVE0, 0x2);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_OSCAL_VGA1IOS,
+ CSR_2L_PXP_RX1_PR_OSCAL_VGA1IOS, 0x19);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_OSCAL_VGA1IOS,
+ CSR_2L_PXP_RX1_PR_OSCAL_VGA1VOS, 0x19);
+ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_OSCAL_VGA1IOS,
+ CSR_2L_PXP_RX1_PR_OSCAL_VGA2IOS, 0x14);
+}
+
+static void airoha_pcie_phy_load_kflow(struct airoha_pcie_phy *pcie_phy)
+{
+ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_12,
+ PCIE_FORCE_PMA_RX_SPEED, 0xa);
+ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_12,
+ PCIE_FORCE_PMA_RX_SPEED, 0xa);
+ airoha_phy_init_lane0_rx_fw_pre_calib(pcie_phy, PCIE_PORT_GEN3);
+ airoha_phy_init_lane1_rx_fw_pre_calib(pcie_phy, PCIE_PORT_GEN3);
+
+ airoha_phy_pma0_clear_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_12,
+ PCIE_FORCE_PMA_RX_SPEED);
+ airoha_phy_pma1_clear_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_12,
+ PCIE_FORCE_PMA_RX_SPEED);
+ usleep_range(100, 200);
+
+ airoha_phy_init_lane0_rx_fw_pre_calib(pcie_phy, PCIE_PORT_GEN2);
+ airoha_phy_init_lane1_rx_fw_pre_calib(pcie_phy, PCIE_PORT_GEN2);
+}
+
+/**
+ * airoha_pcie_phy_init() - Initialize the phy
+ * @phy: the phy to be initialized
+ *
+ * Initialize the phy registers.
+ * The hardware settings will be reset during suspend, it should be
+ * reinitialized when the consumer calls phy_init() again on resume.
+ */
+static int airoha_pcie_phy_init(struct phy *phy)
+{
+ struct airoha_pcie_phy *pcie_phy = phy_get_drvdata(phy);
+ u32 val;
+
+ /* Setup Tx-Rx detection time */
+ val = FIELD_PREP(PCIE_XTP_RXDET_VCM_OFF_STB_T_SEL, 0x33) |
+ FIELD_PREP(PCIE_XTP_RXDET_EN_STB_T_SEL, 0x1) |
+ FIELD_PREP(PCIE_XTP_RXDET_FINISH_STB_T_SEL, 0x2) |
+ FIELD_PREP(PCIE_XTP_TXPD_TX_DATA_EN_DLY, 0x3) |
+ FIELD_PREP(PCIE_XTP_RXDET_LATCH_STB_T_SEL, 0x1);
+ writel(val, pcie_phy->p0_xr_dtime + REG_PCIE_PEXTP_DIG_GLB44);
+ writel(val, pcie_phy->p1_xr_dtime + REG_PCIE_PEXTP_DIG_GLB44);
+ /* Setup Rx AEQ training time */
+ val = FIELD_PREP(PCIE_XTP_LN_RX_PDOWN_L1P2_EXIT_WAIT, 0x32) |
+ FIELD_PREP(PCIE_XTP_LN_RX_PDOWN_E0_AEQEN_WAIT, 0x5050);
+ writel(val, pcie_phy->rx_aeq + REG_PCIE_PEXTP_DIG_LN_RX30_P0);
+ writel(val, pcie_phy->rx_aeq + REG_PCIE_PEXTP_DIG_LN_RX30_P1);
+
+ /* enable load FLL-K flow */
+ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_14,
+ PCIE_FLL_LOAD_EN);
+ airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_14,
+ PCIE_FLL_LOAD_EN);
+
+ airoha_pcie_phy_init_default(pcie_phy);
+ airoha_pcie_phy_init_clk_out(pcie_phy);
+ airoha_pcie_phy_init_csr_2l(pcie_phy);
+
+ usleep_range(100, 200);
+
+ airoha_pcie_phy_init_rx(pcie_phy);
+ /* phase 1, no ssc for K TXPLL */
+ airoha_pcie_phy_init_jcpll(pcie_phy);
+
+ usleep_range(500, 600);
+
+ /* TX PLL settings */
+ airoha_pcie_phy_txpll(pcie_phy);
+
+ usleep_range(200, 300);
+
+ /* SSC JCPLL setting */
+ airoha_pcie_phy_init_ssc_jcpll(pcie_phy);
+
+ usleep_range(100, 200);
+
+ /* Rx lan0 signal detect */
+ airoha_pcie_phy_set_rxlan0_signal_detect(pcie_phy);
+ /* Rx lan1 signal detect */
+ airoha_pcie_phy_set_rxlan1_signal_detect(pcie_phy);
+ /* RX FLOW */
+ airoha_pcie_phy_set_rxflow(pcie_phy);
+
+ usleep_range(100, 200);
+
+ airoha_pcie_phy_set_pr(pcie_phy);
+ /* TX FLOW */
+ airoha_pcie_phy_set_txflow(pcie_phy);
+
+ usleep_range(100, 200);
+ /* RX mode setting */
+ airoha_pcie_phy_set_rx_mode(pcie_phy);
+ /* Load K-Flow */
+ airoha_pcie_phy_load_kflow(pcie_phy);
+ airoha_phy_pma0_clear_bits(pcie_phy, REG_PCIE_PMA_SS_DA_XPON_PWDB0,
+ PCIE_DA_XPON_CDR_PR_PWDB);
+ airoha_phy_pma1_clear_bits(pcie_phy, REG_PCIE_PMA_SS_DA_XPON_PWDB0,
+ PCIE_DA_XPON_CDR_PR_PWDB);
+
+ usleep_range(100, 200);
+
+ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_SS_DA_XPON_PWDB0,
+ PCIE_DA_XPON_CDR_PR_PWDB);
+ airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_SS_DA_XPON_PWDB0,
+ PCIE_DA_XPON_CDR_PR_PWDB);
+
+ /* Wait for the PCIe PHY to complete initialization before returning */
+ msleep(PHY_HW_INIT_TIME_MS);
+
+ return 0;
+}
+
+static int airoha_pcie_phy_exit(struct phy *phy)
+{
+ struct airoha_pcie_phy *pcie_phy = phy_get_drvdata(phy);
+
+ airoha_phy_pma0_clear_bits(pcie_phy, REG_PCIE_PMA_SW_RESET,
+ PCIE_PMA_SW_RST);
+ airoha_phy_pma1_clear_bits(pcie_phy, REG_PCIE_PMA_SW_RESET,
+ PCIE_PMA_SW_RST);
+ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC,
+ CSR_2L_PXP_JCPLL_SSC_PHASE_INI |
+ CSR_2L_PXP_JCPLL_SSC_TRI_EN |
+ CSR_2L_PXP_JCPLL_SSC_EN);
+
+ return 0;
+}
+
+static const struct phy_ops airoha_pcie_phy_ops = {
+ .init = airoha_pcie_phy_init,
+ .exit = airoha_pcie_phy_exit,
+ .owner = THIS_MODULE,
+};
+
+static int airoha_pcie_phy_probe(struct platform_device *pdev)
+{
+ struct airoha_pcie_phy *pcie_phy;
+ struct device *dev = &pdev->dev;
+ struct phy_provider *provider;
+
+ pcie_phy = devm_kzalloc(dev, sizeof(*pcie_phy), GFP_KERNEL);
+ if (!pcie_phy)
+ return -ENOMEM;
+
+ pcie_phy->csr_2l = devm_platform_ioremap_resource_byname(pdev, "csr-2l");
+ if (IS_ERR(pcie_phy->csr_2l))
+ return dev_err_probe(dev, PTR_ERR(pcie_phy->csr_2l),
+ "Failed to map phy-csr-2l base\n");
+
+ pcie_phy->pma0 = devm_platform_ioremap_resource_byname(pdev, "pma0");
+ if (IS_ERR(pcie_phy->pma0))
+ return dev_err_probe(dev, PTR_ERR(pcie_phy->pma0),
+ "Failed to map phy-pma0 base\n");
+
+ pcie_phy->pma1 = devm_platform_ioremap_resource_byname(pdev, "pma1");
+ if (IS_ERR(pcie_phy->pma1))
+ return dev_err_probe(dev, PTR_ERR(pcie_phy->pma1),
+ "Failed to map phy-pma1 base\n");
+
+ pcie_phy->phy = devm_phy_create(dev, dev->of_node, &airoha_pcie_phy_ops);
+ if (IS_ERR(pcie_phy->phy))
+ return dev_err_probe(dev, PTR_ERR(pcie_phy->phy),
+ "Failed to create PCIe phy\n");
+
+ pcie_phy->p0_xr_dtime =
+ devm_platform_ioremap_resource_byname(pdev, "p0-xr-dtime");
+ if (IS_ERR(pcie_phy->p0_xr_dtime))
+ return dev_err_probe(dev, PTR_ERR(pcie_phy->p0_xr_dtime),
+ "Failed to map P0 Tx-Rx dtime base\n");
+
+ pcie_phy->p1_xr_dtime =
+ devm_platform_ioremap_resource_byname(pdev, "p1-xr-dtime");
+ if (IS_ERR(pcie_phy->p1_xr_dtime))
+ return dev_err_probe(dev, PTR_ERR(pcie_phy->p1_xr_dtime),
+ "Failed to map P1 Tx-Rx dtime base\n");
+
+ pcie_phy->rx_aeq = devm_platform_ioremap_resource_byname(pdev, "rx-aeq");
+ if (IS_ERR(pcie_phy->rx_aeq))
+ return dev_err_probe(dev, PTR_ERR(pcie_phy->rx_aeq),
+ "Failed to map Rx AEQ base\n");
+
+ pcie_phy->dev = dev;
+ phy_set_drvdata(pcie_phy->phy, pcie_phy);
+
+ provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+ if (IS_ERR(provider))
+ return dev_err_probe(dev, PTR_ERR(provider),
+ "PCIe phy probe failed\n");
+
+ return 0;
+}
+
+static const struct of_device_id airoha_pcie_phy_of_match[] = {
+ { .compatible = "airoha,en7581-pcie-phy" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, airoha_pcie_phy_of_match);
+
+static struct platform_driver airoha_pcie_phy_driver = {
+ .probe = airoha_pcie_phy_probe,
+ .driver = {
+ .name = "airoha-pcie-phy",
+ .of_match_table = airoha_pcie_phy_of_match,
+ },
+};
+module_platform_driver(airoha_pcie_phy_driver);
+
+MODULE_DESCRIPTION("Airoha PCIe PHY driver");
+MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index d9be6a4d5383..8dfdce605a90 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -20,7 +20,12 @@
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
-static struct class *phy_class;
+static void phy_release(struct device *dev);
+static const struct class phy_class = {
+ .name = "phy",
+ .dev_release = phy_release,
+};
+
static struct dentry *phy_debugfs_root;
static DEFINE_MUTEX(phy_provider_mutex);
static LIST_HEAD(phy_provider_list);
@@ -140,8 +145,10 @@ static struct phy_provider *of_phy_provider_lookup(struct device_node *node)
return phy_provider;
for_each_child_of_node(phy_provider->children, child)
- if (child == node)
+ if (child == node) {
+ of_node_put(child);
return phy_provider;
+ }
}
return ERR_PTR(-EPROBE_DEFER);
@@ -490,6 +497,53 @@ int phy_calibrate(struct phy *phy)
EXPORT_SYMBOL_GPL(phy_calibrate);
/**
+ * phy_notify_connect() - phy connect notification
+ * @phy: the phy returned by phy_get()
+ * @port: the port index for connect
+ *
+ * If the phy needs to get connection status, the callback can be used.
+ * Returns: %0 if successful, a negative error code otherwise
+ */
+int phy_notify_connect(struct phy *phy, int port)
+{
+ int ret;
+
+ if (!phy || !phy->ops->connect)
+ return 0;
+
+ mutex_lock(&phy->mutex);
+ ret = phy->ops->connect(phy, port);
+ mutex_unlock(&phy->mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(phy_notify_connect);
+
+/**
+ * phy_notify_disconnect() - phy disconnect notification
+ * @phy: the phy returned by phy_get()
+ * @port: the port index for disconnect
+ *
+ * If the phy needs to get connection status, the callback can be used.
+ *
+ * Returns: %0 if successful, a negative error code otherwise
+ */
+int phy_notify_disconnect(struct phy *phy, int port)
+{
+ int ret;
+
+ if (!phy || !phy->ops->disconnect)
+ return 0;
+
+ mutex_lock(&phy->mutex);
+ ret = phy->ops->disconnect(phy, port);
+ mutex_unlock(&phy->mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(phy_notify_disconnect);
+
+/**
* phy_configure() - Changes the phy parameters
* @phy: the phy returned by phy_get()
* @opts: New configuration to apply
@@ -577,8 +631,10 @@ static struct phy *_of_phy_get(struct device_node *np, int index)
return ERR_PTR(-ENODEV);
/* This phy type handled by the usb-phy subsystem for now */
- if (of_device_is_compatible(args.np, "usb-nop-xceiv"))
- return ERR_PTR(-ENODEV);
+ if (of_device_is_compatible(args.np, "usb-nop-xceiv")) {
+ phy = ERR_PTR(-ENODEV);
+ goto out_put_node;
+ }
mutex_lock(&phy_provider_mutex);
phy_provider = of_phy_provider_lookup(args.np);
@@ -600,6 +656,7 @@ out_put_module:
out_unlock:
mutex_unlock(&phy_provider_mutex);
+out_put_node:
of_node_put(args.np);
return phy;
@@ -612,7 +669,7 @@ out_unlock:
*
* Returns the phy driver, after getting a refcount to it; or
* -ENODEV if there is no such phy. The caller is responsible for
- * calling phy_put() to release that count.
+ * calling of_phy_put() to release that count.
*/
struct phy *of_phy_get(struct device_node *np, const char *con_id)
{
@@ -685,39 +742,32 @@ void devm_phy_put(struct device *dev, struct phy *phy)
if (!phy)
return;
- r = devres_destroy(dev, devm_phy_release, devm_phy_match, phy);
+ r = devres_release(dev, devm_phy_release, devm_phy_match, phy);
dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");
}
EXPORT_SYMBOL_GPL(devm_phy_put);
/**
* of_phy_simple_xlate() - returns the phy instance from phy provider
- * @dev: the PHY provider device
- * @args: of_phandle_args (not used here)
+ * @dev: the PHY provider device (not used here)
+ * @args: of_phandle_args
*
* Intended to be used by phy provider for the common case where #phy-cells is
* 0. For other cases where #phy-cells is greater than '0', the phy provider
* should provide a custom of_xlate function that reads the *args* and returns
* the appropriate phy.
*/
-struct phy *of_phy_simple_xlate(struct device *dev, struct of_phandle_args
- *args)
+struct phy *of_phy_simple_xlate(struct device *dev,
+ const struct of_phandle_args *args)
{
- struct phy *phy;
- struct class_dev_iter iter;
-
- class_dev_iter_init(&iter, phy_class, NULL, NULL);
- while ((dev = class_dev_iter_next(&iter))) {
- phy = to_phy(dev);
- if (args->np != phy->dev.of_node)
- continue;
+ struct device *target_dev;
- class_dev_iter_exit(&iter);
- return phy;
- }
+ target_dev = class_find_device_by_of_node(&phy_class, args->np);
+ if (!target_dev)
+ return ERR_PTR(-ENODEV);
- class_dev_iter_exit(&iter);
- return ERR_PTR(-ENODEV);
+ put_device(target_dev);
+ return to_phy(target_dev);
}
EXPORT_SYMBOL_GPL(of_phy_simple_xlate);
@@ -969,7 +1019,7 @@ struct phy *phy_create(struct device *dev, struct device_node *node,
device_initialize(&phy->dev);
mutex_init(&phy->mutex);
- phy->dev.class = phy_class;
+ phy->dev.class = &phy_class;
phy->dev.parent = dev;
phy->dev.of_node = node ?: dev->of_node;
phy->id = id;
@@ -1069,7 +1119,7 @@ void devm_phy_destroy(struct device *dev, struct phy *phy)
{
int r;
- r = devres_destroy(dev, devm_phy_consume, devm_phy_match, phy);
+ r = devres_release(dev, devm_phy_consume, devm_phy_match, phy);
dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");
}
EXPORT_SYMBOL_GPL(devm_phy_destroy);
@@ -1095,7 +1145,7 @@ EXPORT_SYMBOL_GPL(devm_phy_destroy);
struct phy_provider *__of_phy_provider_register(struct device *dev,
struct device_node *children, struct module *owner,
struct phy * (*of_xlate)(struct device *dev,
- struct of_phandle_args *args))
+ const struct of_phandle_args *args))
{
struct phy_provider *phy_provider;
@@ -1158,7 +1208,7 @@ EXPORT_SYMBOL_GPL(__of_phy_provider_register);
struct phy_provider *__devm_of_phy_provider_register(struct device *dev,
struct device_node *children, struct module *owner,
struct phy * (*of_xlate)(struct device *dev,
- struct of_phandle_args *args))
+ const struct of_phandle_args *args))
{
struct phy_provider **ptr, *phy_provider;
@@ -1207,12 +1257,12 @@ EXPORT_SYMBOL_GPL(of_phy_provider_unregister);
* of_phy_provider_unregister to unregister the phy provider.
*/
void devm_of_phy_provider_unregister(struct device *dev,
- struct phy_provider *phy_provider)
+ struct phy_provider *phy_provider)
{
int r;
- r = devres_destroy(dev, devm_phy_provider_release, devm_phy_match,
- phy_provider);
+ r = devres_release(dev, devm_phy_provider_release, devm_phy_match,
+ phy_provider);
dev_WARN_ONCE(dev, r, "couldn't find PHY provider device resource\n");
}
EXPORT_SYMBOL_GPL(devm_of_phy_provider_unregister);
@@ -1238,14 +1288,13 @@ static void phy_release(struct device *dev)
static int __init phy_core_init(void)
{
- phy_class = class_create("phy");
- if (IS_ERR(phy_class)) {
- pr_err("failed to create phy class --> %ld\n",
- PTR_ERR(phy_class));
- return PTR_ERR(phy_class);
- }
+ int err;
- phy_class->dev_release = phy_release;
+ err = class_register(&phy_class);
+ if (err) {
+ pr_err("failed to register phy class");
+ return err;
+ }
phy_debugfs_root = debugfs_create_dir("phy", NULL);
@@ -1256,6 +1305,6 @@ device_initcall(phy_core_init);
static void __exit phy_core_exit(void)
{
debugfs_remove_recursive(phy_debugfs_root);
- class_destroy(phy_class);
+ class_unregister(&phy_class);
}
module_exit(phy_core_exit);
diff --git a/drivers/phy/phy-lgm-usb.c b/drivers/phy/phy-lgm-usb.c
index 410729c7f513..eb7c6fed20d3 100644
--- a/drivers/phy/phy-lgm-usb.c
+++ b/drivers/phy/phy-lgm-usb.c
@@ -271,7 +271,7 @@ static struct platform_driver lgm_phy_driver = {
.of_match_table = intel_usb_phy_dt_ids,
},
.probe = phy_probe,
- .remove_new = phy_remove,
+ .remove = phy_remove,
};
module_platform_driver(lgm_phy_driver);
diff --git a/drivers/phy/phy-nxp-ptn3222.c b/drivers/phy/phy-nxp-ptn3222.c
new file mode 100644
index 000000000000..c6179d8701e6
--- /dev/null
+++ b/drivers/phy/phy-nxp-ptn3222.c
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2024, Linaro Limited
+ */
+
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+#define NUM_SUPPLIES 2
+
+struct ptn3222 {
+ struct i2c_client *client;
+ struct phy *phy;
+ struct gpio_desc *reset_gpio;
+ struct regulator_bulk_data *supplies;
+};
+
+static int ptn3222_init(struct phy *phy)
+{
+ struct ptn3222 *ptn3222 = phy_get_drvdata(phy);
+ int ret;
+
+ ret = regulator_bulk_enable(NUM_SUPPLIES, ptn3222->supplies);
+ if (ret)
+ return ret;
+
+ gpiod_set_value_cansleep(ptn3222->reset_gpio, 0);
+
+ return 0;
+}
+
+static int ptn3222_exit(struct phy *phy)
+{
+ struct ptn3222 *ptn3222 = phy_get_drvdata(phy);
+
+ gpiod_set_value_cansleep(ptn3222->reset_gpio, 1);
+
+ return regulator_bulk_disable(NUM_SUPPLIES, ptn3222->supplies);
+}
+
+static const struct phy_ops ptn3222_ops = {
+ .init = ptn3222_init,
+ .exit = ptn3222_exit,
+ .owner = THIS_MODULE,
+};
+
+static const struct regulator_bulk_data ptn3222_supplies[NUM_SUPPLIES] = {
+ {
+ .supply = "vdd3v3",
+ .init_load_uA = 11000,
+ }, {
+ .supply = "vdd1v8",
+ .init_load_uA = 55000,
+ }
+};
+
+static int ptn3222_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct phy_provider *phy_provider;
+ struct ptn3222 *ptn3222;
+ int ret;
+
+ ptn3222 = devm_kzalloc(dev, sizeof(*ptn3222), GFP_KERNEL);
+ if (!ptn3222)
+ return -ENOMEM;
+
+ ptn3222->client = client;
+
+ ptn3222->reset_gpio = devm_gpiod_get_optional(dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(ptn3222->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(ptn3222->reset_gpio),
+ "unable to acquire reset gpio\n");
+
+ ret = devm_regulator_bulk_get_const(dev, NUM_SUPPLIES, ptn3222_supplies,
+ &ptn3222->supplies);
+ if (ret)
+ return ret;
+
+ ptn3222->phy = devm_phy_create(dev, dev->of_node, &ptn3222_ops);
+ if (IS_ERR(ptn3222->phy)) {
+ dev_err(dev, "failed to create PHY: %d\n", ret);
+ return PTR_ERR(ptn3222->phy);
+ }
+
+ phy_set_drvdata(ptn3222->phy, ptn3222);
+
+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct i2c_device_id ptn3222_table[] = {
+ { "ptn3222" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ptn3222_table);
+
+static const struct of_device_id ptn3222_of_table[] = {
+ { .compatible = "nxp,ptn3222" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ptn3222_of_table);
+
+static struct i2c_driver ptn3222_driver = {
+ .driver = {
+ .name = "ptn3222",
+ .of_match_table = ptn3222_of_table,
+ },
+ .probe = ptn3222_probe,
+ .id_table = ptn3222_table,
+};
+
+module_i2c_driver(ptn3222_driver);
+
+MODULE_DESCRIPTION("NXP PTN3222 eUSB2 Redriver driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/phy-xgene.c b/drivers/phy/phy-xgene.c
index 1f0f908323f0..5007dc7a357c 100644
--- a/drivers/phy/phy-xgene.c
+++ b/drivers/phy/phy-xgene.c
@@ -1611,7 +1611,7 @@ static const struct phy_ops xgene_phy_ops = {
};
static struct phy *xgene_phy_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct xgene_phy_ctx *ctx = dev_get_drvdata(dev);
diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile
index ffd609ac6233..eb60e950ad53 100644
--- a/drivers/phy/qualcomm/Makefile
+++ b/drivers/phy/qualcomm/Makefile
@@ -7,7 +7,7 @@ obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o
obj-$(CONFIG_PHY_QCOM_M31_USB) += phy-qcom-m31.o
obj-$(CONFIG_PHY_QCOM_PCIE2) += phy-qcom-pcie2.o
-obj-$(CONFIG_PHY_QCOM_QMP_COMBO) += phy-qcom-qmp-combo.o
+obj-$(CONFIG_PHY_QCOM_QMP_COMBO) += phy-qcom-qmp-combo.o phy-qcom-qmp-usbc.o
obj-$(CONFIG_PHY_QCOM_QMP_PCIE) += phy-qcom-qmp-pcie.o
obj-$(CONFIG_PHY_QCOM_QMP_PCIE_8996) += phy-qcom-qmp-pcie-msm8996.o
obj-$(CONFIG_PHY_QCOM_QMP_UFS) += phy-qcom-qmp-ufs.o
diff --git a/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c b/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c
index 3642a5d4f2f3..cae290a6e19f 100644
--- a/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c
+++ b/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c
@@ -257,12 +257,12 @@ static const struct of_device_id qcom_apq8064_sata_phy_of_match[] = {
MODULE_DEVICE_TABLE(of, qcom_apq8064_sata_phy_of_match);
static struct platform_driver qcom_apq8064_sata_phy_driver = {
- .probe = qcom_apq8064_sata_phy_probe,
- .remove_new = qcom_apq8064_sata_phy_remove,
+ .probe = qcom_apq8064_sata_phy_probe,
+ .remove = qcom_apq8064_sata_phy_remove,
.driver = {
- .name = "qcom-apq8064-sata-phy",
- .of_match_table = qcom_apq8064_sata_phy_of_match,
- }
+ .name = "qcom-apq8064-sata-phy",
+ .of_match_table = qcom_apq8064_sata_phy_of_match,
+ },
};
module_platform_driver(qcom_apq8064_sata_phy_driver);
diff --git a/drivers/phy/qualcomm/phy-qcom-edp.c b/drivers/phy/qualcomm/phy-qcom-edp.c
index 8e5078304646..f1b51018683d 100644
--- a/drivers/phy/qualcomm/phy-qcom-edp.c
+++ b/drivers/phy/qualcomm/phy-qcom-edp.c
@@ -14,6 +14,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/phy/phy.h>
+#include <linux/phy/phy-dp.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/reset.h>
@@ -21,7 +22,9 @@
#include <dt-bindings/phy/phy.h>
-#include "phy-qcom-qmp.h"
+#include "phy-qcom-qmp-dp-phy.h"
+#include "phy-qcom-qmp-qserdes-com-v4.h"
+#include "phy-qcom-qmp-qserdes-com-v6.h"
/* EDP_PHY registers */
#define DP_PHY_CFG 0x0010
@@ -29,16 +32,8 @@
#define DP_PHY_PD_CTL 0x001c
#define DP_PHY_MODE 0x0020
-#define DP_PHY_AUX_CFG0 0x0024
-#define DP_PHY_AUX_CFG1 0x0028
-#define DP_PHY_AUX_CFG2 0x002C
-#define DP_PHY_AUX_CFG3 0x0030
-#define DP_PHY_AUX_CFG4 0x0034
-#define DP_PHY_AUX_CFG5 0x0038
-#define DP_PHY_AUX_CFG6 0x003C
-#define DP_PHY_AUX_CFG7 0x0040
-#define DP_PHY_AUX_CFG8 0x0044
-#define DP_PHY_AUX_CFG9 0x0048
+#define DP_AUX_CFG_SIZE 10
+#define DP_PHY_AUX_CFG(n) (0x24 + (0x04 * (n)))
#define DP_PHY_AUX_INTERRUPT_MASK 0x0058
@@ -68,19 +63,33 @@
#define TXn_TRAN_DRVR_EMP_EN 0x0078
-struct qcom_edp_cfg {
- bool is_dp;
-
- /* DP PHY swing and pre_emphasis tables */
+struct qcom_edp_swing_pre_emph_cfg {
const u8 (*swing_hbr_rbr)[4][4];
const u8 (*swing_hbr3_hbr2)[4][4];
const u8 (*pre_emphasis_hbr_rbr)[4][4];
const u8 (*pre_emphasis_hbr3_hbr2)[4][4];
};
+struct qcom_edp;
+
+struct phy_ver_ops {
+ int (*com_power_on)(const struct qcom_edp *edp);
+ int (*com_resetsm_cntrl)(const struct qcom_edp *edp);
+ int (*com_bias_en_clkbuflr)(const struct qcom_edp *edp);
+ int (*com_configure_pll)(const struct qcom_edp *edp);
+ int (*com_configure_ssc)(const struct qcom_edp *edp);
+};
+
+struct qcom_edp_phy_cfg {
+ bool is_edp;
+ const u8 *aux_cfg;
+ const struct qcom_edp_swing_pre_emph_cfg *swing_pre_emph_cfg;
+ const struct phy_ver_ops *ver_ops;
+};
+
struct qcom_edp {
struct device *dev;
- const struct qcom_edp_cfg *cfg;
+ const struct qcom_edp_phy_cfg *cfg;
struct phy *phy;
@@ -96,6 +105,8 @@ struct qcom_edp {
struct clk_bulk_data clks[2];
struct regulator_bulk_data supplies[2];
+
+ bool is_edp;
};
static const u8 dp_swing_hbr_rbr[4][4] = {
@@ -126,8 +137,7 @@ static const u8 dp_pre_emp_hbr2_hbr3[4][4] = {
{ 0x04, 0xff, 0xff, 0xff }
};
-static const struct qcom_edp_cfg dp_phy_cfg = {
- .is_dp = true,
+static const struct qcom_edp_swing_pre_emph_cfg dp_phy_swing_pre_emph_cfg = {
.swing_hbr_rbr = &dp_swing_hbr_rbr,
.swing_hbr3_hbr2 = &dp_swing_hbr2_hbr3,
.pre_emphasis_hbr_rbr = &dp_pre_emp_hbr_rbr,
@@ -162,20 +172,47 @@ static const u8 edp_pre_emp_hbr2_hbr3[4][4] = {
{ 0x00, 0xff, 0xff, 0xff }
};
-static const struct qcom_edp_cfg edp_phy_cfg = {
- .is_dp = false,
+static const struct qcom_edp_swing_pre_emph_cfg edp_phy_swing_pre_emph_cfg = {
.swing_hbr_rbr = &edp_swing_hbr_rbr,
.swing_hbr3_hbr2 = &edp_swing_hbr2_hbr3,
.pre_emphasis_hbr_rbr = &edp_pre_emp_hbr_rbr,
.pre_emphasis_hbr3_hbr2 = &edp_pre_emp_hbr2_hbr3,
};
+static const u8 edp_phy_aux_cfg_v4[10] = {
+ 0x00, 0x13, 0x24, 0x00, 0x0a, 0x26, 0x0a, 0x03, 0x37, 0x03
+};
+
+static const u8 edp_pre_emp_hbr_rbr_v5[4][4] = {
+ { 0x05, 0x11, 0x17, 0x1d },
+ { 0x05, 0x11, 0x18, 0xff },
+ { 0x06, 0x11, 0xff, 0xff },
+ { 0x00, 0xff, 0xff, 0xff }
+};
+
+static const u8 edp_pre_emp_hbr2_hbr3_v5[4][4] = {
+ { 0x0c, 0x15, 0x19, 0x1e },
+ { 0x0b, 0x15, 0x19, 0xff },
+ { 0x0e, 0x14, 0xff, 0xff },
+ { 0x0d, 0xff, 0xff, 0xff }
+};
+
+static const struct qcom_edp_swing_pre_emph_cfg edp_phy_swing_pre_emph_cfg_v5 = {
+ .swing_hbr_rbr = &edp_swing_hbr_rbr,
+ .swing_hbr3_hbr2 = &edp_swing_hbr2_hbr3,
+ .pre_emphasis_hbr_rbr = &edp_pre_emp_hbr_rbr_v5,
+ .pre_emphasis_hbr3_hbr2 = &edp_pre_emp_hbr2_hbr3_v5,
+};
+
+static const u8 edp_phy_aux_cfg_v5[10] = {
+ 0x00, 0x13, 0xa4, 0x00, 0x0a, 0x26, 0x0a, 0x03, 0x37, 0x03
+};
+
static int qcom_edp_phy_init(struct phy *phy)
{
struct qcom_edp *edp = phy_get_drvdata(phy);
- const struct qcom_edp_cfg *cfg = edp->cfg;
+ u8 aux_cfg[DP_AUX_CFG_SIZE];
int ret;
- u8 cfg8;
ret = regulator_bulk_enable(ARRAY_SIZE(edp->supplies), edp->supplies);
if (ret)
@@ -185,12 +222,15 @@ static int qcom_edp_phy_init(struct phy *phy)
if (ret)
goto out_disable_supplies;
+ memcpy(aux_cfg, edp->cfg->aux_cfg, sizeof(aux_cfg));
+
writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
edp->edp + DP_PHY_PD_CTL);
- /* Turn on BIAS current for PHY/PLL */
- writel(0x17, edp->pll + QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN);
+ ret = edp->cfg->ver_ops->com_bias_en_clkbuflr(edp);
+ if (ret)
+ return ret;
writel(DP_PHY_PD_CTL_PSR_PWRDN, edp->edp + DP_PHY_PD_CTL);
msleep(20);
@@ -200,23 +240,18 @@ static int qcom_edp_phy_init(struct phy *phy)
DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
edp->edp + DP_PHY_PD_CTL);
- if (cfg && cfg->is_dp)
- cfg8 = 0xb7;
- else
- cfg8 = 0x37;
+ /*
+ * TODO: Re-work the conditions around setting the cfg8 value
+ * when more information becomes available about why this is
+ * even needed.
+ */
+ if (edp->cfg->swing_pre_emph_cfg && !edp->is_edp)
+ aux_cfg[8] = 0xb7;
writel(0xfc, edp->edp + DP_PHY_MODE);
- writel(0x00, edp->edp + DP_PHY_AUX_CFG0);
- writel(0x13, edp->edp + DP_PHY_AUX_CFG1);
- writel(0x24, edp->edp + DP_PHY_AUX_CFG2);
- writel(0x00, edp->edp + DP_PHY_AUX_CFG3);
- writel(0x0a, edp->edp + DP_PHY_AUX_CFG4);
- writel(0x26, edp->edp + DP_PHY_AUX_CFG5);
- writel(0x0a, edp->edp + DP_PHY_AUX_CFG6);
- writel(0x03, edp->edp + DP_PHY_AUX_CFG7);
- writel(cfg8, edp->edp + DP_PHY_AUX_CFG8);
- writel(0x03, edp->edp + DP_PHY_AUX_CFG9);
+ for (int i = 0; i < DP_AUX_CFG_SIZE; i++)
+ writel(aux_cfg[i], edp->edp + DP_PHY_AUX_CFG(i));
writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK |
PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK |
@@ -234,7 +269,7 @@ out_disable_supplies:
static int qcom_edp_set_voltages(struct qcom_edp *edp, const struct phy_configure_opts_dp *dp_opts)
{
- const struct qcom_edp_cfg *cfg = edp->cfg;
+ const struct qcom_edp_swing_pre_emph_cfg *cfg = edp->cfg->swing_pre_emph_cfg;
unsigned int v_level = 0;
unsigned int p_level = 0;
u8 ldo_config;
@@ -245,6 +280,9 @@ static int qcom_edp_set_voltages(struct qcom_edp *edp, const struct phy_configur
if (!cfg)
return 0;
+ if (edp->is_edp)
+ cfg = &edp_phy_swing_pre_emph_cfg;
+
for (i = 0; i < dp_opts->lanes; i++) {
v_level = max(v_level, dp_opts->voltage[i]);
p_level = max(p_level, dp_opts->pre[i]);
@@ -261,7 +299,7 @@ static int qcom_edp_set_voltages(struct qcom_edp *edp, const struct phy_configur
if (swing == 0xff || emph == 0xff)
return -EINVAL;
- ldo_config = (cfg && cfg->is_dp) ? 0x1 : 0x0;
+ ldo_config = edp->is_edp ? 0x0 : 0x1;
writel(ldo_config, edp->tx0 + TXn_LDO_CONFIG);
writel(swing, edp->tx0 + TXn_TX_DRV_LVL);
@@ -290,6 +328,84 @@ static int qcom_edp_phy_configure(struct phy *phy, union phy_configure_opts *opt
static int qcom_edp_configure_ssc(const struct qcom_edp *edp)
{
+ return edp->cfg->ver_ops->com_configure_ssc(edp);
+}
+
+static int qcom_edp_configure_pll(const struct qcom_edp *edp)
+{
+ return edp->cfg->ver_ops->com_configure_pll(edp);
+}
+
+static int qcom_edp_set_vco_div(const struct qcom_edp *edp, unsigned long *pixel_freq)
+{
+ const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
+ u32 vco_div;
+
+ switch (dp_opts->link_rate) {
+ case 1620:
+ vco_div = 0x1;
+ *pixel_freq = 1620000000UL / 2;
+ break;
+
+ case 2700:
+ vco_div = 0x1;
+ *pixel_freq = 2700000000UL / 2;
+ break;
+
+ case 5400:
+ vco_div = 0x2;
+ *pixel_freq = 5400000000UL / 4;
+ break;
+
+ case 8100:
+ vco_div = 0x0;
+ *pixel_freq = 8100000000UL / 6;
+ break;
+
+ default:
+ /* Other link rates aren't supported */
+ return -EINVAL;
+ }
+
+ writel(vco_div, edp->edp + DP_PHY_VCO_DIV);
+
+ return 0;
+}
+
+static int qcom_edp_phy_power_on_v4(const struct qcom_edp *edp)
+{
+ u32 val;
+
+ writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
+ DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN |
+ DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
+ edp->edp + DP_PHY_PD_CTL);
+ writel(0xfc, edp->edp + DP_PHY_MODE);
+
+ return readl_poll_timeout(edp->pll + QSERDES_V4_COM_CMN_STATUS,
+ val, val & BIT(7), 5, 200);
+}
+
+static int qcom_edp_phy_com_resetsm_cntrl_v4(const struct qcom_edp *edp)
+{
+ u32 val;
+
+ writel(0x20, edp->pll + QSERDES_V4_COM_RESETSM_CNTRL);
+
+ return readl_poll_timeout(edp->pll + QSERDES_V4_COM_C_READY_STATUS,
+ val, val & BIT(0), 500, 10000);
+}
+
+static int qcom_edp_com_bias_en_clkbuflr_v4(const struct qcom_edp *edp)
+{
+ /* Turn on BIAS current for PHY/PLL */
+ writel(0x17, edp->pll + QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN);
+
+ return 0;
+}
+
+static int qcom_edp_com_configure_ssc_v4(const struct qcom_edp *edp)
+{
const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
u32 step1;
u32 step2;
@@ -322,7 +438,7 @@ static int qcom_edp_configure_ssc(const struct qcom_edp *edp)
return 0;
}
-static int qcom_edp_configure_pll(const struct qcom_edp *edp)
+static int qcom_edp_com_configure_pll_v4(const struct qcom_edp *edp)
{
const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
u32 div_frac_start2_mode0;
@@ -408,30 +524,160 @@ static int qcom_edp_configure_pll(const struct qcom_edp *edp)
return 0;
}
-static int qcom_edp_set_vco_div(const struct qcom_edp *edp, unsigned long *pixel_freq)
+static const struct phy_ver_ops qcom_edp_phy_ops_v4 = {
+ .com_power_on = qcom_edp_phy_power_on_v4,
+ .com_resetsm_cntrl = qcom_edp_phy_com_resetsm_cntrl_v4,
+ .com_bias_en_clkbuflr = qcom_edp_com_bias_en_clkbuflr_v4,
+ .com_configure_pll = qcom_edp_com_configure_pll_v4,
+ .com_configure_ssc = qcom_edp_com_configure_ssc_v4,
+};
+
+static const struct qcom_edp_phy_cfg sa8775p_dp_phy_cfg = {
+ .is_edp = false,
+ .aux_cfg = edp_phy_aux_cfg_v5,
+ .swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg_v5,
+ .ver_ops = &qcom_edp_phy_ops_v4,
+};
+
+static const struct qcom_edp_phy_cfg sc7280_dp_phy_cfg = {
+ .aux_cfg = edp_phy_aux_cfg_v4,
+ .ver_ops = &qcom_edp_phy_ops_v4,
+};
+
+static const struct qcom_edp_phy_cfg sc8280xp_dp_phy_cfg = {
+ .aux_cfg = edp_phy_aux_cfg_v4,
+ .swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
+ .ver_ops = &qcom_edp_phy_ops_v4,
+};
+
+static const struct qcom_edp_phy_cfg sc8280xp_edp_phy_cfg = {
+ .is_edp = true,
+ .aux_cfg = edp_phy_aux_cfg_v4,
+ .swing_pre_emph_cfg = &edp_phy_swing_pre_emph_cfg,
+ .ver_ops = &qcom_edp_phy_ops_v4,
+};
+
+static int qcom_edp_phy_power_on_v6(const struct qcom_edp *edp)
+{
+ u32 val;
+
+ writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
+ DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN |
+ DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
+ edp->edp + DP_PHY_PD_CTL);
+ writel(0xfc, edp->edp + DP_PHY_MODE);
+
+ return readl_poll_timeout(edp->pll + QSERDES_V6_COM_CMN_STATUS,
+ val, val & BIT(7), 5, 200);
+}
+
+static int qcom_edp_phy_com_resetsm_cntrl_v6(const struct qcom_edp *edp)
+{
+ u32 val;
+
+ writel(0x20, edp->pll + QSERDES_V6_COM_RESETSM_CNTRL);
+
+ return readl_poll_timeout(edp->pll + QSERDES_V6_COM_C_READY_STATUS,
+ val, val & BIT(0), 500, 10000);
+}
+
+static int qcom_edp_com_bias_en_clkbuflr_v6(const struct qcom_edp *edp)
+{
+ /* Turn on BIAS current for PHY/PLL */
+ writel(0x1f, edp->pll + QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN);
+
+ return 0;
+}
+
+static int qcom_edp_com_configure_ssc_v6(const struct qcom_edp *edp)
{
const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
- u32 vco_div;
+ u32 step1;
+ u32 step2;
switch (dp_opts->link_rate) {
case 1620:
- vco_div = 0x1;
- *pixel_freq = 1620000000UL / 2;
+ case 2700:
+ case 8100:
+ step1 = 0x92;
+ step2 = 0x01;
+ break;
+
+ case 5400:
+ step1 = 0x18;
+ step2 = 0x02;
+ break;
+
+ default:
+ /* Other link rates aren't supported */
+ return -EINVAL;
+ }
+
+ writel(0x01, edp->pll + QSERDES_V6_COM_SSC_EN_CENTER);
+ writel(0x00, edp->pll + QSERDES_V6_COM_SSC_ADJ_PER1);
+ writel(0x36, edp->pll + QSERDES_V6_COM_SSC_PER1);
+ writel(0x01, edp->pll + QSERDES_V6_COM_SSC_PER2);
+ writel(step1, edp->pll + QSERDES_V6_COM_SSC_STEP_SIZE1_MODE0);
+ writel(step2, edp->pll + QSERDES_V6_COM_SSC_STEP_SIZE2_MODE0);
+
+ return 0;
+}
+
+static int qcom_edp_com_configure_pll_v6(const struct qcom_edp *edp)
+{
+ const struct phy_configure_opts_dp *dp_opts = &edp->dp_opts;
+ u32 div_frac_start2_mode0;
+ u32 div_frac_start3_mode0;
+ u32 dec_start_mode0;
+ u32 lock_cmp1_mode0;
+ u32 lock_cmp2_mode0;
+ u32 code1_mode0;
+ u32 code2_mode0;
+ u32 hsclk_sel;
+
+ switch (dp_opts->link_rate) {
+ case 1620:
+ hsclk_sel = 0x5;
+ dec_start_mode0 = 0x34;
+ div_frac_start2_mode0 = 0xc0;
+ div_frac_start3_mode0 = 0x0b;
+ lock_cmp1_mode0 = 0x37;
+ lock_cmp2_mode0 = 0x04;
+ code1_mode0 = 0x71;
+ code2_mode0 = 0x0c;
break;
case 2700:
- vco_div = 0x1;
- *pixel_freq = 2700000000UL / 2;
+ hsclk_sel = 0x3;
+ dec_start_mode0 = 0x34;
+ div_frac_start2_mode0 = 0xc0;
+ div_frac_start3_mode0 = 0x0b;
+ lock_cmp1_mode0 = 0x07;
+ lock_cmp2_mode0 = 0x07;
+ code1_mode0 = 0x71;
+ code2_mode0 = 0x0c;
break;
case 5400:
- vco_div = 0x2;
- *pixel_freq = 5400000000UL / 4;
+ hsclk_sel = 0x1;
+ dec_start_mode0 = 0x46;
+ div_frac_start2_mode0 = 0x00;
+ div_frac_start3_mode0 = 0x05;
+ lock_cmp1_mode0 = 0x0f;
+ lock_cmp2_mode0 = 0x0e;
+ code1_mode0 = 0x97;
+ code2_mode0 = 0x10;
break;
case 8100:
- vco_div = 0x0;
- *pixel_freq = 8100000000UL / 6;
+ hsclk_sel = 0x0;
+ dec_start_mode0 = 0x34;
+ div_frac_start2_mode0 = 0xc0;
+ div_frac_start3_mode0 = 0x0b;
+ lock_cmp1_mode0 = 0x17;
+ lock_cmp2_mode0 = 0x15;
+ code1_mode0 = 0x71;
+ code2_mode0 = 0x0c;
break;
default:
@@ -439,36 +685,73 @@ static int qcom_edp_set_vco_div(const struct qcom_edp *edp, unsigned long *pixel
return -EINVAL;
}
- writel(vco_div, edp->edp + DP_PHY_VCO_DIV);
+ writel(0x01, edp->pll + QSERDES_V6_COM_SVS_MODE_CLK_SEL);
+ writel(0x0b, edp->pll + QSERDES_V6_COM_SYSCLK_EN_SEL);
+ writel(0x02, edp->pll + QSERDES_V6_COM_SYS_CLK_CTRL);
+ writel(0x0c, edp->pll + QSERDES_V6_COM_CLK_ENABLE1);
+ writel(0x06, edp->pll + QSERDES_V6_COM_SYSCLK_BUF_ENABLE);
+ writel(0x30, edp->pll + QSERDES_V6_COM_CLK_SELECT);
+ writel(hsclk_sel, edp->pll + QSERDES_V6_COM_HSCLK_SEL_1);
+ writel(0x07, edp->pll + QSERDES_V6_COM_PLL_IVCO);
+ writel(0x08, edp->pll + QSERDES_V6_COM_LOCK_CMP_EN);
+ writel(0x36, edp->pll + QSERDES_V6_COM_PLL_CCTRL_MODE0);
+ writel(0x16, edp->pll + QSERDES_V6_COM_PLL_RCTRL_MODE0);
+ writel(0x06, edp->pll + QSERDES_V6_COM_CP_CTRL_MODE0);
+ writel(dec_start_mode0, edp->pll + QSERDES_V6_COM_DEC_START_MODE0);
+ writel(0x00, edp->pll + QSERDES_V6_COM_DIV_FRAC_START1_MODE0);
+ writel(div_frac_start2_mode0, edp->pll + QSERDES_V6_COM_DIV_FRAC_START2_MODE0);
+ writel(div_frac_start3_mode0, edp->pll + QSERDES_V6_COM_DIV_FRAC_START3_MODE0);
+ writel(0x12, edp->pll + QSERDES_V6_COM_CMN_CONFIG_1);
+ writel(0x3f, edp->pll + QSERDES_V6_COM_INTEGLOOP_GAIN0_MODE0);
+ writel(0x00, edp->pll + QSERDES_V6_COM_INTEGLOOP_GAIN1_MODE0);
+ writel(0x00, edp->pll + QSERDES_V6_COM_VCO_TUNE_MAP);
+ writel(lock_cmp1_mode0, edp->pll + QSERDES_V6_COM_LOCK_CMP1_MODE0);
+ writel(lock_cmp2_mode0, edp->pll + QSERDES_V6_COM_LOCK_CMP2_MODE0);
+
+ writel(0x0a, edp->pll + QSERDES_V6_COM_BG_TIMER);
+ writel(0x14, edp->pll + QSERDES_V6_COM_PLL_CORE_CLK_DIV_MODE0);
+ writel(0x00, edp->pll + QSERDES_V6_COM_VCO_TUNE_CTRL);
+ writel(0x1f, edp->pll + QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN);
+ writel(0x0f, edp->pll + QSERDES_V6_COM_CORE_CLK_EN);
+ writel(0xa0, edp->pll + QSERDES_V6_COM_VCO_TUNE1_MODE0);
+ writel(0x03, edp->pll + QSERDES_V6_COM_VCO_TUNE2_MODE0);
+
+ writel(code1_mode0, edp->pll + QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE1_MODE0);
+ writel(code2_mode0, edp->pll + QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE2_MODE0);
return 0;
}
+static const struct phy_ver_ops qcom_edp_phy_ops_v6 = {
+ .com_power_on = qcom_edp_phy_power_on_v6,
+ .com_resetsm_cntrl = qcom_edp_phy_com_resetsm_cntrl_v6,
+ .com_bias_en_clkbuflr = qcom_edp_com_bias_en_clkbuflr_v6,
+ .com_configure_pll = qcom_edp_com_configure_pll_v6,
+ .com_configure_ssc = qcom_edp_com_configure_ssc_v6,
+};
+
+static struct qcom_edp_phy_cfg x1e80100_phy_cfg = {
+ .aux_cfg = edp_phy_aux_cfg_v4,
+ .swing_pre_emph_cfg = &dp_phy_swing_pre_emph_cfg,
+ .ver_ops = &qcom_edp_phy_ops_v6,
+};
+
static int qcom_edp_phy_power_on(struct phy *phy)
{
const struct qcom_edp *edp = phy_get_drvdata(phy);
- const struct qcom_edp_cfg *cfg = edp->cfg;
u32 bias0_en, drvr0_en, bias1_en, drvr1_en;
unsigned long pixel_freq;
- u8 ldo_config;
- int timeout;
+ u8 ldo_config = 0x0;
int ret;
u32 val;
u8 cfg1;
- writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
- DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN |
- DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN,
- edp->edp + DP_PHY_PD_CTL);
- writel(0xfc, edp->edp + DP_PHY_MODE);
-
- timeout = readl_poll_timeout(edp->pll + QSERDES_V4_COM_CMN_STATUS,
- val, val & BIT(7), 5, 200);
- if (timeout)
- return timeout;
-
+ ret = edp->cfg->ver_ops->com_power_on(edp);
+ if (ret)
+ return ret;
- ldo_config = (cfg && cfg->is_dp) ? 0x1 : 0x0;
+ if (edp->cfg->swing_pre_emph_cfg && !edp->is_edp)
+ ldo_config = 0x1;
writel(ldo_config, edp->tx0 + TXn_LDO_CONFIG);
writel(ldo_config, edp->tx1 + TXn_LDO_CONFIG);
@@ -512,12 +795,9 @@ static int qcom_edp_phy_power_on(struct phy *phy)
writel(0x01, edp->edp + DP_PHY_CFG);
writel(0x09, edp->edp + DP_PHY_CFG);
- writel(0x20, edp->pll + QSERDES_V4_COM_RESETSM_CNTRL);
-
- timeout = readl_poll_timeout(edp->pll + QSERDES_V4_COM_C_READY_STATUS,
- val, val & BIT(0), 500, 10000);
- if (timeout)
- return timeout;
+ ret = edp->cfg->ver_ops->com_resetsm_cntrl(edp);
+ if (ret)
+ return ret;
writel(0x19, edp->edp + DP_PHY_CFG);
writel(0x1f, edp->tx0 + TXn_HIGHZ_DRVR_EN);
@@ -589,6 +869,18 @@ static int qcom_edp_phy_power_off(struct phy *phy)
return 0;
}
+static int qcom_edp_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
+{
+ struct qcom_edp *edp = phy_get_drvdata(phy);
+
+ if (mode != PHY_MODE_DP)
+ return -EINVAL;
+
+ edp->is_edp = submode == PHY_SUBMODE_EDP;
+
+ return 0;
+}
+
static int qcom_edp_phy_exit(struct phy *phy)
{
struct qcom_edp *edp = phy_get_drvdata(phy);
@@ -604,6 +896,7 @@ static const struct phy_ops qcom_edp_ops = {
.configure = qcom_edp_phy_configure,
.power_on = qcom_edp_phy_power_on,
.power_off = qcom_edp_phy_power_off,
+ .set_mode = qcom_edp_phy_set_mode,
.exit = qcom_edp_phy_exit,
.owner = THIS_MODULE,
};
@@ -781,6 +1074,7 @@ static int qcom_edp_phy_probe(struct platform_device *pdev)
edp->dev = dev;
edp->cfg = of_device_get_match_data(&pdev->dev);
+ edp->is_edp = edp->cfg->is_edp;
edp->edp = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(edp->edp))
@@ -839,10 +1133,12 @@ static int qcom_edp_phy_probe(struct platform_device *pdev)
}
static const struct of_device_id qcom_edp_phy_match_table[] = {
- { .compatible = "qcom,sc7280-edp-phy" },
- { .compatible = "qcom,sc8180x-edp-phy" },
- { .compatible = "qcom,sc8280xp-dp-phy", .data = &dp_phy_cfg },
- { .compatible = "qcom,sc8280xp-edp-phy", .data = &edp_phy_cfg },
+ { .compatible = "qcom,sa8775p-edp-phy", .data = &sa8775p_dp_phy_cfg, },
+ { .compatible = "qcom,sc7280-edp-phy", .data = &sc7280_dp_phy_cfg, },
+ { .compatible = "qcom,sc8180x-edp-phy", .data = &sc7280_dp_phy_cfg, },
+ { .compatible = "qcom,sc8280xp-dp-phy", .data = &sc8280xp_dp_phy_cfg, },
+ { .compatible = "qcom,sc8280xp-edp-phy", .data = &sc8280xp_edp_phy_cfg, },
+ { .compatible = "qcom,x1e80100-dp-phy", .data = &x1e80100_phy_cfg, },
{ }
};
MODULE_DEVICE_TABLE(of, qcom_edp_phy_match_table);
diff --git a/drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c b/drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c
index a43e20abb10d..6bd1b3c75c77 100644
--- a/drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c
+++ b/drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c
@@ -88,6 +88,12 @@ static const u32 pm8550b_init_tbl[NUM_TUNE_FIELDS] = {
[TUNE_USB2_PREEM] = 0x5,
};
+static const u32 smb2360_init_tbl[NUM_TUNE_FIELDS] = {
+ [TUNE_IUSB2] = 0x5,
+ [TUNE_SQUELCH_U] = 0x3,
+ [TUNE_USB2_PREEM] = 0x2,
+};
+
static const struct eusb2_repeater_cfg pm8550b_eusb2_cfg = {
.init_tbl = pm8550b_init_tbl,
.init_tbl_num = ARRAY_SIZE(pm8550b_init_tbl),
@@ -95,6 +101,13 @@ static const struct eusb2_repeater_cfg pm8550b_eusb2_cfg = {
.num_vregs = ARRAY_SIZE(pm8550b_vreg_l),
};
+static const struct eusb2_repeater_cfg smb2360_eusb2_cfg = {
+ .init_tbl = smb2360_init_tbl,
+ .init_tbl_num = ARRAY_SIZE(smb2360_init_tbl),
+ .vreg_list = pm8550b_vreg_l,
+ .num_vregs = ARRAY_SIZE(pm8550b_vreg_l),
+};
+
static int eusb2_repeater_init_vregs(struct eusb2_repeater *rptr)
{
int num = rptr->cfg->num_vregs;
@@ -271,13 +284,17 @@ static const struct of_device_id eusb2_repeater_of_match_table[] = {
.compatible = "qcom,pm8550b-eusb2-repeater",
.data = &pm8550b_eusb2_cfg,
},
+ {
+ .compatible = "qcom,smb2360-eusb2-repeater",
+ .data = &smb2360_eusb2_cfg,
+ },
{ },
};
MODULE_DEVICE_TABLE(of, eusb2_repeater_of_match_table);
static struct platform_driver eusb2_repeater_driver = {
.probe = eusb2_repeater_probe,
- .remove_new = eusb2_repeater_remove,
+ .remove = eusb2_repeater_remove,
.driver = {
.name = "qcom-eusb2-repeater",
.of_match_table = eusb2_repeater_of_match_table,
diff --git a/drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c b/drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c
index f0a72b82c770..f5eb0bdac418 100644
--- a/drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c
+++ b/drivers/phy/qualcomm/phy-qcom-ipq806x-sata.c
@@ -184,11 +184,11 @@ static const struct of_device_id qcom_ipq806x_sata_phy_of_match[] = {
MODULE_DEVICE_TABLE(of, qcom_ipq806x_sata_phy_of_match);
static struct platform_driver qcom_ipq806x_sata_phy_driver = {
- .probe = qcom_ipq806x_sata_phy_probe,
- .remove_new = qcom_ipq806x_sata_phy_remove,
+ .probe = qcom_ipq806x_sata_phy_probe,
+ .remove = qcom_ipq806x_sata_phy_remove,
.driver = {
- .name = "qcom-ipq806x-sata-phy",
- .of_match_table = qcom_ipq806x_sata_phy_of_match,
+ .name = "qcom-ipq806x-sata-phy",
+ .of_match_table = qcom_ipq806x_sata_phy_of_match,
}
};
module_platform_driver(qcom_ipq806x_sata_phy_driver);
diff --git a/drivers/phy/qualcomm/phy-qcom-m31.c b/drivers/phy/qualcomm/phy-qcom-m31.c
index 03fb0d4b75d7..20d4c020a83c 100644
--- a/drivers/phy/qualcomm/phy-qcom-m31.c
+++ b/drivers/phy/qualcomm/phy-qcom-m31.c
@@ -297,7 +297,7 @@ static int m31usb_phy_probe(struct platform_device *pdev)
return dev_err_probe(dev, PTR_ERR(qphy->phy),
"failed to create phy\n");
- qphy->vreg = devm_regulator_get(dev, "vdda-phy");
+ qphy->vreg = devm_regulator_get(dev, "vdd");
if (IS_ERR(qphy->vreg))
return dev_err_probe(dev, PTR_ERR(qphy->vreg),
"failed to get vreg\n");
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
index 17c4ad7553a5..b09fa00e9fe7 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
@@ -25,21 +25,21 @@
#include <dt-bindings/phy/phy-qcom-qmp.h>
+#include "phy-qcom-qmp-common.h"
+
#include "phy-qcom-qmp.h"
#include "phy-qcom-qmp-pcs-misc-v3.h"
#include "phy-qcom-qmp-pcs-usb-v4.h"
#include "phy-qcom-qmp-pcs-usb-v5.h"
#include "phy-qcom-qmp-pcs-usb-v6.h"
-/* QPHY_SW_RESET bit */
-#define SW_RESET BIT(0)
-/* QPHY_POWER_DOWN_CONTROL */
-#define SW_PWRDN BIT(0)
-/* QPHY_START_CONTROL bits */
-#define SERDES_START BIT(0)
-#define PCS_START BIT(1)
-/* QPHY_PCS_STATUS bit */
-#define PHYSTATUS BIT(6)
+#include "phy-qcom-qmp-dp-com-v3.h"
+
+#include "phy-qcom-qmp-dp-phy.h"
+#include "phy-qcom-qmp-dp-phy-v3.h"
+#include "phy-qcom-qmp-dp-phy-v4.h"
+#include "phy-qcom-qmp-dp-phy-v5.h"
+#include "phy-qcom-qmp-dp-phy-v6.h"
/* QPHY_V3_DP_COM_RESET_OVRD_CTRL register bits */
/* DP PHY soft reset */
@@ -55,47 +55,12 @@
#define USB3_MODE BIT(0) /* enables USB3 mode */
#define DP_MODE BIT(1) /* enables DP mode */
-/* QPHY_PCS_AUTONOMOUS_MODE_CTRL register bits */
-#define ARCVR_DTCT_EN BIT(0)
-#define ALFPS_DTCT_EN BIT(1)
-#define ARCVR_DTCT_EVENT_SEL BIT(4)
-
-/* QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR register bits */
-#define IRQ_CLEAR BIT(0)
-
-/* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */
-#define CLAMP_EN BIT(0) /* enables i/o clamp_n */
-
/* QPHY_V3_DP_COM_TYPEC_CTRL register bits */
#define SW_PORTSELECT_VAL BIT(0)
#define SW_PORTSELECT_MUX BIT(1)
#define PHY_INIT_COMPLETE_TIMEOUT 10000
-struct qmp_phy_init_tbl {
- unsigned int offset;
- unsigned int val;
- /*
- * mask of lanes for which this register is written
- * for cases when second lane needs different values
- */
- u8 lane_mask;
-};
-
-#define QMP_PHY_INIT_CFG(o, v) \
- { \
- .offset = o, \
- .val = v, \
- .lane_mask = 0xff, \
- }
-
-#define QMP_PHY_INIT_CFG_LANE(o, v, l) \
- { \
- .offset = o, \
- .val = v, \
- .lane_mask = l, \
- }
-
/* set of registers with offsets different per-PHY */
enum qphy_reg_layout {
/* PCS registers */
@@ -112,6 +77,7 @@ enum qphy_reg_layout {
QPHY_COM_BIAS_EN_CLKBUFLR_EN,
QPHY_DP_PHY_STATUS,
+ QPHY_DP_PHY_VCO_DIV,
QPHY_TX_TX_POL_INV,
QPHY_TX_TX_DRV_LVL,
@@ -137,6 +103,7 @@ static const unsigned int qmp_v3_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_COM_BIAS_EN_CLKBUFLR_EN] = QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN,
[QPHY_DP_PHY_STATUS] = QSERDES_V3_DP_PHY_STATUS,
+ [QPHY_DP_PHY_VCO_DIV] = QSERDES_V3_DP_PHY_VCO_DIV,
[QPHY_TX_TX_POL_INV] = QSERDES_V3_TX_TX_POL_INV,
[QPHY_TX_TX_DRV_LVL] = QSERDES_V3_TX_TX_DRV_LVL,
@@ -161,6 +128,7 @@ static const unsigned int qmp_v45_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_COM_BIAS_EN_CLKBUFLR_EN] = QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN,
[QPHY_DP_PHY_STATUS] = QSERDES_V4_DP_PHY_STATUS,
+ [QPHY_DP_PHY_VCO_DIV] = QSERDES_V4_DP_PHY_VCO_DIV,
[QPHY_TX_TX_POL_INV] = QSERDES_V4_TX_TX_POL_INV,
[QPHY_TX_TX_DRV_LVL] = QSERDES_V4_TX_TX_DRV_LVL,
@@ -185,6 +153,7 @@ static const unsigned int qmp_v5_5nm_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_COM_BIAS_EN_CLKBUFLR_EN] = QSERDES_V5_COM_BIAS_EN_CLKBUFLR_EN,
[QPHY_DP_PHY_STATUS] = QSERDES_V5_DP_PHY_STATUS,
+ [QPHY_DP_PHY_VCO_DIV] = QSERDES_V5_DP_PHY_VCO_DIV,
[QPHY_TX_TX_POL_INV] = QSERDES_V5_5NM_TX_TX_POL_INV,
[QPHY_TX_TX_DRV_LVL] = QSERDES_V5_5NM_TX_TX_DRV_LVL,
@@ -209,6 +178,7 @@ static const unsigned int qmp_v6_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_COM_BIAS_EN_CLKBUFLR_EN] = QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN,
[QPHY_DP_PHY_STATUS] = QSERDES_V6_DP_PHY_STATUS,
+ [QPHY_DP_PHY_VCO_DIV] = QSERDES_V6_DP_PHY_VCO_DIV,
[QPHY_TX_TX_POL_INV] = QSERDES_V6_TX_TX_POL_INV,
[QPHY_TX_TX_DRV_LVL] = QSERDES_V6_TX_TX_DRV_LVL,
@@ -217,6 +187,31 @@ static const unsigned int qmp_v6_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_TX_TRANSCEIVER_BIAS_EN] = QSERDES_V6_TX_TRANSCEIVER_BIAS_EN,
};
+static const unsigned int qmp_v6_n4_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
+ [QPHY_SW_RESET] = QPHY_V6_N4_PCS_SW_RESET,
+ [QPHY_START_CTRL] = QPHY_V6_N4_PCS_START_CONTROL,
+ [QPHY_PCS_STATUS] = QPHY_V6_N4_PCS_PCS_STATUS1,
+ [QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V6_N4_PCS_POWER_DOWN_CONTROL,
+
+ /* In PCS_USB */
+ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = QPHY_V6_PCS_USB3_AUTONOMOUS_MODE_CTRL,
+ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = QPHY_V6_PCS_USB3_LFPS_RXTERM_IRQ_CLEAR,
+
+ [QPHY_COM_RESETSM_CNTRL] = QSERDES_V6_COM_RESETSM_CNTRL,
+ [QPHY_COM_C_READY_STATUS] = QSERDES_V6_COM_C_READY_STATUS,
+ [QPHY_COM_CMN_STATUS] = QSERDES_V6_COM_CMN_STATUS,
+ [QPHY_COM_BIAS_EN_CLKBUFLR_EN] = QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN,
+
+ [QPHY_DP_PHY_STATUS] = QSERDES_V6_DP_PHY_STATUS,
+ [QPHY_DP_PHY_VCO_DIV] = QSERDES_V6_DP_PHY_VCO_DIV,
+
+ [QPHY_TX_TX_POL_INV] = QSERDES_V6_N4_TX_TX_POL_INV,
+ [QPHY_TX_TX_DRV_LVL] = QSERDES_V6_N4_TX_TX_DRV_LVL,
+ [QPHY_TX_TX_EMP_POST1_LVL] = QSERDES_V6_N4_TX_TX_EMP_POST1_LVL,
+ [QPHY_TX_HIGHZ_DRVR_EN] = QSERDES_V6_N4_TX_HIGHZ_DRVR_EN,
+ [QPHY_TX_TRANSCEIVER_BIAS_EN] = QSERDES_V6_N4_TX_TRANSCEIVER_BIAS_EN,
+};
+
static const struct qmp_phy_init_tbl qmp_v3_usb3_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14),
@@ -405,6 +400,57 @@ static const struct qmp_phy_init_tbl qmp_v3_usb3_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13),
};
+static const struct qmp_phy_init_tbl sar2130p_usb3_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE1, 0x55),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE1, 0x0e),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE1, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE1, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORECLK_DIV_MODE1, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE1, 0x2e),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE1, 0x82),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MSB_MODE1, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE1, 0x55),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE1, 0xd5),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE1, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE1_MODE1, 0x25),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE2_MODE1, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xb7),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x1e),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xb7),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE0, 0x55),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE0, 0x0e),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x12),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x34),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MSB_MODE0, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE0, 0x55),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE0, 0xd5),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE0, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE1_MODE0, 0x25),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE2_MODE0, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_BG_TIMER, 0x0e),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_EN_CENTER, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER1, 0x31),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER2, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_BUF_ENABLE, 0x0c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0x1a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_CFG, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORE_CLK_EN, 0x20),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_AUTO_GAIN_ADJ_CTRL_1, 0xb6),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_AUTO_GAIN_ADJ_CTRL_2, 0x4b),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_AUTO_GAIN_ADJ_CTRL_3, 0x37),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_ADDITIONAL_MISC, 0x0c),
+};
+
static const struct qmp_phy_init_tbl sm6350_usb3_rx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b),
QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f),
@@ -1027,6 +1073,31 @@ static const struct qmp_phy_init_tbl qmp_v6_dp_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORE_CLK_EN, 0x0f),
};
+static const struct qmp_phy_init_tbl qmp_v6_n4_dp_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SVS_MODE_CLK_SEL, 0x15),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0x3b),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYS_CLK_CTRL, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_ENABLE1, 0x0c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_BUF_ENABLE, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_SELECT, 0x30),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x34),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE0, 0xc0),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x12),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_INTEGLOOP_GAIN0_MODE0, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_BG_TIMER, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CORE_CLK_DIV_MODE0, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_CTRL, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN, 0x17),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORE_CLK_EN, 0x0f),
+};
+
static const struct qmp_phy_init_tbl qmp_v6_dp_tx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_TX_VMODE_CTRL1, 0x40),
QMP_PHY_INIT_CFG(QSERDES_V6_TX_PRE_STALL_LDO_BOOST_EN, 0x30),
@@ -1041,6 +1112,19 @@ static const struct qmp_phy_init_tbl qmp_v6_dp_tx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_TX_TX_BAND, 0x4),
};
+static const struct qmp_phy_init_tbl qmp_v6_n4_dp_tx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_N4_TX_VMODE_CTRL1, 0x40),
+ QMP_PHY_INIT_CFG(QSERDES_V6_N4_TX_PRE_STALL_LDO_BOOST_EN, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_N4_TX_INTERFACE_SELECT, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_V6_N4_TX_CLKBUF_ENABLE, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_N4_TX_RESET_TSYNC_EN, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V6_N4_TX_TRAN_DRVR_EMP_EN, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_N4_TX_PARRATE_REC_DETECT_IDLE_EN, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_N4_TX_RES_CODE_LANE_OFFSET_TX, 0x11),
+ QMP_PHY_INIT_CFG(QSERDES_V6_N4_TX_RES_CODE_LANE_OFFSET_RX, 0x11),
+ QMP_PHY_INIT_CFG(QSERDES_V6_N4_TX_TX_BAND, 0x1),
+};
+
static const struct qmp_phy_init_tbl qmp_v6_dp_serdes_tbl_rbr[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x34),
@@ -1089,6 +1173,74 @@ static const struct qmp_phy_init_tbl qmp_v6_dp_serdes_tbl_hbr3[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x0c),
};
+static const struct qmp_phy_init_tbl qmp_v6_n4_dp_serdes_tbl_rbr[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x34),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE0, 0x0b),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x37),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x71),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x0c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_EN_CENTER, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_ADJ_PER1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER1, 0x6b),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER2, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE0, 0x92),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE0, 0x01),
+};
+
+static const struct qmp_phy_init_tbl qmp_v6_n4_dp_serdes_tbl_hbr[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x34),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE0, 0x0b),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x71),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x0c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_EN_CENTER, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_ADJ_PER1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER1, 0x6b),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER2, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE0, 0x92),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE0, 0x01),
+};
+
+static const struct qmp_phy_init_tbl qmp_v6_n4_dp_serdes_tbl_hbr2[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x46),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE0, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x0e),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x97),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x10),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_EN_CENTER, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_ADJ_PER1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER1, 0x6b),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER2, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE0, 0x18),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE0, 0x02),
+};
+
+static const struct qmp_phy_init_tbl qmp_v6_n4_dp_serdes_tbl_hbr3[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x34),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE0, 0x0b),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x17),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x15),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x71),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x0c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_EN_CENTER, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_ADJ_PER1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER1, 0x6b),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER2, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE0, 0x92),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE0, 0x01),
+};
+
static const struct qmp_phy_init_tbl sc8280xp_usb43dp_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_EN_CENTER, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER1, 0x31),
@@ -1303,20 +1455,20 @@ static const struct qmp_phy_init_tbl x1e80100_usb43dp_rx_tbl[] = {
};
static const struct qmp_phy_init_tbl x1e80100_usb43dp_pcs_tbl[] = {
- QMP_PHY_INIT_CFG(QPHY_V6_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7),
- QMP_PHY_INIT_CFG(QPHY_V6_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03),
- QMP_PHY_INIT_CFG(QPHY_V6_PCS_LOCK_DETECT_CONFIG1, 0xc4),
- QMP_PHY_INIT_CFG(QPHY_V6_PCS_LOCK_DETECT_CONFIG2, 0x89),
- QMP_PHY_INIT_CFG(QPHY_V6_PCS_LOCK_DETECT_CONFIG3, 0x20),
- QMP_PHY_INIT_CFG(QPHY_V6_PCS_LOCK_DETECT_CONFIG6, 0x13),
- QMP_PHY_INIT_CFG(QPHY_V6_PCS_REFGEN_REQ_CONFIG1, 0x21),
- QMP_PHY_INIT_CFG(QPHY_V6_PCS_RX_SIGDET_LVL, 0x55),
- QMP_PHY_INIT_CFG(QPHY_V6_PCS_CDR_RESET_TIME, 0x0a),
- QMP_PHY_INIT_CFG(QPHY_V6_PCS_ALIGN_DETECT_CONFIG1, 0xd4),
- QMP_PHY_INIT_CFG(QPHY_V6_PCS_ALIGN_DETECT_CONFIG2, 0x30),
- QMP_PHY_INIT_CFG(QPHY_V6_PCS_PCS_TX_RX_CONFIG, 0x0c),
- QMP_PHY_INIT_CFG(QPHY_V6_PCS_EQ_CONFIG1, 0x4b),
- QMP_PHY_INIT_CFG(QPHY_V6_PCS_EQ_CONFIG5, 0x10),
+ QMP_PHY_INIT_CFG(QPHY_V6_N4_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7),
+ QMP_PHY_INIT_CFG(QPHY_V6_N4_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03),
+ QMP_PHY_INIT_CFG(QPHY_V6_N4_PCS_LOCK_DETECT_CONFIG1, 0xc4),
+ QMP_PHY_INIT_CFG(QPHY_V6_N4_PCS_LOCK_DETECT_CONFIG2, 0x89),
+ QMP_PHY_INIT_CFG(QPHY_V6_N4_PCS_LOCK_DETECT_CONFIG3, 0x20),
+ QMP_PHY_INIT_CFG(QPHY_V6_N4_PCS_LOCK_DETECT_CONFIG6, 0x13),
+ QMP_PHY_INIT_CFG(QPHY_V6_N4_PCS_REFGEN_REQ_CONFIG1, 0x21),
+ QMP_PHY_INIT_CFG(QPHY_V6_N4_PCS_RX_SIGDET_LVL, 0x55),
+ QMP_PHY_INIT_CFG(QPHY_V6_N4_PCS_RX_CONFIG, 0x0a),
+ QMP_PHY_INIT_CFG(QPHY_V6_N4_PCS_ALIGN_DETECT_CONFIG1, 0xd4),
+ QMP_PHY_INIT_CFG(QPHY_V6_N4_PCS_ALIGN_DETECT_CONFIG2, 0x30),
+ QMP_PHY_INIT_CFG(QPHY_V6_N4_PCS_PCS_TX_RX_CONFIG, 0x0c),
+ QMP_PHY_INIT_CFG(QPHY_V6_N4_PCS_EQ_CONFIG1, 0x4b),
+ QMP_PHY_INIT_CFG(QPHY_V6_N4_PCS_EQ_CONFIG5, 0x10),
};
static const struct qmp_phy_init_tbl x1e80100_usb43dp_pcs_usb_tbl[] = {
@@ -1412,6 +1564,13 @@ static const u8 qmp_dp_v5_voltage_swing_hbr_rbr[4][4] = {
{ 0x3f, 0xff, 0xff, 0xff }
};
+static const u8 qmp_dp_v6_voltage_swing_hbr_rbr[4][4] = {
+ { 0x27, 0x2f, 0x36, 0x3f },
+ { 0x31, 0x3e, 0x3f, 0xff },
+ { 0x36, 0x3f, 0xff, 0xff },
+ { 0x3f, 0xff, 0xff, 0xff }
+};
+
static const u8 qmp_dp_v6_pre_emphasis_hbr_rbr[4][4] = {
{ 0x20, 0x2d, 0x34, 0x3a },
{ 0x20, 0x2e, 0x35, 0xff },
@@ -1622,6 +1781,51 @@ static const struct qmp_combo_offsets qmp_combo_offsets_v5 = {
.dp_dp_phy = 0x2200,
};
+static const struct qmp_phy_cfg sar2130p_usb3dpphy_cfg = {
+ .offsets = &qmp_combo_offsets_v3,
+
+ .serdes_tbl = sar2130p_usb3_serdes_tbl,
+ .serdes_tbl_num = ARRAY_SIZE(sar2130p_usb3_serdes_tbl),
+ .tx_tbl = sm8550_usb3_tx_tbl,
+ .tx_tbl_num = ARRAY_SIZE(sm8550_usb3_tx_tbl),
+ .rx_tbl = sm8550_usb3_rx_tbl,
+ .rx_tbl_num = ARRAY_SIZE(sm8550_usb3_rx_tbl),
+ .pcs_tbl = sm8550_usb3_pcs_tbl,
+ .pcs_tbl_num = ARRAY_SIZE(sm8550_usb3_pcs_tbl),
+ .pcs_usb_tbl = sm8550_usb3_pcs_usb_tbl,
+ .pcs_usb_tbl_num = ARRAY_SIZE(sm8550_usb3_pcs_usb_tbl),
+
+ .dp_serdes_tbl = qmp_v6_dp_serdes_tbl,
+ .dp_serdes_tbl_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl),
+ .dp_tx_tbl = qmp_v6_dp_tx_tbl,
+ .dp_tx_tbl_num = ARRAY_SIZE(qmp_v6_dp_tx_tbl),
+
+ .serdes_tbl_rbr = qmp_v6_dp_serdes_tbl_rbr,
+ .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl_rbr),
+ .serdes_tbl_hbr = qmp_v6_dp_serdes_tbl_hbr,
+ .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl_hbr),
+ .serdes_tbl_hbr2 = qmp_v6_dp_serdes_tbl_hbr2,
+ .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl_hbr2),
+ .serdes_tbl_hbr3 = qmp_v6_dp_serdes_tbl_hbr3,
+ .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl_hbr3),
+
+ .swing_hbr_rbr = &qmp_dp_v5_voltage_swing_hbr_rbr,
+ .pre_emphasis_hbr_rbr = &qmp_dp_v6_pre_emphasis_hbr_rbr,
+ .swing_hbr3_hbr2 = &qmp_dp_v5_voltage_swing_hbr3_hbr2,
+ .pre_emphasis_hbr3_hbr2 = &qmp_dp_v5_pre_emphasis_hbr3_hbr2,
+
+ .dp_aux_init = qmp_v4_dp_aux_init,
+ .configure_dp_tx = qmp_v4_configure_dp_tx,
+ .configure_dp_phy = qmp_v4_configure_dp_phy,
+ .calibrate_dp_phy = qmp_v4_calibrate_dp_phy,
+
+ .regs = qmp_v6_usb3phy_regs_layout,
+ .reset_list = msm8996_usb3phy_reset_l,
+ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l),
+ .vreg_list = qmp_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
+};
+
static const struct qmp_phy_cfg sc7180_usb3dpphy_cfg = {
.offsets = &qmp_combo_offsets_v3,
@@ -1817,22 +2021,22 @@ static const struct qmp_phy_cfg x1e80100_usb3dpphy_cfg = {
.pcs_usb_tbl = x1e80100_usb43dp_pcs_usb_tbl,
.pcs_usb_tbl_num = ARRAY_SIZE(x1e80100_usb43dp_pcs_usb_tbl),
- .dp_serdes_tbl = qmp_v6_dp_serdes_tbl,
- .dp_serdes_tbl_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl),
- .dp_tx_tbl = qmp_v6_dp_tx_tbl,
- .dp_tx_tbl_num = ARRAY_SIZE(qmp_v6_dp_tx_tbl),
-
- .serdes_tbl_rbr = qmp_v6_dp_serdes_tbl_rbr,
- .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl_rbr),
- .serdes_tbl_hbr = qmp_v6_dp_serdes_tbl_hbr,
- .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl_hbr),
- .serdes_tbl_hbr2 = qmp_v6_dp_serdes_tbl_hbr2,
- .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl_hbr2),
- .serdes_tbl_hbr3 = qmp_v6_dp_serdes_tbl_hbr3,
- .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl_hbr3),
-
- .swing_hbr_rbr = &qmp_dp_v5_voltage_swing_hbr_rbr,
- .pre_emphasis_hbr_rbr = &qmp_dp_v5_pre_emphasis_hbr_rbr,
+ .dp_serdes_tbl = qmp_v6_n4_dp_serdes_tbl,
+ .dp_serdes_tbl_num = ARRAY_SIZE(qmp_v6_n4_dp_serdes_tbl),
+ .dp_tx_tbl = qmp_v6_n4_dp_tx_tbl,
+ .dp_tx_tbl_num = ARRAY_SIZE(qmp_v6_n4_dp_tx_tbl),
+
+ .serdes_tbl_rbr = qmp_v6_n4_dp_serdes_tbl_rbr,
+ .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v6_n4_dp_serdes_tbl_rbr),
+ .serdes_tbl_hbr = qmp_v6_n4_dp_serdes_tbl_hbr,
+ .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v6_n4_dp_serdes_tbl_hbr),
+ .serdes_tbl_hbr2 = qmp_v6_n4_dp_serdes_tbl_hbr2,
+ .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v6_n4_dp_serdes_tbl_hbr2),
+ .serdes_tbl_hbr3 = qmp_v6_n4_dp_serdes_tbl_hbr3,
+ .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v6_n4_dp_serdes_tbl_hbr3),
+
+ .swing_hbr_rbr = &qmp_dp_v6_voltage_swing_hbr_rbr,
+ .pre_emphasis_hbr_rbr = &qmp_dp_v6_pre_emphasis_hbr_rbr,
.swing_hbr3_hbr2 = &qmp_dp_v5_voltage_swing_hbr3_hbr2,
.pre_emphasis_hbr3_hbr2 = &qmp_dp_v5_pre_emphasis_hbr3_hbr2,
@@ -1845,7 +2049,7 @@ static const struct qmp_phy_cfg x1e80100_usb3dpphy_cfg = {
.num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l),
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
- .regs = qmp_v45_usb3phy_regs_layout,
+ .regs = qmp_v6_n4_usb3phy_regs_layout,
};
static const struct qmp_phy_cfg sm6350_usb3dpphy_cfg = {
@@ -2031,31 +2235,50 @@ static const struct qmp_phy_cfg sm8550_usb3dpphy_cfg = {
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
};
-static void qmp_combo_configure_lane(void __iomem *base,
- const struct qmp_phy_init_tbl tbl[],
- int num,
- u8 lane_mask)
-{
- int i;
- const struct qmp_phy_init_tbl *t = tbl;
+static const struct qmp_phy_cfg sm8650_usb3dpphy_cfg = {
+ .offsets = &qmp_combo_offsets_v3,
- if (!t)
- return;
+ .serdes_tbl = sm8550_usb3_serdes_tbl,
+ .serdes_tbl_num = ARRAY_SIZE(sm8550_usb3_serdes_tbl),
+ .tx_tbl = sm8550_usb3_tx_tbl,
+ .tx_tbl_num = ARRAY_SIZE(sm8550_usb3_tx_tbl),
+ .rx_tbl = sm8550_usb3_rx_tbl,
+ .rx_tbl_num = ARRAY_SIZE(sm8550_usb3_rx_tbl),
+ .pcs_tbl = sm8550_usb3_pcs_tbl,
+ .pcs_tbl_num = ARRAY_SIZE(sm8550_usb3_pcs_tbl),
+ .pcs_usb_tbl = sm8550_usb3_pcs_usb_tbl,
+ .pcs_usb_tbl_num = ARRAY_SIZE(sm8550_usb3_pcs_usb_tbl),
- for (i = 0; i < num; i++, t++) {
- if (!(t->lane_mask & lane_mask))
- continue;
+ .dp_serdes_tbl = qmp_v6_dp_serdes_tbl,
+ .dp_serdes_tbl_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl),
+ .dp_tx_tbl = qmp_v6_dp_tx_tbl,
+ .dp_tx_tbl_num = ARRAY_SIZE(qmp_v6_dp_tx_tbl),
- writel(t->val, base + t->offset);
- }
-}
+ .serdes_tbl_rbr = qmp_v6_dp_serdes_tbl_rbr,
+ .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl_rbr),
+ .serdes_tbl_hbr = qmp_v6_dp_serdes_tbl_hbr,
+ .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl_hbr),
+ .serdes_tbl_hbr2 = qmp_v6_dp_serdes_tbl_hbr2,
+ .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl_hbr2),
+ .serdes_tbl_hbr3 = qmp_v6_dp_serdes_tbl_hbr3,
+ .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v6_dp_serdes_tbl_hbr3),
-static void qmp_combo_configure(void __iomem *base,
- const struct qmp_phy_init_tbl tbl[],
- int num)
-{
- qmp_combo_configure_lane(base, tbl, num, 0xff);
-}
+ .swing_hbr_rbr = &qmp_dp_v6_voltage_swing_hbr_rbr,
+ .pre_emphasis_hbr_rbr = &qmp_dp_v6_pre_emphasis_hbr_rbr,
+ .swing_hbr3_hbr2 = &qmp_dp_v5_voltage_swing_hbr3_hbr2,
+ .pre_emphasis_hbr3_hbr2 = &qmp_dp_v5_pre_emphasis_hbr3_hbr2,
+
+ .dp_aux_init = qmp_v4_dp_aux_init,
+ .configure_dp_tx = qmp_v4_configure_dp_tx,
+ .configure_dp_phy = qmp_v4_configure_dp_phy,
+ .calibrate_dp_phy = qmp_v4_calibrate_dp_phy,
+
+ .regs = qmp_v6_usb3phy_regs_layout,
+ .reset_list = msm8996_usb3phy_reset_l,
+ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l),
+ .vreg_list = qmp_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
+};
static int qmp_combo_dp_serdes_init(struct qmp_combo *qmp)
{
@@ -2063,24 +2286,25 @@ static int qmp_combo_dp_serdes_init(struct qmp_combo *qmp)
void __iomem *serdes = qmp->dp_serdes;
const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts;
- qmp_combo_configure(serdes, cfg->dp_serdes_tbl, cfg->dp_serdes_tbl_num);
+ qmp_configure(qmp->dev, serdes, cfg->dp_serdes_tbl,
+ cfg->dp_serdes_tbl_num);
switch (dp_opts->link_rate) {
case 1620:
- qmp_combo_configure(serdes, cfg->serdes_tbl_rbr,
- cfg->serdes_tbl_rbr_num);
+ qmp_configure(qmp->dev, serdes, cfg->serdes_tbl_rbr,
+ cfg->serdes_tbl_rbr_num);
break;
case 2700:
- qmp_combo_configure(serdes, cfg->serdes_tbl_hbr,
- cfg->serdes_tbl_hbr_num);
+ qmp_configure(qmp->dev, serdes, cfg->serdes_tbl_hbr,
+ cfg->serdes_tbl_hbr_num);
break;
case 5400:
- qmp_combo_configure(serdes, cfg->serdes_tbl_hbr2,
- cfg->serdes_tbl_hbr2_num);
+ qmp_configure(qmp->dev, serdes, cfg->serdes_tbl_hbr2,
+ cfg->serdes_tbl_hbr2_num);
break;
case 8100:
- qmp_combo_configure(serdes, cfg->serdes_tbl_hbr3,
- cfg->serdes_tbl_hbr3_num);
+ qmp_configure(qmp->dev, serdes, cfg->serdes_tbl_hbr3,
+ cfg->serdes_tbl_hbr3_num);
break;
default:
/* Other link rates aren't supported */
@@ -2211,9 +2435,9 @@ static bool qmp_combo_configure_dp_mode(struct qmp_combo *qmp)
writel(val, qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL);
if (reverse)
- writel(0x4c, qmp->pcs + QSERDES_DP_PHY_MODE);
+ writel(0x4c, qmp->dp_dp_phy + QSERDES_DP_PHY_MODE);
else
- writel(0x5c, qmp->pcs + QSERDES_DP_PHY_MODE);
+ writel(0x5c, qmp->dp_dp_phy + QSERDES_DP_PHY_MODE);
return reverse;
}
@@ -2223,6 +2447,7 @@ static int qmp_combo_configure_dp_clocks(struct qmp_combo *qmp)
const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts;
u32 phy_vco_div;
unsigned long pixel_freq;
+ const struct qmp_phy_cfg *cfg = qmp->cfg;
switch (dp_opts->link_rate) {
case 1620:
@@ -2245,7 +2470,7 @@ static int qmp_combo_configure_dp_clocks(struct qmp_combo *qmp)
/* Other link rates aren't supported */
return -EINVAL;
}
- writel(phy_vco_div, qmp->dp_dp_phy + QSERDES_V4_DP_PHY_VCO_DIV);
+ writel(phy_vco_div, qmp->dp_dp_phy + cfg->regs[QPHY_DP_PHY_VCO_DIV]);
clk_set_rate(qmp->dp_link_hw.clk, dp_opts->link_rate * 100000);
clk_set_rate(qmp->dp_pixel_hw.clk, pixel_freq);
@@ -2370,7 +2595,7 @@ static int qmp_v456_configure_dp_phy(struct qmp_combo *qmp)
u32 status;
int ret;
- writel(0x0f, qmp->dp_dp_phy + QSERDES_V4_DP_PHY_CFG_1);
+ writel(0x0f, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG_1);
qmp_combo_configure_dp_mode(qmp);
@@ -2492,8 +2717,6 @@ static int qmp_v4_configure_dp_phy(struct qmp_combo *qmp)
writel(0x20, qmp->dp_tx2 + cfg->regs[QPHY_TX_TX_EMP_POST1_LVL]);
return 0;
-
- return 0;
}
/*
@@ -2681,8 +2904,8 @@ static int qmp_combo_dp_power_on(struct phy *phy)
qmp_combo_dp_serdes_init(qmp);
- qmp_combo_configure_lane(tx, cfg->dp_tx_tbl, cfg->dp_tx_tbl_num, 1);
- qmp_combo_configure_lane(tx2, cfg->dp_tx_tbl, cfg->dp_tx_tbl_num, 2);
+ qmp_configure_lane(qmp->dev, tx, cfg->dp_tx_tbl, cfg->dp_tx_tbl_num, 1);
+ qmp_configure_lane(qmp->dev, tx2, cfg->dp_tx_tbl, cfg->dp_tx_tbl_num, 2);
/* Configure special DP tx tunings */
cfg->configure_dp_tx(qmp);
@@ -2724,7 +2947,7 @@ static int qmp_combo_usb_power_on(struct phy *phy)
unsigned int val;
int ret;
- qmp_combo_configure(serdes, cfg->serdes_tbl, cfg->serdes_tbl_num);
+ qmp_configure(qmp->dev, serdes, cfg->serdes_tbl, cfg->serdes_tbl_num);
ret = clk_prepare_enable(qmp->pipe_clk);
if (ret) {
@@ -2733,16 +2956,17 @@ static int qmp_combo_usb_power_on(struct phy *phy)
}
/* Tx, Rx, and PCS configurations */
- qmp_combo_configure_lane(tx, cfg->tx_tbl, cfg->tx_tbl_num, 1);
- qmp_combo_configure_lane(tx2, cfg->tx_tbl, cfg->tx_tbl_num, 2);
+ qmp_configure_lane(qmp->dev, tx, cfg->tx_tbl, cfg->tx_tbl_num, 1);
+ qmp_configure_lane(qmp->dev, tx2, cfg->tx_tbl, cfg->tx_tbl_num, 2);
- qmp_combo_configure_lane(rx, cfg->rx_tbl, cfg->rx_tbl_num, 1);
- qmp_combo_configure_lane(rx2, cfg->rx_tbl, cfg->rx_tbl_num, 2);
+ qmp_configure_lane(qmp->dev, rx, cfg->rx_tbl, cfg->rx_tbl_num, 1);
+ qmp_configure_lane(qmp->dev, rx2, cfg->rx_tbl, cfg->rx_tbl_num, 2);
- qmp_combo_configure(pcs, cfg->pcs_tbl, cfg->pcs_tbl_num);
+ qmp_configure(qmp->dev, pcs, cfg->pcs_tbl, cfg->pcs_tbl_num);
if (pcs_usb)
- qmp_combo_configure(pcs_usb, cfg->pcs_usb_tbl, cfg->pcs_usb_tbl_num);
+ qmp_configure(qmp->dev, pcs_usb, cfg->pcs_usb_tbl,
+ cfg->pcs_usb_tbl_num);
if (cfg->has_pwrdn_delay)
usleep_range(10, 20);
@@ -3355,7 +3579,7 @@ static int qmp_combo_typec_switch_register(struct qmp_combo *qmp)
}
#endif
-static int qmp_combo_parse_dt_lecacy_dp(struct qmp_combo *qmp, struct device_node *np)
+static int qmp_combo_parse_dt_legacy_dp(struct qmp_combo *qmp, struct device_node *np)
{
struct device *dev = qmp->dev;
@@ -3382,7 +3606,7 @@ static int qmp_combo_parse_dt_lecacy_dp(struct qmp_combo *qmp, struct device_nod
return 0;
}
-static int qmp_combo_parse_dt_lecacy_usb(struct qmp_combo *qmp, struct device_node *np)
+static int qmp_combo_parse_dt_legacy_usb(struct qmp_combo *qmp, struct device_node *np)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
struct device *dev = qmp->dev;
@@ -3448,11 +3672,11 @@ static int qmp_combo_parse_dt_legacy(struct qmp_combo *qmp, struct device_node *
if (IS_ERR(qmp->dp_serdes))
return PTR_ERR(qmp->dp_serdes);
- ret = qmp_combo_parse_dt_lecacy_usb(qmp, usb_np);
+ ret = qmp_combo_parse_dt_legacy_usb(qmp, usb_np);
if (ret)
return ret;
- ret = qmp_combo_parse_dt_lecacy_dp(qmp, dp_np);
+ ret = qmp_combo_parse_dt_legacy_dp(qmp, dp_np);
if (ret)
return ret;
@@ -3515,7 +3739,7 @@ static int qmp_combo_parse_dt(struct qmp_combo *qmp)
return 0;
}
-static struct phy *qmp_combo_phy_xlate(struct device *dev, struct of_phandle_args *args)
+static struct phy *qmp_combo_phy_xlate(struct device *dev, const struct of_phandle_args *args)
{
struct qmp_combo *qmp = dev_get_drvdata(dev);
@@ -3545,6 +3769,7 @@ static int qmp_combo_probe(struct platform_device *pdev)
return -ENOMEM;
qmp->dev = dev;
+ dev_set_drvdata(dev, qmp);
qmp->orientation = TYPEC_ORIENTATION_NORMAL;
@@ -3621,8 +3846,6 @@ static int qmp_combo_probe(struct platform_device *pdev)
phy_set_drvdata(qmp->dp_phy, qmp);
- dev_set_drvdata(dev, qmp);
-
if (usb_np == dev->of_node)
phy_provider = devm_of_phy_provider_register(dev, qmp_combo_phy_xlate);
else
@@ -3641,6 +3864,10 @@ err_node_put:
static const struct of_device_id qmp_combo_of_match_table[] = {
{
+ .compatible = "qcom,sar2130p-qmp-usb3-dp-phy",
+ .data = &sar2130p_usb3dpphy_cfg,
+ },
+ {
.compatible = "qcom,sc7180-qmp-usb3-dp-phy",
.data = &sc7180_usb3dpphy_cfg,
},
@@ -3686,7 +3913,7 @@ static const struct of_device_id qmp_combo_of_match_table[] = {
},
{
.compatible = "qcom,sm8650-qmp-usb3-dp-phy",
- .data = &sm8550_usb3dpphy_cfg,
+ .data = &sm8650_usb3dpphy_cfg,
},
{
.compatible = "qcom,x1e80100-qmp-usb3-dp-phy",
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-common.h b/drivers/phy/qualcomm/phy-qcom-qmp-common.h
new file mode 100644
index 000000000000..b945fc14cece
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-common.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_COMMON_H_
+#define QCOM_PHY_QMP_COMMON_H_
+
+struct qmp_phy_init_tbl {
+ unsigned int offset;
+ unsigned int val;
+ char *name;
+ /*
+ * mask of lanes for which this register is written
+ * for cases when second lane needs different values
+ */
+ u8 lane_mask;
+};
+
+#define QMP_PHY_INIT_CFG(o, v) \
+ { \
+ .offset = o, \
+ .val = v, \
+ .name = #o, \
+ .lane_mask = 0xff, \
+ }
+
+#define QMP_PHY_INIT_CFG_LANE(o, v, l) \
+ { \
+ .offset = o, \
+ .val = v, \
+ .name = #o, \
+ .lane_mask = l, \
+ }
+
+static inline void qmp_configure_lane(struct device *dev, void __iomem *base,
+ const struct qmp_phy_init_tbl tbl[],
+ int num, u8 lane_mask)
+{
+ int i;
+ const struct qmp_phy_init_tbl *t = tbl;
+
+ if (!t)
+ return;
+
+ for (i = 0; i < num; i++, t++) {
+ if (!(t->lane_mask & lane_mask))
+ continue;
+
+ dev_dbg(dev, "Writing Reg: %s Offset: 0x%04x Val: 0x%02x\n",
+ t->name, t->offset, t->val);
+ writel(t->val, base + t->offset);
+ }
+}
+
+static inline void qmp_configure(struct device *dev, void __iomem *base,
+ const struct qmp_phy_init_tbl tbl[], int num)
+{
+ qmp_configure_lane(dev, base, tbl, num, 0xff);
+}
+
+#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-dp-com-v3.h b/drivers/phy/qualcomm/phy-qcom-qmp-dp-com-v3.h
new file mode 100644
index 000000000000..396179ef38b0
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-dp-com-v3.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_DP_COM_V3_H_
+#define QCOM_PHY_QMP_DP_COM_V3_H_
+
+/* Only for QMP V3 & V4 PHY - DP COM registers */
+#define QPHY_V3_DP_COM_PHY_MODE_CTRL 0x00
+#define QPHY_V3_DP_COM_SW_RESET 0x04
+#define QPHY_V3_DP_COM_POWER_DOWN_CTRL 0x08
+#define QPHY_V3_DP_COM_SWI_CTRL 0x0c
+#define QPHY_V3_DP_COM_TYPEC_CTRL 0x10
+#define QPHY_V3_DP_COM_TYPEC_PWRDN_CTRL 0x14
+#define QPHY_V3_DP_COM_RESET_OVRD_CTRL 0x1c
+
+#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-dp-phy-v3.h b/drivers/phy/qualcomm/phy-qcom-qmp-dp-phy-v3.h
new file mode 100644
index 000000000000..00a9702abccd
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-dp-phy-v3.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_DP_PHY_V3_H_
+#define QCOM_PHY_QMP_DP_PHY_V3_H_
+
+/* Only for QMP V3 PHY - DP PHY registers */
+#define QSERDES_V3_DP_PHY_AUX_INTERRUPT_MASK 0x048
+#define QSERDES_V3_DP_PHY_AUX_INTERRUPT_CLEAR 0x04c
+#define QSERDES_V3_DP_PHY_AUX_BIST_CFG 0x050
+
+#define QSERDES_V3_DP_PHY_VCO_DIV 0x064
+#define QSERDES_V3_DP_PHY_TX0_TX1_LANE_CTL 0x06c
+#define QSERDES_V3_DP_PHY_TX2_TX3_LANE_CTL 0x088
+
+#define QSERDES_V3_DP_PHY_SPARE0 0x0ac
+#define QSERDES_V3_DP_PHY_STATUS 0x0c0
+
+#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-dp-phy-v4.h b/drivers/phy/qualcomm/phy-qcom-qmp-dp-phy-v4.h
new file mode 100644
index 000000000000..ed6795e1257c
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-dp-phy-v4.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_DP_PHY_V4_H_
+#define QCOM_PHY_QMP_DP_PHY_V4_H_
+
+/* Only for QMP V4 PHY - DP PHY registers */
+#define QSERDES_V4_DP_PHY_AUX_INTERRUPT_MASK 0x054
+#define QSERDES_V4_DP_PHY_AUX_INTERRUPT_CLEAR 0x058
+#define QSERDES_V4_DP_PHY_VCO_DIV 0x070
+#define QSERDES_V4_DP_PHY_TX0_TX1_LANE_CTL 0x078
+#define QSERDES_V4_DP_PHY_TX2_TX3_LANE_CTL 0x09c
+#define QSERDES_V4_DP_PHY_SPARE0 0x0c8
+#define QSERDES_V4_DP_PHY_AUX_INTERRUPT_STATUS 0x0d8
+#define QSERDES_V4_DP_PHY_STATUS 0x0dc
+
+#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-dp-phy-v5.h b/drivers/phy/qualcomm/phy-qcom-qmp-dp-phy-v5.h
new file mode 100644
index 000000000000..181057421c11
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-dp-phy-v5.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_DP_PHY_V5_H_
+#define QCOM_PHY_QMP_DP_PHY_V5_H_
+
+/* Only for QMP V5 PHY - DP PHY registers */
+#define QSERDES_V5_DP_PHY_VCO_DIV 0x070
+#define QSERDES_V5_DP_PHY_AUX_INTERRUPT_STATUS 0x0d8
+#define QSERDES_V5_DP_PHY_STATUS 0x0dc
+
+#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-dp-phy-v6.h b/drivers/phy/qualcomm/phy-qcom-qmp-dp-phy-v6.h
new file mode 100644
index 000000000000..fa967a1af058
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-dp-phy-v6.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_DP_PHY_V6_H_
+#define QCOM_PHY_QMP_DP_PHY_V6_H_
+
+/* Only for QMP V6 PHY - DP PHY registers */
+#define QSERDES_V6_DP_PHY_VCO_DIV 0x070
+#define QSERDES_V6_DP_PHY_AUX_INTERRUPT_STATUS 0x0e0
+#define QSERDES_V6_DP_PHY_STATUS 0x0e4
+
+#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-dp-phy.h b/drivers/phy/qualcomm/phy-qcom-qmp-dp-phy.h
new file mode 100644
index 000000000000..0ebd405bcaf0
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-dp-phy.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_DP_PHY_H_
+#define QCOM_PHY_QMP_DP_PHY_H_
+
+/* QMP PHY - DP PHY registers */
+#define QSERDES_DP_PHY_REVISION_ID0 0x000
+#define QSERDES_DP_PHY_REVISION_ID1 0x004
+#define QSERDES_DP_PHY_REVISION_ID2 0x008
+#define QSERDES_DP_PHY_REVISION_ID3 0x00c
+#define QSERDES_DP_PHY_CFG 0x010
+#define QSERDES_DP_PHY_CFG_1 0x014
+#define QSERDES_DP_PHY_PD_CTL 0x018
+#define QSERDES_DP_PHY_MODE 0x01c
+#define QSERDES_DP_PHY_AUX_CFG0 0x020
+#define QSERDES_DP_PHY_AUX_CFG1 0x024
+#define QSERDES_DP_PHY_AUX_CFG2 0x028
+#define QSERDES_DP_PHY_AUX_CFG3 0x02c
+#define QSERDES_DP_PHY_AUX_CFG4 0x030
+#define QSERDES_DP_PHY_AUX_CFG5 0x034
+#define QSERDES_DP_PHY_AUX_CFG6 0x038
+#define QSERDES_DP_PHY_AUX_CFG7 0x03c
+#define QSERDES_DP_PHY_AUX_CFG8 0x040
+#define QSERDES_DP_PHY_AUX_CFG9 0x044
+
+/* QSERDES COM_BIAS_EN_CLKBUFLR_EN bits */
+# define QSERDES_V3_COM_BIAS_EN 0x0001
+# define QSERDES_V3_COM_BIAS_EN_MUX 0x0002
+# define QSERDES_V3_COM_CLKBUF_R_EN 0x0004
+# define QSERDES_V3_COM_CLKBUF_L_EN 0x0008
+# define QSERDES_V3_COM_EN_SYSCLK_TX_SEL 0x0010
+# define QSERDES_V3_COM_CLKBUF_RX_DRIVE_L 0x0020
+# define QSERDES_V3_COM_CLKBUF_RX_DRIVE_R 0x0040
+
+/* QPHY_TX_TX_EMP_POST1_LVL bits */
+# define DP_PHY_TXn_TX_EMP_POST1_LVL_MASK 0x001f
+# define DP_PHY_TXn_TX_EMP_POST1_LVL_MUX_EN 0x0020
+
+/* QPHY_TX_TX_DRV_LVL bits */
+# define DP_PHY_TXn_TX_DRV_LVL_MASK 0x001f
+# define DP_PHY_TXn_TX_DRV_LVL_MUX_EN 0x0020
+
+/* QSERDES_DP_PHY_PD_CTL bits */
+# define DP_PHY_PD_CTL_PWRDN 0x001
+# define DP_PHY_PD_CTL_PSR_PWRDN 0x002
+# define DP_PHY_PD_CTL_AUX_PWRDN 0x004
+# define DP_PHY_PD_CTL_LANE_0_1_PWRDN 0x008
+# define DP_PHY_PD_CTL_LANE_2_3_PWRDN 0x010
+# define DP_PHY_PD_CTL_PLL_PWRDN 0x020
+# define DP_PHY_PD_CTL_DP_CLAMP_EN 0x040
+
+/* QPHY_DP_PHY_AUX_INTERRUPT_STATUS bits */
+# define PHY_AUX_STOP_ERR_MASK 0x01
+# define PHY_AUX_DEC_ERR_MASK 0x02
+# define PHY_AUX_SYNC_ERR_MASK 0x04
+# define PHY_AUX_ALIGN_ERR_MASK 0x08
+# define PHY_AUX_REQ_ERR_MASK 0x10
+
+#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c
index ab61a9c73b18..a7c65cfe31df 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c
@@ -19,19 +19,13 @@
#include <linux/reset.h>
#include <linux/slab.h>
+#include "phy-qcom-qmp-common.h"
+
#include "phy-qcom-qmp.h"
-/* QPHY_SW_RESET bit */
-#define SW_RESET BIT(0)
-/* QPHY_POWER_DOWN_CONTROL */
-#define SW_PWRDN BIT(0)
-#define REFCLK_DRV_DSBL BIT(1)
/* QPHY_START_CONTROL bits */
-#define SERDES_START BIT(0)
-#define PCS_START BIT(1)
#define PLL_READY_GATE_EN BIT(3)
-/* QPHY_PCS_STATUS bit */
-#define PHYSTATUS BIT(6)
+
/* QPHY_COM_PCS_READY_STATUS bit */
#define PCS_READY BIT(0)
@@ -39,30 +33,6 @@
#define POWER_DOWN_DELAY_US_MIN 10
#define POWER_DOWN_DELAY_US_MAX 20
-struct qmp_phy_init_tbl {
- unsigned int offset;
- unsigned int val;
- /*
- * mask of lanes for which this register is written
- * for cases when second lane needs different values
- */
- u8 lane_mask;
-};
-
-#define QMP_PHY_INIT_CFG(o, v) \
- { \
- .offset = o, \
- .val = v, \
- .lane_mask = 0xff, \
- }
-
-#define QMP_PHY_INIT_CFG_LANE(o, v, l) \
- { \
- .offset = o, \
- .val = v, \
- .lane_mask = l, \
- }
-
/* set of registers with offsets different per-PHY */
enum qphy_reg_layout {
/* Common block control registers */
@@ -307,32 +277,6 @@ static const struct qmp_phy_cfg msm8996_pciephy_cfg = {
.regs = pciephy_regs_layout,
};
-static void qmp_pcie_msm8996_configure_lane(void __iomem *base,
- const struct qmp_phy_init_tbl tbl[],
- int num,
- u8 lane_mask)
-{
- int i;
- const struct qmp_phy_init_tbl *t = tbl;
-
- if (!t)
- return;
-
- for (i = 0; i < num; i++, t++) {
- if (!(t->lane_mask & lane_mask))
- continue;
-
- writel(t->val, base + t->offset);
- }
-}
-
-static void qmp_pcie_msm8996_configure(void __iomem *base,
- const struct qmp_phy_init_tbl tbl[],
- int num)
-{
- qmp_pcie_msm8996_configure_lane(base, tbl, num, 0xff);
-}
-
static int qmp_pcie_msm8996_serdes_init(struct qmp_phy *qphy)
{
struct qcom_qmp *qmp = qphy->qmp;
@@ -344,7 +288,7 @@ static int qmp_pcie_msm8996_serdes_init(struct qmp_phy *qphy)
unsigned int val;
int ret;
- qmp_pcie_msm8996_configure(serdes, serdes_tbl, serdes_tbl_num);
+ qmp_configure(qmp->dev, serdes, serdes_tbl, serdes_tbl_num);
qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], SW_RESET);
qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL],
@@ -487,9 +431,9 @@ static int qmp_pcie_msm8996_power_on(struct phy *phy)
}
/* Tx, Rx, and PCS configurations */
- qmp_pcie_msm8996_configure_lane(tx, cfg->tx_tbl, cfg->tx_tbl_num, 1);
- qmp_pcie_msm8996_configure_lane(rx, cfg->rx_tbl, cfg->rx_tbl_num, 1);
- qmp_pcie_msm8996_configure(pcs, cfg->pcs_tbl, cfg->pcs_tbl_num);
+ qmp_configure_lane(qmp->dev, tx, cfg->tx_tbl, cfg->tx_tbl_num, 1);
+ qmp_configure_lane(qmp->dev, rx, cfg->rx_tbl, cfg->rx_tbl_num, 1);
+ qmp_configure(qmp->dev, pcs, cfg->pcs_tbl, cfg->pcs_tbl_num);
/*
* Pull out PHY from POWER DOWN state.
@@ -781,7 +725,6 @@ static int qmp_pcie_msm8996_probe(struct platform_device *pdev)
{
struct qcom_qmp *qmp;
struct device *dev = &pdev->dev;
- struct device_node *child;
struct phy_provider *phy_provider;
void __iomem *serdes;
const struct qmp_phy_cfg *cfg = NULL;
@@ -829,13 +772,13 @@ static int qmp_pcie_msm8996_probe(struct platform_device *pdev)
return -ENOMEM;
id = 0;
- for_each_available_child_of_node(dev->of_node, child) {
+ for_each_available_child_of_node_scoped(dev->of_node, child) {
/* Create per-lane phy */
ret = qmp_pcie_msm8996_create(dev, child, id, serdes, cfg);
if (ret) {
dev_err(dev, "failed to create lane%d phy, %d\n",
id, ret);
- goto err_node_put;
+ return ret;
}
/*
@@ -846,7 +789,7 @@ static int qmp_pcie_msm8996_probe(struct platform_device *pdev)
if (ret) {
dev_err(qmp->dev,
"failed to register pipe clock source\n");
- goto err_node_put;
+ return ret;
}
id++;
@@ -855,10 +798,6 @@ static int qmp_pcie_msm8996_probe(struct platform_device *pdev)
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
return PTR_ERR_OR_ZERO(phy_provider);
-
-err_node_put:
- of_node_put(child);
- return ret;
}
static struct platform_driver qmp_pcie_msm8996_driver = {
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
index 2af7115ef968..018bbb300830 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
@@ -22,6 +22,10 @@
#include <linux/reset.h>
#include <linux/slab.h>
+#include <dt-bindings/phy/phy-qcom-qmp.h>
+
+#include "phy-qcom-qmp-common.h"
+
#include "phy-qcom-qmp.h"
#include "phy-qcom-qmp-pcs-misc-v3.h"
#include "phy-qcom-qmp-pcs-pcie-v4.h"
@@ -30,46 +34,12 @@
#include "phy-qcom-qmp-pcs-pcie-v5_20.h"
#include "phy-qcom-qmp-pcs-pcie-v6.h"
#include "phy-qcom-qmp-pcs-pcie-v6_20.h"
+#include "phy-qcom-qmp-pcs-pcie-v6_30.h"
+#include "phy-qcom-qmp-pcs-v6_30.h"
#include "phy-qcom-qmp-pcie-qhp.h"
-/* QPHY_SW_RESET bit */
-#define SW_RESET BIT(0)
-/* QPHY_POWER_DOWN_CONTROL */
-#define SW_PWRDN BIT(0)
-#define REFCLK_DRV_DSBL BIT(1)
-/* QPHY_START_CONTROL bits */
-#define SERDES_START BIT(0)
-#define PCS_START BIT(1)
-/* QPHY_PCS_STATUS bit */
-#define PHYSTATUS BIT(6)
-#define PHYSTATUS_4_20 BIT(7)
-
#define PHY_INIT_COMPLETE_TIMEOUT 10000
-struct qmp_phy_init_tbl {
- unsigned int offset;
- unsigned int val;
- /*
- * mask of lanes for which this register is written
- * for cases when second lane needs different values
- */
- u8 lane_mask;
-};
-
-#define QMP_PHY_INIT_CFG(o, v) \
- { \
- .offset = o, \
- .val = v, \
- .lane_mask = 0xff, \
- }
-
-#define QMP_PHY_INIT_CFG_LANE(o, v, l) \
- { \
- .offset = o, \
- .val = v, \
- .lane_mask = l, \
- }
-
/* set of registers with offsets different per-PHY */
enum qphy_reg_layout {
/* PCS registers */
@@ -116,6 +86,13 @@ static const unsigned int pciephy_v5_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V5_PCS_POWER_DOWN_CONTROL,
};
+static const unsigned int pciephy_v6_regs_layout[QPHY_LAYOUT_SIZE] = {
+ [QPHY_SW_RESET] = QPHY_V6_PCS_SW_RESET,
+ [QPHY_START_CTRL] = QPHY_V6_PCS_START_CONTROL,
+ [QPHY_PCS_STATUS] = QPHY_V6_PCS_PCS_STATUS1,
+ [QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V6_PCS_POWER_DOWN_CONTROL,
+};
+
static const struct qmp_phy_init_tbl msm8998_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30),
@@ -514,6 +491,320 @@ static const struct qmp_phy_init_tbl ipq8074_pcie_gen3_pcs_misc_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1),
};
+static const struct qmp_phy_init_tbl ipq9574_gen3x1_pcie_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CLKBUFLR_EN, 0x18),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CTRL_BY_PSM, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_SELECT, 0x31),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_IVCO, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_BG_TRIM, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CMN_CONFIG, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP_EN, 0x42),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_RESETSM_CNTRL, 0x20),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE_MAP, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE_TIMER1, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE_TIMER2, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CORE_CLK_EN, 0x30),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_HSCLK_SEL, 0x21),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE0, 0x68),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START3_MODE0, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START2_MODE0, 0xaa),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START1_MODE0, 0xab),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE0, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE0, 0xd4),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE0, 0x09),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE0, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE0, 0x28),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN1_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE0, 0xa0),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE0, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE0, 0x24),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CORE_CLK_EN, 0x20),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CORECLK_DIV, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_SELECT, 0x32),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SYS_CLK_CTRL, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_BUF_ENABLE, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_EN_SEL, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_BG_TIMER, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_HSCLK_SEL, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE1, 0x53),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START3_MODE1, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START2_MODE1, 0x55),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START1_MODE1, 0x55),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE1, 0x29),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE1, 0xaa),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE1, 0x09),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE1, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE1, 0x28),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN1_MODE1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE1, 0xa0),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE1, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE1, 0xb4),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CORE_CLK_EN, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CORECLK_DIV_MODE1, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_EN_CENTER, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER1, 0x7d),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER2, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_ADJ_PER1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_ADJ_PER2, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE1_MODE0, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE2_MODE0, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE1_MODE1, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE2_MODE1, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_EP_DIV_MODE0, 0x19),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_EP_DIV_MODE1, 0x28),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_ENABLE1, 0x90),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_HSCLK_SEL, 0x89),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_ENABLE1, 0x10),
+};
+
+static const struct qmp_phy_init_tbl ipq9574_gen3x2_pcie_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CLKBUFLR_EN, 0x18),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CTRL_BY_PSM, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_SELECT, 0x31),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_IVCO, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_BG_TRIM, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CMN_CONFIG, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP_EN, 0x42),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_RESETSM_CNTRL, 0x20),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE_MAP, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE_TIMER1, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE_TIMER2, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CORE_CLK_EN, 0x30),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_HSCLK_SEL, 0x21),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE0, 0x68),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START3_MODE0, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START2_MODE0, 0xaa),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START1_MODE0, 0xab),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE0, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE0, 0xd4),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE0, 0x09),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE0, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE0, 0x28),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN1_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE0, 0xa0),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE0, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE0, 0x24),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CORE_CLK_EN, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CORECLK_DIV, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_SELECT, 0x32),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SYS_CLK_CTRL, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_BUF_ENABLE, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_EN_SEL, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_BG_TIMER, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_HSCLK_SEL, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE1, 0x53),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START3_MODE1, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START2_MODE1, 0x55),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START1_MODE1, 0x55),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE1, 0x29),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE1, 0xaa),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE1, 0x09),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE1, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE1, 0x28),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN1_MODE1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE1, 0xa0),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE1, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE1, 0xb4),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CORE_CLK_EN, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CORECLK_DIV_MODE1, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_EN_CENTER, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER1, 0x7d),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER2, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_ADJ_PER1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_ADJ_PER2, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE1_MODE0, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE2_MODE0, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE1_MODE1, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE2_MODE1, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_EP_DIV_MODE0, 0x19),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_EP_DIV_MODE1, 0x28),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_ENABLE1, 0x90),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_HSCLK_SEL, 0x89),
+ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_ENABLE1, 0x10),
+};
+
+static const struct qmp_phy_init_tbl ipq9574_pcie_rx_tbl[] = {
+ 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, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x61),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1e),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0c),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x02),
+ 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_CNTRL1, 0x73),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_LOW, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH2, 0xc8),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH3, 0x09),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH4, 0xb1),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xc8),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x09),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb1),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0xf0),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0x2f),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0xd3),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x40),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0),
+};
+
+static const struct qmp_phy_init_tbl ipq9574_gen3x1_pcie_pcs_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_H, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_DCC_CAL_CONFIG, 0x01),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x0d),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_G12S1_TXDEEMPH_M3P5DB, 0x10),
+};
+
+static const struct qmp_phy_init_tbl ipq9574_gen3x1_pcie_pcs_misc_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG2, 0x0d),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_H, 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_H, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_EQ_CONFIG1, 0x14),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_EQ_CONFIG1, 0x10),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_EQ_CONFIG2, 0x0b),
+ 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_POWER_STATE_CONFIG4, 0x07),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_CONFIG2, 0x52),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_INT_AUX_CLK_CONFIG1, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_MODE2_CONFIG2, 0x50),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_MODE2_CONFIG4, 0x1a),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_MODE2_CONFIG5, 0x06),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_MODE2_CONFIG6, 0x03),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1),
+};
+
+static const struct qmp_phy_init_tbl ipq9574_gen3x2_pcie_pcs_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x0d),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_G12S1_TXDEEMPH_M3P5DB, 0x10),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_H, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_DCC_CAL_CONFIG, 0x01),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa),
+};
+
+static const struct qmp_phy_init_tbl ipq9574_gen3x2_pcie_pcs_misc_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_POWER_STATE_CONFIG2, 0x1d),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_H, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_H, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_EQ_CONFIG1, 0x14),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_EQ_CONFIG1, 0x10),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_EQ_CONFIG2, 0x0b),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_PRESET_P10_PRE, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_PRESET_P10_POST, 0x58),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_POWER_STATE_CONFIG4, 0x07),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_OSC_DTCT_CONFIG1, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_OSC_DTCT_CONFIG2, 0x52),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_OSC_DTCT_CONFIG4, 0x19),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_INT_AUX_CLK_CONFIG1, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_OSC_DTCT_MODE2_CONFIG2, 0x49),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_OSC_DTCT_MODE2_CONFIG4, 0x2a),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_OSC_DTCT_MODE2_CONFIG5, 0x02),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_OSC_DTCT_MODE2_CONFIG6, 0x03),
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1),
+};
+
+static const struct qmp_phy_init_tbl qcs615_pcie_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x18),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10),
+ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0xf),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x1),
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x0),
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x6),
+ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0xf),
+ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x0),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x1),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x20),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0xa),
+ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x20),
+ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x9),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x4),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x3),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x0),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0xd),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x35),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x2),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x4),
+ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x30),
+ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x0),
+ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CTRL_BY_PSM, 0x1),
+ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0xa),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x1),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x1),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x2),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x0),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0x2f),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x19),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_EP_DIV, 0x19),
+};
+
+static const struct qmp_phy_init_tbl qcs615_pcie_rx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x1c),
+ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x1),
+ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x0),
+ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xdb),
+ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b),
+ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x4),
+ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN_HALF, 0x4),
+};
+
+static const struct qmp_phy_init_tbl qcs615_pcie_tx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45),
+ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x6),
+ QMP_PHY_INIT_CFG(QSERDES_TX_RES_CODE_LANE_OFFSET, 0x2),
+ QMP_PHY_INIT_CFG(QSERDES_TX_RCV_DETECT_LVL_2, 0x12),
+};
+
+static const struct qmp_phy_init_tbl qcs615_pcie_pcs_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V2_PCS_ENDPOINT_REFCLK_DRIVE, 0x4),
+ QMP_PHY_INIT_CFG(QPHY_V2_PCS_OSC_DTCT_ACTIONS, 0x0),
+ QMP_PHY_INIT_CFG(QPHY_V2_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x40),
+ QMP_PHY_INIT_CFG(QPHY_V2_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x0),
+ QMP_PHY_INIT_CFG(QPHY_V2_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB, 0x40),
+ QMP_PHY_INIT_CFG(QPHY_V2_PCS_PLL_LOCK_CHK_DLY_TIME_AUXCLK_LSB, 0x0),
+ QMP_PHY_INIT_CFG(QPHY_V2_PCS_LP_WAKEUP_DLY_TIME_AUXCLK, 0x40),
+ QMP_PHY_INIT_CFG(QPHY_V2_PCS_PLL_LOCK_CHK_DLY_TIME, 0x73),
+ QMP_PHY_INIT_CFG(QPHY_V2_PCS_SIGDET_CNTRL, 0x7),
+ QMP_PHY_INIT_CFG(QPHY_V2_PCS_RX_SIGDET_LVL, 0x99),
+ QMP_PHY_INIT_CFG(QPHY_V2_PCS_TXDEEMPH_M6DB_V0, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V2_PCS_TXDEEMPH_M3P5DB_V0, 0xe),
+};
+
static const struct qmp_phy_init_tbl sdm845_qmp_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30),
@@ -982,6 +1273,304 @@ static const struct qmp_phy_init_tbl sc8280xp_qmp_gen3x2_pcie_pcs_misc_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00),
};
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x2_pcie_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE1, 0x26),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE1, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE1, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE1, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORECLK_DIV_MODE1, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE1, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE1, 0x1a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x68),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE1, 0xab),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE1, 0xaa),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE1, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x12),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE0, 0xf8),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE0, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CORE_CLK_DIV_MODE0, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x0d),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x41),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE0, 0xab),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE0, 0xaa),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE0, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_HS_SWITCH_SEL_1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_BG_TIMER, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_EN_CENTER, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER1, 0x62),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER2, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_POST_DIV_MUX, 0x40),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_ENABLE1, 0x90),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYS_CLK_CTRL, 0x82),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x46),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_CFG, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_SELECT, 0x34),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORE_CLK_EN, 0xa0),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_MISC_1, 0x88),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_MODE, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_VCO_DC_LEVEL_CTRL, 0x0f),
+};
+
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x4_pcie_serdes_4ln_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN, 0x1c),
+};
+
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x2_pcie_ln_shrd_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RXCLK_DIV2_CTRL, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_DFE_DAC_ENABLE1, 0x88),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_TX_ADAPT_POST_THRESH1, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_TX_ADAPT_POST_THRESH2, 0x0d),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B0, 0xd4),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B1, 0x12),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B2, 0xdb),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B3, 0x9a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B4, 0x32),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B5, 0xb6),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B6, 0x64),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH1_RATE210, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH1_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH2_RATE210, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH2_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH3_RATE210, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH3_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH4_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH5_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH6_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_SUMMER_CAL_SPD_MODE, 0x5b),
+};
+
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x2_pcie_tx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_RES_CODE_LANE_OFFSET_TX, 0x1d),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_RES_CODE_LANE_OFFSET_RX, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_LANE_MODE_1, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_LANE_MODE_2, 0x10),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_LANE_MODE_3, 0x51),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_TRAN_DRVR_EMP_EN, 0x34),
+};
+
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x2_pcie_rx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_FO_GAIN_RATE_2, 0x0c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_SO_GAIN_RATE_2, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_FO_GAIN_RATE_3, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_PI_CONTROLS, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_SO_ACC_DEFAULT_VAL_RATE3, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_IVCM_CAL_CTRL2, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_IVCM_POSTCAL_OFFSET, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_BKUP_CTRL1, 0x15),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_DFE_1, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_DFE_2, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_DFE_3, 0x45),
+ QMP_PHY_INIT_CFG_LANE(QSERDES_V6_20_RX_VGA_CAL_MAN_VAL, 0x0a, 1),
+ QMP_PHY_INIT_CFG_LANE(QSERDES_V6_20_RX_VGA_CAL_MAN_VAL, 0x0b, 2),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_VGA_CAL_CNTRL1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_GM_CAL, 0x0d),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_EQU_ADAPTOR_CNTRL4, 0x0b),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_SIGDET_ENABLES, 0x1c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_PHPRE_CTRL, 0x20),
+ QMP_PHY_INIT_CFG_LANE(QSERDES_V6_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x3a, 1),
+ QMP_PHY_INIT_CFG_LANE(QSERDES_V6_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38, 2),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_Q_PI_INTRINSIC_BIAS_RATE32, 0x39),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B0, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B1, 0xb3),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B2, 0x58),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B3, 0x9a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B4, 0x26),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B5, 0xb6),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B6, 0xee),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B0, 0xe4),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B1, 0xa4),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B2, 0x60),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B3, 0xdf),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B4, 0x4b),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B5, 0x76),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B6, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_TX_ADPT_CTRL, 0x10),
+};
+
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x2_pcie_pcs_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_G3S2_PRE_GAIN, 0x2e),
+ QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_RX_SIGDET_LVL, 0xcc),
+ QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_EQ_CONFIG4, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_EQ_CONFIG5, 0x22),
+ QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_TX_RX_CONFIG1, 0x04),
+ QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_TX_RX_CONFIG2, 0x02),
+};
+
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x2_pcie_pcs_misc_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_ENDPOINT_REFCLK_DRIVE, 0xc1),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_OSC_DTCT_ATCIONS, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_EQ_CONFIG1, 0x16),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_EQ_CONFIG5, 0x02),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G4_PRE_GAIN, 0x2e),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_RX_MARGINING_CONFIG1, 0x03),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_RX_MARGINING_CONFIG3, 0x28),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G3_RXEQEVAL_TIME, 0x27),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G4_RXEQEVAL_TIME, 0x27),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_TX_RX_CONFIG, 0xc0),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_POWER_STATE_CONFIG2, 0x1d),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_RX_MARGINING_CONFIG5, 0x18),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G3_FOM_EQ_CONFIG5, 0x7a),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G4_FOM_EQ_CONFIG5, 0x8a),
+};
+
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x8_pcie_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE1, 0x26),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE1, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE1, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE1, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORECLK_DIV_MODE1, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE1, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE1, 0x0d),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x68),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE1, 0xab),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE1, 0xaa),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE1, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x12),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE0, 0xf8),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE0, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CORE_CLK_DIV_MODE0, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x0d),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x41),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE0, 0xab),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE0, 0xaa),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE0, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_HS_SWITCH_SEL_1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_BG_TIMER, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_EN_CENTER, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER1, 0x62),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER2, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_POST_DIV_MUX, 0x40),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN, 0x1c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_ENABLE1, 0x90),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYS_CLK_CTRL, 0x82),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x46),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_CFG, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_SELECT, 0x34),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORE_CLK_EN, 0x20),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_MISC_1, 0x88),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_MODE, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_VCO_DC_LEVEL_CTRL, 0x0f),
+};
+
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x8_pcie_ln_shrd_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RXCLK_DIV2_CTRL, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_SUMMER_CAL_SPD_MODE, 0x5b),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_DFE_DAC_ENABLE1, 0x88),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_TX_ADAPT_POST_THRESH1, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_TX_ADAPT_POST_THRESH2, 0x0d),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B0, 0x12),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B1, 0x12),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B2, 0xdb),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B3, 0x9a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B4, 0x38),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B5, 0xb6),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B6, 0x64),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH1_RATE210, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH1_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH2_RATE210, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH2_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH3_RATE210, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH3_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH4_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH5_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH6_RATE3, 0x1f),
+};
+
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x8_pcie_txz_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_RES_CODE_LANE_OFFSET_TX, 0x1a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_RES_CODE_LANE_OFFSET_RX, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_LANE_MODE_1, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_LANE_MODE_2, 0x10),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_LANE_MODE_3, 0x51),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_TRAN_DRVR_EMP_EN, 0x34),
+};
+
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x8_pcie_rxz_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_FO_GAIN_RATE_2, 0x0c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_SO_GAIN_RATE_2, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_FO_GAIN_RATE_3, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_PI_CONTROLS, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_SO_ACC_DEFAULT_VAL_RATE3, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_IVCM_CAL_CTRL2, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_IVCM_POSTCAL_OFFSET, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_BKUP_CTRL1, 0x15),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_DFE_3, 0x45),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_VGA_CAL_MAN_VAL, 0x0c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_VGA_CAL_CNTRL1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_GM_CAL, 0x0d),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_EQU_ADAPTOR_CNTRL4, 0x0b),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_SIGDET_ENABLES, 0x1c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_PHPRE_CTRL, 0x20),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_Q_PI_INTRINSIC_BIAS_RATE32, 0x39),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B0, 0xd4),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B1, 0x23),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B2, 0x58),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B3, 0x9a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B4, 0x38),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B5, 0xb6),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B6, 0xee),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B0, 0x1c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B1, 0xe4),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B2, 0x60),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B3, 0xdf),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B4, 0x69),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B5, 0x76),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B6, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_TX_ADPT_CTRL, 0x10),
+};
+
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x8_pcie_rx_tbl[] = {
+ QMP_PHY_INIT_CFG_LANE(QSERDES_V6_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x3a, BIT(0)),
+};
+
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x8_pcie_pcs_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V6_30_PCS_LOCK_DETECT_CONFIG2, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V6_30_PCS_G3S2_PRE_GAIN, 0x2e),
+ QMP_PHY_INIT_CFG(QPHY_V6_30_PCS_RX_SIGDET_LVL, 0x99),
+ QMP_PHY_INIT_CFG(QPHY_V6_30_PCS_ALIGN_DETECT_CONFIG7, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V6_30_PCS_EQ_CONFIG4, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V6_30_PCS_EQ_CONFIG5, 0x22),
+ QMP_PHY_INIT_CFG(QPHY_V6_30_PCS_TX_RX_CONFIG, 0x04),
+ QMP_PHY_INIT_CFG(QPHY_V6_30_PCS_TX_RX_CONFIG2, 0x02),
+};
+
+static const struct qmp_phy_init_tbl x1e80100_qmp_gen4x8_pcie_pcs_misc_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_ENDPOINT_REFCLK_DRIVE, 0xc1),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_OSC_DTCT_ACTIONS, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_EQ_CONFIG1, 0x16),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_G4_EQ_CONFIG5, 0x02),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_G4_PRE_GAIN, 0x2e),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_RX_MARGINING_CONFIG1, 0x03),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_RX_MARGINING_CONFIG3, 0x28),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_RX_MARGINING_CONFIG5, 0x18),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_G3_FOM_EQ_CONFIG5, 0x7a),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_G4_FOM_EQ_CONFIG5, 0x8a),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_G3_RXEQEVAL_TIME, 0x27),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_G4_RXEQEVAL_TIME, 0x27),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_TX_RX_CONFIG, 0xc0),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_30_PCS_POWER_STATE_CONFIG2, 0x1d),
+};
+
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),
@@ -1261,7 +1850,7 @@ static const struct qmp_phy_init_tbl sdx55_qmp_pcie_rc_pcs_misc_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00),
};
-static const struct qmp_phy_init_tbl sdx55_qmp_pcie_ep_pcs_misc_tbl[] = {
+static const struct qmp_phy_init_tbl sdx55_qmp_pcie_ep_pcs_lane1_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_LANE1_INSIG_SW_CTRL2, 0x00),
QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_LANE1_INSIG_MX_CTRL2, 0x00),
};
@@ -1395,6 +1984,9 @@ static const struct qmp_phy_init_tbl sdx65_qmp_pcie_pcs_misc_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_G4_EQ_CONFIG2, 0x0d),
QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_G4_EQ_CONFIG5, 0x02),
QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_G4_PRE_GAIN, 0x2e),
+};
+
+static const struct qmp_phy_init_tbl sdx65_qmp_pcie_pcs_lane1_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_LANE1_INSIG_SW_CTRL2, 0x00),
QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_LANE1_INSIG_MX_CTRL2, 0x00),
};
@@ -1747,7 +2339,7 @@ static const struct qmp_phy_init_tbl sm8550_qmp_gen3x2_pcie_rx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_10_HIGH2, 0x5b),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_10_HIGH3, 0x1a),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_10_HIGH4, 0x89),
- QMP_PHY_INIT_CFG(QSERDES_V6_RX_TX_ADAPT_POST_THRESH, 0xf0),
+ QMP_PHY_INIT_CFG(QSERDES_V6_RX_TX_ADAPT_POST_THRESH, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_FO_GAIN, 0x09),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_SO_GAIN, 0x05),
QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_SB2_THRESH1, 0x08),
@@ -1767,6 +2359,8 @@ static const struct qmp_phy_init_tbl sm8550_qmp_gen3x2_pcie_pcs_tbl[] = {
};
static const struct qmp_phy_init_tbl sm8550_qmp_gen3x2_pcie_pcs_misc_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_EQ_CONFIG1, 0x1e),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_RXEQEVAL_TIME, 0x27),
QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_POWER_STATE_CONFIG2, 0x1d),
QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_POWER_STATE_CONFIG4, 0x07),
QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1),
@@ -1823,10 +2417,9 @@ static const struct qmp_phy_init_tbl sm8550_qmp_gen4x2_pcie_serdes_tbl[] = {
static const struct qmp_phy_init_tbl sm8550_qmp_gen4x2_pcie_ln_shrd_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RXCLK_DIV2_CTRL, 0x01),
- QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_Q_EN_RATES, 0xe),
QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_DFE_DAC_ENABLE1, 0x00),
- QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_TX_ADAPT_POST_THRESH1, 0x00),
- QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_TX_ADAPT_POST_THRESH2, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_TX_ADAPT_POST_THRESH1, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_TX_ADAPT_POST_THRESH2, 0x0d),
QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B0, 0x12),
QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B1, 0x12),
QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B2, 0xdb),
@@ -1843,6 +2436,7 @@ static const struct qmp_phy_init_tbl sm8550_qmp_gen4x2_pcie_ln_shrd_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH4_RATE3, 0x1f),
QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH5_RATE3, 0x1f),
QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH6_RATE3, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_SUMMER_CAL_SPD_MODE, 0x5b),
};
static const struct qmp_phy_init_tbl sm8550_qmp_gen4x2_pcie_tx_tbl[] = {
@@ -1855,13 +2449,15 @@ static const struct qmp_phy_init_tbl sm8550_qmp_gen4x2_pcie_tx_tbl[] = {
};
static const struct qmp_phy_init_tbl sm8550_qmp_gen4x2_pcie_rx_tbl[] = {
- QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_FO_GAIN_RATE_2, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_FO_GAIN_RATE_2, 0x0c),
QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_FO_GAIN_RATE_3, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_SO_GAIN_RATE_2, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_PI_CONTROLS, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_SO_ACC_DEFAULT_VAL_RATE3, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_IVCM_CAL_CTRL2, 0x80),
QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_IVCM_POSTCAL_OFFSET, 0x7c),
QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_DFE_3, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_TX_ADPT_CTRL, 0x10),
QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_VGA_CAL_MAN_VAL, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_GM_CAL, 0x0d),
QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_EQU_ADAPTOR_CNTRL4, 0x0b),
@@ -1883,11 +2479,13 @@ static const struct qmp_phy_init_tbl sm8550_qmp_gen4x2_pcie_rx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B4, 0x78),
QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B5, 0x76),
QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B6, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_V6_20_VGA_CAL_CNTRL1, 0x00),
};
static const struct qmp_phy_init_tbl sm8550_qmp_gen4x2_pcie_pcs_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_G12S1_TXDEEMPH_M6DB, 0x17),
QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_G3S2_PRE_GAIN, 0x2e),
- QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_COM_ELECIDLE_DLY_SEL, 0x25),
+ QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_RX_SIGDET_LVL, 0xcc),
QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_EQ_CONFIG4, 0x00),
QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_EQ_CONFIG5, 0x22),
QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_TX_RX_CONFIG1, 0x04),
@@ -1898,6 +2496,8 @@ static const struct qmp_phy_init_tbl sm8550_qmp_gen4x2_pcie_pcs_misc_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_ENDPOINT_REFCLK_DRIVE, 0xc1),
QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_OSC_DTCT_ATCIONS, 0x00),
QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_EQ_CONFIG1, 0x16),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G3_RXEQEVAL_TIME, 0x27),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G4_RXEQEVAL_TIME, 0x27),
QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_EQ_CONFIG5, 0x02),
QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G4_PRE_GAIN, 0x2e),
QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_RX_MARGINING_CONFIG1, 0x03),
@@ -2062,8 +2662,6 @@ static const struct qmp_phy_init_tbl sa8775p_qmp_gen4_pcie_rc_pcs_misc_tbl[] = {
static const struct qmp_phy_init_tbl sa8775p_qmp_gen4x2_pcie_pcs_alt_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_EQ_CONFIG4, 0x16),
QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_EQ_CONFIG5, 0x22),
- QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_LANE1_INSIG_SW_CTRL2, 0x00),
- QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_LANE1_INSIG_MX_CTRL2, 0x00),
QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_G3S2_PRE_GAIN, 0x2e),
QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_RX_SIGDET_LVL, 0x66),
};
@@ -2128,6 +2726,7 @@ static const struct qmp_phy_init_tbl sa8775p_qmp_gen4x4_pcie_pcs_alt_tbl[] = {
};
static const struct qmp_phy_init_tbl sa8775p_qmp_gen4x4_pcie_serdes_alt_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIAS_EN_CLKBUFLR_EN, 0x1c),
QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_IVCO, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x36),
QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE1, 0x36),
@@ -2154,7 +2753,6 @@ static const struct qmp_phy_init_tbl sa8775p_qmp_gen4x4_pcie_rc_serdes_alt_tbl[]
QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE0, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE1, 0x97),
QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE1, 0x0c),
- QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIAS_EN_CLKBUFLR_EN, 0x1c),
QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_ENABLE1, 0x90),
QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE0, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE1, 0x06),
@@ -2204,14 +2802,112 @@ static const struct qmp_phy_init_tbl sa8775p_qmp_gen4x2_pcie_ep_pcs_alt_tbl[] =
QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_INSIG_SW_CTRL7, 0x00),
};
+static const struct qmp_phy_init_tbl sar2130p_qmp_gen3x2_pcie_rc_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_EN_CENTER, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER1, 0x31),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER2, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE0, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE0, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE1, 0x4c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE1, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_ENABLE1, 0x90),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYS_CLK_CTRL, 0x82),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE1, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE1, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_BG_TIMER, 0x0e),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x42),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x1a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE1, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE1, 0x34),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x82),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x68),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE0, 0xab),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE0, 0xea),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE0, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE1, 0xab),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE1, 0xaa),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE1, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_SELECT, 0x34),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORECLK_DIV_MODE1, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_ADDITIONAL_MISC_3, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORE_CLK_EN, 0xa0),
+};
+
+static const struct qmp_phy_init_tbl sar2130p_qmp_gen3x2_pcie_pcs_lane1_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_LANE1_INSIG_SW_CTRL2, 0x01),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_LANE1_INSIG_MX_CTRL2, 0x01),
+};
+
+static const struct qmp_phy_init_tbl sar2130p_qmp_gen3x2_pcie_rc_tx_tbl[] = {
+ QMP_PHY_INIT_CFG_LANE(QSERDES_V6_TX_BIST_MODE_LANENO, 0x00, 2),
+};
+
+static const struct qmp_phy_init_tbl sar2130p_qmp_gen3x2_pcie_rc_pcs_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_G12S1_TXDEEMPH_M6DB, 0x17),
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_G3S2_PRE_GAIN, 0x2e),
+};
+
+static const struct qmp_phy_init_tbl sar2130p_qmp_gen3x2_pcie_ep_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_BG_TIMER, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYS_CLK_CTRL, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x28),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x28),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x0d),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE1, 0x0d),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x42),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE1, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE1, 0x09),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x19),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_INTEGLOOP_GAIN0_MODE0, 0xfb),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_INTEGLOOP_GAIN1_MODE0, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_INTEGLOOP_GAIN0_MODE1, 0xfb),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_INTEGLOOP_GAIN1_MODE1, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORECLK_DIV_MODE1, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_MODE, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORE_CLK_EN, 0xa0),
+};
+
+static const struct qmp_phy_init_tbl sar2130p_qmp_gen3x2_pcie_ep_pcs_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_G12S1_TXDEEMPH_M6DB, 0x17),
+};
+
+static const struct qmp_phy_init_tbl sar2130p_qmp_gen3x2_pcie_ep_pcs_misc_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_EQ_CONFIG1, 0x1e),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_POWER_STATE_CONFIG2, 0x14),
+ QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_POWER_STATE_CONFIG4, 0x07),
+};
+
struct qmp_pcie_offsets {
u16 serdes;
u16 pcs;
u16 pcs_misc;
+ u16 pcs_lane1;
u16 tx;
u16 rx;
u16 tx2;
u16 rx2;
+ u16 txz;
+ u16 rxz;
u16 ln_shrd;
};
@@ -2222,10 +2918,16 @@ struct qmp_phy_cfg_tbls {
int tx_num;
const struct qmp_phy_init_tbl *rx;
int rx_num;
+ const struct qmp_phy_init_tbl *txz;
+ int txz_num;
+ const struct qmp_phy_init_tbl *rxz;
+ int rxz_num;
const struct qmp_phy_init_tbl *pcs;
int pcs_num;
const struct qmp_phy_init_tbl *pcs_misc;
int pcs_misc_num;
+ const struct qmp_phy_init_tbl *pcs_lane1;
+ int pcs_lane1_num;
const struct qmp_phy_init_tbl *ln_shrd;
int ln_shrd_num;
};
@@ -2271,6 +2973,9 @@ struct qmp_phy_cfg {
/* QMP PHY pipe clock interface rate */
unsigned long pipe_clock_rate;
+
+ /* QMP PHY AUX clock interface rate */
+ unsigned long aux_clock_rate;
};
struct qmp_pcie {
@@ -2282,10 +2987,13 @@ struct qmp_pcie {
void __iomem *serdes;
void __iomem *pcs;
void __iomem *pcs_misc;
+ void __iomem *pcs_lane1;
void __iomem *tx;
void __iomem *rx;
void __iomem *tx2;
void __iomem *rx2;
+ void __iomem *txz;
+ void __iomem *rxz;
void __iomem *ln_shrd;
void __iomem *port_b;
@@ -2302,6 +3010,7 @@ struct qmp_pcie {
int mode;
struct clk_fixed_rate pipe_clk_fixed;
+ struct clk_fixed_rate aux_clk_fixed;
};
static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val)
@@ -2395,6 +3104,7 @@ static const struct qmp_pcie_offsets qmp_pcie_offsets_v4_20 = {
.serdes = 0x1000,
.pcs = 0x1200,
.pcs_misc = 0x1600,
+ .pcs_lane1 = 0x1e00,
.tx = 0x0000,
.rx = 0x0200,
.tx2 = 0x0800,
@@ -2411,10 +3121,21 @@ static const struct qmp_pcie_offsets qmp_pcie_offsets_v5 = {
.rx2 = 0x1800,
};
+static const struct qmp_pcie_offsets qmp_pcie_offsets_ipq9574 = {
+ .serdes = 0,
+ .pcs = 0x1000,
+ .pcs_misc = 0x1400,
+ .tx = 0x0200,
+ .rx = 0x0400,
+ .tx2 = 0x0600,
+ .rx2 = 0x0800,
+};
+
static const struct qmp_pcie_offsets qmp_pcie_offsets_v5_20 = {
.serdes = 0x1000,
.pcs = 0x1200,
.pcs_misc = 0x1400,
+ .pcs_lane1 = 0x1e00,
.tx = 0x0000,
.rx = 0x0200,
.tx2 = 0x0800,
@@ -2442,6 +3163,17 @@ static const struct qmp_pcie_offsets qmp_pcie_offsets_v6_20 = {
.ln_shrd = 0x0e00,
};
+static const struct qmp_pcie_offsets qmp_pcie_offsets_v6_30 = {
+ .serdes = 0x8800,
+ .pcs = 0x9000,
+ .pcs_misc = 0x9800,
+ .tx = 0x0000,
+ .rx = 0x0200,
+ .txz = 0xe000,
+ .rxz = 0xe200,
+ .ln_shrd = 0x8000,
+};
+
static const struct qmp_phy_cfg ipq8074_pciephy_cfg = {
.lanes = 1,
@@ -2523,6 +3255,87 @@ static const struct qmp_phy_cfg ipq6018_pciephy_cfg = {
.phy_status = PHYSTATUS,
};
+static const struct qmp_phy_cfg ipq9574_gen3x1_pciephy_cfg = {
+ .lanes = 1,
+
+ .offsets = &qmp_pcie_offsets_v4x1,
+
+ .tbls = {
+ .serdes = ipq9574_gen3x1_pcie_serdes_tbl,
+ .serdes_num = ARRAY_SIZE(ipq9574_gen3x1_pcie_serdes_tbl),
+ .tx = ipq8074_pcie_gen3_tx_tbl,
+ .tx_num = ARRAY_SIZE(ipq8074_pcie_gen3_tx_tbl),
+ .rx = ipq9574_pcie_rx_tbl,
+ .rx_num = ARRAY_SIZE(ipq9574_pcie_rx_tbl),
+ .pcs = ipq9574_gen3x1_pcie_pcs_tbl,
+ .pcs_num = ARRAY_SIZE(ipq9574_gen3x1_pcie_pcs_tbl),
+ .pcs_misc = ipq9574_gen3x1_pcie_pcs_misc_tbl,
+ .pcs_misc_num = ARRAY_SIZE(ipq9574_gen3x1_pcie_pcs_misc_tbl),
+ },
+ .reset_list = ipq8074_pciephy_reset_l,
+ .num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l),
+ .vreg_list = NULL,
+ .num_vregs = 0,
+ .regs = pciephy_v4_regs_layout,
+
+ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
+ .phy_status = PHYSTATUS,
+ .pipe_clock_rate = 250000000,
+};
+
+static const struct qmp_phy_cfg ipq9574_gen3x2_pciephy_cfg = {
+ .lanes = 2,
+
+ .offsets = &qmp_pcie_offsets_ipq9574,
+
+ .tbls = {
+ .serdes = ipq9574_gen3x2_pcie_serdes_tbl,
+ .serdes_num = ARRAY_SIZE(ipq9574_gen3x2_pcie_serdes_tbl),
+ .tx = ipq8074_pcie_gen3_tx_tbl,
+ .tx_num = ARRAY_SIZE(ipq8074_pcie_gen3_tx_tbl),
+ .rx = ipq9574_pcie_rx_tbl,
+ .rx_num = ARRAY_SIZE(ipq9574_pcie_rx_tbl),
+ .pcs = ipq9574_gen3x2_pcie_pcs_tbl,
+ .pcs_num = ARRAY_SIZE(ipq9574_gen3x2_pcie_pcs_tbl),
+ .pcs_misc = ipq9574_gen3x2_pcie_pcs_misc_tbl,
+ .pcs_misc_num = ARRAY_SIZE(ipq9574_gen3x2_pcie_pcs_misc_tbl),
+ },
+ .reset_list = ipq8074_pciephy_reset_l,
+ .num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l),
+ .vreg_list = NULL,
+ .num_vregs = 0,
+ .regs = pciephy_v5_regs_layout,
+
+ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
+ .phy_status = PHYSTATUS,
+ .pipe_clock_rate = 250000000,
+};
+
+static const struct qmp_phy_cfg qcs615_pciephy_cfg = {
+ .lanes = 1,
+
+ .offsets = &qmp_pcie_offsets_v2,
+
+ .tbls = {
+ .serdes = qcs615_pcie_serdes_tbl,
+ .serdes_num = ARRAY_SIZE(qcs615_pcie_serdes_tbl),
+ .tx = qcs615_pcie_tx_tbl,
+ .tx_num = ARRAY_SIZE(qcs615_pcie_tx_tbl),
+ .rx = qcs615_pcie_rx_tbl,
+ .rx_num = ARRAY_SIZE(qcs615_pcie_rx_tbl),
+ .pcs = qcs615_pcie_pcs_tbl,
+ .pcs_num = ARRAY_SIZE(qcs615_pcie_pcs_tbl),
+ },
+ .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 = pciephy_v2_regs_layout,
+
+ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
+ .phy_status = PHYSTATUS,
+};
+
static const struct qmp_phy_cfg sdm845_qmp_pciephy_cfg = {
.lanes = 1,
@@ -2674,6 +3487,49 @@ static const struct qmp_phy_cfg msm8998_pciephy_cfg = {
.skip_start_delay = true,
};
+static const struct qmp_phy_cfg sar2130p_qmp_gen3x2_pciephy_cfg = {
+ .lanes = 2,
+
+ .offsets = &qmp_pcie_offsets_v5,
+
+ .tbls = {
+ .tx = sm8550_qmp_gen3x2_pcie_tx_tbl,
+ .tx_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_tx_tbl),
+ .rx = sm8550_qmp_gen3x2_pcie_rx_tbl,
+ .rx_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_rx_tbl),
+ .pcs = sm8550_qmp_gen3x2_pcie_pcs_tbl,
+ .pcs_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_pcs_tbl),
+ .pcs_lane1 = sar2130p_qmp_gen3x2_pcie_pcs_lane1_tbl,
+ .pcs_lane1_num = ARRAY_SIZE(sar2130p_qmp_gen3x2_pcie_pcs_lane1_tbl),
+ },
+ .tbls_rc = &(const struct qmp_phy_cfg_tbls) {
+ .serdes = sar2130p_qmp_gen3x2_pcie_rc_serdes_tbl,
+ .serdes_num = ARRAY_SIZE(sar2130p_qmp_gen3x2_pcie_rc_serdes_tbl),
+ .tx = sar2130p_qmp_gen3x2_pcie_rc_tx_tbl,
+ .tx_num = ARRAY_SIZE(sar2130p_qmp_gen3x2_pcie_rc_tx_tbl),
+ .pcs = sar2130p_qmp_gen3x2_pcie_rc_pcs_tbl,
+ .pcs_num = ARRAY_SIZE(sar2130p_qmp_gen3x2_pcie_rc_pcs_tbl),
+ .pcs_misc = sm8550_qmp_gen3x2_pcie_pcs_misc_tbl,
+ .pcs_misc_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_pcs_misc_tbl),
+ },
+ .tbls_ep = &(const struct qmp_phy_cfg_tbls) {
+ .serdes = sar2130p_qmp_gen3x2_pcie_ep_serdes_tbl,
+ .serdes_num = ARRAY_SIZE(sar2130p_qmp_gen3x2_pcie_ep_serdes_tbl),
+ .pcs = sar2130p_qmp_gen3x2_pcie_ep_pcs_tbl,
+ .pcs_num = ARRAY_SIZE(sar2130p_qmp_gen3x2_pcie_ep_pcs_tbl),
+ .pcs_misc = sar2130p_qmp_gen3x2_pcie_ep_pcs_misc_tbl,
+ .pcs_misc_num = ARRAY_SIZE(sar2130p_qmp_gen3x2_pcie_ep_pcs_misc_tbl),
+ },
+ .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 = pciephy_v5_regs_layout,
+
+ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
+ .phy_status = PHYSTATUS,
+};
+
static const struct qmp_phy_cfg sc8180x_pciephy_cfg = {
.lanes = 2,
@@ -2831,8 +3687,8 @@ static const struct qmp_phy_cfg sdx55_qmp_pciephy_cfg = {
.tbls_ep = &(const struct qmp_phy_cfg_tbls) {
.serdes = sdx55_qmp_pcie_ep_serdes_tbl,
.serdes_num = ARRAY_SIZE(sdx55_qmp_pcie_ep_serdes_tbl),
- .pcs_misc = sdx55_qmp_pcie_ep_pcs_misc_tbl,
- .pcs_misc_num = ARRAY_SIZE(sdx55_qmp_pcie_ep_pcs_misc_tbl),
+ .pcs_lane1 = sdx55_qmp_pcie_ep_pcs_lane1_tbl,
+ .pcs_lane1_num = ARRAY_SIZE(sdx55_qmp_pcie_ep_pcs_lane1_tbl),
},
.reset_list = sdm845_pciephy_reset_l,
@@ -2931,12 +3787,14 @@ static const struct qmp_phy_cfg sdx65_qmp_pciephy_cfg = {
.pcs_num = ARRAY_SIZE(sdx65_qmp_pcie_pcs_tbl),
.pcs_misc = sdx65_qmp_pcie_pcs_misc_tbl,
.pcs_misc_num = ARRAY_SIZE(sdx65_qmp_pcie_pcs_misc_tbl),
+ .pcs_lane1 = sdx65_qmp_pcie_pcs_lane1_tbl,
+ .pcs_lane1_num = ARRAY_SIZE(sdx65_qmp_pcie_pcs_lane1_tbl),
},
.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 = pciephy_v5_regs_layout,
+ .regs = pciephy_v6_regs_layout,
.pwrdn_ctrl = SW_PWRDN,
.phy_status = PHYSTATUS_4_20,
@@ -3017,6 +3875,9 @@ static const struct qmp_phy_cfg sm8450_qmp_gen4x2_pciephy_cfg = {
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
.phy_status = PHYSTATUS_4_20,
+
+ /* 20MHz PHY AUX Clock */
+ .aux_clock_rate = 20000000,
};
static const struct qmp_phy_cfg sm8550_qmp_gen3x2_pciephy_cfg = {
@@ -3069,11 +3930,14 @@ static const struct qmp_phy_cfg sm8550_qmp_gen4x2_pciephy_cfg = {
.num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
.vreg_list = sm8550_qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l),
- .regs = pciephy_v5_regs_layout,
+ .regs = pciephy_v6_regs_layout,
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
.phy_status = PHYSTATUS_4_20,
.has_nocsr_reset = true,
+
+ /* 20MHz PHY AUX Clock */
+ .aux_clock_rate = 20000000,
};
static const struct qmp_phy_cfg sm8650_qmp_gen4x2_pciephy_cfg = {
@@ -3099,11 +3963,14 @@ static const struct qmp_phy_cfg sm8650_qmp_gen4x2_pciephy_cfg = {
.num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
.vreg_list = sm8550_qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l),
- .regs = pciephy_v5_regs_layout,
+ .regs = pciephy_v6_regs_layout,
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
.phy_status = PHYSTATUS_4_20,
.has_nocsr_reset = true,
+
+ /* 20MHz PHY AUX Clock */
+ .aux_clock_rate = 20000000,
};
static const struct qmp_phy_cfg sa8775p_qmp_gen4x2_pciephy_cfg = {
@@ -3121,6 +3988,8 @@ static const struct qmp_phy_cfg sa8775p_qmp_gen4x2_pciephy_cfg = {
.pcs_num = ARRAY_SIZE(sa8775p_qmp_gen4x2_pcie_pcs_alt_tbl),
.pcs_misc = sa8775p_qmp_gen4_pcie_pcs_misc_tbl,
.pcs_misc_num = ARRAY_SIZE(sa8775p_qmp_gen4_pcie_pcs_misc_tbl),
+ .pcs_lane1 = sdx65_qmp_pcie_pcs_lane1_tbl,
+ .pcs_lane1_num = ARRAY_SIZE(sdx65_qmp_pcie_pcs_lane1_tbl),
},
.tbls_rc = &(const struct qmp_phy_cfg_tbls) {
@@ -3173,6 +4042,13 @@ static const struct qmp_phy_cfg sa8775p_qmp_gen4x4_pciephy_cfg = {
.pcs_misc_num = ARRAY_SIZE(sa8775p_qmp_gen4_pcie_rc_pcs_misc_tbl),
},
+ .tbls_ep = &(const struct qmp_phy_cfg_tbls) {
+ .serdes = sa8775p_qmp_gen4x2_pcie_ep_serdes_alt_tbl,
+ .serdes_num = ARRAY_SIZE(sa8775p_qmp_gen4x2_pcie_ep_serdes_alt_tbl),
+ .pcs_misc = sm8450_qmp_gen4x2_pcie_ep_pcs_misc_tbl,
+ .pcs_misc_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_ep_pcs_misc_tbl),
+ },
+
.reset_list = sdm845_pciephy_reset_l,
.num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
.vreg_list = qmp_phy_vreg_l,
@@ -3183,48 +4059,131 @@ static const struct qmp_phy_cfg sa8775p_qmp_gen4x4_pciephy_cfg = {
.phy_status = PHYSTATUS_4_20,
};
-static void qmp_pcie_configure_lane(void __iomem *base,
- const struct qmp_phy_init_tbl tbl[],
- int num,
- u8 lane_mask)
-{
- int i;
- const struct qmp_phy_init_tbl *t = tbl;
+static const struct qmp_phy_cfg x1e80100_qmp_gen4x2_pciephy_cfg = {
+ .lanes = 2,
- if (!t)
- return;
+ .offsets = &qmp_pcie_offsets_v6_20,
- for (i = 0; i < num; i++, t++) {
- if (!(t->lane_mask & lane_mask))
- continue;
+ .tbls = {
+ .serdes = x1e80100_qmp_gen4x2_pcie_serdes_tbl,
+ .serdes_num = ARRAY_SIZE(x1e80100_qmp_gen4x2_pcie_serdes_tbl),
+ .tx = x1e80100_qmp_gen4x2_pcie_tx_tbl,
+ .tx_num = ARRAY_SIZE(x1e80100_qmp_gen4x2_pcie_tx_tbl),
+ .rx = x1e80100_qmp_gen4x2_pcie_rx_tbl,
+ .rx_num = ARRAY_SIZE(x1e80100_qmp_gen4x2_pcie_rx_tbl),
+ .pcs = x1e80100_qmp_gen4x2_pcie_pcs_tbl,
+ .pcs_num = ARRAY_SIZE(x1e80100_qmp_gen4x2_pcie_pcs_tbl),
+ .pcs_misc = x1e80100_qmp_gen4x2_pcie_pcs_misc_tbl,
+ .pcs_misc_num = ARRAY_SIZE(x1e80100_qmp_gen4x2_pcie_pcs_misc_tbl),
+ .ln_shrd = x1e80100_qmp_gen4x2_pcie_ln_shrd_tbl,
+ .ln_shrd_num = ARRAY_SIZE(x1e80100_qmp_gen4x2_pcie_ln_shrd_tbl),
+ },
- writel(t->val, base + t->offset);
- }
-}
+ .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 = pciephy_v6_regs_layout,
-static void qmp_pcie_configure(void __iomem *base,
- const struct qmp_phy_init_tbl tbl[],
- int num)
-{
- qmp_pcie_configure_lane(base, tbl, num, 0xff);
-}
+ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
+ .phy_status = PHYSTATUS_4_20,
+ .has_nocsr_reset = true,
+};
+
+static const struct qmp_phy_cfg x1e80100_qmp_gen4x4_pciephy_cfg = {
+ .lanes = 4,
+
+ .offsets = &qmp_pcie_offsets_v6_20,
+
+ .tbls = {
+ .serdes = x1e80100_qmp_gen4x2_pcie_serdes_tbl,
+ .serdes_num = ARRAY_SIZE(x1e80100_qmp_gen4x2_pcie_serdes_tbl),
+ .tx = x1e80100_qmp_gen4x2_pcie_tx_tbl,
+ .tx_num = ARRAY_SIZE(x1e80100_qmp_gen4x2_pcie_tx_tbl),
+ .rx = x1e80100_qmp_gen4x2_pcie_rx_tbl,
+ .rx_num = ARRAY_SIZE(x1e80100_qmp_gen4x2_pcie_rx_tbl),
+ .pcs = x1e80100_qmp_gen4x2_pcie_pcs_tbl,
+ .pcs_num = ARRAY_SIZE(x1e80100_qmp_gen4x2_pcie_pcs_tbl),
+ .pcs_misc = x1e80100_qmp_gen4x2_pcie_pcs_misc_tbl,
+ .pcs_misc_num = ARRAY_SIZE(x1e80100_qmp_gen4x2_pcie_pcs_misc_tbl),
+ .ln_shrd = x1e80100_qmp_gen4x2_pcie_ln_shrd_tbl,
+ .ln_shrd_num = ARRAY_SIZE(x1e80100_qmp_gen4x2_pcie_ln_shrd_tbl),
+ },
+
+ .serdes_4ln_tbl = x1e80100_qmp_gen4x4_pcie_serdes_4ln_tbl,
+ .serdes_4ln_num = ARRAY_SIZE(x1e80100_qmp_gen4x4_pcie_serdes_4ln_tbl),
+
+ .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 = pciephy_v6_regs_layout,
+
+ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
+ .phy_status = PHYSTATUS_4_20,
+ .has_nocsr_reset = true,
+};
+
+static const struct qmp_phy_cfg x1e80100_qmp_gen4x8_pciephy_cfg = {
+ .lanes = 8,
+
+ .offsets = &qmp_pcie_offsets_v6_30,
+ .tbls = {
+ .serdes = x1e80100_qmp_gen4x8_pcie_serdes_tbl,
+ .serdes_num = ARRAY_SIZE(x1e80100_qmp_gen4x8_pcie_serdes_tbl),
+ .rx = x1e80100_qmp_gen4x8_pcie_rx_tbl,
+ .rx_num = ARRAY_SIZE(x1e80100_qmp_gen4x8_pcie_rx_tbl),
+ .txz = x1e80100_qmp_gen4x8_pcie_txz_tbl,
+ .txz_num = ARRAY_SIZE(x1e80100_qmp_gen4x8_pcie_txz_tbl),
+ .rxz = x1e80100_qmp_gen4x8_pcie_rxz_tbl,
+ .rxz_num = ARRAY_SIZE(x1e80100_qmp_gen4x8_pcie_rxz_tbl),
+ .pcs = x1e80100_qmp_gen4x8_pcie_pcs_tbl,
+ .pcs_num = ARRAY_SIZE(x1e80100_qmp_gen4x8_pcie_pcs_tbl),
+ .pcs_misc = x1e80100_qmp_gen4x8_pcie_pcs_misc_tbl,
+ .pcs_misc_num = ARRAY_SIZE(x1e80100_qmp_gen4x8_pcie_pcs_misc_tbl),
+ .ln_shrd = x1e80100_qmp_gen4x8_pcie_ln_shrd_tbl,
+ .ln_shrd_num = ARRAY_SIZE(x1e80100_qmp_gen4x8_pcie_ln_shrd_tbl),
+ },
+
+ .reset_list = sdm845_pciephy_reset_l,
+ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
+ .vreg_list = sm8550_qmp_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l),
+ .regs = pciephy_v6_regs_layout,
+
+ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
+ .phy_status = PHYSTATUS_4_20,
+ .has_nocsr_reset = true,
+};
static void qmp_pcie_init_port_b(struct qmp_pcie *qmp, const struct qmp_phy_cfg_tbls *tbls)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
const struct qmp_pcie_offsets *offs = cfg->offsets;
- void __iomem *tx3, *rx3, *tx4, *rx4;
+ void __iomem *serdes, *tx3, *rx3, *tx4, *rx4, *pcs, *pcs_misc, *ln_shrd;
+ serdes = qmp->port_b + offs->serdes;
tx3 = qmp->port_b + offs->tx;
rx3 = qmp->port_b + offs->rx;
tx4 = qmp->port_b + offs->tx2;
rx4 = qmp->port_b + offs->rx2;
+ pcs = qmp->port_b + offs->pcs;
+ pcs_misc = qmp->port_b + offs->pcs_misc;
+ ln_shrd = qmp->port_b + offs->ln_shrd;
- qmp_pcie_configure_lane(tx3, tbls->tx, tbls->tx_num, 1);
- qmp_pcie_configure_lane(rx3, tbls->rx, tbls->rx_num, 1);
+ qmp_configure(qmp->dev, serdes, tbls->serdes, tbls->serdes_num);
+ qmp_configure(qmp->dev, serdes, cfg->serdes_4ln_tbl, cfg->serdes_4ln_num);
- qmp_pcie_configure_lane(tx4, tbls->tx, tbls->tx_num, 2);
- qmp_pcie_configure_lane(rx4, tbls->rx, tbls->rx_num, 2);
+ qmp_configure_lane(qmp->dev, tx3, tbls->tx, tbls->tx_num, 1);
+ qmp_configure_lane(qmp->dev, rx3, tbls->rx, tbls->rx_num, 1);
+
+ qmp_configure_lane(qmp->dev, tx4, tbls->tx, tbls->tx_num, 2);
+ qmp_configure_lane(qmp->dev, rx4, tbls->rx, tbls->rx_num, 2);
+
+ qmp_configure(qmp->dev, pcs, tbls->pcs, tbls->pcs_num);
+ qmp_configure(qmp->dev, pcs_misc, tbls->pcs_misc, tbls->pcs_misc_num);
+
+ qmp_configure(qmp->dev, ln_shrd, tbls->ln_shrd, tbls->ln_shrd_num);
}
static void qmp_pcie_init_registers(struct qmp_pcie *qmp, const struct qmp_phy_cfg_tbls *tbls)
@@ -3237,30 +4196,40 @@ static void qmp_pcie_init_registers(struct qmp_pcie *qmp, const struct qmp_phy_c
void __iomem *rx2 = qmp->rx2;
void __iomem *pcs = qmp->pcs;
void __iomem *pcs_misc = qmp->pcs_misc;
+ void __iomem *pcs_lane1 = qmp->pcs_lane1;
void __iomem *ln_shrd = qmp->ln_shrd;
if (!tbls)
return;
- qmp_pcie_configure(serdes, tbls->serdes, tbls->serdes_num);
+ qmp_configure(qmp->dev, serdes, tbls->serdes, tbls->serdes_num);
+
+ /*
+ * Tx/Rx registers that require different settings than
+ * txz/rxz must be programmed after txz/rxz.
+ */
+ qmp_configure(qmp->dev, qmp->txz, tbls->txz, tbls->txz_num);
+ qmp_configure(qmp->dev, qmp->rxz, tbls->rxz, tbls->rxz_num);
- qmp_pcie_configure_lane(tx, tbls->tx, tbls->tx_num, 1);
- qmp_pcie_configure_lane(rx, tbls->rx, tbls->rx_num, 1);
+ qmp_configure_lane(qmp->dev, tx, tbls->tx, tbls->tx_num, 1);
+ qmp_configure_lane(qmp->dev, rx, tbls->rx, tbls->rx_num, 1);
if (cfg->lanes >= 2) {
- qmp_pcie_configure_lane(tx2, tbls->tx, tbls->tx_num, 2);
- qmp_pcie_configure_lane(rx2, tbls->rx, tbls->rx_num, 2);
+ qmp_configure_lane(qmp->dev, tx2, tbls->tx, tbls->tx_num, 2);
+ qmp_configure_lane(qmp->dev, rx2, tbls->rx, tbls->rx_num, 2);
}
- qmp_pcie_configure(pcs, tbls->pcs, tbls->pcs_num);
- qmp_pcie_configure(pcs_misc, tbls->pcs_misc, tbls->pcs_misc_num);
+ qmp_configure(qmp->dev, pcs, tbls->pcs, tbls->pcs_num);
+ qmp_configure(qmp->dev, pcs_misc, tbls->pcs_misc, tbls->pcs_misc_num);
+ qmp_configure(qmp->dev, pcs_lane1, tbls->pcs_lane1, tbls->pcs_lane1_num);
if (cfg->lanes >= 4 && qmp->tcsr_4ln_config) {
- qmp_pcie_configure(serdes, cfg->serdes_4ln_tbl, cfg->serdes_4ln_num);
+ qmp_configure(qmp->dev, serdes, cfg->serdes_4ln_tbl,
+ cfg->serdes_4ln_num);
qmp_pcie_init_port_b(qmp, tbls);
}
- qmp_pcie_configure(ln_shrd, tbls->ln_shrd, tbls->ln_shrd_num);
+ qmp_configure(qmp->dev, ln_shrd, tbls->ln_shrd, tbls->ln_shrd_num);
}
static int qmp_pcie_init(struct phy *phy)
@@ -3542,7 +4511,7 @@ static int phy_pipe_clk_register(struct qmp_pcie *qmp, struct device_node *np)
struct clk_init_data init = { };
int ret;
- ret = of_property_read_string(np, "clock-output-names", &init.name);
+ ret = of_property_read_string_index(np, "clock-output-names", 0, &init.name);
if (ret) {
dev_err(qmp->dev, "%pOFn: No clock-output-names\n", np);
return ret;
@@ -3561,14 +4530,84 @@ static int phy_pipe_clk_register(struct qmp_pcie *qmp, struct device_node *np)
fixed->hw.init = &init;
- ret = devm_clk_hw_register(qmp->dev, &fixed->hw);
- if (ret)
- return ret;
+ return devm_clk_hw_register(qmp->dev, &fixed->hw);
+}
+
+/*
+ * Register a fixed rate PHY aux clock.
+ *
+ * The <s>_phy_aux_clksrc generated by PHY goes to the GCC that gate
+ * controls it. The <s>_phy_aux_clk coming out of the GCC is requested
+ * by the PHY driver for its operations.
+ * We register the <s>_phy_aux_clksrc here. The gcc driver takes care
+ * of assigning this <s>_phy_aux_clksrc as parent to <s>_phy_aux_clk.
+ * Below picture shows this relationship.
+ *
+ * +---------------+
+ * | PHY block |<<---------------------------------------------+
+ * | | |
+ * | +-------+ | +-----+ |
+ * I/P---^-->| PLL |---^--->phy_aux_clksrc--->| GCC |--->phy_aux_clk---+
+ * clk | +-------+ | +-----+
+ * +---------------+
+ */
+static int phy_aux_clk_register(struct qmp_pcie *qmp, struct device_node *np)
+{
+ struct clk_fixed_rate *fixed = &qmp->aux_clk_fixed;
+ struct clk_init_data init = { };
+ char name[64];
+
+ snprintf(name, sizeof(name), "%s::phy_aux_clk", dev_name(qmp->dev));
+
+ init.name = name;
+ init.ops = &clk_fixed_rate_ops;
+
+ fixed->fixed_rate = qmp->cfg->aux_clock_rate;
+ fixed->hw.init = &init;
+
+ return devm_clk_hw_register(qmp->dev, &fixed->hw);
+}
+
+static struct clk_hw *qmp_pcie_clk_hw_get(struct of_phandle_args *clkspec, void *data)
+{
+ struct qmp_pcie *qmp = data;
+
+ /* Support legacy bindings */
+ if (!clkspec->args_count)
+ return &qmp->pipe_clk_fixed.hw;
+
+ switch (clkspec->args[0]) {
+ case QMP_PCIE_PIPE_CLK:
+ return &qmp->pipe_clk_fixed.hw;
+ case QMP_PCIE_PHY_AUX_CLK:
+ return &qmp->aux_clk_fixed.hw;
+ }
+
+ return ERR_PTR(-EINVAL);
+}
- ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &fixed->hw);
+static int qmp_pcie_register_clocks(struct qmp_pcie *qmp, struct device_node *np)
+{
+ int ret;
+
+ ret = phy_pipe_clk_register(qmp, np);
if (ret)
return ret;
+ if (qmp->cfg->aux_clock_rate) {
+ ret = phy_aux_clk_register(qmp, np);
+ if (ret)
+ return ret;
+
+ ret = of_clk_add_hw_provider(np, qmp_pcie_clk_hw_get, qmp);
+ if (ret)
+ return ret;
+ } else {
+ ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &qmp->pipe_clk_fixed.hw);
+ if (ret)
+ return ret;
+ }
+
/*
* Roll a devm action because the clock provider is the child node, but
* the child node is not actually a device.
@@ -3634,6 +4673,14 @@ static int qmp_pcie_parse_dt_legacy(struct qmp_pcie *qmp, struct device_node *np
}
}
+ /*
+ * For all platforms where legacy bindings existed, PCS_LANE1 was
+ * mapped as a part of the PCS_MISC region.
+ */
+ if (!IS_ERR(qmp->pcs_misc) && cfg->offsets->pcs_lane1 != 0)
+ qmp->pcs_lane1 = qmp->pcs_misc +
+ (cfg->offsets->pcs_lane1 - cfg->offsets->pcs_misc);
+
clk = devm_get_clk_from_child(dev, np, NULL);
if (IS_ERR(clk)) {
return dev_err_probe(dev, PTR_ERR(clk),
@@ -3701,6 +4748,7 @@ static int qmp_pcie_parse_dt(struct qmp_pcie *qmp)
qmp->serdes = base + offs->serdes;
qmp->pcs = base + offs->pcs;
qmp->pcs_misc = base + offs->pcs_misc;
+ qmp->pcs_lane1 = base + offs->pcs_lane1;
qmp->tx = base + offs->tx;
qmp->rx = base + offs->rx;
@@ -3715,6 +4763,9 @@ static int qmp_pcie_parse_dt(struct qmp_pcie *qmp)
return PTR_ERR(qmp->port_b);
}
+ qmp->txz = base + offs->txz;
+ qmp->rxz = base + offs->rxz;
+
if (cfg->tbls.ln_shrd)
qmp->ln_shrd = base + offs->ln_shrd;
@@ -3777,7 +4828,7 @@ static int qmp_pcie_probe(struct platform_device *pdev)
if (ret)
goto err_node_put;
- ret = phy_pipe_clk_register(qmp, np);
+ ret = qmp_pcie_register_clocks(qmp, np);
if (ret)
goto err_node_put;
@@ -3814,15 +4865,27 @@ static const struct of_device_id qmp_pcie_of_match_table[] = {
.compatible = "qcom,ipq8074-qmp-pcie-phy",
.data = &ipq8074_pciephy_cfg,
}, {
+ .compatible = "qcom,ipq9574-qmp-gen3x1-pcie-phy",
+ .data = &ipq9574_gen3x1_pciephy_cfg,
+ }, {
+ .compatible = "qcom,ipq9574-qmp-gen3x2-pcie-phy",
+ .data = &ipq9574_gen3x2_pciephy_cfg,
+ }, {
.compatible = "qcom,msm8998-qmp-pcie-phy",
.data = &msm8998_pciephy_cfg,
}, {
+ .compatible = "qcom,qcs615-qmp-gen3x1-pcie-phy",
+ .data = &qcs615_pciephy_cfg,
+ }, {
.compatible = "qcom,sa8775p-qmp-gen4x2-pcie-phy",
.data = &sa8775p_qmp_gen4x2_pciephy_cfg,
}, {
.compatible = "qcom,sa8775p-qmp-gen4x4-pcie-phy",
.data = &sa8775p_qmp_gen4x4_pciephy_cfg,
}, {
+ .compatible = "qcom,sar2130p-qmp-gen3x2-pcie-phy",
+ .data = &sar2130p_qmp_gen3x2_pciephy_cfg,
+ }, {
.compatible = "qcom,sc8180x-qmp-pcie-phy",
.data = &sc8180x_pciephy_cfg,
}, {
@@ -3885,6 +4948,18 @@ static const struct of_device_id qmp_pcie_of_match_table[] = {
}, {
.compatible = "qcom,sm8650-qmp-gen4x2-pcie-phy",
.data = &sm8650_qmp_gen4x2_pciephy_cfg,
+ }, {
+ .compatible = "qcom,x1e80100-qmp-gen3x2-pcie-phy",
+ .data = &sm8550_qmp_gen3x2_pciephy_cfg,
+ }, {
+ .compatible = "qcom,x1e80100-qmp-gen4x2-pcie-phy",
+ .data = &x1e80100_qmp_gen4x2_pciephy_cfg,
+ }, {
+ .compatible = "qcom,x1e80100-qmp-gen4x4-pcie-phy",
+ .data = &x1e80100_qmp_gen4x4_pciephy_cfg,
+ }, {
+ .compatible = "qcom,x1e80100-qmp-gen4x8-pcie-phy",
+ .data = &x1e80100_qmp_gen4x8_pciephy_cfg,
},
{ },
};
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v4_20.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v4_20.h
index ac872a9eff9a..ab892d1067c2 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v4_20.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v4_20.h
@@ -13,7 +13,8 @@
#define QPHY_V4_20_PCS_PCIE_G4_RXEQEVAL_TIME 0x0f4
#define QPHY_V4_20_PCS_PCIE_G4_EQ_CONFIG2 0x0fc
#define QPHY_V4_20_PCS_PCIE_G4_EQ_CONFIG5 0x108
-#define QPHY_V4_20_PCS_LANE1_INSIG_SW_CTRL2 0x824
-#define QPHY_V4_20_PCS_LANE1_INSIG_MX_CTRL2 0x828
+
+#define QPHY_V4_20_PCS_LANE1_INSIG_SW_CTRL2 0x024
+#define QPHY_V4_20_PCS_LANE1_INSIG_MX_CTRL2 0x028
#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v5.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v5.h
index a469ae2a10a1..fa15a03055de 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v5.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v5.h
@@ -11,8 +11,22 @@
#define QPHY_V5_PCS_PCIE_POWER_STATE_CONFIG2 0x0c
#define QPHY_V5_PCS_PCIE_POWER_STATE_CONFIG4 0x14
#define QPHY_V5_PCS_PCIE_ENDPOINT_REFCLK_DRIVE 0x20
+#define QPHY_V5_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L 0x44
+#define QPHY_V5_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_H 0x48
+#define QPHY_V5_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L 0x4c
+#define QPHY_V5_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_H 0x50
#define QPHY_V5_PCS_PCIE_INT_AUX_CLK_CONFIG1 0x54
+#define QPHY_V5_PCS_PCIE_OSC_DTCT_CONFIG1 0x5c
+#define QPHY_V5_PCS_PCIE_OSC_DTCT_CONFIG2 0x60
+#define QPHY_V5_PCS_PCIE_OSC_DTCT_CONFIG4 0x68
+#define QPHY_V5_PCS_PCIE_OSC_DTCT_MODE2_CONFIG2 0x7c
+#define QPHY_V5_PCS_PCIE_OSC_DTCT_MODE2_CONFIG4 0x84
+#define QPHY_V5_PCS_PCIE_OSC_DTCT_MODE2_CONFIG5 0x88
+#define QPHY_V5_PCS_PCIE_OSC_DTCT_MODE2_CONFIG6 0x8c
#define QPHY_V5_PCS_PCIE_OSC_DTCT_ACTIONS 0x94
+#define QPHY_V5_PCS_PCIE_EQ_CONFIG1 0xa4
#define QPHY_V5_PCS_PCIE_EQ_CONFIG2 0xa8
+#define QPHY_V5_PCS_PCIE_PRESET_P10_PRE 0xc0
+#define QPHY_V5_PCS_PCIE_PRESET_P10_POST 0xe4
#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v5_20.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v5_20.h
index cdf8c04ea078..283d63c81593 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v5_20.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v5_20.h
@@ -17,7 +17,8 @@
#define QPHY_V5_20_PCS_PCIE_G4_EQ_CONFIG5 0x108
#define QPHY_V5_20_PCS_PCIE_G4_PRE_GAIN 0x15c
#define QPHY_V5_20_PCS_PCIE_RX_MARGINING_CONFIG3 0x184
-#define QPHY_V5_20_PCS_LANE1_INSIG_SW_CTRL2 0xa24
-#define QPHY_V5_20_PCS_LANE1_INSIG_MX_CTRL2 0xa28
+
+#define QPHY_V5_20_PCS_LANE1_INSIG_SW_CTRL2 0x024
+#define QPHY_V5_20_PCS_LANE1_INSIG_MX_CTRL2 0x028
#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6.h
index 91e70002eb47..45397cb3c0c6 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6.h
@@ -7,9 +7,14 @@
#define QCOM_PHY_QMP_PCS_PCIE_V6_H_
/* Only for QMP V6 PHY - PCIE have different offsets than V5 */
+#define QPHY_PCIE_V6_PCS_PCIE_EQ_CONFIG1 0xa4
+#define QPHY_PCIE_V6_PCS_PCIE_RXEQEVAL_TIME 0xf4
#define QPHY_PCIE_V6_PCS_PCIE_POWER_STATE_CONFIG2 0x0c
#define QPHY_PCIE_V6_PCS_PCIE_POWER_STATE_CONFIG4 0x14
#define QPHY_PCIE_V6_PCS_PCIE_ENDPOINT_REFCLK_DRIVE 0x20
#define QPHY_PCIE_V6_PCS_PCIE_OSC_DTCT_ACTIONS 0x94
+#define QPHY_PCIE_V6_PCS_LANE1_INSIG_SW_CTRL2 0x024
+#define QPHY_PCIE_V6_PCS_LANE1_INSIG_MX_CTRL2 0x028
+
#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6_20.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6_20.h
index e3eb08776339..dfcecf31a606 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6_20.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6_20.h
@@ -12,6 +12,8 @@
#define QPHY_PCIE_V6_20_PCS_ENDPOINT_REFCLK_DRIVE 0x01c
#define QPHY_PCIE_V6_20_PCS_OSC_DTCT_ATCIONS 0x090
#define QPHY_PCIE_V6_20_PCS_EQ_CONFIG1 0x0a0
+#define QPHY_PCIE_V6_20_PCS_G3_RXEQEVAL_TIME 0x0f0
+#define QPHY_PCIE_V6_20_PCS_G4_RXEQEVAL_TIME 0x0f4
#define QPHY_PCIE_V6_20_PCS_EQ_CONFIG5 0x108
#define QPHY_PCIE_V6_20_PCS_G4_PRE_GAIN 0x15c
#define QPHY_PCIE_V6_20_PCS_RX_MARGINING_CONFIG1 0x17c
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6_30.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6_30.h
new file mode 100644
index 000000000000..5a58ff197e6e
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6_30.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_PCS_PCIE_V6_30_H_
+#define QCOM_PHY_QMP_PCS_PCIE_V6_30_H_
+
+/* Only for QMP V6_30 PHY - PCIE have different offsets than V6 */
+#define QPHY_PCIE_V6_30_PCS_POWER_STATE_CONFIG2 0x014
+#define QPHY_PCIE_V6_30_PCS_TX_RX_CONFIG 0x020
+#define QPHY_PCIE_V6_30_PCS_ENDPOINT_REFCLK_DRIVE 0x024
+#define QPHY_PCIE_V6_30_PCS_OSC_DTCT_ACTIONS 0x098
+#define QPHY_PCIE_V6_30_PCS_EQ_CONFIG1 0x0a8
+#define QPHY_PCIE_V6_30_PCS_G3_RXEQEVAL_TIME 0x0f8
+#define QPHY_PCIE_V6_30_PCS_G4_RXEQEVAL_TIME 0x0fc
+#define QPHY_PCIE_V6_30_PCS_G4_EQ_CONFIG5 0x110
+#define QPHY_PCIE_V6_30_PCS_G4_PRE_GAIN 0x164
+#define QPHY_PCIE_V6_30_PCS_RX_MARGINING_CONFIG1 0x184
+#define QPHY_PCIE_V6_30_PCS_RX_MARGINING_CONFIG3 0x18c
+#define QPHY_PCIE_V6_30_PCS_RX_MARGINING_CONFIG5 0x194
+#define QPHY_PCIE_V6_30_PCS_G3_FOM_EQ_CONFIG5 0x1b4
+#define QPHY_PCIE_V6_30_PCS_G4_FOM_EQ_CONFIG5 0x1c8
+
+#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-sgmii.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-sgmii.h
new file mode 100644
index 000000000000..4d8c962f5e0f
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-sgmii.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2023, Linaro Limited
+ */
+
+#ifndef QCOM_PHY_QMP_PCS_SGMII_H_
+#define QCOM_PHY_QMP_PCS_SGMII_H_
+
+#define QPHY_PCS_PHY_START 0x000
+#define QPHY_PCS_POWER_DOWN_CONTROL 0x004
+#define QPHY_PCS_SW_RESET 0x008
+#define QPHY_PCS_LINE_RESET_TIME 0x00c
+#define QPHY_PCS_TX_LARGE_AMP_DRV_LVL 0x020
+#define QPHY_PCS_TX_SMALL_AMP_DRV_LVL 0x028
+#define QPHY_PCS_PCS_READY_STATUS 0x094
+#define QPHY_PCS_TX_MID_TERM_CTRL1 0x0d8
+#define QPHY_PCS_TX_MID_TERM_CTRL2 0x0dc
+#define QPHY_PCS_SGMII_MISC_CTRL8 0x118
+
+#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-ufs-v6.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-ufs-v6.h
index fe6c450f6123..f19f9892ed7b 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-ufs-v6.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-ufs-v6.h
@@ -19,6 +19,7 @@
#define QPHY_V6_PCS_UFS_BIST_FIXED_PAT_CTRL 0x060
#define QPHY_V6_PCS_UFS_TX_HSGEAR_CAPABILITY 0x074
#define QPHY_V6_PCS_UFS_RX_HSGEAR_CAPABILITY 0x0bc
+#define QPHY_V6_PCS_UFS_RX_HS_G5_SYNC_LENGTH_CAPABILITY 0x12c
#define QPHY_V6_PCS_UFS_DEBUG_BUS_CLKSEL 0x158
#define QPHY_V6_PCS_UFS_LINECFG_DISABLE 0x17c
#define QPHY_V6_PCS_UFS_RX_MIN_HIBERN8_TIME 0x184
@@ -28,5 +29,10 @@
#define QPHY_V6_PCS_UFS_READY_STATUS 0x1a8
#define QPHY_V6_PCS_UFS_TX_MID_TERM_CTRL1 0x1f4
#define QPHY_V6_PCS_UFS_MULTI_LANE_CTRL1 0x1fc
+#define QPHY_V6_PCS_UFS_RX_HSG5_SYNC_WAIT_TIME 0x220
+#define QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S4 0x240
+#define QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S5 0x244
+#define QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S6 0x248
+#define QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S7 0x24c
#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v2.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v2.h
index bf36399d0057..1ecf4b5beba6 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v2.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v2.h
@@ -34,6 +34,7 @@
#define QPHY_V2_PCS_USB_PCS_STATUS 0x17c /* USB */
#define QPHY_V2_PCS_PLL_LOCK_CHK_DLY_TIME_AUXCLK_LSB 0x1a8
#define QPHY_V2_PCS_OSC_DTCT_ACTIONS 0x1ac
+#define QPHY_V2_PCS_SIGDET_CNTRL 0x1b0
#define QPHY_V2_PCS_RX_SIGDET_LVL 0x1d8
#define QPHY_V2_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB 0x1dc
#define QPHY_V2_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB 0x1e0
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6-n4.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6-n4.h
new file mode 100644
index 000000000000..b3024714dab4
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6-n4.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2023, Linaro Limited
+ */
+
+#ifndef QCOM_PHY_QMP_PCS_V6_N4_H_
+#define QCOM_PHY_QMP_PCS_V6_N4_H_
+
+/* Only for QMP V6 N4 PHY - USB/PCIe PCS registers */
+#define QPHY_V6_N4_PCS_SW_RESET 0x000
+#define QPHY_V6_N4_PCS_PCS_STATUS1 0x014
+#define QPHY_V6_N4_PCS_POWER_DOWN_CONTROL 0x040
+#define QPHY_V6_N4_PCS_START_CONTROL 0x044
+#define QPHY_V6_N4_PCS_POWER_STATE_CONFIG1 0x090
+#define QPHY_V6_N4_PCS_LOCK_DETECT_CONFIG1 0x0c4
+#define QPHY_V6_N4_PCS_LOCK_DETECT_CONFIG2 0x0c8
+#define QPHY_V6_N4_PCS_LOCK_DETECT_CONFIG3 0x0cc
+#define QPHY_V6_N4_PCS_LOCK_DETECT_CONFIG6 0x0d8
+#define QPHY_V6_N4_PCS_REFGEN_REQ_CONFIG1 0x0dc
+#define QPHY_V6_N4_PCS_RX_SIGDET_LVL 0x188
+#define QPHY_V6_N4_PCS_RCVR_DTCT_DLY_P1U2_L 0x190
+#define QPHY_V6_N4_PCS_RCVR_DTCT_DLY_P1U2_H 0x194
+#define QPHY_V6_N4_PCS_RATE_SLEW_CNTRL1 0x198
+#define QPHY_V6_N4_PCS_RX_CONFIG 0x1b0
+#define QPHY_V6_N4_PCS_ALIGN_DETECT_CONFIG1 0x1c0
+#define QPHY_V6_N4_PCS_ALIGN_DETECT_CONFIG2 0x1c4
+#define QPHY_V6_N4_PCS_PCS_TX_RX_CONFIG 0x1d0
+#define QPHY_V6_N4_PCS_EQ_CONFIG1 0x1dc
+#define QPHY_V6_N4_PCS_EQ_CONFIG2 0x1e0
+#define QPHY_V6_N4_PCS_EQ_CONFIG5 0x1ec
+
+#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6.h
index 08299d2b78f0..aa5afb921f12 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6.h
@@ -17,6 +17,8 @@
#define QPHY_V6_PCS_LOCK_DETECT_CONFIG3 0x0cc
#define QPHY_V6_PCS_LOCK_DETECT_CONFIG6 0x0d8
#define QPHY_V6_PCS_REFGEN_REQ_CONFIG1 0x0dc
+#define QPHY_V6_PCS_G12S1_TXDEEMPH_M6DB 0x168
+#define QPHY_V6_PCS_G3S2_PRE_GAIN 0x170
#define QPHY_V6_PCS_RX_SIGDET_LVL 0x188
#define QPHY_V6_PCS_RCVR_DTCT_DLY_P1U2_L 0x190
#define QPHY_V6_PCS_RCVR_DTCT_DLY_P1U2_H 0x194
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6_20.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6_20.h
index 9c3f1e4950e6..4d9615cc0383 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6_20.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6_20.h
@@ -7,6 +7,7 @@
#define QCOM_PHY_QMP_PCS_V6_20_H_
/* Only for QMP V6_20 PHY - USB/PCIe PCS registers */
+#define QPHY_V6_20_PCS_G12S1_TXDEEMPH_M6DB 0x170
#define QPHY_V6_20_PCS_G3S2_PRE_GAIN 0x178
#define QPHY_V6_20_PCS_RX_SIGDET_LVL 0x190
#define QPHY_V6_20_PCS_COM_ELECIDLE_DLY_SEL 0x1b8
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6_30.h b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6_30.h
new file mode 100644
index 000000000000..369120d88bc2
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-v6_30.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_PCS_V6_30_H_
+#define QCOM_PHY_QMP_PCS_V6_30_H_
+
+/* Only for QMP V6_30 PHY - PCIe PCS registers */
+#define QPHY_V6_30_PCS_LOCK_DETECT_CONFIG2 0x0cc
+#define QPHY_V6_30_PCS_G3S2_PRE_GAIN 0x17c
+#define QPHY_V6_30_PCS_RX_SIGDET_LVL 0x194
+#define QPHY_V6_30_PCS_ALIGN_DETECT_CONFIG7 0x1dc
+#define QPHY_V6_30_PCS_TX_RX_CONFIG 0x1e0
+#define QPHY_V6_30_PCS_TX_RX_CONFIG2 0x1e4
+#define QPHY_V6_30_PCS_EQ_CONFIG4 0x1fc
+#define QPHY_V6_30_PCS_EQ_CONFIG5 0x200
+
+#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v6.h b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v6.h
index ec7291424dd1..328c6c0b0b09 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v6.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v6.h
@@ -60,6 +60,8 @@
#define QSERDES_V6_COM_SYSCLK_BUF_ENABLE 0xe8
#define QSERDES_V6_COM_PLL_IVCO 0xf4
#define QSERDES_V6_COM_PLL_IVCO_MODE1 0xf8
+#define QSERDES_V6_COM_CMN_IETRIM 0xfc
+#define QSERDES_V6_COM_CMN_IPTRIM 0x100
#define QSERDES_V6_COM_SYSCLK_EN_SEL 0x110
#define QSERDES_V6_COM_RESETSM_CNTRL 0x118
#define QSERDES_V6_COM_LOCK_CMP_EN 0x120
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-pll.h b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-pll.h
index ad326e301a3a..231e59364e31 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-pll.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-pll.h
@@ -8,6 +8,9 @@
/* QMP V2 PHY for PCIE gen3 ports - QSERDES PLL registers */
#define QSERDES_PLL_BG_TIMER 0x00c
+#define QSERDES_PLL_SSC_EN_CENTER 0x010
+#define QSERDES_PLL_SSC_ADJ_PER1 0x014
+#define QSERDES_PLL_SSC_ADJ_PER2 0x018
#define QSERDES_PLL_SSC_PER1 0x01c
#define QSERDES_PLL_SSC_PER2 0x020
#define QSERDES_PLL_SSC_STEP_SIZE1_MODE0 0x024
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-ufs-v6.h b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-ufs-v6.h
index 35d497fd9f9a..d17a52357965 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-ufs-v6.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-ufs-v6.h
@@ -15,16 +15,25 @@
#define QSERDES_UFS_V6_RX_UCDR_FASTLOCK_FO_GAIN_RATE2 0x08
#define QSERDES_UFS_V6_RX_UCDR_FASTLOCK_FO_GAIN_RATE4 0x10
+#define QSERDES_UFS_V6_RX_UCDR_FASTLOCK_SO_GAIN_RATE4 0x24
#define QSERDES_UFS_V6_RX_UCDR_SO_SATURATION 0x28
+#define QSERDES_UFS_V6_RX_UCDR_FASTLOCK_COUNT_HIGH_RATE4 0x54
#define QSERDES_UFS_V6_RX_UCDR_PI_CTRL1 0x58
#define QSERDES_UFS_V6_RX_RX_TERM_BW_CTRL0 0xc4
#define QSERDES_UFS_V6_RX_UCDR_FO_GAIN_RATE2 0xd4
#define QSERDES_UFS_V6_RX_UCDR_FO_GAIN_RATE4 0xdc
+#define QSERDES_UFS_V6_RX_UCDR_SO_GAIN_RATE4 0xf0
+#define QSERDES_UFS_V6_RX_UCDR_PI_CONTROLS 0xf4
#define QSERDES_UFS_V6_RX_VGA_CAL_MAN_VAL 0x178
+#define QSERDES_UFS_V6_RX_RX_EQU_ADAPTOR_CNTRL4 0x1ac
+#define QSERDES_UFS_V6_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x1bc
#define QSERDES_UFS_V6_RX_INTERFACE_MODE 0x1e0
+#define QSERDES_UFS_V6_RX_OFFSET_ADAPTOR_CNTRL3 0x1c4
#define QSERDES_UFS_V6_RX_MODE_RATE_0_1_B0 0x208
#define QSERDES_UFS_V6_RX_MODE_RATE_0_1_B1 0x20c
+#define QSERDES_UFS_V6_RX_MODE_RATE_0_1_B2 0x210
#define QSERDES_UFS_V6_RX_MODE_RATE_0_1_B3 0x214
+#define QSERDES_UFS_V6_RX_MODE_RATE_0_1_B4 0x218
#define QSERDES_UFS_V6_RX_MODE_RATE_0_1_B6 0x220
#define QSERDES_UFS_V6_RX_MODE_RATE2_B3 0x238
#define QSERDES_UFS_V6_RX_MODE_RATE2_B6 0x244
@@ -32,7 +41,12 @@
#define QSERDES_UFS_V6_RX_MODE_RATE3_B4 0x260
#define QSERDES_UFS_V6_RX_MODE_RATE3_B5 0x264
#define QSERDES_UFS_V6_RX_MODE_RATE3_B8 0x270
+#define QSERDES_UFS_V6_RX_MODE_RATE4_B0 0x274
+#define QSERDES_UFS_V6_RX_MODE_RATE4_B1 0x278
+#define QSERDES_UFS_V6_RX_MODE_RATE4_B2 0x27c
#define QSERDES_UFS_V6_RX_MODE_RATE4_B3 0x280
+#define QSERDES_UFS_V6_RX_MODE_RATE4_B4 0x284
#define QSERDES_UFS_V6_RX_MODE_RATE4_B6 0x28c
+#define QSERDES_UFS_V6_RX_DLL0_FTUNE_CTRL 0x2f8
#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v6.h b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v6.h
index 23ffcfae9efa..f47fdc9cecda 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v6.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v6.h
@@ -6,6 +6,7 @@
#ifndef QCOM_PHY_QMP_QSERDES_TXRX_USB_V6_H_
#define QCOM_PHY_QMP_QSERDES_TXRX_USB_V6_H_
+#define QSERDES_V6_TX_BIST_MODE_LANENO 0x00
#define QSERDES_V6_TX_CLKBUF_ENABLE 0x08
#define QSERDES_V6_TX_TX_EMP_POST1_LVL 0x0c
#define QSERDES_V6_TX_TX_DRV_LVL 0x14
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v6_20.h b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v6_20.h
index 6ed5339fd2ea..7bac5d5c6c34 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v6_20.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v6_20.h
@@ -23,6 +23,8 @@
#define QSERDES_V6_20_RX_DFE_1 0xac
#define QSERDES_V6_20_RX_DFE_2 0xb0
#define QSERDES_V6_20_RX_DFE_3 0xb4
+#define QSERDES_V6_20_RX_TX_ADPT_CTRL 0xd4
+#define QSERDES_V6_20_VGA_CAL_CNTRL1 0xe0
#define QSERDES_V6_20_RX_VGA_CAL_MAN_VAL 0xe8
#define QSERDES_V6_20_RX_GM_CAL 0x10c
#define QSERDES_V6_20_RX_EQU_ADAPTOR_CNTRL4 0x120
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v6_n4.h b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v6_n4.h
index a814ad11af07..d37cc0d4fd36 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v6_n4.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v6_n4.h
@@ -6,11 +6,24 @@
#ifndef QCOM_PHY_QMP_QSERDES_TXRX_V6_N4_H_
#define QCOM_PHY_QMP_QSERDES_TXRX_V6_N4_H_
+#define QSERDES_V6_N4_TX_CLKBUF_ENABLE 0x08
+#define QSERDES_V6_N4_TX_TX_EMP_POST1_LVL 0x0c
+#define QSERDES_V6_N4_TX_TX_DRV_LVL 0x14
+#define QSERDES_V6_N4_TX_RESET_TSYNC_EN 0x1c
+#define QSERDES_V6_N4_TX_PRE_STALL_LDO_BOOST_EN 0x20
#define QSERDES_V6_N4_TX_RES_CODE_LANE_OFFSET_TX 0x30
#define QSERDES_V6_N4_TX_RES_CODE_LANE_OFFSET_RX 0x34
+#define QSERDES_V6_N4_TX_TRANSCEIVER_BIAS_EN 0x48
+#define QSERDES_V6_N4_TX_HIGHZ_DRVR_EN 0x4c
+#define QSERDES_V6_N4_TX_TX_POL_INV 0x50
+#define QSERDES_V6_N4_TX_PARRATE_REC_DETECT_IDLE_EN 0x54
#define QSERDES_V6_N4_TX_LANE_MODE_1 0x78
#define QSERDES_V6_N4_TX_LANE_MODE_2 0x7c
#define QSERDES_V6_N4_TX_LANE_MODE_3 0x80
+#define QSERDES_V6_N4_TX_TRAN_DRVR_EMP_EN 0xac
+#define QSERDES_V6_N4_TX_TX_BAND 0xd8
+#define QSERDES_V6_N4_TX_INTERFACE_SELECT 0xe4
+#define QSERDES_V6_N4_TX_VMODE_CTRL1 0xb0
#define QSERDES_V6_N4_RX_UCDR_FO_GAIN_RATE2 0x8
#define QSERDES_V6_N4_RX_UCDR_SO_GAIN_RATE2 0x18
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
index 3c2e6255e26f..d964bdfe8700 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
@@ -20,6 +20,9 @@
#include <linux/slab.h>
#include <ufs/unipro.h>
+
+#include "phy-qcom-qmp-common.h"
+
#include "phy-qcom-qmp.h"
#include "phy-qcom-qmp-pcs-ufs-v2.h"
#include "phy-qcom-qmp-pcs-ufs-v3.h"
@@ -29,41 +32,12 @@
#include "phy-qcom-qmp-qserdes-txrx-ufs-v6.h"
-/* QPHY_SW_RESET bit */
-#define SW_RESET BIT(0)
-/* QPHY_POWER_DOWN_CONTROL */
-#define SW_PWRDN BIT(0)
-/* QPHY_START_CONTROL bits */
-#define SERDES_START BIT(0)
-#define PCS_START BIT(1)
/* QPHY_PCS_READY_STATUS bit */
#define PCS_READY BIT(0)
#define PHY_INIT_COMPLETE_TIMEOUT 10000
-struct qmp_phy_init_tbl {
- unsigned int offset;
- unsigned int val;
- /*
- * mask of lanes for which this register is written
- * for cases when second lane needs different values
- */
- u8 lane_mask;
-};
-
-#define QMP_PHY_INIT_CFG(o, v) \
- { \
- .offset = o, \
- .val = v, \
- .lane_mask = 0xff, \
- }
-
-#define QMP_PHY_INIT_CFG_LANE(o, v, l) \
- { \
- .offset = o, \
- .val = v, \
- .lane_mask = l, \
- }
+#define NUM_OVERLAY 2
/* set of registers with offsets different per-PHY */
enum qphy_reg_layout {
@@ -748,21 +722,60 @@ static const struct qmp_phy_init_tbl sm8350_ufsphy_g4_pcs[] = {
QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_BIST_FIXED_PAT_CTRL, 0x0a),
};
-static const struct qmp_phy_init_tbl sm8550_ufsphy_serdes[] = {
+static const struct qmp_phy_init_tbl sm8475_ufsphy_serdes[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0xd9),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x11),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_HS_SWITCH_SEL_1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_INITVAL2, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x82),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x18),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x18),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x0c),
+};
+
+static const struct qmp_phy_init_tbl sm8475_ufsphy_g4_serdes[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x98),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE1, 0x18),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE1, 0x18),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE1, 0x32),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE1, 0x0f),
+};
+
+static const struct qmp_phy_init_tbl sm8475_ufsphy_g4_pcs[] = {
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x0b),
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_HSGEAR_CAPABILITY, 0x04),
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HSGEAR_CAPABILITY, 0x04),
+};
+
+static const struct qmp_phy_init_tbl sm8550_ufsphy_serdes[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0xd9),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x11),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_HS_SWITCH_SEL_1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x01),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_INITVAL2, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x41),
- QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x18),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x7f),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x06),
+};
+
+static const struct qmp_phy_init_tbl sm8550_ufsphy_hs_b_serdes[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x44),
+};
+
+static const struct qmp_phy_init_tbl sm8550_ufsphy_g4_serdes[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x4c),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE1, 0x18),
@@ -771,19 +784,24 @@ static const struct qmp_phy_init_tbl sm8550_ufsphy_serdes[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE1, 0x07),
};
-static const struct qmp_phy_init_tbl sm8550_ufsphy_hs_b_serdes[] = {
- QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x44),
+static const struct qmp_phy_init_tbl sm8550_ufsphy_g5_serdes[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_IETRIM, 0x1b),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_IPTRIM, 0x1c),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x06),
};
static const struct qmp_phy_init_tbl sm8550_ufsphy_tx[] = {
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_LANE_MODE_1, 0x05),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_RES_CODE_LANE_OFFSET_TX, 0x07),
+};
+
+static const struct qmp_phy_init_tbl sm8550_ufsphy_g4_tx[] = {
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_FR_DCC_CTRL, 0x4c),
};
static const struct qmp_phy_init_tbl sm8550_ufsphy_rx[] = {
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FO_GAIN_RATE2, 0x0c),
- QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_VGA_CAL_MAN_VAL, 0x0e),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B0, 0xc2),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B1, 0xc2),
@@ -799,33 +817,65 @@ static const struct qmp_phy_init_tbl sm8550_ufsphy_rx[] = {
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE3_B8, 0x02),
};
+static const struct qmp_phy_init_tbl sm8550_ufsphy_g4_rx[] = {
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_VGA_CAL_MAN_VAL, 0x0e),
+};
+
+static const struct qmp_phy_init_tbl sm8550_ufsphy_g5_rx[] = {
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FO_GAIN_RATE4, 0x0c),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_SO_GAIN_RATE4, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_PI_CONTROLS, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_OFFSET_ADAPTOR_CNTRL3, 0x0e),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FASTLOCK_COUNT_HIGH_RATE4, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FASTLOCK_FO_GAIN_RATE4, 0x1c),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FASTLOCK_SO_GAIN_RATE4, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_VGA_CAL_MAN_VAL, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B3, 0xb9),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B4, 0x4f),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B6, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_DLL0_FTUNE_CTRL, 0x30),
+};
+
static const struct qmp_phy_init_tbl sm8550_ufsphy_pcs[] = {
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_SIGDET_CTRL2, 0x69),
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0f),
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_MID_TERM_CTRL1, 0x43),
- QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x2b),
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_MULTI_LANE_CTRL1, 0x02),
+};
+
+static const struct qmp_phy_init_tbl sm8550_ufsphy_g4_pcs[] = {
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x2b),
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_HSGEAR_CAPABILITY, 0x04),
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HSGEAR_CAPABILITY, 0x04),
};
+static const struct qmp_phy_init_tbl sm8550_ufsphy_g5_pcs[] = {
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x33),
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HS_G5_SYNC_LENGTH_CAPABILITY, 0x4f),
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HSG5_SYNC_WAIT_TIME, 0x9e),
+};
+
static const struct qmp_phy_init_tbl sm8650_ufsphy_serdes[] = {
QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0xd9),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x16),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x11),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_HS_SWITCH_SEL_1, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x01),
- QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x0f),
- QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x44),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO_MODE1, 0x1f),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_IETRIM, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_IPTRIM, 0x17),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x04),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_INITVAL2, 0x00),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x41),
- QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x18),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x7f),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x4c),
- QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x06),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE1, 0x18),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE1, 0x14),
QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE1, 0x99),
@@ -833,17 +883,28 @@ static const struct qmp_phy_init_tbl sm8650_ufsphy_serdes[] = {
};
static const struct qmp_phy_init_tbl sm8650_ufsphy_tx[] = {
- QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_LANE_MODE_1, 0x05),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_LANE_MODE_1, 0x01),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_RES_CODE_LANE_OFFSET_TX, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_RES_CODE_LANE_OFFSET_RX, 0x0e),
};
static const struct qmp_phy_init_tbl sm8650_ufsphy_rx[] = {
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FO_GAIN_RATE2, 0x0c),
- QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FO_GAIN_RATE4, 0x0f),
- QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_VGA_CAL_MAN_VAL, 0x0e),
- QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B0, 0xc2),
- QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B1, 0xc2),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FO_GAIN_RATE4, 0x0c),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_SO_GAIN_RATE4, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_PI_CONTROLS, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_OFFSET_ADAPTOR_CNTRL3, 0x0e),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FASTLOCK_COUNT_HIGH_RATE4, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FASTLOCK_FO_GAIN_RATE4, 0x1c),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FASTLOCK_SO_GAIN_RATE4, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_VGA_CAL_MAN_VAL, 0x3e),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B0, 0xce),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B1, 0xce),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B2, 0x18),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B3, 0x1a),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B4, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B6, 0x60),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE2_B3, 0x9e),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE2_B6, 0x60),
@@ -851,23 +912,41 @@ static const struct qmp_phy_init_tbl sm8650_ufsphy_rx[] = {
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE3_B4, 0x0e),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE3_B5, 0x36),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE3_B8, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B0, 0x24),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B1, 0x24),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B2, 0x20),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B3, 0xb9),
- QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B6, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B4, 0x4f),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_SO_SATURATION, 0x1f),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_PI_CTRL1, 0x94),
QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_RX_TERM_BW_CTRL0, 0xfa),
+ QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_DLL0_FTUNE_CTRL, 0x30),
};
static const struct qmp_phy_init_tbl sm8650_ufsphy_pcs[] = {
- QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_MULTI_LANE_CTRL1, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_MULTI_LANE_CTRL1, 0x02),
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_MID_TERM_CTRL1, 0x43),
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PCS_CTRL1, 0xc1),
- QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x33),
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0f),
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_SIGDET_CTRL2, 0x68),
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S4, 0x0e),
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S5, 0x12),
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S6, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S7, 0x19),
+};
+
+static const struct qmp_phy_init_tbl sm8650_ufsphy_g4_pcs[] = {
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x13),
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_HSGEAR_CAPABILITY, 0x04),
QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HSGEAR_CAPABILITY, 0x04),
- QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0f),
- QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_SIGDET_CTRL2, 0x69),
- QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_MULTI_LANE_CTRL1, 0x02),
+};
+
+static const struct qmp_phy_init_tbl sm8650_ufsphy_g5_pcs[] = {
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x33),
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_HSGEAR_CAPABILITY, 0x05),
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HSGEAR_CAPABILITY, 0x05),
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HS_G5_SYNC_LENGTH_CAPABILITY, 0x4d),
+ QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HSG5_SYNC_WAIT_TIME, 0x9e),
};
struct qmp_ufs_offsets {
@@ -889,6 +968,8 @@ struct qmp_phy_cfg_tbls {
int rx_num;
const struct qmp_phy_init_tbl *pcs;
int pcs_num;
+ /* Maximum supported Gear of this tbls */
+ u32 max_gear;
};
/* struct qmp_phy_cfg - per-PHY initialization config */
@@ -896,17 +977,16 @@ struct qmp_phy_cfg {
int lanes;
const struct qmp_ufs_offsets *offsets;
+ /* Maximum supported Gear of this config */
+ u32 max_supported_gear;
/* Main init sequence for PHY blocks - serdes, tx, rx, pcs */
const struct qmp_phy_cfg_tbls tbls;
/* Additional sequence for HS Series B */
const struct qmp_phy_cfg_tbls tbls_hs_b;
- /* Additional sequence for HS G4 */
- const struct qmp_phy_cfg_tbls tbls_hs_g4;
+ /* Additional sequence for different HS Gears */
+ const struct qmp_phy_cfg_tbls tbls_hs_overlay[NUM_OVERLAY];
- /* clock ids to be requested */
- const char * const *clk_list;
- int num_clks;
/* regulators to be requested */
const char * const *vreg_list;
int num_vregs;
@@ -932,6 +1012,7 @@ struct qmp_ufs {
void __iomem *rx2;
struct clk_bulk_data *clks;
+ int num_clks;
struct regulator_bulk_data *vregs;
struct reset_control *ufs_reset;
@@ -964,20 +1045,6 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
readl(base + offset);
}
-/* list of clocks required by phy */
-static const char * const msm8996_ufs_phy_clk_l[] = {
- "ref",
-};
-
-/* the primary usb3 phy on sm8250 doesn't have a ref clock */
-static const char * const sm8450_ufs_phy_clk_l[] = {
- "qref", "ref", "ref_aux",
-};
-
-static const char * const sdm845_ufs_phy_clk_l[] = {
- "ref", "ref_aux",
-};
-
/* list of regulators */
static const char * const qmp_phy_vreg_l[] = {
"vdda-phy", "vdda-pll",
@@ -1005,6 +1072,7 @@ static const struct qmp_phy_cfg msm8996_ufsphy_cfg = {
.lanes = 1,
.offsets = &qmp_ufs_offsets,
+ .max_supported_gear = UFS_HS_G3,
.tbls = {
.serdes = msm8996_ufsphy_serdes,
@@ -1015,9 +1083,6 @@ static const struct qmp_phy_cfg msm8996_ufsphy_cfg = {
.rx_num = ARRAY_SIZE(msm8996_ufsphy_rx),
},
- .clk_list = msm8996_ufs_phy_clk_l,
- .num_clks = ARRAY_SIZE(msm8996_ufs_phy_clk_l),
-
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
@@ -1030,6 +1095,7 @@ static const struct qmp_phy_cfg sa8775p_ufsphy_cfg = {
.lanes = 2,
.offsets = &qmp_ufs_offsets,
+ .max_supported_gear = UFS_HS_G4,
.tbls = {
.serdes = sm8350_ufsphy_serdes,
@@ -1045,16 +1111,15 @@ static const struct qmp_phy_cfg sa8775p_ufsphy_cfg = {
.serdes = sm8350_ufsphy_hs_b_serdes,
.serdes_num = ARRAY_SIZE(sm8350_ufsphy_hs_b_serdes),
},
- .tbls_hs_g4 = {
+ .tbls_hs_overlay[0] = {
.tx = sm8350_ufsphy_g4_tx,
.tx_num = ARRAY_SIZE(sm8350_ufsphy_g4_tx),
.rx = sm8350_ufsphy_g4_rx,
.rx_num = ARRAY_SIZE(sm8350_ufsphy_g4_rx),
.pcs = sm8350_ufsphy_g4_pcs,
.pcs_num = ARRAY_SIZE(sm8350_ufsphy_g4_pcs),
+ .max_gear = UFS_HS_G4,
},
- .clk_list = sm8450_ufs_phy_clk_l,
- .num_clks = ARRAY_SIZE(sm8450_ufs_phy_clk_l),
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.regs = ufsphy_v5_regs_layout,
@@ -1064,6 +1129,7 @@ static const struct qmp_phy_cfg sc7280_ufsphy_cfg = {
.lanes = 2,
.offsets = &qmp_ufs_offsets,
+ .max_supported_gear = UFS_HS_G4,
.tbls = {
.serdes = sm8150_ufsphy_serdes,
@@ -1079,16 +1145,15 @@ static const struct qmp_phy_cfg sc7280_ufsphy_cfg = {
.serdes = sm8150_ufsphy_hs_b_serdes,
.serdes_num = ARRAY_SIZE(sm8150_ufsphy_hs_b_serdes),
},
- .tbls_hs_g4 = {
+ .tbls_hs_overlay[0] = {
.tx = sm8250_ufsphy_hs_g4_tx,
.tx_num = ARRAY_SIZE(sm8250_ufsphy_hs_g4_tx),
.rx = sc7280_ufsphy_hs_g4_rx,
.rx_num = ARRAY_SIZE(sc7280_ufsphy_hs_g4_rx),
.pcs = sm8150_ufsphy_hs_g4_pcs,
.pcs_num = ARRAY_SIZE(sm8150_ufsphy_hs_g4_pcs),
+ .max_gear = UFS_HS_G4,
},
- .clk_list = sm8450_ufs_phy_clk_l,
- .num_clks = ARRAY_SIZE(sm8450_ufs_phy_clk_l),
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.regs = ufsphy_v4_regs_layout,
@@ -1098,6 +1163,7 @@ static const struct qmp_phy_cfg sc8280xp_ufsphy_cfg = {
.lanes = 2,
.offsets = &qmp_ufs_offsets,
+ .max_supported_gear = UFS_HS_G4,
.tbls = {
.serdes = sm8350_ufsphy_serdes,
@@ -1113,16 +1179,15 @@ static const struct qmp_phy_cfg sc8280xp_ufsphy_cfg = {
.serdes = sm8350_ufsphy_hs_b_serdes,
.serdes_num = ARRAY_SIZE(sm8350_ufsphy_hs_b_serdes),
},
- .tbls_hs_g4 = {
+ .tbls_hs_overlay[0] = {
.tx = sm8350_ufsphy_g4_tx,
.tx_num = ARRAY_SIZE(sm8350_ufsphy_g4_tx),
.rx = sm8350_ufsphy_g4_rx,
.rx_num = ARRAY_SIZE(sm8350_ufsphy_g4_rx),
.pcs = sm8350_ufsphy_g4_pcs,
.pcs_num = ARRAY_SIZE(sm8350_ufsphy_g4_pcs),
+ .max_gear = UFS_HS_G4,
},
- .clk_list = sdm845_ufs_phy_clk_l,
- .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l),
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.regs = ufsphy_v5_regs_layout,
@@ -1132,6 +1197,7 @@ static const struct qmp_phy_cfg sdm845_ufsphy_cfg = {
.lanes = 2,
.offsets = &qmp_ufs_offsets,
+ .max_supported_gear = UFS_HS_G3,
.tbls = {
.serdes = sdm845_ufsphy_serdes,
@@ -1147,8 +1213,6 @@ static const struct qmp_phy_cfg sdm845_ufsphy_cfg = {
.serdes = sdm845_ufsphy_hs_b_serdes,
.serdes_num = ARRAY_SIZE(sdm845_ufsphy_hs_b_serdes),
},
- .clk_list = sdm845_ufs_phy_clk_l,
- .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l),
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.regs = ufsphy_v3_regs_layout,
@@ -1160,6 +1224,7 @@ static const struct qmp_phy_cfg sm6115_ufsphy_cfg = {
.lanes = 1,
.offsets = &qmp_ufs_offsets,
+ .max_supported_gear = UFS_HS_G3,
.tbls = {
.serdes = sm6115_ufsphy_serdes,
@@ -1175,8 +1240,6 @@ static const struct qmp_phy_cfg sm6115_ufsphy_cfg = {
.serdes = sm6115_ufsphy_hs_b_serdes,
.serdes_num = ARRAY_SIZE(sm6115_ufsphy_hs_b_serdes),
},
- .clk_list = sdm845_ufs_phy_clk_l,
- .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l),
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.regs = ufsphy_v2_regs_layout,
@@ -1188,6 +1251,7 @@ static const struct qmp_phy_cfg sm7150_ufsphy_cfg = {
.lanes = 1,
.offsets = &qmp_ufs_offsets,
+ .max_supported_gear = UFS_HS_G3,
.tbls = {
.serdes = sdm845_ufsphy_serdes,
@@ -1203,8 +1267,6 @@ static const struct qmp_phy_cfg sm7150_ufsphy_cfg = {
.serdes = sdm845_ufsphy_hs_b_serdes,
.serdes_num = ARRAY_SIZE(sdm845_ufsphy_hs_b_serdes),
},
- .clk_list = sdm845_ufs_phy_clk_l,
- .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l),
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.regs = ufsphy_v3_regs_layout,
@@ -1216,6 +1278,7 @@ static const struct qmp_phy_cfg sm8150_ufsphy_cfg = {
.lanes = 2,
.offsets = &qmp_ufs_offsets,
+ .max_supported_gear = UFS_HS_G4,
.tbls = {
.serdes = sm8150_ufsphy_serdes,
@@ -1231,16 +1294,15 @@ static const struct qmp_phy_cfg sm8150_ufsphy_cfg = {
.serdes = sm8150_ufsphy_hs_b_serdes,
.serdes_num = ARRAY_SIZE(sm8150_ufsphy_hs_b_serdes),
},
- .tbls_hs_g4 = {
+ .tbls_hs_overlay[0] = {
.tx = sm8150_ufsphy_hs_g4_tx,
.tx_num = ARRAY_SIZE(sm8150_ufsphy_hs_g4_tx),
.rx = sm8150_ufsphy_hs_g4_rx,
.rx_num = ARRAY_SIZE(sm8150_ufsphy_hs_g4_rx),
.pcs = sm8150_ufsphy_hs_g4_pcs,
.pcs_num = ARRAY_SIZE(sm8150_ufsphy_hs_g4_pcs),
+ .max_gear = UFS_HS_G4,
},
- .clk_list = sdm845_ufs_phy_clk_l,
- .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l),
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.regs = ufsphy_v4_regs_layout,
@@ -1250,6 +1312,7 @@ static const struct qmp_phy_cfg sm8250_ufsphy_cfg = {
.lanes = 2,
.offsets = &qmp_ufs_offsets,
+ .max_supported_gear = UFS_HS_G4,
.tbls = {
.serdes = sm8150_ufsphy_serdes,
@@ -1265,16 +1328,15 @@ static const struct qmp_phy_cfg sm8250_ufsphy_cfg = {
.serdes = sm8150_ufsphy_hs_b_serdes,
.serdes_num = ARRAY_SIZE(sm8150_ufsphy_hs_b_serdes),
},
- .tbls_hs_g4 = {
+ .tbls_hs_overlay[0] = {
.tx = sm8250_ufsphy_hs_g4_tx,
.tx_num = ARRAY_SIZE(sm8250_ufsphy_hs_g4_tx),
.rx = sm8250_ufsphy_hs_g4_rx,
.rx_num = ARRAY_SIZE(sm8250_ufsphy_hs_g4_rx),
.pcs = sm8150_ufsphy_hs_g4_pcs,
.pcs_num = ARRAY_SIZE(sm8150_ufsphy_hs_g4_pcs),
+ .max_gear = UFS_HS_G4,
},
- .clk_list = sdm845_ufs_phy_clk_l,
- .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l),
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.regs = ufsphy_v4_regs_layout,
@@ -1284,6 +1346,7 @@ static const struct qmp_phy_cfg sm8350_ufsphy_cfg = {
.lanes = 2,
.offsets = &qmp_ufs_offsets,
+ .max_supported_gear = UFS_HS_G4,
.tbls = {
.serdes = sm8350_ufsphy_serdes,
@@ -1299,16 +1362,15 @@ static const struct qmp_phy_cfg sm8350_ufsphy_cfg = {
.serdes = sm8350_ufsphy_hs_b_serdes,
.serdes_num = ARRAY_SIZE(sm8350_ufsphy_hs_b_serdes),
},
- .tbls_hs_g4 = {
+ .tbls_hs_overlay[0] = {
.tx = sm8350_ufsphy_g4_tx,
.tx_num = ARRAY_SIZE(sm8350_ufsphy_g4_tx),
.rx = sm8350_ufsphy_g4_rx,
.rx_num = ARRAY_SIZE(sm8350_ufsphy_g4_rx),
.pcs = sm8350_ufsphy_g4_pcs,
.pcs_num = ARRAY_SIZE(sm8350_ufsphy_g4_pcs),
+ .max_gear = UFS_HS_G4,
},
- .clk_list = sdm845_ufs_phy_clk_l,
- .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l),
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.regs = ufsphy_v5_regs_layout,
@@ -1318,6 +1380,7 @@ static const struct qmp_phy_cfg sm8450_ufsphy_cfg = {
.lanes = 2,
.offsets = &qmp_ufs_offsets,
+ .max_supported_gear = UFS_HS_G4,
.tbls = {
.serdes = sm8350_ufsphy_serdes,
@@ -1333,25 +1396,61 @@ static const struct qmp_phy_cfg sm8450_ufsphy_cfg = {
.serdes = sm8350_ufsphy_hs_b_serdes,
.serdes_num = ARRAY_SIZE(sm8350_ufsphy_hs_b_serdes),
},
- .tbls_hs_g4 = {
+ .tbls_hs_overlay[0] = {
.tx = sm8350_ufsphy_g4_tx,
.tx_num = ARRAY_SIZE(sm8350_ufsphy_g4_tx),
.rx = sm8350_ufsphy_g4_rx,
.rx_num = ARRAY_SIZE(sm8350_ufsphy_g4_rx),
.pcs = sm8350_ufsphy_g4_pcs,
.pcs_num = ARRAY_SIZE(sm8350_ufsphy_g4_pcs),
+ .max_gear = UFS_HS_G4,
},
- .clk_list = sm8450_ufs_phy_clk_l,
- .num_clks = ARRAY_SIZE(sm8450_ufs_phy_clk_l),
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.regs = ufsphy_v5_regs_layout,
};
+static const struct qmp_phy_cfg sm8475_ufsphy_cfg = {
+ .lanes = 2,
+
+ .offsets = &qmp_ufs_offsets_v6,
+ .max_supported_gear = UFS_HS_G4,
+
+ .tbls = {
+ .serdes = sm8475_ufsphy_serdes,
+ .serdes_num = ARRAY_SIZE(sm8475_ufsphy_serdes),
+ .tx = sm8550_ufsphy_tx,
+ .tx_num = ARRAY_SIZE(sm8550_ufsphy_tx),
+ .rx = sm8550_ufsphy_rx,
+ .rx_num = ARRAY_SIZE(sm8550_ufsphy_rx),
+ .pcs = sm8550_ufsphy_pcs,
+ .pcs_num = ARRAY_SIZE(sm8550_ufsphy_pcs),
+ },
+ .tbls_hs_b = {
+ .serdes = sm8550_ufsphy_hs_b_serdes,
+ .serdes_num = ARRAY_SIZE(sm8550_ufsphy_hs_b_serdes),
+ },
+ .tbls_hs_overlay[0] = {
+ .serdes = sm8475_ufsphy_g4_serdes,
+ .serdes_num = ARRAY_SIZE(sm8475_ufsphy_g4_serdes),
+ .tx = sm8550_ufsphy_g4_tx,
+ .tx_num = ARRAY_SIZE(sm8550_ufsphy_g4_tx),
+ .rx = sm8550_ufsphy_g4_rx,
+ .rx_num = ARRAY_SIZE(sm8550_ufsphy_g4_rx),
+ .pcs = sm8475_ufsphy_g4_pcs,
+ .pcs_num = ARRAY_SIZE(sm8475_ufsphy_g4_pcs),
+ .max_gear = UFS_HS_G4,
+ },
+ .vreg_list = qmp_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
+ .regs = ufsphy_v6_regs_layout,
+};
+
static const struct qmp_phy_cfg sm8550_ufsphy_cfg = {
.lanes = 2,
.offsets = &qmp_ufs_offsets_v6,
+ .max_supported_gear = UFS_HS_G5,
.tbls = {
.serdes = sm8550_ufsphy_serdes,
@@ -1367,8 +1466,26 @@ static const struct qmp_phy_cfg sm8550_ufsphy_cfg = {
.serdes = sm8550_ufsphy_hs_b_serdes,
.serdes_num = ARRAY_SIZE(sm8550_ufsphy_hs_b_serdes),
},
- .clk_list = sdm845_ufs_phy_clk_l,
- .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l),
+ .tbls_hs_overlay[0] = {
+ .serdes = sm8550_ufsphy_g4_serdes,
+ .serdes_num = ARRAY_SIZE(sm8550_ufsphy_g4_serdes),
+ .tx = sm8550_ufsphy_g4_tx,
+ .tx_num = ARRAY_SIZE(sm8550_ufsphy_g4_tx),
+ .rx = sm8550_ufsphy_g4_rx,
+ .rx_num = ARRAY_SIZE(sm8550_ufsphy_g4_rx),
+ .pcs = sm8550_ufsphy_g4_pcs,
+ .pcs_num = ARRAY_SIZE(sm8550_ufsphy_g4_pcs),
+ .max_gear = UFS_HS_G4,
+ },
+ .tbls_hs_overlay[1] = {
+ .serdes = sm8550_ufsphy_g5_serdes,
+ .serdes_num = ARRAY_SIZE(sm8550_ufsphy_g5_serdes),
+ .rx = sm8550_ufsphy_g5_rx,
+ .rx_num = ARRAY_SIZE(sm8550_ufsphy_g5_rx),
+ .pcs = sm8550_ufsphy_g5_pcs,
+ .pcs_num = ARRAY_SIZE(sm8550_ufsphy_g5_pcs),
+ .max_gear = UFS_HS_G5,
+ },
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.regs = ufsphy_v6_regs_layout,
@@ -1378,6 +1495,7 @@ static const struct qmp_phy_cfg sm8650_ufsphy_cfg = {
.lanes = 2,
.offsets = &qmp_ufs_offsets_v6,
+ .max_supported_gear = UFS_HS_G5,
.tbls = {
.serdes = sm8650_ufsphy_serdes,
@@ -1389,44 +1507,27 @@ static const struct qmp_phy_cfg sm8650_ufsphy_cfg = {
.pcs = sm8650_ufsphy_pcs,
.pcs_num = ARRAY_SIZE(sm8650_ufsphy_pcs),
},
- .clk_list = sdm845_ufs_phy_clk_l,
- .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l),
+ .tbls_hs_overlay[0] = {
+ .pcs = sm8650_ufsphy_g4_pcs,
+ .pcs_num = ARRAY_SIZE(sm8650_ufsphy_g4_pcs),
+ .max_gear = UFS_HS_G4,
+ },
+ .tbls_hs_overlay[1] = {
+ .pcs = sm8650_ufsphy_g5_pcs,
+ .pcs_num = ARRAY_SIZE(sm8650_ufsphy_g5_pcs),
+ .max_gear = UFS_HS_G5,
+ },
+
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.regs = ufsphy_v6_regs_layout,
};
-static void qmp_ufs_configure_lane(void __iomem *base,
- const struct qmp_phy_init_tbl tbl[],
- int num,
- u8 lane_mask)
-{
- int i;
- const struct qmp_phy_init_tbl *t = tbl;
-
- if (!t)
- return;
-
- for (i = 0; i < num; i++, t++) {
- if (!(t->lane_mask & lane_mask))
- continue;
-
- writel(t->val, base + t->offset);
- }
-}
-
-static void qmp_ufs_configure(void __iomem *base,
- const struct qmp_phy_init_tbl tbl[],
- int num)
-{
- qmp_ufs_configure_lane(base, tbl, num, 0xff);
-}
-
static void qmp_ufs_serdes_init(struct qmp_ufs *qmp, const struct qmp_phy_cfg_tbls *tbls)
{
void __iomem *serdes = qmp->serdes;
- qmp_ufs_configure(serdes, tbls->serdes, tbls->serdes_num);
+ qmp_configure(qmp->dev, serdes, tbls->serdes, tbls->serdes_num);
}
static void qmp_ufs_lanes_init(struct qmp_ufs *qmp, const struct qmp_phy_cfg_tbls *tbls)
@@ -1435,12 +1536,12 @@ static void qmp_ufs_lanes_init(struct qmp_ufs *qmp, const struct qmp_phy_cfg_tbl
void __iomem *tx = qmp->tx;
void __iomem *rx = qmp->rx;
- qmp_ufs_configure_lane(tx, tbls->tx, tbls->tx_num, 1);
- qmp_ufs_configure_lane(rx, tbls->rx, tbls->rx_num, 1);
+ qmp_configure_lane(qmp->dev, tx, tbls->tx, tbls->tx_num, 1);
+ qmp_configure_lane(qmp->dev, rx, tbls->rx, tbls->rx_num, 1);
if (cfg->lanes >= 2) {
- qmp_ufs_configure_lane(qmp->tx2, tbls->tx, tbls->tx_num, 2);
- qmp_ufs_configure_lane(qmp->rx2, tbls->rx, tbls->rx_num, 2);
+ qmp_configure_lane(qmp->dev, qmp->tx2, tbls->tx, tbls->tx_num, 2);
+ qmp_configure_lane(qmp->dev, qmp->rx2, tbls->rx, tbls->rx_num, 2);
}
}
@@ -1448,20 +1549,52 @@ static void qmp_ufs_pcs_init(struct qmp_ufs *qmp, const struct qmp_phy_cfg_tbls
{
void __iomem *pcs = qmp->pcs;
- qmp_ufs_configure(pcs, tbls->pcs, tbls->pcs_num);
+ qmp_configure(qmp->dev, pcs, tbls->pcs, tbls->pcs_num);
+}
+
+static int qmp_ufs_get_gear_overlay(struct qmp_ufs *qmp, const struct qmp_phy_cfg *cfg)
+{
+ u32 max_gear, floor_max_gear = cfg->max_supported_gear;
+ int idx, ret = -EINVAL;
+
+ for (idx = NUM_OVERLAY - 1; idx >= 0; idx--) {
+ max_gear = cfg->tbls_hs_overlay[idx].max_gear;
+
+ /* Skip if the table is not available */
+ if (max_gear == 0)
+ continue;
+
+ /* Direct matching, bail */
+ if (qmp->submode == max_gear)
+ return idx;
+
+ /* If no direct matching, the lowest gear is the best matching */
+ if (max_gear < floor_max_gear) {
+ ret = idx;
+ floor_max_gear = max_gear;
+ }
+ }
+
+ return ret;
}
static void qmp_ufs_init_registers(struct qmp_ufs *qmp, const struct qmp_phy_cfg *cfg)
{
+ int i;
+
qmp_ufs_serdes_init(qmp, &cfg->tbls);
- if (qmp->mode == PHY_MODE_UFS_HS_B)
- qmp_ufs_serdes_init(qmp, &cfg->tbls_hs_b);
qmp_ufs_lanes_init(qmp, &cfg->tbls);
- if (qmp->submode == UFS_HS_G4)
- qmp_ufs_lanes_init(qmp, &cfg->tbls_hs_g4);
qmp_ufs_pcs_init(qmp, &cfg->tbls);
- if (qmp->submode == UFS_HS_G4)
- qmp_ufs_pcs_init(qmp, &cfg->tbls_hs_g4);
+
+ i = qmp_ufs_get_gear_overlay(qmp, cfg);
+ if (i >= 0) {
+ qmp_ufs_serdes_init(qmp, &cfg->tbls_hs_overlay[i]);
+ qmp_ufs_lanes_init(qmp, &cfg->tbls_hs_overlay[i]);
+ qmp_ufs_pcs_init(qmp, &cfg->tbls_hs_overlay[i]);
+ }
+
+ if (qmp->mode == PHY_MODE_UFS_HS_B)
+ qmp_ufs_serdes_init(qmp, &cfg->tbls_hs_b);
}
static int qmp_ufs_com_init(struct qmp_ufs *qmp)
@@ -1476,7 +1609,7 @@ static int qmp_ufs_com_init(struct qmp_ufs *qmp)
return ret;
}
- ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks);
+ ret = clk_bulk_prepare_enable(qmp->num_clks, qmp->clks);
if (ret)
goto err_disable_regulators;
@@ -1496,7 +1629,7 @@ static int qmp_ufs_com_exit(struct qmp_ufs *qmp)
reset_control_assert(qmp->ufs_reset);
- clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks);
+ clk_bulk_disable_unprepare(qmp->num_clks, qmp->clks);
regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
@@ -1633,6 +1766,12 @@ static int qmp_ufs_disable(struct phy *phy)
static int qmp_ufs_set_mode(struct phy *phy, enum phy_mode mode, int submode)
{
struct qmp_ufs *qmp = phy_get_drvdata(phy);
+ const struct qmp_phy_cfg *cfg = qmp->cfg;
+
+ if (submode > cfg->max_supported_gear || submode == 0) {
+ dev_err(qmp->dev, "Invalid PHY submode %d\n", submode);
+ return -EINVAL;
+ }
qmp->mode = mode;
qmp->submode = submode;
@@ -1666,19 +1805,13 @@ static int qmp_ufs_vreg_init(struct qmp_ufs *qmp)
static int qmp_ufs_clk_init(struct qmp_ufs *qmp)
{
- const struct qmp_phy_cfg *cfg = qmp->cfg;
struct device *dev = qmp->dev;
- int num = cfg->num_clks;
- int i;
-
- qmp->clks = devm_kcalloc(dev, num, sizeof(*qmp->clks), GFP_KERNEL);
- if (!qmp->clks)
- return -ENOMEM;
- for (i = 0; i < num; i++)
- qmp->clks[i].id = cfg->clk_list[i];
+ qmp->num_clks = devm_clk_bulk_get_all(dev, &qmp->clks);
+ if (qmp->num_clks < 0)
+ return qmp->num_clks;
- return devm_clk_bulk_get(dev, num, qmp->clks);
+ return 0;
}
static void qmp_ufs_clk_release_provider(void *res)
@@ -1881,6 +2014,9 @@ static const struct of_device_id qmp_ufs_of_match_table[] = {
.compatible = "qcom,sa8775p-qmp-ufs-phy",
.data = &sa8775p_ufsphy_cfg,
}, {
+ .compatible = "qcom,sc7180-qmp-ufs-phy",
+ .data = &sm7150_ufsphy_cfg,
+ }, {
.compatible = "qcom,sc7280-qmp-ufs-phy",
.data = &sc7280_ufsphy_cfg,
}, {
@@ -1917,6 +2053,9 @@ static const struct of_device_id qmp_ufs_of_match_table[] = {
.compatible = "qcom,sm8450-qmp-ufs-phy",
.data = &sm8450_ufsphy_cfg,
}, {
+ .compatible = "qcom,sm8475-qmp-ufs-phy",
+ .data = &sm8475_ufsphy_cfg,
+ }, {
.compatible = "qcom,sm8550-qmp-ufs-phy",
.data = &sm8550_ufsphy_cfg,
}, {
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usb-legacy.c b/drivers/phy/qualcomm/phy-qcom-qmp-usb-legacy.c
index cf466f6df94d..8bf951b0490c 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-usb-legacy.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-usb-legacy.c
@@ -25,15 +25,7 @@
#include "phy-qcom-qmp-pcs-usb-v4.h"
#include "phy-qcom-qmp-pcs-usb-v5.h"
-/* QPHY_SW_RESET bit */
-#define SW_RESET BIT(0)
-/* QPHY_POWER_DOWN_CONTROL */
-#define SW_PWRDN BIT(0)
-/* QPHY_START_CONTROL bits */
-#define SERDES_START BIT(0)
-#define PCS_START BIT(1)
-/* QPHY_PCS_STATUS bit */
-#define PHYSTATUS BIT(6)
+#include "phy-qcom-qmp-dp-com-v3.h"
/* QPHY_V3_DP_COM_RESET_OVRD_CTRL register bits */
/* DP PHY soft reset */
@@ -49,17 +41,6 @@
#define USB3_MODE BIT(0) /* enables USB3 mode */
#define DP_MODE BIT(1) /* enables DP mode */
-/* QPHY_PCS_AUTONOMOUS_MODE_CTRL register bits */
-#define ARCVR_DTCT_EN BIT(0)
-#define ALFPS_DTCT_EN BIT(1)
-#define ARCVR_DTCT_EVENT_SEL BIT(4)
-
-/* QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR register bits */
-#define IRQ_CLEAR BIT(0)
-
-/* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */
-#define CLAMP_EN BIT(0) /* enables i/o clamp_n */
-
#define PHY_INIT_COMPLETE_TIMEOUT 10000
struct qmp_phy_init_tbl {
@@ -507,8 +488,6 @@ struct qmp_usb_legacy_offsets {
/* struct qmp_phy_cfg - per-PHY initialization config */
struct qmp_phy_cfg {
- int lanes;
-
const struct qmp_usb_legacy_offsets *offsets;
/* Init sequence for PHY blocks - serdes, tx, rx, pcs */
@@ -621,8 +600,6 @@ static const char * const qmp_phy_vreg_l[] = {
};
static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = {
- .lanes = 2,
-
.serdes_tbl = qmp_v3_usb3_serdes_tbl,
.serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl),
.tx_tbl = qmp_v3_usb3_tx_tbl,
@@ -641,8 +618,6 @@ static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = {
};
static const struct qmp_phy_cfg sc7180_usb3phy_cfg = {
- .lanes = 2,
-
.serdes_tbl = qmp_v3_usb3_serdes_tbl,
.serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl),
.tx_tbl = qmp_v3_usb3_tx_tbl,
@@ -661,8 +636,6 @@ static const struct qmp_phy_cfg sc7180_usb3phy_cfg = {
};
static const struct qmp_phy_cfg sm8150_usb3phy_cfg = {
- .lanes = 2,
-
.serdes_tbl = sm8150_usb3_serdes_tbl,
.serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl),
.tx_tbl = sm8150_usb3_tx_tbl,
@@ -684,8 +657,6 @@ static const struct qmp_phy_cfg sm8150_usb3phy_cfg = {
};
static const struct qmp_phy_cfg sm8250_usb3phy_cfg = {
- .lanes = 2,
-
.serdes_tbl = sm8150_usb3_serdes_tbl,
.serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl),
.tx_tbl = sm8250_usb3_tx_tbl,
@@ -707,8 +678,6 @@ static const struct qmp_phy_cfg sm8250_usb3phy_cfg = {
};
static const struct qmp_phy_cfg sm8350_usb3phy_cfg = {
- .lanes = 2,
-
.serdes_tbl = sm8150_usb3_serdes_tbl,
.serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl),
.tx_tbl = sm8350_usb3_tx_tbl,
@@ -874,10 +843,8 @@ static int qmp_usb_legacy_power_on(struct phy *phy)
qmp_usb_legacy_configure_lane(tx, cfg->tx_tbl, cfg->tx_tbl_num, 1);
qmp_usb_legacy_configure_lane(rx, cfg->rx_tbl, cfg->rx_tbl_num, 1);
- if (cfg->lanes >= 2) {
- qmp_usb_legacy_configure_lane(qmp->tx2, cfg->tx_tbl, cfg->tx_tbl_num, 2);
- qmp_usb_legacy_configure_lane(qmp->rx2, cfg->rx_tbl, cfg->rx_tbl_num, 2);
- }
+ qmp_usb_legacy_configure_lane(qmp->tx2, cfg->tx_tbl, cfg->tx_tbl_num, 2);
+ qmp_usb_legacy_configure_lane(qmp->rx2, cfg->rx_tbl, cfg->rx_tbl_num, 2);
qmp_usb_legacy_configure(pcs, cfg->pcs_tbl, cfg->pcs_tbl_num);
@@ -1180,27 +1147,11 @@ static int phy_pipe_clk_register(struct qmp_usb *qmp, struct device_node *np)
return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, np);
}
-static void __iomem *qmp_usb_legacy_iomap(struct device *dev, struct device_node *np,
- int index, bool exclusive)
-{
- struct resource res;
-
- if (!exclusive) {
- if (of_address_to_resource(np, index, &res))
- return IOMEM_ERR_PTR(-EINVAL);
-
- return devm_ioremap(dev, res.start, resource_size(&res));
- }
-
- return devm_of_iomap(dev, np, index, NULL);
-}
-
static int qmp_usb_legacy_parse_dt_legacy(struct qmp_usb *qmp, struct device_node *np)
{
struct platform_device *pdev = to_platform_device(qmp->dev);
const struct qmp_phy_cfg *cfg = qmp->cfg;
struct device *dev = qmp->dev;
- bool exclusive = true;
qmp->serdes = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(qmp->serdes))
@@ -1224,27 +1175,22 @@ static int qmp_usb_legacy_parse_dt_legacy(struct qmp_usb *qmp, struct device_nod
if (IS_ERR(qmp->rx))
return PTR_ERR(qmp->rx);
- qmp->pcs = qmp_usb_legacy_iomap(dev, np, 2, exclusive);
+ qmp->pcs = devm_of_iomap(dev, np, 2, NULL);
if (IS_ERR(qmp->pcs))
return PTR_ERR(qmp->pcs);
if (cfg->pcs_usb_offset)
qmp->pcs_usb = qmp->pcs + cfg->pcs_usb_offset;
- if (cfg->lanes >= 2) {
- qmp->tx2 = devm_of_iomap(dev, np, 3, NULL);
- if (IS_ERR(qmp->tx2))
- return PTR_ERR(qmp->tx2);
-
- qmp->rx2 = devm_of_iomap(dev, np, 4, NULL);
- if (IS_ERR(qmp->rx2))
- return PTR_ERR(qmp->rx2);
+ qmp->tx2 = devm_of_iomap(dev, np, 3, NULL);
+ if (IS_ERR(qmp->tx2))
+ return PTR_ERR(qmp->tx2);
- qmp->pcs_misc = devm_of_iomap(dev, np, 5, NULL);
- } else {
- qmp->pcs_misc = devm_of_iomap(dev, np, 3, NULL);
- }
+ qmp->rx2 = devm_of_iomap(dev, np, 4, NULL);
+ if (IS_ERR(qmp->rx2))
+ return PTR_ERR(qmp->rx2);
+ qmp->pcs_misc = devm_of_iomap(dev, np, 5, NULL);
if (IS_ERR(qmp->pcs_misc)) {
dev_vdbg(dev, "PHY pcs_misc-reg not used\n");
qmp->pcs_misc = NULL;
@@ -1302,6 +1248,7 @@ static int qmp_usb_legacy_probe(struct platform_device *pdev)
return -ENOMEM;
qmp->dev = dev;
+ dev_set_drvdata(dev, qmp);
qmp->cfg = of_device_get_match_data(dev);
if (!qmp->cfg)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c
index 5c003988c35d..787721570457 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c
@@ -19,6 +19,8 @@
#include <linux/reset.h>
#include <linux/slab.h>
+#include "phy-qcom-qmp-common.h"
+
#include "phy-qcom-qmp.h"
#include "phy-qcom-qmp-pcs-misc-v3.h"
#include "phy-qcom-qmp-pcs-misc-v4.h"
@@ -27,67 +29,8 @@
#include "phy-qcom-qmp-pcs-usb-v6.h"
#include "phy-qcom-qmp-pcs-usb-v7.h"
-/* QPHY_SW_RESET bit */
-#define SW_RESET BIT(0)
-/* QPHY_POWER_DOWN_CONTROL */
-#define SW_PWRDN BIT(0)
-/* QPHY_START_CONTROL bits */
-#define SERDES_START BIT(0)
-#define PCS_START BIT(1)
-/* QPHY_PCS_STATUS bit */
-#define PHYSTATUS BIT(6)
-
-/* QPHY_V3_DP_COM_RESET_OVRD_CTRL register bits */
-/* DP PHY soft reset */
-#define SW_DPPHY_RESET BIT(0)
-/* mux to select DP PHY reset control, 0:HW control, 1: software reset */
-#define SW_DPPHY_RESET_MUX BIT(1)
-/* USB3 PHY soft reset */
-#define SW_USB3PHY_RESET BIT(2)
-/* mux to select USB3 PHY reset control, 0:HW control, 1: software reset */
-#define SW_USB3PHY_RESET_MUX BIT(3)
-
-/* QPHY_V3_DP_COM_PHY_MODE_CTRL register bits */
-#define USB3_MODE BIT(0) /* enables USB3 mode */
-#define DP_MODE BIT(1) /* enables DP mode */
-
-/* QPHY_PCS_AUTONOMOUS_MODE_CTRL register bits */
-#define ARCVR_DTCT_EN BIT(0)
-#define ALFPS_DTCT_EN BIT(1)
-#define ARCVR_DTCT_EVENT_SEL BIT(4)
-
-/* QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR register bits */
-#define IRQ_CLEAR BIT(0)
-
-/* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */
-#define CLAMP_EN BIT(0) /* enables i/o clamp_n */
-
#define PHY_INIT_COMPLETE_TIMEOUT 10000
-struct qmp_phy_init_tbl {
- unsigned int offset;
- unsigned int val;
- /*
- * mask of lanes for which this register is written
- * for cases when second lane needs different values
- */
- u8 lane_mask;
-};
-
-#define QMP_PHY_INIT_CFG(o, v) \
- { \
- .offset = o, \
- .val = v, \
- .lane_mask = 0xff, \
- }
-
-#define QMP_PHY_INIT_CFG_LANE(o, v, l) \
- { \
- .offset = o, \
- .val = v, \
- .lane_mask = l, \
- }
-
/* set of registers with offsets different per-PHY */
enum qphy_reg_layout {
/* PCS registers */
@@ -121,15 +64,6 @@ static const unsigned int qmp_v3_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_PCS_MISC_CLAMP_ENABLE] = QPHY_V3_PCS_MISC_CLAMP_ENABLE,
};
-static const unsigned int qmp_v3_usb3phy_regs_layout_qcm2290[QPHY_LAYOUT_SIZE] = {
- [QPHY_SW_RESET] = QPHY_V3_PCS_SW_RESET,
- [QPHY_START_CTRL] = QPHY_V3_PCS_START_CONTROL,
- [QPHY_PCS_STATUS] = QPHY_V3_PCS_PCS_STATUS,
- [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = QPHY_V3_PCS_AUTONOMOUS_MODE_CTRL,
- [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = QPHY_V3_PCS_LFPS_RXTERM_IRQ_CLEAR,
- [QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V3_PCS_POWER_DOWN_CONTROL,
-};
-
static const unsigned int qmp_v4_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
[QPHY_SW_RESET] = QPHY_V4_PCS_SW_RESET,
[QPHY_START_CTRL] = QPHY_V4_PCS_START_CONTROL,
@@ -403,6 +337,29 @@ static const struct qmp_phy_init_tbl msm8996_usb3_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V2_PCS_POWER_STATE_CONFIG2, 0x08),
};
+static const struct qmp_phy_init_tbl qdu1000_usb3_uniphy_pcs_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xc4),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x89),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21),
+};
+
+static const struct qmp_phy_init_tbl qdu1000_usb3_uniphy_pcs_usb_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8),
+ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_POWER_STATE_CONFIG1, 0x6f),
+};
+
static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07),
QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14),
@@ -514,115 +471,6 @@ static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG2, 0x60),
};
-static const struct qmp_phy_init_tbl msm8998_usb3_serdes_tbl[] = {
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x06),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL2, 0x08),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x80),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x34),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x15),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x04),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_CFG, 0x00),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x0a),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_INITVAL, 0x80),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_MODE, 0x01),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x31),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x00),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x85),
- QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x07),
-};
-
-static const struct qmp_phy_init_tbl msm8998_usb3_tx_tbl[] = {
- QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10),
- QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12),
- QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x16),
- QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x00),
-};
-
-static const struct qmp_phy_init_tbl msm8998_usb3_rx_tbl[] = {
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x07),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x43),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1c),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x00),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x80),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FO_GAIN, 0x0a),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x06),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x00),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_VGA_CAL_CNTRL2, 0x03),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x05),
-};
-
-static const struct qmp_phy_init_tbl msm8998_usb3_pcs_tbl[] = {
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V1, 0x9f),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V2, 0xb7),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V3, 0x4e),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V4, 0x65),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_LS, 0x6b),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0d),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V1, 0x15),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V1, 0x0d),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V2, 0x15),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V2, 0x0d),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V3, 0x15),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V3, 0x0d),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V4, 0x15),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V4, 0x0d),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_LS, 0x15),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_LS, 0x0d),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RATE_SLEW_CNTRL, 0x02),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x8a),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13),
-};
-
static const struct qmp_phy_init_tbl sm8150_usb3_uniphy_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x1a),
QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11),
@@ -1023,6 +871,16 @@ static const struct qmp_phy_init_tbl sdx75_usb3_uniphy_pcs_usb_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V6_PCS_USB3_RCVR_DTCT_DLY_U3_H, 0x00),
};
+static const struct qmp_phy_init_tbl qcs8300_usb3_uniphy_tx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0xa5),
+ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_2, 0xf2),
+ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_4, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PI_QEC_CTRL, 0x21),
+ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x10),
+ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x0e),
+};
+
static const struct qmp_phy_init_tbl sm8350_usb3_uniphy_tx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0xa5),
QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_2, 0x82),
@@ -1089,99 +947,6 @@ static const struct qmp_phy_init_tbl sm8350_usb3_uniphy_pcs_usb_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8),
};
-static const struct qmp_phy_init_tbl qcm2290_usb3_serdes_tbl[] = {
- QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14),
- QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08),
- QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30),
- QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06),
- QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x00),
- QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL2, 0x08),
- QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f),
- QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01),
- QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00),
- QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82),
- QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55),
- QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55),
- QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03),
- QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b),
- QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16),
- QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28),
- QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80),
- QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
- QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a),
- QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x15),
- QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x34),
- QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00),
- QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x00),
- QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00),
- QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00),
- QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00),
- QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a),
- QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01),
- QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31),
- QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01),
- QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00),
- QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00),
- QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0xde),
- QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x07),
- QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f),
- QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06),
- QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_INITVAL, 0x80),
- QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CTRL_BY_PSM, 0x01),
-};
-
-static const struct qmp_phy_init_tbl qcm2290_usb3_tx_tbl[] = {
- QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10),
- QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12),
- QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0xc6),
- QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x00),
- QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x00),
-};
-
-static const struct qmp_phy_init_tbl qcm2290_usb3_rx_tbl[] = {
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x80),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x00),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FO_GAIN, 0x0a),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x06),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_VGA_CAL_CNTRL2, 0x0a),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x16),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x00),
- QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x00),
-};
-
-static const struct qmp_phy_init_tbl qcm2290_usb3_pcs_tbl[] = {
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x17),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0f),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x85),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00),
- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x88),
-};
-
static const struct qmp_phy_init_tbl sc8280xp_usb3_uniphy_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0x1a),
QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_HSCLK_SEL, 0x11),
@@ -1234,6 +999,40 @@ static const struct qmp_phy_init_tbl sc8280xp_usb3_uniphy_tx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x0e),
};
+static const struct qmp_phy_init_tbl qcs8300_usb3_uniphy_rx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xec),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0xbd),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0x7f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xa9),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x7b),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xe4),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0x24),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0x64),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x99),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH1, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH2, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN2, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x09),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL1, 0x54),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x0e),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_GM_CAL, 0x19),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_ENABLES, 0x00),
+};
+
static const struct qmp_phy_init_tbl sc8280xp_usb3_uniphy_rx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xdc),
QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0xbd),
@@ -1253,7 +1052,7 @@ static const struct qmp_phy_init_tbl sc8280xp_usb3_uniphy_rx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f),
QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff),
QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f),
- QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL1, 0x54),
QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f),
@@ -1448,15 +1247,10 @@ struct qmp_usb_offsets {
u16 pcs_usb;
u16 tx;
u16 rx;
- /* for PHYs with >= 2 lanes */
- u16 tx2;
- u16 rx2;
};
/* struct qmp_phy_cfg - per-PHY initialization config */
struct qmp_phy_cfg {
- int lanes;
-
const struct qmp_usb_offsets *offsets;
/* Init sequence for PHY blocks - serdes, tx, rx, pcs */
@@ -1496,8 +1290,6 @@ struct qmp_usb {
void __iomem *pcs_usb;
void __iomem *tx;
void __iomem *rx;
- void __iomem *tx2;
- void __iomem *rx2;
struct clk *pipe_clk;
struct clk_bulk_data *clks;
@@ -1579,16 +1371,6 @@ static const struct qmp_usb_offsets qmp_usb_offsets_v3_msm8996 = {
.rx = 0x400,
};
-static const struct qmp_usb_offsets qmp_usb_offsets_v3_qcm2290 = {
- .serdes = 0x0,
- .pcs = 0xc00,
- .pcs_misc = 0xa00,
- .tx = 0x200,
- .rx = 0x400,
- .tx2 = 0x600,
- .rx2 = 0x800,
-};
-
static const struct qmp_usb_offsets qmp_usb_offsets_v4 = {
.serdes = 0,
.pcs = 0x0800,
@@ -1622,8 +1404,6 @@ static const struct qmp_usb_offsets qmp_usb_offsets_v7 = {
};
static const struct qmp_phy_cfg ipq6018_usb3phy_cfg = {
- .lanes = 1,
-
.offsets = &qmp_usb_offsets_v3,
.serdes_tbl = ipq9574_usb3_serdes_tbl,
@@ -1640,8 +1420,6 @@ static const struct qmp_phy_cfg ipq6018_usb3phy_cfg = {
};
static const struct qmp_phy_cfg ipq8074_usb3phy_cfg = {
- .lanes = 1,
-
.offsets = &qmp_usb_offsets_v3,
.serdes_tbl = ipq8074_usb3_serdes_tbl,
@@ -1658,8 +1436,6 @@ static const struct qmp_phy_cfg ipq8074_usb3phy_cfg = {
};
static const struct qmp_phy_cfg ipq9574_usb3phy_cfg = {
- .lanes = 1,
-
.offsets = &qmp_usb_offsets_ipq9574,
.serdes_tbl = ipq9574_usb3_serdes_tbl,
@@ -1676,8 +1452,6 @@ static const struct qmp_phy_cfg ipq9574_usb3phy_cfg = {
};
static const struct qmp_phy_cfg msm8996_usb3phy_cfg = {
- .lanes = 1,
-
.offsets = &qmp_usb_offsets_v3_msm8996,
.serdes_tbl = msm8996_usb3_serdes_tbl,
@@ -1693,9 +1467,28 @@ static const struct qmp_phy_cfg msm8996_usb3phy_cfg = {
.regs = qmp_v2_usb3phy_regs_layout,
};
-static const struct qmp_phy_cfg sa8775p_usb3_uniphy_cfg = {
- .lanes = 1,
+static const struct qmp_phy_cfg qdu1000_usb3_uniphy_cfg = {
+ .offsets = &qmp_usb_offsets_v5,
+
+ .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl,
+ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl),
+ .tx_tbl = sm8350_usb3_uniphy_tx_tbl,
+ .tx_tbl_num = ARRAY_SIZE(sm8350_usb3_uniphy_tx_tbl),
+ .rx_tbl = sm8350_usb3_uniphy_rx_tbl,
+ .rx_tbl_num = ARRAY_SIZE(sm8350_usb3_uniphy_rx_tbl),
+ .pcs_tbl = qdu1000_usb3_uniphy_pcs_tbl,
+ .pcs_tbl_num = ARRAY_SIZE(qdu1000_usb3_uniphy_pcs_tbl),
+ .pcs_usb_tbl = qdu1000_usb3_uniphy_pcs_usb_tbl,
+ .pcs_usb_tbl_num = ARRAY_SIZE(qdu1000_usb3_uniphy_pcs_usb_tbl),
+ .vreg_list = qmp_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
+ .regs = qmp_v4_usb3phy_regs_layout,
+ .pcs_usb_offset = 0x1000,
+
+ .has_pwrdn_delay = true,
+};
+static const struct qmp_phy_cfg sa8775p_usb3_uniphy_cfg = {
.offsets = &qmp_usb_offsets_v5,
.serdes_tbl = sc8280xp_usb3_uniphy_serdes_tbl,
@@ -1713,9 +1506,25 @@ static const struct qmp_phy_cfg sa8775p_usb3_uniphy_cfg = {
.regs = qmp_v5_usb3phy_regs_layout,
};
-static const struct qmp_phy_cfg sc8280xp_usb3_uniphy_cfg = {
- .lanes = 1,
+static const struct qmp_phy_cfg qcs8300_usb3_uniphy_cfg = {
+ .offsets = &qmp_usb_offsets_v5,
+ .serdes_tbl = sc8280xp_usb3_uniphy_serdes_tbl,
+ .serdes_tbl_num = ARRAY_SIZE(sc8280xp_usb3_uniphy_serdes_tbl),
+ .tx_tbl = qcs8300_usb3_uniphy_tx_tbl,
+ .tx_tbl_num = ARRAY_SIZE(qcs8300_usb3_uniphy_tx_tbl),
+ .rx_tbl = qcs8300_usb3_uniphy_rx_tbl,
+ .rx_tbl_num = ARRAY_SIZE(qcs8300_usb3_uniphy_rx_tbl),
+ .pcs_tbl = sa8775p_usb3_uniphy_pcs_tbl,
+ .pcs_tbl_num = ARRAY_SIZE(sa8775p_usb3_uniphy_pcs_tbl),
+ .pcs_usb_tbl = sa8775p_usb3_uniphy_pcs_usb_tbl,
+ .pcs_usb_tbl_num = ARRAY_SIZE(sa8775p_usb3_uniphy_pcs_usb_tbl),
+ .vreg_list = qmp_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
+ .regs = qmp_v5_usb3phy_regs_layout,
+};
+
+static const struct qmp_phy_cfg sc8280xp_usb3_uniphy_cfg = {
.offsets = &qmp_usb_offsets_v5,
.serdes_tbl = sc8280xp_usb3_uniphy_serdes_tbl,
@@ -1734,8 +1543,6 @@ static const struct qmp_phy_cfg sc8280xp_usb3_uniphy_cfg = {
};
static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = {
- .lanes = 1,
-
.offsets = &qmp_usb_offsets_v3,
.serdes_tbl = qmp_v3_usb3_uniphy_serdes_tbl,
@@ -1753,27 +1560,7 @@ static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = {
.has_pwrdn_delay = true,
};
-static const struct qmp_phy_cfg msm8998_usb3phy_cfg = {
- .lanes = 2,
-
- .offsets = &qmp_usb_offsets_v3_qcm2290,
-
- .serdes_tbl = msm8998_usb3_serdes_tbl,
- .serdes_tbl_num = ARRAY_SIZE(msm8998_usb3_serdes_tbl),
- .tx_tbl = msm8998_usb3_tx_tbl,
- .tx_tbl_num = ARRAY_SIZE(msm8998_usb3_tx_tbl),
- .rx_tbl = msm8998_usb3_rx_tbl,
- .rx_tbl_num = ARRAY_SIZE(msm8998_usb3_rx_tbl),
- .pcs_tbl = msm8998_usb3_pcs_tbl,
- .pcs_tbl_num = ARRAY_SIZE(msm8998_usb3_pcs_tbl),
- .vreg_list = qmp_phy_vreg_l,
- .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
- .regs = qmp_v3_usb3phy_regs_layout,
-};
-
static const struct qmp_phy_cfg sm8150_usb3_uniphy_cfg = {
- .lanes = 1,
-
.offsets = &qmp_usb_offsets_v4,
.serdes_tbl = sm8150_usb3_uniphy_serdes_tbl,
@@ -1795,8 +1582,6 @@ static const struct qmp_phy_cfg sm8150_usb3_uniphy_cfg = {
};
static const struct qmp_phy_cfg sm8250_usb3_uniphy_cfg = {
- .lanes = 1,
-
.offsets = &qmp_usb_offsets_v4,
.serdes_tbl = sm8150_usb3_uniphy_serdes_tbl,
@@ -1818,8 +1603,6 @@ static const struct qmp_phy_cfg sm8250_usb3_uniphy_cfg = {
};
static const struct qmp_phy_cfg sdx55_usb3_uniphy_cfg = {
- .lanes = 1,
-
.offsets = &qmp_usb_offsets_v4,
.serdes_tbl = sm8150_usb3_uniphy_serdes_tbl,
@@ -1841,8 +1624,6 @@ static const struct qmp_phy_cfg sdx55_usb3_uniphy_cfg = {
};
static const struct qmp_phy_cfg sdx65_usb3_uniphy_cfg = {
- .lanes = 1,
-
.offsets = &qmp_usb_offsets_v5,
.serdes_tbl = sm8150_usb3_uniphy_serdes_tbl,
@@ -1864,7 +1645,6 @@ static const struct qmp_phy_cfg sdx65_usb3_uniphy_cfg = {
};
static const struct qmp_phy_cfg sdx75_usb3_uniphy_cfg = {
- .lanes = 1,
.offsets = &qmp_usb_offsets_v6,
.serdes_tbl = sdx75_usb3_uniphy_serdes_tbl,
@@ -1886,8 +1666,6 @@ static const struct qmp_phy_cfg sdx75_usb3_uniphy_cfg = {
};
static const struct qmp_phy_cfg sm8350_usb3_uniphy_cfg = {
- .lanes = 1,
-
.offsets = &qmp_usb_offsets_v5,
.serdes_tbl = sm8150_usb3_uniphy_serdes_tbl,
@@ -1908,27 +1686,7 @@ static const struct qmp_phy_cfg sm8350_usb3_uniphy_cfg = {
.has_pwrdn_delay = true,
};
-static const struct qmp_phy_cfg qcm2290_usb3phy_cfg = {
- .lanes = 2,
-
- .offsets = &qmp_usb_offsets_v3_qcm2290,
-
- .serdes_tbl = qcm2290_usb3_serdes_tbl,
- .serdes_tbl_num = ARRAY_SIZE(qcm2290_usb3_serdes_tbl),
- .tx_tbl = qcm2290_usb3_tx_tbl,
- .tx_tbl_num = ARRAY_SIZE(qcm2290_usb3_tx_tbl),
- .rx_tbl = qcm2290_usb3_rx_tbl,
- .rx_tbl_num = ARRAY_SIZE(qcm2290_usb3_rx_tbl),
- .pcs_tbl = qcm2290_usb3_pcs_tbl,
- .pcs_tbl_num = ARRAY_SIZE(qcm2290_usb3_pcs_tbl),
- .vreg_list = qmp_phy_vreg_l,
- .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
- .regs = qmp_v3_usb3phy_regs_layout_qcm2290,
-};
-
static const struct qmp_phy_cfg x1e80100_usb3_uniphy_cfg = {
- .lanes = 1,
-
.offsets = &qmp_usb_offsets_v7,
.serdes_tbl = x1e80100_usb3_uniphy_serdes_tbl,
@@ -1946,32 +1704,6 @@ static const struct qmp_phy_cfg x1e80100_usb3_uniphy_cfg = {
.regs = qmp_v7_usb3phy_regs_layout,
};
-static void qmp_usb_configure_lane(void __iomem *base,
- const struct qmp_phy_init_tbl tbl[],
- int num,
- u8 lane_mask)
-{
- int i;
- const struct qmp_phy_init_tbl *t = tbl;
-
- if (!t)
- return;
-
- for (i = 0; i < num; i++, t++) {
- if (!(t->lane_mask & lane_mask))
- continue;
-
- writel(t->val, base + t->offset);
- }
-}
-
-static void qmp_usb_configure(void __iomem *base,
- const struct qmp_phy_init_tbl tbl[],
- int num)
-{
- qmp_usb_configure_lane(base, tbl, num, 0xff);
-}
-
static int qmp_usb_serdes_init(struct qmp_usb *qmp)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
@@ -1979,7 +1711,7 @@ static int qmp_usb_serdes_init(struct qmp_usb *qmp)
const struct qmp_phy_init_tbl *serdes_tbl = cfg->serdes_tbl;
int serdes_tbl_num = cfg->serdes_tbl_num;
- qmp_usb_configure(serdes, serdes_tbl, serdes_tbl_num);
+ qmp_configure(qmp->dev, serdes, serdes_tbl, serdes_tbl_num);
return 0;
}
@@ -2060,18 +1792,13 @@ static int qmp_usb_power_on(struct phy *phy)
}
/* Tx, Rx, and PCS configurations */
- qmp_usb_configure_lane(tx, cfg->tx_tbl, cfg->tx_tbl_num, 1);
- qmp_usb_configure_lane(rx, cfg->rx_tbl, cfg->rx_tbl_num, 1);
-
- if (cfg->lanes >= 2) {
- qmp_usb_configure_lane(qmp->tx2, cfg->tx_tbl, cfg->tx_tbl_num, 2);
- qmp_usb_configure_lane(qmp->rx2, cfg->rx_tbl, cfg->rx_tbl_num, 2);
- }
+ qmp_configure_lane(qmp->dev, tx, cfg->tx_tbl, cfg->tx_tbl_num, 1);
+ qmp_configure_lane(qmp->dev, rx, cfg->rx_tbl, cfg->rx_tbl_num, 1);
- qmp_usb_configure(pcs, cfg->pcs_tbl, cfg->pcs_tbl_num);
+ qmp_configure(qmp->dev, pcs, cfg->pcs_tbl, cfg->pcs_tbl_num);
if (pcs_usb)
- qmp_usb_configure(pcs_usb, cfg->pcs_usb_tbl, cfg->pcs_usb_tbl_num);
+ qmp_configure(qmp->dev, pcs_usb, cfg->pcs_usb_tbl, cfg->pcs_usb_tbl_num);
if (cfg->has_pwrdn_delay)
usleep_range(10, 20);
@@ -2414,7 +2141,6 @@ static int qmp_usb_parse_dt_legacy(struct qmp_usb *qmp, struct device_node *np)
/*
* Get memory resources for the PHY:
* Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2.
- * For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5
* For single lane PHYs: pcs_misc (optional) -> 3.
*/
qmp->tx = devm_of_iomap(dev, np, 0, NULL);
@@ -2432,19 +2158,7 @@ static int qmp_usb_parse_dt_legacy(struct qmp_usb *qmp, struct device_node *np)
if (cfg->pcs_usb_offset)
qmp->pcs_usb = qmp->pcs + cfg->pcs_usb_offset;
- if (cfg->lanes >= 2) {
- qmp->tx2 = devm_of_iomap(dev, np, 3, NULL);
- if (IS_ERR(qmp->tx2))
- return PTR_ERR(qmp->tx2);
-
- qmp->rx2 = devm_of_iomap(dev, np, 4, NULL);
- if (IS_ERR(qmp->rx2))
- return PTR_ERR(qmp->rx2);
-
- qmp->pcs_misc = devm_of_iomap(dev, np, 5, NULL);
- } else {
- qmp->pcs_misc = devm_of_iomap(dev, np, 3, NULL);
- }
+ qmp->pcs_misc = devm_of_iomap(dev, np, 3, NULL);
if (IS_ERR(qmp->pcs_misc)) {
dev_vdbg(dev, "PHY pcs_misc-reg not used\n");
@@ -2496,11 +2210,6 @@ static int qmp_usb_parse_dt(struct qmp_usb *qmp)
qmp->tx = base + offs->tx;
qmp->rx = base + offs->rx;
- if (cfg->lanes >= 2) {
- qmp->tx2 = base + offs->tx2;
- qmp->rx2 = base + offs->rx2;
- }
-
ret = qmp_usb_clk_init(qmp);
if (ret)
return ret;
@@ -2532,6 +2241,7 @@ static int qmp_usb_probe(struct platform_device *pdev)
return -ENOMEM;
qmp->dev = dev;
+ dev_set_drvdata(dev, qmp);
qmp->cfg = of_device_get_match_data(dev);
if (!qmp->cfg)
@@ -2588,6 +2298,9 @@ err_node_put:
static const struct of_device_id qmp_usb_of_match_table[] = {
{
+ .compatible = "qcom,ipq5424-qmp-usb3-phy",
+ .data = &ipq9574_usb3phy_cfg,
+ }, {
.compatible = "qcom,ipq6018-qmp-usb3-phy",
.data = &ipq6018_usb3phy_cfg,
}, {
@@ -2600,15 +2313,18 @@ static const struct of_device_id qmp_usb_of_match_table[] = {
.compatible = "qcom,msm8996-qmp-usb3-phy",
.data = &msm8996_usb3phy_cfg,
}, {
- .compatible = "qcom,msm8998-qmp-usb3-phy",
- .data = &msm8998_usb3phy_cfg,
+ .compatible = "qcom,qcs8300-qmp-usb3-uni-phy",
+ .data = &qcs8300_usb3_uniphy_cfg,
}, {
- .compatible = "qcom,qcm2290-qmp-usb3-phy",
- .data = &qcm2290_usb3phy_cfg,
+ .compatible = "qcom,qdu1000-qmp-usb3-uni-phy",
+ .data = &qdu1000_usb3_uniphy_cfg,
}, {
.compatible = "qcom,sa8775p-qmp-usb3-uni-phy",
.data = &sa8775p_usb3_uniphy_cfg,
}, {
+ .compatible = "qcom,sc8180x-qmp-usb3-uni-phy",
+ .data = &sm8150_usb3_uniphy_cfg,
+ }, {
.compatible = "qcom,sc8280xp-qmp-usb3-uni-phy",
.data = &sc8280xp_usb3_uniphy_cfg,
}, {
@@ -2624,9 +2340,6 @@ static const struct of_device_id qmp_usb_of_match_table[] = {
.compatible = "qcom,sdx75-qmp-usb3-uni-phy",
.data = &sdx75_usb3_uniphy_cfg,
}, {
- .compatible = "qcom,sm6115-qmp-usb3-phy",
- .data = &qcm2290_usb3phy_cfg,
- }, {
.compatible = "qcom,sm8150-qmp-usb3-uni-phy",
.data = &sm8150_usb3_uniphy_cfg,
}, {
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c b/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c
new file mode 100644
index 000000000000..cf12a6f12134
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c
@@ -0,0 +1,1151 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+#include <linux/usb/typec.h>
+#include <linux/usb/typec_mux.h>
+
+#include "phy-qcom-qmp-common.h"
+
+#include "phy-qcom-qmp.h"
+#include "phy-qcom-qmp-pcs-misc-v3.h"
+
+#define PHY_INIT_COMPLETE_TIMEOUT 10000
+
+/* set of registers with offsets different per-PHY */
+enum qphy_reg_layout {
+ /* PCS registers */
+ QPHY_SW_RESET,
+ QPHY_START_CTRL,
+ QPHY_PCS_STATUS,
+ QPHY_PCS_AUTONOMOUS_MODE_CTRL,
+ QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR,
+ QPHY_PCS_POWER_DOWN_CONTROL,
+ /* Keep last to ensure regs_layout arrays are properly initialized */
+ QPHY_LAYOUT_SIZE
+};
+
+static const unsigned int qmp_v3_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
+ [QPHY_SW_RESET] = QPHY_V3_PCS_SW_RESET,
+ [QPHY_START_CTRL] = QPHY_V3_PCS_START_CONTROL,
+ [QPHY_PCS_STATUS] = QPHY_V3_PCS_PCS_STATUS,
+ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = QPHY_V3_PCS_AUTONOMOUS_MODE_CTRL,
+ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = QPHY_V3_PCS_LFPS_RXTERM_IRQ_CLEAR,
+ [QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V3_PCS_POWER_DOWN_CONTROL,
+};
+
+static const unsigned int qmp_v3_usb3phy_regs_layout_qcm2290[QPHY_LAYOUT_SIZE] = {
+ [QPHY_SW_RESET] = QPHY_V3_PCS_SW_RESET,
+ [QPHY_START_CTRL] = QPHY_V3_PCS_START_CONTROL,
+ [QPHY_PCS_STATUS] = QPHY_V3_PCS_PCS_STATUS,
+ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = QPHY_V3_PCS_AUTONOMOUS_MODE_CTRL,
+ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = QPHY_V3_PCS_LFPS_RXTERM_IRQ_CLEAR,
+ [QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V3_PCS_POWER_DOWN_CONTROL,
+};
+
+static const struct qmp_phy_init_tbl msm8998_usb3_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL2, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x34),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x15),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_CFG, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_INITVAL, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_MODE, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x31),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x85),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x07),
+};
+
+static const struct qmp_phy_init_tbl msm8998_usb3_tx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10),
+ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12),
+ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x00),
+};
+
+static const struct qmp_phy_init_tbl msm8998_usb3_rx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x43),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1c),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FO_GAIN, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_VGA_CAL_CNTRL2, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x05),
+};
+
+static const struct qmp_phy_init_tbl msm8998_usb3_pcs_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V1, 0x9f),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V2, 0xb7),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V3, 0x4e),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V4, 0x65),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_LS, 0x6b),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0d),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V1, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V1, 0x0d),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V2, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V2, 0x0d),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V3, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V3, 0x0d),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V4, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V4, 0x0d),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_LS, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_LS, 0x0d),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RATE_SLEW_CNTRL, 0x02),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x8a),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13),
+};
+
+static const struct qmp_phy_init_tbl qcm2290_usb3_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL2, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55),
+ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b),
+ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28),
+ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x15),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x34),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0xde),
+ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_INITVAL, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CTRL_BY_PSM, 0x01),
+};
+
+static const struct qmp_phy_init_tbl qcm2290_usb3_tx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10),
+ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12),
+ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0xc6),
+ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x00),
+};
+
+static const struct qmp_phy_init_tbl qcm2290_usb3_rx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FO_GAIN, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_VGA_CAL_CNTRL2, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x00),
+};
+
+/* the only difference is QSERDES_V3_RX_UCDR_PI_CONTROLS */
+static const struct qmp_phy_init_tbl sdm660_usb3_rx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FO_GAIN, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_VGA_CAL_CNTRL2, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x00),
+};
+
+static const struct qmp_phy_init_tbl qcm2290_usb3_pcs_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x17),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0f),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x85),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x88),
+};
+
+struct qmp_usbc_offsets {
+ u16 serdes;
+ u16 pcs;
+ u16 pcs_misc;
+ u16 tx;
+ u16 rx;
+ /* for PHYs with >= 2 lanes */
+ u16 tx2;
+ u16 rx2;
+};
+
+/* struct qmp_phy_cfg - per-PHY initialization config */
+struct qmp_phy_cfg {
+ const struct qmp_usbc_offsets *offsets;
+
+ /* Init sequence for PHY blocks - serdes, tx, rx, pcs */
+ const struct qmp_phy_init_tbl *serdes_tbl;
+ int serdes_tbl_num;
+ const struct qmp_phy_init_tbl *tx_tbl;
+ int tx_tbl_num;
+ const struct qmp_phy_init_tbl *rx_tbl;
+ int rx_tbl_num;
+ const struct qmp_phy_init_tbl *pcs_tbl;
+ int pcs_tbl_num;
+
+ /* regulators to be requested */
+ const char * const *vreg_list;
+ int num_vregs;
+
+ /* array of registers with different offsets */
+ const unsigned int *regs;
+};
+
+struct qmp_usbc {
+ struct device *dev;
+
+ const struct qmp_phy_cfg *cfg;
+
+ void __iomem *serdes;
+ void __iomem *pcs;
+ void __iomem *pcs_misc;
+ void __iomem *tx;
+ void __iomem *rx;
+ void __iomem *tx2;
+ void __iomem *rx2;
+
+ struct regmap *tcsr_map;
+ u32 vls_clamp_reg;
+
+ struct clk *pipe_clk;
+ struct clk_bulk_data *clks;
+ int num_clks;
+ int num_resets;
+ struct reset_control_bulk_data *resets;
+ struct regulator_bulk_data *vregs;
+
+ struct mutex phy_mutex;
+
+ enum phy_mode mode;
+ unsigned int usb_init_count;
+
+ struct phy *phy;
+
+ struct clk_fixed_rate pipe_clk_fixed;
+
+ struct typec_switch_dev *sw;
+ enum typec_orientation orientation;
+};
+
+static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val)
+{
+ u32 reg;
+
+ reg = readl(base + offset);
+ reg |= val;
+ writel(reg, base + offset);
+
+ /* ensure that above write is through */
+ readl(base + offset);
+}
+
+static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
+{
+ u32 reg;
+
+ reg = readl(base + offset);
+ reg &= ~val;
+ writel(reg, base + offset);
+
+ /* ensure that above write is through */
+ readl(base + offset);
+}
+
+/* list of clocks required by phy */
+static const char * const qmp_usbc_phy_clk_l[] = {
+ "aux", "cfg_ahb", "ref", "com_aux",
+};
+
+/* list of resets */
+static const char * const usb3phy_legacy_reset_l[] = {
+ "phy", "common",
+};
+
+static const char * const usb3phy_reset_l[] = {
+ "phy_phy", "phy",
+};
+
+/* list of regulators */
+static const char * const qmp_phy_vreg_l[] = {
+ "vdda-phy", "vdda-pll",
+};
+
+static const struct qmp_usbc_offsets qmp_usbc_offsets_v3_qcm2290 = {
+ .serdes = 0x0,
+ .pcs = 0xc00,
+ .pcs_misc = 0xa00,
+ .tx = 0x200,
+ .rx = 0x400,
+ .tx2 = 0x600,
+ .rx2 = 0x800,
+};
+
+static const struct qmp_phy_cfg msm8998_usb3phy_cfg = {
+ .offsets = &qmp_usbc_offsets_v3_qcm2290,
+
+ .serdes_tbl = msm8998_usb3_serdes_tbl,
+ .serdes_tbl_num = ARRAY_SIZE(msm8998_usb3_serdes_tbl),
+ .tx_tbl = msm8998_usb3_tx_tbl,
+ .tx_tbl_num = ARRAY_SIZE(msm8998_usb3_tx_tbl),
+ .rx_tbl = msm8998_usb3_rx_tbl,
+ .rx_tbl_num = ARRAY_SIZE(msm8998_usb3_rx_tbl),
+ .pcs_tbl = msm8998_usb3_pcs_tbl,
+ .pcs_tbl_num = ARRAY_SIZE(msm8998_usb3_pcs_tbl),
+ .vreg_list = qmp_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
+ .regs = qmp_v3_usb3phy_regs_layout,
+};
+
+static const struct qmp_phy_cfg qcm2290_usb3phy_cfg = {
+ .offsets = &qmp_usbc_offsets_v3_qcm2290,
+
+ .serdes_tbl = qcm2290_usb3_serdes_tbl,
+ .serdes_tbl_num = ARRAY_SIZE(qcm2290_usb3_serdes_tbl),
+ .tx_tbl = qcm2290_usb3_tx_tbl,
+ .tx_tbl_num = ARRAY_SIZE(qcm2290_usb3_tx_tbl),
+ .rx_tbl = qcm2290_usb3_rx_tbl,
+ .rx_tbl_num = ARRAY_SIZE(qcm2290_usb3_rx_tbl),
+ .pcs_tbl = qcm2290_usb3_pcs_tbl,
+ .pcs_tbl_num = ARRAY_SIZE(qcm2290_usb3_pcs_tbl),
+ .vreg_list = qmp_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
+ .regs = qmp_v3_usb3phy_regs_layout_qcm2290,
+};
+
+static const struct qmp_phy_cfg sdm660_usb3phy_cfg = {
+ .offsets = &qmp_usbc_offsets_v3_qcm2290,
+
+ .serdes_tbl = qcm2290_usb3_serdes_tbl,
+ .serdes_tbl_num = ARRAY_SIZE(qcm2290_usb3_serdes_tbl),
+ .tx_tbl = qcm2290_usb3_tx_tbl,
+ .tx_tbl_num = ARRAY_SIZE(qcm2290_usb3_tx_tbl),
+ .rx_tbl = sdm660_usb3_rx_tbl,
+ .rx_tbl_num = ARRAY_SIZE(sdm660_usb3_rx_tbl),
+ .pcs_tbl = qcm2290_usb3_pcs_tbl,
+ .pcs_tbl_num = ARRAY_SIZE(qcm2290_usb3_pcs_tbl),
+ .vreg_list = qmp_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
+ .regs = qmp_v3_usb3phy_regs_layout_qcm2290,
+};
+
+static int qmp_usbc_init(struct phy *phy)
+{
+ struct qmp_usbc *qmp = phy_get_drvdata(phy);
+ const struct qmp_phy_cfg *cfg = qmp->cfg;
+ void __iomem *pcs = qmp->pcs;
+ u32 val = 0;
+ int ret;
+
+ ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs);
+ if (ret) {
+ dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret);
+ return ret;
+ }
+
+ ret = reset_control_bulk_assert(qmp->num_resets, qmp->resets);
+ if (ret) {
+ dev_err(qmp->dev, "reset assert failed\n");
+ goto err_disable_regulators;
+ }
+
+ ret = reset_control_bulk_deassert(qmp->num_resets, qmp->resets);
+ if (ret) {
+ dev_err(qmp->dev, "reset deassert failed\n");
+ goto err_disable_regulators;
+ }
+
+ ret = clk_bulk_prepare_enable(qmp->num_clks, qmp->clks);
+ if (ret)
+ goto err_assert_reset;
+
+ qphy_setbits(pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], SW_PWRDN);
+
+#define SW_PORTSELECT_VAL BIT(0)
+#define SW_PORTSELECT_MUX BIT(1)
+ /* Use software based port select and switch on typec orientation */
+ val = SW_PORTSELECT_MUX;
+ if (qmp->orientation == TYPEC_ORIENTATION_REVERSE)
+ val |= SW_PORTSELECT_VAL;
+ writel(val, qmp->pcs_misc);
+
+ return 0;
+
+err_assert_reset:
+ reset_control_bulk_assert(qmp->num_resets, qmp->resets);
+err_disable_regulators:
+ regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
+
+ return ret;
+}
+
+static int qmp_usbc_exit(struct phy *phy)
+{
+ struct qmp_usbc *qmp = phy_get_drvdata(phy);
+ const struct qmp_phy_cfg *cfg = qmp->cfg;
+
+ reset_control_bulk_assert(qmp->num_resets, qmp->resets);
+
+ clk_bulk_disable_unprepare(qmp->num_clks, qmp->clks);
+
+ regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
+
+ return 0;
+}
+
+static int qmp_usbc_power_on(struct phy *phy)
+{
+ struct qmp_usbc *qmp = phy_get_drvdata(phy);
+ const struct qmp_phy_cfg *cfg = qmp->cfg;
+ void __iomem *status;
+ unsigned int val;
+ int ret;
+
+ qmp_configure(qmp->dev, qmp->serdes, cfg->serdes_tbl,
+ cfg->serdes_tbl_num);
+
+ ret = clk_prepare_enable(qmp->pipe_clk);
+ if (ret) {
+ dev_err(qmp->dev, "pipe_clk enable failed err=%d\n", ret);
+ return ret;
+ }
+
+ /* Tx, Rx, and PCS configurations */
+ qmp_configure_lane(qmp->dev, qmp->tx, cfg->tx_tbl, cfg->tx_tbl_num, 1);
+ qmp_configure_lane(qmp->dev, qmp->rx, cfg->rx_tbl, cfg->rx_tbl_num, 1);
+
+ qmp_configure_lane(qmp->dev, qmp->tx2, cfg->tx_tbl, cfg->tx_tbl_num, 2);
+ qmp_configure_lane(qmp->dev, qmp->rx2, cfg->rx_tbl, cfg->rx_tbl_num, 2);
+
+ qmp_configure(qmp->dev, qmp->pcs, cfg->pcs_tbl, cfg->pcs_tbl_num);
+
+ /* Pull PHY out of reset state */
+ qphy_clrbits(qmp->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
+
+ /* start SerDes and Phy-Coding-Sublayer */
+ qphy_setbits(qmp->pcs, cfg->regs[QPHY_START_CTRL], SERDES_START | PCS_START);
+
+ status = qmp->pcs + cfg->regs[QPHY_PCS_STATUS];
+ ret = readl_poll_timeout(status, val, !(val & PHYSTATUS), 200,
+ PHY_INIT_COMPLETE_TIMEOUT);
+ if (ret) {
+ dev_err(qmp->dev, "phy initialization timed-out\n");
+ goto err_disable_pipe_clk;
+ }
+
+ return 0;
+
+err_disable_pipe_clk:
+ clk_disable_unprepare(qmp->pipe_clk);
+
+ return ret;
+}
+
+static int qmp_usbc_power_off(struct phy *phy)
+{
+ struct qmp_usbc *qmp = phy_get_drvdata(phy);
+ const struct qmp_phy_cfg *cfg = qmp->cfg;
+
+ clk_disable_unprepare(qmp->pipe_clk);
+
+ /* PHY reset */
+ qphy_setbits(qmp->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
+
+ /* stop SerDes and Phy-Coding-Sublayer */
+ qphy_clrbits(qmp->pcs, cfg->regs[QPHY_START_CTRL],
+ SERDES_START | PCS_START);
+
+ /* Put PHY into POWER DOWN state: active low */
+ qphy_clrbits(qmp->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL],
+ SW_PWRDN);
+
+ return 0;
+}
+
+static int qmp_usbc_enable(struct phy *phy)
+{
+ struct qmp_usbc *qmp = phy_get_drvdata(phy);
+ int ret;
+
+ mutex_lock(&qmp->phy_mutex);
+
+ ret = qmp_usbc_init(phy);
+ if (ret)
+ goto out_unlock;
+
+ ret = qmp_usbc_power_on(phy);
+ if (ret) {
+ qmp_usbc_exit(phy);
+ goto out_unlock;
+ }
+
+ qmp->usb_init_count++;
+out_unlock:
+ mutex_unlock(&qmp->phy_mutex);
+
+ return ret;
+}
+
+static int qmp_usbc_disable(struct phy *phy)
+{
+ struct qmp_usbc *qmp = phy_get_drvdata(phy);
+ int ret;
+
+ qmp->usb_init_count--;
+ ret = qmp_usbc_power_off(phy);
+ if (ret)
+ return ret;
+ return qmp_usbc_exit(phy);
+}
+
+static int qmp_usbc_set_mode(struct phy *phy, enum phy_mode mode, int submode)
+{
+ struct qmp_usbc *qmp = phy_get_drvdata(phy);
+
+ qmp->mode = mode;
+
+ return 0;
+}
+
+static const struct phy_ops qmp_usbc_phy_ops = {
+ .init = qmp_usbc_enable,
+ .exit = qmp_usbc_disable,
+ .set_mode = qmp_usbc_set_mode,
+ .owner = THIS_MODULE,
+};
+
+static void qmp_usbc_enable_autonomous_mode(struct qmp_usbc *qmp)
+{
+ const struct qmp_phy_cfg *cfg = qmp->cfg;
+ void __iomem *pcs = qmp->pcs;
+ u32 intr_mask;
+
+ if (qmp->mode == PHY_MODE_USB_HOST_SS ||
+ qmp->mode == PHY_MODE_USB_DEVICE_SS)
+ intr_mask = ARCVR_DTCT_EN | ALFPS_DTCT_EN;
+ else
+ intr_mask = ARCVR_DTCT_EN | ARCVR_DTCT_EVENT_SEL;
+
+ /* Clear any pending interrupts status */
+ qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR);
+ /* Writing 1 followed by 0 clears the interrupt */
+ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR);
+
+ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL],
+ ARCVR_DTCT_EN | ALFPS_DTCT_EN | ARCVR_DTCT_EVENT_SEL);
+
+ /* Enable required PHY autonomous mode interrupts */
+ qphy_setbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], intr_mask);
+
+ /* Enable i/o clamp_n for autonomous mode */
+ if (qmp->tcsr_map && qmp->vls_clamp_reg)
+ regmap_write(qmp->tcsr_map, qmp->vls_clamp_reg, 1);
+}
+
+static void qmp_usbc_disable_autonomous_mode(struct qmp_usbc *qmp)
+{
+ const struct qmp_phy_cfg *cfg = qmp->cfg;
+ void __iomem *pcs = qmp->pcs;
+
+ /* Disable i/o clamp_n on resume for normal mode */
+ if (qmp->tcsr_map && qmp->vls_clamp_reg)
+ regmap_write(qmp->tcsr_map, qmp->vls_clamp_reg, 0);
+
+ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL],
+ ARCVR_DTCT_EN | ARCVR_DTCT_EVENT_SEL | ALFPS_DTCT_EN);
+
+ qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR);
+ /* Writing 1 followed by 0 clears the interrupt */
+ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR);
+}
+
+static int __maybe_unused qmp_usbc_runtime_suspend(struct device *dev)
+{
+ struct qmp_usbc *qmp = dev_get_drvdata(dev);
+
+ dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qmp->mode);
+
+ if (!qmp->phy->init_count) {
+ dev_vdbg(dev, "PHY not initialized, bailing out\n");
+ return 0;
+ }
+
+ qmp_usbc_enable_autonomous_mode(qmp);
+
+ clk_disable_unprepare(qmp->pipe_clk);
+ clk_bulk_disable_unprepare(qmp->num_clks, qmp->clks);
+
+ return 0;
+}
+
+static int __maybe_unused qmp_usbc_runtime_resume(struct device *dev)
+{
+ struct qmp_usbc *qmp = dev_get_drvdata(dev);
+ int ret = 0;
+
+ dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qmp->mode);
+
+ if (!qmp->phy->init_count) {
+ dev_vdbg(dev, "PHY not initialized, bailing out\n");
+ return 0;
+ }
+
+ ret = clk_bulk_prepare_enable(qmp->num_clks, qmp->clks);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(qmp->pipe_clk);
+ if (ret) {
+ dev_err(dev, "pipe_clk enable failed, err=%d\n", ret);
+ clk_bulk_disable_unprepare(qmp->num_clks, qmp->clks);
+ return ret;
+ }
+
+ qmp_usbc_disable_autonomous_mode(qmp);
+
+ return 0;
+}
+
+static const struct dev_pm_ops qmp_usbc_pm_ops = {
+ SET_RUNTIME_PM_OPS(qmp_usbc_runtime_suspend,
+ qmp_usbc_runtime_resume, NULL)
+};
+
+static int qmp_usbc_vreg_init(struct qmp_usbc *qmp)
+{
+ const struct qmp_phy_cfg *cfg = qmp->cfg;
+ struct device *dev = qmp->dev;
+ int num = cfg->num_vregs;
+ int i;
+
+ qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL);
+ if (!qmp->vregs)
+ return -ENOMEM;
+
+ for (i = 0; i < num; i++)
+ qmp->vregs[i].supply = cfg->vreg_list[i];
+
+ return devm_regulator_bulk_get(dev, num, qmp->vregs);
+}
+
+static int qmp_usbc_reset_init(struct qmp_usbc *qmp,
+ const char *const *reset_list,
+ int num_resets)
+{
+ struct device *dev = qmp->dev;
+ int i;
+ int ret;
+
+ qmp->resets = devm_kcalloc(dev, num_resets,
+ sizeof(*qmp->resets), GFP_KERNEL);
+ if (!qmp->resets)
+ return -ENOMEM;
+
+ for (i = 0; i < num_resets; i++)
+ qmp->resets[i].id = reset_list[i];
+
+ qmp->num_resets = num_resets;
+
+ ret = devm_reset_control_bulk_get_exclusive(dev, num_resets, qmp->resets);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to get resets\n");
+
+ return 0;
+}
+
+static int qmp_usbc_clk_init(struct qmp_usbc *qmp)
+{
+ struct device *dev = qmp->dev;
+ int num = ARRAY_SIZE(qmp_usbc_phy_clk_l);
+ int i;
+
+ qmp->clks = devm_kcalloc(dev, num, sizeof(*qmp->clks), GFP_KERNEL);
+ if (!qmp->clks)
+ return -ENOMEM;
+
+ for (i = 0; i < num; i++)
+ qmp->clks[i].id = qmp_usbc_phy_clk_l[i];
+
+ qmp->num_clks = num;
+
+ return devm_clk_bulk_get_optional(dev, num, qmp->clks);
+}
+
+static void phy_clk_release_provider(void *res)
+{
+ of_clk_del_provider(res);
+}
+
+/*
+ * Register a fixed rate pipe clock.
+ *
+ * The <s>_pipe_clksrc generated by PHY goes to the GCC that gate
+ * controls it. The <s>_pipe_clk coming out of the GCC is requested
+ * by the PHY driver for its operations.
+ * We register the <s>_pipe_clksrc here. The gcc driver takes care
+ * of assigning this <s>_pipe_clksrc as parent to <s>_pipe_clk.
+ * Below picture shows this relationship.
+ *
+ * +---------------+
+ * | PHY block |<<---------------------------------------+
+ * | | |
+ * | +-------+ | +-----+ |
+ * I/P---^-->| PLL |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+
+ * clk | +-------+ | +-----+
+ * +---------------+
+ */
+static int phy_pipe_clk_register(struct qmp_usbc *qmp, struct device_node *np)
+{
+ struct clk_fixed_rate *fixed = &qmp->pipe_clk_fixed;
+ struct clk_init_data init = { };
+ int ret;
+
+ ret = of_property_read_string(np, "clock-output-names", &init.name);
+ if (ret) {
+ dev_err(qmp->dev, "%pOFn: No clock-output-names\n", np);
+ return ret;
+ }
+
+ init.ops = &clk_fixed_rate_ops;
+
+ /* controllers using QMP phys use 125MHz pipe clock interface */
+ fixed->fixed_rate = 125000000;
+ fixed->hw.init = &init;
+
+ ret = devm_clk_hw_register(qmp->dev, &fixed->hw);
+ if (ret)
+ return ret;
+
+ ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &fixed->hw);
+ if (ret)
+ return ret;
+
+ /*
+ * Roll a devm action because the clock provider is the child node, but
+ * the child node is not actually a device.
+ */
+ return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, np);
+}
+
+#if IS_ENABLED(CONFIG_TYPEC)
+static int qmp_usbc_typec_switch_set(struct typec_switch_dev *sw,
+ enum typec_orientation orientation)
+{
+ struct qmp_usbc *qmp = typec_switch_get_drvdata(sw);
+
+ if (orientation == qmp->orientation || orientation == TYPEC_ORIENTATION_NONE)
+ return 0;
+
+ mutex_lock(&qmp->phy_mutex);
+ qmp->orientation = orientation;
+
+ if (qmp->usb_init_count) {
+ qmp_usbc_power_off(qmp->phy);
+ qmp_usbc_exit(qmp->phy);
+
+ qmp_usbc_init(qmp->phy);
+ qmp_usbc_power_on(qmp->phy);
+ }
+
+ mutex_unlock(&qmp->phy_mutex);
+
+ return 0;
+}
+
+static void qmp_usbc_typec_unregister(void *data)
+{
+ struct qmp_usbc *qmp = data;
+
+ typec_switch_unregister(qmp->sw);
+}
+
+static int qmp_usbc_typec_switch_register(struct qmp_usbc *qmp)
+{
+ struct typec_switch_desc sw_desc = {};
+ struct device *dev = qmp->dev;
+
+ sw_desc.drvdata = qmp;
+ sw_desc.fwnode = dev->fwnode;
+ sw_desc.set = qmp_usbc_typec_switch_set;
+ qmp->sw = typec_switch_register(dev, &sw_desc);
+ if (IS_ERR(qmp->sw)) {
+ dev_err(dev, "Unable to register typec switch: %pe\n", qmp->sw);
+ return PTR_ERR(qmp->sw);
+ }
+
+ return devm_add_action_or_reset(dev, qmp_usbc_typec_unregister, qmp);
+}
+#else
+static int qmp_usbc_typec_switch_register(struct qmp_usbc *qmp)
+{
+ return 0;
+}
+#endif
+
+static int qmp_usbc_parse_dt_legacy(struct qmp_usbc *qmp, struct device_node *np)
+{
+ struct platform_device *pdev = to_platform_device(qmp->dev);
+ struct device *dev = qmp->dev;
+ int ret;
+
+ qmp->serdes = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(qmp->serdes))
+ return PTR_ERR(qmp->serdes);
+
+ /*
+ * Get memory resources for the PHY:
+ * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2.
+ * For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5
+ * For single lane PHYs: pcs_misc (optional) -> 3.
+ */
+ qmp->tx = devm_of_iomap(dev, np, 0, NULL);
+ if (IS_ERR(qmp->tx))
+ return PTR_ERR(qmp->tx);
+
+ qmp->rx = devm_of_iomap(dev, np, 1, NULL);
+ if (IS_ERR(qmp->rx))
+ return PTR_ERR(qmp->rx);
+
+ qmp->pcs = devm_of_iomap(dev, np, 2, NULL);
+ if (IS_ERR(qmp->pcs))
+ return PTR_ERR(qmp->pcs);
+
+ qmp->tx2 = devm_of_iomap(dev, np, 3, NULL);
+ if (IS_ERR(qmp->tx2))
+ return PTR_ERR(qmp->tx2);
+
+ qmp->rx2 = devm_of_iomap(dev, np, 4, NULL);
+ if (IS_ERR(qmp->rx2))
+ return PTR_ERR(qmp->rx2);
+
+ qmp->pcs_misc = devm_of_iomap(dev, np, 5, NULL);
+ if (IS_ERR(qmp->pcs_misc)) {
+ dev_vdbg(dev, "PHY pcs_misc-reg not used\n");
+ qmp->pcs_misc = NULL;
+ }
+
+ qmp->pipe_clk = devm_get_clk_from_child(dev, np, NULL);
+ if (IS_ERR(qmp->pipe_clk)) {
+ return dev_err_probe(dev, PTR_ERR(qmp->pipe_clk),
+ "failed to get pipe clock\n");
+ }
+
+ ret = devm_clk_bulk_get_all(qmp->dev, &qmp->clks);
+ if (ret < 0)
+ return ret;
+
+ qmp->num_clks = ret;
+
+ ret = qmp_usbc_reset_init(qmp, usb3phy_legacy_reset_l,
+ ARRAY_SIZE(usb3phy_legacy_reset_l));
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int qmp_usbc_parse_dt(struct qmp_usbc *qmp)
+{
+ struct platform_device *pdev = to_platform_device(qmp->dev);
+ const struct qmp_phy_cfg *cfg = qmp->cfg;
+ const struct qmp_usbc_offsets *offs = cfg->offsets;
+ struct device *dev = qmp->dev;
+ void __iomem *base;
+ int ret;
+
+ if (!offs)
+ return -EINVAL;
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ qmp->serdes = base + offs->serdes;
+ qmp->pcs = base + offs->pcs;
+ if (offs->pcs_misc)
+ qmp->pcs_misc = base + offs->pcs_misc;
+ qmp->tx = base + offs->tx;
+ qmp->rx = base + offs->rx;
+
+ qmp->tx2 = base + offs->tx2;
+ qmp->rx2 = base + offs->rx2;
+
+ ret = qmp_usbc_clk_init(qmp);
+ if (ret)
+ return ret;
+
+ qmp->pipe_clk = devm_clk_get(dev, "pipe");
+ if (IS_ERR(qmp->pipe_clk)) {
+ return dev_err_probe(dev, PTR_ERR(qmp->pipe_clk),
+ "failed to get pipe clock\n");
+ }
+
+ ret = qmp_usbc_reset_init(qmp, usb3phy_reset_l,
+ ARRAY_SIZE(usb3phy_reset_l));
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int qmp_usbc_parse_vls_clamp(struct qmp_usbc *qmp)
+{
+ struct of_phandle_args tcsr_args;
+ struct device *dev = qmp->dev;
+ int ret;
+
+ /* for backwards compatibility ignore if there is no property */
+ ret = of_parse_phandle_with_fixed_args(dev->of_node, "qcom,tcsr-reg", 1, 0,
+ &tcsr_args);
+ if (ret == -ENOENT)
+ return 0;
+ else if (ret < 0)
+ return dev_err_probe(dev, ret, "Failed to parse qcom,tcsr-reg\n");
+
+ qmp->tcsr_map = syscon_node_to_regmap(tcsr_args.np);
+ of_node_put(tcsr_args.np);
+ if (IS_ERR(qmp->tcsr_map))
+ return PTR_ERR(qmp->tcsr_map);
+
+ qmp->vls_clamp_reg = tcsr_args.args[0];
+
+ return 0;
+}
+
+static int qmp_usbc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct phy_provider *phy_provider;
+ struct device_node *np;
+ struct qmp_usbc *qmp;
+ int ret;
+
+ qmp = devm_kzalloc(dev, sizeof(*qmp), GFP_KERNEL);
+ if (!qmp)
+ return -ENOMEM;
+
+ qmp->dev = dev;
+ dev_set_drvdata(dev, qmp);
+
+ qmp->orientation = TYPEC_ORIENTATION_NORMAL;
+
+ qmp->cfg = of_device_get_match_data(dev);
+ if (!qmp->cfg)
+ return -EINVAL;
+
+ mutex_init(&qmp->phy_mutex);
+
+ ret = qmp_usbc_vreg_init(qmp);
+ if (ret)
+ return ret;
+
+ ret = qmp_usbc_typec_switch_register(qmp);
+ if (ret)
+ return ret;
+
+ ret = qmp_usbc_parse_vls_clamp(qmp);
+ if (ret)
+ return ret;
+
+ /* Check for legacy binding with child node. */
+ np = of_get_child_by_name(dev->of_node, "phy");
+ if (np) {
+ ret = qmp_usbc_parse_dt_legacy(qmp, np);
+ } else {
+ np = of_node_get(dev->of_node);
+ ret = qmp_usbc_parse_dt(qmp);
+ }
+ if (ret)
+ goto err_node_put;
+
+ pm_runtime_set_active(dev);
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ goto err_node_put;
+ /*
+ * Prevent runtime pm from being ON by default. Users can enable
+ * it using power/control in sysfs.
+ */
+ pm_runtime_forbid(dev);
+
+ ret = phy_pipe_clk_register(qmp, np);
+ if (ret)
+ goto err_node_put;
+
+ qmp->phy = devm_phy_create(dev, np, &qmp_usbc_phy_ops);
+ if (IS_ERR(qmp->phy)) {
+ ret = PTR_ERR(qmp->phy);
+ dev_err(dev, "failed to create PHY: %d\n", ret);
+ goto err_node_put;
+ }
+
+ phy_set_drvdata(qmp->phy, qmp);
+
+ of_node_put(np);
+
+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+ return PTR_ERR_OR_ZERO(phy_provider);
+
+err_node_put:
+ of_node_put(np);
+ return ret;
+}
+
+static const struct of_device_id qmp_usbc_of_match_table[] = {
+ {
+ .compatible = "qcom,msm8998-qmp-usb3-phy",
+ .data = &msm8998_usb3phy_cfg,
+ }, {
+ .compatible = "qcom,qcm2290-qmp-usb3-phy",
+ .data = &qcm2290_usb3phy_cfg,
+ }, {
+ .compatible = "qcom,sdm660-qmp-usb3-phy",
+ .data = &sdm660_usb3phy_cfg,
+ }, {
+ .compatible = "qcom,sm6115-qmp-usb3-phy",
+ .data = &qcm2290_usb3phy_cfg,
+ },
+ { },
+};
+MODULE_DEVICE_TABLE(of, qmp_usbc_of_match_table);
+
+static struct platform_driver qmp_usbc_driver = {
+ .probe = qmp_usbc_probe,
+ .driver = {
+ .name = "qcom-qmp-usbc-phy",
+ .pm = &qmp_usbc_pm_ops,
+ .of_match_table = qmp_usbc_of_match_table,
+ },
+};
+
+module_platform_driver(qmp_usbc_driver);
+
+MODULE_AUTHOR("Vivek Gautam <vivek.gautam@codeaurora.org>");
+MODULE_DESCRIPTION("Qualcomm QMP USB-C PHY driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h
index 6923496cbfee..d0f41e4aaa85 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.h
@@ -46,96 +46,35 @@
#include "phy-qcom-qmp-pcs-v6.h"
+#include "phy-qcom-qmp-pcs-v6-n4.h"
+
#include "phy-qcom-qmp-pcs-v6_20.h"
#include "phy-qcom-qmp-pcs-v7.h"
-/* Only for QMP V3 & V4 PHY - DP COM registers */
-#define QPHY_V3_DP_COM_PHY_MODE_CTRL 0x00
-#define QPHY_V3_DP_COM_SW_RESET 0x04
-#define QPHY_V3_DP_COM_POWER_DOWN_CTRL 0x08
-#define QPHY_V3_DP_COM_SWI_CTRL 0x0c
-#define QPHY_V3_DP_COM_TYPEC_CTRL 0x10
-#define QPHY_V3_DP_COM_TYPEC_PWRDN_CTRL 0x14
-#define QPHY_V3_DP_COM_RESET_OVRD_CTRL 0x1c
-
-/* QSERDES V3 COM bits */
-# define QSERDES_V3_COM_BIAS_EN 0x0001
-# define QSERDES_V3_COM_BIAS_EN_MUX 0x0002
-# define QSERDES_V3_COM_CLKBUF_R_EN 0x0004
-# define QSERDES_V3_COM_CLKBUF_L_EN 0x0008
-# define QSERDES_V3_COM_EN_SYSCLK_TX_SEL 0x0010
-# define QSERDES_V3_COM_CLKBUF_RX_DRIVE_L 0x0020
-# define QSERDES_V3_COM_CLKBUF_RX_DRIVE_R 0x0040
-
-/* QSERDES V3 TX bits */
-# define DP_PHY_TXn_TX_EMP_POST1_LVL_MASK 0x001f
-# define DP_PHY_TXn_TX_EMP_POST1_LVL_MUX_EN 0x0020
-# define DP_PHY_TXn_TX_DRV_LVL_MASK 0x001f
-# define DP_PHY_TXn_TX_DRV_LVL_MUX_EN 0x0020
-
-/* QMP PHY - DP PHY registers */
-#define QSERDES_DP_PHY_REVISION_ID0 0x000
-#define QSERDES_DP_PHY_REVISION_ID1 0x004
-#define QSERDES_DP_PHY_REVISION_ID2 0x008
-#define QSERDES_DP_PHY_REVISION_ID3 0x00c
-#define QSERDES_DP_PHY_CFG 0x010
-#define QSERDES_DP_PHY_PD_CTL 0x018
-# define DP_PHY_PD_CTL_PWRDN 0x001
-# define DP_PHY_PD_CTL_PSR_PWRDN 0x002
-# define DP_PHY_PD_CTL_AUX_PWRDN 0x004
-# define DP_PHY_PD_CTL_LANE_0_1_PWRDN 0x008
-# define DP_PHY_PD_CTL_LANE_2_3_PWRDN 0x010
-# define DP_PHY_PD_CTL_PLL_PWRDN 0x020
-# define DP_PHY_PD_CTL_DP_CLAMP_EN 0x040
-#define QSERDES_DP_PHY_MODE 0x01c
-#define QSERDES_DP_PHY_AUX_CFG0 0x020
-#define QSERDES_DP_PHY_AUX_CFG1 0x024
-#define QSERDES_DP_PHY_AUX_CFG2 0x028
-#define QSERDES_DP_PHY_AUX_CFG3 0x02c
-#define QSERDES_DP_PHY_AUX_CFG4 0x030
-#define QSERDES_DP_PHY_AUX_CFG5 0x034
-#define QSERDES_DP_PHY_AUX_CFG6 0x038
-#define QSERDES_DP_PHY_AUX_CFG7 0x03c
-#define QSERDES_DP_PHY_AUX_CFG8 0x040
-#define QSERDES_DP_PHY_AUX_CFG9 0x044
-
-/* Only for QMP V3 PHY - DP PHY registers */
-#define QSERDES_V3_DP_PHY_AUX_INTERRUPT_MASK 0x048
-# define PHY_AUX_STOP_ERR_MASK 0x01
-# define PHY_AUX_DEC_ERR_MASK 0x02
-# define PHY_AUX_SYNC_ERR_MASK 0x04
-# define PHY_AUX_ALIGN_ERR_MASK 0x08
-# define PHY_AUX_REQ_ERR_MASK 0x10
-
-#define QSERDES_V3_DP_PHY_AUX_INTERRUPT_CLEAR 0x04c
-#define QSERDES_V3_DP_PHY_AUX_BIST_CFG 0x050
-
-#define QSERDES_V3_DP_PHY_VCO_DIV 0x064
-#define QSERDES_V3_DP_PHY_TX0_TX1_LANE_CTL 0x06c
-#define QSERDES_V3_DP_PHY_TX2_TX3_LANE_CTL 0x088
-
-#define QSERDES_V3_DP_PHY_SPARE0 0x0ac
-#define DP_PHY_SPARE0_MASK 0x0f
-#define DP_PHY_SPARE0_ORIENTATION_INFO_SHIFT 0x04(0x0004)
-
-#define QSERDES_V3_DP_PHY_STATUS 0x0c0
-
-/* Only for QMP V4 PHY - DP PHY registers */
-#define QSERDES_V4_DP_PHY_CFG_1 0x014
-#define QSERDES_V4_DP_PHY_AUX_INTERRUPT_MASK 0x054
-#define QSERDES_V4_DP_PHY_AUX_INTERRUPT_CLEAR 0x058
-#define QSERDES_V4_DP_PHY_VCO_DIV 0x070
-#define QSERDES_V4_DP_PHY_TX0_TX1_LANE_CTL 0x078
-#define QSERDES_V4_DP_PHY_TX2_TX3_LANE_CTL 0x09c
-#define QSERDES_V4_DP_PHY_SPARE0 0x0c8
-#define QSERDES_V4_DP_PHY_AUX_INTERRUPT_STATUS 0x0d8
-#define QSERDES_V4_DP_PHY_STATUS 0x0dc
-
-#define QSERDES_V5_DP_PHY_STATUS 0x0dc
-
-/* Only for QMP V6 PHY - DP PHY registers */
-#define QSERDES_V6_DP_PHY_AUX_INTERRUPT_STATUS 0x0e0
-#define QSERDES_V6_DP_PHY_STATUS 0x0e4
+/* QPHY_SW_RESET bit */
+#define SW_RESET BIT(0)
+/* QPHY_POWER_DOWN_CONTROL */
+#define SW_PWRDN BIT(0)
+#define REFCLK_DRV_DSBL BIT(1) /* PCIe */
+
+/* QPHY_START_CONTROL bits */
+#define SERDES_START BIT(0)
+#define PCS_START BIT(1)
+
+/* QPHY_PCS_STATUS bit */
+#define PHYSTATUS BIT(6)
+#define PHYSTATUS_4_20 BIT(7)
+
+/* QPHY_PCS_AUTONOMOUS_MODE_CTRL register bits */
+#define ARCVR_DTCT_EN BIT(0)
+#define ALFPS_DTCT_EN BIT(1)
+#define ARCVR_DTCT_EVENT_SEL BIT(4)
+
+/* QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR register bits */
+#define IRQ_CLEAR BIT(0)
+
+/* QPHY_PCS_MISC_CLAMP_ENABLE register bits */
+#define CLAMP_EN BIT(0) /* enables i/o clamp_n */
#endif
diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c
index c52655a383ce..1f5f7df14d5a 100644
--- a/drivers/phy/qualcomm/phy-qcom-qusb2.c
+++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c
@@ -151,6 +151,34 @@ static const struct qusb2_phy_init_tbl ipq6018_init_tbl[] = {
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_AUTOPGM_CTL1, 0x9F),
};
+static const struct qusb2_phy_init_tbl ipq5424_init_tbl[] = {
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL, 0x14),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE1, 0x00),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE2, 0x53),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE4, 0xc3),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_TUNE, 0x30),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_USER_CTL1, 0x79),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_USER_CTL2, 0x21),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE5, 0x00),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_PWR_CTRL, 0x00),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TEST2, 0x14),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_TEST, 0x80),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_AUTOPGM_CTL1, 0x9f),
+};
+
+static const struct qusb2_phy_init_tbl qcs615_init_tbl[] = {
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE1, 0xc8),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE2, 0xb3),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE3, 0x83),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE4, 0xc0),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_TUNE, 0x30),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_USER_CTL1, 0x79),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_USER_CTL2, 0x21),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TEST2, 0x14),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_AUTOPGM_CTL1, 0x9f),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_PWR_CTRL, 0x00),
+};
+
static const unsigned int ipq6018_regs_layout[] = {
[QUSB2PHY_PLL_STATUS] = 0x38,
[QUSB2PHY_PORT_TUNE1] = 0x80,
@@ -331,6 +359,27 @@ static const struct qusb2_phy_cfg ipq6018_phy_cfg = {
.autoresume_en = BIT(0),
};
+static const struct qusb2_phy_cfg ipq5424_phy_cfg = {
+ .tbl = ipq5424_init_tbl,
+ .tbl_num = ARRAY_SIZE(ipq5424_init_tbl),
+ .regs = ipq6018_regs_layout,
+
+ .disable_ctrl = POWER_DOWN,
+ .mask_core_ready = PLL_LOCKED,
+ .autoresume_en = BIT(0),
+};
+
+static const struct qusb2_phy_cfg qcs615_phy_cfg = {
+ .tbl = qcs615_init_tbl,
+ .tbl_num = ARRAY_SIZE(qcs615_init_tbl),
+ .regs = ipq6018_regs_layout,
+
+ .disable_ctrl = (CLAMP_N_EN | FREEZIO_N | POWER_DOWN),
+ .mask_core_ready = PLL_LOCKED,
+ /* autoresume not used */
+ .autoresume_en = BIT(0),
+};
+
static const struct qusb2_phy_cfg qusb2_v2_phy_cfg = {
.tbl = qusb2_v2_init_tbl,
.tbl_num = ARRAY_SIZE(qusb2_v2_init_tbl),
@@ -905,6 +954,9 @@ static const struct phy_ops qusb2_phy_gen_ops = {
static const struct of_device_id qusb2_phy_of_match_table[] = {
{
+ .compatible = "qcom,ipq5424-qusb2-phy",
+ .data = &ipq5424_phy_cfg,
+ }, {
.compatible = "qcom,ipq6018-qusb2-phy",
.data = &ipq6018_phy_cfg,
}, {
@@ -923,6 +975,9 @@ static const struct of_device_id qusb2_phy_of_match_table[] = {
.compatible = "qcom,msm8998-qusb2-phy",
.data = &msm8998_phy_cfg,
}, {
+ .compatible = "qcom,qcs615-qusb2-phy",
+ .data = &qcs615_phy_cfg,
+ }, {
.compatible = "qcom,qcm2290-qusb2-phy",
.data = &sm6115_phy_cfg,
}, {
diff --git a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
index 03dc753f0de1..5b1c82459c12 100644
--- a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
+++ b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
@@ -11,93 +11,14 @@
#include <linux/platform_device.h>
#include <linux/regmap.h>
-#define QSERDES_QMP_PLL 0x0
-#define QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0 (QSERDES_QMP_PLL + 0x1ac)
-#define QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0 (QSERDES_QMP_PLL + 0x1b0)
-#define QSERDES_COM_BIN_VCOCAL_HSCLK_SEL (QSERDES_QMP_PLL + 0x1bc)
-#define QSERDES_COM_CORE_CLK_EN (QSERDES_QMP_PLL + 0x174)
-#define QSERDES_COM_CORECLK_DIV_MODE0 (QSERDES_QMP_PLL + 0x168)
-#define QSERDES_COM_CP_CTRL_MODE0 (QSERDES_QMP_PLL + 0x74)
-#define QSERDES_COM_DEC_START_MODE0 (QSERDES_QMP_PLL + 0xbc)
-#define QSERDES_COM_DIV_FRAC_START1_MODE0 (QSERDES_QMP_PLL + 0xcc)
-#define QSERDES_COM_DIV_FRAC_START2_MODE0 (QSERDES_QMP_PLL + 0xd0)
-#define QSERDES_COM_DIV_FRAC_START3_MODE0 (QSERDES_QMP_PLL + 0xd4)
-#define QSERDES_COM_HSCLK_HS_SWITCH_SEL (QSERDES_QMP_PLL + 0x15c)
-#define QSERDES_COM_HSCLK_SEL (QSERDES_QMP_PLL + 0x158)
-#define QSERDES_COM_LOCK_CMP1_MODE0 (QSERDES_QMP_PLL + 0xac)
-#define QSERDES_COM_LOCK_CMP2_MODE0 (QSERDES_QMP_PLL + 0xb0)
-#define QSERDES_COM_PLL_CCTRL_MODE0 (QSERDES_QMP_PLL + 0x84)
-#define QSERDES_COM_PLL_IVCO (QSERDES_QMP_PLL + 0x58)
-#define QSERDES_COM_PLL_RCTRL_MODE0 (QSERDES_QMP_PLL + 0x7c)
-#define QSERDES_COM_SYSCLK_EN_SEL (QSERDES_QMP_PLL + 0x94)
-#define QSERDES_COM_VCO_TUNE1_MODE0 (QSERDES_QMP_PLL + 0x110)
-#define QSERDES_COM_VCO_TUNE2_MODE0 (QSERDES_QMP_PLL + 0x114)
-#define QSERDES_COM_VCO_TUNE_INITVAL2 (QSERDES_QMP_PLL + 0x124)
-#define QSERDES_COM_C_READY_STATUS (QSERDES_QMP_PLL + 0x178)
-#define QSERDES_COM_CMN_STATUS (QSERDES_QMP_PLL + 0x140)
+#include "phy-qcom-qmp-pcs-sgmii.h"
+#include "phy-qcom-qmp-qserdes-com-v5.h"
+#include "phy-qcom-qmp-qserdes-txrx-v5.h"
+#define QSERDES_QMP_PLL 0x0
#define QSERDES_RX 0x600
-#define QSERDES_RX_UCDR_FO_GAIN (QSERDES_RX + 0x8)
-#define QSERDES_RX_UCDR_SO_GAIN (QSERDES_RX + 0x14)
-#define QSERDES_RX_UCDR_FASTLOCK_FO_GAIN (QSERDES_RX + 0x30)
-#define QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE (QSERDES_RX + 0x34)
-#define QSERDES_RX_UCDR_FASTLOCK_COUNT_LOW (QSERDES_RX + 0x3c)
-#define QSERDES_RX_UCDR_FASTLOCK_COUNT_HIGH (QSERDES_RX + 0x40)
-#define QSERDES_RX_UCDR_PI_CONTROLS (QSERDES_RX + 0x44)
-#define QSERDES_RX_UCDR_PI_CTRL2 (QSERDES_RX + 0x48)
-#define QSERDES_RX_RX_TERM_BW (QSERDES_RX + 0x80)
-#define QSERDES_RX_VGA_CAL_CNTRL2 (QSERDES_RX + 0xd8)
-#define QSERDES_RX_GM_CAL (QSERDES_RX + 0xdc)
-#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1 (QSERDES_RX + 0xe8)
-#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2 (QSERDES_RX + 0xec)
-#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3 (QSERDES_RX + 0xf0)
-#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4 (QSERDES_RX + 0xf4)
-#define QSERDES_RX_RX_IDAC_TSETTLE_LOW (QSERDES_RX + 0xf8)
-#define QSERDES_RX_RX_IDAC_TSETTLE_HIGH (QSERDES_RX + 0xfc)
-#define QSERDES_RX_RX_IDAC_MEASURE_TIME (QSERDES_RX + 0x100)
-#define QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 (QSERDES_RX + 0x110)
-#define QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2 (QSERDES_RX + 0x114)
-#define QSERDES_RX_SIGDET_CNTRL (QSERDES_RX + 0x11c)
-#define QSERDES_RX_SIGDET_DEGLITCH_CNTRL (QSERDES_RX + 0x124)
-#define QSERDES_RX_RX_BAND (QSERDES_RX + 0x128)
-#define QSERDES_RX_RX_MODE_00_LOW (QSERDES_RX + 0x15c)
-#define QSERDES_RX_RX_MODE_00_HIGH (QSERDES_RX + 0x160)
-#define QSERDES_RX_RX_MODE_00_HIGH2 (QSERDES_RX + 0x164)
-#define QSERDES_RX_RX_MODE_00_HIGH3 (QSERDES_RX + 0x168)
-#define QSERDES_RX_RX_MODE_00_HIGH4 (QSERDES_RX + 0x16c)
-#define QSERDES_RX_RX_MODE_01_LOW (QSERDES_RX + 0x170)
-#define QSERDES_RX_RX_MODE_01_HIGH (QSERDES_RX + 0x174)
-#define QSERDES_RX_RX_MODE_01_HIGH2 (QSERDES_RX + 0x178)
-#define QSERDES_RX_RX_MODE_01_HIGH3 (QSERDES_RX + 0x17c)
-#define QSERDES_RX_RX_MODE_01_HIGH4 (QSERDES_RX + 0x180)
-#define QSERDES_RX_RX_MODE_10_LOW (QSERDES_RX + 0x184)
-#define QSERDES_RX_RX_MODE_10_HIGH (QSERDES_RX + 0x188)
-#define QSERDES_RX_RX_MODE_10_HIGH2 (QSERDES_RX + 0x18c)
-#define QSERDES_RX_RX_MODE_10_HIGH3 (QSERDES_RX + 0x190)
-#define QSERDES_RX_RX_MODE_10_HIGH4 (QSERDES_RX + 0x194)
-#define QSERDES_RX_DCC_CTRL1 (QSERDES_RX + 0x1a8)
-
#define QSERDES_TX 0x400
-#define QSERDES_TX_TX_BAND (QSERDES_TX + 0x24)
-#define QSERDES_TX_SLEW_CNTL (QSERDES_TX + 0x28)
-#define QSERDES_TX_RES_CODE_LANE_OFFSET_TX (QSERDES_TX + 0x3c)
-#define QSERDES_TX_RES_CODE_LANE_OFFSET_RX (QSERDES_TX + 0x40)
-#define QSERDES_TX_LANE_MODE_1 (QSERDES_TX + 0x84)
-#define QSERDES_TX_LANE_MODE_3 (QSERDES_TX + 0x8c)
-#define QSERDES_TX_RCV_DETECT_LVL_2 (QSERDES_TX + 0xa4)
-#define QSERDES_TX_TRAN_DRVR_EMP_EN (QSERDES_TX + 0xc0)
-
-#define QSERDES_PCS 0xC00
-#define QSERDES_PCS_PHY_START (QSERDES_PCS + 0x0)
-#define QSERDES_PCS_POWER_DOWN_CONTROL (QSERDES_PCS + 0x4)
-#define QSERDES_PCS_SW_RESET (QSERDES_PCS + 0x8)
-#define QSERDES_PCS_LINE_RESET_TIME (QSERDES_PCS + 0xc)
-#define QSERDES_PCS_TX_LARGE_AMP_DRV_LVL (QSERDES_PCS + 0x20)
-#define QSERDES_PCS_TX_SMALL_AMP_DRV_LVL (QSERDES_PCS + 0x28)
-#define QSERDES_PCS_TX_MID_TERM_CTRL1 (QSERDES_PCS + 0xd8)
-#define QSERDES_PCS_TX_MID_TERM_CTRL2 (QSERDES_PCS + 0xdc)
-#define QSERDES_PCS_SGMII_MISC_CTRL8 (QSERDES_PCS + 0x118)
-#define QSERDES_PCS_PCS_READY_STATUS (QSERDES_PCS + 0x94)
+#define QSERDES_PCS 0xc00
#define QSERDES_COM_C_READY BIT(0)
#define QSERDES_PCS_READY BIT(0)
@@ -112,178 +33,178 @@ struct qcom_dwmac_sgmii_phy_data {
static void qcom_dwmac_sgmii_phy_init_1g(struct regmap *regmap)
{
- regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x01);
- regmap_write(regmap, QSERDES_PCS_POWER_DOWN_CONTROL, 0x01);
-
- regmap_write(regmap, QSERDES_COM_PLL_IVCO, 0x0F);
- regmap_write(regmap, QSERDES_COM_CP_CTRL_MODE0, 0x06);
- regmap_write(regmap, QSERDES_COM_PLL_RCTRL_MODE0, 0x16);
- regmap_write(regmap, QSERDES_COM_PLL_CCTRL_MODE0, 0x36);
- regmap_write(regmap, QSERDES_COM_SYSCLK_EN_SEL, 0x1A);
- regmap_write(regmap, QSERDES_COM_LOCK_CMP1_MODE0, 0x0A);
- regmap_write(regmap, QSERDES_COM_LOCK_CMP2_MODE0, 0x1A);
- regmap_write(regmap, QSERDES_COM_DEC_START_MODE0, 0x82);
- regmap_write(regmap, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55);
- regmap_write(regmap, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55);
- regmap_write(regmap, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03);
- regmap_write(regmap, QSERDES_COM_VCO_TUNE1_MODE0, 0x24);
-
- regmap_write(regmap, QSERDES_COM_VCO_TUNE2_MODE0, 0x02);
- regmap_write(regmap, QSERDES_COM_VCO_TUNE_INITVAL2, 0x00);
- regmap_write(regmap, QSERDES_COM_HSCLK_SEL, 0x04);
- regmap_write(regmap, QSERDES_COM_HSCLK_HS_SWITCH_SEL, 0x00);
- regmap_write(regmap, QSERDES_COM_CORECLK_DIV_MODE0, 0x0A);
- regmap_write(regmap, QSERDES_COM_CORE_CLK_EN, 0x00);
- regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xB9);
- regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1E);
- regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_HSCLK_SEL, 0x11);
-
- regmap_write(regmap, QSERDES_TX_TX_BAND, 0x05);
- regmap_write(regmap, QSERDES_TX_SLEW_CNTL, 0x0A);
- regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_TX, 0x09);
- regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_RX, 0x09);
- regmap_write(regmap, QSERDES_TX_LANE_MODE_1, 0x05);
- regmap_write(regmap, QSERDES_TX_LANE_MODE_3, 0x00);
- regmap_write(regmap, QSERDES_TX_RCV_DETECT_LVL_2, 0x12);
- regmap_write(regmap, QSERDES_TX_TRAN_DRVR_EMP_EN, 0x0C);
-
- regmap_write(regmap, QSERDES_RX_UCDR_FO_GAIN, 0x0A);
- regmap_write(regmap, QSERDES_RX_UCDR_SO_GAIN, 0x06);
- regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0A);
- regmap_write(regmap, QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7F);
- regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00);
- regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x01);
- regmap_write(regmap, QSERDES_RX_UCDR_PI_CONTROLS, 0x81);
- regmap_write(regmap, QSERDES_RX_UCDR_PI_CTRL2, 0x80);
- regmap_write(regmap, QSERDES_RX_RX_TERM_BW, 0x04);
- regmap_write(regmap, QSERDES_RX_VGA_CAL_CNTRL2, 0x08);
- regmap_write(regmap, QSERDES_RX_GM_CAL, 0x0F);
- regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04);
- regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00);
- regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4A);
- regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0A);
- regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_LOW, 0x80);
- regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_HIGH, 0x01);
- regmap_write(regmap, QSERDES_RX_RX_IDAC_MEASURE_TIME, 0x20);
- regmap_write(regmap, QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17);
- regmap_write(regmap, QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00);
- regmap_write(regmap, QSERDES_RX_SIGDET_CNTRL, 0x0F);
- regmap_write(regmap, QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E);
- regmap_write(regmap, QSERDES_RX_RX_BAND, 0x05);
- regmap_write(regmap, QSERDES_RX_RX_MODE_00_LOW, 0xE0);
- regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH, 0xC8);
- regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH2, 0xC8);
- regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH3, 0x09);
- regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH4, 0xB1);
- regmap_write(regmap, QSERDES_RX_RX_MODE_01_LOW, 0xE0);
- regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH, 0xC8);
- regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH2, 0xC8);
- regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH3, 0x09);
- regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH4, 0xB1);
- regmap_write(regmap, QSERDES_RX_RX_MODE_10_LOW, 0xE0);
- regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH, 0xC8);
- regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH2, 0xC8);
- regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH3, 0x3B);
- regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH4, 0xB7);
- regmap_write(regmap, QSERDES_RX_DCC_CTRL1, 0x0C);
-
- regmap_write(regmap, QSERDES_PCS_LINE_RESET_TIME, 0x0C);
- regmap_write(regmap, QSERDES_PCS_TX_LARGE_AMP_DRV_LVL, 0x1F);
- regmap_write(regmap, QSERDES_PCS_TX_SMALL_AMP_DRV_LVL, 0x03);
- regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL1, 0x83);
- regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL2, 0x08);
- regmap_write(regmap, QSERDES_PCS_SGMII_MISC_CTRL8, 0x0C);
- regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x00);
-
- regmap_write(regmap, QSERDES_PCS_PHY_START, 0x01);
+ regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x01);
+ regmap_write(regmap, QSERDES_PCS + QPHY_PCS_POWER_DOWN_CONTROL, 0x01);
+
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_PLL_IVCO, 0x0F);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_CP_CTRL_MODE0, 0x06);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x16);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x36);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_SYSCLK_EN_SEL, 0x1A);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_LOCK_CMP1_MODE0, 0x0A);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x1A);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DEC_START_MODE0, 0x82);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DIV_FRAC_START1_MODE0, 0x55);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DIV_FRAC_START2_MODE0, 0x55);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DIV_FRAC_START3_MODE0, 0x03);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_VCO_TUNE1_MODE0, 0x24);
+
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_VCO_TUNE2_MODE0, 0x02);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_VCO_TUNE_INITVAL2, 0x00);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_HSCLK_SEL, 0x04);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_HSCLK_HS_SWITCH_SEL, 0x00);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_CORECLK_DIV_MODE0, 0x0A);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_CORE_CLK_EN, 0x00);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xB9);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1E);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_BIN_VCOCAL_HSCLK_SEL, 0x11);
+
+ regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_TX_BAND, 0x05);
+ regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_SLEW_CNTL, 0x0A);
+ regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x09);
+ regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x09);
+ regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_LANE_MODE_1, 0x05);
+ regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_LANE_MODE_3, 0x00);
+ regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_RCV_DETECT_LVL_2, 0x12);
+ regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_TRAN_DRVR_EMP_EN, 0x0C);
+
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FO_GAIN, 0x0A);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_SO_GAIN, 0x06);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x0A);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7F);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x01);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x81);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_PI_CTRL2, 0x80);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_TERM_BW, 0x04);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x08);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_GM_CAL, 0x0F);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4A);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0A);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_IDAC_TSETTLE_LOW, 0x80);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_IDAC_TSETTLE_HIGH, 0x01);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_IDAC_MEASURE_TIME, 0x20);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_SIGDET_CNTRL, 0x0F);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x1E);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_BAND, 0x05);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_LOW, 0xE0);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH, 0xC8);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xC8);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x09);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xB1);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_LOW, 0xE0);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH, 0xC8);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xC8);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x09);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xB1);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_LOW, 0xE0);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH, 0xC8);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH2, 0xC8);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH3, 0x3B);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH4, 0xB7);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_DCC_CTRL1, 0x0C);
+
+ regmap_write(regmap, QSERDES_PCS + QPHY_PCS_LINE_RESET_TIME, 0x0C);
+ regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_LARGE_AMP_DRV_LVL, 0x1F);
+ regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_SMALL_AMP_DRV_LVL, 0x03);
+ regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_MID_TERM_CTRL1, 0x83);
+ regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_MID_TERM_CTRL2, 0x08);
+ regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SGMII_MISC_CTRL8, 0x0C);
+ regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x00);
+
+ regmap_write(regmap, QSERDES_PCS + QPHY_PCS_PHY_START, 0x01);
}
static void qcom_dwmac_sgmii_phy_init_2p5g(struct regmap *regmap)
{
- regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x01);
- regmap_write(regmap, QSERDES_PCS_POWER_DOWN_CONTROL, 0x01);
-
- regmap_write(regmap, QSERDES_COM_PLL_IVCO, 0x0F);
- regmap_write(regmap, QSERDES_COM_CP_CTRL_MODE0, 0x06);
- regmap_write(regmap, QSERDES_COM_PLL_RCTRL_MODE0, 0x16);
- regmap_write(regmap, QSERDES_COM_PLL_CCTRL_MODE0, 0x36);
- regmap_write(regmap, QSERDES_COM_SYSCLK_EN_SEL, 0x1A);
- regmap_write(regmap, QSERDES_COM_LOCK_CMP1_MODE0, 0x1A);
- regmap_write(regmap, QSERDES_COM_LOCK_CMP2_MODE0, 0x41);
- regmap_write(regmap, QSERDES_COM_DEC_START_MODE0, 0x7A);
- regmap_write(regmap, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00);
- regmap_write(regmap, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x20);
- regmap_write(regmap, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x01);
- regmap_write(regmap, QSERDES_COM_VCO_TUNE1_MODE0, 0xA1);
-
- regmap_write(regmap, QSERDES_COM_VCO_TUNE2_MODE0, 0x02);
- regmap_write(regmap, QSERDES_COM_VCO_TUNE_INITVAL2, 0x00);
- regmap_write(regmap, QSERDES_COM_HSCLK_SEL, 0x03);
- regmap_write(regmap, QSERDES_COM_HSCLK_HS_SWITCH_SEL, 0x00);
- regmap_write(regmap, QSERDES_COM_CORECLK_DIV_MODE0, 0x05);
- regmap_write(regmap, QSERDES_COM_CORE_CLK_EN, 0x00);
- regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xCD);
- regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1C);
- regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_HSCLK_SEL, 0x11);
-
- regmap_write(regmap, QSERDES_TX_TX_BAND, 0x04);
- regmap_write(regmap, QSERDES_TX_SLEW_CNTL, 0x0A);
- regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_TX, 0x09);
- regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_RX, 0x02);
- regmap_write(regmap, QSERDES_TX_LANE_MODE_1, 0x05);
- regmap_write(regmap, QSERDES_TX_LANE_MODE_3, 0x00);
- regmap_write(regmap, QSERDES_TX_RCV_DETECT_LVL_2, 0x12);
- regmap_write(regmap, QSERDES_TX_TRAN_DRVR_EMP_EN, 0x0C);
-
- regmap_write(regmap, QSERDES_RX_UCDR_FO_GAIN, 0x0A);
- regmap_write(regmap, QSERDES_RX_UCDR_SO_GAIN, 0x06);
- regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0A);
- regmap_write(regmap, QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7F);
- regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00);
- regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x01);
- regmap_write(regmap, QSERDES_RX_UCDR_PI_CONTROLS, 0x81);
- regmap_write(regmap, QSERDES_RX_UCDR_PI_CTRL2, 0x80);
- regmap_write(regmap, QSERDES_RX_RX_TERM_BW, 0x00);
- regmap_write(regmap, QSERDES_RX_VGA_CAL_CNTRL2, 0x08);
- regmap_write(regmap, QSERDES_RX_GM_CAL, 0x0F);
- regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04);
- regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00);
- regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4A);
- regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0A);
- regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_LOW, 0x80);
- regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_HIGH, 0x01);
- regmap_write(regmap, QSERDES_RX_RX_IDAC_MEASURE_TIME, 0x20);
- regmap_write(regmap, QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17);
- regmap_write(regmap, QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00);
- regmap_write(regmap, QSERDES_RX_SIGDET_CNTRL, 0x0F);
- regmap_write(regmap, QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E);
- regmap_write(regmap, QSERDES_RX_RX_BAND, 0x18);
- regmap_write(regmap, QSERDES_RX_RX_MODE_00_LOW, 0x18);
- regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH, 0xC8);
- regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH2, 0xC8);
- regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH3, 0x0C);
- regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH4, 0xB8);
- regmap_write(regmap, QSERDES_RX_RX_MODE_01_LOW, 0xE0);
- regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH, 0xC8);
- regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH2, 0xC8);
- regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH3, 0x09);
- regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH4, 0xB1);
- regmap_write(regmap, QSERDES_RX_RX_MODE_10_LOW, 0xE0);
- regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH, 0xC8);
- regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH2, 0xC8);
- regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH3, 0x3B);
- regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH4, 0xB7);
- regmap_write(regmap, QSERDES_RX_DCC_CTRL1, 0x0C);
-
- regmap_write(regmap, QSERDES_PCS_LINE_RESET_TIME, 0x0C);
- regmap_write(regmap, QSERDES_PCS_TX_LARGE_AMP_DRV_LVL, 0x1F);
- regmap_write(regmap, QSERDES_PCS_TX_SMALL_AMP_DRV_LVL, 0x03);
- regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL1, 0x83);
- regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL2, 0x08);
- regmap_write(regmap, QSERDES_PCS_SGMII_MISC_CTRL8, 0x8C);
- regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x00);
-
- regmap_write(regmap, QSERDES_PCS_PHY_START, 0x01);
+ regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x01);
+ regmap_write(regmap, QSERDES_PCS + QPHY_PCS_POWER_DOWN_CONTROL, 0x01);
+
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_PLL_IVCO, 0x0F);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_CP_CTRL_MODE0, 0x06);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x16);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x36);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_SYSCLK_EN_SEL, 0x1A);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_LOCK_CMP1_MODE0, 0x1A);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x41);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DEC_START_MODE0, 0x7A);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DIV_FRAC_START1_MODE0, 0x00);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DIV_FRAC_START2_MODE0, 0x20);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_DIV_FRAC_START3_MODE0, 0x01);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_VCO_TUNE1_MODE0, 0xA1);
+
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_VCO_TUNE2_MODE0, 0x02);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_VCO_TUNE_INITVAL2, 0x00);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_HSCLK_SEL, 0x03);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_HSCLK_HS_SWITCH_SEL, 0x00);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_CORECLK_DIV_MODE0, 0x05);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_CORE_CLK_EN, 0x00);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xCD);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1C);
+ regmap_write(regmap, QSERDES_QMP_PLL + QSERDES_V5_COM_BIN_VCOCAL_HSCLK_SEL, 0x11);
+
+ regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_TX_BAND, 0x04);
+ regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_SLEW_CNTL, 0x0A);
+ regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x09);
+ regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x02);
+ regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_LANE_MODE_1, 0x05);
+ regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_LANE_MODE_3, 0x00);
+ regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_RCV_DETECT_LVL_2, 0x12);
+ regmap_write(regmap, QSERDES_TX + QSERDES_V5_TX_TRAN_DRVR_EMP_EN, 0x0C);
+
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FO_GAIN, 0x0A);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_SO_GAIN, 0x06);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x0A);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7F);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x01);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x81);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_UCDR_PI_CTRL2, 0x80);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_TERM_BW, 0x00);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x08);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_GM_CAL, 0x0F);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4A);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0A);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_IDAC_TSETTLE_LOW, 0x80);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_IDAC_TSETTLE_HIGH, 0x01);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_IDAC_MEASURE_TIME, 0x20);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_SIGDET_CNTRL, 0x0F);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x1E);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_BAND, 0x18);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_LOW, 0x18);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH, 0xC8);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xC8);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x0C);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xB8);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_LOW, 0xE0);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH, 0xC8);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xC8);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x09);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xB1);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_LOW, 0xE0);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH, 0xC8);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH2, 0xC8);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH3, 0x3B);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_RX_MODE_10_HIGH4, 0xB7);
+ regmap_write(regmap, QSERDES_RX + QSERDES_V5_RX_DCC_CTRL1, 0x0C);
+
+ regmap_write(regmap, QSERDES_PCS + QPHY_PCS_LINE_RESET_TIME, 0x0C);
+ regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_LARGE_AMP_DRV_LVL, 0x1F);
+ regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_SMALL_AMP_DRV_LVL, 0x03);
+ regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_MID_TERM_CTRL1, 0x83);
+ regmap_write(regmap, QSERDES_PCS + QPHY_PCS_TX_MID_TERM_CTRL2, 0x08);
+ regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SGMII_MISC_CTRL8, 0x8C);
+ regmap_write(regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x00);
+
+ regmap_write(regmap, QSERDES_PCS + QPHY_PCS_PHY_START, 0x01);
}
static inline int
@@ -313,28 +234,28 @@ static int qcom_dwmac_sgmii_phy_calibrate(struct phy *phy)
}
if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
- QSERDES_COM_C_READY_STATUS,
+ QSERDES_QMP_PLL + QSERDES_V5_COM_C_READY_STATUS,
QSERDES_COM_C_READY)) {
dev_err(dev, "QSERDES_COM_C_READY_STATUS timed-out");
return -ETIMEDOUT;
}
if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
- QSERDES_PCS_PCS_READY_STATUS,
+ QSERDES_PCS + QPHY_PCS_PCS_READY_STATUS,
QSERDES_PCS_READY)) {
dev_err(dev, "PCS_READY timed-out");
return -ETIMEDOUT;
}
if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
- QSERDES_PCS_PCS_READY_STATUS,
+ QSERDES_PCS + QPHY_PCS_PCS_READY_STATUS,
QSERDES_PCS_SGMIIPHY_READY)) {
dev_err(dev, "SGMIIPHY_READY timed-out");
return -ETIMEDOUT;
}
if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
- QSERDES_COM_CMN_STATUS,
+ QSERDES_QMP_PLL + QSERDES_V5_COM_CMN_STATUS,
QSERDES_COM_C_PLL_LOCKED)) {
dev_err(dev, "PLL Lock Status timed-out");
return -ETIMEDOUT;
@@ -354,11 +275,11 @@ static int qcom_dwmac_sgmii_phy_power_off(struct phy *phy)
{
struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
- regmap_write(data->regmap, QSERDES_PCS_TX_MID_TERM_CTRL2, 0x08);
- regmap_write(data->regmap, QSERDES_PCS_SW_RESET, 0x01);
+ regmap_write(data->regmap, QSERDES_PCS + QPHY_PCS_TX_MID_TERM_CTRL2, 0x08);
+ regmap_write(data->regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x01);
udelay(100);
- regmap_write(data->regmap, QSERDES_PCS_SW_RESET, 0x00);
- regmap_write(data->regmap, QSERDES_PCS_PHY_START, 0x01);
+ regmap_write(data->regmap, QSERDES_PCS + QPHY_PCS_SW_RESET, 0x00);
+ regmap_write(data->regmap, QSERDES_PCS + QPHY_PCS_PHY_START, 0x01);
clk_disable_unprepare(data->refclk);
diff --git a/drivers/phy/ralink/phy-mt7621-pci.c b/drivers/phy/ralink/phy-mt7621-pci.c
index 2f876f158e1d..a591ad95347c 100644
--- a/drivers/phy/ralink/phy-mt7621-pci.c
+++ b/drivers/phy/ralink/phy-mt7621-pci.c
@@ -263,7 +263,7 @@ static const struct phy_ops mt7621_pci_phy_ops = {
};
static struct phy *mt7621_pcie_phy_of_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct mt7621_pci_phy *mt7621_phy = dev_get_drvdata(dev);
diff --git a/drivers/phy/realtek/Kconfig b/drivers/phy/realtek/Kconfig
new file mode 100644
index 000000000000..75ac7e7c31ae
--- /dev/null
+++ b/drivers/phy/realtek/Kconfig
@@ -0,0 +1,32 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Phy drivers for Realtek platforms
+#
+
+if ARCH_REALTEK || COMPILE_TEST
+
+config PHY_RTK_RTD_USB2PHY
+ tristate "Realtek RTD USB2 PHY Transceiver Driver"
+ depends on USB_SUPPORT
+ select GENERIC_PHY
+ select USB_PHY
+ select USB_COMMON
+ help
+ Enable this to support Realtek SoC USB2 phy transceiver.
+ The DHC (digital home center) RTD series SoCs used the Synopsys
+ DWC3 USB IP. This driver will do the PHY initialization
+ of the parameters.
+
+config PHY_RTK_RTD_USB3PHY
+ tristate "Realtek RTD USB3 PHY Transceiver Driver"
+ depends on USB_SUPPORT
+ select GENERIC_PHY
+ select USB_PHY
+ select USB_COMMON
+ help
+ Enable this to support Realtek SoC USB3 phy transceiver.
+ The DHC (digital home center) RTD series SoCs used the Synopsys
+ DWC3 USB IP. This driver will do the PHY initialization
+ of the parameters.
+
+endif # ARCH_REALTEK || COMPILE_TEST
diff --git a/drivers/phy/realtek/Makefile b/drivers/phy/realtek/Makefile
new file mode 100644
index 000000000000..ed7b47ff8a26
--- /dev/null
+++ b/drivers/phy/realtek/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_PHY_RTK_RTD_USB2PHY) += phy-rtk-usb2.o
+obj-$(CONFIG_PHY_RTK_RTD_USB3PHY) += phy-rtk-usb3.o
diff --git a/drivers/phy/realtek/phy-rtk-usb2.c b/drivers/phy/realtek/phy-rtk-usb2.c
new file mode 100644
index 000000000000..248550ef98ca
--- /dev/null
+++ b/drivers/phy/realtek/phy-rtk-usb2.c
@@ -0,0 +1,1314 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * phy-rtk-usb2.c RTK usb2.0 PHY driver
+ *
+ * Copyright (C) 2023 Realtek Semiconductor Corporation
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/debugfs.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/regmap.h>
+#include <linux/sys_soc.h>
+#include <linux/mfd/syscon.h>
+#include <linux/phy/phy.h>
+#include <linux/usb.h>
+
+/* GUSB2PHYACCn register */
+#define PHY_NEW_REG_REQ BIT(25)
+#define PHY_VSTS_BUSY BIT(23)
+#define PHY_VCTRL_SHIFT 8
+#define PHY_REG_DATA_MASK 0xff
+
+#define GET_LOW_NIBBLE(addr) ((addr) & 0x0f)
+#define GET_HIGH_NIBBLE(addr) (((addr) & 0xf0) >> 4)
+
+#define EFUS_USB_DC_CAL_RATE 2
+#define EFUS_USB_DC_CAL_MAX 7
+
+#define EFUS_USB_DC_DIS_RATE 1
+#define EFUS_USB_DC_DIS_MAX 7
+
+#define MAX_PHY_DATA_SIZE 20
+#define OFFEST_PHY_READ 0x20
+
+#define MAX_USB_PHY_NUM 4
+#define MAX_USB_PHY_PAGE0_DATA_SIZE 16
+#define MAX_USB_PHY_PAGE1_DATA_SIZE 16
+#define MAX_USB_PHY_PAGE2_DATA_SIZE 8
+
+#define SET_PAGE_OFFSET 0xf4
+#define SET_PAGE_0 0x9b
+#define SET_PAGE_1 0xbb
+#define SET_PAGE_2 0xdb
+
+#define PAGE_START 0xe0
+#define PAGE0_0XE4 0xe4
+#define PAGE0_0XE6 0xe6
+#define PAGE0_0XE7 0xe7
+#define PAGE1_0XE0 0xe0
+#define PAGE1_0XE2 0xe2
+
+#define SENSITIVITY_CTRL (BIT(4) | BIT(5) | BIT(6))
+#define ENABLE_AUTO_SENSITIVITY_CALIBRATION BIT(2)
+#define DEFAULT_DC_DRIVING_VALUE (0x8)
+#define DEFAULT_DC_DISCONNECTION_VALUE (0x6)
+#define HS_CLK_SELECT BIT(6)
+
+struct phy_reg {
+ void __iomem *reg_wrap_vstatus;
+ void __iomem *reg_gusb2phyacc0;
+ int vstatus_index;
+};
+
+struct phy_data {
+ u8 addr;
+ u8 data;
+};
+
+struct phy_cfg {
+ int page0_size;
+ struct phy_data page0[MAX_USB_PHY_PAGE0_DATA_SIZE];
+ int page1_size;
+ struct phy_data page1[MAX_USB_PHY_PAGE1_DATA_SIZE];
+ int page2_size;
+ struct phy_data page2[MAX_USB_PHY_PAGE2_DATA_SIZE];
+
+ int num_phy;
+
+ bool check_efuse;
+ int check_efuse_version;
+#define CHECK_EFUSE_V1 1
+#define CHECK_EFUSE_V2 2
+ int efuse_dc_driving_rate;
+ int efuse_dc_disconnect_rate;
+ int dc_driving_mask;
+ int dc_disconnect_mask;
+ bool usb_dc_disconnect_at_page0;
+ int driving_updated_for_dev_dis;
+
+ bool do_toggle;
+ bool do_toggle_driving;
+ bool use_default_parameter;
+ bool is_double_sensitivity_mode;
+};
+
+struct phy_parameter {
+ struct phy_reg phy_reg;
+
+ /* Get from efuse */
+ s8 efuse_usb_dc_cal;
+ s8 efuse_usb_dc_dis;
+
+ /* Get from dts */
+ bool inverse_hstx_sync_clock;
+ u32 driving_level;
+ s32 driving_level_compensate;
+ s32 disconnection_compensate;
+};
+
+struct rtk_phy {
+ struct device *dev;
+
+ struct phy_cfg *phy_cfg;
+ int num_phy;
+ struct phy_parameter *phy_parameter;
+
+ struct dentry *debug_dir;
+};
+
+/* mapping 0xE0 to 0 ... 0xE7 to 7, 0xF0 to 8 ,,, 0xF7 to 15 */
+static inline int page_addr_to_array_index(u8 addr)
+{
+ return (int)((((addr) - PAGE_START) & 0x7) +
+ ((((addr) - PAGE_START) & 0x10) >> 1));
+}
+
+static inline u8 array_index_to_page_addr(int index)
+{
+ return ((((index) + PAGE_START) & 0x7) +
+ ((((index) & 0x8) << 1) + PAGE_START));
+}
+
+#define PHY_IO_TIMEOUT_USEC (50000)
+#define PHY_IO_DELAY_US (100)
+
+static inline int utmi_wait_register(void __iomem *reg, u32 mask, u32 result)
+{
+ int ret;
+ unsigned int val;
+
+ ret = read_poll_timeout(readl, val, ((val & mask) == result),
+ PHY_IO_DELAY_US, PHY_IO_TIMEOUT_USEC, false, reg);
+ if (ret) {
+ pr_err("%s can't program USB phy\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static char rtk_phy_read(struct phy_reg *phy_reg, char addr)
+{
+ void __iomem *reg_gusb2phyacc0 = phy_reg->reg_gusb2phyacc0;
+ unsigned int val;
+ int ret = 0;
+
+ addr -= OFFEST_PHY_READ;
+
+ /* polling until VBusy == 0 */
+ ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
+ if (ret)
+ return (char)ret;
+
+ /* VCtrl = low nibble of addr, and set PHY_NEW_REG_REQ */
+ val = PHY_NEW_REG_REQ | (GET_LOW_NIBBLE(addr) << PHY_VCTRL_SHIFT);
+ writel(val, reg_gusb2phyacc0);
+ ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
+ if (ret)
+ return (char)ret;
+
+ /* VCtrl = high nibble of addr, and set PHY_NEW_REG_REQ */
+ val = PHY_NEW_REG_REQ | (GET_HIGH_NIBBLE(addr) << PHY_VCTRL_SHIFT);
+ writel(val, reg_gusb2phyacc0);
+ ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
+ if (ret)
+ return (char)ret;
+
+ val = readl(reg_gusb2phyacc0);
+
+ return (char)(val & PHY_REG_DATA_MASK);
+}
+
+static int rtk_phy_write(struct phy_reg *phy_reg, char addr, char data)
+{
+ unsigned int val;
+ void __iomem *reg_wrap_vstatus = phy_reg->reg_wrap_vstatus;
+ void __iomem *reg_gusb2phyacc0 = phy_reg->reg_gusb2phyacc0;
+ int shift_bits = phy_reg->vstatus_index * 8;
+ int ret = 0;
+
+ /* write data to VStatusOut2 (data output to phy) */
+ writel((u32)data << shift_bits, reg_wrap_vstatus);
+
+ ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
+ if (ret)
+ return ret;
+
+ /* VCtrl = low nibble of addr, set PHY_NEW_REG_REQ */
+ val = PHY_NEW_REG_REQ | (GET_LOW_NIBBLE(addr) << PHY_VCTRL_SHIFT);
+
+ writel(val, reg_gusb2phyacc0);
+ ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
+ if (ret)
+ return ret;
+
+ /* VCtrl = high nibble of addr, set PHY_NEW_REG_REQ */
+ val = PHY_NEW_REG_REQ | (GET_HIGH_NIBBLE(addr) << PHY_VCTRL_SHIFT);
+
+ writel(val, reg_gusb2phyacc0);
+ ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int rtk_phy_set_page(struct phy_reg *phy_reg, int page)
+{
+ switch (page) {
+ case 0:
+ return rtk_phy_write(phy_reg, SET_PAGE_OFFSET, SET_PAGE_0);
+ case 1:
+ return rtk_phy_write(phy_reg, SET_PAGE_OFFSET, SET_PAGE_1);
+ case 2:
+ return rtk_phy_write(phy_reg, SET_PAGE_OFFSET, SET_PAGE_2);
+ default:
+ pr_err("%s error page=%d\n", __func__, page);
+ }
+
+ return -EINVAL;
+}
+
+static u8 __updated_dc_disconnect_level_page0_0xe4(struct phy_cfg *phy_cfg,
+ struct phy_parameter *phy_parameter, u8 data)
+{
+ u8 ret;
+ s32 val;
+ s32 dc_disconnect_mask = phy_cfg->dc_disconnect_mask;
+ int offset = 4;
+
+ val = (s32)((data >> offset) & dc_disconnect_mask)
+ + phy_parameter->efuse_usb_dc_dis
+ + phy_parameter->disconnection_compensate;
+
+ if (val > dc_disconnect_mask)
+ val = dc_disconnect_mask;
+ else if (val < 0)
+ val = 0;
+
+ ret = (data & (~(dc_disconnect_mask << offset))) |
+ (val & dc_disconnect_mask) << offset;
+
+ return ret;
+}
+
+/* updated disconnect level at page0 */
+static void update_dc_disconnect_level_at_page0(struct rtk_phy *rtk_phy,
+ struct phy_parameter *phy_parameter, bool update)
+{
+ struct phy_cfg *phy_cfg;
+ struct phy_reg *phy_reg;
+ struct phy_data *phy_data_page;
+ struct phy_data *phy_data;
+ u8 addr, data;
+ int offset = 4;
+ s32 dc_disconnect_mask;
+ int i;
+
+ phy_cfg = rtk_phy->phy_cfg;
+ phy_reg = &phy_parameter->phy_reg;
+
+ /* Set page 0 */
+ phy_data_page = phy_cfg->page0;
+ rtk_phy_set_page(phy_reg, 0);
+
+ i = page_addr_to_array_index(PAGE0_0XE4);
+ phy_data = phy_data_page + i;
+ if (!phy_data->addr) {
+ phy_data->addr = PAGE0_0XE4;
+ phy_data->data = rtk_phy_read(phy_reg, PAGE0_0XE4);
+ }
+
+ addr = phy_data->addr;
+ data = phy_data->data;
+ dc_disconnect_mask = phy_cfg->dc_disconnect_mask;
+
+ if (update)
+ data = __updated_dc_disconnect_level_page0_0xe4(phy_cfg, phy_parameter, data);
+ else
+ data = (data & ~(dc_disconnect_mask << offset)) |
+ (DEFAULT_DC_DISCONNECTION_VALUE << offset);
+
+ if (rtk_phy_write(phy_reg, addr, data))
+ dev_err(rtk_phy->dev,
+ "%s: Error to set page1 parameter addr=0x%x value=0x%x\n",
+ __func__, addr, data);
+}
+
+static u8 __updated_dc_disconnect_level_page1_0xe2(struct phy_cfg *phy_cfg,
+ struct phy_parameter *phy_parameter, u8 data)
+{
+ u8 ret;
+ s32 val;
+ s32 dc_disconnect_mask = phy_cfg->dc_disconnect_mask;
+
+ if (phy_cfg->check_efuse_version == CHECK_EFUSE_V1) {
+ val = (s32)(data & dc_disconnect_mask)
+ + phy_parameter->efuse_usb_dc_dis
+ + phy_parameter->disconnection_compensate;
+ } else { /* for CHECK_EFUSE_V2 or no efuse */
+ if (phy_parameter->efuse_usb_dc_dis)
+ val = (s32)(phy_parameter->efuse_usb_dc_dis +
+ phy_parameter->disconnection_compensate);
+ else
+ val = (s32)((data & dc_disconnect_mask) +
+ phy_parameter->disconnection_compensate);
+ }
+
+ if (val > dc_disconnect_mask)
+ val = dc_disconnect_mask;
+ else if (val < 0)
+ val = 0;
+
+ ret = (data & (~dc_disconnect_mask)) | (val & dc_disconnect_mask);
+
+ return ret;
+}
+
+/* updated disconnect level at page1 */
+static void update_dc_disconnect_level_at_page1(struct rtk_phy *rtk_phy,
+ struct phy_parameter *phy_parameter, bool update)
+{
+ struct phy_cfg *phy_cfg;
+ struct phy_data *phy_data_page;
+ struct phy_data *phy_data;
+ struct phy_reg *phy_reg;
+ u8 addr, data;
+ s32 dc_disconnect_mask;
+ int i;
+
+ phy_cfg = rtk_phy->phy_cfg;
+ phy_reg = &phy_parameter->phy_reg;
+
+ /* Set page 1 */
+ phy_data_page = phy_cfg->page1;
+ rtk_phy_set_page(phy_reg, 1);
+
+ i = page_addr_to_array_index(PAGE1_0XE2);
+ phy_data = phy_data_page + i;
+ if (!phy_data->addr) {
+ phy_data->addr = PAGE1_0XE2;
+ phy_data->data = rtk_phy_read(phy_reg, PAGE1_0XE2);
+ }
+
+ addr = phy_data->addr;
+ data = phy_data->data;
+ dc_disconnect_mask = phy_cfg->dc_disconnect_mask;
+
+ if (update)
+ data = __updated_dc_disconnect_level_page1_0xe2(phy_cfg, phy_parameter, data);
+ else
+ data = (data & ~dc_disconnect_mask) | DEFAULT_DC_DISCONNECTION_VALUE;
+
+ if (rtk_phy_write(phy_reg, addr, data))
+ dev_err(rtk_phy->dev,
+ "%s: Error to set page1 parameter addr=0x%x value=0x%x\n",
+ __func__, addr, data);
+}
+
+static void update_dc_disconnect_level(struct rtk_phy *rtk_phy,
+ struct phy_parameter *phy_parameter, bool update)
+{
+ struct phy_cfg *phy_cfg = rtk_phy->phy_cfg;
+
+ if (phy_cfg->usb_dc_disconnect_at_page0)
+ update_dc_disconnect_level_at_page0(rtk_phy, phy_parameter, update);
+ else
+ update_dc_disconnect_level_at_page1(rtk_phy, phy_parameter, update);
+}
+
+static u8 __update_dc_driving_page0_0xe4(struct phy_cfg *phy_cfg,
+ struct phy_parameter *phy_parameter, u8 data)
+{
+ s32 driving_level_compensate = phy_parameter->driving_level_compensate;
+ s32 dc_driving_mask = phy_cfg->dc_driving_mask;
+ s32 val;
+ u8 ret;
+
+ if (phy_cfg->check_efuse_version == CHECK_EFUSE_V1) {
+ val = (s32)(data & dc_driving_mask) + driving_level_compensate
+ + phy_parameter->efuse_usb_dc_cal;
+ } else { /* for CHECK_EFUSE_V2 or no efuse */
+ if (phy_parameter->efuse_usb_dc_cal)
+ val = (s32)((phy_parameter->efuse_usb_dc_cal & dc_driving_mask)
+ + driving_level_compensate);
+ else
+ val = (s32)(data & dc_driving_mask);
+ }
+
+ if (val > dc_driving_mask)
+ val = dc_driving_mask;
+ else if (val < 0)
+ val = 0;
+
+ ret = (data & (~dc_driving_mask)) | (val & dc_driving_mask);
+
+ return ret;
+}
+
+static void update_dc_driving_level(struct rtk_phy *rtk_phy,
+ struct phy_parameter *phy_parameter)
+{
+ struct phy_cfg *phy_cfg;
+ struct phy_reg *phy_reg;
+
+ phy_reg = &phy_parameter->phy_reg;
+ phy_cfg = rtk_phy->phy_cfg;
+ if (!phy_cfg->page0[4].addr) {
+ rtk_phy_set_page(phy_reg, 0);
+ phy_cfg->page0[4].addr = PAGE0_0XE4;
+ phy_cfg->page0[4].data = rtk_phy_read(phy_reg, PAGE0_0XE4);
+ }
+
+ if (phy_parameter->driving_level != DEFAULT_DC_DRIVING_VALUE) {
+ u32 dc_driving_mask;
+ u8 driving_level;
+ u8 data;
+
+ data = phy_cfg->page0[4].data;
+ dc_driving_mask = phy_cfg->dc_driving_mask;
+ driving_level = data & dc_driving_mask;
+
+ dev_dbg(rtk_phy->dev, "%s driving_level=%d => dts driving_level=%d\n",
+ __func__, driving_level, phy_parameter->driving_level);
+
+ phy_cfg->page0[4].data = (data & (~dc_driving_mask)) |
+ (phy_parameter->driving_level & dc_driving_mask);
+ }
+
+ phy_cfg->page0[4].data = __update_dc_driving_page0_0xe4(phy_cfg,
+ phy_parameter,
+ phy_cfg->page0[4].data);
+}
+
+static void update_hs_clk_select(struct rtk_phy *rtk_phy,
+ struct phy_parameter *phy_parameter)
+{
+ struct phy_cfg *phy_cfg;
+ struct phy_reg *phy_reg;
+
+ phy_cfg = rtk_phy->phy_cfg;
+ phy_reg = &phy_parameter->phy_reg;
+
+ if (phy_parameter->inverse_hstx_sync_clock) {
+ if (!phy_cfg->page0[6].addr) {
+ rtk_phy_set_page(phy_reg, 0);
+ phy_cfg->page0[6].addr = PAGE0_0XE6;
+ phy_cfg->page0[6].data = rtk_phy_read(phy_reg, PAGE0_0XE6);
+ }
+
+ phy_cfg->page0[6].data = phy_cfg->page0[6].data | HS_CLK_SELECT;
+ }
+}
+
+static void do_rtk_phy_toggle(struct rtk_phy *rtk_phy,
+ int index, bool connect)
+{
+ struct phy_parameter *phy_parameter;
+ struct phy_cfg *phy_cfg;
+ struct phy_reg *phy_reg;
+ struct phy_data *phy_data_page;
+ u8 addr, data;
+ int i;
+
+ phy_cfg = rtk_phy->phy_cfg;
+ phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
+ phy_reg = &phy_parameter->phy_reg;
+
+ if (!phy_cfg->do_toggle)
+ goto out;
+
+ if (phy_cfg->is_double_sensitivity_mode)
+ goto do_toggle_driving;
+
+ /* Set page 0 */
+ rtk_phy_set_page(phy_reg, 0);
+
+ addr = PAGE0_0XE7;
+ data = rtk_phy_read(phy_reg, addr);
+
+ if (connect)
+ rtk_phy_write(phy_reg, addr, data & (~SENSITIVITY_CTRL));
+ else
+ rtk_phy_write(phy_reg, addr, data | (SENSITIVITY_CTRL));
+
+do_toggle_driving:
+
+ if (!phy_cfg->do_toggle_driving)
+ goto do_toggle;
+
+ /* Page 0 addr 0xE4 driving capability */
+
+ /* Set page 0 */
+ phy_data_page = phy_cfg->page0;
+ rtk_phy_set_page(phy_reg, 0);
+
+ i = page_addr_to_array_index(PAGE0_0XE4);
+ addr = phy_data_page[i].addr;
+ data = phy_data_page[i].data;
+
+ if (connect) {
+ rtk_phy_write(phy_reg, addr, data);
+ } else {
+ u8 value;
+ s32 tmp;
+ s32 driving_updated =
+ phy_cfg->driving_updated_for_dev_dis;
+ s32 dc_driving_mask = phy_cfg->dc_driving_mask;
+
+ tmp = (s32)(data & dc_driving_mask) + driving_updated;
+
+ if (tmp > dc_driving_mask)
+ tmp = dc_driving_mask;
+ else if (tmp < 0)
+ tmp = 0;
+
+ value = (data & (~dc_driving_mask)) | (tmp & dc_driving_mask);
+
+ rtk_phy_write(phy_reg, addr, value);
+ }
+
+do_toggle:
+ /* restore dc disconnect level before toggle */
+ update_dc_disconnect_level(rtk_phy, phy_parameter, false);
+
+ /* Set page 1 */
+ rtk_phy_set_page(phy_reg, 1);
+
+ addr = PAGE1_0XE0;
+ data = rtk_phy_read(phy_reg, addr);
+
+ rtk_phy_write(phy_reg, addr, data &
+ (~ENABLE_AUTO_SENSITIVITY_CALIBRATION));
+ mdelay(1);
+ rtk_phy_write(phy_reg, addr, data |
+ (ENABLE_AUTO_SENSITIVITY_CALIBRATION));
+
+ /* update dc disconnect level after toggle */
+ update_dc_disconnect_level(rtk_phy, phy_parameter, true);
+
+out:
+ return;
+}
+
+static int do_rtk_phy_init(struct rtk_phy *rtk_phy, int index)
+{
+ struct phy_parameter *phy_parameter;
+ struct phy_cfg *phy_cfg;
+ struct phy_data *phy_data_page;
+ struct phy_reg *phy_reg;
+ int i;
+
+ phy_cfg = rtk_phy->phy_cfg;
+ phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
+ phy_reg = &phy_parameter->phy_reg;
+
+ if (phy_cfg->use_default_parameter) {
+ dev_dbg(rtk_phy->dev, "%s phy#%d use default parameter\n",
+ __func__, index);
+ goto do_toggle;
+ }
+
+ /* Set page 0 */
+ phy_data_page = phy_cfg->page0;
+ rtk_phy_set_page(phy_reg, 0);
+
+ for (i = 0; i < phy_cfg->page0_size; i++) {
+ struct phy_data *phy_data = phy_data_page + i;
+ u8 addr = phy_data->addr;
+ u8 data = phy_data->data;
+
+ if (!addr)
+ continue;
+
+ if (rtk_phy_write(phy_reg, addr, data)) {
+ dev_err(rtk_phy->dev,
+ "%s: Error to set page0 parameter addr=0x%x value=0x%x\n",
+ __func__, addr, data);
+ return -EINVAL;
+ }
+ }
+
+ /* Set page 1 */
+ phy_data_page = phy_cfg->page1;
+ rtk_phy_set_page(phy_reg, 1);
+
+ for (i = 0; i < phy_cfg->page1_size; i++) {
+ struct phy_data *phy_data = phy_data_page + i;
+ u8 addr = phy_data->addr;
+ u8 data = phy_data->data;
+
+ if (!addr)
+ continue;
+
+ if (rtk_phy_write(phy_reg, addr, data)) {
+ dev_err(rtk_phy->dev,
+ "%s: Error to set page1 parameter addr=0x%x value=0x%x\n",
+ __func__, addr, data);
+ return -EINVAL;
+ }
+ }
+
+ if (phy_cfg->page2_size == 0)
+ goto do_toggle;
+
+ /* Set page 2 */
+ phy_data_page = phy_cfg->page2;
+ rtk_phy_set_page(phy_reg, 2);
+
+ for (i = 0; i < phy_cfg->page2_size; i++) {
+ struct phy_data *phy_data = phy_data_page + i;
+ u8 addr = phy_data->addr;
+ u8 data = phy_data->data;
+
+ if (!addr)
+ continue;
+
+ if (rtk_phy_write(phy_reg, addr, data)) {
+ dev_err(rtk_phy->dev,
+ "%s: Error to set page2 parameter addr=0x%x value=0x%x\n",
+ __func__, addr, data);
+ return -EINVAL;
+ }
+ }
+
+do_toggle:
+ do_rtk_phy_toggle(rtk_phy, index, false);
+
+ return 0;
+}
+
+static int rtk_phy_init(struct phy *phy)
+{
+ struct rtk_phy *rtk_phy = phy_get_drvdata(phy);
+ unsigned long phy_init_time = jiffies;
+ int i, ret = 0;
+
+ if (!rtk_phy)
+ return -EINVAL;
+
+ for (i = 0; i < rtk_phy->num_phy; i++)
+ ret = do_rtk_phy_init(rtk_phy, i);
+
+ dev_dbg(rtk_phy->dev, "Initialized RTK USB 2.0 PHY (take %dms)\n",
+ jiffies_to_msecs(jiffies - phy_init_time));
+ return ret;
+}
+
+static int rtk_phy_exit(struct phy *phy)
+{
+ return 0;
+}
+
+static void rtk_phy_toggle(struct rtk_phy *rtk_phy, bool connect, int port)
+{
+ int index = port;
+
+ if (index > rtk_phy->num_phy) {
+ dev_err(rtk_phy->dev, "%s: The port=%d is not in usb phy (num_phy=%d)\n",
+ __func__, index, rtk_phy->num_phy);
+ return;
+ }
+
+ do_rtk_phy_toggle(rtk_phy, index, connect);
+}
+
+static int rtk_phy_connect(struct phy *phy, int port)
+{
+ struct rtk_phy *rtk_phy = phy_get_drvdata(phy);
+
+ dev_dbg(rtk_phy->dev, "%s port=%d\n", __func__, port);
+ rtk_phy_toggle(rtk_phy, true, port);
+
+ return 0;
+}
+
+static int rtk_phy_disconnect(struct phy *phy, int port)
+{
+ struct rtk_phy *rtk_phy = phy_get_drvdata(phy);
+
+ dev_dbg(rtk_phy->dev, "%s port=%d\n", __func__, port);
+ rtk_phy_toggle(rtk_phy, false, port);
+
+ return 0;
+}
+
+static const struct phy_ops ops = {
+ .init = rtk_phy_init,
+ .exit = rtk_phy_exit,
+ .connect = rtk_phy_connect,
+ .disconnect = rtk_phy_disconnect,
+ .owner = THIS_MODULE,
+};
+
+#ifdef CONFIG_DEBUG_FS
+static struct dentry *create_phy_debug_root(void)
+{
+ struct dentry *phy_debug_root;
+
+ phy_debug_root = debugfs_lookup("phy", usb_debug_root);
+ if (!phy_debug_root)
+ phy_debug_root = debugfs_create_dir("phy", usb_debug_root);
+
+ return phy_debug_root;
+}
+
+static int rtk_usb2_parameter_show(struct seq_file *s, void *unused)
+{
+ struct rtk_phy *rtk_phy = s->private;
+ struct phy_cfg *phy_cfg;
+ int i, index;
+
+ phy_cfg = rtk_phy->phy_cfg;
+
+ seq_puts(s, "Property:\n");
+ seq_printf(s, " check_efuse: %s\n",
+ phy_cfg->check_efuse ? "Enable" : "Disable");
+ seq_printf(s, " check_efuse_version: %d\n",
+ phy_cfg->check_efuse_version);
+ seq_printf(s, " efuse_dc_driving_rate: %d\n",
+ phy_cfg->efuse_dc_driving_rate);
+ seq_printf(s, " dc_driving_mask: 0x%x\n",
+ phy_cfg->dc_driving_mask);
+ seq_printf(s, " efuse_dc_disconnect_rate: %d\n",
+ phy_cfg->efuse_dc_disconnect_rate);
+ seq_printf(s, " dc_disconnect_mask: 0x%x\n",
+ phy_cfg->dc_disconnect_mask);
+ seq_printf(s, " usb_dc_disconnect_at_page0: %s\n",
+ phy_cfg->usb_dc_disconnect_at_page0 ? "true" : "false");
+ seq_printf(s, " do_toggle: %s\n",
+ phy_cfg->do_toggle ? "Enable" : "Disable");
+ seq_printf(s, " do_toggle_driving: %s\n",
+ phy_cfg->do_toggle_driving ? "Enable" : "Disable");
+ seq_printf(s, " driving_updated_for_dev_dis: 0x%x\n",
+ phy_cfg->driving_updated_for_dev_dis);
+ seq_printf(s, " use_default_parameter: %s\n",
+ phy_cfg->use_default_parameter ? "Enable" : "Disable");
+ seq_printf(s, " is_double_sensitivity_mode: %s\n",
+ phy_cfg->is_double_sensitivity_mode ? "Enable" : "Disable");
+
+ for (index = 0; index < rtk_phy->num_phy; index++) {
+ struct phy_parameter *phy_parameter;
+ struct phy_reg *phy_reg;
+ struct phy_data *phy_data_page;
+
+ phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
+ phy_reg = &phy_parameter->phy_reg;
+
+ seq_printf(s, "PHY %d:\n", index);
+
+ seq_puts(s, "Page 0:\n");
+ /* Set page 0 */
+ phy_data_page = phy_cfg->page0;
+ rtk_phy_set_page(phy_reg, 0);
+
+ for (i = 0; i < phy_cfg->page0_size; i++) {
+ struct phy_data *phy_data = phy_data_page + i;
+ u8 addr = array_index_to_page_addr(i);
+ u8 data = phy_data->data;
+ u8 value = rtk_phy_read(phy_reg, addr);
+
+ if (phy_data->addr)
+ seq_printf(s, " Page 0: addr=0x%x data=0x%02x ==> read value=0x%02x\n",
+ addr, data, value);
+ else
+ seq_printf(s, " Page 0: addr=0x%x data=none ==> read value=0x%02x\n",
+ addr, value);
+ }
+
+ seq_puts(s, "Page 1:\n");
+ /* Set page 1 */
+ phy_data_page = phy_cfg->page1;
+ rtk_phy_set_page(phy_reg, 1);
+
+ for (i = 0; i < phy_cfg->page1_size; i++) {
+ struct phy_data *phy_data = phy_data_page + i;
+ u8 addr = array_index_to_page_addr(i);
+ u8 data = phy_data->data;
+ u8 value = rtk_phy_read(phy_reg, addr);
+
+ if (phy_data->addr)
+ seq_printf(s, " Page 1: addr=0x%x data=0x%02x ==> read value=0x%02x\n",
+ addr, data, value);
+ else
+ seq_printf(s, " Page 1: addr=0x%x data=none ==> read value=0x%02x\n",
+ addr, value);
+ }
+
+ if (phy_cfg->page2_size == 0)
+ goto out;
+
+ seq_puts(s, "Page 2:\n");
+ /* Set page 2 */
+ phy_data_page = phy_cfg->page2;
+ rtk_phy_set_page(phy_reg, 2);
+
+ for (i = 0; i < phy_cfg->page2_size; i++) {
+ struct phy_data *phy_data = phy_data_page + i;
+ u8 addr = array_index_to_page_addr(i);
+ u8 data = phy_data->data;
+ u8 value = rtk_phy_read(phy_reg, addr);
+
+ if (phy_data->addr)
+ seq_printf(s, " Page 2: addr=0x%x data=0x%02x ==> read value=0x%02x\n",
+ addr, data, value);
+ else
+ seq_printf(s, " Page 2: addr=0x%x data=none ==> read value=0x%02x\n",
+ addr, value);
+ }
+
+out:
+ seq_puts(s, "PHY Property:\n");
+ seq_printf(s, " efuse_usb_dc_cal: %d\n",
+ (int)phy_parameter->efuse_usb_dc_cal);
+ seq_printf(s, " efuse_usb_dc_dis: %d\n",
+ (int)phy_parameter->efuse_usb_dc_dis);
+ seq_printf(s, " inverse_hstx_sync_clock: %s\n",
+ phy_parameter->inverse_hstx_sync_clock ? "Enable" : "Disable");
+ seq_printf(s, " driving_level: %d\n",
+ phy_parameter->driving_level);
+ seq_printf(s, " driving_level_compensate: %d\n",
+ phy_parameter->driving_level_compensate);
+ seq_printf(s, " disconnection_compensate: %d\n",
+ phy_parameter->disconnection_compensate);
+ }
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(rtk_usb2_parameter);
+
+static inline void create_debug_files(struct rtk_phy *rtk_phy)
+{
+ struct dentry *phy_debug_root = NULL;
+
+ phy_debug_root = create_phy_debug_root();
+ if (!phy_debug_root)
+ return;
+
+ rtk_phy->debug_dir = debugfs_create_dir(dev_name(rtk_phy->dev),
+ phy_debug_root);
+
+ debugfs_create_file("parameter", 0444, rtk_phy->debug_dir, rtk_phy,
+ &rtk_usb2_parameter_fops);
+}
+
+static inline void remove_debug_files(struct rtk_phy *rtk_phy)
+{
+ debugfs_remove_recursive(rtk_phy->debug_dir);
+}
+#else
+static inline void create_debug_files(struct rtk_phy *rtk_phy) { }
+static inline void remove_debug_files(struct rtk_phy *rtk_phy) { }
+#endif /* CONFIG_DEBUG_FS */
+
+static int get_phy_data_by_efuse(struct rtk_phy *rtk_phy,
+ struct phy_parameter *phy_parameter, int index)
+{
+ struct phy_cfg *phy_cfg = rtk_phy->phy_cfg;
+ u8 value = 0;
+ struct nvmem_cell *cell;
+ struct soc_device_attribute rtk_soc_groot[] = {
+ { .family = "Realtek Groot",},
+ { /* empty */ } };
+
+ if (!phy_cfg->check_efuse)
+ goto out;
+
+ /* Read efuse for usb dc cal */
+ cell = nvmem_cell_get(rtk_phy->dev, "usb-dc-cal");
+ if (IS_ERR(cell)) {
+ dev_dbg(rtk_phy->dev, "%s no usb-dc-cal: %ld\n",
+ __func__, PTR_ERR(cell));
+ } else {
+ unsigned char *buf;
+ size_t buf_size;
+
+ buf = nvmem_cell_read(cell, &buf_size);
+ if (!IS_ERR(buf)) {
+ value = buf[0] & phy_cfg->dc_driving_mask;
+ kfree(buf);
+ }
+ nvmem_cell_put(cell);
+ }
+
+ if (phy_cfg->check_efuse_version == CHECK_EFUSE_V1) {
+ int rate = phy_cfg->efuse_dc_driving_rate;
+
+ if (value <= EFUS_USB_DC_CAL_MAX)
+ phy_parameter->efuse_usb_dc_cal = (int8_t)(value * rate);
+ else
+ phy_parameter->efuse_usb_dc_cal = -(int8_t)
+ ((EFUS_USB_DC_CAL_MAX & value) * rate);
+
+ if (soc_device_match(rtk_soc_groot)) {
+ dev_dbg(rtk_phy->dev, "For groot IC we need a workaround to adjust efuse_usb_dc_cal\n");
+
+ /* We don't multiple dc_cal_rate=2 for positive dc cal compensate */
+ if (value <= EFUS_USB_DC_CAL_MAX)
+ phy_parameter->efuse_usb_dc_cal = (int8_t)(value);
+
+ /* We set max dc cal compensate is 0x8 if otp is 0x7 */
+ if (value == 0x7)
+ phy_parameter->efuse_usb_dc_cal = (int8_t)(value + 1);
+ }
+ } else { /* for CHECK_EFUSE_V2 */
+ phy_parameter->efuse_usb_dc_cal = value & phy_cfg->dc_driving_mask;
+ }
+
+ /* Read efuse for usb dc disconnect level */
+ value = 0;
+ cell = nvmem_cell_get(rtk_phy->dev, "usb-dc-dis");
+ if (IS_ERR(cell)) {
+ dev_dbg(rtk_phy->dev, "%s no usb-dc-dis: %ld\n",
+ __func__, PTR_ERR(cell));
+ } else {
+ unsigned char *buf;
+ size_t buf_size;
+
+ buf = nvmem_cell_read(cell, &buf_size);
+ if (!IS_ERR(buf)) {
+ value = buf[0] & phy_cfg->dc_disconnect_mask;
+ kfree(buf);
+ }
+ nvmem_cell_put(cell);
+ }
+
+ if (phy_cfg->check_efuse_version == CHECK_EFUSE_V1) {
+ int rate = phy_cfg->efuse_dc_disconnect_rate;
+
+ if (value <= EFUS_USB_DC_DIS_MAX)
+ phy_parameter->efuse_usb_dc_dis = (int8_t)(value * rate);
+ else
+ phy_parameter->efuse_usb_dc_dis = -(int8_t)
+ ((EFUS_USB_DC_DIS_MAX & value) * rate);
+ } else { /* for CHECK_EFUSE_V2 */
+ phy_parameter->efuse_usb_dc_dis = value & phy_cfg->dc_disconnect_mask;
+ }
+
+out:
+ return 0;
+}
+
+static int parse_phy_data(struct rtk_phy *rtk_phy)
+{
+ struct device *dev = rtk_phy->dev;
+ struct device_node *np = dev->of_node;
+ struct phy_parameter *phy_parameter;
+ int ret = 0;
+ int index;
+
+ rtk_phy->phy_parameter = devm_kzalloc(dev, sizeof(struct phy_parameter) *
+ rtk_phy->num_phy, GFP_KERNEL);
+ if (!rtk_phy->phy_parameter)
+ return -ENOMEM;
+
+ for (index = 0; index < rtk_phy->num_phy; index++) {
+ phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
+
+ phy_parameter->phy_reg.reg_wrap_vstatus = of_iomap(np, 0);
+ phy_parameter->phy_reg.reg_gusb2phyacc0 = of_iomap(np, 1) + index;
+ phy_parameter->phy_reg.vstatus_index = index;
+
+ if (of_property_read_bool(np, "realtek,inverse-hstx-sync-clock"))
+ phy_parameter->inverse_hstx_sync_clock = true;
+ else
+ phy_parameter->inverse_hstx_sync_clock = false;
+
+ if (of_property_read_u32_index(np, "realtek,driving-level",
+ index, &phy_parameter->driving_level))
+ phy_parameter->driving_level = DEFAULT_DC_DRIVING_VALUE;
+
+ if (of_property_read_u32_index(np, "realtek,driving-level-compensate",
+ index, &phy_parameter->driving_level_compensate))
+ phy_parameter->driving_level_compensate = 0;
+
+ if (of_property_read_u32_index(np, "realtek,disconnection-compensate",
+ index, &phy_parameter->disconnection_compensate))
+ phy_parameter->disconnection_compensate = 0;
+
+ get_phy_data_by_efuse(rtk_phy, phy_parameter, index);
+
+ update_dc_driving_level(rtk_phy, phy_parameter);
+
+ update_hs_clk_select(rtk_phy, phy_parameter);
+ }
+
+ return ret;
+}
+
+static int rtk_usb2phy_probe(struct platform_device *pdev)
+{
+ struct rtk_phy *rtk_phy;
+ struct device *dev = &pdev->dev;
+ struct phy *generic_phy;
+ struct phy_provider *phy_provider;
+ const struct phy_cfg *phy_cfg;
+ int ret = 0;
+
+ phy_cfg = of_device_get_match_data(dev);
+ if (!phy_cfg) {
+ dev_err(dev, "phy config are not assigned!\n");
+ return -EINVAL;
+ }
+
+ rtk_phy = devm_kzalloc(dev, sizeof(*rtk_phy), GFP_KERNEL);
+ if (!rtk_phy)
+ return -ENOMEM;
+
+ rtk_phy->dev = &pdev->dev;
+ rtk_phy->phy_cfg = devm_kzalloc(dev, sizeof(*phy_cfg), GFP_KERNEL);
+ if (!rtk_phy->phy_cfg)
+ return -ENOMEM;
+
+ memcpy(rtk_phy->phy_cfg, phy_cfg, sizeof(*phy_cfg));
+
+ rtk_phy->num_phy = phy_cfg->num_phy;
+
+ ret = parse_phy_data(rtk_phy);
+ if (ret)
+ goto err;
+
+ platform_set_drvdata(pdev, rtk_phy);
+
+ generic_phy = devm_phy_create(rtk_phy->dev, NULL, &ops);
+ if (IS_ERR(generic_phy))
+ return PTR_ERR(generic_phy);
+
+ phy_set_drvdata(generic_phy, rtk_phy);
+
+ phy_provider = devm_of_phy_provider_register(rtk_phy->dev,
+ of_phy_simple_xlate);
+ if (IS_ERR(phy_provider))
+ return PTR_ERR(phy_provider);
+
+ create_debug_files(rtk_phy);
+
+err:
+ return ret;
+}
+
+static void rtk_usb2phy_remove(struct platform_device *pdev)
+{
+ struct rtk_phy *rtk_phy = platform_get_drvdata(pdev);
+
+ remove_debug_files(rtk_phy);
+}
+
+static const struct phy_cfg rtd1295_phy_cfg = {
+ .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
+ .page0 = { [0] = {0xe0, 0x90},
+ [3] = {0xe3, 0x3a},
+ [4] = {0xe4, 0x68},
+ [6] = {0xe6, 0x91},
+ [13] = {0xf5, 0x81},
+ [15] = {0xf7, 0x02}, },
+ .page1_size = 8,
+ .page1 = { /* default parameter */ },
+ .page2_size = 0,
+ .page2 = { /* no parameter */ },
+ .num_phy = 1,
+ .check_efuse = false,
+ .check_efuse_version = CHECK_EFUSE_V1,
+ .efuse_dc_driving_rate = 1,
+ .dc_driving_mask = 0xf,
+ .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
+ .dc_disconnect_mask = 0xf,
+ .usb_dc_disconnect_at_page0 = true,
+ .do_toggle = true,
+ .do_toggle_driving = false,
+ .driving_updated_for_dev_dis = 0xf,
+ .use_default_parameter = false,
+ .is_double_sensitivity_mode = false,
+};
+
+static const struct phy_cfg rtd1395_phy_cfg = {
+ .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
+ .page0 = { [4] = {0xe4, 0xac},
+ [13] = {0xf5, 0x00},
+ [15] = {0xf7, 0x02}, },
+ .page1_size = 8,
+ .page1 = { /* default parameter */ },
+ .page2_size = 0,
+ .page2 = { /* no parameter */ },
+ .num_phy = 1,
+ .check_efuse = false,
+ .check_efuse_version = CHECK_EFUSE_V1,
+ .efuse_dc_driving_rate = 1,
+ .dc_driving_mask = 0xf,
+ .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
+ .dc_disconnect_mask = 0xf,
+ .usb_dc_disconnect_at_page0 = true,
+ .do_toggle = true,
+ .do_toggle_driving = false,
+ .driving_updated_for_dev_dis = 0xf,
+ .use_default_parameter = false,
+ .is_double_sensitivity_mode = false,
+};
+
+static const struct phy_cfg rtd1395_phy_cfg_2port = {
+ .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
+ .page0 = { [4] = {0xe4, 0xac},
+ [13] = {0xf5, 0x00},
+ [15] = {0xf7, 0x02}, },
+ .page1_size = 8,
+ .page1 = { /* default parameter */ },
+ .page2_size = 0,
+ .page2 = { /* no parameter */ },
+ .num_phy = 2,
+ .check_efuse = false,
+ .check_efuse_version = CHECK_EFUSE_V1,
+ .efuse_dc_driving_rate = 1,
+ .dc_driving_mask = 0xf,
+ .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
+ .dc_disconnect_mask = 0xf,
+ .usb_dc_disconnect_at_page0 = true,
+ .do_toggle = true,
+ .do_toggle_driving = false,
+ .driving_updated_for_dev_dis = 0xf,
+ .use_default_parameter = false,
+ .is_double_sensitivity_mode = false,
+};
+
+static const struct phy_cfg rtd1619_phy_cfg = {
+ .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
+ .page0 = { [4] = {0xe4, 0x68}, },
+ .page1_size = 8,
+ .page1 = { /* default parameter */ },
+ .page2_size = 0,
+ .page2 = { /* no parameter */ },
+ .num_phy = 1,
+ .check_efuse = true,
+ .check_efuse_version = CHECK_EFUSE_V1,
+ .efuse_dc_driving_rate = 1,
+ .dc_driving_mask = 0xf,
+ .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
+ .dc_disconnect_mask = 0xf,
+ .usb_dc_disconnect_at_page0 = true,
+ .do_toggle = true,
+ .do_toggle_driving = false,
+ .driving_updated_for_dev_dis = 0xf,
+ .use_default_parameter = false,
+ .is_double_sensitivity_mode = false,
+};
+
+static const struct phy_cfg rtd1319_phy_cfg = {
+ .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
+ .page0 = { [0] = {0xe0, 0x18},
+ [4] = {0xe4, 0x6a},
+ [7] = {0xe7, 0x71},
+ [13] = {0xf5, 0x15},
+ [15] = {0xf7, 0x32}, },
+ .page1_size = 8,
+ .page1 = { [3] = {0xe3, 0x44}, },
+ .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE,
+ .page2 = { [0] = {0xe0, 0x01}, },
+ .num_phy = 1,
+ .check_efuse = true,
+ .check_efuse_version = CHECK_EFUSE_V1,
+ .efuse_dc_driving_rate = 1,
+ .dc_driving_mask = 0xf,
+ .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
+ .dc_disconnect_mask = 0xf,
+ .usb_dc_disconnect_at_page0 = true,
+ .do_toggle = true,
+ .do_toggle_driving = true,
+ .driving_updated_for_dev_dis = 0xf,
+ .use_default_parameter = false,
+ .is_double_sensitivity_mode = true,
+};
+
+static const struct phy_cfg rtd1312c_phy_cfg = {
+ .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
+ .page0 = { [0] = {0xe0, 0x14},
+ [4] = {0xe4, 0x67},
+ [5] = {0xe5, 0x55}, },
+ .page1_size = 8,
+ .page1 = { [3] = {0xe3, 0x23},
+ [6] = {0xe6, 0x58}, },
+ .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE,
+ .page2 = { /* default parameter */ },
+ .num_phy = 1,
+ .check_efuse = true,
+ .check_efuse_version = CHECK_EFUSE_V1,
+ .efuse_dc_driving_rate = 1,
+ .dc_driving_mask = 0xf,
+ .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
+ .dc_disconnect_mask = 0xf,
+ .usb_dc_disconnect_at_page0 = true,
+ .do_toggle = true,
+ .do_toggle_driving = true,
+ .driving_updated_for_dev_dis = 0xf,
+ .use_default_parameter = false,
+ .is_double_sensitivity_mode = true,
+};
+
+static const struct phy_cfg rtd1619b_phy_cfg = {
+ .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
+ .page0 = { [0] = {0xe0, 0xa3},
+ [4] = {0xe4, 0xa8},
+ [5] = {0xe5, 0x4f},
+ [6] = {0xe6, 0x02}, },
+ .page1_size = 8,
+ .page1 = { [3] = {0xe3, 0x64}, },
+ .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE,
+ .page2 = { [7] = {0xe7, 0x45}, },
+ .num_phy = 1,
+ .check_efuse = true,
+ .check_efuse_version = CHECK_EFUSE_V1,
+ .efuse_dc_driving_rate = EFUS_USB_DC_CAL_RATE,
+ .dc_driving_mask = 0x1f,
+ .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
+ .dc_disconnect_mask = 0xf,
+ .usb_dc_disconnect_at_page0 = false,
+ .do_toggle = true,
+ .do_toggle_driving = true,
+ .driving_updated_for_dev_dis = 0x8,
+ .use_default_parameter = false,
+ .is_double_sensitivity_mode = true,
+};
+
+static const struct phy_cfg rtd1319d_phy_cfg = {
+ .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
+ .page0 = { [0] = {0xe0, 0xa3},
+ [4] = {0xe4, 0x8e},
+ [5] = {0xe5, 0x4f},
+ [6] = {0xe6, 0x02}, },
+ .page1_size = MAX_USB_PHY_PAGE1_DATA_SIZE,
+ .page1 = { [14] = {0xf5, 0x1}, },
+ .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE,
+ .page2 = { [7] = {0xe7, 0x44}, },
+ .check_efuse = true,
+ .num_phy = 1,
+ .check_efuse_version = CHECK_EFUSE_V1,
+ .efuse_dc_driving_rate = EFUS_USB_DC_CAL_RATE,
+ .dc_driving_mask = 0x1f,
+ .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
+ .dc_disconnect_mask = 0xf,
+ .usb_dc_disconnect_at_page0 = false,
+ .do_toggle = true,
+ .do_toggle_driving = false,
+ .driving_updated_for_dev_dis = 0x8,
+ .use_default_parameter = false,
+ .is_double_sensitivity_mode = true,
+};
+
+static const struct phy_cfg rtd1315e_phy_cfg = {
+ .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE,
+ .page0 = { [0] = {0xe0, 0xa3},
+ [4] = {0xe4, 0x8c},
+ [5] = {0xe5, 0x4f},
+ [6] = {0xe6, 0x02}, },
+ .page1_size = MAX_USB_PHY_PAGE1_DATA_SIZE,
+ .page1 = { [3] = {0xe3, 0x7f},
+ [14] = {0xf5, 0x01}, },
+ .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE,
+ .page2 = { [7] = {0xe7, 0x44}, },
+ .num_phy = 1,
+ .check_efuse = true,
+ .check_efuse_version = CHECK_EFUSE_V2,
+ .efuse_dc_driving_rate = EFUS_USB_DC_CAL_RATE,
+ .dc_driving_mask = 0x1f,
+ .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE,
+ .dc_disconnect_mask = 0xf,
+ .usb_dc_disconnect_at_page0 = false,
+ .do_toggle = true,
+ .do_toggle_driving = false,
+ .driving_updated_for_dev_dis = 0x8,
+ .use_default_parameter = false,
+ .is_double_sensitivity_mode = true,
+};
+
+static const struct of_device_id usbphy_rtk_dt_match[] = {
+ { .compatible = "realtek,rtd1295-usb2phy", .data = &rtd1295_phy_cfg },
+ { .compatible = "realtek,rtd1312c-usb2phy", .data = &rtd1312c_phy_cfg },
+ { .compatible = "realtek,rtd1315e-usb2phy", .data = &rtd1315e_phy_cfg },
+ { .compatible = "realtek,rtd1319-usb2phy", .data = &rtd1319_phy_cfg },
+ { .compatible = "realtek,rtd1319d-usb2phy", .data = &rtd1319d_phy_cfg },
+ { .compatible = "realtek,rtd1395-usb2phy", .data = &rtd1395_phy_cfg },
+ { .compatible = "realtek,rtd1395-usb2phy-2port", .data = &rtd1395_phy_cfg_2port },
+ { .compatible = "realtek,rtd1619-usb2phy", .data = &rtd1619_phy_cfg },
+ { .compatible = "realtek,rtd1619b-usb2phy", .data = &rtd1619b_phy_cfg },
+ {},
+};
+MODULE_DEVICE_TABLE(of, usbphy_rtk_dt_match);
+
+static struct platform_driver rtk_usb2phy_driver = {
+ .probe = rtk_usb2phy_probe,
+ .remove = rtk_usb2phy_remove,
+ .driver = {
+ .name = "rtk-usb2phy",
+ .of_match_table = usbphy_rtk_dt_match,
+ },
+};
+
+module_platform_driver(rtk_usb2phy_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Stanley Chang <stanley_chang@realtek.com>");
+MODULE_DESCRIPTION("Realtek usb 2.0 phy driver");
diff --git a/drivers/phy/realtek/phy-rtk-usb3.c b/drivers/phy/realtek/phy-rtk-usb3.c
new file mode 100644
index 000000000000..cce453686db2
--- /dev/null
+++ b/drivers/phy/realtek/phy-rtk-usb3.c
@@ -0,0 +1,750 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * phy-rtk-usb3.c RTK usb3.0 phy driver
+ *
+ * copyright (c) 2023 realtek semiconductor corporation
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/debugfs.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/regmap.h>
+#include <linux/sys_soc.h>
+#include <linux/mfd/syscon.h>
+#include <linux/phy/phy.h>
+#include <linux/usb.h>
+
+#define USB_MDIO_CTRL_PHY_BUSY BIT(7)
+#define USB_MDIO_CTRL_PHY_WRITE BIT(0)
+#define USB_MDIO_CTRL_PHY_ADDR_SHIFT 8
+#define USB_MDIO_CTRL_PHY_DATA_SHIFT 16
+
+#define MAX_USB_PHY_DATA_SIZE 0x30
+#define PHY_ADDR_0X09 0x09
+#define PHY_ADDR_0X0B 0x0b
+#define PHY_ADDR_0X0D 0x0d
+#define PHY_ADDR_0X10 0x10
+#define PHY_ADDR_0X1F 0x1f
+#define PHY_ADDR_0X20 0x20
+#define PHY_ADDR_0X21 0x21
+#define PHY_ADDR_0X30 0x30
+
+#define REG_0X09_FORCE_CALIBRATION BIT(9)
+#define REG_0X0B_RX_OFFSET_RANGE_MASK 0xc
+#define REG_0X0D_RX_DEBUG_TEST_EN BIT(6)
+#define REG_0X10_DEBUG_MODE_SETTING 0x3c0
+#define REG_0X10_DEBUG_MODE_SETTING_MASK 0x3f8
+#define REG_0X1F_RX_OFFSET_CODE_MASK 0x1e
+
+#define USB_U3_TX_LFPS_SWING_TRIM_SHIFT 4
+#define USB_U3_TX_LFPS_SWING_TRIM_MASK 0xf
+#define AMPLITUDE_CONTROL_COARSE_MASK 0xff
+#define AMPLITUDE_CONTROL_FINE_MASK 0xffff
+#define AMPLITUDE_CONTROL_COARSE_DEFAULT 0xff
+#define AMPLITUDE_CONTROL_FINE_DEFAULT 0xffff
+
+#define PHY_ADDR_MAP_ARRAY_INDEX(addr) (addr)
+#define ARRAY_INDEX_MAP_PHY_ADDR(index) (index)
+
+struct phy_reg {
+ void __iomem *reg_mdio_ctl;
+};
+
+struct phy_data {
+ u8 addr;
+ u16 data;
+};
+
+struct phy_cfg {
+ int param_size;
+ struct phy_data param[MAX_USB_PHY_DATA_SIZE];
+
+ bool check_efuse;
+ bool do_toggle;
+ bool do_toggle_once;
+ bool use_default_parameter;
+ bool check_rx_front_end_offset;
+};
+
+struct phy_parameter {
+ struct phy_reg phy_reg;
+
+ /* Get from efuse */
+ u8 efuse_usb_u3_tx_lfps_swing_trim;
+
+ /* Get from dts */
+ u32 amplitude_control_coarse;
+ u32 amplitude_control_fine;
+};
+
+struct rtk_phy {
+ struct device *dev;
+
+ struct phy_cfg *phy_cfg;
+ int num_phy;
+ struct phy_parameter *phy_parameter;
+
+ struct dentry *debug_dir;
+};
+
+#define PHY_IO_TIMEOUT_USEC (50000)
+#define PHY_IO_DELAY_US (100)
+
+static inline int utmi_wait_register(void __iomem *reg, u32 mask, u32 result)
+{
+ int ret;
+ unsigned int val;
+
+ ret = read_poll_timeout(readl, val, ((val & mask) == result),
+ PHY_IO_DELAY_US, PHY_IO_TIMEOUT_USEC, false, reg);
+ if (ret) {
+ pr_err("%s can't program USB phy\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int rtk_phy3_wait_vbusy(struct phy_reg *phy_reg)
+{
+ return utmi_wait_register(phy_reg->reg_mdio_ctl, USB_MDIO_CTRL_PHY_BUSY, 0);
+}
+
+static u16 rtk_phy_read(struct phy_reg *phy_reg, char addr)
+{
+ unsigned int tmp;
+ u32 value;
+
+ tmp = (addr << USB_MDIO_CTRL_PHY_ADDR_SHIFT);
+
+ writel(tmp, phy_reg->reg_mdio_ctl);
+
+ rtk_phy3_wait_vbusy(phy_reg);
+
+ value = readl(phy_reg->reg_mdio_ctl);
+ value = value >> USB_MDIO_CTRL_PHY_DATA_SHIFT;
+
+ return (u16)value;
+}
+
+static int rtk_phy_write(struct phy_reg *phy_reg, char addr, u16 data)
+{
+ unsigned int val;
+
+ val = USB_MDIO_CTRL_PHY_WRITE |
+ (addr << USB_MDIO_CTRL_PHY_ADDR_SHIFT) |
+ (data << USB_MDIO_CTRL_PHY_DATA_SHIFT);
+
+ writel(val, phy_reg->reg_mdio_ctl);
+
+ rtk_phy3_wait_vbusy(phy_reg);
+
+ return 0;
+}
+
+static void do_rtk_usb3_phy_toggle(struct rtk_phy *rtk_phy, int index, bool connect)
+{
+ struct phy_cfg *phy_cfg = rtk_phy->phy_cfg;
+ struct phy_reg *phy_reg;
+ struct phy_parameter *phy_parameter;
+ struct phy_data *phy_data;
+ u8 addr;
+ u16 data;
+ int i;
+
+ phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
+ phy_reg = &phy_parameter->phy_reg;
+
+ if (!phy_cfg->do_toggle)
+ return;
+
+ i = PHY_ADDR_MAP_ARRAY_INDEX(PHY_ADDR_0X09);
+ phy_data = phy_cfg->param + i;
+ addr = phy_data->addr;
+ data = phy_data->data;
+
+ if (!addr && !data) {
+ addr = PHY_ADDR_0X09;
+ data = rtk_phy_read(phy_reg, addr);
+ phy_data->addr = addr;
+ phy_data->data = data;
+ }
+
+ rtk_phy_write(phy_reg, addr, data & (~REG_0X09_FORCE_CALIBRATION));
+ mdelay(1);
+ rtk_phy_write(phy_reg, addr, data | REG_0X09_FORCE_CALIBRATION);
+}
+
+static int do_rtk_phy_init(struct rtk_phy *rtk_phy, int index)
+{
+ struct phy_cfg *phy_cfg;
+ struct phy_reg *phy_reg;
+ struct phy_parameter *phy_parameter;
+ int i = 0;
+
+ phy_cfg = rtk_phy->phy_cfg;
+ phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
+ phy_reg = &phy_parameter->phy_reg;
+
+ if (phy_cfg->use_default_parameter)
+ goto do_toggle;
+
+ for (i = 0; i < phy_cfg->param_size; i++) {
+ struct phy_data *phy_data = phy_cfg->param + i;
+ u8 addr = phy_data->addr;
+ u16 data = phy_data->data;
+
+ if (!addr && !data)
+ continue;
+
+ rtk_phy_write(phy_reg, addr, data);
+ }
+
+do_toggle:
+ if (phy_cfg->do_toggle_once)
+ phy_cfg->do_toggle = true;
+
+ do_rtk_usb3_phy_toggle(rtk_phy, index, false);
+
+ if (phy_cfg->do_toggle_once) {
+ u16 check_value = 0;
+ int count = 10;
+ u16 value_0x0d, value_0x10;
+
+ /* Enable Debug mode by set 0x0D and 0x10 */
+ value_0x0d = rtk_phy_read(phy_reg, PHY_ADDR_0X0D);
+ value_0x10 = rtk_phy_read(phy_reg, PHY_ADDR_0X10);
+
+ rtk_phy_write(phy_reg, PHY_ADDR_0X0D,
+ value_0x0d | REG_0X0D_RX_DEBUG_TEST_EN);
+ rtk_phy_write(phy_reg, PHY_ADDR_0X10,
+ (value_0x10 & ~REG_0X10_DEBUG_MODE_SETTING_MASK) |
+ REG_0X10_DEBUG_MODE_SETTING);
+
+ check_value = rtk_phy_read(phy_reg, PHY_ADDR_0X30);
+
+ while (!(check_value & BIT(15))) {
+ check_value = rtk_phy_read(phy_reg, PHY_ADDR_0X30);
+ mdelay(1);
+ if (count-- < 0)
+ break;
+ }
+
+ if (!(check_value & BIT(15)))
+ dev_info(rtk_phy->dev, "toggle fail addr=0x%02x, data=0x%04x\n",
+ PHY_ADDR_0X30, check_value);
+
+ /* Disable Debug mode by set 0x0D and 0x10 to default*/
+ rtk_phy_write(phy_reg, PHY_ADDR_0X0D, value_0x0d);
+ rtk_phy_write(phy_reg, PHY_ADDR_0X10, value_0x10);
+
+ phy_cfg->do_toggle = false;
+ }
+
+ if (phy_cfg->check_rx_front_end_offset) {
+ u16 rx_offset_code, rx_offset_range;
+ u16 code_mask = REG_0X1F_RX_OFFSET_CODE_MASK;
+ u16 range_mask = REG_0X0B_RX_OFFSET_RANGE_MASK;
+ bool do_update = false;
+
+ rx_offset_code = rtk_phy_read(phy_reg, PHY_ADDR_0X1F);
+ if (((rx_offset_code & code_mask) == 0x0) ||
+ ((rx_offset_code & code_mask) == code_mask))
+ do_update = true;
+
+ rx_offset_range = rtk_phy_read(phy_reg, PHY_ADDR_0X0B);
+ if (((rx_offset_range & range_mask) == range_mask) && do_update) {
+ dev_warn(rtk_phy->dev, "Don't update rx_offset_range (rx_offset_code=0x%x, rx_offset_range=0x%x)\n",
+ rx_offset_code, rx_offset_range);
+ do_update = false;
+ }
+
+ if (do_update) {
+ u16 tmp1, tmp2;
+
+ tmp1 = rx_offset_range & (~range_mask);
+ tmp2 = rx_offset_range & range_mask;
+ tmp2 += (1 << 2);
+ rx_offset_range = tmp1 | (tmp2 & range_mask);
+ rtk_phy_write(phy_reg, PHY_ADDR_0X0B, rx_offset_range);
+ goto do_toggle;
+ }
+ }
+
+ return 0;
+}
+
+static int rtk_phy_init(struct phy *phy)
+{
+ struct rtk_phy *rtk_phy = phy_get_drvdata(phy);
+ int ret = 0;
+ int i;
+ unsigned long phy_init_time = jiffies;
+
+ for (i = 0; i < rtk_phy->num_phy; i++)
+ ret = do_rtk_phy_init(rtk_phy, i);
+
+ dev_dbg(rtk_phy->dev, "Initialized RTK USB 3.0 PHY (take %dms)\n",
+ jiffies_to_msecs(jiffies - phy_init_time));
+
+ return ret;
+}
+
+static int rtk_phy_exit(struct phy *phy)
+{
+ return 0;
+}
+
+static void rtk_phy_toggle(struct rtk_phy *rtk_phy, bool connect, int port)
+{
+ int index = port;
+
+ if (index > rtk_phy->num_phy) {
+ dev_err(rtk_phy->dev, "%s: The port=%d is not in usb phy (num_phy=%d)\n",
+ __func__, index, rtk_phy->num_phy);
+ return;
+ }
+
+ do_rtk_usb3_phy_toggle(rtk_phy, index, connect);
+}
+
+static int rtk_phy_connect(struct phy *phy, int port)
+{
+ struct rtk_phy *rtk_phy = phy_get_drvdata(phy);
+
+ dev_dbg(rtk_phy->dev, "%s port=%d\n", __func__, port);
+ rtk_phy_toggle(rtk_phy, true, port);
+
+ return 0;
+}
+
+static int rtk_phy_disconnect(struct phy *phy, int port)
+{
+ struct rtk_phy *rtk_phy = phy_get_drvdata(phy);
+
+ dev_dbg(rtk_phy->dev, "%s port=%d\n", __func__, port);
+ rtk_phy_toggle(rtk_phy, false, port);
+
+ return 0;
+}
+
+static const struct phy_ops ops = {
+ .init = rtk_phy_init,
+ .exit = rtk_phy_exit,
+ .connect = rtk_phy_connect,
+ .disconnect = rtk_phy_disconnect,
+ .owner = THIS_MODULE,
+};
+
+#ifdef CONFIG_DEBUG_FS
+static struct dentry *create_phy_debug_root(void)
+{
+ struct dentry *phy_debug_root;
+
+ phy_debug_root = debugfs_lookup("phy", usb_debug_root);
+ if (!phy_debug_root)
+ phy_debug_root = debugfs_create_dir("phy", usb_debug_root);
+
+ return phy_debug_root;
+}
+
+static int rtk_usb3_parameter_show(struct seq_file *s, void *unused)
+{
+ struct rtk_phy *rtk_phy = s->private;
+ struct phy_cfg *phy_cfg;
+ int i, index;
+
+ phy_cfg = rtk_phy->phy_cfg;
+
+ seq_puts(s, "Property:\n");
+ seq_printf(s, " check_efuse: %s\n",
+ phy_cfg->check_efuse ? "Enable" : "Disable");
+ seq_printf(s, " do_toggle: %s\n",
+ phy_cfg->do_toggle ? "Enable" : "Disable");
+ seq_printf(s, " do_toggle_once: %s\n",
+ phy_cfg->do_toggle_once ? "Enable" : "Disable");
+ seq_printf(s, " use_default_parameter: %s\n",
+ phy_cfg->use_default_parameter ? "Enable" : "Disable");
+
+ for (index = 0; index < rtk_phy->num_phy; index++) {
+ struct phy_reg *phy_reg;
+ struct phy_parameter *phy_parameter;
+
+ phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
+ phy_reg = &phy_parameter->phy_reg;
+
+ seq_printf(s, "PHY %d:\n", index);
+
+ for (i = 0; i < phy_cfg->param_size; i++) {
+ struct phy_data *phy_data = phy_cfg->param + i;
+ u8 addr = ARRAY_INDEX_MAP_PHY_ADDR(i);
+ u16 data = phy_data->data;
+
+ if (!phy_data->addr && !data)
+ seq_printf(s, " addr = 0x%02x, data = none ==> read value = 0x%04x\n",
+ addr, rtk_phy_read(phy_reg, addr));
+ else
+ seq_printf(s, " addr = 0x%02x, data = 0x%04x ==> read value = 0x%04x\n",
+ addr, data, rtk_phy_read(phy_reg, addr));
+ }
+
+ seq_puts(s, "PHY Property:\n");
+ seq_printf(s, " efuse_usb_u3_tx_lfps_swing_trim: 0x%x\n",
+ (int)phy_parameter->efuse_usb_u3_tx_lfps_swing_trim);
+ seq_printf(s, " amplitude_control_coarse: 0x%x\n",
+ (int)phy_parameter->amplitude_control_coarse);
+ seq_printf(s, " amplitude_control_fine: 0x%x\n",
+ (int)phy_parameter->amplitude_control_fine);
+ }
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(rtk_usb3_parameter);
+
+static inline void create_debug_files(struct rtk_phy *rtk_phy)
+{
+ struct dentry *phy_debug_root = NULL;
+
+ phy_debug_root = create_phy_debug_root();
+
+ if (!phy_debug_root)
+ return;
+
+ rtk_phy->debug_dir = debugfs_create_dir(dev_name(rtk_phy->dev), phy_debug_root);
+
+ debugfs_create_file("parameter", 0444, rtk_phy->debug_dir, rtk_phy,
+ &rtk_usb3_parameter_fops);
+}
+
+static inline void remove_debug_files(struct rtk_phy *rtk_phy)
+{
+ debugfs_remove_recursive(rtk_phy->debug_dir);
+}
+#else
+static inline void create_debug_files(struct rtk_phy *rtk_phy) { }
+static inline void remove_debug_files(struct rtk_phy *rtk_phy) { }
+#endif /* CONFIG_DEBUG_FS */
+
+static int get_phy_data_by_efuse(struct rtk_phy *rtk_phy,
+ struct phy_parameter *phy_parameter, int index)
+{
+ struct phy_cfg *phy_cfg = rtk_phy->phy_cfg;
+ u8 value = 0;
+ struct nvmem_cell *cell;
+
+ if (!phy_cfg->check_efuse)
+ goto out;
+
+ cell = nvmem_cell_get(rtk_phy->dev, "usb_u3_tx_lfps_swing_trim");
+ if (IS_ERR(cell)) {
+ dev_dbg(rtk_phy->dev, "%s no usb_u3_tx_lfps_swing_trim: %ld\n",
+ __func__, PTR_ERR(cell));
+ } else {
+ unsigned char *buf;
+ size_t buf_size;
+
+ buf = nvmem_cell_read(cell, &buf_size);
+ if (!IS_ERR(buf)) {
+ value = buf[0] & USB_U3_TX_LFPS_SWING_TRIM_MASK;
+ kfree(buf);
+ }
+ nvmem_cell_put(cell);
+ }
+
+ if (value > 0 && value < 0x8)
+ phy_parameter->efuse_usb_u3_tx_lfps_swing_trim = 0x8;
+ else
+ phy_parameter->efuse_usb_u3_tx_lfps_swing_trim = (u8)value;
+
+out:
+ return 0;
+}
+
+static void update_amplitude_control_value(struct rtk_phy *rtk_phy,
+ struct phy_parameter *phy_parameter)
+{
+ struct phy_cfg *phy_cfg;
+ struct phy_reg *phy_reg;
+
+ phy_reg = &phy_parameter->phy_reg;
+ phy_cfg = rtk_phy->phy_cfg;
+
+ if (phy_parameter->amplitude_control_coarse != AMPLITUDE_CONTROL_COARSE_DEFAULT) {
+ u16 val_mask = AMPLITUDE_CONTROL_COARSE_MASK;
+ u16 data;
+
+ if (!phy_cfg->param[PHY_ADDR_0X20].addr && !phy_cfg->param[PHY_ADDR_0X20].data) {
+ phy_cfg->param[PHY_ADDR_0X20].addr = PHY_ADDR_0X20;
+ data = rtk_phy_read(phy_reg, PHY_ADDR_0X20);
+ } else {
+ data = phy_cfg->param[PHY_ADDR_0X20].data;
+ }
+
+ data &= (~val_mask);
+ data |= (phy_parameter->amplitude_control_coarse & val_mask);
+
+ phy_cfg->param[PHY_ADDR_0X20].data = data;
+ }
+
+ if (phy_parameter->efuse_usb_u3_tx_lfps_swing_trim) {
+ u8 efuse_val = phy_parameter->efuse_usb_u3_tx_lfps_swing_trim;
+ u16 val_mask = USB_U3_TX_LFPS_SWING_TRIM_MASK;
+ int val_shift = USB_U3_TX_LFPS_SWING_TRIM_SHIFT;
+ u16 data;
+
+ if (!phy_cfg->param[PHY_ADDR_0X20].addr && !phy_cfg->param[PHY_ADDR_0X20].data) {
+ phy_cfg->param[PHY_ADDR_0X20].addr = PHY_ADDR_0X20;
+ data = rtk_phy_read(phy_reg, PHY_ADDR_0X20);
+ } else {
+ data = phy_cfg->param[PHY_ADDR_0X20].data;
+ }
+
+ data &= ~(val_mask << val_shift);
+ data |= ((efuse_val & val_mask) << val_shift);
+
+ phy_cfg->param[PHY_ADDR_0X20].data = data;
+ }
+
+ if (phy_parameter->amplitude_control_fine != AMPLITUDE_CONTROL_FINE_DEFAULT) {
+ u16 val_mask = AMPLITUDE_CONTROL_FINE_MASK;
+
+ if (!phy_cfg->param[PHY_ADDR_0X21].addr && !phy_cfg->param[PHY_ADDR_0X21].data)
+ phy_cfg->param[PHY_ADDR_0X21].addr = PHY_ADDR_0X21;
+
+ phy_cfg->param[PHY_ADDR_0X21].data =
+ phy_parameter->amplitude_control_fine & val_mask;
+ }
+}
+
+static int parse_phy_data(struct rtk_phy *rtk_phy)
+{
+ struct device *dev = rtk_phy->dev;
+ struct phy_parameter *phy_parameter;
+ int ret = 0;
+ int index;
+
+ rtk_phy->phy_parameter = devm_kzalloc(dev, sizeof(struct phy_parameter) *
+ rtk_phy->num_phy, GFP_KERNEL);
+ if (!rtk_phy->phy_parameter)
+ return -ENOMEM;
+
+ for (index = 0; index < rtk_phy->num_phy; index++) {
+ phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index];
+
+ phy_parameter->phy_reg.reg_mdio_ctl = of_iomap(dev->of_node, 0) + index;
+
+ /* Amplitude control address 0x20 bit 0 to bit 7 */
+ if (of_property_read_u32(dev->of_node, "realtek,amplitude-control-coarse-tuning",
+ &phy_parameter->amplitude_control_coarse))
+ phy_parameter->amplitude_control_coarse = AMPLITUDE_CONTROL_COARSE_DEFAULT;
+
+ /* Amplitude control address 0x21 bit 0 to bit 16 */
+ if (of_property_read_u32(dev->of_node, "realtek,amplitude-control-fine-tuning",
+ &phy_parameter->amplitude_control_fine))
+ phy_parameter->amplitude_control_fine = AMPLITUDE_CONTROL_FINE_DEFAULT;
+
+ get_phy_data_by_efuse(rtk_phy, phy_parameter, index);
+
+ update_amplitude_control_value(rtk_phy, phy_parameter);
+ }
+
+ return ret;
+}
+
+static int rtk_usb3phy_probe(struct platform_device *pdev)
+{
+ struct rtk_phy *rtk_phy;
+ struct device *dev = &pdev->dev;
+ struct phy *generic_phy;
+ struct phy_provider *phy_provider;
+ const struct phy_cfg *phy_cfg;
+ int ret;
+
+ phy_cfg = of_device_get_match_data(dev);
+ if (!phy_cfg) {
+ dev_err(dev, "phy config are not assigned!\n");
+ return -EINVAL;
+ }
+
+ rtk_phy = devm_kzalloc(dev, sizeof(*rtk_phy), GFP_KERNEL);
+ if (!rtk_phy)
+ return -ENOMEM;
+
+ rtk_phy->dev = &pdev->dev;
+ rtk_phy->phy_cfg = devm_kzalloc(dev, sizeof(*phy_cfg), GFP_KERNEL);
+ if (!rtk_phy->phy_cfg)
+ return -ENOMEM;
+
+ memcpy(rtk_phy->phy_cfg, phy_cfg, sizeof(*phy_cfg));
+
+ rtk_phy->num_phy = 1;
+
+ ret = parse_phy_data(rtk_phy);
+ if (ret)
+ goto err;
+
+ platform_set_drvdata(pdev, rtk_phy);
+
+ generic_phy = devm_phy_create(rtk_phy->dev, NULL, &ops);
+ if (IS_ERR(generic_phy))
+ return PTR_ERR(generic_phy);
+
+ phy_set_drvdata(generic_phy, rtk_phy);
+
+ phy_provider = devm_of_phy_provider_register(rtk_phy->dev, of_phy_simple_xlate);
+ if (IS_ERR(phy_provider))
+ return PTR_ERR(phy_provider);
+
+ create_debug_files(rtk_phy);
+
+err:
+ return ret;
+}
+
+static void rtk_usb3phy_remove(struct platform_device *pdev)
+{
+ struct rtk_phy *rtk_phy = platform_get_drvdata(pdev);
+
+ remove_debug_files(rtk_phy);
+}
+
+static const struct phy_cfg rtd1295_phy_cfg = {
+ .param_size = MAX_USB_PHY_DATA_SIZE,
+ .param = { [0] = {0x01, 0x4008}, [1] = {0x01, 0xe046},
+ [2] = {0x02, 0x6046}, [3] = {0x03, 0x2779},
+ [4] = {0x04, 0x72f5}, [5] = {0x05, 0x2ad3},
+ [6] = {0x06, 0x000e}, [7] = {0x07, 0x2e00},
+ [8] = {0x08, 0x3591}, [9] = {0x09, 0x525c},
+ [10] = {0x0a, 0xa600}, [11] = {0x0b, 0xa904},
+ [12] = {0x0c, 0xc000}, [13] = {0x0d, 0xef1c},
+ [14] = {0x0e, 0x2000}, [15] = {0x0f, 0x0000},
+ [16] = {0x10, 0x000c}, [17] = {0x11, 0x4c00},
+ [18] = {0x12, 0xfc00}, [19] = {0x13, 0x0c81},
+ [20] = {0x14, 0xde01}, [21] = {0x15, 0x0000},
+ [22] = {0x16, 0x0000}, [23] = {0x17, 0x0000},
+ [24] = {0x18, 0x0000}, [25] = {0x19, 0x4004},
+ [26] = {0x1a, 0x1260}, [27] = {0x1b, 0xff00},
+ [28] = {0x1c, 0xcb00}, [29] = {0x1d, 0xa03f},
+ [30] = {0x1e, 0xc2e0}, [31] = {0x1f, 0x2807},
+ [32] = {0x20, 0x947a}, [33] = {0x21, 0x88aa},
+ [34] = {0x22, 0x0057}, [35] = {0x23, 0xab66},
+ [36] = {0x24, 0x0800}, [37] = {0x25, 0x0000},
+ [38] = {0x26, 0x040a}, [39] = {0x27, 0x01d6},
+ [40] = {0x28, 0xf8c2}, [41] = {0x29, 0x3080},
+ [42] = {0x2a, 0x3082}, [43] = {0x2b, 0x2078},
+ [44] = {0x2c, 0xffff}, [45] = {0x2d, 0xffff},
+ [46] = {0x2e, 0x0000}, [47] = {0x2f, 0x0040}, },
+ .check_efuse = false,
+ .do_toggle = true,
+ .do_toggle_once = false,
+ .use_default_parameter = false,
+ .check_rx_front_end_offset = false,
+};
+
+static const struct phy_cfg rtd1619_phy_cfg = {
+ .param_size = MAX_USB_PHY_DATA_SIZE,
+ .param = { [8] = {0x08, 0x3591},
+ [38] = {0x26, 0x840b},
+ [40] = {0x28, 0xf842}, },
+ .check_efuse = false,
+ .do_toggle = true,
+ .do_toggle_once = false,
+ .use_default_parameter = false,
+ .check_rx_front_end_offset = false,
+};
+
+static const struct phy_cfg rtd1319_phy_cfg = {
+ .param_size = MAX_USB_PHY_DATA_SIZE,
+ .param = { [1] = {0x01, 0xac86},
+ [6] = {0x06, 0x0003},
+ [9] = {0x09, 0x924c},
+ [10] = {0x0a, 0xa608},
+ [11] = {0x0b, 0xb905},
+ [14] = {0x0e, 0x2010},
+ [32] = {0x20, 0x705a},
+ [33] = {0x21, 0xf645},
+ [34] = {0x22, 0x0013},
+ [35] = {0x23, 0xcb66},
+ [41] = {0x29, 0xff00}, },
+ .check_efuse = true,
+ .do_toggle = true,
+ .do_toggle_once = false,
+ .use_default_parameter = false,
+ .check_rx_front_end_offset = false,
+};
+
+static const struct phy_cfg rtd1619b_phy_cfg = {
+ .param_size = MAX_USB_PHY_DATA_SIZE,
+ .param = { [1] = {0x01, 0xac8c},
+ [6] = {0x06, 0x0017},
+ [9] = {0x09, 0x724c},
+ [10] = {0x0a, 0xb610},
+ [11] = {0x0b, 0xb90d},
+ [13] = {0x0d, 0xef2a},
+ [15] = {0x0f, 0x9050},
+ [16] = {0x10, 0x000c},
+ [32] = {0x20, 0x70ff},
+ [34] = {0x22, 0x0013},
+ [35] = {0x23, 0xdb66},
+ [38] = {0x26, 0x8609},
+ [41] = {0x29, 0xff13},
+ [42] = {0x2a, 0x3070}, },
+ .check_efuse = true,
+ .do_toggle = false,
+ .do_toggle_once = true,
+ .use_default_parameter = false,
+ .check_rx_front_end_offset = false,
+};
+
+static const struct phy_cfg rtd1319d_phy_cfg = {
+ .param_size = MAX_USB_PHY_DATA_SIZE,
+ .param = { [1] = {0x01, 0xac89},
+ [4] = {0x04, 0xf2f5},
+ [6] = {0x06, 0x0017},
+ [9] = {0x09, 0x424c},
+ [10] = {0x0a, 0x9610},
+ [11] = {0x0b, 0x9901},
+ [12] = {0x0c, 0xf000},
+ [13] = {0x0d, 0xef2a},
+ [14] = {0x0e, 0x1000},
+ [15] = {0x0f, 0x9050},
+ [32] = {0x20, 0x7077},
+ [35] = {0x23, 0x0b62},
+ [37] = {0x25, 0x10ec},
+ [42] = {0x2a, 0x3070}, },
+ .check_efuse = true,
+ .do_toggle = false,
+ .do_toggle_once = true,
+ .use_default_parameter = false,
+ .check_rx_front_end_offset = true,
+};
+
+static const struct of_device_id usbphy_rtk_dt_match[] = {
+ { .compatible = "realtek,rtd1295-usb3phy", .data = &rtd1295_phy_cfg },
+ { .compatible = "realtek,rtd1319-usb3phy", .data = &rtd1319_phy_cfg },
+ { .compatible = "realtek,rtd1319d-usb3phy", .data = &rtd1319d_phy_cfg },
+ { .compatible = "realtek,rtd1619-usb3phy", .data = &rtd1619_phy_cfg },
+ { .compatible = "realtek,rtd1619b-usb3phy", .data = &rtd1619b_phy_cfg },
+ {},
+};
+MODULE_DEVICE_TABLE(of, usbphy_rtk_dt_match);
+
+static struct platform_driver rtk_usb3phy_driver = {
+ .probe = rtk_usb3phy_probe,
+ .remove = rtk_usb3phy_remove,
+ .driver = {
+ .name = "rtk-usb3phy",
+ .of_match_table = usbphy_rtk_dt_match,
+ },
+};
+
+module_platform_driver(rtk_usb3phy_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Stanley Chang <stanley_chang@realtek.com>");
+MODULE_DESCRIPTION("Realtek usb 3.0 phy driver");
diff --git a/drivers/phy/renesas/phy-rcar-gen2.c b/drivers/phy/renesas/phy-rcar-gen2.c
index 507435af2656..c0221e7258c0 100644
--- a/drivers/phy/renesas/phy-rcar-gen2.c
+++ b/drivers/phy/renesas/phy-rcar-gen2.c
@@ -306,7 +306,7 @@ static const struct of_device_id rcar_gen2_phy_match_table[] = {
MODULE_DEVICE_TABLE(of, rcar_gen2_phy_match_table);
static struct phy *rcar_gen2_phy_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct rcar_gen2_phy_driver *drv;
struct device_node *np = args->np;
diff --git a/drivers/phy/renesas/phy-rcar-gen3-pcie.c b/drivers/phy/renesas/phy-rcar-gen3-pcie.c
index 0ce7e9c94444..feca4cb2ff4d 100644
--- a/drivers/phy/renesas/phy-rcar-gen3-pcie.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-pcie.c
@@ -132,11 +132,11 @@ static void rcar_gen3_phy_pcie_remove(struct platform_device *pdev)
static struct platform_driver rcar_gen3_phy_driver = {
.driver = {
- .name = "phy_rcar_gen3_pcie",
- .of_match_table = rcar_gen3_phy_pcie_match_table,
+ .name = "phy_rcar_gen3_pcie",
+ .of_match_table = rcar_gen3_phy_pcie_match_table,
},
- .probe = rcar_gen3_phy_pcie_probe,
- .remove_new = rcar_gen3_phy_pcie_remove,
+ .probe = rcar_gen3_phy_pcie_probe,
+ .remove = rcar_gen3_phy_pcie_remove,
};
module_platform_driver(rcar_gen3_phy_driver);
diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
index 6387c0d34c55..775f4f973a6c 100644
--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
@@ -19,12 +19,14 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
#include <linux/string.h>
#include <linux/usb/of.h>
#include <linux/workqueue.h>
/******* USB2.0 Host registers (original offset is +0x200) *******/
#define USB2_INT_ENABLE 0x000
+#define USB2_AHB_BUS_CTR 0x008
#define USB2_USBCTR 0x00c
#define USB2_SPD_RSM_TIMSET 0x10c
#define USB2_OC_TIMSET 0x110
@@ -40,6 +42,10 @@
#define USB2_INT_ENABLE_USBH_INTB_EN BIT(2) /* For EHCI */
#define USB2_INT_ENABLE_USBH_INTA_EN BIT(1) /* For OHCI */
+/* AHB_BUS_CTR */
+#define USB2_AHB_BUS_CTR_MBL_MASK GENMASK(1, 0)
+#define USB2_AHB_BUS_CTR_MBL_INCR4 2
+
/* USBCTR */
#define USB2_USBCTR_DIRPD BIT(2)
#define USB2_USBCTR_PLL_RST BIT(1)
@@ -111,6 +117,7 @@ struct rcar_gen3_chan {
struct extcon_dev *extcon;
struct rcar_gen3_phy rphys[NUM_OF_PHYS];
struct regulator *vbus;
+ struct reset_control *rstc;
struct work_struct work;
struct mutex lock; /* protects rphys[...].powered */
enum usb_dr_mode dr_mode;
@@ -125,6 +132,7 @@ struct rcar_gen3_chan {
struct rcar_gen3_phy_drv_data {
const struct phy_ops *phy_usb2_ops;
bool no_adp_ctrl;
+ bool init_bus;
};
/*
@@ -188,6 +196,9 @@ static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus)
dev_vdbg(ch->dev, "%s: %08x, %d\n", __func__, val, vbus);
if (ch->soc_no_adp_ctrl) {
+ if (ch->vbus)
+ regulator_hardware_enable(ch->vbus, vbus);
+
vbus_ctrl_reg = USB2_VBCTRL;
vbus_ctrl_val = USB2_VBCTRL_VBOUT;
}
@@ -572,6 +583,12 @@ static const struct rcar_gen3_phy_drv_data rz_g2l_phy_usb2_data = {
.no_adp_ctrl = true,
};
+static const struct rcar_gen3_phy_drv_data rz_g3s_phy_usb2_data = {
+ .phy_usb2_ops = &rcar_gen3_phy_usb2_ops,
+ .no_adp_ctrl = true,
+ .init_bus = true,
+};
+
static const struct of_device_id rcar_gen3_phy_usb2_match_table[] = {
{
.compatible = "renesas,usb2-phy-r8a77470",
@@ -594,6 +611,10 @@ static const struct of_device_id rcar_gen3_phy_usb2_match_table[] = {
.data = &rz_g2l_phy_usb2_data,
},
{
+ .compatible = "renesas,usb2-phy-r9a08g045",
+ .data = &rz_g3s_phy_usb2_data,
+ },
+ {
.compatible = "renesas,rcar-gen3-usb2-phy",
.data = &rcar_gen3_phy_usb2_data,
},
@@ -608,7 +629,7 @@ static const unsigned int rcar_gen3_phy_cable[] = {
};
static struct phy *rcar_gen3_phy_usb2_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct rcar_gen3_chan *ch = dev_get_drvdata(dev);
@@ -647,6 +668,35 @@ static enum usb_dr_mode rcar_gen3_get_dr_mode(struct device_node *np)
return candidate;
}
+static int rcar_gen3_phy_usb2_init_bus(struct rcar_gen3_chan *channel)
+{
+ struct device *dev = channel->dev;
+ int ret;
+ u32 val;
+
+ channel->rstc = devm_reset_control_array_get_shared(dev);
+ if (IS_ERR(channel->rstc))
+ return PTR_ERR(channel->rstc);
+
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret)
+ return ret;
+
+ ret = reset_control_deassert(channel->rstc);
+ if (ret)
+ goto rpm_put;
+
+ val = readl(channel->base + USB2_AHB_BUS_CTR);
+ val &= ~USB2_AHB_BUS_CTR_MBL_MASK;
+ val |= USB2_AHB_BUS_CTR_MBL_INCR4;
+ writel(val, channel->base + USB2_AHB_BUS_CTR);
+
+rpm_put:
+ pm_runtime_put(dev);
+
+ return ret;
+}
+
static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
{
const struct rcar_gen3_phy_drv_data *phy_data;
@@ -700,6 +750,15 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
goto error;
}
+ platform_set_drvdata(pdev, channel);
+ channel->dev = dev;
+
+ if (phy_data->init_bus) {
+ ret = rcar_gen3_phy_usb2_init_bus(channel);
+ if (ret)
+ goto error;
+ }
+
channel->soc_no_adp_ctrl = phy_data->no_adp_ctrl;
if (phy_data->no_adp_ctrl)
channel->obint_enable_bits = USB2_OBINT_IDCHG_EN;
@@ -718,7 +777,10 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
phy_set_drvdata(channel->rphys[i].phy, &channel->rphys[i]);
}
- channel->vbus = devm_regulator_get_optional(dev, "vbus");
+ if (channel->soc_no_adp_ctrl && channel->is_otg_channel)
+ channel->vbus = devm_regulator_get_exclusive(dev, "vbus");
+ else
+ channel->vbus = devm_regulator_get_optional(dev, "vbus");
if (IS_ERR(channel->vbus)) {
if (PTR_ERR(channel->vbus) == -EPROBE_DEFER) {
ret = PTR_ERR(channel->vbus);
@@ -727,9 +789,6 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
channel->vbus = NULL;
}
- platform_set_drvdata(pdev, channel);
- channel->dev = dev;
-
provider = devm_of_phy_provider_register(dev, rcar_gen3_phy_usb2_xlate);
if (IS_ERR(provider)) {
dev_err(dev, "Failed to register PHY provider\n");
@@ -756,6 +815,7 @@ static void rcar_gen3_phy_usb2_remove(struct platform_device *pdev)
if (channel->is_otg_channel)
device_remove_file(&pdev->dev, &dev_attr_role);
+ reset_control_assert(channel->rstc);
pm_runtime_disable(&pdev->dev);
};
@@ -765,7 +825,7 @@ static struct platform_driver rcar_gen3_phy_usb2_driver = {
.of_match_table = rcar_gen3_phy_usb2_match_table,
},
.probe = rcar_gen3_phy_usb2_probe,
- .remove_new = rcar_gen3_phy_usb2_remove,
+ .remove = rcar_gen3_phy_usb2_remove,
};
module_platform_driver(rcar_gen3_phy_usb2_driver);
diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb3.c b/drivers/phy/renesas/phy-rcar-gen3-usb3.c
index e2d630edd992..5c267d148c90 100644
--- a/drivers/phy/renesas/phy-rcar-gen3-usb3.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-usb3.c
@@ -206,11 +206,11 @@ static void rcar_gen3_phy_usb3_remove(struct platform_device *pdev)
static struct platform_driver rcar_gen3_phy_usb3_driver = {
.driver = {
- .name = "phy_rcar_gen3_usb3",
- .of_match_table = rcar_gen3_phy_usb3_match_table,
+ .name = "phy_rcar_gen3_usb3",
+ .of_match_table = rcar_gen3_phy_usb3_match_table,
},
- .probe = rcar_gen3_phy_usb3_probe,
- .remove_new = rcar_gen3_phy_usb3_remove,
+ .probe = rcar_gen3_phy_usb3_probe,
+ .remove = rcar_gen3_phy_usb3_remove,
};
module_platform_driver(rcar_gen3_phy_usb3_driver);
diff --git a/drivers/phy/renesas/r8a779f0-ether-serdes.c b/drivers/phy/renesas/r8a779f0-ether-serdes.c
index fc6e398fa3bf..3b2d8cef75e5 100644
--- a/drivers/phy/renesas/r8a779f0-ether-serdes.c
+++ b/drivers/phy/renesas/r8a779f0-ether-serdes.c
@@ -334,7 +334,7 @@ static const struct phy_ops r8a779f0_eth_serdes_ops = {
};
static struct phy *r8a779f0_eth_serdes_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct r8a779f0_eth_serdes_drv_data *dd = dev_get_drvdata(dev);
@@ -404,7 +404,7 @@ static void r8a779f0_eth_serdes_remove(struct platform_device *pdev)
static struct platform_driver r8a779f0_eth_serdes_driver_platform = {
.probe = r8a779f0_eth_serdes_probe,
- .remove_new = r8a779f0_eth_serdes_remove,
+ .remove = r8a779f0_eth_serdes_remove,
.driver = {
.name = "r8a779f0_eth_serdes",
.of_match_table = r8a779f0_eth_serdes_of_table,
diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig
index 94360fc96a6f..dcb8e1628632 100644
--- a/drivers/phy/rockchip/Kconfig
+++ b/drivers/phy/rockchip/Kconfig
@@ -83,6 +83,18 @@ config PHY_ROCKCHIP_PCIE
help
Enable this to support the Rockchip PCIe PHY.
+config PHY_ROCKCHIP_SAMSUNG_HDPTX
+ tristate "Rockchip Samsung HDMI/eDP Combo PHY driver"
+ depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF
+ depends on COMMON_CLK
+ depends on HAS_IOMEM
+ select GENERIC_PHY
+ select MFD_SYSCON
+ select RATIONAL
+ help
+ Enable this to support the Rockchip HDMI/eDP Combo PHY
+ with Samsung IP block.
+
config PHY_ROCKCHIP_SNPS_PCIE3
tristate "Rockchip Snps PCIe3 PHY Driver"
depends on (ARCH_ROCKCHIP && OF) || COMPILE_TEST
@@ -107,3 +119,16 @@ config PHY_ROCKCHIP_USB
select GENERIC_PHY
help
Enable this to support the Rockchip USB 2.0 PHY.
+
+config PHY_ROCKCHIP_USBDP
+ tristate "Rockchip USBDP COMBO PHY Driver"
+ depends on ARCH_ROCKCHIP && OF
+ depends on TYPEC
+ select GENERIC_PHY
+ select USB_COMMON
+ help
+ Enable this to support the Rockchip USB3.0/DP combo PHY with
+ Samsung IP block. This is required for USB3 support on RK3588.
+
+ To compile this driver as a module, choose M here: the module
+ will be called phy-rockchip-usbdp
diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile
index 7eab129230d1..010a824e32ce 100644
--- a/drivers/phy/rockchip/Makefile
+++ b/drivers/phy/rockchip/Makefile
@@ -8,6 +8,8 @@ obj-$(CONFIG_PHY_ROCKCHIP_INNO_HDMI) += phy-rockchip-inno-hdmi.o
obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.o
obj-$(CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY) += phy-rockchip-naneng-combphy.o
obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o
+obj-$(CONFIG_PHY_ROCKCHIP_SAMSUNG_HDPTX) += phy-rockchip-samsung-hdptx.o
obj-$(CONFIG_PHY_ROCKCHIP_SNPS_PCIE3) += phy-rockchip-snps-pcie3.o
obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o
obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o
+obj-$(CONFIG_PHY_ROCKCHIP_USBDP) += phy-rockchip-usbdp.o
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-csidphy.c b/drivers/phy/rockchip/phy-rockchip-inno-csidphy.c
index 98c92d6c482f..2ab99e1d47eb 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-csidphy.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-csidphy.c
@@ -472,7 +472,7 @@ static struct platform_driver rockchip_inno_csidphy_driver = {
.of_match_table = rockchip_inno_csidphy_match_id,
},
.probe = rockchip_inno_csidphy_probe,
- .remove_new = rockchip_inno_csidphy_remove,
+ .remove = rockchip_inno_csidphy_remove,
};
module_platform_driver(rockchip_inno_csidphy_driver);
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c b/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c
index 6405943a2676..d5b1a4e2f7d3 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c
@@ -784,7 +784,7 @@ static struct platform_driver inno_dsidphy_driver = {
.of_match_table = of_match_ptr(inno_dsidphy_of_match),
},
.probe = inno_dsidphy_probe,
- .remove_new = inno_dsidphy_remove,
+ .remove = inno_dsidphy_remove,
};
module_platform_driver(inno_dsidphy_driver);
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
index 053bd62e31ba..8dcc2bb777b5 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
@@ -1424,8 +1424,8 @@ static const struct of_device_id inno_hdmi_phy_of_match[] = {
MODULE_DEVICE_TABLE(of, inno_hdmi_phy_of_match);
static struct platform_driver inno_hdmi_phy_driver = {
- .probe = inno_hdmi_phy_probe,
- .remove_new = inno_hdmi_phy_remove,
+ .probe = inno_hdmi_phy_probe,
+ .remove = inno_hdmi_phy_remove,
.driver = {
.name = "inno-hdmi-phy",
.of_match_table = inno_hdmi_phy_of_match,
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
index 4f71373ae6e1..96f3d868a526 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
@@ -229,9 +229,10 @@ struct rockchip_usb2phy_port {
* @dev: pointer to device.
* @grf: General Register Files regmap.
* @usbgrf: USB General Register Files regmap.
- * @clk: clock struct of phy input clk.
+ * @clks: array of phy input clocks.
* @clk480m: clock struct of phy output clk.
* @clk480m_hw: clock struct of phy output clk management.
+ * @num_clks: number of phy input clocks.
* @phy_reset: phy reset control.
* @chg_state: states involved in USB charger detection.
* @chg_type: USB charger types.
@@ -246,9 +247,10 @@ struct rockchip_usb2phy {
struct device *dev;
struct regmap *grf;
struct regmap *usbgrf;
- struct clk *clk;
+ struct clk_bulk_data *clks;
struct clk *clk480m;
struct clk_hw clk480m_hw;
+ int num_clks;
struct reset_control *phy_reset;
enum usb_chg_state chg_state;
enum power_supply_type chg_type;
@@ -310,6 +312,13 @@ static int rockchip_usb2phy_reset(struct rockchip_usb2phy *rphy)
return 0;
}
+static void rockchip_usb2phy_clk_bulk_disable(void *data)
+{
+ struct rockchip_usb2phy *rphy = data;
+
+ clk_bulk_disable_unprepare(rphy->num_clks, rphy->clks);
+}
+
static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw)
{
struct rockchip_usb2phy *rphy =
@@ -376,7 +385,9 @@ rockchip_usb2phy_clk480m_register(struct rockchip_usb2phy *rphy)
{
struct device_node *node = rphy->dev->of_node;
struct clk_init_data init;
+ struct clk *refclk = NULL;
const char *clk_name;
+ int i;
int ret = 0;
init.flags = 0;
@@ -386,8 +397,15 @@ rockchip_usb2phy_clk480m_register(struct rockchip_usb2phy *rphy)
/* optional override of the clockname */
of_property_read_string(node, "clock-output-names", &init.name);
- if (rphy->clk) {
- clk_name = __clk_get_name(rphy->clk);
+ for (i = 0; i < rphy->num_clks; i++) {
+ if (!strncmp(rphy->clks[i].id, "phyclk", 6)) {
+ refclk = rphy->clks[i].clk;
+ break;
+ }
+ }
+
+ if (!IS_ERR(refclk)) {
+ clk_name = __clk_get_name(refclk);
init.parent_names = &clk_name;
init.num_parents = 1;
} else {
@@ -418,30 +436,28 @@ err_ret:
static int rockchip_usb2phy_extcon_register(struct rockchip_usb2phy *rphy)
{
- int ret;
struct device_node *node = rphy->dev->of_node;
struct extcon_dev *edev;
+ int ret;
if (of_property_read_bool(node, "extcon")) {
edev = extcon_get_edev_by_phandle(rphy->dev, 0);
- if (IS_ERR(edev)) {
- if (PTR_ERR(edev) != -EPROBE_DEFER)
- dev_err(rphy->dev, "Invalid or missing extcon\n");
- return PTR_ERR(edev);
- }
+ if (IS_ERR(edev))
+ return dev_err_probe(rphy->dev, PTR_ERR(edev),
+ "invalid or missing extcon\n");
} else {
/* Initialize extcon device */
edev = devm_extcon_dev_allocate(rphy->dev,
rockchip_usb2phy_extcon_cable);
if (IS_ERR(edev))
- return -ENOMEM;
+ return dev_err_probe(rphy->dev, PTR_ERR(edev),
+ "failed to allocate extcon device\n");
ret = devm_extcon_dev_register(rphy->dev, edev);
- if (ret) {
- dev_err(rphy->dev, "failed to register extcon device\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(rphy->dev, ret,
+ "failed to register extcon device\n");
}
rphy->edev = edev;
@@ -1327,7 +1343,7 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
struct rockchip_usb2phy *rphy;
const struct rockchip_usb2phy_cfg *phy_cfgs;
unsigned int reg;
- int index, ret;
+ int index = 0, ret;
rphy = devm_kzalloc(dev, sizeof(*rphy), GFP_KERNEL);
if (!rphy)
@@ -1339,9 +1355,7 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
dev_err(dev, "failed to locate usbgrf\n");
return PTR_ERR(rphy->grf);
}
- }
-
- else {
+ } else {
rphy->grf = syscon_node_to_regmap(dev->parent->of_node);
if (IS_ERR(rphy->grf))
return PTR_ERR(rphy->grf);
@@ -1358,16 +1372,14 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
}
if (of_property_read_u32_index(np, "reg", 0, &reg)) {
- dev_err(dev, "the reg property is not assigned in %pOFn node\n",
- np);
+ dev_err(dev, "the reg property is not assigned in %pOFn node\n", np);
return -EINVAL;
}
/* support address_cells=2 */
if (of_property_count_u32_elems(np, "reg") > 2 && reg == 0) {
if (of_property_read_u32_index(np, "reg", 1, &reg)) {
- dev_err(dev, "the reg property is not assigned in %pOFn node\n",
- np);
+ dev_err(dev, "the reg property is not assigned in %pOFn node\n", np);
return -EINVAL;
}
}
@@ -1386,8 +1398,7 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
if (ret)
return ret;
- /* find out a proper config which can be matched with dt. */
- index = 0;
+ /* find a proper config that can be matched with the DT */
do {
if (phy_cfgs[index].reg == reg) {
rphy->phy_cfg = &phy_cfgs[index];
@@ -1406,17 +1417,25 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
if (IS_ERR(rphy->phy_reset))
return PTR_ERR(rphy->phy_reset);
- rphy->clk = devm_clk_get_optional_enabled(dev, "phyclk");
- if (IS_ERR(rphy->clk)) {
- return dev_err_probe(&pdev->dev, PTR_ERR(rphy->clk),
- "failed to get phyclk\n");
- }
+ ret = devm_clk_bulk_get_all(dev, &rphy->clks);
+ if (ret == -EPROBE_DEFER)
+ return dev_err_probe(&pdev->dev, -EPROBE_DEFER,
+ "failed to get phy clock\n");
+
+ /* Clocks are optional */
+ rphy->num_clks = ret < 0 ? 0 : ret;
ret = rockchip_usb2phy_clk480m_register(rphy);
- if (ret) {
- dev_err(dev, "failed to register 480m output clock\n");
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to register 480m output clock\n");
+
+ ret = clk_bulk_prepare_enable(rphy->num_clks, rphy->clks);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to enable phy clock\n");
+
+ ret = devm_add_action_or_reset(dev, rockchip_usb2phy_clk_bulk_disable, rphy);
+ if (ret)
return ret;
- }
if (rphy->phy_cfg->phy_tuning) {
ret = rphy->phy_cfg->phy_tuning(rphy);
@@ -1436,8 +1455,7 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
phy = devm_phy_create(dev, child_np, &rockchip_usb2phy_ops);
if (IS_ERR(phy)) {
- dev_err_probe(dev, PTR_ERR(phy), "failed to create phy\n");
- ret = PTR_ERR(phy);
+ ret = dev_err_probe(dev, PTR_ERR(phy), "failed to create phy\n");
goto put_child;
}
@@ -1446,13 +1464,11 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
/* initialize otg/host port separately */
if (of_node_name_eq(child_np, "host-port")) {
- ret = rockchip_usb2phy_host_port_init(rphy, rport,
- child_np);
+ ret = rockchip_usb2phy_host_port_init(rphy, rport, child_np);
if (ret)
goto put_child;
} else {
- ret = rockchip_usb2phy_otg_port_init(rphy, rport,
- child_np);
+ ret = rockchip_usb2phy_otg_port_init(rphy, rport, child_np);
if (ret)
goto put_child;
}
@@ -1474,8 +1490,7 @@ next_child:
"rockchip_usb2phy",
rphy);
if (ret) {
- dev_err(rphy->dev,
- "failed to request usb2phy irq handle\n");
+ dev_err_probe(rphy->dev, ret, "failed to request usb2phy irq handle\n");
goto put_child;
}
}
@@ -1495,6 +1510,30 @@ static int rk3128_usb2phy_tuning(struct rockchip_usb2phy *rphy)
BIT(2) << BIT_WRITEABLE_SHIFT | 0);
}
+static int rk3576_usb2phy_tuning(struct rockchip_usb2phy *rphy)
+{
+ int ret;
+ u32 reg = rphy->phy_cfg->reg;
+
+ /* Deassert SIDDQ to power on analog block */
+ ret = regmap_write(rphy->grf, reg + 0x0010, GENMASK(29, 29) | 0x0000);
+ if (ret)
+ return ret;
+
+ /* Do reset after exit IDDQ mode */
+ ret = rockchip_usb2phy_reset(rphy);
+ if (ret)
+ return ret;
+
+ /* HS DC Voltage Level Adjustment 4'b1001 : +5.89% */
+ ret |= regmap_write(rphy->grf, reg + 0x000c, GENMASK(27, 24) | 0x0900);
+
+ /* HS Transmitter Pre-Emphasis Current Control 2'b10 : 2x */
+ ret |= regmap_write(rphy->grf, reg + 0x0010, GENMASK(20, 19) | 0x0010);
+
+ return ret;
+}
+
static int rk3588_usb2phy_tuning(struct rockchip_usb2phy *rphy)
{
int ret;
@@ -1923,6 +1962,84 @@ static const struct rockchip_usb2phy_cfg rk3568_phy_cfgs[] = {
{ /* sentinel */ }
};
+static const struct rockchip_usb2phy_cfg rk3576_phy_cfgs[] = {
+ {
+ .reg = 0x0,
+ .num_ports = 1,
+ .phy_tuning = rk3576_usb2phy_tuning,
+ .clkout_ctl = { 0x0008, 0, 0, 1, 0 },
+ .port_cfgs = {
+ [USB2PHY_PORT_OTG] = {
+ .phy_sus = { 0x0000, 8, 0, 0, 0x1d1 },
+ .bvalid_det_en = { 0x00c0, 1, 1, 0, 1 },
+ .bvalid_det_st = { 0x00c4, 1, 1, 0, 1 },
+ .bvalid_det_clr = { 0x00c8, 1, 1, 0, 1 },
+ .ls_det_en = { 0x00c0, 0, 0, 0, 1 },
+ .ls_det_st = { 0x00c4, 0, 0, 0, 1 },
+ .ls_det_clr = { 0x00c8, 0, 0, 0, 1 },
+ .disfall_en = { 0x00c0, 6, 6, 0, 1 },
+ .disfall_st = { 0x00c4, 6, 6, 0, 1 },
+ .disfall_clr = { 0x00c8, 6, 6, 0, 1 },
+ .disrise_en = { 0x00c0, 5, 5, 0, 1 },
+ .disrise_st = { 0x00c4, 5, 5, 0, 1 },
+ .disrise_clr = { 0x00c8, 5, 5, 0, 1 },
+ .utmi_avalid = { 0x0080, 1, 1, 0, 1 },
+ .utmi_bvalid = { 0x0080, 0, 0, 0, 1 },
+ .utmi_ls = { 0x0080, 5, 4, 0, 1 },
+ }
+ },
+ .chg_det = {
+ .cp_det = { 0x0080, 8, 8, 0, 1 },
+ .dcp_det = { 0x0080, 8, 8, 0, 1 },
+ .dp_det = { 0x0080, 9, 9, 1, 0 },
+ .idm_sink_en = { 0x0010, 5, 5, 1, 0 },
+ .idp_sink_en = { 0x0010, 5, 5, 0, 1 },
+ .idp_src_en = { 0x0010, 14, 14, 0, 1 },
+ .rdm_pdwn_en = { 0x0010, 14, 14, 0, 1 },
+ .vdm_src_en = { 0x0010, 7, 6, 0, 3 },
+ .vdp_src_en = { 0x0010, 7, 6, 0, 3 },
+ },
+ },
+ {
+ .reg = 0x2000,
+ .num_ports = 1,
+ .phy_tuning = rk3576_usb2phy_tuning,
+ .clkout_ctl = { 0x2008, 0, 0, 1, 0 },
+ .port_cfgs = {
+ [USB2PHY_PORT_OTG] = {
+ .phy_sus = { 0x2000, 8, 0, 0, 0x1d1 },
+ .bvalid_det_en = { 0x20c0, 1, 1, 0, 1 },
+ .bvalid_det_st = { 0x20c4, 1, 1, 0, 1 },
+ .bvalid_det_clr = { 0x20c8, 1, 1, 0, 1 },
+ .ls_det_en = { 0x20c0, 0, 0, 0, 1 },
+ .ls_det_st = { 0x20c4, 0, 0, 0, 1 },
+ .ls_det_clr = { 0x20c8, 0, 0, 0, 1 },
+ .disfall_en = { 0x20c0, 6, 6, 0, 1 },
+ .disfall_st = { 0x20c4, 6, 6, 0, 1 },
+ .disfall_clr = { 0x20c8, 6, 6, 0, 1 },
+ .disrise_en = { 0x20c0, 5, 5, 0, 1 },
+ .disrise_st = { 0x20c4, 5, 5, 0, 1 },
+ .disrise_clr = { 0x20c8, 5, 5, 0, 1 },
+ .utmi_avalid = { 0x2080, 1, 1, 0, 1 },
+ .utmi_bvalid = { 0x2080, 0, 0, 0, 1 },
+ .utmi_ls = { 0x2080, 5, 4, 0, 1 },
+ }
+ },
+ .chg_det = {
+ .cp_det = { 0x2080, 8, 8, 0, 1 },
+ .dcp_det = { 0x2080, 8, 8, 0, 1 },
+ .dp_det = { 0x2080, 9, 9, 1, 0 },
+ .idm_sink_en = { 0x2010, 5, 5, 1, 0 },
+ .idp_sink_en = { 0x2010, 5, 5, 0, 1 },
+ .idp_src_en = { 0x2010, 14, 14, 0, 1 },
+ .rdm_pdwn_en = { 0x2010, 14, 14, 0, 1 },
+ .vdm_src_en = { 0x2010, 7, 6, 0, 3 },
+ .vdp_src_en = { 0x2010, 7, 6, 0, 3 },
+ },
+ },
+ { /* sentinel */ }
+};
+
static const struct rockchip_usb2phy_cfg rk3588_phy_cfgs[] = {
{
.reg = 0x0000,
@@ -2094,6 +2211,7 @@ static const struct of_device_id rockchip_usb2phy_dt_match[] = {
{ .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs },
{ .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs },
{ .compatible = "rockchip,rk3568-usb2phy", .data = &rk3568_phy_cfgs },
+ { .compatible = "rockchip,rk3576-usb2phy", .data = &rk3576_phy_cfgs },
{ .compatible = "rockchip,rk3588-usb2phy", .data = &rk3588_phy_cfgs },
{ .compatible = "rockchip,rv1108-usb2phy", .data = &rv1108_phy_cfgs },
{}
diff --git a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c
index 5de5e2e97ffa..8c3ce57f8915 100644
--- a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c
+++ b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c
@@ -37,6 +37,10 @@
#define PHYREG8 0x1C
#define PHYREG8_SSC_EN BIT(4)
+#define PHYREG10 0x24
+#define PHYREG10_SSC_PCM_MASK GENMASK(3, 0)
+#define PHYREG10_SSC_PCM_3500PPM 7
+
#define PHYREG11 0x28
#define PHYREG11_SU_TRIM_0_7 0xF0
@@ -61,17 +65,26 @@
#define PHYREG16 0x3C
#define PHYREG16_SSC_CNT_VALUE 0x5f
+#define PHYREG17 0x40
+
#define PHYREG18 0x44
#define PHYREG18_PLL_LOOP 0x32
+#define PHYREG21 0x50
+#define PHYREG21_RX_SQUELCH_VAL 0x0D
+
#define PHYREG27 0x6C
#define PHYREG27_RX_TRIM_RK3588 0x4C
+#define PHYREG30 0x74
+
#define PHYREG32 0x7C
#define PHYREG32_SSC_MASK GENMASK(7, 4)
+#define PHYREG32_SSC_DIR_MASK GENMASK(5, 4)
#define PHYREG32_SSC_DIR_SHIFT 4
#define PHYREG32_SSC_UPWARD 0
#define PHYREG32_SSC_DOWNWARD 1
+#define PHYREG32_SSC_OFFSET_MASK GENMASK(7, 6)
#define PHYREG32_SSC_OFFSET_SHIFT 6
#define PHYREG32_SSC_OFFSET_500PPM 1
@@ -79,6 +92,7 @@
#define PHYREG33_PLL_KVCO_MASK GENMASK(4, 2)
#define PHYREG33_PLL_KVCO_SHIFT 2
#define PHYREG33_PLL_KVCO_VALUE 2
+#define PHYREG33_PLL_KVCO_VALUE_RK3576 4
struct rockchip_combphy_priv;
@@ -98,6 +112,7 @@ struct rockchip_combphy_grfcfg {
struct combphy_reg pipe_rxterm_set;
struct combphy_reg pipe_txelec_set;
struct combphy_reg pipe_txcomp_set;
+ struct combphy_reg pipe_clk_24m;
struct combphy_reg pipe_clk_25m;
struct combphy_reg pipe_clk_100m;
struct combphy_reg pipe_phymode_sel;
@@ -125,12 +140,15 @@ struct rockchip_combphy_grfcfg {
};
struct rockchip_combphy_cfg {
+ unsigned int num_phys;
+ unsigned int phy_ids[3];
const struct rockchip_combphy_grfcfg *grfcfg;
int (*combphy_cfg)(struct rockchip_combphy_priv *priv);
};
struct rockchip_combphy_priv {
u8 type;
+ int id;
void __iomem *mmio;
int num_clks;
struct clk_bulk_data *clks;
@@ -245,13 +263,13 @@ static int rockchip_combphy_exit(struct phy *phy)
return 0;
}
-static const struct phy_ops rochchip_combphy_ops = {
+static const struct phy_ops rockchip_combphy_ops = {
.init = rockchip_combphy_init,
.exit = rockchip_combphy_exit,
.owner = THIS_MODULE,
};
-static struct phy *rockchip_combphy_xlate(struct device *dev, struct of_phandle_args *args)
+static struct phy *rockchip_combphy_xlate(struct device *dev, const struct of_phandle_args *args)
{
struct rockchip_combphy_priv *priv = dev_get_drvdata(dev);
@@ -306,7 +324,10 @@ static int rockchip_combphy_parse_dt(struct device *dev, struct rockchip_combphy
priv->ext_refclk = device_property_present(dev, "rockchip,ext-refclk");
- priv->phy_rst = devm_reset_control_array_get_exclusive(dev);
+ priv->phy_rst = devm_reset_control_get_exclusive(dev, "phy");
+ /* fallback to old behaviour */
+ if (PTR_ERR(priv->phy_rst) == -ENOENT)
+ priv->phy_rst = devm_reset_control_array_get_exclusive(dev);
if (IS_ERR(priv->phy_rst))
return dev_err_probe(dev, PTR_ERR(priv->phy_rst), "failed to get phy reset\n");
@@ -320,7 +341,7 @@ static int rockchip_combphy_probe(struct platform_device *pdev)
struct rockchip_combphy_priv *priv;
const struct rockchip_combphy_cfg *phy_cfg;
struct resource *res;
- int ret;
+ int ret, id;
phy_cfg = of_device_get_match_data(dev);
if (!phy_cfg) {
@@ -338,6 +359,15 @@ static int rockchip_combphy_probe(struct platform_device *pdev)
return ret;
}
+ /* find the phy-id from the io address */
+ priv->id = -ENODEV;
+ for (id = 0; id < phy_cfg->num_phys; id++) {
+ if (res->start == phy_cfg->phy_ids[id]) {
+ priv->id = id;
+ break;
+ }
+ }
+
priv->dev = dev;
priv->type = PHY_NONE;
priv->cfg = phy_cfg;
@@ -352,7 +382,7 @@ static int rockchip_combphy_probe(struct platform_device *pdev)
return ret;
}
- priv->phy = devm_phy_create(dev, NULL, &rochchip_combphy_ops);
+ priv->phy = devm_phy_create(dev, NULL, &rockchip_combphy_ops);
if (IS_ERR(priv->phy)) {
dev_err(dev, "failed to create combphy\n");
return PTR_ERR(priv->phy);
@@ -562,10 +592,276 @@ static const struct rockchip_combphy_grfcfg rk3568_combphy_grfcfgs = {
};
static const struct rockchip_combphy_cfg rk3568_combphy_cfgs = {
+ .num_phys = 3,
+ .phy_ids = {
+ 0xfe820000,
+ 0xfe830000,
+ 0xfe840000,
+ },
.grfcfg = &rk3568_combphy_grfcfgs,
.combphy_cfg = rk3568_combphy_cfg,
};
+static int rk3576_combphy_cfg(struct rockchip_combphy_priv *priv)
+{
+ const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
+ unsigned long rate;
+ u32 val;
+
+ switch (priv->type) {
+ case PHY_TYPE_PCIE:
+ /* Set SSC downward spread spectrum */
+ val = FIELD_PREP(PHYREG32_SSC_MASK, PHYREG32_SSC_DOWNWARD);
+ rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, val, PHYREG32);
+
+ rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_pcie, true);
+ rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_pcie, true);
+ rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_pcie, true);
+ rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_pcie, true);
+ break;
+
+ case PHY_TYPE_USB3:
+ /* Set SSC downward spread spectrum */
+ val = FIELD_PREP(PHYREG32_SSC_MASK, PHYREG32_SSC_DOWNWARD);
+ rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, val, PHYREG32);
+
+ /* Enable adaptive CTLE for USB3.0 Rx */
+ val = readl(priv->mmio + PHYREG15);
+ val |= PHYREG15_CTLE_EN;
+ writel(val, priv->mmio + PHYREG15);
+
+ /* Set PLL KVCO fine tuning signals */
+ rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK, BIT(3), PHYREG33);
+
+ /* Set PLL LPF R1 to su_trim[10:7]=1001 */
+ writel(PHYREG12_PLL_LPF_ADJ_VALUE, priv->mmio + PHYREG12);
+
+ /* Set PLL input clock divider 1/2 */
+ val = FIELD_PREP(PHYREG6_PLL_DIV_MASK, PHYREG6_PLL_DIV_2);
+ rockchip_combphy_updatel(priv, PHYREG6_PLL_DIV_MASK, val, PHYREG6);
+
+ /* Set PLL loop divider */
+ writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18);
+
+ /* Set PLL KVCO to min and set PLL charge pump current to max */
+ writel(PHYREG11_SU_TRIM_0_7, priv->mmio + PHYREG11);
+
+ /* Set Rx squelch input filler bandwidth */
+ writel(PHYREG21_RX_SQUELCH_VAL, priv->mmio + PHYREG21);
+
+ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false);
+ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false);
+ rockchip_combphy_param_write(priv->phy_grf, &cfg->usb_mode_set, true);
+ break;
+
+ case PHY_TYPE_SATA:
+ /* Enable adaptive CTLE for SATA Rx */
+ val = readl(priv->mmio + PHYREG15);
+ val |= PHYREG15_CTLE_EN;
+ writel(val, priv->mmio + PHYREG15);
+
+ /* Set tx_rterm = 50 ohm and rx_rterm = 43.5 ohm */
+ val = PHYREG7_TX_RTERM_50OHM << PHYREG7_TX_RTERM_SHIFT;
+ val |= PHYREG7_RX_RTERM_44OHM << PHYREG7_RX_RTERM_SHIFT;
+ writel(val, priv->mmio + PHYREG7);
+
+ rockchip_combphy_param_write(priv->phy_grf, &cfg->con0_for_sata, true);
+ rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_sata, true);
+ rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_sata, true);
+ rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_sata, true);
+ rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true);
+ rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_con1_for_sata, true);
+ break;
+
+ default:
+ dev_err(priv->dev, "incompatible PHY type\n");
+ return -EINVAL;
+ }
+
+ rate = clk_get_rate(priv->refclk);
+
+ switch (rate) {
+ case REF_CLOCK_24MHz:
+ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_24m, true);
+ if (priv->type == PHY_TYPE_USB3 || priv->type == PHY_TYPE_SATA) {
+ /* Set ssc_cnt[9:0]=0101111101 & 31.5KHz */
+ val = FIELD_PREP(PHYREG15_SSC_CNT_MASK, PHYREG15_SSC_CNT_VALUE);
+ rockchip_combphy_updatel(priv, PHYREG15_SSC_CNT_MASK,
+ val, PHYREG15);
+
+ writel(PHYREG16_SSC_CNT_VALUE, priv->mmio + PHYREG16);
+ } else if (priv->type == PHY_TYPE_PCIE) {
+ /* PLL KVCO tuning fine */
+ val = FIELD_PREP(PHYREG33_PLL_KVCO_MASK, PHYREG33_PLL_KVCO_VALUE_RK3576);
+ rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK,
+ val, PHYREG33);
+
+ /* Set up rx_pck invert and rx msb to disable */
+ writel(0x00, priv->mmio + PHYREG27);
+
+ /*
+ * Set up SU adjust signal:
+ * su_trim[7:0], PLL KVCO adjust bits[2:0] to min
+ * su_trim[15:8], PLL LPF R1 adujst bits[9:7]=3'b011
+ * su_trim[31:24], CKDRV adjust
+ */
+ writel(0x90, priv->mmio + PHYREG11);
+ writel(0x02, priv->mmio + PHYREG12);
+ writel(0x57, priv->mmio + PHYREG14);
+
+ writel(PHYREG16_SSC_CNT_VALUE, priv->mmio + PHYREG16);
+ }
+ break;
+
+ case REF_CLOCK_25MHz:
+ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_25m, true);
+ break;
+
+ case REF_CLOCK_100MHz:
+ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_100m, true);
+ if (priv->type == PHY_TYPE_PCIE) {
+ /* gate_tx_pck_sel length select work for L1SS */
+ writel(0xc0, priv->mmio + PHYREG30);
+
+ /* PLL KVCO tuning fine */
+ val = FIELD_PREP(PHYREG33_PLL_KVCO_MASK, PHYREG33_PLL_KVCO_VALUE_RK3576);
+ rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK,
+ val, PHYREG33);
+
+ /* Set up rx_trim: PLL LPF C1 85pf R1 1.25kohm */
+ writel(0x4c, priv->mmio + PHYREG27);
+
+ /*
+ * Set up SU adjust signal:
+ * su_trim[7:0], PLL KVCO adjust bits[2:0] to min
+ * su_trim[15:8], bypass PLL loop divider code, and
+ * PLL LPF R1 adujst bits[9:7]=3'b101
+ * su_trim[23:16], CKRCV adjust
+ * su_trim[31:24], CKDRV adjust
+ */
+ writel(0x90, priv->mmio + PHYREG11);
+ writel(0x43, priv->mmio + PHYREG12);
+ writel(0x88, priv->mmio + PHYREG13);
+ writel(0x56, priv->mmio + PHYREG14);
+ } else if (priv->type == PHY_TYPE_SATA) {
+ /* downward spread spectrum +500ppm */
+ val = FIELD_PREP(PHYREG32_SSC_DIR_MASK, PHYREG32_SSC_DOWNWARD);
+ val |= FIELD_PREP(PHYREG32_SSC_OFFSET_MASK, PHYREG32_SSC_OFFSET_500PPM);
+ rockchip_combphy_updatel(priv, PHYREG32_SSC_MASK, val, PHYREG32);
+
+ /* ssc ppm adjust to 3500ppm */
+ rockchip_combphy_updatel(priv, PHYREG10_SSC_PCM_MASK,
+ PHYREG10_SSC_PCM_3500PPM,
+ PHYREG10);
+ }
+ break;
+
+ default:
+ dev_err(priv->dev, "Unsupported rate: %lu\n", rate);
+ return -EINVAL;
+ }
+
+ if (priv->ext_refclk) {
+ rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_clk_ext, true);
+ if (priv->type == PHY_TYPE_PCIE && rate == REF_CLOCK_100MHz) {
+ val = FIELD_PREP(PHYREG33_PLL_KVCO_MASK, PHYREG33_PLL_KVCO_VALUE_RK3576);
+ rockchip_combphy_updatel(priv, PHYREG33_PLL_KVCO_MASK,
+ val, PHYREG33);
+
+ /* Set up rx_trim: PLL LPF C1 85pf R1 2.5kohm */
+ writel(0x0c, priv->mmio + PHYREG27);
+
+ /*
+ * Set up SU adjust signal:
+ * su_trim[7:0], PLL KVCO adjust bits[2:0] to min
+ * su_trim[15:8], bypass PLL loop divider code, and
+ * PLL LPF R1 adujst bits[9:7]=3'b101.
+ * su_trim[23:16], CKRCV adjust
+ * su_trim[31:24], CKDRV adjust
+ */
+ writel(0x90, priv->mmio + PHYREG11);
+ writel(0x43, priv->mmio + PHYREG12);
+ writel(0x88, priv->mmio + PHYREG13);
+ writel(0x56, priv->mmio + PHYREG14);
+ }
+ }
+
+ if (priv->enable_ssc) {
+ val = readl(priv->mmio + PHYREG8);
+ val |= PHYREG8_SSC_EN;
+ writel(val, priv->mmio + PHYREG8);
+
+ if (priv->type == PHY_TYPE_PCIE && rate == REF_CLOCK_24MHz) {
+ /* Set PLL loop divider */
+ writel(0x00, priv->mmio + PHYREG17);
+ writel(PHYREG18_PLL_LOOP, priv->mmio + PHYREG18);
+
+ /* Set up rx_pck invert and rx msb to disable */
+ writel(0x00, priv->mmio + PHYREG27);
+
+ /*
+ * Set up SU adjust signal:
+ * su_trim[7:0], PLL KVCO adjust bits[2:0] to min
+ * su_trim[15:8], PLL LPF R1 adujst bits[9:7]=3'b101
+ * su_trim[23:16], CKRCV adjust
+ * su_trim[31:24], CKDRV adjust
+ */
+ writel(0x90, priv->mmio + PHYREG11);
+ writel(0x02, priv->mmio + PHYREG12);
+ writel(0x08, priv->mmio + PHYREG13);
+ writel(0x57, priv->mmio + PHYREG14);
+ writel(0x40, priv->mmio + PHYREG15);
+
+ writel(PHYREG16_SSC_CNT_VALUE, priv->mmio + PHYREG16);
+
+ val = FIELD_PREP(PHYREG33_PLL_KVCO_MASK, PHYREG33_PLL_KVCO_VALUE_RK3576);
+ writel(val, priv->mmio + PHYREG33);
+ }
+ }
+
+ return 0;
+}
+
+static const struct rockchip_combphy_grfcfg rk3576_combphy_grfcfgs = {
+ /* pipe-phy-grf */
+ .pcie_mode_set = { 0x0000, 5, 0, 0x00, 0x11 },
+ .usb_mode_set = { 0x0000, 5, 0, 0x00, 0x04 },
+ .pipe_rxterm_set = { 0x0000, 12, 12, 0x00, 0x01 },
+ .pipe_txelec_set = { 0x0004, 1, 1, 0x00, 0x01 },
+ .pipe_txcomp_set = { 0x0004, 4, 4, 0x00, 0x01 },
+ .pipe_clk_24m = { 0x0004, 14, 13, 0x00, 0x00 },
+ .pipe_clk_25m = { 0x0004, 14, 13, 0x00, 0x01 },
+ .pipe_clk_100m = { 0x0004, 14, 13, 0x00, 0x02 },
+ .pipe_phymode_sel = { 0x0008, 1, 1, 0x00, 0x01 },
+ .pipe_rate_sel = { 0x0008, 2, 2, 0x00, 0x01 },
+ .pipe_rxterm_sel = { 0x0008, 8, 8, 0x00, 0x01 },
+ .pipe_txelec_sel = { 0x0008, 12, 12, 0x00, 0x01 },
+ .pipe_txcomp_sel = { 0x0008, 15, 15, 0x00, 0x01 },
+ .pipe_clk_ext = { 0x000c, 9, 8, 0x02, 0x01 },
+ .pipe_phy_status = { 0x0034, 6, 6, 0x01, 0x00 },
+ .con0_for_pcie = { 0x0000, 15, 0, 0x00, 0x1000 },
+ .con1_for_pcie = { 0x0004, 15, 0, 0x00, 0x0000 },
+ .con2_for_pcie = { 0x0008, 15, 0, 0x00, 0x0101 },
+ .con3_for_pcie = { 0x000c, 15, 0, 0x00, 0x0200 },
+ .con0_for_sata = { 0x0000, 15, 0, 0x00, 0x0129 },
+ .con1_for_sata = { 0x0004, 15, 0, 0x00, 0x0000 },
+ .con2_for_sata = { 0x0008, 15, 0, 0x00, 0x80c1 },
+ .con3_for_sata = { 0x000c, 15, 0, 0x00, 0x0407 },
+ /* php-grf */
+ .pipe_con0_for_sata = { 0x001C, 2, 0, 0x00, 0x2 },
+ .pipe_con1_for_sata = { 0x0020, 2, 0, 0x00, 0x2 },
+};
+
+static const struct rockchip_combphy_cfg rk3576_combphy_cfgs = {
+ .num_phys = 2,
+ .phy_ids = {
+ 0x2b050000,
+ 0x2b060000
+ },
+ .grfcfg = &rk3576_combphy_grfcfgs,
+ .combphy_cfg = rk3576_combphy_cfg,
+};
+
static int rk3588_combphy_cfg(struct rockchip_combphy_priv *priv)
{
const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg;
@@ -578,8 +874,14 @@ static int rk3588_combphy_cfg(struct rockchip_combphy_priv *priv)
rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_pcie, true);
rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_pcie, true);
rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_pcie, true);
- rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_pcie1l0_sel, true);
- rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_pcie1l1_sel, true);
+ switch (priv->id) {
+ case 1:
+ rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_pcie1l0_sel, true);
+ break;
+ case 2:
+ rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_pcie1l1_sel, true);
+ break;
+ }
break;
case PHY_TYPE_USB3:
/* Set SSC downward spread spectrum */
@@ -736,6 +1038,12 @@ static const struct rockchip_combphy_grfcfg rk3588_combphy_grfcfgs = {
};
static const struct rockchip_combphy_cfg rk3588_combphy_cfgs = {
+ .num_phys = 3,
+ .phy_ids = {
+ 0xfee00000,
+ 0xfee10000,
+ 0xfee20000,
+ },
.grfcfg = &rk3588_combphy_grfcfgs,
.combphy_cfg = rk3588_combphy_cfg,
};
@@ -746,6 +1054,10 @@ static const struct of_device_id rockchip_combphy_of_match[] = {
.data = &rk3568_combphy_cfgs,
},
{
+ .compatible = "rockchip,rk3576-naneng-combphy",
+ .data = &rk3576_combphy_cfgs,
+ },
+ {
.compatible = "rockchip,rk3588-naneng-combphy",
.data = &rk3588_combphy_cfgs,
},
diff --git a/drivers/phy/rockchip/phy-rockchip-pcie.c b/drivers/phy/rockchip/phy-rockchip-pcie.c
index 1bbd6be2a584..bd44af36c67a 100644
--- a/drivers/phy/rockchip/phy-rockchip-pcie.c
+++ b/drivers/phy/rockchip/phy-rockchip-pcie.c
@@ -82,7 +82,7 @@ static struct rockchip_pcie_phy *to_pcie_phy(struct phy_pcie_instance *inst)
}
static struct phy *rockchip_pcie_phy_of_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct rockchip_pcie_phy *rk_phy = dev_get_drvdata(dev);
@@ -124,7 +124,7 @@ static int rockchip_pcie_phy_power_off(struct phy *phy)
struct rockchip_pcie_phy *rk_phy = to_pcie_phy(inst);
int err = 0;
- mutex_lock(&rk_phy->pcie_mutex);
+ guard(mutex)(&rk_phy->pcie_mutex);
regmap_write(rk_phy->reg_base,
rk_phy->phy_data->pcie_laneoff,
@@ -132,27 +132,22 @@ static int rockchip_pcie_phy_power_off(struct phy *phy)
PHY_LANE_IDLE_MASK,
PHY_LANE_IDLE_A_SHIFT + inst->index));
- if (--rk_phy->pwr_cnt)
- goto err_out;
+ if (--rk_phy->pwr_cnt) {
+ return 0;
+ }
err = reset_control_assert(rk_phy->phy_rst);
if (err) {
dev_err(&phy->dev, "assert phy_rst err %d\n", err);
- goto err_restore;
+ rk_phy->pwr_cnt++;
+ regmap_write(rk_phy->reg_base,
+ rk_phy->phy_data->pcie_laneoff,
+ HIWORD_UPDATE(!PHY_LANE_IDLE_OFF,
+ PHY_LANE_IDLE_MASK,
+ PHY_LANE_IDLE_A_SHIFT + inst->index));
+ return err;
}
-err_out:
- mutex_unlock(&rk_phy->pcie_mutex);
- return 0;
-
-err_restore:
- rk_phy->pwr_cnt++;
- regmap_write(rk_phy->reg_base,
- rk_phy->phy_data->pcie_laneoff,
- HIWORD_UPDATE(!PHY_LANE_IDLE_OFF,
- PHY_LANE_IDLE_MASK,
- PHY_LANE_IDLE_A_SHIFT + inst->index));
- mutex_unlock(&rk_phy->pcie_mutex);
return err;
}
@@ -162,17 +157,18 @@ static int rockchip_pcie_phy_power_on(struct phy *phy)
struct rockchip_pcie_phy *rk_phy = to_pcie_phy(inst);
int err = 0;
u32 status;
- unsigned long timeout;
- mutex_lock(&rk_phy->pcie_mutex);
+ guard(mutex)(&rk_phy->pcie_mutex);
- if (rk_phy->pwr_cnt++)
- goto err_out;
+ if (rk_phy->pwr_cnt++) {
+ return 0;
+ }
err = reset_control_deassert(rk_phy->phy_rst);
if (err) {
dev_err(&phy->dev, "deassert phy_rst err %d\n", err);
- goto err_pwr_cnt;
+ rk_phy->pwr_cnt--;
+ return err;
}
regmap_write(rk_phy->reg_base, rk_phy->phy_data->pcie_conf,
@@ -191,21 +187,11 @@ static int rockchip_pcie_phy_power_on(struct phy *phy)
* so we make it large enough here. And we use loop-break
* method which should not be harmful.
*/
- timeout = jiffies + msecs_to_jiffies(1000);
-
- err = -EINVAL;
- while (time_before(jiffies, timeout)) {
- regmap_read(rk_phy->reg_base,
- rk_phy->phy_data->pcie_status,
- &status);
- if (status & PHY_PLL_LOCKED) {
- dev_dbg(&phy->dev, "pll locked!\n");
- err = 0;
- break;
- }
- msleep(20);
- }
-
+ err = regmap_read_poll_timeout(rk_phy->reg_base,
+ rk_phy->phy_data->pcie_status,
+ status,
+ status & PHY_PLL_LOCKED,
+ 200, 100000);
if (err) {
dev_err(&phy->dev, "pll lock timeout!\n");
goto err_pll_lock;
@@ -214,19 +200,11 @@ static int rockchip_pcie_phy_power_on(struct phy *phy)
phy_wr_cfg(rk_phy, PHY_CFG_CLK_TEST, PHY_CFG_SEPE_RATE);
phy_wr_cfg(rk_phy, PHY_CFG_CLK_SCC, PHY_CFG_PLL_100M);
- err = -ETIMEDOUT;
- while (time_before(jiffies, timeout)) {
- regmap_read(rk_phy->reg_base,
- rk_phy->phy_data->pcie_status,
- &status);
- if (!(status & PHY_PLL_OUTPUT)) {
- dev_dbg(&phy->dev, "pll output enable done!\n");
- err = 0;
- break;
- }
- msleep(20);
- }
-
+ err = regmap_read_poll_timeout(rk_phy->reg_base,
+ rk_phy->phy_data->pcie_status,
+ status,
+ !(status & PHY_PLL_OUTPUT),
+ 200, 100000);
if (err) {
dev_err(&phy->dev, "pll output enable timeout!\n");
goto err_pll_lock;
@@ -236,33 +214,22 @@ static int rockchip_pcie_phy_power_on(struct phy *phy)
HIWORD_UPDATE(PHY_CFG_PLL_LOCK,
PHY_CFG_ADDR_MASK,
PHY_CFG_ADDR_SHIFT));
- err = -EINVAL;
- while (time_before(jiffies, timeout)) {
- regmap_read(rk_phy->reg_base,
- rk_phy->phy_data->pcie_status,
- &status);
- if (status & PHY_PLL_LOCKED) {
- dev_dbg(&phy->dev, "pll relocked!\n");
- err = 0;
- break;
- }
- msleep(20);
- }
+ err = regmap_read_poll_timeout(rk_phy->reg_base,
+ rk_phy->phy_data->pcie_status,
+ status,
+ status & PHY_PLL_LOCKED,
+ 200, 100000);
if (err) {
dev_err(&phy->dev, "pll relock timeout!\n");
goto err_pll_lock;
}
-err_out:
- mutex_unlock(&rk_phy->pcie_mutex);
- return 0;
+ return err;
err_pll_lock:
reset_control_assert(rk_phy->phy_rst);
-err_pwr_cnt:
rk_phy->pwr_cnt--;
- mutex_unlock(&rk_phy->pcie_mutex);
return err;
}
@@ -272,33 +239,19 @@ static int rockchip_pcie_phy_init(struct phy *phy)
struct rockchip_pcie_phy *rk_phy = to_pcie_phy(inst);
int err = 0;
- mutex_lock(&rk_phy->pcie_mutex);
-
- if (rk_phy->init_cnt++)
- goto err_out;
+ guard(mutex)(&rk_phy->pcie_mutex);
- err = clk_prepare_enable(rk_phy->clk_pciephy_ref);
- if (err) {
- dev_err(&phy->dev, "Fail to enable pcie ref clock.\n");
- goto err_refclk;
+ if (rk_phy->init_cnt++) {
+ return 0;
}
err = reset_control_assert(rk_phy->phy_rst);
if (err) {
dev_err(&phy->dev, "assert phy_rst err %d\n", err);
- goto err_reset;
+ rk_phy->init_cnt--;
+ return err;
}
-err_out:
- mutex_unlock(&rk_phy->pcie_mutex);
- return 0;
-
-err_reset:
-
- clk_disable_unprepare(rk_phy->clk_pciephy_ref);
-err_refclk:
- rk_phy->init_cnt--;
- mutex_unlock(&rk_phy->pcie_mutex);
return err;
}
@@ -307,15 +260,12 @@ static int rockchip_pcie_phy_exit(struct phy *phy)
struct phy_pcie_instance *inst = phy_get_drvdata(phy);
struct rockchip_pcie_phy *rk_phy = to_pcie_phy(inst);
- mutex_lock(&rk_phy->pcie_mutex);
+ guard(mutex)(&rk_phy->pcie_mutex);
if (--rk_phy->init_cnt)
goto err_init_cnt;
- clk_disable_unprepare(rk_phy->clk_pciephy_ref);
-
err_init_cnt:
- mutex_unlock(&rk_phy->pcie_mutex);
return 0;
}
@@ -371,18 +321,14 @@ static int rockchip_pcie_phy_probe(struct platform_device *pdev)
mutex_init(&rk_phy->pcie_mutex);
rk_phy->phy_rst = devm_reset_control_get(dev, "phy");
- if (IS_ERR(rk_phy->phy_rst)) {
- if (PTR_ERR(rk_phy->phy_rst) != -EPROBE_DEFER)
- dev_err(dev,
- "missing phy property for reset controller\n");
- return PTR_ERR(rk_phy->phy_rst);
- }
-
- rk_phy->clk_pciephy_ref = devm_clk_get(dev, "refclk");
- if (IS_ERR(rk_phy->clk_pciephy_ref)) {
- dev_err(dev, "refclk not found.\n");
- return PTR_ERR(rk_phy->clk_pciephy_ref);
- }
+ if (IS_ERR(rk_phy->phy_rst))
+ return dev_err_probe(&pdev->dev, PTR_ERR(rk_phy->phy_rst),
+ "missing phy property for reset controller\n");
+
+ rk_phy->clk_pciephy_ref = devm_clk_get_enabled(dev, "refclk");
+ if (IS_ERR(rk_phy->clk_pciephy_ref))
+ return dev_err_probe(&pdev->dev, PTR_ERR(rk_phy->clk_pciephy_ref),
+ "failed to get phyclk\n");
/* parse #phy-cells to see if it's legacy PHY model */
if (of_property_read_u32(dev->of_node, "#phy-cells", &phy_num))
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
new file mode 100644
index 000000000000..0965b9d4f9cf
--- /dev/null
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -0,0 +1,1154 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2021-2022 Rockchip Electronics Co., Ltd.
+ * Copyright (c) 2024 Collabora Ltd.
+ *
+ * Author: Algea Cao <algea.cao@rock-chips.com>
+ * Author: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
+ */
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/rational.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#define GRF_HDPTX_CON0 0x00
+#define HDPTX_I_PLL_EN BIT(7)
+#define HDPTX_I_BIAS_EN BIT(6)
+#define HDPTX_I_BGR_EN BIT(5)
+#define GRF_HDPTX_STATUS 0x80
+#define HDPTX_O_PLL_LOCK_DONE BIT(3)
+#define HDPTX_O_PHY_CLK_RDY BIT(2)
+#define HDPTX_O_PHY_RDY BIT(1)
+#define HDPTX_O_SB_RDY BIT(0)
+
+#define HDTPX_REG(_n, _min, _max) \
+ ( \
+ BUILD_BUG_ON_ZERO((0x##_n) < (0x##_min)) + \
+ BUILD_BUG_ON_ZERO((0x##_n) > (0x##_max)) + \
+ ((0x##_n) * 4) \
+ )
+
+#define CMN_REG(n) HDTPX_REG(n, 0000, 00a7)
+#define SB_REG(n) HDTPX_REG(n, 0100, 0129)
+#define LNTOP_REG(n) HDTPX_REG(n, 0200, 0229)
+#define LANE_REG(n) HDTPX_REG(n, 0300, 062d)
+
+/* CMN_REG(0008) */
+#define LCPLL_EN_MASK BIT(6)
+#define LCPLL_LCVCO_MODE_EN_MASK BIT(4)
+/* CMN_REG(001e) */
+#define LCPLL_PI_EN_MASK BIT(5)
+#define LCPLL_100M_CLK_EN_MASK BIT(0)
+/* CMN_REG(0025) */
+#define LCPLL_PMS_IQDIV_RSTN BIT(4)
+/* CMN_REG(0028) */
+#define LCPLL_SDC_FRAC_EN BIT(2)
+#define LCPLL_SDC_FRAC_RSTN BIT(0)
+/* CMN_REG(002d) */
+#define LCPLL_SDC_N_MASK GENMASK(3, 1)
+/* CMN_REG(002e) */
+#define LCPLL_SDC_NUMBERATOR_MASK GENMASK(5, 0)
+/* CMN_REG(002f) */
+#define LCPLL_SDC_DENOMINATOR_MASK GENMASK(7, 2)
+#define LCPLL_SDC_NDIV_RSTN BIT(0)
+/* CMN_REG(003d) */
+#define ROPLL_LCVCO_EN BIT(4)
+/* CMN_REG(004e) */
+#define ROPLL_PI_EN BIT(5)
+/* CMN_REG(005c) */
+#define ROPLL_PMS_IQDIV_RSTN BIT(5)
+/* CMN_REG(005e) */
+#define ROPLL_SDM_EN_MASK BIT(6)
+#define ROPLL_SDM_FRAC_EN_RBR BIT(3)
+#define ROPLL_SDM_FRAC_EN_HBR BIT(2)
+#define ROPLL_SDM_FRAC_EN_HBR2 BIT(1)
+#define ROPLL_SDM_FRAC_EN_HBR3 BIT(0)
+/* CMN_REG(0064) */
+#define ROPLL_SDM_NUM_SIGN_RBR_MASK BIT(3)
+/* CMN_REG(0069) */
+#define ROPLL_SDC_N_RBR_MASK GENMASK(2, 0)
+/* CMN_REG(0074) */
+#define ROPLL_SDC_NDIV_RSTN BIT(2)
+#define ROPLL_SSC_EN BIT(0)
+/* CMN_REG(0081) */
+#define OVRD_PLL_CD_CLK_EN BIT(8)
+#define PLL_CD_HSCLK_EAST_EN BIT(0)
+/* CMN_REG(0086) */
+#define PLL_PCG_POSTDIV_SEL_MASK GENMASK(7, 4)
+#define PLL_PCG_CLK_SEL_MASK GENMASK(3, 1)
+#define PLL_PCG_CLK_EN BIT(0)
+/* CMN_REG(0087) */
+#define PLL_FRL_MODE_EN BIT(3)
+#define PLL_TX_HS_CLK_EN BIT(2)
+/* CMN_REG(0089) */
+#define LCPLL_ALONE_MODE BIT(1)
+/* CMN_REG(0097) */
+#define DIG_CLK_SEL BIT(1)
+#define ROPLL_REF BIT(1)
+#define LCPLL_REF 0
+/* CMN_REG(0099) */
+#define CMN_ROPLL_ALONE_MODE BIT(2)
+#define ROPLL_ALONE_MODE BIT(2)
+/* CMN_REG(009a) */
+#define HS_SPEED_SEL BIT(0)
+#define DIV_10_CLOCK BIT(0)
+/* CMN_REG(009b) */
+#define IS_SPEED_SEL BIT(4)
+#define LINK_SYMBOL_CLOCK BIT(4)
+#define LINK_SYMBOL_CLOCK1_2 0
+
+/* SB_REG(0102) */
+#define OVRD_SB_RXTERM_EN_MASK BIT(5)
+#define SB_RXTERM_EN_MASK BIT(4)
+#define ANA_SB_RXTERM_OFFSP_MASK GENMASK(3, 0)
+/* SB_REG(0103) */
+#define ANA_SB_RXTERM_OFFSN_MASK GENMASK(6, 3)
+#define OVRD_SB_RX_RESCAL_DONE_MASK BIT(1)
+#define SB_RX_RESCAL_DONE_MASK BIT(0)
+/* SB_REG(0104) */
+#define OVRD_SB_EN_MASK BIT(5)
+#define SB_EN_MASK BIT(4)
+/* SB_REG(0105) */
+#define OVRD_SB_EARC_CMDC_EN_MASK BIT(6)
+#define SB_EARC_CMDC_EN_MASK BIT(5)
+#define ANA_SB_TX_HLVL_PROG_MASK GENMASK(2, 0)
+/* SB_REG(0106) */
+#define ANA_SB_TX_LLVL_PROG_MASK GENMASK(6, 4)
+/* SB_REG(0109) */
+#define ANA_SB_DMRX_AFC_DIV_RATIO_MASK GENMASK(2, 0)
+/* SB_REG(010f) */
+#define OVRD_SB_VREG_EN_MASK BIT(7)
+#define SB_VREG_EN_MASK BIT(6)
+#define OVRD_SB_VREG_LPF_BYPASS_MASK BIT(5)
+#define SB_VREG_LPF_BYPASS_MASK BIT(4)
+#define ANA_SB_VREG_GAIN_CTRL_MASK GENMASK(3, 0)
+/* SB_REG(0110) */
+#define ANA_SB_VREG_REF_SEL_MASK BIT(0)
+/* SB_REG(0113) */
+#define SB_RX_RCAL_OPT_CODE_MASK GENMASK(5, 4)
+#define SB_RX_RTERM_CTRL_MASK GENMASK(3, 0)
+/* SB_REG(0114) */
+#define SB_TG_SB_EN_DELAY_TIME_MASK GENMASK(5, 3)
+#define SB_TG_RXTERM_EN_DELAY_TIME_MASK GENMASK(2, 0)
+/* SB_REG(0115) */
+#define SB_READY_DELAY_TIME_MASK GENMASK(5, 3)
+#define SB_TG_OSC_EN_DELAY_TIME_MASK GENMASK(2, 0)
+/* SB_REG(0116) */
+#define AFC_RSTN_DELAY_TIME_MASK GENMASK(6, 4)
+/* SB_REG(0117) */
+#define FAST_PULSE_TIME_MASK GENMASK(3, 0)
+/* SB_REG(011b) */
+#define SB_EARC_SIG_DET_BYPASS_MASK BIT(4)
+#define SB_AFC_TOL_MASK GENMASK(3, 0)
+/* SB_REG(011f) */
+#define SB_PWM_AFC_CTRL_MASK GENMASK(7, 2)
+#define SB_RCAL_RSTN_MASK BIT(1)
+/* SB_REG(0120) */
+#define SB_EARC_EN_MASK BIT(1)
+#define SB_EARC_AFC_EN_MASK BIT(2)
+/* SB_REG(0123) */
+#define OVRD_SB_READY_MASK BIT(5)
+#define SB_READY_MASK BIT(4)
+
+/* LNTOP_REG(0200) */
+#define PROTOCOL_SEL BIT(2)
+#define HDMI_MODE BIT(2)
+#define HDMI_TMDS_FRL_SEL BIT(1)
+/* LNTOP_REG(0206) */
+#define DATA_BUS_SEL BIT(0)
+#define DATA_BUS_36_40 BIT(0)
+/* LNTOP_REG(0207) */
+#define LANE_EN 0xf
+#define ALL_LANE_EN 0xf
+
+/* LANE_REG(0312) */
+#define LN0_TX_SER_RATE_SEL_RBR BIT(5)
+#define LN0_TX_SER_RATE_SEL_HBR BIT(4)
+#define LN0_TX_SER_RATE_SEL_HBR2 BIT(3)
+#define LN0_TX_SER_RATE_SEL_HBR3 BIT(2)
+/* LANE_REG(0412) */
+#define LN1_TX_SER_RATE_SEL_RBR BIT(5)
+#define LN1_TX_SER_RATE_SEL_HBR BIT(4)
+#define LN1_TX_SER_RATE_SEL_HBR2 BIT(3)
+#define LN1_TX_SER_RATE_SEL_HBR3 BIT(2)
+/* LANE_REG(0512) */
+#define LN2_TX_SER_RATE_SEL_RBR BIT(5)
+#define LN2_TX_SER_RATE_SEL_HBR BIT(4)
+#define LN2_TX_SER_RATE_SEL_HBR2 BIT(3)
+#define LN2_TX_SER_RATE_SEL_HBR3 BIT(2)
+/* LANE_REG(0612) */
+#define LN3_TX_SER_RATE_SEL_RBR BIT(5)
+#define LN3_TX_SER_RATE_SEL_HBR BIT(4)
+#define LN3_TX_SER_RATE_SEL_HBR2 BIT(3)
+#define LN3_TX_SER_RATE_SEL_HBR3 BIT(2)
+
+#define HDMI20_MAX_RATE 600000000
+
+struct lcpll_config {
+ u32 bit_rate;
+ u8 lcvco_mode_en;
+ u8 pi_en;
+ u8 clk_en_100m;
+ u8 pms_mdiv;
+ u8 pms_mdiv_afc;
+ u8 pms_pdiv;
+ u8 pms_refdiv;
+ u8 pms_sdiv;
+ u8 pi_cdiv_rstn;
+ u8 pi_cdiv_sel;
+ u8 sdm_en;
+ u8 sdm_rstn;
+ u8 sdc_frac_en;
+ u8 sdc_rstn;
+ u8 sdm_deno;
+ u8 sdm_num_sign;
+ u8 sdm_num;
+ u8 sdc_n;
+ u8 sdc_n2;
+ u8 sdc_num;
+ u8 sdc_deno;
+ u8 sdc_ndiv_rstn;
+ u8 ssc_en;
+ u8 ssc_fm_dev;
+ u8 ssc_fm_freq;
+ u8 ssc_clk_div_sel;
+ u8 cd_tx_ser_rate_sel;
+};
+
+struct ropll_config {
+ u32 bit_rate;
+ u8 pms_mdiv;
+ u8 pms_mdiv_afc;
+ u8 pms_pdiv;
+ u8 pms_refdiv;
+ u8 pms_sdiv;
+ u8 pms_iqdiv_rstn;
+ u8 ref_clk_sel;
+ u8 sdm_en;
+ u8 sdm_rstn;
+ u8 sdc_frac_en;
+ u8 sdc_rstn;
+ u8 sdm_clk_div;
+ u8 sdm_deno;
+ u8 sdm_num_sign;
+ u8 sdm_num;
+ u8 sdc_n;
+ u8 sdc_num;
+ u8 sdc_deno;
+ u8 sdc_ndiv_rstn;
+ u8 ssc_en;
+ u8 ssc_fm_dev;
+ u8 ssc_fm_freq;
+ u8 ssc_clk_div_sel;
+ u8 ana_cpp_ctrl;
+ u8 ana_lpf_c_sel;
+ u8 cd_tx_ser_rate_sel;
+};
+
+enum rk_hdptx_reset {
+ RST_APB = 0,
+ RST_INIT,
+ RST_CMN,
+ RST_LANE,
+ RST_MAX
+};
+
+struct rk_hdptx_phy {
+ struct device *dev;
+ struct regmap *regmap;
+ struct regmap *grf;
+
+ struct phy *phy;
+ struct phy_config *phy_cfg;
+ struct clk_bulk_data *clks;
+ int nr_clks;
+ struct reset_control_bulk_data rsts[RST_MAX];
+
+ /* clk provider */
+ struct clk_hw hw;
+ unsigned long rate;
+
+ atomic_t usage_count;
+};
+
+static const struct ropll_config ropll_tmds_cfg[] = {
+ { 5940000, 124, 124, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
+ { 3712500, 155, 155, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
+ { 2970000, 124, 124, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
+ { 1620000, 135, 135, 1, 1, 3, 1, 1, 0, 1, 1, 1, 1, 4, 0, 3, 5, 5, 0x10,
+ 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
+ { 1856250, 155, 155, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
+ { 1540000, 193, 193, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 193, 1, 32, 2, 1,
+ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
+ { 1485000, 0x7b, 0x7b, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 4, 0, 3, 5, 5,
+ 0x10, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
+ { 1462500, 122, 122, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 244, 1, 16, 2, 1, 1,
+ 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
+ { 1190000, 149, 149, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 149, 1, 16, 2, 1, 1,
+ 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
+ { 1065000, 89, 89, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 89, 1, 16, 1, 0, 1,
+ 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
+ { 1080000, 135, 135, 1, 1, 5, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
+ 0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
+ { 855000, 214, 214, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 214, 1, 16, 2, 1,
+ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
+ { 835000, 105, 105, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 42, 1, 16, 1, 0,
+ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
+ { 928125, 155, 155, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
+ { 742500, 124, 124, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
+ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
+ { 650000, 162, 162, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 54, 0, 16, 4, 1,
+ 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
+ { 337500, 0x70, 0x70, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 0x2, 0, 0x01, 5,
+ 1, 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
+ { 400000, 100, 100, 1, 1, 11, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
+ 0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
+ { 270000, 0x5a, 0x5a, 1, 1, 0xf, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
+ 0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
+ { 251750, 84, 84, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 168, 1, 16, 4, 1, 1,
+ 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
+};
+
+static const struct reg_sequence rk_hdtpx_common_cmn_init_seq[] = {
+ REG_SEQ0(CMN_REG(0009), 0x0c),
+ REG_SEQ0(CMN_REG(000a), 0x83),
+ REG_SEQ0(CMN_REG(000b), 0x06),
+ REG_SEQ0(CMN_REG(000c), 0x20),
+ REG_SEQ0(CMN_REG(000d), 0xb8),
+ REG_SEQ0(CMN_REG(000e), 0x0f),
+ REG_SEQ0(CMN_REG(000f), 0x0f),
+ REG_SEQ0(CMN_REG(0010), 0x04),
+ REG_SEQ0(CMN_REG(0011), 0x00),
+ REG_SEQ0(CMN_REG(0012), 0x26),
+ REG_SEQ0(CMN_REG(0013), 0x22),
+ REG_SEQ0(CMN_REG(0014), 0x24),
+ REG_SEQ0(CMN_REG(0015), 0x77),
+ REG_SEQ0(CMN_REG(0016), 0x08),
+ REG_SEQ0(CMN_REG(0017), 0x00),
+ REG_SEQ0(CMN_REG(0018), 0x04),
+ REG_SEQ0(CMN_REG(0019), 0x48),
+ REG_SEQ0(CMN_REG(001a), 0x01),
+ REG_SEQ0(CMN_REG(001b), 0x00),
+ REG_SEQ0(CMN_REG(001c), 0x01),
+ REG_SEQ0(CMN_REG(001d), 0x64),
+ REG_SEQ0(CMN_REG(001f), 0x00),
+ REG_SEQ0(CMN_REG(0026), 0x53),
+ REG_SEQ0(CMN_REG(0029), 0x01),
+ REG_SEQ0(CMN_REG(0030), 0x00),
+ REG_SEQ0(CMN_REG(0031), 0x20),
+ REG_SEQ0(CMN_REG(0032), 0x30),
+ REG_SEQ0(CMN_REG(0033), 0x0b),
+ REG_SEQ0(CMN_REG(0034), 0x23),
+ REG_SEQ0(CMN_REG(0035), 0x00),
+ REG_SEQ0(CMN_REG(0038), 0x00),
+ REG_SEQ0(CMN_REG(0039), 0x00),
+ REG_SEQ0(CMN_REG(003a), 0x00),
+ REG_SEQ0(CMN_REG(003b), 0x00),
+ REG_SEQ0(CMN_REG(003c), 0x80),
+ REG_SEQ0(CMN_REG(003e), 0x0c),
+ REG_SEQ0(CMN_REG(003f), 0x83),
+ REG_SEQ0(CMN_REG(0040), 0x06),
+ REG_SEQ0(CMN_REG(0041), 0x20),
+ REG_SEQ0(CMN_REG(0042), 0xb8),
+ REG_SEQ0(CMN_REG(0043), 0x00),
+ REG_SEQ0(CMN_REG(0044), 0x46),
+ REG_SEQ0(CMN_REG(0045), 0x24),
+ REG_SEQ0(CMN_REG(0046), 0xff),
+ REG_SEQ0(CMN_REG(0047), 0x00),
+ REG_SEQ0(CMN_REG(0048), 0x44),
+ REG_SEQ0(CMN_REG(0049), 0xfa),
+ REG_SEQ0(CMN_REG(004a), 0x08),
+ REG_SEQ0(CMN_REG(004b), 0x00),
+ REG_SEQ0(CMN_REG(004c), 0x01),
+ REG_SEQ0(CMN_REG(004d), 0x64),
+ REG_SEQ0(CMN_REG(004e), 0x14),
+ REG_SEQ0(CMN_REG(004f), 0x00),
+ REG_SEQ0(CMN_REG(0050), 0x00),
+ REG_SEQ0(CMN_REG(005d), 0x0c),
+ REG_SEQ0(CMN_REG(005f), 0x01),
+ REG_SEQ0(CMN_REG(006b), 0x04),
+ REG_SEQ0(CMN_REG(0073), 0x30),
+ REG_SEQ0(CMN_REG(0074), 0x00),
+ REG_SEQ0(CMN_REG(0075), 0x20),
+ REG_SEQ0(CMN_REG(0076), 0x30),
+ REG_SEQ0(CMN_REG(0077), 0x08),
+ REG_SEQ0(CMN_REG(0078), 0x0c),
+ REG_SEQ0(CMN_REG(0079), 0x00),
+ REG_SEQ0(CMN_REG(007b), 0x00),
+ REG_SEQ0(CMN_REG(007c), 0x00),
+ REG_SEQ0(CMN_REG(007d), 0x00),
+ REG_SEQ0(CMN_REG(007e), 0x00),
+ REG_SEQ0(CMN_REG(007f), 0x00),
+ REG_SEQ0(CMN_REG(0080), 0x00),
+ REG_SEQ0(CMN_REG(0081), 0x09),
+ REG_SEQ0(CMN_REG(0082), 0x04),
+ REG_SEQ0(CMN_REG(0083), 0x24),
+ REG_SEQ0(CMN_REG(0084), 0x20),
+ REG_SEQ0(CMN_REG(0085), 0x03),
+ REG_SEQ0(CMN_REG(0086), 0x01),
+ REG_SEQ0(CMN_REG(0087), 0x0c),
+ REG_SEQ0(CMN_REG(008a), 0x55),
+ REG_SEQ0(CMN_REG(008b), 0x25),
+ REG_SEQ0(CMN_REG(008c), 0x2c),
+ REG_SEQ0(CMN_REG(008d), 0x22),
+ REG_SEQ0(CMN_REG(008e), 0x14),
+ REG_SEQ0(CMN_REG(008f), 0x20),
+ REG_SEQ0(CMN_REG(0090), 0x00),
+ REG_SEQ0(CMN_REG(0091), 0x00),
+ REG_SEQ0(CMN_REG(0092), 0x00),
+ REG_SEQ0(CMN_REG(0093), 0x00),
+ REG_SEQ0(CMN_REG(009a), 0x11),
+ REG_SEQ0(CMN_REG(009b), 0x10),
+};
+
+static const struct reg_sequence rk_hdtpx_tmds_cmn_init_seq[] = {
+ REG_SEQ0(CMN_REG(0008), 0x00),
+ REG_SEQ0(CMN_REG(0011), 0x01),
+ REG_SEQ0(CMN_REG(0017), 0x20),
+ REG_SEQ0(CMN_REG(001e), 0x14),
+ REG_SEQ0(CMN_REG(0020), 0x00),
+ REG_SEQ0(CMN_REG(0021), 0x00),
+ REG_SEQ0(CMN_REG(0022), 0x11),
+ REG_SEQ0(CMN_REG(0023), 0x00),
+ REG_SEQ0(CMN_REG(0024), 0x00),
+ REG_SEQ0(CMN_REG(0025), 0x53),
+ REG_SEQ0(CMN_REG(0026), 0x00),
+ REG_SEQ0(CMN_REG(0027), 0x00),
+ REG_SEQ0(CMN_REG(0028), 0x01),
+ REG_SEQ0(CMN_REG(002a), 0x00),
+ REG_SEQ0(CMN_REG(002b), 0x00),
+ REG_SEQ0(CMN_REG(002c), 0x00),
+ REG_SEQ0(CMN_REG(002d), 0x00),
+ REG_SEQ0(CMN_REG(002e), 0x04),
+ REG_SEQ0(CMN_REG(002f), 0x00),
+ REG_SEQ0(CMN_REG(0030), 0x20),
+ REG_SEQ0(CMN_REG(0031), 0x30),
+ REG_SEQ0(CMN_REG(0032), 0x0b),
+ REG_SEQ0(CMN_REG(0033), 0x23),
+ REG_SEQ0(CMN_REG(0034), 0x00),
+ REG_SEQ0(CMN_REG(003d), 0x40),
+ REG_SEQ0(CMN_REG(0042), 0x78),
+ REG_SEQ0(CMN_REG(004e), 0x34),
+ REG_SEQ0(CMN_REG(005c), 0x25),
+ REG_SEQ0(CMN_REG(005e), 0x4f),
+ REG_SEQ0(CMN_REG(0074), 0x04),
+ REG_SEQ0(CMN_REG(0081), 0x01),
+ REG_SEQ0(CMN_REG(0087), 0x04),
+ REG_SEQ0(CMN_REG(0089), 0x00),
+ REG_SEQ0(CMN_REG(0095), 0x00),
+ REG_SEQ0(CMN_REG(0097), 0x02),
+ REG_SEQ0(CMN_REG(0099), 0x04),
+ REG_SEQ0(CMN_REG(009b), 0x00),
+};
+
+static const struct reg_sequence rk_hdtpx_common_sb_init_seq[] = {
+ REG_SEQ0(SB_REG(0114), 0x00),
+ REG_SEQ0(SB_REG(0115), 0x00),
+ REG_SEQ0(SB_REG(0116), 0x00),
+ REG_SEQ0(SB_REG(0117), 0x00),
+};
+
+static const struct reg_sequence rk_hdtpx_tmds_lntop_highbr_seq[] = {
+ REG_SEQ0(LNTOP_REG(0201), 0x00),
+ REG_SEQ0(LNTOP_REG(0202), 0x00),
+ REG_SEQ0(LNTOP_REG(0203), 0x0f),
+ REG_SEQ0(LNTOP_REG(0204), 0xff),
+ REG_SEQ0(LNTOP_REG(0205), 0xff),
+};
+
+static const struct reg_sequence rk_hdtpx_tmds_lntop_lowbr_seq[] = {
+ REG_SEQ0(LNTOP_REG(0201), 0x07),
+ REG_SEQ0(LNTOP_REG(0202), 0xc1),
+ REG_SEQ0(LNTOP_REG(0203), 0xf0),
+ REG_SEQ0(LNTOP_REG(0204), 0x7c),
+ REG_SEQ0(LNTOP_REG(0205), 0x1f),
+};
+
+static const struct reg_sequence rk_hdtpx_common_lane_init_seq[] = {
+ REG_SEQ0(LANE_REG(0303), 0x0c),
+ REG_SEQ0(LANE_REG(0307), 0x20),
+ REG_SEQ0(LANE_REG(030a), 0x17),
+ REG_SEQ0(LANE_REG(030b), 0x77),
+ REG_SEQ0(LANE_REG(030c), 0x77),
+ REG_SEQ0(LANE_REG(030d), 0x77),
+ REG_SEQ0(LANE_REG(030e), 0x38),
+ REG_SEQ0(LANE_REG(0310), 0x03),
+ REG_SEQ0(LANE_REG(0311), 0x0f),
+ REG_SEQ0(LANE_REG(0316), 0x02),
+ REG_SEQ0(LANE_REG(031b), 0x01),
+ REG_SEQ0(LANE_REG(031f), 0x15),
+ REG_SEQ0(LANE_REG(0320), 0xa0),
+ REG_SEQ0(LANE_REG(0403), 0x0c),
+ REG_SEQ0(LANE_REG(0407), 0x20),
+ REG_SEQ0(LANE_REG(040a), 0x17),
+ REG_SEQ0(LANE_REG(040b), 0x77),
+ REG_SEQ0(LANE_REG(040c), 0x77),
+ REG_SEQ0(LANE_REG(040d), 0x77),
+ REG_SEQ0(LANE_REG(040e), 0x38),
+ REG_SEQ0(LANE_REG(0410), 0x03),
+ REG_SEQ0(LANE_REG(0411), 0x0f),
+ REG_SEQ0(LANE_REG(0416), 0x02),
+ REG_SEQ0(LANE_REG(041b), 0x01),
+ REG_SEQ0(LANE_REG(041f), 0x15),
+ REG_SEQ0(LANE_REG(0420), 0xa0),
+ REG_SEQ0(LANE_REG(0503), 0x0c),
+ REG_SEQ0(LANE_REG(0507), 0x20),
+ REG_SEQ0(LANE_REG(050a), 0x17),
+ REG_SEQ0(LANE_REG(050b), 0x77),
+ REG_SEQ0(LANE_REG(050c), 0x77),
+ REG_SEQ0(LANE_REG(050d), 0x77),
+ REG_SEQ0(LANE_REG(050e), 0x38),
+ REG_SEQ0(LANE_REG(0510), 0x03),
+ REG_SEQ0(LANE_REG(0511), 0x0f),
+ REG_SEQ0(LANE_REG(0516), 0x02),
+ REG_SEQ0(LANE_REG(051b), 0x01),
+ REG_SEQ0(LANE_REG(051f), 0x15),
+ REG_SEQ0(LANE_REG(0520), 0xa0),
+ REG_SEQ0(LANE_REG(0603), 0x0c),
+ REG_SEQ0(LANE_REG(0607), 0x20),
+ REG_SEQ0(LANE_REG(060a), 0x17),
+ REG_SEQ0(LANE_REG(060b), 0x77),
+ REG_SEQ0(LANE_REG(060c), 0x77),
+ REG_SEQ0(LANE_REG(060d), 0x77),
+ REG_SEQ0(LANE_REG(060e), 0x38),
+ REG_SEQ0(LANE_REG(0610), 0x03),
+ REG_SEQ0(LANE_REG(0611), 0x0f),
+ REG_SEQ0(LANE_REG(0616), 0x02),
+ REG_SEQ0(LANE_REG(061b), 0x01),
+ REG_SEQ0(LANE_REG(061f), 0x15),
+ REG_SEQ0(LANE_REG(0620), 0xa0),
+};
+
+static const struct reg_sequence rk_hdtpx_tmds_lane_init_seq[] = {
+ REG_SEQ0(LANE_REG(0312), 0x00),
+ REG_SEQ0(LANE_REG(031e), 0x00),
+ REG_SEQ0(LANE_REG(0412), 0x00),
+ REG_SEQ0(LANE_REG(041e), 0x00),
+ REG_SEQ0(LANE_REG(0512), 0x00),
+ REG_SEQ0(LANE_REG(051e), 0x00),
+ REG_SEQ0(LANE_REG(0612), 0x00),
+ REG_SEQ0(LANE_REG(061e), 0x08),
+ REG_SEQ0(LANE_REG(0303), 0x2f),
+ REG_SEQ0(LANE_REG(0403), 0x2f),
+ REG_SEQ0(LANE_REG(0503), 0x2f),
+ REG_SEQ0(LANE_REG(0603), 0x2f),
+ REG_SEQ0(LANE_REG(0305), 0x03),
+ REG_SEQ0(LANE_REG(0405), 0x03),
+ REG_SEQ0(LANE_REG(0505), 0x03),
+ REG_SEQ0(LANE_REG(0605), 0x03),
+ REG_SEQ0(LANE_REG(0306), 0x1c),
+ REG_SEQ0(LANE_REG(0406), 0x1c),
+ REG_SEQ0(LANE_REG(0506), 0x1c),
+ REG_SEQ0(LANE_REG(0606), 0x1c),
+};
+
+static bool rk_hdptx_phy_is_rw_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case 0x0000 ... 0x029c:
+ case 0x0400 ... 0x04a4:
+ case 0x0800 ... 0x08a4:
+ case 0x0c00 ... 0x0cb4:
+ case 0x1000 ... 0x10b4:
+ case 0x1400 ... 0x14b4:
+ case 0x1800 ... 0x18b4:
+ return true;
+ }
+
+ return false;
+}
+
+static const struct regmap_config rk_hdptx_phy_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .writeable_reg = rk_hdptx_phy_is_rw_reg,
+ .readable_reg = rk_hdptx_phy_is_rw_reg,
+ .fast_io = true,
+ .max_register = 0x18b4,
+};
+
+#define rk_hdptx_multi_reg_write(hdptx, seq) \
+ regmap_multi_reg_write((hdptx)->regmap, seq, ARRAY_SIZE(seq))
+
+static void rk_hdptx_pre_power_up(struct rk_hdptx_phy *hdptx)
+{
+ u32 val;
+
+ reset_control_assert(hdptx->rsts[RST_APB].rstc);
+ usleep_range(20, 25);
+ reset_control_deassert(hdptx->rsts[RST_APB].rstc);
+
+ reset_control_assert(hdptx->rsts[RST_LANE].rstc);
+ reset_control_assert(hdptx->rsts[RST_CMN].rstc);
+ reset_control_assert(hdptx->rsts[RST_INIT].rstc);
+
+ val = (HDPTX_I_PLL_EN | HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN) << 16;
+ regmap_write(hdptx->grf, GRF_HDPTX_CON0, val);
+}
+
+static int rk_hdptx_post_enable_lane(struct rk_hdptx_phy *hdptx)
+{
+ u32 val;
+ int ret;
+
+ reset_control_deassert(hdptx->rsts[RST_LANE].rstc);
+
+ val = (HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN) << 16 |
+ HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN;
+ regmap_write(hdptx->grf, GRF_HDPTX_CON0, val);
+
+ ret = regmap_read_poll_timeout(hdptx->grf, GRF_HDPTX_STATUS, val,
+ (val & HDPTX_O_PHY_RDY) &&
+ (val & HDPTX_O_PLL_LOCK_DONE),
+ 100, 5000);
+ if (ret) {
+ dev_err(hdptx->dev, "Failed to get PHY lane lock: %d\n", ret);
+ return ret;
+ }
+
+ dev_dbg(hdptx->dev, "PHY lane locked\n");
+
+ return 0;
+}
+
+static int rk_hdptx_post_enable_pll(struct rk_hdptx_phy *hdptx)
+{
+ u32 val;
+ int ret;
+
+ val = (HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN) << 16 |
+ HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN;
+ regmap_write(hdptx->grf, GRF_HDPTX_CON0, val);
+
+ usleep_range(10, 15);
+ reset_control_deassert(hdptx->rsts[RST_INIT].rstc);
+
+ usleep_range(10, 15);
+ val = HDPTX_I_PLL_EN << 16 | HDPTX_I_PLL_EN;
+ regmap_write(hdptx->grf, GRF_HDPTX_CON0, val);
+
+ usleep_range(10, 15);
+ reset_control_deassert(hdptx->rsts[RST_CMN].rstc);
+
+ ret = regmap_read_poll_timeout(hdptx->grf, GRF_HDPTX_STATUS, val,
+ val & HDPTX_O_PHY_CLK_RDY, 20, 400);
+ if (ret) {
+ dev_err(hdptx->dev, "Failed to get PHY clk ready: %d\n", ret);
+ return ret;
+ }
+
+ dev_dbg(hdptx->dev, "PHY clk ready\n");
+
+ return 0;
+}
+
+static void rk_hdptx_phy_disable(struct rk_hdptx_phy *hdptx)
+{
+ u32 val;
+
+ reset_control_assert(hdptx->rsts[RST_APB].rstc);
+ usleep_range(20, 30);
+ reset_control_deassert(hdptx->rsts[RST_APB].rstc);
+
+ regmap_write(hdptx->regmap, LANE_REG(0300), 0x82);
+ regmap_write(hdptx->regmap, SB_REG(010f), 0xc1);
+ regmap_write(hdptx->regmap, SB_REG(0110), 0x1);
+ regmap_write(hdptx->regmap, LANE_REG(0301), 0x80);
+ regmap_write(hdptx->regmap, LANE_REG(0401), 0x80);
+ regmap_write(hdptx->regmap, LANE_REG(0501), 0x80);
+ regmap_write(hdptx->regmap, LANE_REG(0601), 0x80);
+
+ reset_control_assert(hdptx->rsts[RST_LANE].rstc);
+ reset_control_assert(hdptx->rsts[RST_CMN].rstc);
+ reset_control_assert(hdptx->rsts[RST_INIT].rstc);
+
+ val = (HDPTX_I_PLL_EN | HDPTX_I_BIAS_EN | HDPTX_I_BGR_EN) << 16;
+ regmap_write(hdptx->grf, GRF_HDPTX_CON0, val);
+}
+
+static bool rk_hdptx_phy_clk_pll_calc(unsigned int data_rate,
+ struct ropll_config *cfg)
+{
+ const unsigned int fout = data_rate / 2, fref = 24000;
+ unsigned long k = 0, lc, k_sub, lc_sub;
+ unsigned int fvco, sdc;
+ u32 mdiv, sdiv, n = 8;
+
+ if (fout > 0xfffffff)
+ return false;
+
+ for (sdiv = 16; sdiv >= 1; sdiv--) {
+ if (sdiv % 2 && sdiv != 1)
+ continue;
+
+ fvco = fout * sdiv;
+
+ if (fvco < 2000000 || fvco > 4000000)
+ continue;
+
+ mdiv = DIV_ROUND_UP(fvco, fref);
+ if (mdiv < 20 || mdiv > 255)
+ continue;
+
+ if (fref * mdiv - fvco) {
+ for (sdc = 264000; sdc <= 750000; sdc += fref)
+ if (sdc * n > fref * mdiv)
+ break;
+
+ if (sdc > 750000)
+ continue;
+
+ rational_best_approximation(fref * mdiv - fvco,
+ sdc / 16,
+ GENMASK(6, 0),
+ GENMASK(7, 0),
+ &k, &lc);
+
+ rational_best_approximation(sdc * n - fref * mdiv,
+ sdc,
+ GENMASK(6, 0),
+ GENMASK(7, 0),
+ &k_sub, &lc_sub);
+ }
+
+ break;
+ }
+
+ if (sdiv < 1)
+ return false;
+
+ if (cfg) {
+ cfg->pms_mdiv = mdiv;
+ cfg->pms_mdiv_afc = mdiv;
+ cfg->pms_pdiv = 1;
+ cfg->pms_refdiv = 1;
+ cfg->pms_sdiv = sdiv - 1;
+
+ cfg->sdm_en = k > 0 ? 1 : 0;
+ if (cfg->sdm_en) {
+ cfg->sdm_deno = lc;
+ cfg->sdm_num_sign = 1;
+ cfg->sdm_num = k;
+ cfg->sdc_n = n - 3;
+ cfg->sdc_num = k_sub;
+ cfg->sdc_deno = lc_sub;
+ }
+ }
+
+ return true;
+}
+
+static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
+ unsigned int rate)
+{
+ const struct ropll_config *cfg = NULL;
+ struct ropll_config rc = {0};
+ int i;
+
+ hdptx->rate = rate * 100;
+
+ for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
+ if (rate == ropll_tmds_cfg[i].bit_rate) {
+ cfg = &ropll_tmds_cfg[i];
+ break;
+ }
+
+ if (!cfg) {
+ if (rk_hdptx_phy_clk_pll_calc(rate, &rc)) {
+ cfg = &rc;
+ } else {
+ dev_err(hdptx->dev, "%s cannot find pll cfg\n", __func__);
+ return -EINVAL;
+ }
+ }
+
+ dev_dbg(hdptx->dev, "mdiv=%u, sdiv=%u, sdm_en=%u, k_sign=%u, k=%u, lc=%u\n",
+ cfg->pms_mdiv, cfg->pms_sdiv + 1, cfg->sdm_en,
+ cfg->sdm_num_sign, cfg->sdm_num, cfg->sdm_deno);
+
+ rk_hdptx_pre_power_up(hdptx);
+
+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_cmn_init_seq);
+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_cmn_init_seq);
+
+ regmap_write(hdptx->regmap, CMN_REG(0051), cfg->pms_mdiv);
+ regmap_write(hdptx->regmap, CMN_REG(0055), cfg->pms_mdiv_afc);
+ regmap_write(hdptx->regmap, CMN_REG(0059),
+ (cfg->pms_pdiv << 4) | cfg->pms_refdiv);
+ regmap_write(hdptx->regmap, CMN_REG(005a), cfg->pms_sdiv << 4);
+
+ regmap_update_bits(hdptx->regmap, CMN_REG(005e), ROPLL_SDM_EN_MASK,
+ FIELD_PREP(ROPLL_SDM_EN_MASK, cfg->sdm_en));
+ if (!cfg->sdm_en)
+ regmap_update_bits(hdptx->regmap, CMN_REG(005e), 0xf, 0);
+
+ regmap_update_bits(hdptx->regmap, CMN_REG(0064), ROPLL_SDM_NUM_SIGN_RBR_MASK,
+ FIELD_PREP(ROPLL_SDM_NUM_SIGN_RBR_MASK, cfg->sdm_num_sign));
+
+ regmap_write(hdptx->regmap, CMN_REG(0060), cfg->sdm_deno);
+ regmap_write(hdptx->regmap, CMN_REG(0065), cfg->sdm_num);
+
+ regmap_update_bits(hdptx->regmap, CMN_REG(0069), ROPLL_SDC_N_RBR_MASK,
+ FIELD_PREP(ROPLL_SDC_N_RBR_MASK, cfg->sdc_n));
+
+ regmap_write(hdptx->regmap, CMN_REG(006c), cfg->sdc_num);
+ regmap_write(hdptx->regmap, CMN_REG(0070), cfg->sdc_deno);
+
+ regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_POSTDIV_SEL_MASK,
+ FIELD_PREP(PLL_PCG_POSTDIV_SEL_MASK, cfg->pms_sdiv));
+
+ regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_EN,
+ PLL_PCG_CLK_EN);
+
+ return rk_hdptx_post_enable_pll(hdptx);
+}
+
+static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx,
+ unsigned int rate)
+{
+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_sb_init_seq);
+
+ regmap_write(hdptx->regmap, LNTOP_REG(0200), 0x06);
+
+ if (rate >= 3400000) {
+ /* For 1/40 bitrate clk */
+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lntop_highbr_seq);
+ } else {
+ /* For 1/10 bitrate clk */
+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lntop_lowbr_seq);
+ }
+
+ regmap_write(hdptx->regmap, LNTOP_REG(0206), 0x07);
+ regmap_write(hdptx->regmap, LNTOP_REG(0207), 0x0f);
+
+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_lane_init_seq);
+ rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lane_init_seq);
+
+ return rk_hdptx_post_enable_lane(hdptx);
+}
+
+static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx,
+ unsigned int rate)
+{
+ u32 status;
+ int ret;
+
+ if (atomic_inc_return(&hdptx->usage_count) > 1)
+ return 0;
+
+ ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &status);
+ if (ret)
+ goto dec_usage;
+
+ if (status & HDPTX_O_PLL_LOCK_DONE)
+ dev_warn(hdptx->dev, "PLL locked by unknown consumer!\n");
+
+ if (rate) {
+ ret = rk_hdptx_ropll_tmds_cmn_config(hdptx, rate);
+ if (ret)
+ goto dec_usage;
+ }
+
+ return 0;
+
+dec_usage:
+ atomic_dec(&hdptx->usage_count);
+ return ret;
+}
+
+static int rk_hdptx_phy_consumer_put(struct rk_hdptx_phy *hdptx, bool force)
+{
+ u32 status;
+ int ret;
+
+ ret = atomic_dec_return(&hdptx->usage_count);
+ if (ret > 0)
+ return 0;
+
+ if (ret < 0) {
+ dev_warn(hdptx->dev, "Usage count underflow!\n");
+ ret = -EINVAL;
+ } else {
+ ret = regmap_read(hdptx->grf, GRF_HDPTX_STATUS, &status);
+ if (!ret) {
+ if (status & HDPTX_O_PLL_LOCK_DONE)
+ rk_hdptx_phy_disable(hdptx);
+ return 0;
+ } else if (force) {
+ return 0;
+ }
+ }
+
+ atomic_inc(&hdptx->usage_count);
+ return ret;
+}
+
+static int rk_hdptx_phy_power_on(struct phy *phy)
+{
+ struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy);
+ int bus_width = phy_get_bus_width(hdptx->phy);
+ int ret;
+
+ /*
+ * FIXME: Temporary workaround to pass pixel_clk_rate
+ * from the HDMI bridge driver until phy_configure_opts_hdmi
+ * becomes available in the PHY API.
+ */
+ unsigned int rate = bus_width & 0xfffffff;
+
+ dev_dbg(hdptx->dev, "%s bus_width=%x rate=%u\n",
+ __func__, bus_width, rate);
+
+ ret = rk_hdptx_phy_consumer_get(hdptx, rate);
+ if (ret)
+ return ret;
+
+ ret = rk_hdptx_ropll_tmds_mode_config(hdptx, rate);
+ if (ret)
+ rk_hdptx_phy_consumer_put(hdptx, true);
+
+ return ret;
+}
+
+static int rk_hdptx_phy_power_off(struct phy *phy)
+{
+ struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy);
+
+ return rk_hdptx_phy_consumer_put(hdptx, false);
+}
+
+static const struct phy_ops rk_hdptx_phy_ops = {
+ .power_on = rk_hdptx_phy_power_on,
+ .power_off = rk_hdptx_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+static struct rk_hdptx_phy *to_rk_hdptx_phy(struct clk_hw *hw)
+{
+ return container_of(hw, struct rk_hdptx_phy, hw);
+}
+
+static int rk_hdptx_phy_clk_prepare(struct clk_hw *hw)
+{
+ struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
+
+ return rk_hdptx_phy_consumer_get(hdptx, hdptx->rate / 100);
+}
+
+static void rk_hdptx_phy_clk_unprepare(struct clk_hw *hw)
+{
+ struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
+
+ rk_hdptx_phy_consumer_put(hdptx, true);
+}
+
+static unsigned long rk_hdptx_phy_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
+
+ return hdptx->rate;
+}
+
+static long rk_hdptx_phy_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ u32 bit_rate = rate / 100;
+ int i;
+
+ if (rate > HDMI20_MAX_RATE)
+ return rate;
+
+ for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
+ if (bit_rate == ropll_tmds_cfg[i].bit_rate)
+ break;
+
+ if (i == ARRAY_SIZE(ropll_tmds_cfg) &&
+ !rk_hdptx_phy_clk_pll_calc(bit_rate, NULL))
+ return -EINVAL;
+
+ return rate;
+}
+
+static int rk_hdptx_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
+
+ return rk_hdptx_ropll_tmds_cmn_config(hdptx, rate / 100);
+}
+
+static const struct clk_ops hdptx_phy_clk_ops = {
+ .prepare = rk_hdptx_phy_clk_prepare,
+ .unprepare = rk_hdptx_phy_clk_unprepare,
+ .recalc_rate = rk_hdptx_phy_clk_recalc_rate,
+ .round_rate = rk_hdptx_phy_clk_round_rate,
+ .set_rate = rk_hdptx_phy_clk_set_rate,
+};
+
+static int rk_hdptx_phy_clk_register(struct rk_hdptx_phy *hdptx)
+{
+ struct device *dev = hdptx->dev;
+ const char *name, *pname;
+ struct clk *refclk;
+ int ret, id;
+
+ refclk = devm_clk_get(dev, "ref");
+ if (IS_ERR(refclk))
+ return dev_err_probe(dev, PTR_ERR(refclk),
+ "Failed to get ref clock\n");
+
+ id = of_alias_get_id(dev->of_node, "hdptxphy");
+ name = id > 0 ? "clk_hdmiphy_pixel1" : "clk_hdmiphy_pixel0";
+ pname = __clk_get_name(refclk);
+
+ hdptx->hw.init = CLK_HW_INIT(name, pname, &hdptx_phy_clk_ops,
+ CLK_GET_RATE_NOCACHE);
+
+ ret = devm_clk_hw_register(dev, &hdptx->hw);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to register clock\n");
+
+ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &hdptx->hw);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to register clk provider\n");
+ return 0;
+}
+
+static int rk_hdptx_phy_runtime_suspend(struct device *dev)
+{
+ struct rk_hdptx_phy *hdptx = dev_get_drvdata(dev);
+
+ clk_bulk_disable_unprepare(hdptx->nr_clks, hdptx->clks);
+
+ return 0;
+}
+
+static int rk_hdptx_phy_runtime_resume(struct device *dev)
+{
+ struct rk_hdptx_phy *hdptx = dev_get_drvdata(dev);
+ int ret;
+
+ ret = clk_bulk_prepare_enable(hdptx->nr_clks, hdptx->clks);
+ if (ret)
+ dev_err(hdptx->dev, "Failed to enable clocks: %d\n", ret);
+
+ return ret;
+}
+
+static int rk_hdptx_phy_probe(struct platform_device *pdev)
+{
+ struct phy_provider *phy_provider;
+ struct device *dev = &pdev->dev;
+ struct rk_hdptx_phy *hdptx;
+ void __iomem *regs;
+ int ret;
+
+ hdptx = devm_kzalloc(dev, sizeof(*hdptx), GFP_KERNEL);
+ if (!hdptx)
+ return -ENOMEM;
+
+ hdptx->dev = dev;
+
+ regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(regs))
+ return dev_err_probe(dev, PTR_ERR(regs),
+ "Failed to ioremap resource\n");
+
+ ret = devm_clk_bulk_get_all(dev, &hdptx->clks);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "Failed to get clocks\n");
+ if (ret == 0)
+ return dev_err_probe(dev, -EINVAL, "Missing clocks\n");
+
+ hdptx->nr_clks = ret;
+
+ hdptx->regmap = devm_regmap_init_mmio(dev, regs,
+ &rk_hdptx_phy_regmap_config);
+ if (IS_ERR(hdptx->regmap))
+ return dev_err_probe(dev, PTR_ERR(hdptx->regmap),
+ "Failed to init regmap\n");
+
+ hdptx->rsts[RST_APB].id = "apb";
+ hdptx->rsts[RST_INIT].id = "init";
+ hdptx->rsts[RST_CMN].id = "cmn";
+ hdptx->rsts[RST_LANE].id = "lane";
+
+ ret = devm_reset_control_bulk_get_exclusive(dev, RST_MAX, hdptx->rsts);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to get resets\n");
+
+ hdptx->grf = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "rockchip,grf");
+ if (IS_ERR(hdptx->grf))
+ return dev_err_probe(dev, PTR_ERR(hdptx->grf),
+ "Could not get GRF syscon\n");
+
+ platform_set_drvdata(pdev, hdptx);
+
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to enable runtime PM\n");
+
+ hdptx->phy = devm_phy_create(dev, NULL, &rk_hdptx_phy_ops);
+ if (IS_ERR(hdptx->phy))
+ return dev_err_probe(dev, PTR_ERR(hdptx->phy),
+ "Failed to create HDMI PHY\n");
+
+ phy_set_drvdata(hdptx->phy, hdptx);
+ phy_set_bus_width(hdptx->phy, 8);
+
+ 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");
+
+ reset_control_deassert(hdptx->rsts[RST_APB].rstc);
+ reset_control_deassert(hdptx->rsts[RST_CMN].rstc);
+ reset_control_deassert(hdptx->rsts[RST_INIT].rstc);
+
+ return rk_hdptx_phy_clk_register(hdptx);
+}
+
+static const struct dev_pm_ops rk_hdptx_phy_pm_ops = {
+ RUNTIME_PM_OPS(rk_hdptx_phy_runtime_suspend,
+ rk_hdptx_phy_runtime_resume, NULL)
+};
+
+static const struct of_device_id rk_hdptx_phy_of_match[] = {
+ { .compatible = "rockchip,rk3588-hdptx-phy", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, rk_hdptx_phy_of_match);
+
+static struct platform_driver rk_hdptx_phy_driver = {
+ .probe = rk_hdptx_phy_probe,
+ .driver = {
+ .name = "rockchip-hdptx-phy",
+ .pm = &rk_hdptx_phy_pm_ops,
+ .of_match_table = rk_hdptx_phy_of_match,
+ },
+};
+module_platform_driver(rk_hdptx_phy_driver);
+
+MODULE_AUTHOR("Algea Cao <algea.cao@rock-chips.com>");
+MODULE_AUTHOR("Cristian Ciocaltea <cristian.ciocaltea@collabora.com>");
+MODULE_DESCRIPTION("Samsung HDMI/eDP Transmitter Combo PHY Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
index 121e5961ce11..4e8ffd173096 100644
--- a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
+++ b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
@@ -35,11 +35,19 @@
#define RK3588_PCIE3PHY_GRF_CMN_CON0 0x0
#define RK3588_PCIE3PHY_GRF_PHY0_STATUS1 0x904
#define RK3588_PCIE3PHY_GRF_PHY1_STATUS1 0xa04
+#define RK3588_PCIE3PHY_GRF_PHY0_LN0_CON1 0x1004
+#define RK3588_PCIE3PHY_GRF_PHY0_LN1_CON1 0x1104
+#define RK3588_PCIE3PHY_GRF_PHY1_LN0_CON1 0x2004
+#define RK3588_PCIE3PHY_GRF_PHY1_LN1_CON1 0x2104
#define RK3588_SRAM_INIT_DONE(reg) (reg & BIT(0))
#define RK3588_BIFURCATION_LANE_0_1 BIT(0)
#define RK3588_BIFURCATION_LANE_2_3 BIT(1)
#define RK3588_LANE_AGGREGATION BIT(2)
+#define RK3588_RX_CMN_REFCLK_MODE_EN ((BIT(7) << 16) | BIT(7))
+#define RK3588_RX_CMN_REFCLK_MODE_DIS (BIT(7) << 16)
+#define RK3588_PCIE1LN_SEL_EN (GENMASK(1, 0) << 16)
+#define RK3588_PCIE30_PHY_MODE_EN (GENMASK(2, 0) << 16)
struct rockchip_p3phy_ops;
@@ -58,6 +66,7 @@ struct rockchip_p3phy_priv {
int num_clks;
int num_lanes;
u32 lanes[4];
+ u32 rx_cmn_refclk_mode[4];
};
struct rockchip_p3phy_ops {
@@ -132,39 +141,45 @@ static const struct rockchip_p3phy_ops rk3568_ops = {
static int rockchip_p3phy_rk3588_init(struct rockchip_p3phy_priv *priv)
{
u32 reg = 0;
- u8 mode = 0;
+ u8 mode = RK3588_LANE_AGGREGATION; /* default */
int ret;
+ regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_PHY0_LN0_CON1,
+ priv->rx_cmn_refclk_mode[0] ? RK3588_RX_CMN_REFCLK_MODE_EN :
+ RK3588_RX_CMN_REFCLK_MODE_DIS);
+ regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_PHY0_LN1_CON1,
+ priv->rx_cmn_refclk_mode[1] ? RK3588_RX_CMN_REFCLK_MODE_EN :
+ RK3588_RX_CMN_REFCLK_MODE_DIS);
+ regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_PHY1_LN0_CON1,
+ priv->rx_cmn_refclk_mode[2] ? RK3588_RX_CMN_REFCLK_MODE_EN :
+ RK3588_RX_CMN_REFCLK_MODE_DIS);
+ regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_PHY1_LN1_CON1,
+ priv->rx_cmn_refclk_mode[3] ? RK3588_RX_CMN_REFCLK_MODE_EN :
+ RK3588_RX_CMN_REFCLK_MODE_DIS);
+
/* Deassert PCIe PMA output clamp mode */
regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0, BIT(8) | BIT(24));
/* Set bifurcation if needed */
for (int i = 0; i < priv->num_lanes; i++) {
- if (!priv->lanes[i])
- mode |= (BIT(i) << 3);
-
if (priv->lanes[i] > 1)
- mode |= (BIT(i) >> 1);
- }
-
- if (!mode)
- reg = RK3588_LANE_AGGREGATION;
- else {
- if (mode & (BIT(0) | BIT(1)))
- reg |= RK3588_BIFURCATION_LANE_0_1;
-
- if (mode & (BIT(2) | BIT(3)))
- reg |= RK3588_BIFURCATION_LANE_2_3;
+ mode &= ~RK3588_LANE_AGGREGATION;
+ if (priv->lanes[i] == 3)
+ mode |= RK3588_BIFURCATION_LANE_0_1;
+ if (priv->lanes[i] == 4)
+ mode |= RK3588_BIFURCATION_LANE_2_3;
}
- regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0, (0x7<<16) | reg);
+ reg = mode;
+ regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0,
+ RK3588_PCIE30_PHY_MODE_EN | reg);
/* Set pcie1ln_sel in PHP_GRF_PCIESEL_CON */
if (!IS_ERR(priv->pipe_grf)) {
- reg = (mode & (BIT(6) | BIT(7))) >> 6;
+ reg = mode & (RK3588_BIFURCATION_LANE_0_1 | RK3588_BIFURCATION_LANE_2_3);
if (reg)
regmap_write(priv->pipe_grf, PHP_GRF_PCIESEL_CON,
- (reg << 16) | reg);
+ RK3588_PCIE1LN_SEL_EN | reg);
}
reset_control_deassert(priv->p30phy);
@@ -187,7 +202,7 @@ static const struct rockchip_p3phy_ops rk3588_ops = {
.phy_init = rockchip_p3phy_rk3588_init,
};
-static int rochchip_p3phy_init(struct phy *phy)
+static int rockchip_p3phy_init(struct phy *phy)
{
struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy);
int ret;
@@ -210,7 +225,7 @@ static int rochchip_p3phy_init(struct phy *phy)
return ret;
}
-static int rochchip_p3phy_exit(struct phy *phy)
+static int rockchip_p3phy_exit(struct phy *phy)
{
struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy);
@@ -219,9 +234,9 @@ static int rochchip_p3phy_exit(struct phy *phy)
return 0;
}
-static const struct phy_ops rochchip_p3phy_ops = {
- .init = rochchip_p3phy_init,
- .exit = rochchip_p3phy_exit,
+static const struct phy_ops rockchip_p3phy_ops = {
+ .init = rockchip_p3phy_init,
+ .exit = rockchip_p3phy_exit,
.set_mode = rockchip_p3phy_set_mode,
.owner = THIS_MODULE,
};
@@ -280,7 +295,24 @@ static int rockchip_p3phy_probe(struct platform_device *pdev)
return priv->num_lanes;
}
- priv->phy = devm_phy_create(dev, NULL, &rochchip_p3phy_ops);
+ ret = of_property_read_variable_u32_array(dev->of_node,
+ "rockchip,rx-common-refclk-mode",
+ priv->rx_cmn_refclk_mode, 1,
+ ARRAY_SIZE(priv->rx_cmn_refclk_mode));
+ /*
+ * if no rockchip,rx-common-refclk-mode, assume enabled for all lanes in
+ * order to be DT backwards compatible. (Since HW reset val is enabled.)
+ */
+ if (ret == -EINVAL) {
+ for (int i = 0; i < ARRAY_SIZE(priv->rx_cmn_refclk_mode); i++)
+ priv->rx_cmn_refclk_mode[i] = 1;
+ } else if (ret < 0) {
+ dev_err(dev, "failed to read rockchip,rx-common-refclk-mode property %d\n",
+ ret);
+ return ret;
+ }
+
+ priv->phy = devm_phy_create(dev, NULL, &rockchip_p3phy_ops);
if (IS_ERR(priv->phy)) {
dev_err(dev, "failed to create combphy\n");
return PTR_ERR(priv->phy);
diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c b/drivers/phy/rockchip/phy-rockchip-typec.c
index 4efcb78b0ab1..d9701b6106d5 100644
--- a/drivers/phy/rockchip/phy-rockchip-typec.c
+++ b/drivers/phy/rockchip/phy-rockchip-typec.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
+ * Copyright (C) Rockchip Electronics Co., Ltd.
* Author: Chris Zhong <zyw@rock-chips.com>
* Kever Yang <kever.yang@rock-chips.com>
*
@@ -1210,7 +1210,7 @@ MODULE_DEVICE_TABLE(of, rockchip_typec_phy_dt_ids);
static struct platform_driver rockchip_typec_phy_driver = {
.probe = rockchip_typec_phy_probe,
- .remove_new = rockchip_typec_phy_remove,
+ .remove = rockchip_typec_phy_remove,
.driver = {
.name = "rockchip-typec-phy",
.of_match_table = rockchip_typec_phy_dt_ids,
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
new file mode 100644
index 000000000000..5b1e8a3806ed
--- /dev/null
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -0,0 +1,1649 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Rockchip USBDP Combo PHY with Samsung IP block driver
+ *
+ * Copyright (C) 2021-2024 Rockchip Electronics Co., Ltd
+ * Copyright (C) 2024 Collabora Ltd
+ */
+
+#include <dt-bindings/phy/phy.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/typec_dp.h>
+#include <linux/usb/typec_mux.h>
+
+/* USBDP PHY Register Definitions */
+#define UDPHY_PCS 0x4000
+#define UDPHY_PMA 0x8000
+
+/* VO0 GRF Registers */
+#define DP_SINK_HPD_CFG BIT(11)
+#define DP_SINK_HPD_SEL BIT(10)
+#define DP_AUX_DIN_SEL BIT(9)
+#define DP_AUX_DOUT_SEL BIT(8)
+#define DP_LANE_SEL_N(n) GENMASK(2 * (n) + 1, 2 * (n))
+#define DP_LANE_SEL_ALL GENMASK(7, 0)
+
+/* PMA CMN Registers */
+#define CMN_LANE_MUX_AND_EN_OFFSET 0x0288 /* cmn_reg00A2 */
+#define CMN_DP_LANE_MUX_N(n) BIT((n) + 4)
+#define CMN_DP_LANE_EN_N(n) BIT(n)
+#define CMN_DP_LANE_MUX_ALL GENMASK(7, 4)
+#define CMN_DP_LANE_EN_ALL GENMASK(3, 0)
+
+#define CMN_DP_LINK_OFFSET 0x28c /* cmn_reg00A3 */
+#define CMN_DP_TX_LINK_BW GENMASK(6, 5)
+#define CMN_DP_TX_LANE_SWAP_EN BIT(2)
+
+#define CMN_SSC_EN_OFFSET 0x2d0 /* cmn_reg00B4 */
+#define CMN_ROPLL_SSC_EN BIT(1)
+#define CMN_LCPLL_SSC_EN BIT(0)
+
+#define CMN_ANA_LCPLL_DONE_OFFSET 0x0350 /* cmn_reg00D4 */
+#define CMN_ANA_LCPLL_LOCK_DONE BIT(7)
+#define CMN_ANA_LCPLL_AFC_DONE BIT(6)
+
+#define CMN_ANA_ROPLL_DONE_OFFSET 0x0354 /* cmn_reg00D5 */
+#define CMN_ANA_ROPLL_LOCK_DONE BIT(1)
+#define CMN_ANA_ROPLL_AFC_DONE BIT(0)
+
+#define CMN_DP_RSTN_OFFSET 0x038c /* cmn_reg00E3 */
+#define CMN_DP_INIT_RSTN BIT(3)
+#define CMN_DP_CMN_RSTN BIT(2)
+#define CMN_CDR_WTCHDG_EN BIT(1)
+#define CMN_CDR_WTCHDG_MSK_CDR_EN BIT(0)
+
+#define TRSV_ANA_TX_CLK_OFFSET_N(n) (0x854 + (n) * 0x800) /* trsv_reg0215 */
+#define LN_ANA_TX_SER_TXCLK_INV BIT(1)
+
+#define TRSV_LN0_MON_RX_CDR_DONE_OFFSET 0x0b84 /* trsv_reg02E1 */
+#define TRSV_LN0_MON_RX_CDR_LOCK_DONE BIT(0)
+
+#define TRSV_LN2_MON_RX_CDR_DONE_OFFSET 0x1b84 /* trsv_reg06E1 */
+#define TRSV_LN2_MON_RX_CDR_LOCK_DONE BIT(0)
+
+#define BIT_WRITEABLE_SHIFT 16
+#define PHY_AUX_DP_DATA_POL_NORMAL 0
+#define PHY_AUX_DP_DATA_POL_INVERT 1
+#define PHY_LANE_MUX_USB 0
+#define PHY_LANE_MUX_DP 1
+
+enum {
+ DP_BW_RBR,
+ DP_BW_HBR,
+ DP_BW_HBR2,
+ DP_BW_HBR3,
+};
+
+enum {
+ UDPHY_MODE_NONE = 0,
+ UDPHY_MODE_USB = BIT(0),
+ UDPHY_MODE_DP = BIT(1),
+ UDPHY_MODE_DP_USB = BIT(1) | BIT(0),
+};
+
+struct rk_udphy_grf_reg {
+ unsigned int offset;
+ unsigned int disable;
+ unsigned int enable;
+};
+
+#define _RK_UDPHY_GEN_GRF_REG(offset, mask, disable, enable) \
+{\
+ offset, \
+ FIELD_PREP_CONST(mask, disable) | (mask << BIT_WRITEABLE_SHIFT), \
+ FIELD_PREP_CONST(mask, enable) | (mask << BIT_WRITEABLE_SHIFT), \
+}
+
+#define RK_UDPHY_GEN_GRF_REG(offset, bitend, bitstart, disable, enable) \
+ _RK_UDPHY_GEN_GRF_REG(offset, GENMASK(bitend, bitstart), disable, enable)
+
+struct rk_udphy_grf_cfg {
+ /* u2phy-grf */
+ struct rk_udphy_grf_reg bvalid_phy_con;
+ struct rk_udphy_grf_reg bvalid_grf_con;
+
+ /* usb-grf */
+ struct rk_udphy_grf_reg usb3otg0_cfg;
+ struct rk_udphy_grf_reg usb3otg1_cfg;
+
+ /* usbdpphy-grf */
+ struct rk_udphy_grf_reg low_pwrn;
+ struct rk_udphy_grf_reg rx_lfps;
+};
+
+struct rk_udphy_vogrf_cfg {
+ /* vo-grf */
+ struct rk_udphy_grf_reg hpd_trigger;
+ u32 dp_lane_reg;
+};
+
+struct rk_udphy_dp_tx_drv_ctrl {
+ u32 trsv_reg0204;
+ u32 trsv_reg0205;
+ u32 trsv_reg0206;
+ u32 trsv_reg0207;
+};
+
+struct rk_udphy_cfg {
+ unsigned int num_phys;
+ unsigned int phy_ids[2];
+ /* resets to be requested */
+ const char * const *rst_list;
+ int num_rsts;
+
+ struct rk_udphy_grf_cfg grfcfg;
+ struct rk_udphy_vogrf_cfg vogrfcfg[2];
+ const struct rk_udphy_dp_tx_drv_ctrl (*dp_tx_ctrl_cfg[4])[4];
+ const struct rk_udphy_dp_tx_drv_ctrl (*dp_tx_ctrl_cfg_typec[4])[4];
+};
+
+struct rk_udphy {
+ struct device *dev;
+ struct regmap *pma_regmap;
+ struct regmap *u2phygrf;
+ struct regmap *udphygrf;
+ struct regmap *usbgrf;
+ struct regmap *vogrf;
+ struct typec_switch_dev *sw;
+ struct typec_mux_dev *mux;
+ struct mutex mutex; /* mutex to protect access to individual PHYs */
+
+ /* clocks and rests */
+ int num_clks;
+ struct clk_bulk_data *clks;
+ struct clk *refclk;
+ int num_rsts;
+ struct reset_control_bulk_data *rsts;
+
+ /* PHY status management */
+ bool flip;
+ bool mode_change;
+ u8 mode;
+ u8 status;
+
+ /* utilized for USB */
+ bool hs; /* flag for high-speed */
+
+ /* utilized for DP */
+ struct gpio_desc *sbu1_dc_gpio;
+ struct gpio_desc *sbu2_dc_gpio;
+ u32 lane_mux_sel[4];
+ u32 dp_lane_sel[4];
+ u32 dp_aux_dout_sel;
+ u32 dp_aux_din_sel;
+ bool dp_sink_hpd_sel;
+ bool dp_sink_hpd_cfg;
+ u8 bw;
+ int id;
+
+ bool dp_in_use;
+
+ /* PHY const config */
+ const struct rk_udphy_cfg *cfgs;
+
+ /* PHY devices */
+ struct phy *phy_dp;
+ struct phy *phy_u3;
+};
+
+static const struct rk_udphy_dp_tx_drv_ctrl rk3588_dp_tx_drv_ctrl_rbr_hbr[4][4] = {
+ /* voltage swing 0, pre-emphasis 0->3 */
+ {
+ { 0x20, 0x10, 0x42, 0xe5 },
+ { 0x26, 0x14, 0x42, 0xe5 },
+ { 0x29, 0x18, 0x42, 0xe5 },
+ { 0x2b, 0x1c, 0x43, 0xe7 },
+ },
+
+ /* voltage swing 1, pre-emphasis 0->2 */
+ {
+ { 0x23, 0x10, 0x42, 0xe7 },
+ { 0x2a, 0x17, 0x43, 0xe7 },
+ { 0x2b, 0x1a, 0x43, 0xe7 },
+ },
+
+ /* voltage swing 2, pre-emphasis 0->1 */
+ {
+ { 0x27, 0x10, 0x42, 0xe7 },
+ { 0x2b, 0x17, 0x43, 0xe7 },
+ },
+
+ /* voltage swing 3, pre-emphasis 0 */
+ {
+ { 0x29, 0x10, 0x43, 0xe7 },
+ },
+};
+
+static const struct rk_udphy_dp_tx_drv_ctrl rk3588_dp_tx_drv_ctrl_rbr_hbr_typec[4][4] = {
+ /* voltage swing 0, pre-emphasis 0->3 */
+ {
+ { 0x20, 0x10, 0x42, 0xe5 },
+ { 0x26, 0x14, 0x42, 0xe5 },
+ { 0x29, 0x18, 0x42, 0xe5 },
+ { 0x2b, 0x1c, 0x43, 0xe7 },
+ },
+
+ /* voltage swing 1, pre-emphasis 0->2 */
+ {
+ { 0x23, 0x10, 0x42, 0xe7 },
+ { 0x2a, 0x17, 0x43, 0xe7 },
+ { 0x2b, 0x1a, 0x43, 0xe7 },
+ },
+
+ /* voltage swing 2, pre-emphasis 0->1 */
+ {
+ { 0x27, 0x10, 0x43, 0x67 },
+ { 0x2b, 0x17, 0x43, 0xe7 },
+ },
+
+ /* voltage swing 3, pre-emphasis 0 */
+ {
+ { 0x29, 0x10, 0x43, 0xe7 },
+ },
+};
+
+static const struct rk_udphy_dp_tx_drv_ctrl rk3588_dp_tx_drv_ctrl_hbr2[4][4] = {
+ /* voltage swing 0, pre-emphasis 0->3 */
+ {
+ { 0x21, 0x10, 0x42, 0xe5 },
+ { 0x26, 0x14, 0x42, 0xe5 },
+ { 0x26, 0x16, 0x43, 0xe5 },
+ { 0x2a, 0x19, 0x43, 0xe7 },
+ },
+
+ /* voltage swing 1, pre-emphasis 0->2 */
+ {
+ { 0x24, 0x10, 0x42, 0xe7 },
+ { 0x2a, 0x17, 0x43, 0xe7 },
+ { 0x2b, 0x1a, 0x43, 0xe7 },
+ },
+
+ /* voltage swing 2, pre-emphasis 0->1 */
+ {
+ { 0x28, 0x10, 0x42, 0xe7 },
+ { 0x2b, 0x17, 0x43, 0xe7 },
+ },
+
+ /* voltage swing 3, pre-emphasis 0 */
+ {
+ { 0x28, 0x10, 0x43, 0xe7 },
+ },
+};
+
+static const struct rk_udphy_dp_tx_drv_ctrl rk3588_dp_tx_drv_ctrl_hbr3[4][4] = {
+ /* voltage swing 0, pre-emphasis 0->3 */
+ {
+ { 0x21, 0x10, 0x42, 0xe5 },
+ { 0x26, 0x14, 0x42, 0xe5 },
+ { 0x26, 0x16, 0x43, 0xe5 },
+ { 0x29, 0x18, 0x43, 0xe7 },
+ },
+
+ /* voltage swing 1, pre-emphasis 0->2 */
+ {
+ { 0x24, 0x10, 0x42, 0xe7 },
+ { 0x2a, 0x18, 0x43, 0xe7 },
+ { 0x2b, 0x1b, 0x43, 0xe7 }
+ },
+
+ /* voltage swing 2, pre-emphasis 0->1 */
+ {
+ { 0x27, 0x10, 0x42, 0xe7 },
+ { 0x2b, 0x18, 0x43, 0xe7 }
+ },
+
+ /* voltage swing 3, pre-emphasis 0 */
+ {
+ { 0x28, 0x10, 0x43, 0xe7 },
+ },
+};
+
+static const struct reg_sequence rk_udphy_24m_refclk_cfg[] = {
+ {0x0090, 0x68}, {0x0094, 0x68},
+ {0x0128, 0x24}, {0x012c, 0x44},
+ {0x0130, 0x3f}, {0x0134, 0x44},
+ {0x015c, 0xa9}, {0x0160, 0x71},
+ {0x0164, 0x71}, {0x0168, 0xa9},
+ {0x0174, 0xa9}, {0x0178, 0x71},
+ {0x017c, 0x71}, {0x0180, 0xa9},
+ {0x018c, 0x41}, {0x0190, 0x00},
+ {0x0194, 0x05}, {0x01ac, 0x2a},
+ {0x01b0, 0x17}, {0x01b4, 0x17},
+ {0x01b8, 0x2a}, {0x01c8, 0x04},
+ {0x01cc, 0x08}, {0x01d0, 0x08},
+ {0x01d4, 0x04}, {0x01d8, 0x20},
+ {0x01dc, 0x01}, {0x01e0, 0x09},
+ {0x01e4, 0x03}, {0x01f0, 0x29},
+ {0x01f4, 0x02}, {0x01f8, 0x02},
+ {0x01fc, 0x29}, {0x0208, 0x2a},
+ {0x020c, 0x17}, {0x0210, 0x17},
+ {0x0214, 0x2a}, {0x0224, 0x20},
+ {0x03f0, 0x0a}, {0x03f4, 0x07},
+ {0x03f8, 0x07}, {0x03fc, 0x0c},
+ {0x0404, 0x12}, {0x0408, 0x1a},
+ {0x040c, 0x1a}, {0x0410, 0x3f},
+ {0x0ce0, 0x68}, {0x0ce8, 0xd0},
+ {0x0cf0, 0x87}, {0x0cf8, 0x70},
+ {0x0d00, 0x70}, {0x0d08, 0xa9},
+ {0x1ce0, 0x68}, {0x1ce8, 0xd0},
+ {0x1cf0, 0x87}, {0x1cf8, 0x70},
+ {0x1d00, 0x70}, {0x1d08, 0xa9},
+ {0x0a3c, 0xd0}, {0x0a44, 0xd0},
+ {0x0a48, 0x01}, {0x0a4c, 0x0d},
+ {0x0a54, 0xe0}, {0x0a5c, 0xe0},
+ {0x0a64, 0xa8}, {0x1a3c, 0xd0},
+ {0x1a44, 0xd0}, {0x1a48, 0x01},
+ {0x1a4c, 0x0d}, {0x1a54, 0xe0},
+ {0x1a5c, 0xe0}, {0x1a64, 0xa8}
+};
+
+static const struct reg_sequence rk_udphy_26m_refclk_cfg[] = {
+ {0x0830, 0x07}, {0x085c, 0x80},
+ {0x1030, 0x07}, {0x105c, 0x80},
+ {0x1830, 0x07}, {0x185c, 0x80},
+ {0x2030, 0x07}, {0x205c, 0x80},
+ {0x0228, 0x38}, {0x0104, 0x44},
+ {0x0248, 0x44}, {0x038c, 0x02},
+ {0x0878, 0x04}, {0x1878, 0x04},
+ {0x0898, 0x77}, {0x1898, 0x77},
+ {0x0054, 0x01}, {0x00e0, 0x38},
+ {0x0060, 0x24}, {0x0064, 0x77},
+ {0x0070, 0x76}, {0x0234, 0xe8},
+ {0x0af4, 0x15}, {0x1af4, 0x15},
+ {0x081c, 0xe5}, {0x181c, 0xe5},
+ {0x099c, 0x48}, {0x199c, 0x48},
+ {0x09a4, 0x07}, {0x09a8, 0x22},
+ {0x19a4, 0x07}, {0x19a8, 0x22},
+ {0x09b8, 0x3e}, {0x19b8, 0x3e},
+ {0x09e4, 0x02}, {0x19e4, 0x02},
+ {0x0a34, 0x1e}, {0x1a34, 0x1e},
+ {0x0a98, 0x2f}, {0x1a98, 0x2f},
+ {0x0c30, 0x0e}, {0x0c48, 0x06},
+ {0x1c30, 0x0e}, {0x1c48, 0x06},
+ {0x028c, 0x18}, {0x0af0, 0x00},
+ {0x1af0, 0x00}
+};
+
+static const struct reg_sequence rk_udphy_init_sequence[] = {
+ {0x0104, 0x44}, {0x0234, 0xe8},
+ {0x0248, 0x44}, {0x028c, 0x18},
+ {0x081c, 0xe5}, {0x0878, 0x00},
+ {0x0994, 0x1c}, {0x0af0, 0x00},
+ {0x181c, 0xe5}, {0x1878, 0x00},
+ {0x1994, 0x1c}, {0x1af0, 0x00},
+ {0x0428, 0x60}, {0x0d58, 0x33},
+ {0x1d58, 0x33}, {0x0990, 0x74},
+ {0x0d64, 0x17}, {0x08c8, 0x13},
+ {0x1990, 0x74}, {0x1d64, 0x17},
+ {0x18c8, 0x13}, {0x0d90, 0x40},
+ {0x0da8, 0x40}, {0x0dc0, 0x40},
+ {0x0dd8, 0x40}, {0x1d90, 0x40},
+ {0x1da8, 0x40}, {0x1dc0, 0x40},
+ {0x1dd8, 0x40}, {0x03c0, 0x30},
+ {0x03c4, 0x06}, {0x0e10, 0x00},
+ {0x1e10, 0x00}, {0x043c, 0x0f},
+ {0x0d2c, 0xff}, {0x1d2c, 0xff},
+ {0x0d34, 0x0f}, {0x1d34, 0x0f},
+ {0x08fc, 0x2a}, {0x0914, 0x28},
+ {0x0a30, 0x03}, {0x0e38, 0x03},
+ {0x0ecc, 0x27}, {0x0ed0, 0x22},
+ {0x0ed4, 0x26}, {0x18fc, 0x2a},
+ {0x1914, 0x28}, {0x1a30, 0x03},
+ {0x1e38, 0x03}, {0x1ecc, 0x27},
+ {0x1ed0, 0x22}, {0x1ed4, 0x26},
+ {0x0048, 0x0f}, {0x0060, 0x3c},
+ {0x0064, 0xf7}, {0x006c, 0x20},
+ {0x0070, 0x7d}, {0x0074, 0x68},
+ {0x0af4, 0x1a}, {0x1af4, 0x1a},
+ {0x0440, 0x3f}, {0x10d4, 0x08},
+ {0x20d4, 0x08}, {0x00d4, 0x30},
+ {0x0024, 0x6e},
+};
+
+static inline int rk_udphy_grfreg_write(struct regmap *base,
+ const struct rk_udphy_grf_reg *reg, bool en)
+{
+ return regmap_write(base, reg->offset, en ? reg->enable : reg->disable);
+}
+
+static int rk_udphy_clk_init(struct rk_udphy *udphy, struct device *dev)
+{
+ int i;
+
+ udphy->num_clks = devm_clk_bulk_get_all(dev, &udphy->clks);
+ if (udphy->num_clks < 1)
+ return -ENODEV;
+
+ /* used for configure phy reference clock frequency */
+ for (i = 0; i < udphy->num_clks; i++) {
+ if (!strncmp(udphy->clks[i].id, "refclk", 6)) {
+ udphy->refclk = udphy->clks[i].clk;
+ break;
+ }
+ }
+
+ if (!udphy->refclk)
+ return dev_err_probe(udphy->dev, -EINVAL, "no refclk found\n");
+
+ return 0;
+}
+
+static int rk_udphy_reset_assert_all(struct rk_udphy *udphy)
+{
+ return reset_control_bulk_assert(udphy->num_rsts, udphy->rsts);
+}
+
+static int rk_udphy_reset_deassert_all(struct rk_udphy *udphy)
+{
+ return reset_control_bulk_deassert(udphy->num_rsts, udphy->rsts);
+}
+
+static int rk_udphy_reset_deassert(struct rk_udphy *udphy, char *name)
+{
+ struct reset_control_bulk_data *list = udphy->rsts;
+ int idx;
+
+ for (idx = 0; idx < udphy->num_rsts; idx++) {
+ if (!strcmp(list[idx].id, name))
+ return reset_control_deassert(list[idx].rstc);
+ }
+
+ return -EINVAL;
+}
+
+static int rk_udphy_reset_init(struct rk_udphy *udphy, struct device *dev)
+{
+ const struct rk_udphy_cfg *cfg = udphy->cfgs;
+ int idx;
+
+ udphy->num_rsts = cfg->num_rsts;
+ udphy->rsts = devm_kcalloc(dev, udphy->num_rsts,
+ sizeof(*udphy->rsts), GFP_KERNEL);
+ if (!udphy->rsts)
+ return -ENOMEM;
+
+ for (idx = 0; idx < cfg->num_rsts; idx++)
+ udphy->rsts[idx].id = cfg->rst_list[idx];
+
+ return devm_reset_control_bulk_get_exclusive(dev, cfg->num_rsts,
+ udphy->rsts);
+}
+
+static void rk_udphy_u3_port_disable(struct rk_udphy *udphy, u8 disable)
+{
+ const struct rk_udphy_cfg *cfg = udphy->cfgs;
+ const struct rk_udphy_grf_reg *preg;
+
+ preg = udphy->id ? &cfg->grfcfg.usb3otg1_cfg : &cfg->grfcfg.usb3otg0_cfg;
+ rk_udphy_grfreg_write(udphy->usbgrf, preg, disable);
+}
+
+static void rk_udphy_usb_bvalid_enable(struct rk_udphy *udphy, u8 enable)
+{
+ const struct rk_udphy_cfg *cfg = udphy->cfgs;
+
+ rk_udphy_grfreg_write(udphy->u2phygrf, &cfg->grfcfg.bvalid_phy_con, enable);
+ rk_udphy_grfreg_write(udphy->u2phygrf, &cfg->grfcfg.bvalid_grf_con, enable);
+}
+
+/*
+ * In usb/dp combo phy driver, here are 2 ways to mapping lanes.
+ *
+ * 1 Type-C Mapping table (DP_Alt_Mode V1.0b remove ABF pin mapping)
+ * ---------------------------------------------------------------------------
+ * Type-C Pin B11-B10 A2-A3 A11-A10 B2-B3
+ * PHY Pad ln0(tx/rx) ln1(tx) ln2(tx/rx) ln3(tx)
+ * C/E(Normal) dpln3 dpln2 dpln0 dpln1
+ * C/E(Flip ) dpln0 dpln1 dpln3 dpln2
+ * D/F(Normal) usbrx usbtx dpln0 dpln1
+ * D/F(Flip ) dpln0 dpln1 usbrx usbtx
+ * A(Normal ) dpln3 dpln1 dpln2 dpln0
+ * A(Flip ) dpln2 dpln0 dpln3 dpln1
+ * B(Normal ) usbrx usbtx dpln1 dpln0
+ * B(Flip ) dpln1 dpln0 usbrx usbtx
+ * ---------------------------------------------------------------------------
+ *
+ * 2 Mapping the lanes in dtsi
+ * if all 4 lane assignment for dp function, define rockchip,dp-lane-mux = <x x x x>;
+ * sample as follow:
+ * ---------------------------------------------------------------------------
+ * B11-B10 A2-A3 A11-A10 B2-B3
+ * rockchip,dp-lane-mux ln0(tx/rx) ln1(tx) ln2(tx/rx) ln3(tx)
+ * <0 1 2 3> dpln0 dpln1 dpln2 dpln3
+ * <2 3 0 1> dpln2 dpln3 dpln0 dpln1
+ * ---------------------------------------------------------------------------
+ * if 2 lane for dp function, 2 lane for usb function, define rockchip,dp-lane-mux = <x x>;
+ * sample as follow:
+ * ---------------------------------------------------------------------------
+ * B11-B10 A2-A3 A11-A10 B2-B3
+ * rockchip,dp-lane-mux ln0(tx/rx) ln1(tx) ln2(tx/rx) ln3(tx)
+ * <0 1> dpln0 dpln1 usbrx usbtx
+ * <2 3> usbrx usbtx dpln0 dpln1
+ * ---------------------------------------------------------------------------
+ */
+
+static void rk_udphy_dplane_select(struct rk_udphy *udphy)
+{
+ const struct rk_udphy_cfg *cfg = udphy->cfgs;
+ u32 value = 0;
+
+ switch (udphy->mode) {
+ case UDPHY_MODE_DP:
+ value |= 2 << udphy->dp_lane_sel[2] * 2;
+ value |= 3 << udphy->dp_lane_sel[3] * 2;
+ fallthrough;
+
+ case UDPHY_MODE_DP_USB:
+ value |= 0 << udphy->dp_lane_sel[0] * 2;
+ value |= 1 << udphy->dp_lane_sel[1] * 2;
+ break;
+
+ case UDPHY_MODE_USB:
+ break;
+
+ default:
+ break;
+ }
+
+ regmap_write(udphy->vogrf, cfg->vogrfcfg[udphy->id].dp_lane_reg,
+ ((DP_AUX_DIN_SEL | DP_AUX_DOUT_SEL | DP_LANE_SEL_ALL) << 16) |
+ FIELD_PREP(DP_AUX_DIN_SEL, udphy->dp_aux_din_sel) |
+ FIELD_PREP(DP_AUX_DOUT_SEL, udphy->dp_aux_dout_sel) | value);
+}
+
+static int rk_udphy_dplane_get(struct rk_udphy *udphy)
+{
+ int dp_lanes;
+
+ switch (udphy->mode) {
+ case UDPHY_MODE_DP:
+ dp_lanes = 4;
+ break;
+
+ case UDPHY_MODE_DP_USB:
+ dp_lanes = 2;
+ break;
+
+ case UDPHY_MODE_USB:
+ default:
+ dp_lanes = 0;
+ break;
+ }
+
+ return dp_lanes;
+}
+
+static void rk_udphy_dplane_enable(struct rk_udphy *udphy, int dp_lanes)
+{
+ u32 val = 0;
+ int i;
+
+ for (i = 0; i < dp_lanes; i++)
+ val |= BIT(udphy->dp_lane_sel[i]);
+
+ regmap_update_bits(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET, CMN_DP_LANE_EN_ALL,
+ FIELD_PREP(CMN_DP_LANE_EN_ALL, val));
+
+ if (!dp_lanes)
+ regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET,
+ CMN_DP_CMN_RSTN, FIELD_PREP(CMN_DP_CMN_RSTN, 0x0));
+}
+
+static void rk_udphy_dp_hpd_event_trigger(struct rk_udphy *udphy, bool hpd)
+{
+ const struct rk_udphy_cfg *cfg = udphy->cfgs;
+
+ udphy->dp_sink_hpd_sel = true;
+ udphy->dp_sink_hpd_cfg = hpd;
+
+ if (!udphy->dp_in_use)
+ return;
+
+ rk_udphy_grfreg_write(udphy->vogrf, &cfg->vogrfcfg[udphy->id].hpd_trigger, hpd);
+}
+
+static void rk_udphy_set_typec_default_mapping(struct rk_udphy *udphy)
+{
+ if (udphy->flip) {
+ udphy->dp_lane_sel[0] = 0;
+ udphy->dp_lane_sel[1] = 1;
+ udphy->dp_lane_sel[2] = 3;
+ udphy->dp_lane_sel[3] = 2;
+ udphy->lane_mux_sel[0] = PHY_LANE_MUX_DP;
+ udphy->lane_mux_sel[1] = PHY_LANE_MUX_DP;
+ udphy->lane_mux_sel[2] = PHY_LANE_MUX_USB;
+ udphy->lane_mux_sel[3] = PHY_LANE_MUX_USB;
+ udphy->dp_aux_dout_sel = PHY_AUX_DP_DATA_POL_INVERT;
+ udphy->dp_aux_din_sel = PHY_AUX_DP_DATA_POL_INVERT;
+ gpiod_set_value_cansleep(udphy->sbu1_dc_gpio, 1);
+ gpiod_set_value_cansleep(udphy->sbu2_dc_gpio, 0);
+ } else {
+ udphy->dp_lane_sel[0] = 2;
+ udphy->dp_lane_sel[1] = 3;
+ udphy->dp_lane_sel[2] = 1;
+ udphy->dp_lane_sel[3] = 0;
+ udphy->lane_mux_sel[0] = PHY_LANE_MUX_USB;
+ udphy->lane_mux_sel[1] = PHY_LANE_MUX_USB;
+ udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP;
+ udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP;
+ udphy->dp_aux_dout_sel = PHY_AUX_DP_DATA_POL_NORMAL;
+ udphy->dp_aux_din_sel = PHY_AUX_DP_DATA_POL_NORMAL;
+ gpiod_set_value_cansleep(udphy->sbu1_dc_gpio, 0);
+ gpiod_set_value_cansleep(udphy->sbu2_dc_gpio, 1);
+ }
+
+ udphy->mode = UDPHY_MODE_DP_USB;
+}
+
+static int rk_udphy_orien_sw_set(struct typec_switch_dev *sw,
+ enum typec_orientation orien)
+{
+ struct rk_udphy *udphy = typec_switch_get_drvdata(sw);
+
+ mutex_lock(&udphy->mutex);
+
+ if (orien == TYPEC_ORIENTATION_NONE) {
+ gpiod_set_value_cansleep(udphy->sbu1_dc_gpio, 0);
+ gpiod_set_value_cansleep(udphy->sbu2_dc_gpio, 0);
+ /* unattached */
+ rk_udphy_usb_bvalid_enable(udphy, false);
+ goto unlock_ret;
+ }
+
+ udphy->flip = (orien == TYPEC_ORIENTATION_REVERSE) ? true : false;
+ rk_udphy_set_typec_default_mapping(udphy);
+ rk_udphy_usb_bvalid_enable(udphy, true);
+
+unlock_ret:
+ mutex_unlock(&udphy->mutex);
+ return 0;
+}
+
+static void rk_udphy_orien_switch_unregister(void *data)
+{
+ struct rk_udphy *udphy = data;
+
+ typec_switch_unregister(udphy->sw);
+}
+
+static int rk_udphy_setup_orien_switch(struct rk_udphy *udphy)
+{
+ struct typec_switch_desc sw_desc = { };
+
+ sw_desc.drvdata = udphy;
+ sw_desc.fwnode = dev_fwnode(udphy->dev);
+ sw_desc.set = rk_udphy_orien_sw_set;
+
+ udphy->sw = typec_switch_register(udphy->dev, &sw_desc);
+ if (IS_ERR(udphy->sw)) {
+ dev_err(udphy->dev, "Error register typec orientation switch: %ld\n",
+ PTR_ERR(udphy->sw));
+ return PTR_ERR(udphy->sw);
+ }
+
+ return devm_add_action_or_reset(udphy->dev,
+ rk_udphy_orien_switch_unregister, udphy);
+}
+
+static int rk_udphy_refclk_set(struct rk_udphy *udphy)
+{
+ unsigned long rate;
+ int ret;
+
+ /* configure phy reference clock */
+ rate = clk_get_rate(udphy->refclk);
+ dev_dbg(udphy->dev, "refclk freq %ld\n", rate);
+
+ switch (rate) {
+ case 24000000:
+ ret = regmap_multi_reg_write(udphy->pma_regmap, rk_udphy_24m_refclk_cfg,
+ ARRAY_SIZE(rk_udphy_24m_refclk_cfg));
+ if (ret)
+ return ret;
+ break;
+
+ case 26000000:
+ /* register default is 26MHz */
+ ret = regmap_multi_reg_write(udphy->pma_regmap, rk_udphy_26m_refclk_cfg,
+ ARRAY_SIZE(rk_udphy_26m_refclk_cfg));
+ if (ret)
+ return ret;
+ break;
+
+ default:
+ dev_err(udphy->dev, "unsupported refclk freq %ld\n", rate);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int rk_udphy_status_check(struct rk_udphy *udphy)
+{
+ unsigned int val;
+ int ret;
+
+ /* LCPLL check */
+ if (udphy->mode & UDPHY_MODE_USB) {
+ ret = regmap_read_poll_timeout(udphy->pma_regmap, CMN_ANA_LCPLL_DONE_OFFSET,
+ val, (val & CMN_ANA_LCPLL_AFC_DONE) &&
+ (val & CMN_ANA_LCPLL_LOCK_DONE), 200, 100000);
+ if (ret) {
+ dev_err(udphy->dev, "cmn ana lcpll lock timeout\n");
+ /*
+ * If earlier software (U-Boot) enabled USB once already
+ * the PLL may have problems locking on the first try.
+ * It will be successful on the second try, so for the
+ * time being a -EPROBE_DEFER will solve the issue.
+ *
+ * This requires further investigation to understand the
+ * root cause, especially considering that the driver is
+ * asserting all reset lines at probe time.
+ */
+ return -EPROBE_DEFER;
+ }
+
+ if (!udphy->flip) {
+ ret = regmap_read_poll_timeout(udphy->pma_regmap,
+ TRSV_LN0_MON_RX_CDR_DONE_OFFSET, val,
+ val & TRSV_LN0_MON_RX_CDR_LOCK_DONE,
+ 200, 100000);
+ if (ret)
+ dev_err(udphy->dev, "trsv ln0 mon rx cdr lock timeout\n");
+ } else {
+ ret = regmap_read_poll_timeout(udphy->pma_regmap,
+ TRSV_LN2_MON_RX_CDR_DONE_OFFSET, val,
+ val & TRSV_LN2_MON_RX_CDR_LOCK_DONE,
+ 200, 100000);
+ if (ret)
+ dev_err(udphy->dev, "trsv ln2 mon rx cdr lock timeout\n");
+ }
+ }
+
+ return 0;
+}
+
+static int rk_udphy_init(struct rk_udphy *udphy)
+{
+ const struct rk_udphy_cfg *cfg = udphy->cfgs;
+ int ret;
+
+ rk_udphy_reset_assert_all(udphy);
+ usleep_range(10000, 11000);
+
+ /* enable rx lfps for usb */
+ if (udphy->mode & UDPHY_MODE_USB)
+ rk_udphy_grfreg_write(udphy->udphygrf, &cfg->grfcfg.rx_lfps, true);
+
+ /* Step 1: power on pma and deassert apb rstn */
+ rk_udphy_grfreg_write(udphy->udphygrf, &cfg->grfcfg.low_pwrn, true);
+
+ rk_udphy_reset_deassert(udphy, "pma_apb");
+ rk_udphy_reset_deassert(udphy, "pcs_apb");
+
+ /* Step 2: set init sequence and phy refclk */
+ ret = regmap_multi_reg_write(udphy->pma_regmap, rk_udphy_init_sequence,
+ ARRAY_SIZE(rk_udphy_init_sequence));
+ if (ret) {
+ dev_err(udphy->dev, "init sequence set error %d\n", ret);
+ goto assert_resets;
+ }
+
+ ret = rk_udphy_refclk_set(udphy);
+ if (ret) {
+ dev_err(udphy->dev, "refclk set error %d\n", ret);
+ goto assert_resets;
+ }
+
+ /* Step 3: configure lane mux */
+ regmap_update_bits(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET,
+ CMN_DP_LANE_MUX_ALL | CMN_DP_LANE_EN_ALL,
+ FIELD_PREP(CMN_DP_LANE_MUX_N(3), udphy->lane_mux_sel[3]) |
+ FIELD_PREP(CMN_DP_LANE_MUX_N(2), udphy->lane_mux_sel[2]) |
+ FIELD_PREP(CMN_DP_LANE_MUX_N(1), udphy->lane_mux_sel[1]) |
+ FIELD_PREP(CMN_DP_LANE_MUX_N(0), udphy->lane_mux_sel[0]) |
+ FIELD_PREP(CMN_DP_LANE_EN_ALL, 0));
+
+ /* Step 4: deassert init rstn and wait for 200ns from datasheet */
+ if (udphy->mode & UDPHY_MODE_USB)
+ rk_udphy_reset_deassert(udphy, "init");
+
+ if (udphy->mode & UDPHY_MODE_DP) {
+ regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET,
+ CMN_DP_INIT_RSTN,
+ FIELD_PREP(CMN_DP_INIT_RSTN, 0x1));
+ }
+
+ udelay(1);
+
+ /* Step 5: deassert cmn/lane rstn */
+ if (udphy->mode & UDPHY_MODE_USB) {
+ rk_udphy_reset_deassert(udphy, "cmn");
+ rk_udphy_reset_deassert(udphy, "lane");
+ }
+
+ /* Step 6: wait for lock done of pll */
+ ret = rk_udphy_status_check(udphy);
+ if (ret)
+ goto assert_resets;
+
+ return 0;
+
+assert_resets:
+ rk_udphy_reset_assert_all(udphy);
+ return ret;
+}
+
+static int rk_udphy_setup(struct rk_udphy *udphy)
+{
+ int ret;
+
+ ret = clk_bulk_prepare_enable(udphy->num_clks, udphy->clks);
+ if (ret) {
+ dev_err(udphy->dev, "failed to enable clk\n");
+ return ret;
+ }
+
+ ret = rk_udphy_init(udphy);
+ if (ret) {
+ dev_err(udphy->dev, "failed to init combophy\n");
+ clk_bulk_disable_unprepare(udphy->num_clks, udphy->clks);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void rk_udphy_disable(struct rk_udphy *udphy)
+{
+ clk_bulk_disable_unprepare(udphy->num_clks, udphy->clks);
+ rk_udphy_reset_assert_all(udphy);
+}
+
+static int rk_udphy_parse_lane_mux_data(struct rk_udphy *udphy)
+{
+ int ret, i, num_lanes;
+
+ num_lanes = device_property_count_u32(udphy->dev, "rockchip,dp-lane-mux");
+ if (num_lanes < 0) {
+ dev_dbg(udphy->dev, "no dp-lane-mux, following dp alt mode\n");
+ udphy->mode = UDPHY_MODE_USB;
+ return 0;
+ }
+
+ if (num_lanes != 2 && num_lanes != 4)
+ return dev_err_probe(udphy->dev, -EINVAL,
+ "invalid number of lane mux\n");
+
+ ret = device_property_read_u32_array(udphy->dev, "rockchip,dp-lane-mux",
+ udphy->dp_lane_sel, num_lanes);
+ if (ret)
+ return dev_err_probe(udphy->dev, ret, "get dp lane mux failed\n");
+
+ for (i = 0; i < num_lanes; i++) {
+ int j;
+
+ if (udphy->dp_lane_sel[i] > 3)
+ return dev_err_probe(udphy->dev, -EINVAL,
+ "lane mux between 0 and 3, exceeding the range\n");
+
+ udphy->lane_mux_sel[udphy->dp_lane_sel[i]] = PHY_LANE_MUX_DP;
+
+ for (j = i + 1; j < num_lanes; j++) {
+ if (udphy->dp_lane_sel[i] == udphy->dp_lane_sel[j])
+ return dev_err_probe(udphy->dev, -EINVAL,
+ "set repeat lane mux value\n");
+ }
+ }
+
+ udphy->mode = UDPHY_MODE_DP;
+ if (num_lanes == 2) {
+ udphy->mode |= UDPHY_MODE_USB;
+ udphy->flip = (udphy->lane_mux_sel[0] == PHY_LANE_MUX_DP);
+ }
+
+ return 0;
+}
+
+static int rk_udphy_get_initial_status(struct rk_udphy *udphy)
+{
+ int ret;
+ u32 value;
+
+ ret = clk_bulk_prepare_enable(udphy->num_clks, udphy->clks);
+ if (ret) {
+ dev_err(udphy->dev, "failed to enable clk\n");
+ return ret;
+ }
+
+ rk_udphy_reset_deassert_all(udphy);
+
+ regmap_read(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET, &value);
+ if (FIELD_GET(CMN_DP_LANE_MUX_ALL, value) && FIELD_GET(CMN_DP_LANE_EN_ALL, value))
+ udphy->status = UDPHY_MODE_DP;
+ else
+ rk_udphy_disable(udphy);
+
+ return 0;
+}
+
+static int rk_udphy_parse_dt(struct rk_udphy *udphy)
+{
+ struct device *dev = udphy->dev;
+ struct device_node *np = dev_of_node(dev);
+ enum usb_device_speed maximum_speed;
+ int ret;
+
+ udphy->u2phygrf = syscon_regmap_lookup_by_phandle(np, "rockchip,u2phy-grf");
+ if (IS_ERR(udphy->u2phygrf))
+ return dev_err_probe(dev, PTR_ERR(udphy->u2phygrf), "failed to get u2phy-grf\n");
+
+ udphy->udphygrf = syscon_regmap_lookup_by_phandle(np, "rockchip,usbdpphy-grf");
+ if (IS_ERR(udphy->udphygrf))
+ return dev_err_probe(dev, PTR_ERR(udphy->udphygrf), "failed to get usbdpphy-grf\n");
+
+ udphy->usbgrf = syscon_regmap_lookup_by_phandle(np, "rockchip,usb-grf");
+ if (IS_ERR(udphy->usbgrf))
+ return dev_err_probe(dev, PTR_ERR(udphy->usbgrf), "failed to get usb-grf\n");
+
+ udphy->vogrf = syscon_regmap_lookup_by_phandle(np, "rockchip,vo-grf");
+ if (IS_ERR(udphy->vogrf))
+ return dev_err_probe(dev, PTR_ERR(udphy->vogrf), "failed to get vo-grf\n");
+
+ ret = rk_udphy_parse_lane_mux_data(udphy);
+ if (ret)
+ return ret;
+
+ udphy->sbu1_dc_gpio = devm_gpiod_get_optional(dev, "sbu1-dc", GPIOD_OUT_LOW);
+ if (IS_ERR(udphy->sbu1_dc_gpio))
+ return PTR_ERR(udphy->sbu1_dc_gpio);
+
+ udphy->sbu2_dc_gpio = devm_gpiod_get_optional(dev, "sbu2-dc", GPIOD_OUT_LOW);
+ if (IS_ERR(udphy->sbu2_dc_gpio))
+ return PTR_ERR(udphy->sbu2_dc_gpio);
+
+ if (device_property_present(dev, "maximum-speed")) {
+ maximum_speed = usb_get_maximum_speed(dev);
+ udphy->hs = maximum_speed <= USB_SPEED_HIGH ? true : false;
+ }
+
+ ret = rk_udphy_clk_init(udphy, dev);
+ if (ret)
+ return ret;
+
+ return rk_udphy_reset_init(udphy, dev);
+}
+
+static int rk_udphy_power_on(struct rk_udphy *udphy, u8 mode)
+{
+ int ret;
+
+ if (!(udphy->mode & mode)) {
+ dev_info(udphy->dev, "mode 0x%02x is not support\n", mode);
+ return 0;
+ }
+
+ if (udphy->status == UDPHY_MODE_NONE) {
+ udphy->mode_change = false;
+ ret = rk_udphy_setup(udphy);
+ if (ret)
+ return ret;
+
+ if (udphy->mode & UDPHY_MODE_USB)
+ rk_udphy_u3_port_disable(udphy, false);
+ } else if (udphy->mode_change) {
+ udphy->mode_change = false;
+ udphy->status = UDPHY_MODE_NONE;
+ if (udphy->mode == UDPHY_MODE_DP)
+ rk_udphy_u3_port_disable(udphy, true);
+
+ rk_udphy_disable(udphy);
+ ret = rk_udphy_setup(udphy);
+ if (ret)
+ return ret;
+ }
+
+ udphy->status |= mode;
+
+ return 0;
+}
+
+static void rk_udphy_power_off(struct rk_udphy *udphy, u8 mode)
+{
+ if (!(udphy->mode & mode)) {
+ dev_info(udphy->dev, "mode 0x%02x is not support\n", mode);
+ return;
+ }
+
+ if (!udphy->status)
+ return;
+
+ udphy->status &= ~mode;
+
+ if (udphy->status == UDPHY_MODE_NONE)
+ rk_udphy_disable(udphy);
+}
+
+static int rk_udphy_dp_phy_init(struct phy *phy)
+{
+ struct rk_udphy *udphy = phy_get_drvdata(phy);
+
+ mutex_lock(&udphy->mutex);
+
+ udphy->dp_in_use = true;
+ rk_udphy_dp_hpd_event_trigger(udphy, udphy->dp_sink_hpd_cfg);
+
+ mutex_unlock(&udphy->mutex);
+
+ return 0;
+}
+
+static int rk_udphy_dp_phy_exit(struct phy *phy)
+{
+ struct rk_udphy *udphy = phy_get_drvdata(phy);
+
+ mutex_lock(&udphy->mutex);
+ udphy->dp_in_use = false;
+ mutex_unlock(&udphy->mutex);
+ return 0;
+}
+
+static int rk_udphy_dp_phy_power_on(struct phy *phy)
+{
+ struct rk_udphy *udphy = phy_get_drvdata(phy);
+ int ret, dp_lanes;
+
+ mutex_lock(&udphy->mutex);
+
+ dp_lanes = rk_udphy_dplane_get(udphy);
+ phy_set_bus_width(phy, dp_lanes);
+
+ ret = rk_udphy_power_on(udphy, UDPHY_MODE_DP);
+ if (ret)
+ goto unlock;
+
+ rk_udphy_dplane_enable(udphy, dp_lanes);
+
+ rk_udphy_dplane_select(udphy);
+
+unlock:
+ mutex_unlock(&udphy->mutex);
+ /*
+ * If data send by aux channel too fast after phy power on,
+ * the aux may be not ready which will cause aux error. Adding
+ * delay to avoid this issue.
+ */
+ usleep_range(10000, 11000);
+ return ret;
+}
+
+static int rk_udphy_dp_phy_power_off(struct phy *phy)
+{
+ struct rk_udphy *udphy = phy_get_drvdata(phy);
+
+ mutex_lock(&udphy->mutex);
+ rk_udphy_dplane_enable(udphy, 0);
+ rk_udphy_power_off(udphy, UDPHY_MODE_DP);
+ mutex_unlock(&udphy->mutex);
+
+ return 0;
+}
+
+static int rk_udphy_dp_phy_verify_link_rate(unsigned int link_rate)
+{
+ switch (link_rate) {
+ case 1620:
+ case 2700:
+ case 5400:
+ case 8100:
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int rk_udphy_dp_phy_verify_config(struct rk_udphy *udphy,
+ struct phy_configure_opts_dp *dp)
+{
+ int i, ret;
+
+ /* If changing link rate was required, verify it's supported. */
+ ret = rk_udphy_dp_phy_verify_link_rate(dp->link_rate);
+ if (ret)
+ return ret;
+
+ /* Verify lane count. */
+ switch (dp->lanes) {
+ case 1:
+ case 2:
+ case 4:
+ /* valid lane count. */
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ /*
+ * If changing voltages is required, check swing and pre-emphasis
+ * levels, per-lane.
+ */
+ if (dp->set_voltages) {
+ /* Lane count verified previously. */
+ for (i = 0; i < dp->lanes; i++) {
+ if (dp->voltage[i] > 3 || dp->pre[i] > 3)
+ return -EINVAL;
+
+ /*
+ * Sum of voltage swing and pre-emphasis levels cannot
+ * exceed 3.
+ */
+ if (dp->voltage[i] + dp->pre[i] > 3)
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static void rk_udphy_dp_set_voltage(struct rk_udphy *udphy, u8 bw,
+ u32 voltage, u32 pre, u32 lane)
+{
+ const struct rk_udphy_cfg *cfg = udphy->cfgs;
+ const struct rk_udphy_dp_tx_drv_ctrl (*dp_ctrl)[4];
+ u32 offset = 0x800 * lane;
+ u32 val;
+
+ if (udphy->mux)
+ dp_ctrl = cfg->dp_tx_ctrl_cfg_typec[bw];
+ else
+ dp_ctrl = cfg->dp_tx_ctrl_cfg[bw];
+
+ val = dp_ctrl[voltage][pre].trsv_reg0204;
+ regmap_write(udphy->pma_regmap, 0x0810 + offset, val);
+
+ val = dp_ctrl[voltage][pre].trsv_reg0205;
+ regmap_write(udphy->pma_regmap, 0x0814 + offset, val);
+
+ val = dp_ctrl[voltage][pre].trsv_reg0206;
+ regmap_write(udphy->pma_regmap, 0x0818 + offset, val);
+
+ val = dp_ctrl[voltage][pre].trsv_reg0207;
+ regmap_write(udphy->pma_regmap, 0x081c + offset, val);
+}
+
+static int rk_udphy_dp_phy_configure(struct phy *phy,
+ union phy_configure_opts *opts)
+{
+ struct rk_udphy *udphy = phy_get_drvdata(phy);
+ struct phy_configure_opts_dp *dp = &opts->dp;
+ u32 i, val, lane;
+ int ret;
+
+ ret = rk_udphy_dp_phy_verify_config(udphy, dp);
+ if (ret)
+ return ret;
+
+ if (dp->set_rate) {
+ regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET,
+ CMN_DP_CMN_RSTN, FIELD_PREP(CMN_DP_CMN_RSTN, 0x0));
+
+ switch (dp->link_rate) {
+ case 1620:
+ udphy->bw = DP_BW_RBR;
+ break;
+
+ case 2700:
+ udphy->bw = DP_BW_HBR;
+ break;
+
+ case 5400:
+ udphy->bw = DP_BW_HBR2;
+ break;
+
+ case 8100:
+ udphy->bw = DP_BW_HBR3;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ regmap_update_bits(udphy->pma_regmap, CMN_DP_LINK_OFFSET, CMN_DP_TX_LINK_BW,
+ FIELD_PREP(CMN_DP_TX_LINK_BW, udphy->bw));
+ regmap_update_bits(udphy->pma_regmap, CMN_SSC_EN_OFFSET, CMN_ROPLL_SSC_EN,
+ FIELD_PREP(CMN_ROPLL_SSC_EN, dp->ssc));
+ regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, CMN_DP_CMN_RSTN,
+ FIELD_PREP(CMN_DP_CMN_RSTN, 0x1));
+
+ ret = regmap_read_poll_timeout(udphy->pma_regmap, CMN_ANA_ROPLL_DONE_OFFSET, val,
+ FIELD_GET(CMN_ANA_ROPLL_LOCK_DONE, val) &&
+ FIELD_GET(CMN_ANA_ROPLL_AFC_DONE, val),
+ 0, 1000);
+ if (ret) {
+ dev_err(udphy->dev, "ROPLL is not lock, set_rate failed\n");
+ return ret;
+ }
+ }
+
+ if (dp->set_voltages) {
+ for (i = 0; i < dp->lanes; i++) {
+ lane = udphy->dp_lane_sel[i];
+ switch (dp->link_rate) {
+ case 1620:
+ case 2700:
+ regmap_update_bits(udphy->pma_regmap,
+ TRSV_ANA_TX_CLK_OFFSET_N(lane),
+ LN_ANA_TX_SER_TXCLK_INV,
+ FIELD_PREP(LN_ANA_TX_SER_TXCLK_INV,
+ udphy->lane_mux_sel[lane]));
+ break;
+
+ case 5400:
+ case 8100:
+ regmap_update_bits(udphy->pma_regmap,
+ TRSV_ANA_TX_CLK_OFFSET_N(lane),
+ LN_ANA_TX_SER_TXCLK_INV,
+ FIELD_PREP(LN_ANA_TX_SER_TXCLK_INV, 0x0));
+ break;
+ }
+
+ rk_udphy_dp_set_voltage(udphy, udphy->bw, dp->voltage[i],
+ dp->pre[i], lane);
+ }
+ }
+
+ return 0;
+}
+
+static const struct phy_ops rk_udphy_dp_phy_ops = {
+ .init = rk_udphy_dp_phy_init,
+ .exit = rk_udphy_dp_phy_exit,
+ .power_on = rk_udphy_dp_phy_power_on,
+ .power_off = rk_udphy_dp_phy_power_off,
+ .configure = rk_udphy_dp_phy_configure,
+ .owner = THIS_MODULE,
+};
+
+static int rk_udphy_usb3_phy_init(struct phy *phy)
+{
+ struct rk_udphy *udphy = phy_get_drvdata(phy);
+ int ret = 0;
+
+ mutex_lock(&udphy->mutex);
+ /* DP only or high-speed, disable U3 port */
+ if (!(udphy->mode & UDPHY_MODE_USB) || udphy->hs) {
+ rk_udphy_u3_port_disable(udphy, true);
+ goto unlock;
+ }
+
+ ret = rk_udphy_power_on(udphy, UDPHY_MODE_USB);
+
+unlock:
+ mutex_unlock(&udphy->mutex);
+ return ret;
+}
+
+static int rk_udphy_usb3_phy_exit(struct phy *phy)
+{
+ struct rk_udphy *udphy = phy_get_drvdata(phy);
+
+ mutex_lock(&udphy->mutex);
+ /* DP only or high-speed */
+ if (!(udphy->mode & UDPHY_MODE_USB) || udphy->hs)
+ goto unlock;
+
+ rk_udphy_power_off(udphy, UDPHY_MODE_USB);
+
+unlock:
+ mutex_unlock(&udphy->mutex);
+ return 0;
+}
+
+static const struct phy_ops rk_udphy_usb3_phy_ops = {
+ .init = rk_udphy_usb3_phy_init,
+ .exit = rk_udphy_usb3_phy_exit,
+ .owner = THIS_MODULE,
+};
+
+static int rk_udphy_typec_mux_set(struct typec_mux_dev *mux,
+ struct typec_mux_state *state)
+{
+ struct rk_udphy *udphy = typec_mux_get_drvdata(mux);
+ u8 mode;
+
+ mutex_lock(&udphy->mutex);
+
+ switch (state->mode) {
+ case TYPEC_DP_STATE_C:
+ case TYPEC_DP_STATE_E:
+ udphy->lane_mux_sel[0] = PHY_LANE_MUX_DP;
+ udphy->lane_mux_sel[1] = PHY_LANE_MUX_DP;
+ udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP;
+ udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP;
+ mode = UDPHY_MODE_DP;
+ break;
+
+ case TYPEC_DP_STATE_D:
+ default:
+ if (udphy->flip) {
+ udphy->lane_mux_sel[0] = PHY_LANE_MUX_DP;
+ udphy->lane_mux_sel[1] = PHY_LANE_MUX_DP;
+ udphy->lane_mux_sel[2] = PHY_LANE_MUX_USB;
+ udphy->lane_mux_sel[3] = PHY_LANE_MUX_USB;
+ } else {
+ udphy->lane_mux_sel[0] = PHY_LANE_MUX_USB;
+ udphy->lane_mux_sel[1] = PHY_LANE_MUX_USB;
+ udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP;
+ udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP;
+ }
+ mode = UDPHY_MODE_DP_USB;
+ break;
+ }
+
+ if (state->alt && state->alt->svid == USB_TYPEC_DP_SID) {
+ struct typec_displayport_data *data = state->data;
+
+ if (!data) {
+ rk_udphy_dp_hpd_event_trigger(udphy, false);
+ } else if (data->status & DP_STATUS_IRQ_HPD) {
+ rk_udphy_dp_hpd_event_trigger(udphy, false);
+ usleep_range(750, 800);
+ rk_udphy_dp_hpd_event_trigger(udphy, true);
+ } else if (data->status & DP_STATUS_HPD_STATE) {
+ if (udphy->mode != mode) {
+ udphy->mode = mode;
+ udphy->mode_change = true;
+ }
+ rk_udphy_dp_hpd_event_trigger(udphy, true);
+ } else {
+ rk_udphy_dp_hpd_event_trigger(udphy, false);
+ }
+ }
+
+ mutex_unlock(&udphy->mutex);
+ return 0;
+}
+
+static void rk_udphy_typec_mux_unregister(void *data)
+{
+ struct rk_udphy *udphy = data;
+
+ typec_mux_unregister(udphy->mux);
+}
+
+static int rk_udphy_setup_typec_mux(struct rk_udphy *udphy)
+{
+ struct typec_mux_desc mux_desc = {};
+
+ mux_desc.drvdata = udphy;
+ mux_desc.fwnode = dev_fwnode(udphy->dev);
+ mux_desc.set = rk_udphy_typec_mux_set;
+
+ udphy->mux = typec_mux_register(udphy->dev, &mux_desc);
+ if (IS_ERR(udphy->mux)) {
+ dev_err(udphy->dev, "Error register typec mux: %ld\n",
+ PTR_ERR(udphy->mux));
+ return PTR_ERR(udphy->mux);
+ }
+
+ return devm_add_action_or_reset(udphy->dev, rk_udphy_typec_mux_unregister,
+ udphy);
+}
+
+static const struct regmap_config rk_udphy_pma_regmap_cfg = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .fast_io = true,
+ .max_register = 0x20dc,
+};
+
+static struct phy *rk_udphy_phy_xlate(struct device *dev, const struct of_phandle_args *args)
+{
+ struct rk_udphy *udphy = dev_get_drvdata(dev);
+
+ if (args->args_count == 0)
+ return ERR_PTR(-EINVAL);
+
+ switch (args->args[0]) {
+ case PHY_TYPE_USB3:
+ return udphy->phy_u3;
+ case PHY_TYPE_DP:
+ return udphy->phy_dp;
+ }
+
+ return ERR_PTR(-EINVAL);
+}
+
+static int rk_udphy_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct phy_provider *phy_provider;
+ struct resource *res;
+ struct rk_udphy *udphy;
+ void __iomem *base;
+ int id, ret;
+
+ udphy = devm_kzalloc(dev, sizeof(*udphy), GFP_KERNEL);
+ if (!udphy)
+ return -ENOMEM;
+
+ udphy->cfgs = device_get_match_data(dev);
+ if (!udphy->cfgs)
+ return dev_err_probe(dev, -EINVAL, "missing match data\n");
+
+ base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ /* find the phy-id from the io address */
+ udphy->id = -ENODEV;
+ for (id = 0; id < udphy->cfgs->num_phys; id++) {
+ if (res->start == udphy->cfgs->phy_ids[id]) {
+ udphy->id = id;
+ break;
+ }
+ }
+
+ if (udphy->id < 0)
+ return dev_err_probe(dev, -ENODEV, "no matching device found\n");
+
+ udphy->pma_regmap = devm_regmap_init_mmio(dev, base + UDPHY_PMA,
+ &rk_udphy_pma_regmap_cfg);
+ if (IS_ERR(udphy->pma_regmap))
+ return PTR_ERR(udphy->pma_regmap);
+
+ udphy->dev = dev;
+ ret = rk_udphy_parse_dt(udphy);
+ if (ret)
+ return ret;
+
+ ret = rk_udphy_get_initial_status(udphy);
+ if (ret)
+ return ret;
+
+ mutex_init(&udphy->mutex);
+ platform_set_drvdata(pdev, udphy);
+
+ if (device_property_present(dev, "orientation-switch")) {
+ ret = rk_udphy_setup_orien_switch(udphy);
+ if (ret)
+ return ret;
+ }
+
+ if (device_property_present(dev, "mode-switch")) {
+ ret = rk_udphy_setup_typec_mux(udphy);
+ if (ret)
+ return ret;
+ }
+
+ udphy->phy_u3 = devm_phy_create(dev, dev->of_node, &rk_udphy_usb3_phy_ops);
+ if (IS_ERR(udphy->phy_u3)) {
+ ret = PTR_ERR(udphy->phy_u3);
+ return dev_err_probe(dev, ret, "failed to create USB3 phy\n");
+ }
+ phy_set_drvdata(udphy->phy_u3, udphy);
+
+ udphy->phy_dp = devm_phy_create(dev, dev->of_node, &rk_udphy_dp_phy_ops);
+ if (IS_ERR(udphy->phy_dp)) {
+ ret = PTR_ERR(udphy->phy_dp);
+ return dev_err_probe(dev, ret, "failed to create DP phy\n");
+ }
+ phy_set_bus_width(udphy->phy_dp, rk_udphy_dplane_get(udphy));
+ udphy->phy_dp->attrs.max_link_rate = 8100;
+ phy_set_drvdata(udphy->phy_dp, udphy);
+
+ phy_provider = devm_of_phy_provider_register(dev, rk_udphy_phy_xlate);
+ if (IS_ERR(phy_provider)) {
+ ret = PTR_ERR(phy_provider);
+ return dev_err_probe(dev, ret, "failed to register phy provider\n");
+ }
+
+ return 0;
+}
+
+static int __maybe_unused rk_udphy_resume(struct device *dev)
+{
+ struct rk_udphy *udphy = dev_get_drvdata(dev);
+
+ if (udphy->dp_sink_hpd_sel)
+ rk_udphy_dp_hpd_event_trigger(udphy, udphy->dp_sink_hpd_cfg);
+
+ return 0;
+}
+
+static const struct dev_pm_ops rk_udphy_pm_ops = {
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, rk_udphy_resume)
+};
+
+static const char * const rk_udphy_rst_list[] = {
+ "init", "cmn", "lane", "pcs_apb", "pma_apb"
+};
+
+static const struct rk_udphy_cfg rk3576_udphy_cfgs = {
+ .num_phys = 1,
+ .phy_ids = { 0x2b010000 },
+ .num_rsts = ARRAY_SIZE(rk_udphy_rst_list),
+ .rst_list = rk_udphy_rst_list,
+ .grfcfg = {
+ /* u2phy-grf */
+ .bvalid_phy_con = RK_UDPHY_GEN_GRF_REG(0x0010, 1, 0, 0x2, 0x3),
+ .bvalid_grf_con = RK_UDPHY_GEN_GRF_REG(0x0000, 15, 14, 0x1, 0x3),
+
+ /* usb-grf */
+ .usb3otg0_cfg = RK_UDPHY_GEN_GRF_REG(0x0030, 15, 0, 0x1100, 0x0188),
+
+ /* usbdpphy-grf */
+ .low_pwrn = RK_UDPHY_GEN_GRF_REG(0x0004, 13, 13, 0, 1),
+ .rx_lfps = RK_UDPHY_GEN_GRF_REG(0x0004, 14, 14, 0, 1),
+ },
+ .vogrfcfg = {
+ {
+ .hpd_trigger = RK_UDPHY_GEN_GRF_REG(0x0000, 11, 10, 1, 3),
+ .dp_lane_reg = 0x0000,
+ },
+ },
+ .dp_tx_ctrl_cfg = {
+ rk3588_dp_tx_drv_ctrl_rbr_hbr_typec,
+ rk3588_dp_tx_drv_ctrl_rbr_hbr_typec,
+ rk3588_dp_tx_drv_ctrl_hbr2,
+ rk3588_dp_tx_drv_ctrl_hbr3,
+ },
+ .dp_tx_ctrl_cfg_typec = {
+ rk3588_dp_tx_drv_ctrl_rbr_hbr_typec,
+ rk3588_dp_tx_drv_ctrl_rbr_hbr_typec,
+ rk3588_dp_tx_drv_ctrl_hbr2,
+ rk3588_dp_tx_drv_ctrl_hbr3,
+ },
+};
+
+static const struct rk_udphy_cfg rk3588_udphy_cfgs = {
+ .num_phys = 2,
+ .phy_ids = {
+ 0xfed80000,
+ 0xfed90000,
+ },
+ .num_rsts = ARRAY_SIZE(rk_udphy_rst_list),
+ .rst_list = rk_udphy_rst_list,
+ .grfcfg = {
+ /* u2phy-grf */
+ .bvalid_phy_con = RK_UDPHY_GEN_GRF_REG(0x0008, 1, 0, 0x2, 0x3),
+ .bvalid_grf_con = RK_UDPHY_GEN_GRF_REG(0x0010, 3, 2, 0x2, 0x3),
+
+ /* usb-grf */
+ .usb3otg0_cfg = RK_UDPHY_GEN_GRF_REG(0x001c, 15, 0, 0x1100, 0x0188),
+ .usb3otg1_cfg = RK_UDPHY_GEN_GRF_REG(0x0034, 15, 0, 0x1100, 0x0188),
+
+ /* usbdpphy-grf */
+ .low_pwrn = RK_UDPHY_GEN_GRF_REG(0x0004, 13, 13, 0, 1),
+ .rx_lfps = RK_UDPHY_GEN_GRF_REG(0x0004, 14, 14, 0, 1),
+ },
+ .vogrfcfg = {
+ {
+ .hpd_trigger = RK_UDPHY_GEN_GRF_REG(0x0000, 11, 10, 1, 3),
+ .dp_lane_reg = 0x0000,
+ },
+ {
+ .hpd_trigger = RK_UDPHY_GEN_GRF_REG(0x0008, 11, 10, 1, 3),
+ .dp_lane_reg = 0x0008,
+ },
+ },
+ .dp_tx_ctrl_cfg = {
+ rk3588_dp_tx_drv_ctrl_rbr_hbr,
+ rk3588_dp_tx_drv_ctrl_rbr_hbr,
+ rk3588_dp_tx_drv_ctrl_hbr2,
+ rk3588_dp_tx_drv_ctrl_hbr3,
+ },
+ .dp_tx_ctrl_cfg_typec = {
+ rk3588_dp_tx_drv_ctrl_rbr_hbr_typec,
+ rk3588_dp_tx_drv_ctrl_rbr_hbr_typec,
+ rk3588_dp_tx_drv_ctrl_hbr2,
+ rk3588_dp_tx_drv_ctrl_hbr3,
+ },
+};
+
+static const struct of_device_id rk_udphy_dt_match[] = {
+ {
+ .compatible = "rockchip,rk3576-usbdp-phy",
+ .data = &rk3576_udphy_cfgs
+ },
+ {
+ .compatible = "rockchip,rk3588-usbdp-phy",
+ .data = &rk3588_udphy_cfgs
+ },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, rk_udphy_dt_match);
+
+static struct platform_driver rk_udphy_driver = {
+ .probe = rk_udphy_probe,
+ .driver = {
+ .name = "rockchip-usbdp-phy",
+ .of_match_table = rk_udphy_dt_match,
+ .pm = &rk_udphy_pm_ops,
+ },
+};
+module_platform_driver(rk_udphy_driver);
+
+MODULE_AUTHOR("Frank Wang <frank.wang@rock-chips.com>");
+MODULE_AUTHOR("Zhang Yubing <yubing.zhang@rock-chips.com>");
+MODULE_DESCRIPTION("Rockchip USBDP Combo PHY driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/samsung/Kconfig b/drivers/phy/samsung/Kconfig
index f10afa3d7ff5..e2330b0894d6 100644
--- a/drivers/phy/samsung/Kconfig
+++ b/drivers/phy/samsung/Kconfig
@@ -33,6 +33,7 @@ config PHY_SAMSUNG_UFS
tristate "Exynos SoC series UFS PHY driver"
depends on OF && (ARCH_EXYNOS || COMPILE_TEST)
select GENERIC_PHY
+ select MFD_SYSCON
help
Enable this to support the Samsung Exynos SoC UFS PHY driver for
Samsung Exynos SoCs. This driver provides the interface for UFS host
diff --git a/drivers/phy/samsung/Makefile b/drivers/phy/samsung/Makefile
index afb34a153e34..fea1f96d0e43 100644
--- a/drivers/phy/samsung/Makefile
+++ b/drivers/phy/samsung/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o
obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o
obj-$(CONFIG_PHY_EXYNOS_PCIE) += phy-exynos-pcie.o
obj-$(CONFIG_PHY_SAMSUNG_UFS) += phy-exynos-ufs.o
+phy-exynos-ufs-y += phy-gs101-ufs.o
phy-exynos-ufs-y += phy-samsung-ufs.o
phy-exynos-ufs-y += phy-exynos7-ufs.o
phy-exynos-ufs-y += phy-exynosautov9-ufs.o
diff --git a/drivers/phy/samsung/phy-exynos-mipi-video.c b/drivers/phy/samsung/phy-exynos-mipi-video.c
index 592d8067e848..f6756a609a9a 100644
--- a/drivers/phy/samsung/phy-exynos-mipi-video.c
+++ b/drivers/phy/samsung/phy-exynos-mipi-video.c
@@ -274,7 +274,7 @@ static int exynos_mipi_video_phy_power_off(struct phy *phy)
}
static struct phy *exynos_mipi_video_phy_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct exynos_mipi_video_phy *state = dev_get_drvdata(dev);
diff --git a/drivers/phy/samsung/phy-exynos5-usbdrd.c b/drivers/phy/samsung/phy-exynos5-usbdrd.c
index 3f310b28bfff..46b8f6987c62 100644
--- a/drivers/phy/samsung/phy-exynos5-usbdrd.c
+++ b/drivers/phy/samsung/phy-exynos5-usbdrd.c
@@ -8,6 +8,7 @@
* Author: Vivek Gautam <gautam.vivek@samsung.com>
*/
+#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/io.h>
@@ -30,18 +31,16 @@
#define EXYNOS5_FSEL_19MHZ2 0x3
#define EXYNOS5_FSEL_20MHZ 0x4
#define EXYNOS5_FSEL_24MHZ 0x5
-#define EXYNOS5_FSEL_26MHZ 0x82
+#define EXYNOS5_FSEL_26MHZ 0x6
#define EXYNOS5_FSEL_50MHZ 0x7
/* Exynos5: USB 3.0 DRD PHY registers */
#define EXYNOS5_DRD_LINKSYSTEM 0x04
-
+#define LINKSYSTEM_XHCI_VERSION_CONTROL BIT(27)
#define LINKSYSTEM_FLADJ_MASK (0x3f << 1)
#define LINKSYSTEM_FLADJ(_x) ((_x) << 1)
-#define LINKSYSTEM_XHCI_VERSION_CONTROL BIT(27)
#define EXYNOS5_DRD_PHYUTMI 0x08
-
#define PHYUTMI_OTGDISABLE BIT(6)
#define PHYUTMI_FORCESUSPEND BIT(1)
#define PHYUTMI_FORCESLEEP BIT(0)
@@ -49,40 +48,31 @@
#define EXYNOS5_DRD_PHYPIPE 0x0c
#define EXYNOS5_DRD_PHYCLKRST 0x10
-
#define PHYCLKRST_EN_UTMISUSPEND BIT(31)
-
#define PHYCLKRST_SSC_REFCLKSEL_MASK (0xff << 23)
#define PHYCLKRST_SSC_REFCLKSEL(_x) ((_x) << 23)
-
#define PHYCLKRST_SSC_RANGE_MASK (0x03 << 21)
#define PHYCLKRST_SSC_RANGE(_x) ((_x) << 21)
-
#define PHYCLKRST_SSC_EN BIT(20)
#define PHYCLKRST_REF_SSP_EN BIT(19)
#define PHYCLKRST_REF_CLKDIV2 BIT(18)
-
#define PHYCLKRST_MPLL_MULTIPLIER_MASK (0x7f << 11)
#define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF (0x19 << 11)
#define PHYCLKRST_MPLL_MULTIPLIER_50M_REF (0x32 << 11)
#define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF (0x68 << 11)
#define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF (0x7d << 11)
#define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF (0x02 << 11)
-
-#define PHYCLKRST_FSEL_UTMI_MASK (0x7 << 5)
#define PHYCLKRST_FSEL_PIPE_MASK (0x7 << 8)
+#define PHYCLKRST_FSEL_UTMI_MASK (0x7 << 5)
#define PHYCLKRST_FSEL(_x) ((_x) << 5)
#define PHYCLKRST_FSEL_PAD_100MHZ (0x27 << 5)
#define PHYCLKRST_FSEL_PAD_24MHZ (0x2a << 5)
#define PHYCLKRST_FSEL_PAD_20MHZ (0x31 << 5)
#define PHYCLKRST_FSEL_PAD_19_2MHZ (0x38 << 5)
-
#define PHYCLKRST_RETENABLEN BIT(4)
-
#define PHYCLKRST_REFCLKSEL_MASK (0x03 << 2)
#define PHYCLKRST_REFCLKSEL_PAD_REFCLK (0x2 << 2)
#define PHYCLKRST_REFCLKSEL_EXT_REFCLK (0x3 << 2)
-
#define PHYCLKRST_PORTRESET BIT(1)
#define PHYCLKRST_COMMONONN BIT(0)
@@ -100,30 +90,27 @@
#define PHYREG1_CR_ACK BIT(0)
#define EXYNOS5_DRD_PHYPARAM0 0x1c
-
#define PHYPARAM0_REF_USE_PAD BIT(31)
#define PHYPARAM0_REF_LOSLEVEL_MASK (0x1f << 26)
#define PHYPARAM0_REF_LOSLEVEL (0x9 << 26)
#define EXYNOS5_DRD_PHYPARAM1 0x20
-
#define PHYPARAM1_PCS_TXDEEMPH_MASK (0x1f << 0)
#define PHYPARAM1_PCS_TXDEEMPH (0x1c)
#define EXYNOS5_DRD_PHYTERM 0x24
#define EXYNOS5_DRD_PHYTEST 0x28
-
#define PHYTEST_POWERDOWN_SSP BIT(3)
#define PHYTEST_POWERDOWN_HSP BIT(2)
#define EXYNOS5_DRD_PHYADP 0x2c
#define EXYNOS5_DRD_PHYUTMICLKSEL 0x30
-
#define PHYUTMICLKSEL_UTMI_CLKSEL BIT(2)
#define EXYNOS5_DRD_PHYRESUME 0x34
+
#define EXYNOS5_DRD_LINKPORT 0x44
/* USB 3.0 DRD PHY SS Function Control Reg; accessed by CR_PORT */
@@ -147,35 +134,215 @@
/* Exynos850: USB DRD PHY registers */
#define EXYNOS850_DRD_LINKCTRL 0x04
-#define LINKCTRL_BUS_FILTER_BYPASS(_x) ((_x) << 4)
+#define LINKCTRL_FORCE_RXELECIDLE BIT(18)
+#define LINKCTRL_FORCE_PHYSTATUS BIT(17)
+#define LINKCTRL_FORCE_PIPE_EN BIT(16)
#define LINKCTRL_FORCE_QACT BIT(8)
+#define LINKCTRL_BUS_FILTER_BYPASS(_x) ((_x) << 4)
+
+#define EXYNOS850_DRD_LINKPORT 0x08
+#define LINKPORT_HOST_NUM_U3 GENMASK(19, 16)
+#define LINKPORT_HOST_NUM_U2 GENMASK(15, 12)
#define EXYNOS850_DRD_CLKRST 0x20
-#define CLKRST_LINK_SW_RST BIT(0)
-#define CLKRST_PORT_RST BIT(1)
+/*
+ * On versions without SS ports (like E850), bit 3 is for the 2.0 phy (HS),
+ * while on versions with (like gs101), bits 2 and 3 are for the 3.0 phy (SS)
+ * and bits 12 & 13 for the 2.0 phy.
+ */
+#define CLKRST_PHY20_SW_POR BIT(13)
+#define CLKRST_PHY20_SW_POR_SEL BIT(12)
+#define CLKRST_LINK_PCLK_SEL BIT(7)
#define CLKRST_PHY_SW_RST BIT(3)
+#define CLKRST_PHY_RESET_SEL BIT(2)
+#define CLKRST_PORT_RST BIT(1)
+#define CLKRST_LINK_SW_RST BIT(0)
+
+#define EXYNOS850_DRD_SSPPLLCTL 0x30
+#define SSPPLLCTL_FSEL GENMASK(2, 0)
#define EXYNOS850_DRD_UTMI 0x50
-#define UTMI_FORCE_SLEEP BIT(0)
-#define UTMI_FORCE_SUSPEND BIT(1)
-#define UTMI_DM_PULLDOWN BIT(2)
-#define UTMI_DP_PULLDOWN BIT(3)
-#define UTMI_FORCE_BVALID BIT(4)
#define UTMI_FORCE_VBUSVALID BIT(5)
+#define UTMI_FORCE_BVALID BIT(4)
+#define UTMI_DP_PULLDOWN BIT(3)
+#define UTMI_DM_PULLDOWN BIT(2)
+#define UTMI_FORCE_SUSPEND BIT(1)
+#define UTMI_FORCE_SLEEP BIT(0)
#define EXYNOS850_DRD_HSP 0x54
-#define HSP_COMMONONN BIT(8)
-#define HSP_EN_UTMISUSPEND BIT(9)
-#define HSP_VBUSVLDEXT BIT(12)
-#define HSP_VBUSVLDEXTSEL BIT(13)
#define HSP_FSV_OUT_EN BIT(24)
+#define HSP_VBUSVLDEXTSEL BIT(13)
+#define HSP_VBUSVLDEXT BIT(12)
+#define HSP_EN_UTMISUSPEND BIT(9)
+#define HSP_COMMONONN BIT(8)
+
+#define EXYNOS850_DRD_HSPPARACON 0x58
+#define HSPPARACON_TXVREF GENMASK(31, 28)
+#define HSPPARACON_TXRISE GENMASK(25, 24)
+#define HSPPARACON_TXRES GENMASK(22, 21)
+#define HSPPARACON_TXPREEMPPULSE BIT(20)
+#define HSPPARACON_TXPREEMPAMP GENMASK(19, 18)
+#define HSPPARACON_TXHSXV GENMASK(17, 16)
+#define HSPPARACON_TXFSLS GENMASK(15, 12)
+#define HSPPARACON_SQRX GENMASK(10, 8)
+#define HSPPARACON_OTG GENMASK(6, 4)
+#define HSPPARACON_COMPDIS GENMASK(2, 0)
#define EXYNOS850_DRD_HSP_TEST 0x5c
#define HSP_TEST_SIDDQ BIT(24)
+/* Exynos9 - GS101 */
+#define EXYNOS850_DRD_SECPMACTL 0x48
+#define SECPMACTL_PMA_ROPLL_REF_CLK_SEL GENMASK(13, 12)
+#define SECPMACTL_PMA_LCPLL_REF_CLK_SEL GENMASK(11, 10)
+#define SECPMACTL_PMA_REF_FREQ_SEL GENMASK(9, 8)
+#define SECPMACTL_PMA_LOW_PWR BIT(4)
+#define SECPMACTL_PMA_TRSV_SW_RST BIT(3)
+#define SECPMACTL_PMA_CMN_SW_RST BIT(2)
+#define SECPMACTL_PMA_INIT_SW_RST BIT(1)
+#define SECPMACTL_PMA_APB_SW_RST BIT(0)
+
+/* PMA registers */
+#define EXYNOS9_PMA_USBDP_CMN_REG0008 0x0020
+#define CMN_REG0008_OVRD_AUX_EN BIT(3)
+#define CMN_REG0008_AUX_EN BIT(2)
+
+#define EXYNOS9_PMA_USBDP_CMN_REG00B8 0x02e0
+#define CMN_REG00B8_LANE_MUX_SEL_DP GENMASK(3, 0)
+
+#define EXYNOS9_PMA_USBDP_CMN_REG01C0 0x0700
+#define CMN_REG01C0_ANA_LCPLL_LOCK_DONE BIT(7)
+#define CMN_REG01C0_ANA_LCPLL_AFC_DONE BIT(6)
+
+/* these have similar register layout, for lanes 0 and 2 */
+#define EXYNOS9_PMA_USBDP_TRSV_REG03C3 0x0f0c
+#define EXYNOS9_PMA_USBDP_TRSV_REG07C3 0x1f0c
+#define TRSV_REG03C3_LN0_MON_RX_CDR_AFC_DONE BIT(3)
+#define TRSV_REG03C3_LN0_MON_RX_CDR_CAL_DONE BIT(2)
+#define TRSV_REG03C3_LN0_MON_RX_CDR_FLD_PLL_MODE_DONE BIT(1)
+#define TRSV_REG03C3_LN0_MON_RX_CDR_LOCK_DONE BIT(0)
+
+/* TRSV_REG0413 and TRSV_REG0813 have similar register layout */
+#define EXYNOS9_PMA_USBDP_TRSV_REG0413 0x104c
+#define TRSV_REG0413_OVRD_LN1_TX_RXD_COMP_EN BIT(7)
+#define TRSV_REG0413_OVRD_LN1_TX_RXD_EN BIT(5)
+
+#define EXYNOS9_PMA_USBDP_TRSV_REG0813 0x204c
+#define TRSV_REG0813_OVRD_LN3_TX_RXD_COMP_EN BIT(7)
+#define TRSV_REG0813_OVRD_LN3_TX_RXD_EN BIT(5)
+
+/* PCS registers */
+#define EXYNOS9_PCS_NS_VEC_PS1_N1 0x010c
+#define EXYNOS9_PCS_NS_VEC_PS2_N0 0x0110
+#define EXYNOS9_PCS_NS_VEC_PS3_N0 0x0118
+#define NS_VEC_NS_REQ GENMASK(31, 24)
+#define NS_VEC_ENABLE_TIMER BIT(22)
+#define NS_VEC_SEL_TIMEOUT GENMASK(21, 20)
+#define NS_VEC_INV_MASK GENMASK(19, 16)
+#define NS_VEC_COND_MASK GENMASK(11, 8)
+#define NS_VEC_EXP_COND GENMASK(3, 0)
+
+#define EXYNOS9_PCS_OUT_VEC_2 0x014c
+#define EXYNOS9_PCS_OUT_VEC_3 0x0150
+#define PCS_OUT_VEC_B9_DYNAMIC BIT(19)
+#define PCS_OUT_VEC_B9_SEL_OUT BIT(18)
+#define PCS_OUT_VEC_B8_DYNAMIC BIT(17)
+#define PCS_OUT_VEC_B8_SEL_OUT BIT(16)
+#define PCS_OUT_VEC_B7_DYNAMIC BIT(15)
+#define PCS_OUT_VEC_B7_SEL_OUT BIT(14)
+#define PCS_OUT_VEC_B6_DYNAMIC BIT(13)
+#define PCS_OUT_VEC_B6_SEL_OUT BIT(12)
+#define PCS_OUT_VEC_B5_DYNAMIC BIT(11)
+#define PCS_OUT_VEC_B5_SEL_OUT BIT(10)
+#define PCS_OUT_VEC_B4_DYNAMIC BIT(9)
+#define PCS_OUT_VEC_B4_SEL_OUT BIT(8)
+#define PCS_OUT_VEC_B3_DYNAMIC BIT(7)
+#define PCS_OUT_VEC_B3_SEL_OUT BIT(6)
+#define PCS_OUT_VEC_B2_DYNAMIC BIT(5)
+#define PCS_OUT_VEC_B2_SEL_OUT BIT(4)
+#define PCS_OUT_VEC_B1_DYNAMIC BIT(3)
+#define PCS_OUT_VEC_B1_SEL_OUT BIT(2)
+#define PCS_OUT_VEC_B0_DYNAMIC BIT(1)
+#define PCS_OUT_VEC_B0_SEL_OUT BIT(0)
+
+#define EXYNOS9_PCS_TIMEOUT_0 0x0170
+
+#define EXYNOS9_PCS_TIMEOUT_3 0x017c
+
+#define EXYNOS9_PCS_EBUF_PARAM 0x0304
+#define EBUF_PARAM_SKP_REMOVE_TH_EMPTY_MODE GENMASK(29, 24)
+
+#define EXYNOS9_PCS_BACK_END_MODE_VEC 0x030c
+#define BACK_END_MODE_VEC_FORCE_EBUF_EMPTY_MODE BIT(1)
+#define BACK_END_MODE_VEC_DISABLE_DATA_MASK BIT(0)
+
+#define EXYNOS9_PCS_RX_CONTROL 0x03f0
+#define RX_CONTROL_EN_BLOCK_ALIGNER_TYPE_B BIT(22)
+
+#define EXYNOS9_PCS_RX_CONTROL_DEBUG 0x03f4
+#define RX_CONTROL_DEBUG_EN_TS_CHECK BIT(5)
+#define RX_CONTROL_DEBUG_NUM_COM_FOUND GENMASK(3, 0)
+
+#define EXYNOS9_PCS_LOCAL_COEF 0x040c
+#define LOCAL_COEF_PMA_CENTER_COEF GENMASK(21, 16)
+#define LOCAL_COEF_LF GENMASK(13, 8)
+#define LOCAL_COEF_FS GENMASK(5, 0)
+
+#define EXYNOS9_PCS_HS_TX_COEF_MAP_0 0x0410
+#define HS_TX_COEF_MAP_0_SSTX_DEEMP GENMASK(17, 12)
+#define HS_TX_COEF_MAP_0_SSTX_LEVEL GENMASK(11, 6)
+#define HS_TX_COEF_MAP_0_SSTX_PRE_SHOOT GENMASK(5, 0)
+
+
#define KHZ 1000
#define MHZ (KHZ * KHZ)
+#define PHY_TUNING_ENTRY_PHY(o, m, v) { \
+ .off = (o), \
+ .mask = (m), \
+ .val = (v), \
+ .region = PTR_PHY \
+ }
+
+#define PHY_TUNING_ENTRY_PCS(o, m, v) { \
+ .off = (o), \
+ .mask = (m), \
+ .val = (v), \
+ .region = PTR_PCS \
+ }
+
+#define PHY_TUNING_ENTRY_PMA(o, m, v) { \
+ .off = (o), \
+ .mask = (m), \
+ .val = (v), \
+ .region = PTR_PMA, \
+ }
+
+#define PHY_TUNING_ENTRY_LAST { .region = PTR_INVALID }
+
+#define for_each_phy_tune(tune) \
+ for (; (tune)->region != PTR_INVALID; ++(tune))
+
+struct exynos5_usbdrd_phy_tuning {
+ u32 off;
+ u32 mask;
+ u32 val;
+ char region;
+#define PTR_INVALID 0
+#define PTR_PHY 1
+#define PTR_PCS 2
+#define PTR_PMA 3
+};
+
+enum exynos5_usbdrd_phy_tuning_state {
+ PTS_UTMI_POSTINIT,
+ PTS_PIPE3_PREINIT,
+ PTS_PIPE3_INIT,
+ PTS_PIPE3_POSTINIT,
+ PTS_PIPE3_POSTLOCK,
+ PTS_MAX,
+};
+
enum exynos5_usbdrd_phy_id {
EXYNOS5_DRDPHY_UTMI,
EXYNOS5_DRDPHY_PIPE3,
@@ -187,44 +354,48 @@ struct exynos5_usbdrd_phy;
struct exynos5_usbdrd_phy_config {
u32 id;
- void (*phy_isol)(struct phy_usb_instance *inst, u32 on);
+ void (*phy_isol)(struct phy_usb_instance *inst, bool isolate);
void (*phy_init)(struct exynos5_usbdrd_phy *phy_drd);
unsigned int (*set_refclk)(struct phy_usb_instance *inst);
};
struct exynos5_usbdrd_phy_drvdata {
const struct exynos5_usbdrd_phy_config *phy_cfg;
+ const struct exynos5_usbdrd_phy_tuning **phy_tunes;
const struct phy_ops *phy_ops;
+ const char * const *clk_names;
+ int n_clks;
+ const char * const *core_clk_names;
+ int n_core_clks;
+ const char * const *regulator_names;
+ int n_regulators;
u32 pmu_offset_usbdrd0_phy;
+ u32 pmu_offset_usbdrd0_phy_ss;
u32 pmu_offset_usbdrd1_phy;
- bool has_common_clk_gate;
};
/**
* struct exynos5_usbdrd_phy - driver data for USB 3.0 PHY
* @dev: pointer to device instance of this platform device
* @reg_phy: usb phy controller register memory base
- * @clk: phy clock for register access
- * @pipeclk: clock for pipe3 phy
- * @utmiclk: clock for utmi+ phy
- * @itpclk: clock for ITP generation
+ * @reg_pcs: usb phy physical coding sublayer register memory base
+ * @reg_pma: usb phy physical media attachment register memory base
+ * @clks: clocks for register access
+ * @core_clks: core clocks for phy (ref, pipe3, utmi+, ITP, etc. as required)
* @drv_data: pointer to SoC level driver data structure
* @phys: array for 'EXYNOS5_DRDPHYS_NUM' number of PHY
* instances each with its 'phy' and 'phy_cfg'.
* @extrefclk: frequency select settings when using 'separate
* reference clocks' for SS and HS operations
- * @ref_clk: reference clock to PHY block from which PHY's
- * operational clocks are derived
- * @vbus: VBUS regulator for phy
- * @vbus_boost: Boost regulator for VBUS present on few Exynos boards
+ * @regulators: regulators for phy
*/
struct exynos5_usbdrd_phy {
struct device *dev;
void __iomem *reg_phy;
- struct clk *clk;
- struct clk *pipeclk;
- struct clk *utmiclk;
- struct clk *itpclk;
+ void __iomem *reg_pcs;
+ void __iomem *reg_pma;
+ struct clk_bulk_data *clks;
+ struct clk_bulk_data *core_clks;
const struct exynos5_usbdrd_phy_drvdata *drv_data;
struct phy_usb_instance {
struct phy *phy;
@@ -234,9 +405,7 @@ struct exynos5_usbdrd_phy {
const struct exynos5_usbdrd_phy_config *phy_cfg;
} phys[EXYNOS5_DRDPHYS_NUM];
u32 extrefclk;
- struct clk *ref_clk;
- struct regulator *vbus;
- struct regulator *vbus_boost;
+ struct regulator_bulk_data *regulators;
};
static inline
@@ -287,14 +456,14 @@ static unsigned int exynos5_rate_to_clk(unsigned long rate, u32 *reg)
}
static void exynos5_usbdrd_phy_isol(struct phy_usb_instance *inst,
- unsigned int on)
+ bool isolate)
{
unsigned int val;
if (!inst->reg_pmu)
return;
- val = on ? 0 : EXYNOS4_PHY_ENABLE;
+ val = isolate ? 0 : EXYNOS4_PHY_ENABLE;
regmap_update_bits(inst->reg_pmu, inst->pmu_offset,
EXYNOS4_PHY_ENABLE, val);
@@ -319,9 +488,9 @@ exynos5_usbdrd_pipe3_set_refclk(struct phy_usb_instance *inst)
reg |= PHYCLKRST_REFCLKSEL_EXT_REFCLK;
/* FSEL settings corresponding to reference clock */
- reg &= ~PHYCLKRST_FSEL_PIPE_MASK |
- PHYCLKRST_MPLL_MULTIPLIER_MASK |
- PHYCLKRST_SSC_REFCLKSEL_MASK;
+ reg &= ~(PHYCLKRST_FSEL_PIPE_MASK |
+ PHYCLKRST_MPLL_MULTIPLIER_MASK |
+ PHYCLKRST_SSC_REFCLKSEL_MASK);
switch (phy_drd->extrefclk) {
case EXYNOS5_FSEL_50MHZ:
reg |= (PHYCLKRST_MPLL_MULTIPLIER_50M_REF |
@@ -363,14 +532,53 @@ exynos5_usbdrd_utmi_set_refclk(struct phy_usb_instance *inst)
reg &= ~PHYCLKRST_REFCLKSEL_MASK;
reg |= PHYCLKRST_REFCLKSEL_EXT_REFCLK;
- reg &= ~PHYCLKRST_FSEL_UTMI_MASK |
- PHYCLKRST_MPLL_MULTIPLIER_MASK |
- PHYCLKRST_SSC_REFCLKSEL_MASK;
+ reg &= ~(PHYCLKRST_FSEL_UTMI_MASK |
+ PHYCLKRST_MPLL_MULTIPLIER_MASK |
+ PHYCLKRST_SSC_REFCLKSEL_MASK);
reg |= PHYCLKRST_FSEL(phy_drd->extrefclk);
return reg;
}
+static void
+exynos5_usbdrd_apply_phy_tunes(struct exynos5_usbdrd_phy *phy_drd,
+ enum exynos5_usbdrd_phy_tuning_state state)
+{
+ const struct exynos5_usbdrd_phy_tuning *tune;
+
+ tune = phy_drd->drv_data->phy_tunes[state];
+ if (!tune)
+ return;
+
+ for_each_phy_tune(tune) {
+ void __iomem *reg_base;
+ u32 reg = 0;
+
+ switch (tune->region) {
+ case PTR_PHY:
+ reg_base = phy_drd->reg_phy;
+ break;
+ case PTR_PCS:
+ reg_base = phy_drd->reg_pcs;
+ break;
+ case PTR_PMA:
+ reg_base = phy_drd->reg_pma;
+ break;
+ default:
+ dev_warn_once(phy_drd->dev,
+ "unknown phy region %d\n", tune->region);
+ continue;
+ }
+
+ if (~tune->mask) {
+ reg = readl(reg_base + tune->off);
+ reg &= ~tune->mask;
+ }
+ reg |= tune->val;
+ writel(reg, reg_base + tune->off);
+ }
+}
+
static void exynos5_usbdrd_pipe3_init(struct exynos5_usbdrd_phy *phy_drd)
{
u32 reg;
@@ -386,6 +594,129 @@ static void exynos5_usbdrd_pipe3_init(struct exynos5_usbdrd_phy *phy_drd)
writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
}
+static void
+exynos5_usbdrd_usbdp_g2_v4_ctrl_pma_ready(struct exynos5_usbdrd_phy *phy_drd)
+{
+ void __iomem *regs_base = phy_drd->reg_phy;
+ u32 reg;
+
+ /* link pipe_clock selection to pclk of PMA */
+ reg = readl(regs_base + EXYNOS850_DRD_CLKRST);
+ reg |= CLKRST_LINK_PCLK_SEL;
+ writel(reg, regs_base + EXYNOS850_DRD_CLKRST);
+
+ reg = readl(regs_base + EXYNOS850_DRD_SECPMACTL);
+ reg &= ~SECPMACTL_PMA_REF_FREQ_SEL;
+ reg |= FIELD_PREP(SECPMACTL_PMA_REF_FREQ_SEL, 1);
+ /* SFR reset */
+ reg |= (SECPMACTL_PMA_LOW_PWR | SECPMACTL_PMA_APB_SW_RST);
+ reg &= ~(SECPMACTL_PMA_ROPLL_REF_CLK_SEL |
+ SECPMACTL_PMA_LCPLL_REF_CLK_SEL);
+ /* PMA power off */
+ reg |= (SECPMACTL_PMA_TRSV_SW_RST | SECPMACTL_PMA_CMN_SW_RST |
+ SECPMACTL_PMA_INIT_SW_RST);
+ writel(reg, regs_base + EXYNOS850_DRD_SECPMACTL);
+
+ udelay(1);
+
+ reg = readl(regs_base + EXYNOS850_DRD_SECPMACTL);
+ reg &= ~SECPMACTL_PMA_LOW_PWR;
+ writel(reg, regs_base + EXYNOS850_DRD_SECPMACTL);
+
+ udelay(1);
+
+ /* release override */
+ reg = readl(regs_base + EXYNOS850_DRD_LINKCTRL);
+ reg &= ~LINKCTRL_FORCE_PIPE_EN;
+ writel(reg, regs_base + EXYNOS850_DRD_LINKCTRL);
+
+ udelay(1);
+
+ /* APB enable */
+ reg = readl(regs_base + EXYNOS850_DRD_SECPMACTL);
+ reg &= ~SECPMACTL_PMA_APB_SW_RST;
+ writel(reg, regs_base + EXYNOS850_DRD_SECPMACTL);
+}
+
+static void
+exynos5_usbdrd_usbdp_g2_v4_pma_lane_mux_sel(struct exynos5_usbdrd_phy *phy_drd)
+{
+ void __iomem *regs_base = phy_drd->reg_pma;
+ u32 reg;
+
+ /* lane configuration: USB on all lanes */
+ reg = readl(regs_base + EXYNOS9_PMA_USBDP_CMN_REG00B8);
+ reg &= ~CMN_REG00B8_LANE_MUX_SEL_DP;
+ writel(reg, regs_base + EXYNOS9_PMA_USBDP_CMN_REG00B8);
+
+ /*
+ * FIXME: below code supports one connector orientation only. It needs
+ * updating once we can receive connector events.
+ */
+ /* override of TX receiver detector and comparator: lane 1 */
+ reg = readl(regs_base + EXYNOS9_PMA_USBDP_TRSV_REG0413);
+ reg &= ~TRSV_REG0413_OVRD_LN1_TX_RXD_COMP_EN;
+ reg &= ~TRSV_REG0413_OVRD_LN1_TX_RXD_EN;
+ writel(reg, regs_base + EXYNOS9_PMA_USBDP_TRSV_REG0413);
+
+ /* lane 3 */
+ reg = readl(regs_base + EXYNOS9_PMA_USBDP_TRSV_REG0813);
+ reg |= TRSV_REG0813_OVRD_LN3_TX_RXD_COMP_EN;
+ reg |= TRSV_REG0813_OVRD_LN3_TX_RXD_EN;
+ writel(reg, regs_base + EXYNOS9_PMA_USBDP_TRSV_REG0813);
+}
+
+static int
+exynos5_usbdrd_usbdp_g2_v4_pma_check_pll_lock(struct exynos5_usbdrd_phy *phy_drd)
+{
+ static const unsigned int timeout_us = 40000;
+ static const unsigned int sleep_us = 40;
+ static const u32 locked = (CMN_REG01C0_ANA_LCPLL_LOCK_DONE |
+ CMN_REG01C0_ANA_LCPLL_AFC_DONE);
+ u32 reg;
+ int err;
+
+ err = readl_poll_timeout(
+ phy_drd->reg_pma + EXYNOS9_PMA_USBDP_CMN_REG01C0,
+ reg, (reg & locked) == locked, sleep_us, timeout_us);
+ if (err)
+ dev_err(phy_drd->dev,
+ "timed out waiting for PLL lock: %#.8x\n", reg);
+
+ return err;
+}
+
+static void
+exynos5_usbdrd_usbdp_g2_v4_pma_check_cdr_lock(struct exynos5_usbdrd_phy *phy_drd)
+{
+ static const unsigned int timeout_us = 40000;
+ static const unsigned int sleep_us = 40;
+ static const u32 locked =
+ (TRSV_REG03C3_LN0_MON_RX_CDR_AFC_DONE
+ | TRSV_REG03C3_LN0_MON_RX_CDR_CAL_DONE
+ | TRSV_REG03C3_LN0_MON_RX_CDR_FLD_PLL_MODE_DONE
+ | TRSV_REG03C3_LN0_MON_RX_CDR_LOCK_DONE);
+ u32 reg;
+ int err;
+
+ err = readl_poll_timeout(
+ phy_drd->reg_pma + EXYNOS9_PMA_USBDP_TRSV_REG03C3,
+ reg, (reg & locked) == locked, sleep_us, timeout_us);
+ if (!err)
+ return;
+
+ dev_err(phy_drd->dev,
+ "timed out waiting for CDR lock (l0): %#.8x, retrying\n", reg);
+
+ /* based on cable orientation, this might be on the other phy port */
+ err = readl_poll_timeout(
+ phy_drd->reg_pma + EXYNOS9_PMA_USBDP_TRSV_REG07C3,
+ reg, (reg & locked) == locked, sleep_us, timeout_us);
+ if (err)
+ dev_err(phy_drd->dev,
+ "timed out waiting for CDR lock (l2): %#.8x\n", reg);
+}
+
static void exynos5_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd)
{
u32 reg;
@@ -417,7 +748,7 @@ static int exynos5_usbdrd_phy_init(struct phy *phy)
struct phy_usb_instance *inst = phy_get_drvdata(phy);
struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
- ret = clk_prepare_enable(phy_drd->clk);
+ ret = clk_bulk_prepare_enable(phy_drd->drv_data->n_clks, phy_drd->clks);
if (ret)
return ret;
@@ -462,12 +793,12 @@ static int exynos5_usbdrd_phy_init(struct phy *phy)
writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
- udelay(10);
+ fsleep(10);
reg &= ~PHYCLKRST_PORTRESET;
writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
- clk_disable_unprepare(phy_drd->clk);
+ clk_bulk_disable_unprepare(phy_drd->drv_data->n_clks, phy_drd->clks);
return 0;
}
@@ -479,7 +810,7 @@ static int exynos5_usbdrd_phy_exit(struct phy *phy)
struct phy_usb_instance *inst = phy_get_drvdata(phy);
struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
- ret = clk_prepare_enable(phy_drd->clk);
+ ret = clk_bulk_prepare_enable(phy_drd->drv_data->n_clks, phy_drd->clks);
if (ret)
return ret;
@@ -501,7 +832,7 @@ static int exynos5_usbdrd_phy_exit(struct phy *phy)
PHYTEST_POWERDOWN_HSP;
writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
- clk_disable_unprepare(phy_drd->clk);
+ clk_bulk_disable_unprepare(phy_drd->drv_data->n_clks, phy_drd->clks);
return 0;
}
@@ -514,47 +845,27 @@ static int exynos5_usbdrd_phy_power_on(struct phy *phy)
dev_dbg(phy_drd->dev, "Request to power_on usbdrd_phy phy\n");
- clk_prepare_enable(phy_drd->ref_clk);
- if (!phy_drd->drv_data->has_common_clk_gate) {
- clk_prepare_enable(phy_drd->pipeclk);
- clk_prepare_enable(phy_drd->utmiclk);
- clk_prepare_enable(phy_drd->itpclk);
- }
+ ret = clk_bulk_prepare_enable(phy_drd->drv_data->n_core_clks,
+ phy_drd->core_clks);
+ if (ret)
+ return ret;
/* Enable VBUS supply */
- if (phy_drd->vbus_boost) {
- ret = regulator_enable(phy_drd->vbus_boost);
- if (ret) {
- dev_err(phy_drd->dev,
- "Failed to enable VBUS boost supply\n");
- goto fail_vbus;
- }
- }
-
- if (phy_drd->vbus) {
- ret = regulator_enable(phy_drd->vbus);
- if (ret) {
- dev_err(phy_drd->dev, "Failed to enable VBUS supply\n");
- goto fail_vbus_boost;
- }
+ ret = regulator_bulk_enable(phy_drd->drv_data->n_regulators,
+ phy_drd->regulators);
+ if (ret) {
+ dev_err(phy_drd->dev, "Failed to enable PHY regulator(s)\n");
+ goto fail_vbus;
}
- /* Power-on PHY*/
- inst->phy_cfg->phy_isol(inst, 0);
+ /* Power-on PHY */
+ inst->phy_cfg->phy_isol(inst, false);
return 0;
-fail_vbus_boost:
- if (phy_drd->vbus_boost)
- regulator_disable(phy_drd->vbus_boost);
-
fail_vbus:
- clk_disable_unprepare(phy_drd->ref_clk);
- if (!phy_drd->drv_data->has_common_clk_gate) {
- clk_disable_unprepare(phy_drd->itpclk);
- clk_disable_unprepare(phy_drd->utmiclk);
- clk_disable_unprepare(phy_drd->pipeclk);
- }
+ clk_bulk_disable_unprepare(phy_drd->drv_data->n_core_clks,
+ phy_drd->core_clks);
return ret;
}
@@ -567,20 +878,14 @@ static int exynos5_usbdrd_phy_power_off(struct phy *phy)
dev_dbg(phy_drd->dev, "Request to power_off usbdrd_phy phy\n");
/* Power-off the PHY */
- inst->phy_cfg->phy_isol(inst, 1);
+ inst->phy_cfg->phy_isol(inst, true);
/* Disable VBUS supply */
- if (phy_drd->vbus)
- regulator_disable(phy_drd->vbus);
- if (phy_drd->vbus_boost)
- regulator_disable(phy_drd->vbus_boost);
-
- clk_disable_unprepare(phy_drd->ref_clk);
- if (!phy_drd->drv_data->has_common_clk_gate) {
- clk_disable_unprepare(phy_drd->itpclk);
- clk_disable_unprepare(phy_drd->pipeclk);
- clk_disable_unprepare(phy_drd->utmiclk);
- }
+ regulator_bulk_disable(phy_drd->drv_data->n_regulators,
+ phy_drd->regulators);
+
+ clk_bulk_disable_unprepare(phy_drd->drv_data->n_core_clks,
+ phy_drd->core_clks);
return 0;
}
@@ -715,7 +1020,7 @@ static int exynos5420_usbdrd_phy_calibrate(struct exynos5_usbdrd_phy *phy_drd)
}
static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct exynos5_usbdrd_phy *phy_drd = dev_get_drvdata(dev);
@@ -744,10 +1049,29 @@ static const struct phy_ops exynos5_usbdrd_phy_ops = {
.owner = THIS_MODULE,
};
+static void
+exynos5_usbdrd_usb_v3p1_pipe_override(struct exynos5_usbdrd_phy *phy_drd)
+{
+ void __iomem *regs_base = phy_drd->reg_phy;
+ u32 reg;
+
+ /* force pipe3 signal for link */
+ reg = readl(regs_base + EXYNOS850_DRD_LINKCTRL);
+ reg &= ~LINKCTRL_FORCE_PHYSTATUS;
+ reg |= LINKCTRL_FORCE_PIPE_EN | LINKCTRL_FORCE_RXELECIDLE;
+ writel(reg, regs_base + EXYNOS850_DRD_LINKCTRL);
+
+ /* PMA disable */
+ reg = readl(regs_base + EXYNOS850_DRD_SECPMACTL);
+ reg |= SECPMACTL_PMA_LOW_PWR;
+ writel(reg, regs_base + EXYNOS850_DRD_SECPMACTL);
+}
+
static void exynos850_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd)
{
void __iomem *regs_base = phy_drd->reg_phy;
u32 reg;
+ u32 ss_ports;
/*
* Disable HWACG (hardware auto clock gating control). This will force
@@ -758,8 +1082,16 @@ static void exynos850_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd)
reg |= LINKCTRL_FORCE_QACT;
writel(reg, regs_base + EXYNOS850_DRD_LINKCTRL);
+ reg = readl(regs_base + EXYNOS850_DRD_LINKPORT);
+ ss_ports = FIELD_GET(LINKPORT_HOST_NUM_U3, reg);
+
/* Start PHY Reset (POR=high) */
reg = readl(regs_base + EXYNOS850_DRD_CLKRST);
+ if (ss_ports) {
+ reg |= CLKRST_PHY20_SW_POR;
+ reg |= CLKRST_PHY20_SW_POR_SEL;
+ reg |= CLKRST_PHY_RESET_SEL;
+ }
reg |= CLKRST_PHY_SW_RST;
writel(reg, regs_base + EXYNOS850_DRD_CLKRST);
@@ -787,22 +1119,58 @@ static void exynos850_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd)
reg |= HSP_VBUSVLDEXT | HSP_VBUSVLDEXTSEL;
writel(reg, regs_base + EXYNOS850_DRD_HSP);
+ reg = readl(regs_base + EXYNOS850_DRD_SSPPLLCTL);
+ reg &= ~SSPPLLCTL_FSEL;
+ switch (phy_drd->extrefclk) {
+ case EXYNOS5_FSEL_50MHZ:
+ reg |= FIELD_PREP(SSPPLLCTL_FSEL, 7);
+ break;
+ case EXYNOS5_FSEL_26MHZ:
+ reg |= FIELD_PREP(SSPPLLCTL_FSEL, 6);
+ break;
+ case EXYNOS5_FSEL_24MHZ:
+ reg |= FIELD_PREP(SSPPLLCTL_FSEL, 2);
+ break;
+ case EXYNOS5_FSEL_20MHZ:
+ reg |= FIELD_PREP(SSPPLLCTL_FSEL, 1);
+ break;
+ case EXYNOS5_FSEL_19MHZ2:
+ reg |= FIELD_PREP(SSPPLLCTL_FSEL, 0);
+ break;
+ default:
+ dev_warn(phy_drd->dev, "unsupported ref clk: %#.2x\n",
+ phy_drd->extrefclk);
+ break;
+ }
+ writel(reg, regs_base + EXYNOS850_DRD_SSPPLLCTL);
+
+ if (phy_drd->drv_data->phy_tunes)
+ exynos5_usbdrd_apply_phy_tunes(phy_drd,
+ PTS_UTMI_POSTINIT);
+
/* Power up PHY analog blocks */
reg = readl(regs_base + EXYNOS850_DRD_HSP_TEST);
reg &= ~HSP_TEST_SIDDQ;
writel(reg, regs_base + EXYNOS850_DRD_HSP_TEST);
/* Finish PHY reset (POR=low) */
- udelay(10); /* required before doing POR=low */
+ fsleep(10); /* required before doing POR=low */
reg = readl(regs_base + EXYNOS850_DRD_CLKRST);
+ if (ss_ports) {
+ reg |= CLKRST_PHY20_SW_POR_SEL;
+ reg &= ~CLKRST_PHY20_SW_POR;
+ }
reg &= ~(CLKRST_PHY_SW_RST | CLKRST_PORT_RST);
writel(reg, regs_base + EXYNOS850_DRD_CLKRST);
- udelay(75); /* required after POR=low for guaranteed PHY clock */
+ fsleep(75); /* required after POR=low for guaranteed PHY clock */
/* Disable single ended signal out */
reg = readl(regs_base + EXYNOS850_DRD_HSP);
reg &= ~HSP_FSV_OUT_EN;
writel(reg, regs_base + EXYNOS850_DRD_HSP);
+
+ if (ss_ports)
+ exynos5_usbdrd_usb_v3p1_pipe_override(phy_drd);
}
static int exynos850_usbdrd_phy_init(struct phy *phy)
@@ -811,14 +1179,14 @@ static int exynos850_usbdrd_phy_init(struct phy *phy)
struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
int ret;
- ret = clk_prepare_enable(phy_drd->clk);
+ ret = clk_bulk_prepare_enable(phy_drd->drv_data->n_clks, phy_drd->clks);
if (ret)
return ret;
/* UTMI or PIPE3 specific init */
inst->phy_cfg->phy_init(phy_drd);
- clk_disable_unprepare(phy_drd->clk);
+ clk_bulk_disable_unprepare(phy_drd->drv_data->n_clks, phy_drd->clks);
return 0;
}
@@ -831,7 +1199,7 @@ static int exynos850_usbdrd_phy_exit(struct phy *phy)
u32 reg;
int ret;
- ret = clk_prepare_enable(phy_drd->clk);
+ ret = clk_bulk_prepare_enable(phy_drd->drv_data->n_clks, phy_drd->clks);
if (ret)
return ret;
@@ -850,11 +1218,11 @@ static int exynos850_usbdrd_phy_exit(struct phy *phy)
reg = readl(regs_base + EXYNOS850_DRD_CLKRST);
reg |= CLKRST_LINK_SW_RST;
writel(reg, regs_base + EXYNOS850_DRD_CLKRST);
- udelay(10); /* required before doing POR=low */
+ fsleep(10); /* required before doing POR=low */
reg &= ~CLKRST_LINK_SW_RST;
writel(reg, regs_base + EXYNOS850_DRD_CLKRST);
- clk_disable_unprepare(phy_drd->clk);
+ clk_bulk_disable_unprepare(phy_drd->drv_data->n_clks, phy_drd->clks);
return 0;
}
@@ -867,53 +1235,141 @@ static const struct phy_ops exynos850_usbdrd_phy_ops = {
.owner = THIS_MODULE,
};
-static int exynos5_usbdrd_phy_clk_handle(struct exynos5_usbdrd_phy *phy_drd)
+static void exynos5_usbdrd_gs101_pipe3_init(struct exynos5_usbdrd_phy *phy_drd)
{
- unsigned long ref_rate;
+ void __iomem *regs_pma = phy_drd->reg_pma;
+ void __iomem *regs_phy = phy_drd->reg_phy;
+ u32 reg;
+
+ exynos5_usbdrd_usbdp_g2_v4_ctrl_pma_ready(phy_drd);
+
+ /* force aux off */
+ reg = readl(regs_pma + EXYNOS9_PMA_USBDP_CMN_REG0008);
+ reg &= ~CMN_REG0008_AUX_EN;
+ reg |= CMN_REG0008_OVRD_AUX_EN;
+ writel(reg, regs_pma + EXYNOS9_PMA_USBDP_CMN_REG0008);
+
+ exynos5_usbdrd_apply_phy_tunes(phy_drd, PTS_PIPE3_PREINIT);
+ exynos5_usbdrd_apply_phy_tunes(phy_drd, PTS_PIPE3_INIT);
+ exynos5_usbdrd_apply_phy_tunes(phy_drd, PTS_PIPE3_POSTINIT);
+
+ exynos5_usbdrd_usbdp_g2_v4_pma_lane_mux_sel(phy_drd);
+
+ /* reset release from port */
+ reg = readl(regs_phy + EXYNOS850_DRD_SECPMACTL);
+ reg &= ~(SECPMACTL_PMA_TRSV_SW_RST | SECPMACTL_PMA_CMN_SW_RST |
+ SECPMACTL_PMA_INIT_SW_RST);
+ writel(reg, regs_phy + EXYNOS850_DRD_SECPMACTL);
+
+ if (!exynos5_usbdrd_usbdp_g2_v4_pma_check_pll_lock(phy_drd))
+ exynos5_usbdrd_usbdp_g2_v4_pma_check_cdr_lock(phy_drd);
+}
+
+static int exynos5_usbdrd_gs101_phy_init(struct phy *phy)
+{
+ struct phy_usb_instance *inst = phy_get_drvdata(phy);
+ struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
int ret;
- phy_drd->clk = devm_clk_get(phy_drd->dev, "phy");
- if (IS_ERR(phy_drd->clk)) {
- dev_err(phy_drd->dev, "Failed to get phy clock\n");
- return PTR_ERR(phy_drd->clk);
+ if (inst->phy_cfg->id == EXYNOS5_DRDPHY_UTMI) {
+ /* Power-on PHY ... */
+ ret = regulator_bulk_enable(phy_drd->drv_data->n_regulators,
+ phy_drd->regulators);
+ if (ret) {
+ dev_err(phy_drd->dev,
+ "Failed to enable PHY regulator(s)\n");
+ return ret;
+ }
}
+ /*
+ * ... and ungate power via PMU. Without this here, we get an SError
+ * trying to access PMA registers
+ */
+ exynos5_usbdrd_phy_isol(inst, false);
- phy_drd->ref_clk = devm_clk_get(phy_drd->dev, "ref");
- if (IS_ERR(phy_drd->ref_clk)) {
- dev_err(phy_drd->dev, "Failed to get phy reference clock\n");
- return PTR_ERR(phy_drd->ref_clk);
- }
- ref_rate = clk_get_rate(phy_drd->ref_clk);
+ return exynos850_usbdrd_phy_init(phy);
+}
- ret = exynos5_rate_to_clk(ref_rate, &phy_drd->extrefclk);
- if (ret) {
- dev_err(phy_drd->dev, "Clock rate (%ld) not supported\n",
- ref_rate);
- return ret;
+static int exynos5_usbdrd_gs101_phy_exit(struct phy *phy)
+{
+ struct phy_usb_instance *inst = phy_get_drvdata(phy);
+ struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
+ int ret;
+
+ if (inst->phy_cfg->id == EXYNOS5_DRDPHY_UTMI) {
+ ret = exynos850_usbdrd_phy_exit(phy);
+ if (ret)
+ return ret;
}
- if (!phy_drd->drv_data->has_common_clk_gate) {
- phy_drd->pipeclk = devm_clk_get(phy_drd->dev, "phy_pipe");
- if (IS_ERR(phy_drd->pipeclk)) {
- dev_info(phy_drd->dev,
- "PIPE3 phy operational clock not specified\n");
- phy_drd->pipeclk = NULL;
- }
+ exynos5_usbdrd_phy_isol(inst, true);
- phy_drd->utmiclk = devm_clk_get(phy_drd->dev, "phy_utmi");
- if (IS_ERR(phy_drd->utmiclk)) {
- dev_info(phy_drd->dev,
- "UTMI phy operational clock not specified\n");
- phy_drd->utmiclk = NULL;
- }
+ if (inst->phy_cfg->id != EXYNOS5_DRDPHY_UTMI)
+ return 0;
+
+ return regulator_bulk_disable(phy_drd->drv_data->n_regulators,
+ phy_drd->regulators);
+}
+
+static const struct phy_ops gs101_usbdrd_phy_ops = {
+ .init = exynos5_usbdrd_gs101_phy_init,
+ .exit = exynos5_usbdrd_gs101_phy_exit,
+ .owner = THIS_MODULE,
+};
+
+static int exynos5_usbdrd_phy_clk_handle(struct exynos5_usbdrd_phy *phy_drd)
+{
+ int ret;
+ struct clk *ref_clk;
+ unsigned long ref_rate;
+
+ phy_drd->clks = devm_kcalloc(phy_drd->dev, phy_drd->drv_data->n_clks,
+ sizeof(*phy_drd->clks), GFP_KERNEL);
+ if (!phy_drd->clks)
+ return -ENOMEM;
- phy_drd->itpclk = devm_clk_get(phy_drd->dev, "itp");
- if (IS_ERR(phy_drd->itpclk)) {
- dev_info(phy_drd->dev,
- "ITP clock from main OSC not specified\n");
- phy_drd->itpclk = NULL;
+ for (int i = 0; i < phy_drd->drv_data->n_clks; ++i)
+ phy_drd->clks[i].id = phy_drd->drv_data->clk_names[i];
+
+ ret = devm_clk_bulk_get(phy_drd->dev, phy_drd->drv_data->n_clks,
+ phy_drd->clks);
+ if (ret)
+ return dev_err_probe(phy_drd->dev, ret,
+ "failed to get phy clock(s)\n");
+
+ phy_drd->core_clks = devm_kcalloc(phy_drd->dev,
+ phy_drd->drv_data->n_core_clks,
+ sizeof(*phy_drd->core_clks),
+ GFP_KERNEL);
+ if (!phy_drd->core_clks)
+ return -ENOMEM;
+
+ for (int i = 0; i < phy_drd->drv_data->n_core_clks; ++i)
+ phy_drd->core_clks[i].id = phy_drd->drv_data->core_clk_names[i];
+
+ ret = devm_clk_bulk_get(phy_drd->dev, phy_drd->drv_data->n_core_clks,
+ phy_drd->core_clks);
+ if (ret)
+ return dev_err_probe(phy_drd->dev, ret,
+ "failed to get phy core clock(s)\n");
+
+ ref_clk = NULL;
+ for (int i = 0; i < phy_drd->drv_data->n_core_clks; ++i) {
+ if (!strcmp(phy_drd->core_clks[i].id, "ref")) {
+ ref_clk = phy_drd->core_clks[i].clk;
+ break;
}
}
+ if (!ref_clk)
+ return dev_err_probe(phy_drd->dev, -ENODEV,
+ "failed to find phy reference clock\n");
+
+ ref_rate = clk_get_rate(ref_clk);
+ ret = exynos5_rate_to_clk(ref_rate, &phy_drd->extrefclk);
+ if (ret)
+ return dev_err_probe(phy_drd->dev, ret,
+ "clock rate (%ld) not supported\n",
+ ref_rate);
return 0;
}
@@ -941,19 +1397,45 @@ static const struct exynos5_usbdrd_phy_config phy_cfg_exynos850[] = {
},
};
+static const char * const exynos5_clk_names[] = {
+ "phy",
+};
+
+static const char * const exynos5_core_clk_names[] = {
+ "ref",
+};
+
+static const char * const exynos5433_core_clk_names[] = {
+ "ref", "phy_pipe", "phy_utmi", "itp",
+};
+
+static const char * const exynos5_regulator_names[] = {
+ "vbus", "vbus-boost",
+};
+
static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
.phy_cfg = phy_cfg_exynos5,
.phy_ops = &exynos5_usbdrd_phy_ops,
.pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
.pmu_offset_usbdrd1_phy = EXYNOS5420_USBDRD1_PHY_CONTROL,
- .has_common_clk_gate = true,
+ .clk_names = exynos5_clk_names,
+ .n_clks = ARRAY_SIZE(exynos5_clk_names),
+ .core_clk_names = exynos5_core_clk_names,
+ .n_core_clks = ARRAY_SIZE(exynos5_core_clk_names),
+ .regulator_names = exynos5_regulator_names,
+ .n_regulators = ARRAY_SIZE(exynos5_regulator_names),
};
static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
.phy_cfg = phy_cfg_exynos5,
.phy_ops = &exynos5_usbdrd_phy_ops,
.pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
- .has_common_clk_gate = true,
+ .clk_names = exynos5_clk_names,
+ .n_clks = ARRAY_SIZE(exynos5_clk_names),
+ .core_clk_names = exynos5_core_clk_names,
+ .n_core_clks = ARRAY_SIZE(exynos5_core_clk_names),
+ .regulator_names = exynos5_regulator_names,
+ .n_regulators = ARRAY_SIZE(exynos5_regulator_names),
};
static const struct exynos5_usbdrd_phy_drvdata exynos5433_usbdrd_phy = {
@@ -961,25 +1443,218 @@ static const struct exynos5_usbdrd_phy_drvdata exynos5433_usbdrd_phy = {
.phy_ops = &exynos5_usbdrd_phy_ops,
.pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
.pmu_offset_usbdrd1_phy = EXYNOS5433_USBHOST30_PHY_CONTROL,
- .has_common_clk_gate = false,
+ .clk_names = exynos5_clk_names,
+ .n_clks = ARRAY_SIZE(exynos5_clk_names),
+ .core_clk_names = exynos5433_core_clk_names,
+ .n_core_clks = ARRAY_SIZE(exynos5433_core_clk_names),
+ .regulator_names = exynos5_regulator_names,
+ .n_regulators = ARRAY_SIZE(exynos5_regulator_names),
};
static const struct exynos5_usbdrd_phy_drvdata exynos7_usbdrd_phy = {
.phy_cfg = phy_cfg_exynos5,
.phy_ops = &exynos5_usbdrd_phy_ops,
.pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
- .has_common_clk_gate = false,
+ .clk_names = exynos5_clk_names,
+ .n_clks = ARRAY_SIZE(exynos5_clk_names),
+ .core_clk_names = exynos5433_core_clk_names,
+ .n_core_clks = ARRAY_SIZE(exynos5433_core_clk_names),
+ .regulator_names = exynos5_regulator_names,
+ .n_regulators = ARRAY_SIZE(exynos5_regulator_names),
};
static const struct exynos5_usbdrd_phy_drvdata exynos850_usbdrd_phy = {
.phy_cfg = phy_cfg_exynos850,
.phy_ops = &exynos850_usbdrd_phy_ops,
.pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
- .has_common_clk_gate = true,
+ .clk_names = exynos5_clk_names,
+ .n_clks = ARRAY_SIZE(exynos5_clk_names),
+ .core_clk_names = exynos5_core_clk_names,
+ .n_core_clks = ARRAY_SIZE(exynos5_core_clk_names),
+ .regulator_names = exynos5_regulator_names,
+ .n_regulators = ARRAY_SIZE(exynos5_regulator_names),
+};
+
+static const struct exynos5_usbdrd_phy_config phy_cfg_gs101[] = {
+ {
+ .id = EXYNOS5_DRDPHY_UTMI,
+ .phy_isol = exynos5_usbdrd_phy_isol,
+ .phy_init = exynos850_usbdrd_utmi_init,
+ },
+ {
+ .id = EXYNOS5_DRDPHY_PIPE3,
+ .phy_isol = exynos5_usbdrd_phy_isol,
+ .phy_init = exynos5_usbdrd_gs101_pipe3_init,
+ },
+};
+
+static const struct exynos5_usbdrd_phy_tuning gs101_tunes_utmi_postinit[] = {
+ PHY_TUNING_ENTRY_PHY(EXYNOS850_DRD_HSPPARACON,
+ (HSPPARACON_TXVREF | HSPPARACON_TXRES |
+ HSPPARACON_TXPREEMPAMP | HSPPARACON_SQRX |
+ HSPPARACON_COMPDIS),
+ (FIELD_PREP_CONST(HSPPARACON_TXVREF, 6) |
+ FIELD_PREP_CONST(HSPPARACON_TXRES, 1) |
+ FIELD_PREP_CONST(HSPPARACON_TXPREEMPAMP, 3) |
+ FIELD_PREP_CONST(HSPPARACON_SQRX, 5) |
+ FIELD_PREP_CONST(HSPPARACON_COMPDIS, 7))),
+ PHY_TUNING_ENTRY_LAST
+};
+
+static const struct exynos5_usbdrd_phy_tuning gs101_tunes_pipe3_preinit[] = {
+ /* preinit */
+ /* CDR data mode exit GEN1 ON / GEN2 OFF */
+ PHY_TUNING_ENTRY_PMA(0x0c8c, -1, 0xff),
+ PHY_TUNING_ENTRY_PMA(0x1c8c, -1, 0xff),
+ PHY_TUNING_ENTRY_PMA(0x0c9c, -1, 0x7d),
+ PHY_TUNING_ENTRY_PMA(0x1c9c, -1, 0x7d),
+ /* improve EDS distribution */
+ PHY_TUNING_ENTRY_PMA(0x0e7c, -1, 0x06),
+ PHY_TUNING_ENTRY_PMA(0x09e0, -1, 0x00),
+ PHY_TUNING_ENTRY_PMA(0x09e4, -1, 0x36),
+ PHY_TUNING_ENTRY_PMA(0x1e7c, -1, 0x06),
+ PHY_TUNING_ENTRY_PMA(0x1e90, -1, 0x00),
+ PHY_TUNING_ENTRY_PMA(0x1e94, -1, 0x36),
+ /* improve LVCC */
+ PHY_TUNING_ENTRY_PMA(0x08f0, -1, 0x30),
+ PHY_TUNING_ENTRY_PMA(0x18f0, -1, 0x30),
+ /* LFPS RX VIH shmoo hole */
+ PHY_TUNING_ENTRY_PMA(0x0a08, -1, 0x0c),
+ PHY_TUNING_ENTRY_PMA(0x1a08, -1, 0x0c),
+ /* remove unrelated option for v4 phy */
+ PHY_TUNING_ENTRY_PMA(0x0a0c, -1, 0x05),
+ PHY_TUNING_ENTRY_PMA(0x1a0c, -1, 0x05),
+ /* improve Gen2 LVCC */
+ PHY_TUNING_ENTRY_PMA(0x00f8, -1, 0x1c),
+ PHY_TUNING_ENTRY_PMA(0x00fc, -1, 0x54),
+ /* Change Vth of RCV_DET because of TD 7.40 Polling Retry Test */
+ PHY_TUNING_ENTRY_PMA(0x104c, -1, 0x07),
+ PHY_TUNING_ENTRY_PMA(0x204c, -1, 0x07),
+ /* reduce Ux Exit time, assuming 26MHz clock */
+ /* Gen1 */
+ PHY_TUNING_ENTRY_PMA(0x0ca8, -1, 0x00),
+ PHY_TUNING_ENTRY_PMA(0x0cac, -1, 0x04),
+ PHY_TUNING_ENTRY_PMA(0x1ca8, -1, 0x00),
+ PHY_TUNING_ENTRY_PMA(0x1cac, -1, 0x04),
+ /* Gen2 */
+ PHY_TUNING_ENTRY_PMA(0x0cb8, -1, 0x00),
+ PHY_TUNING_ENTRY_PMA(0x0cbc, -1, 0x04),
+ PHY_TUNING_ENTRY_PMA(0x1cb8, -1, 0x00),
+ PHY_TUNING_ENTRY_PMA(0x1cbc, -1, 0x04),
+ /* RX impedance setting */
+ PHY_TUNING_ENTRY_PMA(0x0bb0, 0x03, 0x01),
+ PHY_TUNING_ENTRY_PMA(0x0bb4, 0xf0, 0xa0),
+ PHY_TUNING_ENTRY_PMA(0x1bb0, 0x03, 0x01),
+ PHY_TUNING_ENTRY_PMA(0x1bb4, 0xf0, 0xa0),
+
+ PHY_TUNING_ENTRY_LAST
+};
+
+static const struct exynos5_usbdrd_phy_tuning gs101_tunes_pipe3_init[] = {
+ /* init */
+ /* abnormal common pattern mask */
+ PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_BACK_END_MODE_VEC,
+ BACK_END_MODE_VEC_DISABLE_DATA_MASK, 0),
+ /* de-serializer enabled when U2 */
+ PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_OUT_VEC_2, PCS_OUT_VEC_B4_DYNAMIC,
+ PCS_OUT_VEC_B4_SEL_OUT),
+ /* TX Keeper Disable, Squelch on when U3 */
+ PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_OUT_VEC_3, PCS_OUT_VEC_B7_DYNAMIC,
+ PCS_OUT_VEC_B7_SEL_OUT | PCS_OUT_VEC_B2_SEL_OUT),
+ PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_NS_VEC_PS1_N1, -1,
+ (FIELD_PREP_CONST(NS_VEC_NS_REQ, 5) |
+ NS_VEC_ENABLE_TIMER |
+ FIELD_PREP_CONST(NS_VEC_SEL_TIMEOUT, 3))),
+ PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_NS_VEC_PS2_N0, -1,
+ (FIELD_PREP_CONST(NS_VEC_NS_REQ, 1) |
+ NS_VEC_ENABLE_TIMER |
+ FIELD_PREP_CONST(NS_VEC_SEL_TIMEOUT, 3) |
+ FIELD_PREP_CONST(NS_VEC_COND_MASK, 2) |
+ FIELD_PREP_CONST(NS_VEC_EXP_COND, 2))),
+ PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_NS_VEC_PS3_N0, -1,
+ (FIELD_PREP_CONST(NS_VEC_NS_REQ, 1) |
+ NS_VEC_ENABLE_TIMER |
+ FIELD_PREP_CONST(NS_VEC_SEL_TIMEOUT, 3) |
+ FIELD_PREP_CONST(NS_VEC_COND_MASK, 7) |
+ FIELD_PREP_CONST(NS_VEC_EXP_COND, 7))),
+ PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_TIMEOUT_0, -1, 112),
+ /* Block Aligner Type B */
+ PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_RX_CONTROL, 0,
+ RX_CONTROL_EN_BLOCK_ALIGNER_TYPE_B),
+ /* Block align at TS1/TS2 for Gen2 stability (Gen2 only) */
+ PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_RX_CONTROL_DEBUG,
+ RX_CONTROL_DEBUG_NUM_COM_FOUND,
+ (RX_CONTROL_DEBUG_EN_TS_CHECK |
+ /*
+ * increase pcs ts1 adding packet-cnt 1 --> 4
+ * lnx_rx_valid_rstn_delay_rise_sp/ssp :
+ * 19.6us(0x200) -> 15.3us(0x4)
+ */
+ FIELD_PREP_CONST(RX_CONTROL_DEBUG_NUM_COM_FOUND, 4))),
+ /* Gen1 Tx DRIVER pre-shoot, de-emphasis, level ctrl */
+ PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_HS_TX_COEF_MAP_0,
+ (HS_TX_COEF_MAP_0_SSTX_DEEMP | HS_TX_COEF_MAP_0_SSTX_LEVEL |
+ HS_TX_COEF_MAP_0_SSTX_PRE_SHOOT),
+ (FIELD_PREP_CONST(HS_TX_COEF_MAP_0_SSTX_DEEMP, 8) |
+ FIELD_PREP_CONST(HS_TX_COEF_MAP_0_SSTX_LEVEL, 0xb) |
+ FIELD_PREP_CONST(HS_TX_COEF_MAP_0_SSTX_PRE_SHOOT, 0))),
+ /* Gen2 Tx DRIVER level ctrl */
+ PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_LOCAL_COEF,
+ LOCAL_COEF_PMA_CENTER_COEF,
+ FIELD_PREP_CONST(LOCAL_COEF_PMA_CENTER_COEF, 0xb)),
+ /* Gen2 U1 exit LFPS duration : 900ns ~ 1.2us */
+ PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_TIMEOUT_3, -1, 4096),
+ /* set skp_remove_th 0x2 -> 0x7 for avoiding retry problem. */
+ PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_EBUF_PARAM,
+ EBUF_PARAM_SKP_REMOVE_TH_EMPTY_MODE,
+ FIELD_PREP_CONST(EBUF_PARAM_SKP_REMOVE_TH_EMPTY_MODE, 0x7)),
+
+ PHY_TUNING_ENTRY_LAST
+};
+
+static const struct exynos5_usbdrd_phy_tuning gs101_tunes_pipe3_postlock[] = {
+ /* Squelch off when U3 */
+ PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_OUT_VEC_3, PCS_OUT_VEC_B2_SEL_OUT, 0),
+
+ PHY_TUNING_ENTRY_LAST
+};
+
+static const struct exynos5_usbdrd_phy_tuning *gs101_tunes[PTS_MAX] = {
+ [PTS_UTMI_POSTINIT] = gs101_tunes_utmi_postinit,
+ [PTS_PIPE3_PREINIT] = gs101_tunes_pipe3_preinit,
+ [PTS_PIPE3_INIT] = gs101_tunes_pipe3_init,
+ [PTS_PIPE3_POSTLOCK] = gs101_tunes_pipe3_postlock,
+};
+
+static const char * const gs101_clk_names[] = {
+ "phy", "ctrl_aclk", "ctrl_pclk", "scl_pclk",
+};
+
+static const char * const gs101_regulator_names[] = {
+ "pll",
+ "dvdd-usb20", "vddh-usb20", "vdd33-usb20",
+ "vdda-usbdp", "vddh-usbdp",
+};
+
+static const struct exynos5_usbdrd_phy_drvdata gs101_usbd31rd_phy = {
+ .phy_cfg = phy_cfg_gs101,
+ .phy_tunes = gs101_tunes,
+ .phy_ops = &gs101_usbdrd_phy_ops,
+ .pmu_offset_usbdrd0_phy = GS101_PHY_CTRL_USB20,
+ .pmu_offset_usbdrd0_phy_ss = GS101_PHY_CTRL_USBDP,
+ .clk_names = gs101_clk_names,
+ .n_clks = ARRAY_SIZE(gs101_clk_names),
+ .core_clk_names = exynos5_core_clk_names,
+ .n_core_clks = ARRAY_SIZE(exynos5_core_clk_names),
+ .regulator_names = gs101_regulator_names,
+ .n_regulators = ARRAY_SIZE(gs101_regulator_names),
};
static const struct of_device_id exynos5_usbdrd_phy_of_match[] = {
{
+ .compatible = "google,gs101-usb31drd-phy",
+ .data = &gs101_usbd31rd_phy
+ }, {
.compatible = "samsung,exynos5250-usbdrd-phy",
.data = &exynos5250_usbdrd_phy
}, {
@@ -1018,21 +1693,38 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
dev_set_drvdata(dev, phy_drd);
phy_drd->dev = dev;
- phy_drd->reg_phy = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(phy_drd->reg_phy))
- return PTR_ERR(phy_drd->reg_phy);
-
drv_data = of_device_get_match_data(dev);
if (!drv_data)
return -EINVAL;
-
phy_drd->drv_data = drv_data;
+ if (of_property_present(dev->of_node, "reg-names")) {
+ void __iomem *reg;
+
+ reg = devm_platform_ioremap_resource_byname(pdev, "phy");
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+ phy_drd->reg_phy = reg;
+
+ reg = devm_platform_ioremap_resource_byname(pdev, "pcs");
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+ phy_drd->reg_pcs = reg;
+
+ reg = devm_platform_ioremap_resource_byname(pdev, "pma");
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+ phy_drd->reg_pma = reg;
+ } else {
+ /* DTB with just a single region */
+ phy_drd->reg_phy = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(phy_drd->reg_phy))
+ return PTR_ERR(phy_drd->reg_phy);
+ }
+
ret = exynos5_usbdrd_phy_clk_handle(phy_drd);
- if (ret) {
- dev_err(dev, "Failed to initialize clocks\n");
+ if (ret)
return ret;
- }
reg_pmu = syscon_regmap_lookup_by_phandle(dev->of_node,
"samsung,pmu-syscon");
@@ -1050,36 +1742,20 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
if (channel < 0)
dev_dbg(dev, "Not a multi-controller usbdrd phy\n");
- switch (channel) {
- case 1:
- pmu_offset = phy_drd->drv_data->pmu_offset_usbdrd1_phy;
- break;
- case 0:
- default:
- pmu_offset = phy_drd->drv_data->pmu_offset_usbdrd0_phy;
- break;
- }
-
- /* Get Vbus regulators */
- phy_drd->vbus = devm_regulator_get(dev, "vbus");
- if (IS_ERR(phy_drd->vbus)) {
- ret = PTR_ERR(phy_drd->vbus);
- if (ret == -EPROBE_DEFER)
- return ret;
-
- dev_warn(dev, "Failed to get VBUS supply regulator\n");
- phy_drd->vbus = NULL;
- }
-
- phy_drd->vbus_boost = devm_regulator_get(dev, "vbus-boost");
- if (IS_ERR(phy_drd->vbus_boost)) {
- ret = PTR_ERR(phy_drd->vbus_boost);
- if (ret == -EPROBE_DEFER)
- return ret;
-
- dev_warn(dev, "Failed to get VBUS boost supply regulator\n");
- phy_drd->vbus_boost = NULL;
- }
+ /* Get regulators */
+ phy_drd->regulators = devm_kcalloc(dev,
+ drv_data->n_regulators,
+ sizeof(*phy_drd->regulators),
+ GFP_KERNEL);
+ if (!phy_drd->regulators)
+ return -ENOMEM;
+ regulator_bulk_set_supply_names(phy_drd->regulators,
+ drv_data->regulator_names,
+ drv_data->n_regulators);
+ ret = devm_regulator_bulk_get(dev, drv_data->n_regulators,
+ phy_drd->regulators);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to get regulators\n");
dev_vdbg(dev, "Creating usbdrd_phy phy\n");
@@ -1094,6 +1770,18 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
phy_drd->phys[i].phy = phy;
phy_drd->phys[i].index = i;
phy_drd->phys[i].reg_pmu = reg_pmu;
+ switch (channel) {
+ case 1:
+ pmu_offset = drv_data->pmu_offset_usbdrd1_phy;
+ break;
+ case 0:
+ default:
+ pmu_offset = drv_data->pmu_offset_usbdrd0_phy;
+ if (i == EXYNOS5_DRDPHY_PIPE3 && drv_data
+ ->pmu_offset_usbdrd0_phy_ss)
+ pmu_offset = drv_data->pmu_offset_usbdrd0_phy_ss;
+ break;
+ }
phy_drd->phys[i].pmu_offset = pmu_offset;
phy_drd->phys[i].phy_cfg = &drv_data->phy_cfg[i];
phy_set_drvdata(phy, &phy_drd->phys[i]);
diff --git a/drivers/phy/samsung/phy-exynos5250-usb2.c b/drivers/phy/samsung/phy-exynos5250-usb2.c
index e198010e1bfd..21b06072f866 100644
--- a/drivers/phy/samsung/phy-exynos5250-usb2.c
+++ b/drivers/phy/samsung/phy-exynos5250-usb2.c
@@ -121,7 +121,7 @@
#define EXYNOS_5420_USB_ISOL_HOST_OFFSET 0x70C
#define EXYNOS_5250_USB_ISOL_ENABLE BIT(0)
-/* Mode swtich register */
+/* Mode switch register */
#define EXYNOS_5250_MODE_SWITCH_OFFSET 0x230
#define EXYNOS_5250_MODE_SWITCH_MASK 1
#define EXYNOS_5250_MODE_SWITCH_DEVICE 0
diff --git a/drivers/phy/samsung/phy-exynos7-ufs.c b/drivers/phy/samsung/phy-exynos7-ufs.c
index a982e7c128c5..15eec1d9e0e0 100644
--- a/drivers/phy/samsung/phy-exynos7-ufs.c
+++ b/drivers/phy/samsung/phy-exynos7-ufs.c
@@ -82,4 +82,5 @@ const struct samsung_ufs_phy_drvdata exynos7_ufs_phy = {
.clk_list = exynos7_ufs_phy_clks,
.num_clks = ARRAY_SIZE(exynos7_ufs_phy_clks),
.cdr_lock_status_offset = EXYNOS7_EMBEDDED_COMBO_PHY_CDR_LOCK_STATUS,
+ .wait_for_cdr = samsung_ufs_phy_wait_for_lock_acq,
};
diff --git a/drivers/phy/samsung/phy-exynosautov9-ufs.c b/drivers/phy/samsung/phy-exynosautov9-ufs.c
index 49e2bcbef0b4..9c3e030f07ba 100644
--- a/drivers/phy/samsung/phy-exynosautov9-ufs.c
+++ b/drivers/phy/samsung/phy-exynosautov9-ufs.c
@@ -71,4 +71,5 @@ const struct samsung_ufs_phy_drvdata exynosautov9_ufs_phy = {
.clk_list = exynosautov9_ufs_phy_clks,
.num_clks = ARRAY_SIZE(exynosautov9_ufs_phy_clks),
.cdr_lock_status_offset = EXYNOSAUTOV9_EMBEDDED_COMBO_PHY_CDR_LOCK_STATUS,
+ .wait_for_cdr = samsung_ufs_phy_wait_for_lock_acq,
};
diff --git a/drivers/phy/samsung/phy-fsd-ufs.c b/drivers/phy/samsung/phy-fsd-ufs.c
index d36cabd53434..f2361746db0e 100644
--- a/drivers/phy/samsung/phy-fsd-ufs.c
+++ b/drivers/phy/samsung/phy-fsd-ufs.c
@@ -60,4 +60,5 @@ const struct samsung_ufs_phy_drvdata fsd_ufs_phy = {
.clk_list = fsd_ufs_phy_clks,
.num_clks = ARRAY_SIZE(fsd_ufs_phy_clks),
.cdr_lock_status_offset = FSD_EMBEDDED_COMBO_PHY_CDR_LOCK_STATUS,
+ .wait_for_cdr = samsung_ufs_phy_wait_for_lock_acq,
};
diff --git a/drivers/phy/samsung/phy-gs101-ufs.c b/drivers/phy/samsung/phy-gs101-ufs.c
new file mode 100644
index 000000000000..17b798da5b57
--- /dev/null
+++ b/drivers/phy/samsung/phy-gs101-ufs.c
@@ -0,0 +1,182 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * UFS PHY driver data for Google Tensor gs101 SoC
+ *
+ * Copyright (C) 2024 Linaro Ltd
+ * Author: Peter Griffin <peter.griffin@linaro.org>
+ */
+
+#include "phy-samsung-ufs.h"
+
+#define TENSOR_GS101_PHY_CTRL 0x3ec8
+#define TENSOR_GS101_PHY_CTRL_MASK 0x1
+#define TENSOR_GS101_PHY_CTRL_EN BIT(0)
+#define PHY_GS101_LANE_OFFSET 0x200
+#define TRSV_REG338 0x338
+#define LN0_MON_RX_CAL_DONE BIT(3)
+#define TRSV_REG339 0x339
+#define LN0_MON_RX_CDR_FLD_CK_MODE_DONE BIT(3)
+#define TRSV_REG222 0x222
+#define LN0_OVRD_RX_CDR_EN BIT(4)
+#define LN0_RX_CDR_EN BIT(3)
+
+#define PHY_PMA_TRSV_ADDR(reg, lane) (PHY_APB_ADDR((reg) + \
+ ((lane) * PHY_GS101_LANE_OFFSET)))
+
+#define PHY_TRSV_REG_CFG_GS101(o, v, d) \
+ PHY_TRSV_REG_CFG_OFFSET(o, v, d, PHY_GS101_LANE_OFFSET)
+
+/* Calibration for phy initialization */
+static const struct samsung_ufs_phy_cfg tensor_gs101_pre_init_cfg[] = {
+ PHY_COMN_REG_CFG(0x43, 0x10, PWR_MODE_ANY),
+ PHY_COMN_REG_CFG(0x3C, 0x14, PWR_MODE_ANY),
+ PHY_COMN_REG_CFG(0x46, 0x48, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x200, 0x00, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x201, 0x06, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x202, 0x06, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x203, 0x0a, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x204, 0x00, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x205, 0x11, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x207, 0x0c, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x2E1, 0xc0, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x22D, 0xb8, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x234, 0x60, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x238, 0x13, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x239, 0x48, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x23A, 0x01, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x23B, 0x25, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x23C, 0x2a, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x23D, 0x01, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x23E, 0x13, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x23F, 0x13, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x240, 0x4a, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x243, 0x40, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x244, 0x02, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x25D, 0x00, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x25E, 0x3f, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x25F, 0xff, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x273, 0x33, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x274, 0x50, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x284, 0x02, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x285, 0x02, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x2A2, 0x04, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x25D, 0x01, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x2FA, 0x01, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x286, 0x03, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x287, 0x03, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x288, 0x03, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x289, 0x03, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x2B3, 0x04, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x2B6, 0x0b, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x2B7, 0x0b, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x2B8, 0x0b, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x2B9, 0x0b, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x2BA, 0x0b, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x2BB, 0x06, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x2BC, 0x06, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x2BD, 0x06, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x29E, 0x06, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x2E4, 0x1a, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x2ED, 0x25, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x269, 0x1a, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x2F4, 0x2f, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x34B, 0x01, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x34C, 0x23, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x34D, 0x23, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x34E, 0x45, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x34F, 0x00, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x350, 0x31, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x351, 0x00, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x352, 0x02, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x353, 0x00, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x354, 0x01, PWR_MODE_ANY),
+ PHY_COMN_REG_CFG(0x43, 0x18, PWR_MODE_ANY),
+ PHY_COMN_REG_CFG(0x43, 0x00, PWR_MODE_ANY),
+ END_UFS_PHY_CFG,
+};
+
+static const struct samsung_ufs_phy_cfg tensor_gs101_pre_pwr_hs_config[] = {
+ PHY_TRSV_REG_CFG_GS101(0x369, 0x11, PWR_MODE_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x246, 0x03, PWR_MODE_ANY),
+};
+
+/* Calibration for HS mode series A/B */
+static const struct samsung_ufs_phy_cfg tensor_gs101_post_pwr_hs_config[] = {
+ PHY_COMN_REG_CFG(0x8, 0x60, PWR_MODE_PWM_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x222, 0x08, PWR_MODE_PWM_ANY),
+ PHY_TRSV_REG_CFG_GS101(0x246, 0x01, PWR_MODE_ANY),
+ END_UFS_PHY_CFG,
+};
+
+static const struct samsung_ufs_phy_cfg *tensor_gs101_ufs_phy_cfgs[CFG_TAG_MAX] = {
+ [CFG_PRE_INIT] = tensor_gs101_pre_init_cfg,
+ [CFG_PRE_PWR_HS] = tensor_gs101_pre_pwr_hs_config,
+ [CFG_POST_PWR_HS] = tensor_gs101_post_pwr_hs_config,
+};
+
+static const char * const tensor_gs101_ufs_phy_clks[] = {
+ "ref_clk",
+};
+
+static int gs101_phy_wait_for_calibration(struct phy *phy, u8 lane)
+{
+ struct samsung_ufs_phy *ufs_phy = get_samsung_ufs_phy(phy);
+ const unsigned int timeout_us = 40000;
+ const unsigned int sleep_us = 40;
+ u32 val;
+ u32 off;
+ int err;
+
+ off = PHY_PMA_TRSV_ADDR(TRSV_REG338, lane);
+
+ err = readl_poll_timeout(ufs_phy->reg_pma + off,
+ val, (val & LN0_MON_RX_CAL_DONE),
+ sleep_us, timeout_us);
+
+ if (err) {
+ dev_err(ufs_phy->dev,
+ "failed to get phy cal done %d\n", err);
+ }
+
+ return err;
+}
+
+#define DELAY_IN_US 40
+#define RETRY_CNT 100
+static int gs101_phy_wait_for_cdr_lock(struct phy *phy, u8 lane)
+{
+ struct samsung_ufs_phy *ufs_phy = get_samsung_ufs_phy(phy);
+ u32 val;
+ int i;
+
+ for (i = 0; i < RETRY_CNT; i++) {
+ udelay(DELAY_IN_US);
+ val = readl(ufs_phy->reg_pma +
+ PHY_PMA_TRSV_ADDR(TRSV_REG339, lane));
+
+ if (val & LN0_MON_RX_CDR_FLD_CK_MODE_DONE)
+ return 0;
+
+ udelay(DELAY_IN_US);
+ /* Override and enable clock data recovery */
+ writel(LN0_OVRD_RX_CDR_EN, ufs_phy->reg_pma +
+ PHY_PMA_TRSV_ADDR(TRSV_REG222, lane));
+ writel(LN0_OVRD_RX_CDR_EN | LN0_RX_CDR_EN,
+ ufs_phy->reg_pma + PHY_PMA_TRSV_ADDR(TRSV_REG222, lane));
+ }
+ dev_err(ufs_phy->dev, "failed to get cdr lock\n");
+ return -ETIMEDOUT;
+}
+
+const struct samsung_ufs_phy_drvdata tensor_gs101_ufs_phy = {
+ .cfgs = tensor_gs101_ufs_phy_cfgs,
+ .isol = {
+ .offset = TENSOR_GS101_PHY_CTRL,
+ .mask = TENSOR_GS101_PHY_CTRL_MASK,
+ .en = TENSOR_GS101_PHY_CTRL_EN,
+ },
+ .clk_list = tensor_gs101_ufs_phy_clks,
+ .num_clks = ARRAY_SIZE(tensor_gs101_ufs_phy_clks),
+ .wait_for_cal = gs101_phy_wait_for_calibration,
+ .wait_for_cdr = gs101_phy_wait_for_cdr_lock,
+};
diff --git a/drivers/phy/samsung/phy-samsung-ufs.c b/drivers/phy/samsung/phy-samsung-ufs.c
index 183c88e3d1ec..8e9ccd39f97e 100644
--- a/drivers/phy/samsung/phy-samsung-ufs.c
+++ b/drivers/phy/samsung/phy-samsung-ufs.c
@@ -45,7 +45,7 @@ static void samsung_ufs_phy_config(struct samsung_ufs_phy *phy,
}
}
-static int samsung_ufs_phy_wait_for_lock_acq(struct phy *phy)
+int samsung_ufs_phy_wait_for_lock_acq(struct phy *phy, u8 lane)
{
struct samsung_ufs_phy *ufs_phy = get_samsung_ufs_phy(phy);
const unsigned int timeout_us = 100000;
@@ -97,8 +97,21 @@ static int samsung_ufs_phy_calibrate(struct phy *phy)
}
}
- if (ufs_phy->ufs_phy_state == CFG_POST_PWR_HS)
- err = samsung_ufs_phy_wait_for_lock_acq(phy);
+ for_each_phy_lane(ufs_phy, i) {
+ if (ufs_phy->ufs_phy_state == CFG_PRE_INIT &&
+ ufs_phy->drvdata->wait_for_cal) {
+ err = ufs_phy->drvdata->wait_for_cal(phy, i);
+ if (err)
+ goto out;
+ }
+
+ if (ufs_phy->ufs_phy_state == CFG_POST_PWR_HS &&
+ ufs_phy->drvdata->wait_for_cdr) {
+ err = ufs_phy->drvdata->wait_for_cdr(phy, i);
+ if (err)
+ goto out;
+ }
+ }
/**
* In Samsung ufshci, PHY need to be calibrated at different
@@ -255,8 +268,8 @@ static int samsung_ufs_phy_probe(struct platform_device *pdev)
goto out;
}
- phy->reg_pmu = syscon_regmap_lookup_by_phandle(
- dev->of_node, "samsung,pmu-syscon");
+ phy->reg_pmu = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "samsung,pmu-syscon");
if (IS_ERR(phy->reg_pmu)) {
err = PTR_ERR(phy->reg_pmu);
dev_err(dev, "failed syscon remap for pmu\n");
@@ -302,6 +315,9 @@ out:
static const struct of_device_id samsung_ufs_phy_match[] = {
{
+ .compatible = "google,gs101-ufs-phy",
+ .data = &tensor_gs101_ufs_phy,
+ }, {
.compatible = "samsung,exynos7-ufs-phy",
.data = &exynos7_ufs_phy,
}, {
diff --git a/drivers/phy/samsung/phy-samsung-ufs.h b/drivers/phy/samsung/phy-samsung-ufs.h
index e122960cfee8..9b7deef6e10f 100644
--- a/drivers/phy/samsung/phy-samsung-ufs.h
+++ b/drivers/phy/samsung/phy-samsung-ufs.h
@@ -112,6 +112,9 @@ struct samsung_ufs_phy_drvdata {
const char * const *clk_list;
int num_clks;
u32 cdr_lock_status_offset;
+ /* SoC's specific operations */
+ int (*wait_for_cal)(struct phy *phy, u8 lane);
+ int (*wait_for_cdr)(struct phy *phy, u8 lane);
};
struct samsung_ufs_phy {
@@ -139,8 +142,11 @@ static inline void samsung_ufs_phy_ctrl_isol(
phy->isol.mask, isol ? 0 : phy->isol.en);
}
+int samsung_ufs_phy_wait_for_lock_acq(struct phy *phy, u8 lane);
+
extern const struct samsung_ufs_phy_drvdata exynos7_ufs_phy;
extern const struct samsung_ufs_phy_drvdata exynosautov9_ufs_phy;
extern const struct samsung_ufs_phy_drvdata fsd_ufs_phy;
+extern const struct samsung_ufs_phy_drvdata tensor_gs101_ufs_phy;
#endif /* _PHY_SAMSUNG_UFS_ */
diff --git a/drivers/phy/samsung/phy-samsung-usb2.c b/drivers/phy/samsung/phy-samsung-usb2.c
index 68a174eca0ba..9de744cd6f39 100644
--- a/drivers/phy/samsung/phy-samsung-usb2.c
+++ b/drivers/phy/samsung/phy-samsung-usb2.c
@@ -87,7 +87,7 @@ static const struct phy_ops samsung_usb2_phy_ops = {
};
static struct phy *samsung_usb2_phy_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct samsung_usb2_phy_driver *drv;
diff --git a/drivers/phy/socionext/phy-uniphier-usb2.c b/drivers/phy/socionext/phy-uniphier-usb2.c
index 3f2086ed4fe4..21c201717d95 100644
--- a/drivers/phy/socionext/phy-uniphier-usb2.c
+++ b/drivers/phy/socionext/phy-uniphier-usb2.c
@@ -81,7 +81,7 @@ static int uniphier_u2phy_init(struct phy *phy)
}
static struct phy *uniphier_u2phy_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct uniphier_u2phy_priv *priv = dev_get_drvdata(dev);
diff --git a/drivers/phy/st/Kconfig b/drivers/phy/st/Kconfig
index 3fc3d0781fb8..304614b6dabf 100644
--- a/drivers/phy/st/Kconfig
+++ b/drivers/phy/st/Kconfig
@@ -33,6 +33,17 @@ config PHY_STIH407_USB
Enable this support to enable the picoPHY device used by USB2
and USB3 controllers on STMicroelectronics STiH407 SoC families.
+config PHY_STM32_COMBOPHY
+ tristate "STMicroelectronics COMBOPHY driver for STM32MP25"
+ depends on ARCH_STM32 || COMPILE_TEST
+ select GENERIC_PHY
+ help
+ Enable this to support the COMBOPHY device used by USB3 or PCIe
+ controllers on STMicroelectronics STM32MP25 SoC.
+ This driver controls the COMBOPHY block to generate the PCIe 100Mhz
+ reference clock from either the external clock generator or HSE
+ internal SoC clock source.
+
config PHY_STM32_USBPHYC
tristate "STMicroelectronics STM32 USB HS PHY Controller driver"
depends on ARCH_STM32 || COMPILE_TEST
diff --git a/drivers/phy/st/Makefile b/drivers/phy/st/Makefile
index c862dd937b64..cb80e954ea9f 100644
--- a/drivers/phy/st/Makefile
+++ b/drivers/phy/st/Makefile
@@ -3,4 +3,5 @@ obj-$(CONFIG_PHY_MIPHY28LP) += phy-miphy28lp.o
obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY) += phy-spear1310-miphy.o
obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o
obj-$(CONFIG_PHY_STIH407_USB) += phy-stih407-usb.o
+obj-$(CONFIG_PHY_STM32_COMBOPHY) += phy-stm32-combophy.o
obj-$(CONFIG_PHY_STM32_USBPHYC) += phy-stm32-usbphyc.o
diff --git a/drivers/phy/st/phy-miphy28lp.c b/drivers/phy/st/phy-miphy28lp.c
index e30305b77f0d..43cef89af55e 100644
--- a/drivers/phy/st/phy-miphy28lp.c
+++ b/drivers/phy/st/phy-miphy28lp.c
@@ -228,11 +228,6 @@ struct miphy28lp_dev {
int nphys;
};
-struct miphy_initval {
- u16 reg;
- u16 val;
-};
-
enum miphy_sata_gen { SATA_GEN1, SATA_GEN2, SATA_GEN3 };
static char *PHY_TYPE_name[] = { "sata-up", "pcie-up", "", "usb3-up" };
@@ -1074,7 +1069,7 @@ static int miphy28lp_get_addr(struct miphy28lp_phy *miphy_phy)
}
static struct phy *miphy28lp_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct miphy28lp_dev *miphy_dev = dev_get_drvdata(dev);
struct miphy28lp_phy *miphy_phy = NULL;
diff --git a/drivers/phy/st/phy-spear1310-miphy.c b/drivers/phy/st/phy-spear1310-miphy.c
index 35a9831b5161..c661ab63505f 100644
--- a/drivers/phy/st/phy-spear1310-miphy.c
+++ b/drivers/phy/st/phy-spear1310-miphy.c
@@ -183,7 +183,7 @@ static const struct phy_ops spear1310_miphy_ops = {
};
static struct phy *spear1310_miphy_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct spear1310_miphy_priv *priv = dev_get_drvdata(dev);
diff --git a/drivers/phy/st/phy-spear1340-miphy.c b/drivers/phy/st/phy-spear1340-miphy.c
index 34a1cf21015f..85a60d64ebb7 100644
--- a/drivers/phy/st/phy-spear1340-miphy.c
+++ b/drivers/phy/st/phy-spear1340-miphy.c
@@ -220,7 +220,7 @@ static SIMPLE_DEV_PM_OPS(spear1340_miphy_pm_ops, spear1340_miphy_suspend,
spear1340_miphy_resume);
static struct phy *spear1340_miphy_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct spear1340_miphy_priv *priv = dev_get_drvdata(dev);
diff --git a/drivers/phy/st/phy-stm32-combophy.c b/drivers/phy/st/phy-stm32-combophy.c
new file mode 100644
index 000000000000..607b4d607eb5
--- /dev/null
+++ b/drivers/phy/st/phy-stm32-combophy.c
@@ -0,0 +1,605 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * STMicroelectronics COMBOPHY STM32MP25 Controller driver.
+ *
+ * Copyright (C) 2024 STMicroelectronics
+ * Author: Christian Bruel <christian.bruel@foss.st.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/mfd/syscon.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <dt-bindings/phy/phy.h>
+
+#define SYSCFG_COMBOPHY_CR1 0x4c00
+#define SYSCFG_COMBOPHY_CR2 0x4c04
+#define SYSCFG_COMBOPHY_CR4 0x4c0c
+#define SYSCFG_COMBOPHY_CR5 0x4c10
+#define SYSCFG_COMBOPHY_SR 0x4c14
+#define SYSCFG_PCIEPRGCR 0x6080
+
+/* SYSCFG PCIEPRGCR */
+#define STM32MP25_PCIEPRGCR_EN BIT(0)
+#define STM32MP25_PCIEPRG_IMPCTRL_OHM GENMASK(3, 1)
+#define STM32MP25_PCIEPRG_IMPCTRL_VSWING GENMASK(5, 4)
+
+/* SYSCFG SYSCFG_COMBOPHY_SR */
+#define STM32MP25_PIPE0_PHYSTATUS BIT(1)
+
+/* SYSCFG CR1 */
+#define SYSCFG_COMBOPHY_CR1_REFUSEPAD BIT(0)
+#define SYSCFG_COMBOPHY_CR1_MPLLMULT GENMASK(7, 1)
+#define SYSCFG_COMBOPHY_CR1_REFCLKSEL GENMASK(16, 8)
+#define SYSCFG_COMBOPHY_CR1_REFCLKDIV2 BIT(17)
+#define SYSCFG_COMBOPHY_CR1_REFSSPEN BIT(18)
+#define SYSCFG_COMBOPHY_CR1_SSCEN BIT(19)
+
+/* SYSCFG CR4 */
+#define SYSCFG_COMBOPHY_CR4_RX0_EQ GENMASK(2, 0)
+
+#define MPLLMULT_19_2 (0x02u << 1)
+#define MPLLMULT_20 (0x7du << 1)
+#define MPLLMULT_24 (0x68u << 1)
+#define MPLLMULT_25 (0x64u << 1)
+#define MPLLMULT_26 (0x60u << 1)
+#define MPLLMULT_38_4 (0x41u << 1)
+#define MPLLMULT_48 (0x6cu << 1)
+#define MPLLMULT_50 (0x32u << 1)
+#define MPLLMULT_52 (0x30u << 1)
+#define MPLLMULT_100 (0x19u << 1)
+
+#define REFCLKSEL_0 0
+#define REFCLKSEL_1 (0x108u << 8)
+
+#define REFCLDIV_0 0
+
+/* SYSCFG CR2 */
+#define SYSCFG_COMBOPHY_CR2_MODESEL GENMASK(1, 0)
+#define SYSCFG_COMBOPHY_CR2_ISO_DIS BIT(15)
+
+#define COMBOPHY_MODESEL_PCIE 0
+#define COMBOPHY_MODESEL_USB 3
+
+/* SYSCFG CR5 */
+#define SYSCFG_COMBOPHY_CR5_COMMON_CLOCKS BIT(12)
+
+#define COMBOPHY_SUP_ANA_MPLL_LOOP_CTL 0xc0
+#define COMBOPHY_PROP_CNTRL GENMASK(7, 4)
+
+/* Required apb/ker clocks first, optional pad last. */
+static const char * const combophy_clks[] = {"apb", "ker", "pad"};
+#define APB_CLK 0
+#define KER_CLK 1
+#define PAD_CLK 2
+
+struct stm32_combophy {
+ struct phy *phy;
+ struct regmap *regmap;
+ struct device *dev;
+ void __iomem *base;
+ struct reset_control *phy_reset;
+ struct clk_bulk_data clks[ARRAY_SIZE(combophy_clks)];
+ int num_clks;
+ bool have_pad_clk;
+ unsigned int type;
+ bool is_init;
+ int irq_wakeup;
+};
+
+struct clk_impedance {
+ u32 microohm;
+ u32 vswing[4];
+};
+
+/*
+ * lookup table to hold the settings needed for a ref clock frequency
+ * impedance, the offset is used to set the IMP_CTL and DE_EMP bit of the
+ * PRG_IMP_CTRL register. Use ordered discrete values in the table
+ */
+static const struct clk_impedance imp_lookup[] = {
+ { 6090000, { 442000, 564000, 684000, 802000 } },
+ { 5662000, { 528000, 621000, 712000, 803000 } },
+ { 5292000, { 491000, 596000, 700000, 802000 } },
+ { 4968000, { 558000, 640000, 722000, 803000 } },
+ { 4684000, { 468000, 581000, 692000, 802000 } },
+ { 4429000, { 554000, 613000, 717000, 803000 } },
+ { 4204000, { 511000, 609000, 706000, 802000 } },
+ { 3999000, { 571000, 648000, 726000, 803000 } }
+};
+#define DEFAULT_IMP_INDEX 3 /* Default impedance is 50 Ohm */
+
+static int stm32_impedance_tune(struct stm32_combophy *combophy)
+{
+ u8 imp_size = ARRAY_SIZE(imp_lookup);
+ u8 vswing_size = ARRAY_SIZE(imp_lookup[0].vswing);
+ u8 imp_of, vswing_of;
+ u32 max_imp = imp_lookup[0].microohm;
+ u32 min_imp = imp_lookup[imp_size - 1].microohm;
+ u32 max_vswing;
+ u32 min_vswing = imp_lookup[0].vswing[0];
+ u32 val;
+
+ if (!of_property_read_u32(combophy->dev->of_node, "st,output-micro-ohms", &val)) {
+ if (val < min_imp || val > max_imp) {
+ dev_err(combophy->dev, "Invalid value %u for output ohm\n", val);
+ return -EINVAL;
+ }
+
+ for (imp_of = 0; imp_of < ARRAY_SIZE(imp_lookup); imp_of++)
+ if (imp_lookup[imp_of].microohm <= val)
+ break;
+
+ if (WARN_ON(imp_of == ARRAY_SIZE(imp_lookup)))
+ return -EINVAL;
+
+ dev_dbg(combophy->dev, "Set %u micro-ohms output impedance\n",
+ imp_lookup[imp_of].microohm);
+
+ regmap_update_bits(combophy->regmap, SYSCFG_PCIEPRGCR,
+ STM32MP25_PCIEPRG_IMPCTRL_OHM,
+ FIELD_PREP(STM32MP25_PCIEPRG_IMPCTRL_OHM, imp_of));
+ } else
+ imp_of = DEFAULT_IMP_INDEX;
+
+ if (!of_property_read_u32(combophy->dev->of_node, "st,output-vswing-microvolt", &val)) {
+ max_vswing = imp_lookup[imp_of].vswing[vswing_size - 1];
+
+ if (val < min_vswing || val > max_vswing) {
+ dev_err(combophy->dev, "Invalid value %u for output vswing\n", val);
+ return -EINVAL;
+ }
+
+ for (vswing_of = 0; vswing_of < ARRAY_SIZE(imp_lookup[imp_of].vswing); vswing_of++)
+ if (imp_lookup[imp_of].vswing[vswing_of] >= val)
+ break;
+
+ if (WARN_ON(vswing_of == ARRAY_SIZE(imp_lookup[imp_of].vswing)))
+ return -EINVAL;
+
+ dev_dbg(combophy->dev, "Set %u microvolt swing\n",
+ imp_lookup[imp_of].vswing[vswing_of]);
+
+ regmap_update_bits(combophy->regmap, SYSCFG_PCIEPRGCR,
+ STM32MP25_PCIEPRG_IMPCTRL_VSWING,
+ FIELD_PREP(STM32MP25_PCIEPRG_IMPCTRL_VSWING, vswing_of));
+ }
+
+ return 0;
+}
+
+static int stm32_combophy_pll_init(struct stm32_combophy *combophy)
+{
+ int ret;
+ u32 refclksel, pllmult, propcntrl, val;
+ u32 clk_rate;
+ struct clk *clk;
+ u32 cr1_val = 0, cr1_mask = 0;
+
+ if (combophy->have_pad_clk)
+ clk = combophy->clks[PAD_CLK].clk;
+ else
+ clk = combophy->clks[KER_CLK].clk;
+
+ clk_rate = clk_get_rate(clk);
+
+ dev_dbg(combophy->dev, "%s pll init rate %d\n",
+ combophy->have_pad_clk ? "External" : "Ker", clk_rate);
+
+ if (combophy->type != PHY_TYPE_PCIE) {
+ cr1_mask |= SYSCFG_COMBOPHY_CR1_REFSSPEN;
+ cr1_val |= SYSCFG_COMBOPHY_CR1_REFSSPEN;
+ }
+
+ if (of_property_present(combophy->dev->of_node, "st,ssc-on")) {
+ dev_dbg(combophy->dev, "Enabling clock with SSC\n");
+ cr1_mask |= SYSCFG_COMBOPHY_CR1_SSCEN;
+ cr1_val |= SYSCFG_COMBOPHY_CR1_SSCEN;
+ }
+
+ switch (clk_rate) {
+ case 100000000:
+ pllmult = MPLLMULT_100;
+ refclksel = REFCLKSEL_0;
+ propcntrl = 0x8u << 4;
+ break;
+ case 19200000:
+ pllmult = MPLLMULT_19_2;
+ refclksel = REFCLKSEL_1;
+ propcntrl = 0x8u << 4;
+ break;
+ case 25000000:
+ pllmult = MPLLMULT_25;
+ refclksel = REFCLKSEL_0;
+ propcntrl = 0xeu << 4;
+ break;
+ case 24000000:
+ pllmult = MPLLMULT_24;
+ refclksel = REFCLKSEL_1;
+ propcntrl = 0xeu << 4;
+ break;
+ case 20000000:
+ pllmult = MPLLMULT_20;
+ refclksel = REFCLKSEL_0;
+ propcntrl = 0xeu << 4;
+ break;
+ default:
+ dev_err(combophy->dev, "Invalid rate 0x%x\n", clk_rate);
+ return -EINVAL;
+ }
+
+ cr1_mask |= SYSCFG_COMBOPHY_CR1_REFCLKDIV2;
+ cr1_val |= REFCLDIV_0;
+
+ cr1_mask |= SYSCFG_COMBOPHY_CR1_REFCLKSEL;
+ cr1_val |= refclksel;
+
+ cr1_mask |= SYSCFG_COMBOPHY_CR1_MPLLMULT;
+ cr1_val |= pllmult;
+
+ /*
+ * vddcombophy is interconnected with vddcore. Isolation bit should be unset
+ * before using the ComboPHY.
+ */
+ regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR2,
+ SYSCFG_COMBOPHY_CR2_ISO_DIS, SYSCFG_COMBOPHY_CR2_ISO_DIS);
+
+ reset_control_assert(combophy->phy_reset);
+
+ if (combophy->type == PHY_TYPE_PCIE) {
+ ret = stm32_impedance_tune(combophy);
+ if (ret)
+ goto out_iso;
+
+ cr1_mask |= SYSCFG_COMBOPHY_CR1_REFUSEPAD;
+ cr1_val |= combophy->have_pad_clk ? SYSCFG_COMBOPHY_CR1_REFUSEPAD : 0;
+ }
+
+ if (!of_property_read_u32(combophy->dev->of_node, "st,rx-equalizer", &val)) {
+ dev_dbg(combophy->dev, "Set RX equalizer %u\n", val);
+ if (val > SYSCFG_COMBOPHY_CR4_RX0_EQ) {
+ dev_err(combophy->dev, "Invalid value %u for rx0 equalizer\n", val);
+ ret = -EINVAL;
+ goto out_iso;
+ }
+
+ regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR4,
+ SYSCFG_COMBOPHY_CR4_RX0_EQ, val);
+ }
+
+ regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR1, cr1_mask, cr1_val);
+
+ /*
+ * Force elasticity buffer to be tuned for the reference clock as
+ * the separated clock model is not supported
+ */
+ regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR5,
+ SYSCFG_COMBOPHY_CR5_COMMON_CLOCKS, SYSCFG_COMBOPHY_CR5_COMMON_CLOCKS);
+
+ reset_control_deassert(combophy->phy_reset);
+
+ ret = regmap_read_poll_timeout(combophy->regmap, SYSCFG_COMBOPHY_SR, val,
+ !(val & STM32MP25_PIPE0_PHYSTATUS),
+ 10, 1000);
+ if (ret) {
+ dev_err(combophy->dev, "timeout, cannot lock PLL\n");
+ if (combophy->type == PHY_TYPE_PCIE && !combophy->have_pad_clk)
+ regmap_update_bits(combophy->regmap, SYSCFG_PCIEPRGCR,
+ STM32MP25_PCIEPRGCR_EN, 0);
+
+ if (combophy->type != PHY_TYPE_PCIE)
+ regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR1,
+ SYSCFG_COMBOPHY_CR1_REFSSPEN, 0);
+
+ goto out;
+ }
+
+
+ if (combophy->type == PHY_TYPE_PCIE) {
+ if (!combophy->have_pad_clk)
+ regmap_update_bits(combophy->regmap, SYSCFG_PCIEPRGCR,
+ STM32MP25_PCIEPRGCR_EN, STM32MP25_PCIEPRGCR_EN);
+
+ val = readl_relaxed(combophy->base + COMBOPHY_SUP_ANA_MPLL_LOOP_CTL);
+ val &= ~COMBOPHY_PROP_CNTRL;
+ val |= propcntrl;
+ writel_relaxed(val, combophy->base + COMBOPHY_SUP_ANA_MPLL_LOOP_CTL);
+ }
+
+ return 0;
+
+out_iso:
+ reset_control_deassert(combophy->phy_reset);
+
+out:
+ regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR2,
+ SYSCFG_COMBOPHY_CR2_ISO_DIS, 0);
+
+ return ret;
+}
+
+static struct phy *stm32_combophy_xlate(struct device *dev,
+ const struct of_phandle_args *args)
+{
+ struct stm32_combophy *combophy = dev_get_drvdata(dev);
+ unsigned int type;
+
+ if (args->args_count != 1) {
+ dev_err(dev, "invalid number of cells in 'phy' property\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ type = args->args[0];
+ if (type != PHY_TYPE_USB3 && type != PHY_TYPE_PCIE) {
+ dev_err(dev, "unsupported device type: %d\n", type);
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (combophy->have_pad_clk && type != PHY_TYPE_PCIE) {
+ dev_err(dev, "Invalid use of clk_pad for USB3 mode\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ combophy->type = type;
+
+ return combophy->phy;
+}
+
+static int stm32_combophy_set_mode(struct stm32_combophy *combophy)
+{
+ int type = combophy->type;
+ u32 val;
+
+ switch (type) {
+ case PHY_TYPE_PCIE:
+ dev_dbg(combophy->dev, "setting PCIe ComboPHY\n");
+ val = COMBOPHY_MODESEL_PCIE;
+ break;
+ case PHY_TYPE_USB3:
+ dev_dbg(combophy->dev, "setting USB3 ComboPHY\n");
+ val = COMBOPHY_MODESEL_USB;
+ break;
+ default:
+ dev_err(combophy->dev, "Invalid PHY mode %d\n", type);
+ return -EINVAL;
+ }
+
+ return regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR2,
+ SYSCFG_COMBOPHY_CR2_MODESEL, val);
+}
+
+static int stm32_combophy_suspend_noirq(struct device *dev)
+{
+ struct stm32_combophy *combophy = dev_get_drvdata(dev);
+
+ /*
+ * Clocks should be turned off since it is not needed for
+ * wakeup capability. In case usb-remote wakeup is not enabled,
+ * combo-phy is already turned off by HCD driver using exit callback
+ */
+ if (combophy->is_init) {
+ clk_bulk_disable_unprepare(combophy->num_clks, combophy->clks);
+
+ /* since wakeup is enabled for ctrl */
+ enable_irq_wake(combophy->irq_wakeup);
+ }
+
+ return 0;
+}
+
+static int stm32_combophy_resume_noirq(struct device *dev)
+{
+ struct stm32_combophy *combophy = dev_get_drvdata(dev);
+ int ret;
+
+ /*
+ * If clocks was turned off by suspend call for wakeup then needs
+ * to be turned back ON in resume. In case usb-remote wakeup is not
+ * enabled, clocks already turned ON by HCD driver using init callback
+ */
+ if (combophy->is_init) {
+ /* since wakeup was enabled for ctrl */
+ disable_irq_wake(combophy->irq_wakeup);
+
+ ret = clk_bulk_prepare_enable(combophy->num_clks, combophy->clks);
+ if (ret) {
+ dev_err(dev, "can't enable clocks (%d)\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int stm32_combophy_exit(struct phy *phy)
+{
+ struct stm32_combophy *combophy = phy_get_drvdata(phy);
+ struct device *dev = combophy->dev;
+
+ combophy->is_init = false;
+
+ if (combophy->type == PHY_TYPE_PCIE && !combophy->have_pad_clk)
+ regmap_update_bits(combophy->regmap, SYSCFG_PCIEPRGCR,
+ STM32MP25_PCIEPRGCR_EN, 0);
+
+ if (combophy->type != PHY_TYPE_PCIE)
+ regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR1,
+ SYSCFG_COMBOPHY_CR1_REFSSPEN, 0);
+
+ regmap_update_bits(combophy->regmap, SYSCFG_COMBOPHY_CR2,
+ SYSCFG_COMBOPHY_CR2_ISO_DIS, 0);
+
+ clk_bulk_disable_unprepare(combophy->num_clks, combophy->clks);
+
+ pm_runtime_put_noidle(dev);
+
+ return 0;
+}
+
+static int stm32_combophy_init(struct phy *phy)
+{
+ struct stm32_combophy *combophy = phy_get_drvdata(phy);
+ struct device *dev = combophy->dev;
+ int ret;
+
+ pm_runtime_get_noresume(dev);
+
+ ret = clk_bulk_prepare_enable(combophy->num_clks, combophy->clks);
+ if (ret) {
+ dev_err(dev, "can't enable clocks (%d)\n", ret);
+ pm_runtime_put_noidle(dev);
+ return ret;
+ }
+
+ ret = stm32_combophy_set_mode(combophy);
+ if (ret) {
+ dev_err(dev, "combophy mode not set\n");
+ clk_bulk_disable_unprepare(combophy->num_clks, combophy->clks);
+ pm_runtime_put_noidle(dev);
+ return ret;
+ }
+
+ ret = stm32_combophy_pll_init(combophy);
+ if (ret) {
+ clk_bulk_disable_unprepare(combophy->num_clks, combophy->clks);
+ pm_runtime_put_noidle(dev);
+ return ret;
+ }
+
+ pm_runtime_disable(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+
+ combophy->is_init = true;
+
+ return ret;
+}
+
+static const struct phy_ops stm32_combophy_phy_data = {
+ .init = stm32_combophy_init,
+ .exit = stm32_combophy_exit,
+ .owner = THIS_MODULE
+};
+
+static irqreturn_t stm32_combophy_irq_wakeup_handler(int irq, void *dev_id)
+{
+ return IRQ_HANDLED;
+}
+
+static int stm32_combophy_get_clocks(struct stm32_combophy *combophy)
+{
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(combophy_clks); i++)
+ combophy->clks[i].id = combophy_clks[i];
+
+ combophy->num_clks = ARRAY_SIZE(combophy_clks) - 1;
+
+ ret = devm_clk_bulk_get(combophy->dev, combophy->num_clks, combophy->clks);
+ if (ret)
+ return ret;
+
+ ret = devm_clk_bulk_get_optional(combophy->dev, 1, combophy->clks + combophy->num_clks);
+ if (ret)
+ return ret;
+
+ if (combophy->clks[combophy->num_clks].clk != NULL) {
+ combophy->have_pad_clk = true;
+ combophy->num_clks++;
+ }
+
+ return 0;
+}
+
+static int stm32_combophy_probe(struct platform_device *pdev)
+{
+ struct stm32_combophy *combophy;
+ struct device *dev = &pdev->dev;
+ struct phy_provider *phy_provider;
+ int ret, irq;
+
+ combophy = devm_kzalloc(dev, sizeof(*combophy), GFP_KERNEL);
+ if (!combophy)
+ return -ENOMEM;
+
+ combophy->dev = dev;
+
+ dev_set_drvdata(dev, combophy);
+
+ combophy->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(combophy->base))
+ return PTR_ERR(combophy->base);
+
+ ret = stm32_combophy_get_clocks(combophy);
+ if (ret)
+ return ret;
+
+ combophy->phy_reset = devm_reset_control_get_exclusive(dev, "phy");
+ if (IS_ERR(combophy->phy_reset))
+ return dev_err_probe(dev, PTR_ERR(combophy->phy_reset),
+ "Failed to get PHY reset\n");
+
+ combophy->regmap = syscon_regmap_lookup_by_compatible("st,stm32mp25-syscfg");
+ if (IS_ERR(combophy->regmap))
+ return dev_err_probe(dev, PTR_ERR(combophy->regmap),
+ "No syscfg specified\n");
+
+ combophy->phy = devm_phy_create(dev, NULL, &stm32_combophy_phy_data);
+ if (IS_ERR(combophy->phy))
+ return dev_err_probe(dev, PTR_ERR(combophy->phy),
+ "failed to create PCIe/USB3 ComboPHY\n");
+
+ if (device_property_read_bool(dev, "wakeup-source")) {
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return dev_err_probe(dev, irq, "failed to get IRQ\n");
+ combophy->irq_wakeup = irq;
+
+ ret = devm_request_threaded_irq(dev, combophy->irq_wakeup, NULL,
+ stm32_combophy_irq_wakeup_handler, IRQF_ONESHOT,
+ NULL, NULL);
+ if (ret)
+ return dev_err_probe(dev, ret, "unable to request wake IRQ %d\n",
+ combophy->irq_wakeup);
+ }
+
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to enable pm runtime\n");
+
+ phy_set_drvdata(combophy->phy, combophy);
+
+ phy_provider = devm_of_phy_provider_register(dev, stm32_combophy_xlate);
+
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct dev_pm_ops stm32_combophy_pm_ops = {
+ NOIRQ_SYSTEM_SLEEP_PM_OPS(stm32_combophy_suspend_noirq,
+ stm32_combophy_resume_noirq)
+};
+
+static const struct of_device_id stm32_combophy_of_match[] = {
+ { .compatible = "st,stm32mp25-combophy", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, stm32_combophy_of_match);
+
+static struct platform_driver stm32_combophy_driver = {
+ .probe = stm32_combophy_probe,
+ .driver = {
+ .name = "stm32-combophy",
+ .of_match_table = stm32_combophy_of_match,
+ .pm = pm_sleep_ptr(&stm32_combophy_pm_ops)
+ }
+};
+
+module_platform_driver(stm32_combophy_driver);
+
+MODULE_AUTHOR("Christian Bruel <christian.bruel@foss.st.com>");
+MODULE_DESCRIPTION("STM32MP25 Combophy USB3/PCIe controller driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/st/phy-stm32-usbphyc.c b/drivers/phy/st/phy-stm32-usbphyc.c
index d5e7e44000b5..b917cd413de7 100644
--- a/drivers/phy/st/phy-stm32-usbphyc.c
+++ b/drivers/phy/st/phy-stm32-usbphyc.c
@@ -574,7 +574,7 @@ static void stm32_usbphyc_switch_setup(struct stm32_usbphyc *usbphyc,
}
static struct phy *stm32_usbphyc_of_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct stm32_usbphyc *usbphyc = dev_get_drvdata(dev);
struct stm32_usbphyc_phy *usbphyc_phy = NULL;
@@ -812,7 +812,7 @@ MODULE_DEVICE_TABLE(of, stm32_usbphyc_of_match);
static struct platform_driver stm32_usbphyc_driver = {
.probe = stm32_usbphyc_probe,
- .remove_new = stm32_usbphyc_remove,
+ .remove = stm32_usbphyc_remove,
.driver = {
.of_match_table = stm32_usbphyc_of_match,
.name = "stm32-usbphyc",
diff --git a/drivers/phy/starfive/Kconfig b/drivers/phy/starfive/Kconfig
index 9508e2143011..d0cdd7cb4a13 100644
--- a/drivers/phy/starfive/Kconfig
+++ b/drivers/phy/starfive/Kconfig
@@ -15,6 +15,16 @@ config PHY_STARFIVE_JH7110_DPHY_RX
system. If M is selected, the module will be called
phy-jh7110-dphy-rx.ko.
+config PHY_STARFIVE_JH7110_DPHY_TX
+ tristate "StarFive JH7110 D-PHY TX Support"
+ depends on HAS_IOMEM
+ select GENERIC_PHY
+ select GENERIC_PHY_MIPI_DPHY
+ help
+ Choose this option if you have a StarFive D-PHY TX in your
+ system. If M is selected, the module will be called
+ phy-jh7110-dphy-tx.ko.
+
config PHY_STARFIVE_JH7110_PCIE
tristate "Starfive JH7110 PCIE 2.0/USB 3.0 PHY support"
depends on HAS_IOMEM
diff --git a/drivers/phy/starfive/Makefile b/drivers/phy/starfive/Makefile
index b391018b7c47..eedc4a6fec15 100644
--- a/drivers/phy/starfive/Makefile
+++ b/drivers/phy/starfive/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_PHY_STARFIVE_JH7110_DPHY_RX) += phy-jh7110-dphy-rx.o
+obj-$(CONFIG_PHY_STARFIVE_JH7110_DPHY_TX) += phy-jh7110-dphy-tx.o
obj-$(CONFIG_PHY_STARFIVE_JH7110_PCIE) += phy-jh7110-pcie.o
obj-$(CONFIG_PHY_STARFIVE_JH7110_USB) += phy-jh7110-usb.o
diff --git a/drivers/phy/starfive/phy-jh7110-dphy-rx.c b/drivers/phy/starfive/phy-jh7110-dphy-rx.c
index 037a9e0263cd..0b039e1f71c5 100644
--- a/drivers/phy/starfive/phy-jh7110-dphy-rx.c
+++ b/drivers/phy/starfive/phy-jh7110-dphy-rx.c
@@ -46,11 +46,6 @@
#define STF_MAP_LANES_NUM 6
-struct regval {
- u32 addr;
- u32 val;
-};
-
struct stf_dphy_info {
/**
* @maps:
diff --git a/drivers/phy/starfive/phy-jh7110-dphy-tx.c b/drivers/phy/starfive/phy-jh7110-dphy-tx.c
new file mode 100644
index 000000000000..c64d1c91b130
--- /dev/null
+++ b/drivers/phy/starfive/phy-jh7110-dphy-tx.c
@@ -0,0 +1,461 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * DPHY TX driver for the StarFive JH7110 SoC
+ *
+ * Copyright (C) 2023 StarFive Technology Co., Ltd.
+ * Author: Keith Zhao <keith.zhao@starfivetech.com>
+ * Author: Shengyang Chen <shengyang.chen@starfivetech.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/phy/phy.h>
+#include <linux/phy/phy-mipi-dphy.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+
+#define STF_DPHY_APBIFSAIF_SYSCFG(x) (x)
+
+#define STF_DPHY_AON_POWER_READY_N_ACTIVE 0
+#define STF_DPHY_AON_POWER_READY_N BIT(0)
+#define STF_DPHY_CFG_L0_SWAP_SEL GENMASK(14, 12)
+#define STF_DPHY_CFG_L1_SWAP_SEL GENMASK(17, 15)
+#define STF_DPHY_CFG_L2_SWAP_SEL GENMASK(20, 18)
+#define STF_DPHY_CFG_L3_SWAP_SEL GENMASK(23, 21)
+#define STF_DPHY_CFG_L4_SWAP_SEL GENMASK(26, 24)
+#define STF_DPHY_RGS_CDTX_PLL_UNLOCK BIT(18)
+#define STF_DPHY_RG_CDTX_L0N_HSTX_RES GENMASK(23, 19)
+#define STF_DPHY_RG_CDTX_L0P_HSTX_RES GENMASK(28, 24)
+
+#define STF_DPHY_RG_CDTX_L1P_HSTX_RES GENMASK(9, 5)
+#define STF_DPHY_RG_CDTX_L2N_HSTX_RES GENMASK(14, 10)
+#define STF_DPHY_RG_CDTX_L2P_HSTX_RES GENMASK(19, 15)
+#define STF_DPHY_RG_CDTX_L3N_HSTX_RES GENMASK(24, 20)
+#define STF_DPHY_RG_CDTX_L3P_HSTX_RES GENMASK(29, 25)
+
+#define STF_DPHY_RG_CDTX_L4N_HSTX_RES GENMASK(4, 0)
+#define STF_DPHY_RG_CDTX_L4P_HSTX_RES GENMASK(9, 5)
+#define STF_DPHY_RG_CDTX_PLL_FBK_FRA GENMASK(23, 0)
+
+#define STF_DPHY_RG_CDTX_PLL_FBK_INT GENMASK(8, 0)
+#define STF_DPHY_RG_CDTX_PLL_FM_EN BIT(9)
+#define STF_DPHY_RG_CDTX_PLL_LDO_STB_X2_EN BIT(10)
+#define STF_DPHY_RG_CDTX_PLL_PRE_DIV GENMASK(12, 11)
+
+#define STF_DPHY_RG_CDTX_PLL_SSC_EN BIT(18)
+
+#define STF_DPHY_RG_CLANE_HS_CLK_POST_TIME GENMASK(7, 0)
+#define STF_DPHY_RG_CLANE_HS_CLK_PRE_TIME GENMASK(15, 8)
+#define STF_DPHY_RG_CLANE_HS_PRE_TIME GENMASK(23, 16)
+#define STF_DPHY_RG_CLANE_HS_TRAIL_TIME GENMASK(31, 24)
+
+#define STF_DPHY_RG_CLANE_HS_ZERO_TIME GENMASK(7, 0)
+#define STF_DPHY_RG_DLANE_HS_PRE_TIME GENMASK(15, 8)
+#define STF_DPHY_RG_DLANE_HS_TRAIL_TIME GENMASK(23, 16)
+#define STF_DPHY_RG_DLANE_HS_ZERO_TIME GENMASK(31, 24)
+
+#define STF_DPHY_RG_EXTD_CYCLE_SEL GENMASK(2, 0)
+#define STF_DPHY_SCFG_C_HS_PRE_ZERO_TIME GENMASK(31, 0)
+
+#define STF_DPHY_SCFG_DSI_TXREADY_ESC_SEL GENMASK(2, 1)
+#define STF_DPHY_SCFG_PPI_C_READY_SEL GENMASK(4, 3)
+
+#define STF_DPHY_REFCLK_IN_SEL GENMASK(28, 26)
+#define STF_DPHY_RESETB BIT(29)
+
+#define STF_DPHY_REFCLK_12M 1
+#define STF_DPHY_BITRATE_ALIGN 10000000
+
+#define STF_MAP_LANES_NUM 5
+
+#define STF_DPHY_LSHIFT_16(x) (FIELD_PREP(GENMASK(23, 16), (x)))
+#define STF_DPHY_LSHIFT_8(x) (FIELD_PREP(GENMASK(15, 8), (x)))
+
+#define STF_DPHY_HW_DELAY_US 200
+#define STF_DPHY_HW_TIMEOUT_US 5000
+
+struct stf_dphy_config {
+ unsigned long bitrate;
+ u32 pll_fbk_int;
+ u32 pll_fbk_fra_val;
+ u32 extd_cycle_sel;
+ u32 dlane_hs_pre_time;
+ u32 dlane_hs_zero_time;
+ u32 dlane_hs_trail_time;
+ u32 clane_hs_pre_time;
+ u32 clane_hs_zero_time;
+ u32 clane_hs_trail_time;
+ u32 clane_hs_clk_pre_time;
+ u32 clane_hs_clk_post_time;
+};
+
+static const struct stf_dphy_config reg_configs[] = {
+ {160000000, 0x6a, 0xaa, 0x3, 0xa, 0x17, 0x11, 0x5, 0x2b, 0xd, 0x7, 0x3d},
+ {170000000, 0x71, 0x55, 0x3, 0xb, 0x18, 0x11, 0x5, 0x2e, 0xd, 0x7, 0x3d},
+ {180000000, 0x78, 0x0, 0x3, 0xb, 0x19, 0x12, 0x6, 0x30, 0xe, 0x7, 0x3e},
+ {190000000, 0x7e, 0xaa, 0x3, 0xc, 0x1a, 0x12, 0x6, 0x33, 0xe, 0x7, 0x3e},
+ {200000000, 0x85, 0x55, 0x3, 0xc, 0x1b, 0x13, 0x7, 0x35, 0xf, 0x7, 0x3f},
+ {320000000, 0x6a, 0xaa, 0x2, 0x8, 0x14, 0xf, 0x5, 0x2b, 0xd, 0x3, 0x23},
+ {330000000, 0x6e, 0x0, 0x2, 0x8, 0x15, 0xf, 0x5, 0x2d, 0xd, 0x3, 0x23},
+ {340000000, 0x71, 0x55, 0x2, 0x9, 0x15, 0xf, 0x5, 0x2e, 0xd, 0x3, 0x23},
+ {350000000, 0x74, 0xaa, 0x2, 0x9, 0x15, 0x10, 0x6, 0x2f, 0xe, 0x3, 0x24},
+ {360000000, 0x78, 0x0, 0x2, 0x9, 0x16, 0x10, 0x6, 0x30, 0xe, 0x3, 0x24},
+ {370000000, 0x7b, 0x55, 0x2, 0x9, 0x17, 0x10, 0x6, 0x32, 0xe, 0x3, 0x24},
+ {380000000, 0x7e, 0xaa, 0x2, 0xa, 0x17, 0x10, 0x6, 0x33, 0xe, 0x3, 0x24},
+ {390000000, 0x82, 0x0, 0x2, 0xa, 0x17, 0x11, 0x6, 0x35, 0xf, 0x3, 0x25},
+ {400000000, 0x85, 0x55, 0x2, 0xa, 0x18, 0x11, 0x7, 0x35, 0xf, 0x3, 0x25},
+ {410000000, 0x88, 0xaa, 0x2, 0xa, 0x19, 0x11, 0x7, 0x37, 0xf, 0x3, 0x25},
+ {420000000, 0x8c, 0x0, 0x2, 0xa, 0x19, 0x12, 0x7, 0x38, 0x10, 0x3, 0x26},
+ {430000000, 0x8f, 0x55, 0x2, 0xb, 0x19, 0x12, 0x7, 0x39, 0x10, 0x3, 0x26},
+ {440000000, 0x92, 0xaa, 0x2, 0xb, 0x1a, 0x12, 0x7, 0x3b, 0x10, 0x3, 0x26},
+ {450000000, 0x96, 0x0, 0x2, 0xb, 0x1b, 0x12, 0x8, 0x3c, 0x10, 0x3, 0x26},
+ {460000000, 0x99, 0x55, 0x2, 0xb, 0x1b, 0x13, 0x8, 0x3d, 0x11, 0x3, 0x27},
+ {470000000, 0x9c, 0xaa, 0x2, 0xc, 0x1b, 0x13, 0x8, 0x3e, 0x11, 0x3, 0x27},
+ {480000000, 0xa0, 0x27, 0x2, 0xc, 0x1c, 0x13, 0x8, 0x40, 0x11, 0x3, 0x27},
+ {490000000, 0xa3, 0x55, 0x2, 0xc, 0x1d, 0x14, 0x8, 0x42, 0x12, 0x3, 0x28},
+ {500000000, 0xa6, 0xaa, 0x2, 0xc, 0x1d, 0x14, 0x9, 0x42, 0x12, 0x3, 0x28},
+ {510000000, 0xaa, 0x0, 0x2, 0xc, 0x1e, 0x14, 0x9, 0x44, 0x12, 0x3, 0x28},
+ {520000000, 0xad, 0x55, 0x2, 0xd, 0x1e, 0x15, 0x9, 0x45, 0x13, 0x3, 0x29},
+ {530000000, 0xb0, 0xaa, 0x2, 0xd, 0x1e, 0x15, 0x9, 0x47, 0x13, 0x3, 0x29},
+ {540000000, 0xb4, 0x0, 0x2, 0xd, 0x1f, 0x15, 0x9, 0x48, 0x13, 0x3, 0x29},
+ {550000000, 0xb7, 0x55, 0x2, 0xd, 0x20, 0x16, 0x9, 0x4a, 0x14, 0x3, 0x2a},
+ {560000000, 0xba, 0xaa, 0x2, 0xe, 0x20, 0x16, 0xa, 0x4a, 0x14, 0x3, 0x2a},
+ {570000000, 0xbe, 0x0, 0x2, 0xe, 0x20, 0x16, 0xa, 0x4c, 0x14, 0x3, 0x2a},
+ {580000000, 0xc1, 0x55, 0x2, 0xe, 0x21, 0x16, 0xa, 0x4d, 0x14, 0x3, 0x2a},
+ {590000000, 0xc4, 0xaa, 0x2, 0xe, 0x22, 0x17, 0xa, 0x4f, 0x15, 0x3, 0x2b},
+ {600000000, 0xc8, 0x0, 0x2, 0xe, 0x23, 0x17, 0xa, 0x50, 0x15, 0x3, 0x2b},
+ {610000000, 0xcb, 0x55, 0x2, 0xf, 0x22, 0x17, 0xb, 0x50, 0x15, 0x3, 0x2b},
+ {620000000, 0xce, 0xaa, 0x2, 0xf, 0x23, 0x18, 0xb, 0x52, 0x16, 0x3, 0x2c},
+ {630000000, 0x69, 0x0, 0x1, 0x7, 0x12, 0xd, 0x5, 0x2a, 0xc, 0x1, 0x15},
+ {640000000, 0x6a, 0xaa, 0x1, 0x7, 0x13, 0xe, 0x5, 0x2b, 0xd, 0x1, 0x16},
+ {650000000, 0x6c, 0x55, 0x1, 0x7, 0x13, 0xe, 0x5, 0x2c, 0xd, 0x1, 0x16},
+ {660000000, 0x6e, 0x0, 0x1, 0x7, 0x13, 0xe, 0x5, 0x2d, 0xd, 0x1, 0x16},
+ {670000000, 0x6f, 0xaa, 0x1, 0x8, 0x13, 0xe, 0x5, 0x2d, 0xd, 0x1, 0x16},
+ {680000000, 0x71, 0x55, 0x1, 0x8, 0x13, 0xe, 0x5, 0x2e, 0xd, 0x1, 0x16},
+ {690000000, 0x73, 0x0, 0x1, 0x8, 0x14, 0xe, 0x6, 0x2e, 0xd, 0x1, 0x16},
+ {700000000, 0x74, 0xaa, 0x1, 0x8, 0x14, 0xf, 0x6, 0x2f, 0xe, 0x1, 0x16},
+ {710000000, 0x76, 0x55, 0x1, 0x8, 0x14, 0xf, 0x6, 0x2f, 0xe, 0x1, 0x17},
+ {720000000, 0x78, 0x0, 0x1, 0x8, 0x15, 0xf, 0x6, 0x30, 0xe, 0x1, 0x17},
+ {730000000, 0x79, 0xaa, 0x1, 0x8, 0x15, 0xf, 0x6, 0x31, 0xe, 0x1, 0x17},
+ {740000000, 0x7b, 0x55, 0x1, 0x8, 0x15, 0xf, 0x6, 0x32, 0xe, 0x1, 0x17},
+ {750000000, 0x7d, 0x0, 0x1, 0x8, 0x16, 0xf, 0x6, 0x32, 0xe, 0x1, 0x17},
+ {760000000, 0x7e, 0xaa, 0x1, 0x9, 0x15, 0xf, 0x6, 0x33, 0xe, 0x1, 0x17},
+ {770000000, 0x80, 0x55, 0x1, 0x9, 0x15, 0x10, 0x6, 0x34, 0xf, 0x1, 0x18},
+ {780000000, 0x82, 0x0, 0x1, 0x9, 0x16, 0x10, 0x6, 0x35, 0xf, 0x1, 0x18,},
+ {790000000, 0x83, 0xaa, 0x1, 0x9, 0x16, 0x10, 0x7, 0x34, 0xf, 0x1, 0x18},
+ {800000000, 0x85, 0x55, 0x1, 0x9, 0x17, 0x10, 0x7, 0x35, 0xf, 0x1, 0x18},
+ {810000000, 0x87, 0x0, 0x1, 0x9, 0x17, 0x10, 0x7, 0x36, 0xf, 0x1, 0x18},
+ {820000000, 0x88, 0xaa, 0x1, 0x9, 0x17, 0x10, 0x7, 0x37, 0xf, 0x1, 0x18},
+ {830000000, 0x8a, 0x55, 0x1, 0x9, 0x18, 0x10, 0x7, 0x37, 0xf, 0x1, 0x18},
+ {840000000, 0x8c, 0x0, 0x1, 0x9, 0x18, 0x11, 0x7, 0x38, 0x10, 0x1, 0x19},
+ {850000000, 0x8d, 0xaa, 0x1, 0xa, 0x17, 0x11, 0x7, 0x39, 0x10, 0x1, 0x19},
+ {860000000, 0x8f, 0x55, 0x1, 0xa, 0x18, 0x11, 0x7, 0x39, 0x10, 0x1, 0x19},
+ {870000000, 0x91, 0x0, 0x1, 0xa, 0x18, 0x11, 0x7, 0x3a, 0x10, 0x1, 0x19},
+ {880000000, 0x92, 0xaa, 0x1, 0xa, 0x18, 0x11, 0x7, 0x3b, 0x10, 0x1, 0x19},
+ {890000000, 0x94, 0x55, 0x1, 0xa, 0x19, 0x11, 0x7, 0x3c, 0x10, 0x1, 0x19},
+ {900000000, 0x96, 0x0, 0x1, 0xa, 0x19, 0x12, 0x8, 0x3c, 0x10, 0x1, 0x19},
+ {910000000, 0x97, 0xaa, 0x1, 0xa, 0x19, 0x12, 0x8, 0x3c, 0x11, 0x1, 0x1a},
+ {920000000, 0x99, 0x55, 0x1, 0xa, 0x1a, 0x12, 0x8, 0x3d, 0x11, 0x1, 0x1a},
+ {930000000, 0x9b, 0x0, 0x1, 0xa, 0x1a, 0x12, 0x8, 0x3e, 0x11, 0x1, 0x1a},
+ {940000000, 0x9c, 0xaa, 0x1, 0xb, 0x1a, 0x12, 0x8, 0x3e, 0x11, 0x1, 0x1a},
+ {950000000, 0x9e, 0x55, 0x1, 0xb, 0x1a, 0x12, 0x8, 0x3f, 0x11, 0x1, 0x1a},
+ {960000000, 0xa0, 0x0, 0x1, 0xb, 0x1a, 0x12, 0x8, 0x40, 0x11, 0x1, 0x1a},
+ {970000000, 0xa1, 0xaa, 0x1, 0xb, 0x1b, 0x13, 0x8, 0x41, 0x12, 0x1, 0x1b},
+ {980000000, 0xa3, 0x55, 0x1, 0xb, 0x1b, 0x13, 0x8, 0x42, 0x12, 0x1, 0x1b},
+ {990000000, 0xa5, 0x0, 0x1, 0xb, 0x1b, 0x13, 0x8, 0x42, 0x12, 0x1, 0x1b},
+ {1000000000, 0xa6, 0xaa, 0x1, 0xb, 0x1c, 0x13, 0x9, 0x42, 0x12, 0x1, 0x1b},
+};
+
+struct stf_dphy_info {
+ /**
+ * @maps:
+ *
+ * Physical lanes and logic lanes mapping table.
+ *
+ * The default order is:
+ * [data lane 0, data lane 1, data lane 2, date lane 3, clk lane]
+ */
+ u8 maps[STF_MAP_LANES_NUM];
+};
+
+struct stf_dphy {
+ struct device *dev;
+ void __iomem *topsys;
+ struct clk *txesc_clk;
+ struct reset_control *sys_rst;
+
+ struct phy_configure_opts_mipi_dphy config;
+
+ struct phy *phy;
+ const struct stf_dphy_info *info;
+};
+
+static u32 stf_dphy_get_config_index(u32 bitrate)
+{
+ u32 i;
+
+ for (i = 0; i < ARRAY_SIZE(reg_configs); i++) {
+ if (reg_configs[i].bitrate == bitrate)
+ return i;
+ }
+
+ return 0;
+}
+
+static void stf_dphy_hw_reset(struct stf_dphy *dphy, int assert)
+{
+ int rc;
+ u32 status = 0;
+
+ writel(FIELD_PREP(STF_DPHY_RESETB, assert),
+ dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(100));
+
+ if (assert) {
+ rc = readl_poll_timeout_atomic(dphy->topsys +
+ STF_DPHY_APBIFSAIF_SYSCFG(8),
+ status,
+ !(FIELD_GET(STF_DPHY_RGS_CDTX_PLL_UNLOCK, status)),
+ STF_DPHY_HW_DELAY_US, STF_DPHY_HW_TIMEOUT_US);
+ if (rc)
+ dev_err(dphy->dev, "MIPI dphy-tx # PLL Locked\n");
+ }
+}
+
+static int stf_dphy_configure(struct phy *phy, union phy_configure_opts *opts)
+{
+ struct stf_dphy *dphy = phy_get_drvdata(phy);
+ const struct stf_dphy_info *info = dphy->info;
+ const struct stf_dphy_config *p = reg_configs;
+ unsigned long alignment = STF_DPHY_BITRATE_ALIGN;
+ u32 bitrate = opts->mipi_dphy.hs_clk_rate;
+ u32 tmp;
+ u32 i;
+
+ if (bitrate % alignment)
+ bitrate += alignment - (bitrate % alignment);
+
+ i = stf_dphy_get_config_index(bitrate);
+
+ tmp = readl(dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(100));
+ tmp &= ~STF_DPHY_REFCLK_IN_SEL;
+ tmp |= FIELD_PREP(STF_DPHY_REFCLK_IN_SEL, STF_DPHY_REFCLK_12M);
+ writel(tmp, dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(100));
+
+ writel(FIELD_PREP(STF_DPHY_RG_CDTX_L0N_HSTX_RES, 0x10) |
+ FIELD_PREP(STF_DPHY_RG_CDTX_L0P_HSTX_RES, 0x10),
+ dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(8));
+
+ writel(FIELD_PREP(STF_DPHY_RG_CDTX_L0N_HSTX_RES, 0x10) |
+ FIELD_PREP(STF_DPHY_RG_CDTX_L2N_HSTX_RES, 0x10) |
+ FIELD_PREP(STF_DPHY_RG_CDTX_L3N_HSTX_RES, 0x10) |
+ FIELD_PREP(STF_DPHY_RG_CDTX_L1P_HSTX_RES, 0x10) |
+ FIELD_PREP(STF_DPHY_RG_CDTX_L2P_HSTX_RES, 0x10) |
+ FIELD_PREP(STF_DPHY_RG_CDTX_L3P_HSTX_RES, 0x10),
+ dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(12));
+
+ writel(FIELD_PREP(STF_DPHY_RG_CDTX_L4N_HSTX_RES, 0x10) |
+ FIELD_PREP(STF_DPHY_RG_CDTX_L4P_HSTX_RES, 0x10),
+ dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(16));
+
+ /* Lane setting */
+ writel(FIELD_PREP(STF_DPHY_AON_POWER_READY_N,
+ STF_DPHY_AON_POWER_READY_N_ACTIVE) |
+ FIELD_PREP(STF_DPHY_CFG_L0_SWAP_SEL, info->maps[0]) |
+ FIELD_PREP(STF_DPHY_CFG_L1_SWAP_SEL, info->maps[1]) |
+ FIELD_PREP(STF_DPHY_CFG_L2_SWAP_SEL, info->maps[2]) |
+ FIELD_PREP(STF_DPHY_CFG_L3_SWAP_SEL, info->maps[3]) |
+ FIELD_PREP(STF_DPHY_CFG_L4_SWAP_SEL, info->maps[4]),
+ dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(0));
+
+ /* PLL setting */
+ writel(FIELD_PREP(STF_DPHY_RG_CDTX_PLL_SSC_EN, 0x0),
+ dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(28));
+
+ writel(FIELD_PREP(STF_DPHY_RG_CDTX_PLL_LDO_STB_X2_EN, 0x1) |
+ FIELD_PREP(STF_DPHY_RG_CDTX_PLL_FM_EN, 0x1) |
+ FIELD_PREP(STF_DPHY_RG_CDTX_PLL_PRE_DIV, 0x0) |
+ FIELD_PREP(STF_DPHY_RG_CDTX_PLL_FBK_INT, p[i].pll_fbk_int),
+ dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(24));
+
+ writel(FIELD_PREP(STF_DPHY_RG_CDTX_PLL_FBK_FRA,
+ STF_DPHY_LSHIFT_16(p[i].pll_fbk_fra_val) |
+ STF_DPHY_LSHIFT_8(p[i].pll_fbk_fra_val) |
+ p[i].pll_fbk_fra_val),
+ dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(20));
+
+ writel(FIELD_PREP(STF_DPHY_RG_EXTD_CYCLE_SEL, p[i].extd_cycle_sel),
+ dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(40));
+
+ writel(FIELD_PREP(STF_DPHY_RG_DLANE_HS_PRE_TIME, p[i].dlane_hs_pre_time) |
+ FIELD_PREP(STF_DPHY_RG_DLANE_HS_ZERO_TIME, p[i].dlane_hs_zero_time) |
+ FIELD_PREP(STF_DPHY_RG_DLANE_HS_TRAIL_TIME, p[i].dlane_hs_trail_time) |
+ FIELD_PREP(STF_DPHY_RG_CLANE_HS_ZERO_TIME, p[i].clane_hs_zero_time),
+ dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(36));
+
+ writel(FIELD_PREP(STF_DPHY_RG_CLANE_HS_PRE_TIME, p[i].clane_hs_pre_time) |
+ FIELD_PREP(STF_DPHY_RG_CLANE_HS_TRAIL_TIME, p[i].clane_hs_trail_time) |
+ FIELD_PREP(STF_DPHY_RG_CLANE_HS_CLK_PRE_TIME, p[i].clane_hs_clk_pre_time) |
+ FIELD_PREP(STF_DPHY_RG_CLANE_HS_CLK_POST_TIME, p[i].clane_hs_clk_post_time),
+ dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(32));
+
+ return 0;
+}
+
+static int stf_dphy_init(struct phy *phy)
+{
+ struct stf_dphy *dphy = phy_get_drvdata(phy);
+ int ret;
+
+ stf_dphy_hw_reset(dphy, 1);
+
+ writel(FIELD_PREP(STF_DPHY_SCFG_PPI_C_READY_SEL, 0) |
+ FIELD_PREP(STF_DPHY_SCFG_DSI_TXREADY_ESC_SEL, 0),
+ dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(48));
+
+ writel(FIELD_PREP(STF_DPHY_SCFG_C_HS_PRE_ZERO_TIME, 0x30),
+ dphy->topsys + STF_DPHY_APBIFSAIF_SYSCFG(44));
+
+ ret = clk_prepare_enable(dphy->txesc_clk);
+ if (ret) {
+ dev_err(dphy->dev, "Failed to prepare/enable txesc_clk\n");
+ return ret;
+ }
+
+ ret = reset_control_deassert(dphy->sys_rst);
+ if (ret) {
+ dev_err(dphy->dev, "Failed to deassert sys_rst\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int stf_dphy_exit(struct phy *phy)
+{
+ struct stf_dphy *dphy = phy_get_drvdata(phy);
+ int ret;
+
+ ret = reset_control_assert(dphy->sys_rst);
+ if (ret) {
+ dev_err(dphy->dev, "Failed to assert sys_rst\n");
+ return ret;
+ }
+
+ clk_disable_unprepare(dphy->txesc_clk);
+
+ stf_dphy_hw_reset(dphy, 0);
+
+ return 0;
+}
+
+static int stf_dphy_power_on(struct phy *phy)
+{
+ struct stf_dphy *dphy = phy_get_drvdata(phy);
+
+ return pm_runtime_resume_and_get(dphy->dev);
+}
+
+static int stf_dphy_validate(struct phy *phy, enum phy_mode mode, int submode,
+ union phy_configure_opts *opts)
+{
+ if (mode != PHY_MODE_MIPI_DPHY)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int stf_dphy_power_off(struct phy *phy)
+{
+ struct stf_dphy *dphy = phy_get_drvdata(phy);
+
+ return pm_runtime_put_sync(dphy->dev);
+}
+
+static const struct phy_ops stf_dphy_ops = {
+ .power_on = stf_dphy_power_on,
+ .power_off = stf_dphy_power_off,
+ .init = stf_dphy_init,
+ .exit = stf_dphy_exit,
+ .configure = stf_dphy_configure,
+ .validate = stf_dphy_validate,
+ .owner = THIS_MODULE,
+};
+
+static int stf_dphy_probe(struct platform_device *pdev)
+{
+ struct phy_provider *phy_provider;
+ struct stf_dphy *dphy;
+
+ dphy = devm_kzalloc(&pdev->dev, sizeof(*dphy), GFP_KERNEL);
+ if (!dphy)
+ return -ENOMEM;
+
+ dphy->info = of_device_get_match_data(&pdev->dev);
+
+ dphy->dev = &pdev->dev;
+ dev_set_drvdata(&pdev->dev, dphy);
+
+ dphy->topsys = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(dphy->topsys))
+ return PTR_ERR(dphy->topsys);
+
+ pm_runtime_enable(&pdev->dev);
+
+ dphy->txesc_clk = devm_clk_get(&pdev->dev, "txesc");
+ if (IS_ERR(dphy->txesc_clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(dphy->txesc_clk),
+ "Failed to get txesc clock\n");
+
+ dphy->sys_rst = devm_reset_control_get_exclusive(&pdev->dev, "sys");
+ if (IS_ERR(dphy->sys_rst))
+ return dev_err_probe(&pdev->dev, PTR_ERR(dphy->sys_rst),
+ "Failed to get sys reset\n");
+
+ dphy->phy = devm_phy_create(&pdev->dev, NULL, &stf_dphy_ops);
+ if (IS_ERR(dphy->phy))
+ return dev_err_probe(&pdev->dev, PTR_ERR(dphy->phy),
+ "Failed to create phy\n");
+
+ phy_set_drvdata(dphy->phy, dphy);
+
+ phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
+ if (IS_ERR(phy_provider))
+ return dev_err_probe(&pdev->dev, PTR_ERR(phy_provider),
+ "Failed to register phy\n");
+
+ return 0;
+}
+
+static const struct stf_dphy_info starfive_dphy_info = {
+ .maps = {0, 1, 2, 3, 4},
+};
+
+static const struct of_device_id stf_dphy_dt_ids[] = {
+ {
+ .compatible = "starfive,jh7110-dphy-tx",
+ .data = &starfive_dphy_info,
+ },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, stf_dphy_dt_ids);
+
+static struct platform_driver stf_dphy_driver = {
+ .driver = {
+ .name = "starfive-dphy-tx",
+ .of_match_table = stf_dphy_dt_ids,
+ },
+ .probe = stf_dphy_probe,
+};
+module_platform_driver(stf_dphy_driver);
+
+MODULE_AUTHOR("Keith Zhao <keith.zhao@starfivetech.com>");
+MODULE_AUTHOR("Shengyang Chen <shengyang.chen@starfivetech.com>");
+MODULE_DESCRIPTION("StarFive JH7110 DPHY TX driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/starfive/phy-jh7110-usb.c b/drivers/phy/starfive/phy-jh7110-usb.c
index 633912f8a05d..cb5454fbe2c8 100644
--- a/drivers/phy/starfive/phy-jh7110-usb.c
+++ b/drivers/phy/starfive/phy-jh7110-usb.c
@@ -10,18 +10,24 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
+#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
+#include <linux/regmap.h>
#include <linux/usb/of.h>
#define USB_125M_CLK_RATE 125000000
#define USB_LS_KEEPALIVE_OFF 0x4
#define USB_LS_KEEPALIVE_ENABLE BIT(4)
+#define USB_PDRSTN_SPLIT BIT(17)
+#define SYSCON_USB_SPLIT_OFFSET 0x18
+
struct jh7110_usb2_phy {
struct phy *phy;
void __iomem *regs;
+ struct regmap *sys_syscon;
struct clk *usb_125m_clk;
struct clk *app_125m;
enum phy_mode mode;
@@ -61,6 +67,10 @@ static int usb2_phy_set_mode(struct phy *_phy,
usb2_set_ls_keepalive(phy, (mode != PHY_MODE_USB_DEVICE));
}
+ /* Connect usb 2.0 phy mode */
+ regmap_update_bits(phy->sys_syscon, SYSCON_USB_SPLIT_OFFSET,
+ USB_PDRSTN_SPLIT, USB_PDRSTN_SPLIT);
+
return 0;
}
@@ -129,6 +139,12 @@ static int jh7110_usb_phy_probe(struct platform_device *pdev)
phy_set_drvdata(phy->phy, phy);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+ phy->sys_syscon =
+ syscon_regmap_lookup_by_compatible("starfive,jh7110-sys-syscon");
+ if (IS_ERR(phy->sys_syscon))
+ return dev_err_probe(dev, PTR_ERR(phy->sys_syscon),
+ "Failed to get sys-syscon\n");
+
return PTR_ERR_OR_ZERO(phy_provider);
}
diff --git a/drivers/phy/tegra/Kconfig b/drivers/phy/tegra/Kconfig
index c591c958f1eb..f30cfb42b210 100644
--- a/drivers/phy/tegra/Kconfig
+++ b/drivers/phy/tegra/Kconfig
@@ -13,7 +13,8 @@ config PHY_TEGRA_XUSB
config PHY_TEGRA194_P2U
tristate "NVIDIA Tegra194 PIPE2UPHY PHY driver"
- depends on ARCH_TEGRA_194_SOC || COMPILE_TEST
+ depends on ARCH_TEGRA_194_SOC || ARCH_TEGRA_234_SOC || COMPILE_TEST
select GENERIC_PHY
help
- Enable this to support the P2U (PIPE to UPHY) that is part of Tegra 19x SOCs.
+ Enable this to support the P2U (PIPE to UPHY) that is part of Tegra 19x
+ and 234 SOCs.
diff --git a/drivers/phy/tegra/xusb-tegra186.c b/drivers/phy/tegra/xusb-tegra186.c
index 0f60d5d1c167..fae6242aa730 100644
--- a/drivers/phy/tegra/xusb-tegra186.c
+++ b/drivers/phy/tegra/xusb-tegra186.c
@@ -928,6 +928,7 @@ static int tegra186_utmi_phy_init(struct phy *phy)
unsigned int index = lane->index;
struct device *dev = padctl->dev;
int err;
+ u32 reg;
port = tegra_xusb_find_usb2_port(padctl, index);
if (!port) {
@@ -935,6 +936,16 @@ static int tegra186_utmi_phy_init(struct phy *phy)
return -ENODEV;
}
+ if (port->mode == USB_DR_MODE_OTG ||
+ port->mode == USB_DR_MODE_PERIPHERAL) {
+ /* reset VBUS&ID OVERRIDE */
+ reg = padctl_readl(padctl, USB2_VBUS_ID);
+ reg &= ~VBUS_OVERRIDE;
+ reg &= ~ID_OVERRIDE(~0);
+ reg |= ID_OVERRIDE_FLOATING;
+ padctl_writel(padctl, reg, USB2_VBUS_ID);
+ }
+
if (port->supply && port->mode == USB_DR_MODE_HOST) {
err = regulator_enable(port->supply);
if (err) {
diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c
index 142ebe0247cc..79d4814d758d 100644
--- a/drivers/phy/tegra/xusb.c
+++ b/drivers/phy/tegra/xusb.c
@@ -22,7 +22,7 @@
#include "xusb.h"
static struct phy *tegra_xusb_pad_of_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct tegra_xusb_pad *pad = dev_get_drvdata(dev);
struct phy *phy = NULL;
@@ -543,7 +543,7 @@ static int tegra_xusb_port_init(struct tegra_xusb_port *port,
device_initialize(&port->dev);
port->dev.type = &tegra_xusb_port_type;
- port->dev.of_node = of_node_get(np);
+ device_set_node(&port->dev, of_fwnode_handle(of_node_get(np)));
port->dev.parent = padctl->dev;
err = dev_set_name(&port->dev, "%s-%u", name, index);
@@ -699,6 +699,8 @@ static int tegra_xusb_setup_usb_role_switch(struct tegra_xusb_port *port)
return -ENOMEM;
lane = tegra_xusb_find_lane(port->padctl, "usb2", port->index);
+ if (IS_ERR(lane))
+ return PTR_ERR(lane);
/*
* Assign phy dev to usb-phy dev. Host/device drivers can use phy
@@ -1325,7 +1327,7 @@ static struct platform_driver tegra_xusb_padctl_driver = {
.pm = &tegra_xusb_padctl_pm_ops,
},
.probe = tegra_xusb_padctl_probe,
- .remove_new = tegra_xusb_padctl_remove,
+ .remove = tegra_xusb_padctl_remove,
};
module_platform_driver(tegra_xusb_padctl_driver);
@@ -1531,6 +1533,19 @@ int tegra_xusb_padctl_get_usb3_companion(struct tegra_xusb_padctl *padctl,
}
EXPORT_SYMBOL_GPL(tegra_xusb_padctl_get_usb3_companion);
+int tegra_xusb_padctl_get_port_number(struct phy *phy)
+{
+ struct tegra_xusb_lane *lane;
+
+ if (!phy)
+ return -ENODEV;
+
+ lane = phy_get_drvdata(phy);
+
+ return lane->index;
+}
+EXPORT_SYMBOL_GPL(tegra_xusb_padctl_get_port_number);
+
MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
MODULE_DESCRIPTION("Tegra XUSB Pad Controller driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/ti/phy-am654-serdes.c b/drivers/phy/ti/phy-am654-serdes.c
index 3f1d43e8b7ad..431b223996e0 100644
--- a/drivers/phy/ti/phy-am654-serdes.c
+++ b/drivers/phy/ti/phy-am654-serdes.c
@@ -7,6 +7,7 @@
*/
#include <dt-bindings/phy/phy.h>
+#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/delay.h>
@@ -30,7 +31,6 @@
#define LANE_R058 0x258
#define LANE_R06c 0x26c
#define LANE_R070 0x270
-#define LANE_R070 0x270
#define LANE_R19C 0x39c
#define COMLANE_R004 0xa04
@@ -495,7 +495,7 @@ static void serdes_am654_release(struct phy *x)
}
static struct phy *serdes_am654_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct serdes_am654 *am654_phy;
struct phy *phy;
@@ -645,7 +645,6 @@ static int serdes_am654_clk_register(struct serdes_am654 *am654_phy,
struct device_node *node = am654_phy->of_node;
struct device *dev = am654_phy->dev;
struct serdes_am654_clk_mux *mux;
- struct device_node *regmap_node;
const char **parent_names;
struct clk_init_data *init;
unsigned int num_parents;
@@ -653,7 +652,6 @@ static int serdes_am654_clk_register(struct serdes_am654 *am654_phy,
const __be32 *addr;
unsigned int reg;
struct clk *clk;
- int ret = 0;
mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
if (!mux)
@@ -661,41 +659,30 @@ static int serdes_am654_clk_register(struct serdes_am654 *am654_phy,
init = &mux->clk_data;
- regmap_node = of_parse_phandle(node, "ti,serdes-clk", 0);
- if (!regmap_node) {
- dev_err(dev, "Fail to get serdes-clk node\n");
- ret = -ENODEV;
- goto out_put_node;
- }
+ struct device_node *regmap_node __free(device_node) =
+ of_parse_phandle(node, "ti,serdes-clk", 0);
+ if (!regmap_node)
+ return dev_err_probe(dev, -ENODEV, "Fail to get serdes-clk node\n");
regmap = syscon_node_to_regmap(regmap_node->parent);
- if (IS_ERR(regmap)) {
- dev_err(dev, "Fail to get Syscon regmap\n");
- ret = PTR_ERR(regmap);
- goto out_put_node;
- }
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "Fail to get Syscon regmap\n");
num_parents = of_clk_get_parent_count(node);
- if (num_parents < 2) {
- dev_err(dev, "SERDES clock must have parents\n");
- ret = -EINVAL;
- goto out_put_node;
- }
+ if (num_parents < 2)
+ return dev_err_probe(dev, -EINVAL, "SERDES clock must have parents\n");
parent_names = devm_kzalloc(dev, (sizeof(char *) * num_parents),
GFP_KERNEL);
- if (!parent_names) {
- ret = -ENOMEM;
- goto out_put_node;
- }
+ if (!parent_names)
+ return -ENOMEM;
of_clk_parent_fill(node, parent_names, num_parents);
addr = of_get_address(regmap_node, 0, NULL, NULL);
- if (!addr) {
- ret = -EINVAL;
- goto out_put_node;
- }
+ if (!addr)
+ return -EINVAL;
reg = be32_to_cpu(*addr);
@@ -711,16 +698,12 @@ static int serdes_am654_clk_register(struct serdes_am654 *am654_phy,
mux->hw.init = init;
clk = devm_clk_register(dev, &mux->hw);
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
- goto out_put_node;
- }
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
am654_phy->clks[clock_num] = clk;
-out_put_node:
- of_node_put(regmap_node);
- return ret;
+ return 0;
}
static const struct of_device_id serdes_am654_id_table[] = {
@@ -854,7 +837,7 @@ static void serdes_am654_remove(struct platform_device *pdev)
static struct platform_driver serdes_am654_driver = {
.probe = serdes_am654_probe,
- .remove_new = serdes_am654_remove,
+ .remove = serdes_am654_remove,
.driver = {
.name = "phy-am654",
.of_match_table = serdes_am654_id_table,
diff --git a/drivers/phy/ti/phy-da8xx-usb.c b/drivers/phy/ti/phy-da8xx-usb.c
index b7a9ef3f4654..1d81a1e6ec6b 100644
--- a/drivers/phy/ti/phy-da8xx-usb.c
+++ b/drivers/phy/ti/phy-da8xx-usb.c
@@ -14,11 +14,13 @@
#include <linux/phy/phy.h>
#include <linux/platform_data/phy-da8xx-usb.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#define PHY_INIT_BITS (CFGCHIP2_SESENDEN | CFGCHIP2_VBDTCTEN)
struct da8xx_usb_phy {
+ struct device *dev;
struct phy_provider *phy_provider;
struct phy *usb11_phy;
struct phy *usb20_phy;
@@ -39,6 +41,12 @@ static int da8xx_usb11_phy_power_on(struct phy *phy)
regmap_write_bits(d_phy->regmap, CFGCHIP(2), CFGCHIP2_USB1SUSPENDM,
CFGCHIP2_USB1SUSPENDM);
+ /*
+ * USB1.1 can used USB2.0 output clock as reference clock so this is here to prevent USB2.0
+ * from shutting PHY's power when USB1.1 might use it
+ */
+ pm_runtime_get_sync(d_phy->dev);
+
return 0;
}
@@ -49,6 +57,7 @@ static int da8xx_usb11_phy_power_off(struct phy *phy)
regmap_write_bits(d_phy->regmap, CFGCHIP(2), CFGCHIP2_USB1SUSPENDM, 0);
clk_disable_unprepare(d_phy->usb11_clk);
+ pm_runtime_put_sync(d_phy->dev);
return 0;
}
@@ -118,8 +127,37 @@ static const struct phy_ops da8xx_usb20_phy_ops = {
.owner = THIS_MODULE,
};
+static int __maybe_unused da8xx_runtime_suspend(struct device *dev)
+{
+ struct da8xx_usb_phy *d_phy = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "Suspending ...\n");
+
+ regmap_set_bits(d_phy->regmap, CFGCHIP(2), CFGCHIP2_PHYPWRDN | CFGCHIP2_OTGPWRDN);
+
+ return 0;
+}
+
+static int __maybe_unused da8xx_runtime_resume(struct device *dev)
+{
+ u32 mask = CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN | CFGCHIP2_OTGPWRDN | CFGCHIP2_PHY_PLLON;
+ struct da8xx_usb_phy *d_phy = dev_get_drvdata(dev);
+ u32 pll_status;
+
+ regmap_update_bits(d_phy->regmap, CFGCHIP(2), mask, CFGCHIP2_PHY_PLLON);
+
+ dev_dbg(dev, "Resuming ...\n");
+
+ return regmap_read_poll_timeout(d_phy->regmap, CFGCHIP(2), pll_status,
+ pll_status & CFGCHIP2_PHYCLKGD, 1000, 500000);
+}
+
+static const struct dev_pm_ops da8xx_usb_phy_pm_ops = {
+ SET_RUNTIME_PM_OPS(da8xx_runtime_suspend, da8xx_runtime_resume, NULL)
+};
+
static struct phy *da8xx_usb_phy_of_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct da8xx_usb_phy *d_phy = dev_get_drvdata(dev);
@@ -147,6 +185,8 @@ static int da8xx_usb_phy_probe(struct platform_device *pdev)
if (!d_phy)
return -ENOMEM;
+ d_phy->dev = dev;
+
if (pdata)
d_phy->regmap = pdata->cfgchip;
else
@@ -208,6 +248,14 @@ static int da8xx_usb_phy_probe(struct platform_device *pdev)
regmap_write_bits(d_phy->regmap, CFGCHIP(2),
PHY_INIT_BITS, PHY_INIT_BITS);
+ pm_runtime_set_active(dev);
+ devm_pm_runtime_enable(dev);
+ /*
+ * Prevent runtime pm from being ON by default. Users can enable
+ * it using power/control in sysfs.
+ */
+ pm_runtime_forbid(dev);
+
return 0;
}
@@ -229,10 +277,11 @@ MODULE_DEVICE_TABLE(of, da8xx_usb_phy_ids);
static struct platform_driver da8xx_usb_phy_driver = {
.probe = da8xx_usb_phy_probe,
- .remove_new = da8xx_usb_phy_remove,
+ .remove = da8xx_usb_phy_remove,
.driver = {
.name = "da8xx-usb-phy",
- .of_match_table = da8xx_usb_phy_ids,
+ .pm = &da8xx_usb_phy_pm_ops,
+ .of_match_table = da8xx_usb_phy_ids,
},
};
diff --git a/drivers/phy/ti/phy-dm816x-usb.c b/drivers/phy/ti/phy-dm816x-usb.c
index d5ae972a31fb..e8f842d4e841 100644
--- a/drivers/phy/ti/phy-dm816x-usb.c
+++ b/drivers/phy/ti/phy-dm816x-usb.c
@@ -259,7 +259,7 @@ static void dm816x_usb_phy_remove(struct platform_device *pdev)
static struct platform_driver dm816x_usb_phy_driver = {
.probe = dm816x_usb_phy_probe,
- .remove_new = dm816x_usb_phy_remove,
+ .remove = dm816x_usb_phy_remove,
.driver = {
.name = "dm816x-usb-phy",
.pm = &dm816x_usb_phy_pm_ops,
diff --git a/drivers/phy/ti/phy-gmii-sel.c b/drivers/phy/ti/phy-gmii-sel.c
index 0f4818adb440..ff5d5e29629f 100644
--- a/drivers/phy/ti/phy-gmii-sel.c
+++ b/drivers/phy/ti/phy-gmii-sel.c
@@ -230,7 +230,8 @@ static const
struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw5g_soc_j7200 = {
.use_of_data = true,
.regfields = phy_gmii_sel_fields_am654,
- .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII),
+ .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII) |
+ BIT(PHY_INTERFACE_MODE_USXGMII),
.num_ports = 4,
.num_qsgmii_main_ports = 1,
};
@@ -297,7 +298,7 @@ static const struct phy_ops phy_gmii_sel_ops = {
};
static struct phy *phy_gmii_sel_of_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct phy_gmii_sel_priv *priv = dev_get_drvdata(dev);
int phy_id = args->args[0];
@@ -423,6 +424,12 @@ static int phy_gmii_sel_init_ports(struct phy_gmii_sel_priv *priv)
return 0;
}
+static const struct regmap_config phy_gmii_sel_regmap_cfg = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
static int phy_gmii_sel_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -467,12 +474,17 @@ static int phy_gmii_sel_probe(struct platform_device *pdev)
priv->regmap = syscon_node_to_regmap(node->parent);
if (IS_ERR(priv->regmap)) {
- priv->regmap = device_node_to_regmap(node);
- if (IS_ERR(priv->regmap)) {
- ret = PTR_ERR(priv->regmap);
- dev_err(dev, "Failed to get syscon %d\n", ret);
- return ret;
- }
+ void __iomem *base;
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return dev_err_probe(dev, PTR_ERR(base),
+ "failed to get base memory resource\n");
+
+ priv->regmap = regmap_init_mmio(dev, base, &phy_gmii_sel_regmap_cfg);
+ if (IS_ERR(priv->regmap))
+ return dev_err_probe(dev, PTR_ERR(priv->regmap),
+ "Failed to get syscon\n");
priv->no_offset = true;
}
@@ -485,20 +497,42 @@ static int phy_gmii_sel_probe(struct platform_device *pdev)
priv->phy_provider =
devm_of_phy_provider_register(dev,
phy_gmii_sel_of_xlate);
- if (IS_ERR(priv->phy_provider)) {
- ret = PTR_ERR(priv->phy_provider);
- dev_err(dev, "Failed to create phy provider %d\n", ret);
- return ret;
+ if (IS_ERR(priv->phy_provider))
+ return dev_err_probe(dev, PTR_ERR(priv->phy_provider),
+ "Failed to create phy provider\n");
+
+ return 0;
+}
+
+static int phy_gmii_sel_resume_noirq(struct device *dev)
+{
+ struct phy_gmii_sel_priv *priv = dev_get_drvdata(dev);
+ struct phy_gmii_sel_phy_priv *if_phys = priv->if_phys;
+ int ret, i;
+
+ for (i = 0; i < priv->num_ports; i++) {
+ if (if_phys[i].phy_if_mode) {
+ ret = phy_gmii_sel_mode(if_phys[i].if_phy,
+ PHY_MODE_ETHERNET, if_phys[i].phy_if_mode);
+ if (ret) {
+ dev_err(dev, "port%u: restore mode fail %d\n",
+ if_phys[i].if_phy->id, ret);
+ return ret;
+ }
+ }
}
return 0;
}
+static DEFINE_NOIRQ_DEV_PM_OPS(phy_gmii_sel_pm_ops, NULL, phy_gmii_sel_resume_noirq);
+
static struct platform_driver phy_gmii_sel_driver = {
.probe = phy_gmii_sel_probe,
.driver = {
.name = "phy-gmii-sel",
.of_match_table = phy_gmii_sel_id_table,
+ .pm = pm_sleep_ptr(&phy_gmii_sel_pm_ops),
},
};
module_platform_driver(phy_gmii_sel_driver);
diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c
index 00d7e6a6de03..ab2a4f2c0a5b 100644
--- a/drivers/phy/ti/phy-j721e-wiz.c
+++ b/drivers/phy/ti/phy-j721e-wiz.c
@@ -450,8 +450,8 @@ static int wiz_mode_select(struct wiz *wiz)
} else if (wiz->lane_phy_type[i] == PHY_TYPE_USXGMII) {
ret = regmap_field_write(wiz->p0_mac_src_sel[i], 0x3);
ret = regmap_field_write(wiz->p0_rxfclk_sel[i], 0x3);
- ret = regmap_field_write(wiz->p0_refclk_sel[i], 0x3);
- mode = LANE_MODE_GEN1;
+ ret = regmap_field_write(wiz->p0_refclk_sel[i], 0x2);
+ mode = LANE_MODE_GEN2;
} else {
continue;
}
@@ -1076,27 +1076,12 @@ static int wiz_clock_register(struct wiz *wiz)
return ret;
}
-static int wiz_clock_init(struct wiz *wiz, struct device_node *node)
+static void wiz_clock_init(struct wiz *wiz)
{
- const struct wiz_clk_mux_sel *clk_mux_sel = wiz->clk_mux_sel;
- struct device *dev = wiz->dev;
- struct device_node *clk_node;
- const char *node_name;
unsigned long rate;
- struct clk *clk;
- int ret;
- int i;
-
- clk = devm_clk_get(dev, "core_ref_clk");
- if (IS_ERR(clk)) {
- dev_err(dev, "core_ref_clk clock not found\n");
- ret = PTR_ERR(clk);
- return ret;
- }
- wiz->input_clks[WIZ_CORE_REFCLK] = clk;
- rate = clk_get_rate(clk);
- if (rate >= 100000000)
+ rate = clk_get_rate(wiz->input_clks[WIZ_CORE_REFCLK]);
+ if (rate >= REF_CLK_100MHZ)
regmap_field_write(wiz->pma_cmn_refclk_int_mode, 0x1);
else
regmap_field_write(wiz->pma_cmn_refclk_int_mode, 0x3);
@@ -1120,35 +1105,55 @@ static int wiz_clock_init(struct wiz *wiz, struct device_node *node)
break;
}
- if (wiz->data->pma_cmn_refclk1_int_mode) {
- clk = devm_clk_get(dev, "core_ref1_clk");
- if (IS_ERR(clk)) {
- dev_err(dev, "core_ref1_clk clock not found\n");
- ret = PTR_ERR(clk);
- return ret;
- }
- wiz->input_clks[WIZ_CORE_REFCLK1] = clk;
-
- rate = clk_get_rate(clk);
- if (rate >= 100000000)
+ if (wiz->input_clks[WIZ_CORE_REFCLK1]) {
+ rate = clk_get_rate(wiz->input_clks[WIZ_CORE_REFCLK1]);
+ if (rate >= REF_CLK_100MHZ)
regmap_field_write(wiz->pma_cmn_refclk1_int_mode, 0x1);
else
regmap_field_write(wiz->pma_cmn_refclk1_int_mode, 0x3);
}
- clk = devm_clk_get(dev, "ext_ref_clk");
- if (IS_ERR(clk)) {
- dev_err(dev, "ext_ref_clk clock not found\n");
- ret = PTR_ERR(clk);
- return ret;
- }
- wiz->input_clks[WIZ_EXT_REFCLK] = clk;
-
- rate = clk_get_rate(clk);
- if (rate >= 100000000)
+ rate = clk_get_rate(wiz->input_clks[WIZ_EXT_REFCLK]);
+ if (rate >= REF_CLK_100MHZ)
regmap_field_write(wiz->pma_cmn_refclk_mode, 0x0);
else
regmap_field_write(wiz->pma_cmn_refclk_mode, 0x2);
+}
+
+static int wiz_clock_probe(struct wiz *wiz, struct device_node *node)
+{
+ const struct wiz_clk_mux_sel *clk_mux_sel = wiz->clk_mux_sel;
+ struct device *dev = wiz->dev;
+ struct device_node *clk_node;
+ const char *node_name;
+ struct clk *clk;
+ int ret;
+ int i;
+
+ clk = devm_clk_get(dev, "core_ref_clk");
+ if (IS_ERR(clk))
+ return dev_err_probe(dev, PTR_ERR(clk),
+ "core_ref_clk clock not found\n");
+
+ wiz->input_clks[WIZ_CORE_REFCLK] = clk;
+
+ if (wiz->data->pma_cmn_refclk1_int_mode) {
+ clk = devm_clk_get(dev, "core_ref1_clk");
+ if (IS_ERR(clk))
+ return dev_err_probe(dev, PTR_ERR(clk),
+ "core_ref1_clk clock not found\n");
+
+ wiz->input_clks[WIZ_CORE_REFCLK1] = clk;
+ }
+
+ clk = devm_clk_get(dev, "ext_ref_clk");
+ if (IS_ERR(clk))
+ return dev_err_probe(dev, PTR_ERR(clk),
+ "ext_ref_clk clock not found\n");
+
+ wiz->input_clks[WIZ_EXT_REFCLK] = clk;
+
+ wiz_clock_init(wiz);
switch (wiz->type) {
case AM64_WIZ_10G:
@@ -1157,8 +1162,9 @@ static int wiz_clock_init(struct wiz *wiz, struct device_node *node)
case J721S2_WIZ_10G:
ret = wiz_clock_register(wiz);
if (ret)
- dev_err(dev, "Failed to register wiz clocks\n");
- return ret;
+ return dev_err_probe(dev, ret, "Failed to register wiz clocks\n");
+
+ return 0;
default:
break;
}
@@ -1167,42 +1173,37 @@ static int wiz_clock_init(struct wiz *wiz, struct device_node *node)
node_name = clk_mux_sel[i].node_name;
clk_node = of_get_child_by_name(node, node_name);
if (!clk_node) {
- dev_err(dev, "Unable to get %s node\n", node_name);
- ret = -EINVAL;
+ ret = dev_err_probe(dev, -EINVAL, "Unable to get %s node\n", node_name);
goto err;
}
ret = wiz_mux_of_clk_register(wiz, clk_node, wiz->mux_sel_field[i],
clk_mux_sel[i].table);
+ of_node_put(clk_node);
if (ret) {
- dev_err(dev, "Failed to register %s clock\n",
- node_name);
- of_node_put(clk_node);
+ dev_err_probe(dev, ret, "Failed to register %s clock\n",
+ node_name);
goto err;
}
- of_node_put(clk_node);
}
for (i = 0; i < wiz->clk_div_sel_num; i++) {
node_name = clk_div_sel[i].node_name;
clk_node = of_get_child_by_name(node, node_name);
if (!clk_node) {
- dev_err(dev, "Unable to get %s node\n", node_name);
- ret = -EINVAL;
+ ret = dev_err_probe(dev, -EINVAL, "Unable to get %s node\n", node_name);
goto err;
}
ret = wiz_div_clk_register(wiz, clk_node, wiz->div_sel_field[i],
clk_div_sel[i].table);
+ of_node_put(clk_node);
if (ret) {
- dev_err(dev, "Failed to register %s clock\n",
- node_name);
- of_node_put(clk_node);
+ dev_err_probe(dev, ret, "Failed to register %s clock\n",
+ node_name);
goto err;
}
-
- of_node_put(clk_node);
}
return 0;
@@ -1403,7 +1404,7 @@ MODULE_DEVICE_TABLE(of, wiz_id_table);
static int wiz_get_lane_phy_types(struct device *dev, struct wiz *wiz)
{
- struct device_node *serdes, *subnode;
+ struct device_node *serdes;
serdes = of_get_child_by_name(dev->of_node, "serdes");
if (!serdes) {
@@ -1411,7 +1412,7 @@ static int wiz_get_lane_phy_types(struct device *dev, struct wiz *wiz)
return -EINVAL;
}
- for_each_child_of_node(serdes, subnode) {
+ for_each_child_of_node_scoped(serdes, subnode) {
u32 reg, num_lanes = 1, phy_type = PHY_NONE;
int ret, i;
@@ -1421,7 +1422,6 @@ static int wiz_get_lane_phy_types(struct device *dev, struct wiz *wiz)
ret = of_property_read_u32(subnode, "reg", &reg);
if (ret) {
- of_node_put(subnode);
dev_err(dev,
"%s: Reading \"reg\" from \"%s\" failed: %d\n",
__func__, subnode->name, ret);
@@ -1574,8 +1574,8 @@ static int wiz_probe(struct platform_device *pdev)
phy_reset_dev = &wiz->wiz_phy_reset_dev;
phy_reset_dev->dev = dev;
- phy_reset_dev->ops = &wiz_phy_reset_ops,
- phy_reset_dev->owner = THIS_MODULE,
+ phy_reset_dev->ops = &wiz_phy_reset_ops;
+ phy_reset_dev->owner = THIS_MODULE;
phy_reset_dev->of_node = node;
/* Reset for each of the lane and one for the entire SERDES */
phy_reset_dev->nr_resets = num_lanes + 1;
@@ -1593,7 +1593,7 @@ static int wiz_probe(struct platform_device *pdev)
goto err_get_sync;
}
- ret = wiz_clock_init(wiz, node);
+ ret = wiz_clock_probe(wiz, node);
if (ret < 0) {
dev_warn(dev, "Failed to initialize clocks\n");
goto err_get_sync;
@@ -1655,12 +1655,41 @@ static void wiz_remove(struct platform_device *pdev)
pm_runtime_disable(dev);
}
+static int wiz_resume_noirq(struct device *dev)
+{
+ struct device_node *node = dev->of_node;
+ struct wiz *wiz = dev_get_drvdata(dev);
+ int ret;
+
+ /* Enable supplemental Control override if available */
+ if (wiz->sup_legacy_clk_override)
+ regmap_field_write(wiz->sup_legacy_clk_override, 1);
+
+ wiz_clock_init(wiz);
+
+ ret = wiz_init(wiz);
+ if (ret) {
+ dev_err(dev, "WIZ initialization failed\n");
+ goto err_wiz_init;
+ }
+
+ return 0;
+
+err_wiz_init:
+ wiz_clock_cleanup(wiz, node);
+
+ return ret;
+}
+
+static DEFINE_NOIRQ_DEV_PM_OPS(wiz_pm_ops, NULL, wiz_resume_noirq);
+
static struct platform_driver wiz_driver = {
.probe = wiz_probe,
- .remove_new = wiz_remove,
+ .remove = wiz_remove,
.driver = {
.name = "wiz",
.of_match_table = wiz_id_table,
+ .pm = pm_sleep_ptr(&wiz_pm_ops),
},
};
module_platform_driver(wiz_driver);
diff --git a/drivers/phy/ti/phy-omap-usb2.c b/drivers/phy/ti/phy-omap-usb2.c
index 78e19b128962..c1a0ef979142 100644
--- a/drivers/phy/ti/phy-omap-usb2.c
+++ b/drivers/phy/ti/phy-omap-usb2.c
@@ -511,7 +511,7 @@ static void omap_usb2_remove(struct platform_device *pdev)
static struct platform_driver omap_usb2_driver = {
.probe = omap_usb2_probe,
- .remove_new = omap_usb2_remove,
+ .remove = omap_usb2_remove,
.driver = {
.name = "omap-usb2",
.of_match_table = omap_usb2_id_table,
diff --git a/drivers/phy/ti/phy-ti-pipe3.c b/drivers/phy/ti/phy-ti-pipe3.c
index 874c1a25ce36..da2cbacb982c 100644
--- a/drivers/phy/ti/phy-ti-pipe3.c
+++ b/drivers/phy/ti/phy-ti-pipe3.c
@@ -920,7 +920,7 @@ MODULE_DEVICE_TABLE(of, ti_pipe3_id_table);
static struct platform_driver ti_pipe3_driver = {
.probe = ti_pipe3_probe,
- .remove_new = ti_pipe3_remove,
+ .remove = ti_pipe3_remove,
.driver = {
.name = "ti-pipe3",
.of_match_table = ti_pipe3_id_table,
diff --git a/drivers/phy/ti/phy-tusb1210.c b/drivers/phy/ti/phy-tusb1210.c
index b4881cb34475..c3ae9d7948d7 100644
--- a/drivers/phy/ti/phy-tusb1210.c
+++ b/drivers/phy/ti/phy-tusb1210.c
@@ -17,6 +17,10 @@
#include <linux/property.h>
#include <linux/workqueue.h>
+#define TI_VENDOR_ID 0x0451
+#define TI_DEVICE_TUSB1210 0x1507
+#define TI_DEVICE_TUSB1211 0x1508
+
#define TUSB1211_POWER_CONTROL 0x3d
#define TUSB1211_POWER_CONTROL_SET 0x3e
#define TUSB1211_POWER_CONTROL_CLEAR 0x3f
@@ -52,7 +56,7 @@ enum tusb1210_chg_det_state {
};
struct tusb1210 {
- struct ulpi *ulpi;
+ struct device *dev;
struct phy *phy;
struct gpio_desc *gpio_reset;
struct gpio_desc *gpio_cs;
@@ -65,32 +69,32 @@ struct tusb1210 {
struct delayed_work chg_det_work;
struct notifier_block psy_nb;
struct power_supply *psy;
- struct power_supply *charger;
#endif
};
static int tusb1210_ulpi_write(struct tusb1210 *tusb, u8 reg, u8 val)
{
+ struct device *dev = tusb->dev;
int ret;
- ret = ulpi_write(tusb->ulpi, reg, val);
+ ret = ulpi_write(to_ulpi_dev(dev), reg, val);
if (ret)
- dev_err(&tusb->ulpi->dev, "error %d writing val 0x%02x to reg 0x%02x\n",
- ret, val, reg);
+ dev_err(dev, "error %d writing val 0x%02x to reg 0x%02x\n", ret, val, reg);
return ret;
}
static int tusb1210_ulpi_read(struct tusb1210 *tusb, u8 reg, u8 *val)
{
+ struct device *dev = tusb->dev;
int ret;
- ret = ulpi_read(tusb->ulpi, reg);
+ ret = ulpi_read(to_ulpi_dev(dev), reg);
if (ret >= 0) {
*val = ret;
ret = 0;
} else {
- dev_err(&tusb->ulpi->dev, "error %d reading reg 0x%02x\n", ret, reg);
+ dev_err(dev, "error %d reading reg 0x%02x\n", ret, reg);
}
return ret;
@@ -178,7 +182,7 @@ static void tusb1210_reset(struct tusb1210 *tusb)
static void tusb1210_chg_det_set_type(struct tusb1210 *tusb,
enum power_supply_usb_type type)
{
- dev_dbg(&tusb->ulpi->dev, "charger type: %d\n", type);
+ dev_dbg(tusb->dev, "charger type: %d\n", type);
tusb->chg_type = type;
tusb->chg_det_retries = 0;
power_supply_changed(tusb->psy);
@@ -189,7 +193,7 @@ static void tusb1210_chg_det_set_state(struct tusb1210 *tusb,
int delay_ms)
{
if (delay_ms)
- dev_dbg(&tusb->ulpi->dev, "chg_det new state %s in %d ms\n",
+ dev_dbg(tusb->dev, "chg_det new state %s in %d ms\n",
tusb1210_chg_det_states[new_state], delay_ms);
tusb->chg_det_state = new_state;
@@ -231,19 +235,24 @@ static const char * const tusb1210_chargers[] = {
static bool tusb1210_get_online(struct tusb1210 *tusb)
{
+ struct power_supply *charger = NULL;
union power_supply_propval val;
- int i;
+ bool online = false;
+ int i, ret;
- for (i = 0; i < ARRAY_SIZE(tusb1210_chargers) && !tusb->charger; i++)
- tusb->charger = power_supply_get_by_name(tusb1210_chargers[i]);
+ for (i = 0; i < ARRAY_SIZE(tusb1210_chargers) && !charger; i++)
+ charger = power_supply_get_by_name(tusb1210_chargers[i]);
- if (!tusb->charger)
+ if (!charger)
return false;
- if (power_supply_get_property(tusb->charger, POWER_SUPPLY_PROP_ONLINE, &val))
- return false;
+ ret = power_supply_get_property(charger, POWER_SUPPLY_PROP_ONLINE, &val);
+ if (ret == 0)
+ online = val.intval;
- return val.intval;
+ power_supply_put(charger);
+
+ return online;
}
static void tusb1210_chg_det_work(struct work_struct *work)
@@ -253,7 +262,7 @@ static void tusb1210_chg_det_work(struct work_struct *work)
int ret;
u8 val;
- dev_dbg(&tusb->ulpi->dev, "chg_det state %s vbus_present %d\n",
+ dev_dbg(tusb->dev, "chg_det state %s vbus_present %d\n",
tusb1210_chg_det_states[tusb->chg_det_state], vbus_present);
switch (tusb->chg_det_state) {
@@ -261,9 +270,9 @@ static void tusb1210_chg_det_work(struct work_struct *work)
tusb->chg_type = POWER_SUPPLY_USB_TYPE_UNKNOWN;
tusb->chg_det_retries = 0;
/* Power on USB controller for ulpi_read()/_write() */
- ret = pm_runtime_resume_and_get(tusb->ulpi->dev.parent);
+ ret = pm_runtime_resume_and_get(tusb->dev->parent);
if (ret < 0) {
- dev_err(&tusb->ulpi->dev, "error %d runtime-resuming\n", ret);
+ dev_err(tusb->dev, "error %d runtime-resuming\n", ret);
/* Should never happen, skip charger detection */
tusb1210_chg_det_set_state(tusb, TUSB1210_CHG_DET_CONNECTED, 0);
return;
@@ -332,7 +341,7 @@ static void tusb1210_chg_det_work(struct work_struct *work)
mutex_unlock(&tusb->phy->mutex);
- pm_runtime_put(tusb->ulpi->dev.parent);
+ pm_runtime_put(tusb->dev->parent);
tusb1210_chg_det_set_state(tusb, TUSB1210_CHG_DET_CONNECTED, 0);
break;
case TUSB1210_CHG_DET_CONNECTED:
@@ -402,12 +411,6 @@ static int tusb1210_psy_get_prop(struct power_supply *psy,
return 0;
}
-static const enum power_supply_usb_type tusb1210_psy_usb_types[] = {
- POWER_SUPPLY_USB_TYPE_SDP,
- POWER_SUPPLY_USB_TYPE_DCP,
- POWER_SUPPLY_USB_TYPE_UNKNOWN,
-};
-
static const enum power_supply_property tusb1210_psy_props[] = {
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_USB_TYPE,
@@ -417,8 +420,9 @@ static const enum power_supply_property tusb1210_psy_props[] = {
static const struct power_supply_desc tusb1210_psy_desc = {
.name = "tusb1211-charger-detect",
.type = POWER_SUPPLY_TYPE_USB,
- .usb_types = tusb1210_psy_usb_types,
- .num_usb_types = ARRAY_SIZE(tusb1210_psy_usb_types),
+ .usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_DCP) |
+ BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
.properties = tusb1210_psy_props,
.num_properties = ARRAY_SIZE(tusb1210_psy_props),
.get_property = tusb1210_psy_get_prop,
@@ -428,13 +432,14 @@ static const struct power_supply_desc tusb1210_psy_desc = {
static void tusb1210_probe_charger_detect(struct tusb1210 *tusb)
{
struct power_supply_config psy_cfg = { .drv_data = tusb };
- struct device *dev = &tusb->ulpi->dev;
+ struct device *dev = tusb->dev;
+ struct ulpi *ulpi = to_ulpi_dev(dev);
int ret;
if (!device_property_read_bool(dev->parent, "linux,phy_charger_detect"))
return;
- if (tusb->ulpi->id.product != 0x1508) {
+ if (ulpi->id.product != TI_DEVICE_TUSB1211) {
dev_err(dev, "error charger detection is only supported on the TUSB1211\n");
return;
}
@@ -467,9 +472,6 @@ static void tusb1210_remove_charger_detect(struct tusb1210 *tusb)
cancel_delayed_work_sync(&tusb->chg_det_work);
power_supply_unregister(tusb->psy);
}
-
- if (tusb->charger)
- power_supply_put(tusb->charger);
}
#else
static void tusb1210_probe_charger_detect(struct tusb1210 *tusb) { }
@@ -485,25 +487,24 @@ static const struct phy_ops phy_ops = {
static int tusb1210_probe(struct ulpi *ulpi)
{
+ struct device *dev = &ulpi->dev;
struct tusb1210 *tusb;
u8 val, reg;
int ret;
- tusb = devm_kzalloc(&ulpi->dev, sizeof(*tusb), GFP_KERNEL);
+ tusb = devm_kzalloc(dev, sizeof(*tusb), GFP_KERNEL);
if (!tusb)
return -ENOMEM;
- tusb->ulpi = ulpi;
+ tusb->dev = dev;
- tusb->gpio_reset = devm_gpiod_get_optional(&ulpi->dev, "reset",
- GPIOD_OUT_LOW);
+ tusb->gpio_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(tusb->gpio_reset))
return PTR_ERR(tusb->gpio_reset);
gpiod_set_value_cansleep(tusb->gpio_reset, 1);
- tusb->gpio_cs = devm_gpiod_get_optional(&ulpi->dev, "cs",
- GPIOD_OUT_LOW);
+ tusb->gpio_cs = devm_gpiod_get_optional(dev, "cs", GPIOD_OUT_LOW);
if (IS_ERR(tusb->gpio_cs))
return PTR_ERR(tusb->gpio_cs);
@@ -519,15 +520,15 @@ static int tusb1210_probe(struct ulpi *ulpi)
return ret;
/* High speed output drive strength configuration */
- if (!device_property_read_u8(&ulpi->dev, "ihstx", &val))
+ if (!device_property_read_u8(dev, "ihstx", &val))
u8p_replace_bits(&reg, val, (u8)TUSB1210_VENDOR_SPECIFIC2_IHSTX_MASK);
/* High speed output impedance configuration */
- if (!device_property_read_u8(&ulpi->dev, "zhsdrv", &val))
+ if (!device_property_read_u8(dev, "zhsdrv", &val))
u8p_replace_bits(&reg, val, (u8)TUSB1210_VENDOR_SPECIFIC2_ZHSDRV_MASK);
/* DP/DM swap control */
- if (!device_property_read_u8(&ulpi->dev, "datapolarity", &val))
+ if (!device_property_read_u8(dev, "datapolarity", &val))
u8p_replace_bits(&reg, val, (u8)TUSB1210_VENDOR_SPECIFIC2_DP_MASK);
ret = tusb1210_ulpi_write(tusb, TUSB1210_VENDOR_SPECIFIC2, reg);
@@ -561,11 +562,9 @@ static void tusb1210_remove(struct ulpi *ulpi)
tusb1210_remove_charger_detect(tusb);
}
-#define TI_VENDOR_ID 0x0451
-
static const struct ulpi_device_id tusb1210_ulpi_id[] = {
- { TI_VENDOR_ID, 0x1507, }, /* TUSB1210 */
- { TI_VENDOR_ID, 0x1508, }, /* TUSB1211 */
+ { TI_VENDOR_ID, TI_DEVICE_TUSB1210 },
+ { TI_VENDOR_ID, TI_DEVICE_TUSB1211 },
{ },
};
MODULE_DEVICE_TABLE(ulpi, tusb1210_ulpi_id);
diff --git a/drivers/phy/ti/phy-twl4030-usb.c b/drivers/phy/ti/phy-twl4030-usb.c
index 6b265992d988..6f12b38cd894 100644
--- a/drivers/phy/ti/phy-twl4030-usb.c
+++ b/drivers/phy/ti/phy-twl4030-usb.c
@@ -834,7 +834,7 @@ MODULE_DEVICE_TABLE(of, twl4030_usb_id_table);
static struct platform_driver twl4030_usb_driver = {
.probe = twl4030_usb_probe,
- .remove_new = twl4030_usb_remove,
+ .remove = twl4030_usb_remove,
.driver = {
.name = "twl4030_usb",
.pm = &twl4030_usb_pm_ops,
diff --git a/drivers/phy/xilinx/phy-zynqmp.c b/drivers/phy/xilinx/phy-zynqmp.c
index 2559c6594cea..05a4a59f7c40 100644
--- a/drivers/phy/xilinx/phy-zynqmp.c
+++ b/drivers/phy/xilinx/phy-zynqmp.c
@@ -13,6 +13,7 @@
*/
#include <linux/clk.h>
+#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/kernel.h>
@@ -80,7 +81,8 @@
/* Reference clock selection parameters */
#define L0_Ln_REF_CLK_SEL(n) (0x2860 + (n) * 4)
-#define L0_REF_CLK_SEL_MASK 0x8f
+#define L0_REF_CLK_LCL_SEL BIT(7)
+#define L0_REF_CLK_SEL_MASK 0x9f
/* Calibration digital logic parameters */
#define L3_TM_CALIB_DIG19 0xec4c
@@ -122,6 +124,15 @@
#define ICM_PROTOCOL_DP 0x4
#define ICM_PROTOCOL_SGMII 0x5
+static const char *const xpsgtr_icm_str[] = {
+ [ICM_PROTOCOL_PD] = "none",
+ [ICM_PROTOCOL_PCIE] = "PCIe",
+ [ICM_PROTOCOL_SATA] = "SATA",
+ [ICM_PROTOCOL_USB] = "USB",
+ [ICM_PROTOCOL_DP] = "DisplayPort",
+ [ICM_PROTOCOL_SGMII] = "SGMII",
+};
+
/* Test Mode common reset control parameters */
#define TM_CMN_RST 0x10018
#define TM_CMN_RST_EN 0x1
@@ -146,25 +157,27 @@
/* Total number of controllers */
#define CONTROLLERS_PER_LANE 5
-/* Protocol Type parameters */
-#define XPSGTR_TYPE_USB0 0 /* USB controller 0 */
-#define XPSGTR_TYPE_USB1 1 /* USB controller 1 */
-#define XPSGTR_TYPE_SATA_0 2 /* SATA controller lane 0 */
-#define XPSGTR_TYPE_SATA_1 3 /* SATA controller lane 1 */
-#define XPSGTR_TYPE_PCIE_0 4 /* PCIe controller lane 0 */
-#define XPSGTR_TYPE_PCIE_1 5 /* PCIe controller lane 1 */
-#define XPSGTR_TYPE_PCIE_2 6 /* PCIe controller lane 2 */
-#define XPSGTR_TYPE_PCIE_3 7 /* PCIe controller lane 3 */
-#define XPSGTR_TYPE_DP_0 8 /* Display Port controller lane 0 */
-#define XPSGTR_TYPE_DP_1 9 /* Display Port controller lane 1 */
-#define XPSGTR_TYPE_SGMII0 10 /* Ethernet SGMII controller 0 */
-#define XPSGTR_TYPE_SGMII1 11 /* Ethernet SGMII controller 1 */
-#define XPSGTR_TYPE_SGMII2 12 /* Ethernet SGMII controller 2 */
-#define XPSGTR_TYPE_SGMII3 13 /* Ethernet SGMII controller 3 */
-
/* Timeout values */
#define TIMEOUT_US 1000
+/* Lane 0/1/2/3 offset */
+#define DIG_8(n) ((0x4000 * (n)) + 0x1074)
+#define ILL13(n) ((0x4000 * (n)) + 0x1994)
+#define DIG_10(n) ((0x4000 * (n)) + 0x107c)
+#define RST_DLY(n) ((0x4000 * (n)) + 0x19a4)
+#define BYP_15(n) ((0x4000 * (n)) + 0x1038)
+#define BYP_12(n) ((0x4000 * (n)) + 0x102c)
+#define MISC3(n) ((0x4000 * (n)) + 0x19ac)
+#define EQ11(n) ((0x4000 * (n)) + 0x1978)
+
+static u32 save_reg_address[] = {
+ /* Lane 0/1/2/3 Register */
+ DIG_8(0), ILL13(0), DIG_10(0), RST_DLY(0), BYP_15(0), BYP_12(0), MISC3(0), EQ11(0),
+ DIG_8(1), ILL13(1), DIG_10(1), RST_DLY(1), BYP_15(1), BYP_12(1), MISC3(1), EQ11(1),
+ DIG_8(2), ILL13(2), DIG_10(2), RST_DLY(2), BYP_15(2), BYP_12(2), MISC3(2), EQ11(2),
+ DIG_8(3), ILL13(3), DIG_10(3), RST_DLY(3), BYP_15(3), BYP_12(3), MISC3(3), EQ11(3),
+};
+
struct xpsgtr_dev;
/**
@@ -184,7 +197,8 @@ struct xpsgtr_ssc {
/**
* struct xpsgtr_phy - representation of a lane
* @phy: pointer to the kernel PHY device
- * @type: controller which uses this lane
+ * @instance: instance of the protocol type (such as the lane within a
+ * protocol, or the USB/Ethernet controller)
* @lane: lane number
* @protocol: protocol in which the lane operates
* @skip_phy_init: skip phy_init() if true
@@ -193,7 +207,7 @@ struct xpsgtr_ssc {
*/
struct xpsgtr_phy {
struct phy *phy;
- u8 type;
+ u8 instance;
u8 lane;
u8 protocol;
bool skip_phy_init;
@@ -213,6 +227,7 @@ struct xpsgtr_phy {
* @tx_term_fix: fix for GT issue
* @saved_icm_cfg0: stored value of ICM CFG0 register
* @saved_icm_cfg1: stored value of ICM CFG1 register
+ * @saved_regs: registers to be saved/restored during suspend/resume
*/
struct xpsgtr_dev {
struct device *dev;
@@ -225,6 +240,7 @@ struct xpsgtr_dev {
bool tx_term_fix;
unsigned int saved_icm_cfg0;
unsigned int saved_icm_cfg1;
+ u32 *saved_regs;
};
/*
@@ -298,6 +314,32 @@ static inline void xpsgtr_clr_set_phy(struct xpsgtr_phy *gtr_phy,
writel((readl(addr) & ~clr) | set, addr);
}
+/**
+ * xpsgtr_save_lane_regs - Saves registers on suspend
+ * @gtr_dev: pointer to phy controller context structure
+ */
+static void xpsgtr_save_lane_regs(struct xpsgtr_dev *gtr_dev)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(save_reg_address); i++)
+ gtr_dev->saved_regs[i] = xpsgtr_read(gtr_dev,
+ save_reg_address[i]);
+}
+
+/**
+ * xpsgtr_restore_lane_regs - Restores registers on resume
+ * @gtr_dev: pointer to phy controller context structure
+ */
+static void xpsgtr_restore_lane_regs(struct xpsgtr_dev *gtr_dev)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(save_reg_address); i++)
+ xpsgtr_write(gtr_dev, save_reg_address[i],
+ gtr_dev->saved_regs[i]);
+}
+
/*
* Hardware Configuration
*/
@@ -308,10 +350,30 @@ static int xpsgtr_wait_pll_lock(struct phy *phy)
struct xpsgtr_phy *gtr_phy = phy_get_drvdata(phy);
struct xpsgtr_dev *gtr_dev = gtr_phy->dev;
unsigned int timeout = TIMEOUT_US;
+ u8 protocol = gtr_phy->protocol;
int ret;
dev_dbg(gtr_dev->dev, "Waiting for PLL lock\n");
+ /*
+ * For DP and PCIe, only the instance 0 PLL is used. Switch to that phy
+ * so we wait on the right PLL.
+ */
+ if ((protocol == ICM_PROTOCOL_DP || protocol == ICM_PROTOCOL_PCIE) &&
+ gtr_phy->instance) {
+ int i;
+
+ for (i = 0; i < NUM_LANES; i++) {
+ gtr_phy = &gtr_dev->phys[i];
+
+ if (gtr_phy->protocol == protocol && !gtr_phy->instance)
+ goto got_phy;
+ }
+
+ return -EBUSY;
+ }
+
+got_phy:
while (1) {
u32 reg = xpsgtr_read_phy(gtr_phy, L0_PLL_STATUS_READ_1);
@@ -330,8 +392,8 @@ static int xpsgtr_wait_pll_lock(struct phy *phy)
if (ret == -ETIMEDOUT)
dev_err(gtr_dev->dev,
- "lane %u (type %u, protocol %u): PLL lock timeout\n",
- gtr_phy->lane, gtr_phy->type, gtr_phy->protocol);
+ "lane %u (protocol %u, instance %u): PLL lock timeout\n",
+ gtr_phy->lane, gtr_phy->protocol, gtr_phy->instance);
return ret;
}
@@ -349,11 +411,12 @@ static void xpsgtr_configure_pll(struct xpsgtr_phy *gtr_phy)
PLL_FREQ_MASK, ssc->pll_ref_clk);
/* Enable lane clock sharing, if required */
- if (gtr_phy->refclk != gtr_phy->lane) {
- /* Lane3 Ref Clock Selection Register */
+ if (gtr_phy->refclk == gtr_phy->lane)
+ xpsgtr_clr_set(gtr_phy->dev, L0_Ln_REF_CLK_SEL(gtr_phy->lane),
+ L0_REF_CLK_SEL_MASK, L0_REF_CLK_LCL_SEL);
+ else
xpsgtr_clr_set(gtr_phy->dev, L0_Ln_REF_CLK_SEL(gtr_phy->lane),
L0_REF_CLK_SEL_MASK, 1 << gtr_phy->refclk);
- }
/* SSC step size [7:0] */
xpsgtr_clr_set_phy(gtr_phy, L0_PLL_SS_STEP_SIZE_0_LSB,
@@ -573,7 +636,7 @@ static int xpsgtr_phy_init(struct phy *phy)
mutex_lock(&gtr_dev->gtr_mutex);
/* Configure and enable the clock when peripheral phy_init call */
- if (clk_prepare_enable(gtr_dev->clk[gtr_phy->lane]))
+ if (clk_prepare_enable(gtr_dev->clk[gtr_phy->refclk]))
goto out;
/* Skip initialization if not required. */
@@ -625,7 +688,7 @@ static int xpsgtr_phy_exit(struct phy *phy)
gtr_phy->skip_phy_init = false;
/* Ensure that disable clock only, which configure for lane */
- clk_disable_unprepare(gtr_dev->clk[gtr_phy->lane]);
+ clk_disable_unprepare(gtr_dev->clk[gtr_phy->refclk]);
return 0;
}
@@ -638,16 +701,7 @@ static int xpsgtr_phy_power_on(struct phy *phy)
/* Skip initialization if not required. */
if (!xpsgtr_phy_init_required(gtr_phy))
return ret;
- /*
- * Wait for the PLL to lock. For DP, only wait on DP0 to avoid
- * cumulating waits for both lanes. The user is expected to initialize
- * lane 0 last.
- */
- if (gtr_phy->protocol != ICM_PROTOCOL_DP ||
- gtr_phy->type == XPSGTR_TYPE_DP_0)
- ret = xpsgtr_wait_pll_lock(phy);
-
- return ret;
+ return xpsgtr_wait_pll_lock(phy);
}
static int xpsgtr_phy_configure(struct phy *phy, union phy_configure_opts *opts)
@@ -674,73 +728,33 @@ static const struct phy_ops xpsgtr_phyops = {
* OF Xlate Support
*/
-/* Set the lane type and protocol based on the PHY type and instance number. */
+/* Set the lane protocol and instance based on the PHY type and instance number. */
static int xpsgtr_set_lane_type(struct xpsgtr_phy *gtr_phy, u8 phy_type,
unsigned int phy_instance)
{
unsigned int num_phy_types;
- const int *phy_types;
switch (phy_type) {
- case PHY_TYPE_SATA: {
- static const int types[] = {
- XPSGTR_TYPE_SATA_0,
- XPSGTR_TYPE_SATA_1,
- };
-
- phy_types = types;
- num_phy_types = ARRAY_SIZE(types);
+ case PHY_TYPE_SATA:
+ num_phy_types = 2;
gtr_phy->protocol = ICM_PROTOCOL_SATA;
break;
- }
- case PHY_TYPE_USB3: {
- static const int types[] = {
- XPSGTR_TYPE_USB0,
- XPSGTR_TYPE_USB1,
- };
-
- phy_types = types;
- num_phy_types = ARRAY_SIZE(types);
+ case PHY_TYPE_USB3:
+ num_phy_types = 2;
gtr_phy->protocol = ICM_PROTOCOL_USB;
break;
- }
- case PHY_TYPE_DP: {
- static const int types[] = {
- XPSGTR_TYPE_DP_0,
- XPSGTR_TYPE_DP_1,
- };
-
- phy_types = types;
- num_phy_types = ARRAY_SIZE(types);
+ case PHY_TYPE_DP:
+ num_phy_types = 2;
gtr_phy->protocol = ICM_PROTOCOL_DP;
break;
- }
- case PHY_TYPE_PCIE: {
- static const int types[] = {
- XPSGTR_TYPE_PCIE_0,
- XPSGTR_TYPE_PCIE_1,
- XPSGTR_TYPE_PCIE_2,
- XPSGTR_TYPE_PCIE_3,
- };
-
- phy_types = types;
- num_phy_types = ARRAY_SIZE(types);
+ case PHY_TYPE_PCIE:
+ num_phy_types = 4;
gtr_phy->protocol = ICM_PROTOCOL_PCIE;
break;
- }
- case PHY_TYPE_SGMII: {
- static const int types[] = {
- XPSGTR_TYPE_SGMII0,
- XPSGTR_TYPE_SGMII1,
- XPSGTR_TYPE_SGMII2,
- XPSGTR_TYPE_SGMII3,
- };
-
- phy_types = types;
- num_phy_types = ARRAY_SIZE(types);
+ case PHY_TYPE_SGMII:
+ num_phy_types = 4;
gtr_phy->protocol = ICM_PROTOCOL_SGMII;
break;
- }
default:
return -EINVAL;
}
@@ -748,27 +762,30 @@ static int xpsgtr_set_lane_type(struct xpsgtr_phy *gtr_phy, u8 phy_type,
if (phy_instance >= num_phy_types)
return -EINVAL;
- gtr_phy->type = phy_types[phy_instance];
+ gtr_phy->instance = phy_instance;
return 0;
}
/*
- * Valid combinations of controllers and lanes (Interconnect Matrix).
+ * Valid combinations of controllers and lanes (Interconnect Matrix). Each
+ * "instance" represents one controller for a lane. For PCIe and DP, the
+ * "instance" is the logical lane in the link. For SATA, USB, and SGMII,
+ * the instance is the index of the controller.
+ *
+ * This information is only used to validate the devicetree reference, and is
+ * not used when programming the hardware.
*/
static const unsigned int icm_matrix[NUM_LANES][CONTROLLERS_PER_LANE] = {
- { XPSGTR_TYPE_PCIE_0, XPSGTR_TYPE_SATA_0, XPSGTR_TYPE_USB0,
- XPSGTR_TYPE_DP_1, XPSGTR_TYPE_SGMII0 },
- { XPSGTR_TYPE_PCIE_1, XPSGTR_TYPE_SATA_1, XPSGTR_TYPE_USB0,
- XPSGTR_TYPE_DP_0, XPSGTR_TYPE_SGMII1 },
- { XPSGTR_TYPE_PCIE_2, XPSGTR_TYPE_SATA_0, XPSGTR_TYPE_USB0,
- XPSGTR_TYPE_DP_1, XPSGTR_TYPE_SGMII2 },
- { XPSGTR_TYPE_PCIE_3, XPSGTR_TYPE_SATA_1, XPSGTR_TYPE_USB1,
- XPSGTR_TYPE_DP_0, XPSGTR_TYPE_SGMII3 }
+ /* PCIe, SATA, USB, DP, SGMII */
+ { 0, 0, 0, 1, 0 }, /* Lane 0 */
+ { 1, 1, 0, 0, 1 }, /* Lane 1 */
+ { 2, 0, 0, 1, 2 }, /* Lane 2 */
+ { 3, 1, 1, 0, 3 }, /* Lane 3 */
};
/* Translate OF phandle and args to PHY instance. */
static struct phy *xpsgtr_xlate(struct device *dev,
- struct of_phandle_args *args)
+ const struct of_phandle_args *args)
{
struct xpsgtr_dev *gtr_dev = dev_get_drvdata(dev);
struct xpsgtr_phy *gtr_phy;
@@ -798,6 +815,7 @@ static struct phy *xpsgtr_xlate(struct device *dev,
phy_type = args->args[1];
phy_instance = args->args[2];
+ guard(mutex)(&gtr_phy->phy->mutex);
ret = xpsgtr_set_lane_type(gtr_phy, phy_type, phy_instance);
if (ret < 0) {
dev_err(gtr_dev->dev, "Invalid PHY type and/or instance\n");
@@ -818,7 +836,7 @@ static struct phy *xpsgtr_xlate(struct device *dev,
* is allowed to operate on the lane.
*/
for (i = 0; i < CONTROLLERS_PER_LANE; i++) {
- if (icm_matrix[phy_lane][i] == gtr_phy->type)
+ if (icm_matrix[phy_lane][i] == gtr_phy->instance)
return gtr_phy->phy;
}
@@ -826,6 +844,34 @@ static struct phy *xpsgtr_xlate(struct device *dev,
}
/*
+ * DebugFS
+ */
+
+static int xpsgtr_status_read(struct seq_file *seq, void *data)
+{
+ struct device *dev = seq->private;
+ struct xpsgtr_phy *gtr_phy = dev_get_drvdata(dev);
+ struct clk *clk;
+ u32 pll_status;
+
+ mutex_lock(&gtr_phy->phy->mutex);
+ pll_status = xpsgtr_read_phy(gtr_phy, L0_PLL_STATUS_READ_1);
+ clk = gtr_phy->dev->clk[gtr_phy->refclk];
+
+ seq_printf(seq, "Lane: %u\n", gtr_phy->lane);
+ seq_printf(seq, "Protocol: %s\n",
+ xpsgtr_icm_str[gtr_phy->protocol]);
+ seq_printf(seq, "Instance: %u\n", gtr_phy->instance);
+ seq_printf(seq, "Reference clock: %u (%pC)\n", gtr_phy->refclk, clk);
+ seq_printf(seq, "Reference rate: %lu\n", clk_get_rate(clk));
+ seq_printf(seq, "PLL locked: %s\n",
+ pll_status & PLL_STATUS_LOCKED ? "yes" : "no");
+
+ mutex_unlock(&gtr_phy->phy->mutex);
+ return 0;
+}
+
+/*
* Power Management
*/
@@ -837,6 +883,8 @@ static int xpsgtr_runtime_suspend(struct device *dev)
gtr_dev->saved_icm_cfg0 = xpsgtr_read(gtr_dev, ICM_CFG0);
gtr_dev->saved_icm_cfg1 = xpsgtr_read(gtr_dev, ICM_CFG1);
+ xpsgtr_save_lane_regs(gtr_dev);
+
return 0;
}
@@ -847,6 +895,8 @@ static int xpsgtr_runtime_resume(struct device *dev)
unsigned int i;
bool skip_phy_init;
+ xpsgtr_restore_lane_regs(gtr_dev);
+
icm_cfg0 = xpsgtr_read(gtr_dev, ICM_CFG0);
icm_cfg1 = xpsgtr_read(gtr_dev, ICM_CFG1);
@@ -974,6 +1024,8 @@ static int xpsgtr_probe(struct platform_device *pdev)
gtr_phy->phy = phy;
phy_set_drvdata(phy, gtr_phy);
+ debugfs_create_devm_seqfile(&phy->dev, "status", phy->debugfs,
+ xpsgtr_status_read);
}
/* Register the PHY provider. */
@@ -992,18 +1044,22 @@ static int xpsgtr_probe(struct platform_device *pdev)
return ret;
}
+ gtr_dev->saved_regs = devm_kmalloc(gtr_dev->dev,
+ sizeof(save_reg_address),
+ GFP_KERNEL);
+ if (!gtr_dev->saved_regs)
+ return -ENOMEM;
+
return 0;
}
-static int xpsgtr_remove(struct platform_device *pdev)
+static void xpsgtr_remove(struct platform_device *pdev)
{
struct xpsgtr_dev *gtr_dev = platform_get_drvdata(pdev);
pm_runtime_disable(gtr_dev->dev);
pm_runtime_put_noidle(gtr_dev->dev);
pm_runtime_set_suspended(gtr_dev->dev);
-
- return 0;
}
static const struct of_device_id xpsgtr_of_match[] = {
@@ -1015,7 +1071,7 @@ MODULE_DEVICE_TABLE(of, xpsgtr_of_match);
static struct platform_driver xpsgtr_driver = {
.probe = xpsgtr_probe,
- .remove = xpsgtr_remove,
+ .remove = xpsgtr_remove,
.driver = {
.name = "xilinx-psgtr",
.of_match_table = xpsgtr_of_match,