diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-06-23 15:41:48 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-06-23 15:41:48 -0700 |
| commit | 62cf248de32f061d99cf7cd1675419d739031c5e (patch) | |
| tree | 606dc919b1548413a4f5e5a882708661ac5d4425 /drivers | |
| parent | 240303e47f48f434b5dd4a35d6d242856e23fa22 (diff) | |
| parent | 2ace2e949979b82f82f12dd76d7c5a6145246ca3 (diff) | |
| download | ath-62cf248de32f061d99cf7cd1675419d739031c5e.tar.gz | |
Merge tag 'phy-for-7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy
Pull phy updates from Vinod Koul:
"Bunch of new driver, device support in existing drivers/binding and
few updates to existing drivers
New Support:
- Qualcomm Eliza QMP PHY, Eliza Synopsys eUSB2 support, Eliza PCIe
phy support, Nord QMP UFS PHY, IPQ5210 USB3 PHY support
- Econet EN751221 and EN7528 PCIe phy support
- NXPs TJA1145 CAN transceiver phy support
- TI DS125DF111 retimer phy support
- Rockchip RK3528 usb phy support
- TI J722S phy support
- Axiado eMMC PHY driver
- EyeQ5 Ethernet PHY driver
- Generic PHY driver for Lynx 10G SerDes
- Spacemit K3 USB2 PHY support
Updates:
- Tomi helping maintian zynqmp phys
- lynx phy updates to support 25GBASER
- Rockchip GRF for RK3568/RV1108 support
- Qualcomm QSERDES COM v2 support"
* tag 'phy-for-7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy: (87 commits)
phy: rockchip: inno-usb2: Add missing clkout_ctl_phy kerneldoc
phy: Move MODULE_DEVICE_TABLE next to the table itself
phy: add basic support for NXPs TJA1145 CAN transceiver
dt-bindings: phy: add support for NXPs TJA1145 CAN transceiver
phy: freescale: phy-fsl-imx8qm-lvds-phy: Fix missing pm_runtime_disable() on probe error path
dt-bindings: phy: qcom,qmp-usb: Add ipq5210 USB3 PHY
dt-bindings: phy: qcom,qusb2: Document IPQ5210 compatible
phy: freescale: phy-fsl-imx8qm-lvds-phy: Use synchronous PM runtime put in reset
MAINTAINERS: expand Lynx 28G entry to cover Lynx 10G SerDes
phy: lynx-10g: new driver
dt-bindings: phy: lynx-10g: initial document
phy: lynx-28g: improve phy_validate() procedure
phy: lynx-28g: optimize read-modify-write operation
phy: lynx-28g: add support for big endian register maps
phy: lynx-28g: common probe() and remove()
phy: lynx-28g: make lynx_28g_pll_read_configuration() callable per PLL
phy: lynx-28g: move struct lynx_info definitions downwards
phy: lynx-28g: provide default lynx_lane_supports_mode() implementation
phy: lynx-28g: generalize protocol converter accessors
phy: lynx-28g: common lynx_pll_get()
...
Diffstat (limited to 'drivers')
49 files changed, 4907 insertions, 1746 deletions
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 227b9a4c612e8..19f3b7d12b7d4 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -66,6 +66,31 @@ config PHY_CAN_TRANSCEIVER functional modes using gpios and sets the attribute max link rate, for CAN drivers. +config PHY_EYEQ5_ETH + tristate "Ethernet PHY Driver on EyeQ5" + depends on OF + depends on MACH_EYEQ5 || COMPILE_TEST + select AUXILIARY_BUS + select GENERIC_PHY + default MACH_EYEQ5 + help + Enable this to support the Ethernet PHY integrated on EyeQ5. + It supports both RGMII and SGMII. Registers are located in a + shared register region called OLB. If M is selected, the + module will be called phy-eyeq5-eth. + +config PHY_ECONET_PCIE + tristate "EcoNet PCIe-PHY Driver" + depends on ECONET || COMPILE_TEST + depends on OF + select GENERIC_PHY + select REGMAP_MMIO + help + Say Y here to add support for EcoNet PCIe PHY driver. + This driver create the basic PHY instance and provides initialize + callback for PCIe GEN1 and GEN2 ports. This PHY is found on + EcoNet SoCs including EN751221 and EN7528. + config PHY_GOOGLE_USB tristate "Google Tensor SoC USB PHY driver" select GENERIC_PHY @@ -111,6 +136,16 @@ config PHY_NXP_PTN3222 schemes. It supports all three USB 2.0 data rates: Low Speed, Full Speed and High Speed. +config PHY_NXP_TJA1145 + tristate "NXP TJA1145 CAN transceiver PHY" + select GENERIC_PHY + select REGMAP_SPI + depends on SPI + help + This option enables support for NXPs TJA1145 CAN transceiver as a PHY. + This driver provides function for putting the transceiver in various + functional modes using SPI commands. + config PHY_PISTACHIO_USB tristate "IMG Pistachio USB2.0 PHY driver" depends on MIPS || COMPILE_TEST @@ -136,6 +171,7 @@ config PHY_XGENE source "drivers/phy/allwinner/Kconfig" source "drivers/phy/amlogic/Kconfig" source "drivers/phy/apple/Kconfig" +source "drivers/phy/axiado/Kconfig" source "drivers/phy/broadcom/Kconfig" source "drivers/phy/cadence/Kconfig" source "drivers/phy/canaan/Kconfig" diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index f49d83f00a3d8..d7aa516bcc49e 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -9,10 +9,13 @@ obj-$(CONFIG_GENERIC_PHY) += phy-core.o obj-$(CONFIG_GENERIC_PHY_MIPI_DPHY) += phy-core-mipi-dphy.o obj-$(CONFIG_PHY_AIROHA_PCIE) += phy-airoha-pcie.o obj-$(CONFIG_PHY_CAN_TRANSCEIVER) += phy-can-transceiver.o +obj-$(CONFIG_PHY_ECONET_PCIE) += phy-econet-pcie.o +obj-$(CONFIG_PHY_EYEQ5_ETH) += phy-eyeq5-eth.o obj-$(CONFIG_PHY_GOOGLE_USB) += phy-google-usb.o obj-$(CONFIG_USB_LGM_PHY) += phy-lgm-usb.o obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o obj-$(CONFIG_PHY_NXP_PTN3222) += phy-nxp-ptn3222.o +obj-$(CONFIG_PHY_NXP_TJA1145) += phy-nxp-tja1145.o obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o obj-$(CONFIG_PHY_SNPS_EUSB2) += phy-snps-eusb2.o obj-$(CONFIG_PHY_XGENE) += phy-xgene.o @@ -20,6 +23,7 @@ obj-$(CONFIG_PHY_XGENE) += phy-xgene.o obj-$(CONFIG_GENERIC_PHY) += allwinner/ \ amlogic/ \ apple/ \ + axiado/ \ broadcom/ \ cadence/ \ canaan/ \ diff --git a/drivers/phy/axiado/Kconfig b/drivers/phy/axiado/Kconfig new file mode 100644 index 0000000000000..d159e03453459 --- /dev/null +++ b/drivers/phy/axiado/Kconfig @@ -0,0 +1,11 @@ +# +# PHY drivers for Axiado platforms +# + +config PHY_AX3000_EMMC + tristate "Axiado eMMC PHY driver" + depends on OF && (ARCH_AXIADO || COMPILE_TEST) + select GENERIC_PHY + help + Enables this to support for the AX3000 EMMC PHY driver. + If unsure, say N. diff --git a/drivers/phy/axiado/Makefile b/drivers/phy/axiado/Makefile new file mode 100644 index 0000000000000..1e2b1ba016092 --- /dev/null +++ b/drivers/phy/axiado/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_PHY_AX3000_EMMC) += phy-axiado-emmc.o diff --git a/drivers/phy/axiado/phy-axiado-emmc.c b/drivers/phy/axiado/phy-axiado-emmc.c new file mode 100644 index 0000000000000..e0e2174776ad0 --- /dev/null +++ b/drivers/phy/axiado/phy-axiado-emmc.c @@ -0,0 +1,217 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Axiado eMMC PHY driver + * + * Copyright (C) 2017 Arasan Chip Systems Inc. + * Copyright (C) 2022-2026 Axiado Corporation (or its affiliates). + * + * Based on Arasan Driver (sdhci-pci-arasan.c) + * sdhci-pci-arasan.c - Driver for Arasan PCI Controller with integrated phy. + */ +#include <linux/bitfield.h> +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/iopoll.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/phy/phy.h> +#include <linux/platform_device.h> + +/* Arasan eMMC 5.1 - PHY configuration registers */ +#define CAP_REG_IN_S1_MSB 0x04 +#define PHY_CTRL_1 0x38 +#define PHY_CTRL_2 0x3c +#define PHY_CTRL_3 0x40 +#define STATUS 0x50 + +#define DLL_ENBL BIT(26) +#define RTRIM_EN BIT(21) +#define PDB_ENBL BIT(23) +#define RETB_ENBL BIT(1) + +#define REN_STRB BIT(27) +#define REN_CMD_EN GENMASK(20, 12) + +/* Pull-UP Enable on CMD Line */ +#define PU_CMD_EN GENMASK(11, 3) + +/* Selection value for the optimum delay from 1-32 output tap lines */ +#define OTAP_DLY 0x02 +/* DLL charge pump current trim default [1000] */ +#define DLL_TRM_ICP 0x08 +/* Select the frequency range of DLL Operation */ +#define FRQ_SEL 0x01 + +#define OTAP_SEL_MASK GENMASK(10, 7) +#define DLL_TRM_MASK GENMASK(25, 22) +#define DLL_FRQSEL_MASK GENMASK(27, 25) + +#define OTAP_SEL(x) (FIELD_PREP(OTAP_SEL_MASK, x) | OTAPDLY_EN) +#define DLL_TRM(x) (FIELD_PREP(DLL_TRM_MASK, x) | DLL_ENBL) +#define DLL_FRQSEL(x) FIELD_PREP(DLL_FRQSEL_MASK, x) + +#define OTAPDLY_EN BIT(11) + +#define SEL_DLY_RXCLK BIT(18) +#define SEL_DLY_TXCLK BIT(19) + +#define CALDONE_MASK 0x40 +#define DLL_RDY_MASK 0x1 +#define MAX_CLK_BUF0 BIT(20) +#define MAX_CLK_BUF1 BIT(21) +#define MAX_CLK_BUF2 BIT(22) + +#define CLK_MULTIPLIER 0xc008e +#define POLL_TIMEOUT_MS 3000 +#define POLL_DELAY_US 100 + +struct axiado_emmc_phy { + void __iomem *reg_base; + struct device *dev; +}; + +static int axiado_emmc_phy_init(struct phy *phy) +{ + struct axiado_emmc_phy *ax_phy = phy_get_drvdata(phy); + struct device *dev = ax_phy->dev; + u32 val; + int ret; + + val = readl(ax_phy->reg_base + PHY_CTRL_1); + writel(val | RETB_ENBL | RTRIM_EN, ax_phy->reg_base + PHY_CTRL_1); + + val = readl(ax_phy->reg_base + PHY_CTRL_3); + writel(val | PDB_ENBL, ax_phy->reg_base + PHY_CTRL_3); + + ret = readl_poll_timeout(ax_phy->reg_base + STATUS, val, + val & CALDONE_MASK, POLL_DELAY_US, + POLL_TIMEOUT_MS * 1000); + if (ret) { + dev_err(dev, "PHY calibration timeout\n"); + return ret; + } + + val = readl(ax_phy->reg_base + PHY_CTRL_1); + writel(val | REN_CMD_EN | PU_CMD_EN, ax_phy->reg_base + PHY_CTRL_1); + + val = readl(ax_phy->reg_base + PHY_CTRL_2); + writel(val | REN_STRB, ax_phy->reg_base + PHY_CTRL_2); + + val = readl(ax_phy->reg_base + PHY_CTRL_3); + writel(val | MAX_CLK_BUF0 | MAX_CLK_BUF1 | MAX_CLK_BUF2, + ax_phy->reg_base + PHY_CTRL_3); + + writel(CLK_MULTIPLIER, ax_phy->reg_base + CAP_REG_IN_S1_MSB); + + val = readl(ax_phy->reg_base + PHY_CTRL_3); + writel(val | SEL_DLY_RXCLK | SEL_DLY_TXCLK, + ax_phy->reg_base + PHY_CTRL_3); + + return 0; +} + +static int axiado_emmc_phy_power_on(struct phy *phy) +{ + struct axiado_emmc_phy *ax_phy = phy_get_drvdata(phy); + struct device *dev = ax_phy->dev; + u32 val; + int ret; + + val = readl(ax_phy->reg_base + PHY_CTRL_1); + writel(val | RETB_ENBL, ax_phy->reg_base + PHY_CTRL_1); + + val = readl(ax_phy->reg_base + PHY_CTRL_3); + writel(val | PDB_ENBL, ax_phy->reg_base + PHY_CTRL_3); + + val = readl(ax_phy->reg_base + PHY_CTRL_2); + writel(val | OTAP_SEL(OTAP_DLY), ax_phy->reg_base + PHY_CTRL_2); + + val = readl(ax_phy->reg_base + PHY_CTRL_1); + writel(val | DLL_TRM(DLL_TRM_ICP), ax_phy->reg_base + PHY_CTRL_1); + + val = readl(ax_phy->reg_base + PHY_CTRL_3); + writel(val | DLL_FRQSEL(FRQ_SEL), ax_phy->reg_base + PHY_CTRL_3); + + ret = read_poll_timeout(readl, val, val & DLL_RDY_MASK, POLL_DELAY_US, + POLL_TIMEOUT_MS * 1000, false, + ax_phy->reg_base + STATUS); + if (ret) { + dev_err(dev, "DLL ready timeout\n"); + return ret; + } + + return 0; +} + +static int axiado_emmc_phy_power_off(struct phy *phy) +{ + struct axiado_emmc_phy *ax_phy = phy_get_drvdata(phy); + u32 val; + + val = readl(ax_phy->reg_base + PHY_CTRL_1); + val &= ~(DLL_TRM_MASK | DLL_ENBL); + writel(val, ax_phy->reg_base + PHY_CTRL_1); + + val = readl(ax_phy->reg_base + PHY_CTRL_3); + val &= ~(DLL_FRQSEL_MASK | PDB_ENBL); + writel(val, ax_phy->reg_base + PHY_CTRL_3); + + return 0; +} + +static const struct phy_ops axiado_emmc_phy_ops = { + .init = axiado_emmc_phy_init, + .power_on = axiado_emmc_phy_power_on, + .power_off = axiado_emmc_phy_power_off, + .owner = THIS_MODULE, +}; + +static const struct of_device_id axiado_emmc_phy_of_match[] = { + { .compatible = "axiado,ax3000-emmc-phy" }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, axiado_emmc_phy_of_match); + +static int axiado_emmc_phy_probe(struct platform_device *pdev) +{ + struct axiado_emmc_phy *ax_phy; + struct phy_provider *phy_provider; + struct device *dev = &pdev->dev; + struct phy *generic_phy; + + if (!dev->of_node) + return -ENODEV; + + ax_phy = devm_kzalloc(dev, sizeof(*ax_phy), GFP_KERNEL); + if (!ax_phy) + return -ENOMEM; + + ax_phy->reg_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(ax_phy->reg_base)) + return PTR_ERR(ax_phy->reg_base); + + ax_phy->dev = dev; + + generic_phy = devm_phy_create(dev, dev->of_node, &axiado_emmc_phy_ops); + if (IS_ERR(generic_phy)) + return dev_err_probe(dev, PTR_ERR(generic_phy), + "failed to create PHY\n"); + + phy_set_drvdata(generic_phy, ax_phy); + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + + return PTR_ERR_OR_ZERO(phy_provider); +} + +static struct platform_driver axiado_emmc_phy_driver = { + .probe = axiado_emmc_phy_probe, + .driver = { + .name = "axiado-emmc-phy", + .of_match_table = axiado_emmc_phy_of_match, + }, +}; +module_platform_driver(axiado_emmc_phy_driver); + +MODULE_DESCRIPTION("AX3000 eMMC PHY Driver"); +MODULE_AUTHOR("Axiado Corporation"); +MODULE_LICENSE("GPL"); diff --git a/drivers/phy/broadcom/phy-bcm-ns-usb3.c b/drivers/phy/broadcom/phy-bcm-ns-usb3.c index 6e56498d0644b..9240600aeef6e 100644 --- a/drivers/phy/broadcom/phy-bcm-ns-usb3.c +++ b/drivers/phy/broadcom/phy-bcm-ns-usb3.c @@ -65,6 +65,7 @@ static const struct of_device_id bcm_ns_usb3_id_table[] = { }, {}, }; +MODULE_DEVICE_TABLE(of, bcm_ns_usb3_id_table); static int bcm_ns_usb3_mdio_phy_write(struct bcm_ns_usb3 *usb3, u16 reg, u16 value); @@ -242,4 +243,3 @@ 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/freescale/Kconfig b/drivers/phy/freescale/Kconfig index 81f53564ee156..5bf3864fbe642 100644 --- a/drivers/phy/freescale/Kconfig +++ b/drivers/phy/freescale/Kconfig @@ -51,11 +51,25 @@ config PHY_FSL_SAMSUNG_HDMI_PHY Enable this to add support for the Samsung HDMI PHY in i.MX8MP. endif +config PHY_FSL_LYNX_CORE + tristate + +config PHY_FSL_LYNX_10G + tristate "Freescale Layerscape Lynx 10G SerDes PHY support" + depends on OF + depends on ARCH_LAYERSCAPE || COMPILE_TEST + select GENERIC_PHY + select PHY_FSL_LYNX_CORE + help + Enable this to add support for the Lynx 10G SerDes PHY as found on + NXP's Layerscape platform such as LS1088A or LS1028A. + config PHY_FSL_LYNX_28G tristate "Freescale Layerscape Lynx 28G SerDes PHY support" depends on OF depends on ARCH_LAYERSCAPE || COMPILE_TEST select GENERIC_PHY + select PHY_FSL_LYNX_CORE help Enable this to add support for the Lynx SerDes 28G PHY as found on NXP's Layerscape platforms such as LX2160A. diff --git a/drivers/phy/freescale/Makefile b/drivers/phy/freescale/Makefile index 658eac7d0a622..5b0e180d6972f 100644 --- a/drivers/phy/freescale/Makefile +++ b/drivers/phy/freescale/Makefile @@ -4,5 +4,7 @@ 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_CORE) += phy-fsl-lynx-core.o +obj-$(CONFIG_PHY_FSL_LYNX_10G) += phy-fsl-lynx-10g.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-imx8qm-hsio.c b/drivers/phy/freescale/phy-fsl-imx8qm-hsio.c index 279b8ac7822df..4ab45c9f53dff 100644 --- a/drivers/phy/freescale/phy-fsl-imx8qm-hsio.c +++ b/drivers/phy/freescale/phy-fsl-imx8qm-hsio.c @@ -107,7 +107,22 @@ static const char * const lan2_pcieb_clks[] = {"apb_pclk2", "pclk2", "ctl1_crr", static const char * const lan2_sata_clks[] = {"pclk2", "epcs_tx", "epcs_rx", "phy1_crr", "misc_crr"}; -static const struct regmap_config regmap_config = { +static const struct regmap_config regmap_phy_config = { + .name = "phy", + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + +static const struct regmap_config regmap_ctrl_config = { + .name = "ctrl", + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + +static const struct regmap_config regmap_misc_config = { + .name = "misc", .reg_bits = 32, .val_bits = 32, .reg_stride = 4, @@ -562,19 +577,19 @@ static int imx_hsio_probe(struct platform_device *pdev) return PTR_ERR(priv->base); off = devm_platform_ioremap_resource_byname(pdev, "phy"); - priv->phy = devm_regmap_init_mmio(dev, off, ®map_config); + priv->phy = devm_regmap_init_mmio(dev, off, ®map_phy_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, ®map_config); + priv->ctrl = devm_regmap_init_mmio(dev, off, ®map_ctrl_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, ®map_config); + priv->misc = devm_regmap_init_mmio(dev, off, ®map_misc_config); if (IS_ERR(priv->misc)) return dev_err_probe(dev, PTR_ERR(priv->misc), "unable to find misc csr registers\n"); diff --git a/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c b/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c index ece3574435217..368679436d862 100644 --- a/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c +++ b/drivers/phy/freescale/phy-fsl-imx8qm-lvds-phy.c @@ -286,7 +286,7 @@ static int mixel_lvds_phy_reset(struct device *dev) regmap_write(priv->regmap, PHY_CTRL, CTRL_RESET_VAL); - pm_runtime_put(dev); + pm_runtime_put_sync(dev); return 0; } @@ -345,7 +345,9 @@ static int mixel_lvds_phy_probe(struct platform_device *pdev) dev_set_drvdata(dev, priv); - pm_runtime_enable(dev); + ret = devm_pm_runtime_enable(dev); + if (ret) + return ret; ret = mixel_lvds_phy_reset(dev); if (ret) { @@ -355,17 +357,15 @@ static int mixel_lvds_phy_probe(struct platform_device *pdev) for (i = 0; i < PHY_NUM; i++) { lvds_phy = devm_kzalloc(dev, sizeof(*lvds_phy), GFP_KERNEL); - if (!lvds_phy) { - ret = -ENOMEM; - goto err; - } + if (!lvds_phy) + return -ENOMEM; phy = devm_phy_create(dev, NULL, &mixel_lvds_phy_ops); if (IS_ERR(phy)) { ret = PTR_ERR(phy); dev_err(dev, "failed to create PHY for channel%d: %d\n", i, ret); - goto err; + return ret; } lvds_phy->phy = phy; @@ -379,19 +379,10 @@ static int mixel_lvds_phy_probe(struct platform_device *pdev) if (IS_ERR(phy_provider)) { ret = PTR_ERR(phy_provider); dev_err(dev, "failed to register PHY provider: %d\n", ret); - goto err; + return ret; } return 0; -err: - pm_runtime_disable(dev); - - return ret; -} - -static void mixel_lvds_phy_remove(struct platform_device *pdev) -{ - pm_runtime_disable(&pdev->dev); } static int __maybe_unused mixel_lvds_phy_runtime_suspend(struct device *dev) @@ -432,7 +423,6 @@ MODULE_DEVICE_TABLE(of, mixel_lvds_phy_of_match); static struct platform_driver mixel_lvds_phy_driver = { .probe = mixel_lvds_phy_probe, - .remove = mixel_lvds_phy_remove, .driver = { .pm = &mixel_lvds_phy_pm_ops, .name = "mixel-lvds-phy", diff --git a/drivers/phy/freescale/phy-fsl-lynx-10g.c b/drivers/phy/freescale/phy-fsl-lynx-10g.c new file mode 100644 index 0000000000000..38def160ef1aa --- /dev/null +++ b/drivers/phy/freescale/phy-fsl-lynx-10g.c @@ -0,0 +1,1321 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* Copyright 2021-2026 NXP */ + +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/phy.h> +#include <linux/phy/phy.h> +#include <linux/platform_device.h> +#include <linux/workqueue.h> + +#include "phy-fsl-lynx-core.h" + +/* SoC IP wrapper for protocol converters */ +#define PCCR8 0x220 +#define PCCR8_SGMIIa_KX BIT(3) +#define PCCR8_SGMIIa_CFG GENMASK(2, 0) + +#define PCCR9 0x224 +#define PCCR9_QSGMIIa_CFG GENMASK(2, 0) +#define PCCR9_QXGMIIa_CFG GENMASK(2, 0) + +#define PCCRB 0x22c +#define PCCRB_XFIa_CFG GENMASK(2, 0) +#define PCCRB_SXGMIIa_CFG GENMASK(2, 0) + +#define SGMII_CFG(id) (28 - (id) * 4) +#define QSGMII_CFG(id) (28 - (id) * 4) +#define SXGMII_CFG(id) (28 - (id) * 4) +#define QXGMII_CFG(id) (12 - (id) * 4) +#define XFI_CFG(id) (28 - (id) * 4) + +#define CR(x) ((x) * 4) + +#define A 0 +#define B 1 +#define C 2 +#define D 3 +#define E 4 +#define F 5 +#define G 6 +#define H 7 + +#define SGMIIaCR0(id) (0x1800 + (id) * 0x10) +#define QSGMIIaCR0(id) (0x1880 + (id) * 0x10) +#define XAUIaCR0(id) (0x1900 + (id) * 0x10) +#define XFIaCR0(id) (0x1980 + (id) * 0x10) +#define SXGMIIaCR0(id) (0x1a80 + (id) * 0x10) +#define QXGMIIaCR0(id) (0x1b00 + (id) * 0x20) + +#define SGMIIaCR0_RST_SGM BIT(31) +#define SGMIIaCR0_RST_SGM_OFF SGMIIaCR0_RST_SGM +#define SGMIIaCR0_RST_SGM_ON 0 +#define SGMIIaCR0_PD_SGM BIT(30) +#define SGMIIaCR1_SGPCS_EN BIT(11) +#define SGMIIaCR1_SGPCS_DIS 0x0 + +#define QSGMIIaCR0_RST_QSGM BIT(31) +#define QSGMIIaCR0_RST_QSGM_OFF QSGMIIaCR0_RST_QSGM +#define QSGMIIaCR0_RST_QSGM_ON 0 +#define QSGMIIaCR0_PD_QSGM BIT(30) + +/* Per PLL registers */ +#define PLLnCR0(pll) ((pll) * 0x20 + 0x4) + +#define PLLnCR0_POFF BIT(31) + +#define PLLnCR0_REFCLK_SEL GENMASK(30, 28) +#define PLLnCR0_REFCLK_SEL_100MHZ 0x0 +#define PLLnCR0_REFCLK_SEL_125MHZ 0x1 +#define PLLnCR0_REFCLK_SEL_156MHZ 0x2 +#define PLLnCR0_REFCLK_SEL_150MHZ 0x3 +#define PLLnCR0_REFCLK_SEL_161MHZ 0x4 +#define PLLnCR0_PLL_LCK BIT(23) +#define PLLnCR0_FRATE_SEL GENMASK(19, 16) +#define PLLnCR0_FRATE_5G 0x0 +#define PLLnCR0_FRATE_5_15625G 0x6 +#define PLLnCR0_FRATE_4G 0x7 +#define PLLnCR0_FRATE_3_125G 0x9 +#define PLLnCR0_FRATE_3G 0xa + +/* Per SerDes lane registers */ + +/* Lane a Protocol Select status register */ +#define LNaPSSR0(lane) (0x100 + (lane) * 0x20) +#define LNaPSSR0_TYPE GENMASK(30, 26) +#define LNaPSSR0_IS_QUAD GENMASK(25, 24) +#define LNaPSSR0_MAC GENMASK(19, 16) +#define LNaPSSR0_PCS GENMASK(10, 8) +#define LNaPSSR0_LANE GENMASK(2, 0) + +/* Lane a General Control Register */ +#define LNaGCR0(lane) (0x800 + (lane) * 0x40 + 0x0) +#define LNaGCR0_RPLL_PLLF BIT(31) +#define LNaGCR0_RPLL_PLLS 0x0 +#define LNaGCR0_RPLL_MSK BIT(31) +#define LNaGCR0_RRAT_SEL GENMASK(29, 28) +#define LNaGCR0_TRAT_SEL GENMASK(25, 24) +#define LNaGCR0_TPLL_PLLF BIT(27) +#define LNaGCR0_TPLL_PLLS 0x0 +#define LNaGCR0_TPLL_MSK BIT(27) +#define LNaGCR0_RRST_OFF LNaGCR0_RRST +#define LNaGCR0_TRST_OFF LNaGCR0_TRST +#define LNaGCR0_RRST_ON 0x0 +#define LNaGCR0_TRST_ON 0x0 +#define LNaGCR0_RRST BIT(22) +#define LNaGCR0_TRST BIT(21) +#define LNaGCR0_RX_PD BIT(20) +#define LNaGCR0_TX_PD BIT(19) +#define LNaGCR0_IF20BIT_EN BIT(18) +#define LNaGCR0_PROTS GENMASK(11, 7) + +#define LNaGCR1(lane) (0x800 + (lane) * 0x40 + 0x4) +#define LNaGCR1_RDAT_INV BIT(31) +#define LNaGCR1_TDAT_INV BIT(30) +#define LNaGCR1_OPAD_CTL BIT(26) +#define LNaGCR1_REIDL_TH GENMASK(22, 20) +#define LNaGCR1_REIDL_EX_SEL GENMASK(19, 18) +#define LNaGCR1_REIDL_ET_SEL GENMASK(17, 16) +#define LNaGCR1_REIDL_EX_MSB BIT(15) +#define LNaGCR1_REIDL_ET_MSB BIT(14) +#define LNaGCR1_REQ_CTL_SNP BIT(13) +#define LNaGCR1_REQ_CDR_SNP BIT(12) +#define LNaGCR1_TRSTDIR BIT(7) +#define LNaGCR1_REQ_BIN_SNP BIT(6) +#define LNaGCR1_ISLEW_RCTL GENMASK(5, 4) +#define LNaGCR1_OSLEW_RCTL GENMASK(1, 0) + +#define LNaRECR0(lane) (0x800 + (lane) * 0x40 + 0x10) +#define LNaRECR0_RXEQ_BST BIT(28) +#define LNaRECR0_GK2OVD GENMASK(27, 24) +#define LNaRECR0_GK3OVD GENMASK(19, 16) +#define LNaRECR0_GK2OVD_EN BIT(15) +#define LNaRECR0_GK3OVD_EN BIT(14) +#define LNaRECR0_OSETOVD_EN BIT(13) +#define LNaRECR0_BASE_WAND GENMASK(11, 10) +#define LNaRECR0_OSETOVD GENMASK(6, 0) + +#define LNaTECR0(lane) (0x800 + (lane) * 0x40 + 0x18) +#define LNaTECR0_TEQ_TYPE GENMASK(29, 28) +#define LNaTECR0_SGN_PREQ BIT(26) +#define LNaTECR0_RATIO_PREQ GENMASK(25, 22) +#define LNaTECR0_SGN_POST1Q BIT(21) +#define LNaTECR0_RATIO_PST1Q GENMASK(20, 16) +#define LNaTECR0_ADPT_EQ GENMASK(13, 8) +#define LNaTECR0_AMP_RED GENMASK(5, 0) + +#define LNaTTLCR0(lane) (0x800 + (lane) * 0x40 + 0x20) +#define LNaTTLCR1(lane) (0x800 + (lane) * 0x40 + 0x24) +#define LNaTTLCR2(lane) (0x800 + (lane) * 0x40 + 0x28) + +#define LNaTCSR3(lane) (0x800 + (lane) * 0x40 + 0x3C) +#define LNaTCSR3_CDR_LCK BIT(27) + +enum lynx_10g_rat_sel { + RAT_SEL_FULL = 0x0, + RAT_SEL_HALF = 0x1, + RAT_SEL_QUARTER = 0x2, + RAT_SEL_DOUBLE = 0x3, +}; + +enum lynx_10g_eq_type { + EQ_TYPE_NO_EQ = 0, + EQ_TYPE_2TAP = 1, + EQ_TYPE_3TAP = 2, +}; + +enum lynx_10g_proto_sel { + PROTO_SEL_PCIE = 0, + PROTO_SEL_SGMII_BASEX_KX_QSGMII = 1, + PROTO_SEL_SATA = 2, + PROTO_SEL_XAUI = 4, + PROTO_SEL_XFI_10GBASER_KR_SXGMII = 0xa, +}; + +struct lynx_10g_proto_conf { + int proto_sel; + int if20bit_en; + int reidl_th; + int reidl_et_msb; + int reidl_et_sel; + int reidl_ex_msb; + int reidl_ex_sel; + int islew_rctl; + int oslew_rctl; + int rxeq_bst; + int gk2ovd; + int gk3ovd; + int gk2ovd_en; + int gk3ovd_en; + int base_wand; + int teq_type; + int sgn_preq; + int ratio_preq; + int sgn_post1q; + int ratio_post1q; + int adpt_eq; + int amp_red; + int ttlcr0; +}; + +static const struct lynx_10g_proto_conf lynx_10g_proto_conf[LANE_MODE_MAX] = { + [LANE_MODE_1000BASEX_SGMII] = { + .proto_sel = PROTO_SEL_SGMII_BASEX_KX_QSGMII, + .reidl_th = 1, + .reidl_ex_sel = 3, + .reidl_et_msb = 1, + .islew_rctl = 1, + .oslew_rctl = 1, + .gk2ovd = 15, + .gk3ovd = 15, + .gk2ovd_en = 1, + .gk3ovd_en = 1, + .teq_type = EQ_TYPE_NO_EQ, + .adpt_eq = 48, + .amp_red = 6, + .ttlcr0 = 0x39000400, + }, + [LANE_MODE_2500BASEX] = { + .proto_sel = PROTO_SEL_SGMII_BASEX_KX_QSGMII, + .islew_rctl = 2, + .oslew_rctl = 2, + .teq_type = EQ_TYPE_2TAP, + .sgn_post1q = 1, + .ratio_post1q = 6, + .adpt_eq = 48, + .ttlcr0 = 0x00000400, + }, + [LANE_MODE_QSGMII] = { + .proto_sel = PROTO_SEL_SGMII_BASEX_KX_QSGMII, + .islew_rctl = 1, + .oslew_rctl = 1, + .teq_type = EQ_TYPE_2TAP, + .sgn_post1q = 1, + .ratio_post1q = 6, + .adpt_eq = 48, + .amp_red = 2, + .ttlcr0 = 0x00000400, + }, + [LANE_MODE_10G_QXGMII] = { + .proto_sel = PROTO_SEL_XFI_10GBASER_KR_SXGMII, + .if20bit_en = 1, + .islew_rctl = 1, + .oslew_rctl = 1, + .base_wand = 1, + .teq_type = EQ_TYPE_NO_EQ, + .adpt_eq = 48, + .ttlcr0 = 0x00000400, + }, + [LANE_MODE_USXGMII] = { + .proto_sel = PROTO_SEL_XFI_10GBASER_KR_SXGMII, + .if20bit_en = 1, + .islew_rctl = 1, + .oslew_rctl = 1, + .base_wand = 1, + .teq_type = EQ_TYPE_NO_EQ, + .sgn_post1q = 1, + .adpt_eq = 48, + .ttlcr0 = 0x00000400, + }, + [LANE_MODE_10GBASER] = { + .proto_sel = PROTO_SEL_XFI_10GBASER_KR_SXGMII, + .if20bit_en = 1, + .islew_rctl = 2, + .oslew_rctl = 2, + .rxeq_bst = 1, + .base_wand = 1, + .teq_type = EQ_TYPE_2TAP, + .sgn_post1q = 1, + .ratio_post1q = 3, + .adpt_eq = 48, + .amp_red = 7, + .ttlcr0 = 0x00000400, + }, +}; + +static void lynx_10g_cdr_lock_check(struct lynx_lane *lane) +{ + u32 tcsr3 = lynx_lane_read(lane, LNaTCSR3); + + if (tcsr3 & LNaTCSR3_CDR_LCK) + return; + + dev_dbg(&lane->phy->dev, + "Lane %c CDR unlocked, resetting receiver...\n", + 'A' + lane->id); + + lynx_lane_rmw(lane, LNaGCR0, LNaGCR0_RRST_ON, LNaGCR0_RRST); + usleep_range(1, 2); + lynx_lane_rmw(lane, LNaGCR0, LNaGCR0_RRST_OFF, LNaGCR0_RRST); + + usleep_range(1, 2); +} + +static void lynx_10g_pll_read_configuration(struct lynx_pll *pll) +{ + u32 val; + + val = lynx_pll_read(pll, PLLnCR0); + pll->frate_sel = FIELD_GET(PLLnCR0_FRATE_SEL, val); + pll->refclk_sel = FIELD_GET(PLLnCR0_REFCLK_SEL, val); + pll->enabled = !(val & PLLnCR0_POFF); + pll->locked = !!(val & PLLnCR0_PLL_LCK); + + if (!pll->enabled) + return; + + switch (pll->frate_sel) { + case PLLnCR0_FRATE_5G: + /* 5GHz clock net */ + __set_bit(LANE_MODE_1000BASEX_SGMII, pll->supported); + __set_bit(LANE_MODE_QSGMII, pll->supported); + break; + case PLLnCR0_FRATE_3_125G: + __set_bit(LANE_MODE_2500BASEX, pll->supported); + break; + case PLLnCR0_FRATE_5_15625G: + /* 10.3125GHz clock net */ + __set_bit(LANE_MODE_10GBASER, pll->supported); + __set_bit(LANE_MODE_USXGMII, pll->supported); + __set_bit(LANE_MODE_10G_QXGMII, pll->supported); + break; + default: + break; + } +} + +/* On LS1028A, SGMIIA_CFG, SGMIIB_CFG, and SGMIIC_CFG from PCCR8 have the + * ability to map either an ENETC PCS (PCCR8_SGMIIa_CFG=2) or a Felix switch + * PCS (PCCR8_SGMIIa_CFG=1) to the same lane. + * + * On LS1088A, the same QSGMII PCS B can be connected to SerDes lane 1 + * (PCCR9_QSGMIIa_CFG=1) or to lane 3 (PCCR9_QSGMIIa_CFG=2). + * + * The PHY API lacks the capability to distinguish anything about the consumer, + * so we don't support changing the initial muxing done by the RCW. + * + * However, after disabling a PCS through PCCR8, we need to properly restore + * the original value to keep the same muxing, and for that we need to back + * it up (here). + */ +static void lynx_10g_backup_pccr_val(struct lynx_lane *lane) +{ + u32 val; + int err; + + if (lane->mode == LANE_MODE_UNKNOWN) + return; + + err = lynx_pccr_read(lane, lane->mode, &val); + if (err) { + dev_warn(&lane->phy->dev, + "The driver doesn't know how to access the PCCR for lane mode %s\n", + lynx_lane_mode_str(lane->mode)); + lane->mode = LANE_MODE_UNKNOWN; + return; + } + + lane->default_pccr[lane->mode] = val; + + /* 1000Base-X, 1000Base-KX, 2500Base-KX and SGMII use the same PCCR8. + * Only the KX bit differs (set for 1000Base-KX). Since we back up PCCR + * values per lane mode, make sure to not back up the PCCR8 value with + * the KX bit set for the non-KX modes, if the lane was in KX mode at + * boot time. Just preserve bits 2:0, which tell whether the (and + * which) 1G PCS was enabled. + */ + switch (lane->mode) { + case LANE_MODE_1000BASEX_SGMII: + case LANE_MODE_2500BASEX: + lane->default_pccr[LANE_MODE_1000BASEX_SGMII] = val & ~PCCR8_SGMIIa_KX; + lane->default_pccr[LANE_MODE_2500BASEX] = val & ~PCCR8_SGMIIa_KX; + break; + default: + break; + } +} + +/* Is the PCS enabled, according to the value backed up from the PCCR register + * for this lane mode? + * + * Normally we'd need to ask "what lane mode are we talking about?", but the + * answer is invariably the same regardless - PCCR8_SGMIIa_CFG has the same + * layout as PCCR9_QSGMIIa_CFG, PCCRB_XFIa_CFG etc etc, and the value 0 + * universally means "PCS disabled". So this is just a shorthand answer. + */ +static bool lynx_10g_pccr_val_enabled(u32 pccr) +{ + return FIELD_PREP(PCCR8_SGMIIa_CFG, pccr) != 0; +} + +static bool lynx_10g_lane_is_3_125g(struct lynx_lane *lane) +{ + struct lynx_priv *priv = lane->priv; + struct lynx_pll *pll; + u32 gcr0; + + gcr0 = lynx_lane_read(lane, LNaGCR0); + + if (gcr0 & LNaGCR0_TPLL_PLLF) + pll = &priv->pll[0]; + else + pll = &priv->pll[1]; + + if (pll->frate_sel != PLLnCR0_FRATE_3_125G) + return false; + + if (FIELD_GET(LNaGCR0_TRAT_SEL, gcr0) != RAT_SEL_FULL || + FIELD_GET(LNaGCR0_RRAT_SEL, gcr0) != RAT_SEL_FULL) + return false; + + return true; +} + +static void lynx_10g_lane_read_configuration(struct lynx_lane *lane) +{ + u32 pssr0 = lynx_lane_read(lane, LNaPSSR0); + struct lynx_priv *priv = lane->priv; + int proto; + + proto = FIELD_GET(LNaPSSR0_TYPE, pssr0); + switch (proto) { + case PROTO_SEL_SGMII_BASEX_KX_QSGMII: + if (lynx_10g_lane_is_3_125g(lane)) + lane->mode = LANE_MODE_2500BASEX; + else if (FIELD_GET(LNaPSSR0_IS_QUAD, pssr0)) + lane->mode = LANE_MODE_QSGMII; + else + lane->mode = LANE_MODE_1000BASEX_SGMII; + break; + case PROTO_SEL_XFI_10GBASER_KR_SXGMII: + if (FIELD_GET(LNaPSSR0_IS_QUAD, pssr0)) + lane->mode = LANE_MODE_10G_QXGMII; + else if (priv->info->quirks & LYNX_QUIRK_HAS_HARDCODED_USXGMII) + lane->mode = LANE_MODE_USXGMII; + else + lane->mode = LANE_MODE_10GBASER; + break; + case PROTO_SEL_PCIE: + case PROTO_SEL_SATA: + case PROTO_SEL_XAUI: + break; + default: + dev_warn(&lane->phy->dev, "Unknown lane protocol 0x%x\n", + proto); + } + + lynx_10g_backup_pccr_val(lane); +} + +static int ls1028a_get_pccr(enum lynx_lane_mode lane_mode, int lane, + struct lynx_pccr *pccr) +{ + switch (lane_mode) { + case LANE_MODE_1000BASEX_SGMII: + case LANE_MODE_2500BASEX: + pccr->offset = PCCR8; + pccr->width = 4; + pccr->shift = SGMII_CFG(lane); + break; + case LANE_MODE_QSGMII: + if (lane != 1) + return -EINVAL; + + pccr->offset = PCCR9; + pccr->width = 3; + pccr->shift = QSGMII_CFG(A); + break; + case LANE_MODE_10G_QXGMII: + if (lane != 1) + return -EINVAL; + + pccr->offset = PCCR9; + pccr->width = 3; + pccr->shift = QXGMII_CFG(A); + break; + case LANE_MODE_USXGMII: + if (lane != 0) + return -EINVAL; + + pccr->offset = PCCRB; + pccr->width = 3; + pccr->shift = SXGMII_CFG(A); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int ls1028a_get_pcvt_offset(int lane, enum lynx_lane_mode mode) +{ + switch (mode) { + case LANE_MODE_1000BASEX_SGMII: + case LANE_MODE_2500BASEX: + return SGMIIaCR0(lane); + case LANE_MODE_QSGMII: + return lane == 1 ? QSGMIIaCR0(A) : -EINVAL; + case LANE_MODE_USXGMII: + return lane == 0 ? SXGMIIaCR0(A) : -EINVAL; + case LANE_MODE_10G_QXGMII: + return lane == 1 ? QXGMIIaCR0(A) : -EINVAL; + default: + return -EINVAL; + } +} + +static const struct lynx_info lynx_info_ls1028a = { + .get_pccr = ls1028a_get_pccr, + .get_pcvt_offset = ls1028a_get_pcvt_offset, + .pll_read_configuration = lynx_10g_pll_read_configuration, + .lane_read_configuration = lynx_10g_lane_read_configuration, + .cdr_lock_check = lynx_10g_cdr_lock_check, + .num_lanes = 4, + .index = 1, + .quirks = LYNX_QUIRK_HAS_HARDCODED_USXGMII, +}; + +static int ls1046a_serdes1_get_pccr(enum lynx_lane_mode lane_mode, int lane, + struct lynx_pccr *pccr) +{ + switch (lane_mode) { + case LANE_MODE_1000BASEX_SGMII: + case LANE_MODE_2500BASEX: + pccr->offset = PCCR8; + pccr->width = 4; + pccr->shift = SGMII_CFG(lane); + break; + case LANE_MODE_QSGMII: + if (lane != 1) + return -EINVAL; + + pccr->offset = PCCR9; + pccr->width = 3; + pccr->shift = QSGMII_CFG(B); + break; + case LANE_MODE_10GBASER: + switch (lane) { + case 2: + pccr->shift = XFI_CFG(A); + break; + case 3: + pccr->shift = XFI_CFG(B); + break; + default: + return -EINVAL; + } + + pccr->offset = PCCRB; + pccr->width = 3; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int ls1046a_serdes1_get_pcvt_offset(int lane, enum lynx_lane_mode mode) +{ + switch (mode) { + case LANE_MODE_1000BASEX_SGMII: + case LANE_MODE_2500BASEX: + return SGMIIaCR0(lane); + case LANE_MODE_QSGMII: + if (lane != 1) + return -EINVAL; + + return QSGMIIaCR0(B); + case LANE_MODE_10GBASER: + switch (lane) { + case 2: + return XFIaCR0(A); + case 3: + return XFIaCR0(B); + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static const struct lynx_info lynx_info_ls1046a_serdes1 = { + .get_pccr = ls1046a_serdes1_get_pccr, + .get_pcvt_offset = ls1046a_serdes1_get_pcvt_offset, + .pll_read_configuration = lynx_10g_pll_read_configuration, + .lane_read_configuration = lynx_10g_lane_read_configuration, + .cdr_lock_check = lynx_10g_cdr_lock_check, + .num_lanes = 4, + .index = 1, +}; + +static int ls1046a_serdes2_get_pccr(enum lynx_lane_mode lane_mode, int lane, + struct lynx_pccr *pccr) +{ + switch (lane_mode) { + case LANE_MODE_1000BASEX_SGMII: + case LANE_MODE_2500BASEX: + if (lane != 1) + return -EINVAL; + + pccr->offset = PCCR8; + pccr->width = 4; + pccr->shift = SGMII_CFG(B); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int ls1046a_serdes2_get_pcvt_offset(int lane, enum lynx_lane_mode mode) +{ + switch (mode) { + case LANE_MODE_1000BASEX_SGMII: + case LANE_MODE_2500BASEX: + if (lane != 1) + return -EINVAL; + + return SGMIIaCR0(B); + default: + return -EINVAL; + } +} + +static const struct lynx_info lynx_info_ls1046a_serdes2 = { + .get_pccr = ls1046a_serdes2_get_pccr, + .get_pcvt_offset = ls1046a_serdes2_get_pcvt_offset, + .pll_read_configuration = lynx_10g_pll_read_configuration, + .lane_read_configuration = lynx_10g_lane_read_configuration, + .cdr_lock_check = lynx_10g_cdr_lock_check, + .num_lanes = 4, + .index = 2, +}; + +static int ls1088a_serdes1_get_pccr(enum lynx_lane_mode lane_mode, int lane, + struct lynx_pccr *pccr) +{ + switch (lane_mode) { + case LANE_MODE_1000BASEX_SGMII: + pccr->offset = PCCR8; + pccr->width = 4; + pccr->shift = SGMII_CFG(lane); + break; + case LANE_MODE_QSGMII: + switch (lane) { + case 0: + pccr->shift = QSGMII_CFG(A); + break; + case 1: + case 3: + pccr->shift = QSGMII_CFG(B); + break; + default: + return -EINVAL; + } + + pccr->offset = PCCR9; + pccr->width = 3; + break; + case LANE_MODE_10GBASER: + switch (lane) { + case 2: + pccr->shift = XFI_CFG(A); + break; + case 3: + pccr->shift = XFI_CFG(B); + break; + default: + return -EINVAL; + } + + pccr->offset = PCCRB; + pccr->width = 3; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int ls1088a_serdes1_get_pcvt_offset(int lane, enum lynx_lane_mode mode) +{ + switch (mode) { + case LANE_MODE_1000BASEX_SGMII: + return SGMIIaCR0(lane); + case LANE_MODE_QSGMII: + switch (lane) { + case 0: + return QSGMIIaCR0(A); + case 1: + case 3: + return QSGMIIaCR0(B); + default: + return -EINVAL; + } + case LANE_MODE_10GBASER: + switch (lane) { + case 2: + return XFIaCR0(A); + case 3: + return XFIaCR0(B); + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static const struct lynx_info lynx_info_ls1088a_serdes1 = { + .get_pccr = ls1088a_serdes1_get_pccr, + .get_pcvt_offset = ls1088a_serdes1_get_pcvt_offset, + .pll_read_configuration = lynx_10g_pll_read_configuration, + .lane_read_configuration = lynx_10g_lane_read_configuration, + .cdr_lock_check = lynx_10g_cdr_lock_check, + .num_lanes = 4, + .index = 1, +}; + +static int ls2088a_serdes1_get_pccr(enum lynx_lane_mode lane_mode, int lane, + struct lynx_pccr *pccr) +{ + switch (lane_mode) { + case LANE_MODE_1000BASEX_SGMII: + case LANE_MODE_2500BASEX: + pccr->offset = PCCR8; + pccr->width = 4; + pccr->shift = SGMII_CFG(lane); + break; + case LANE_MODE_QSGMII: + switch (lane) { + case 2: + case 6: + pccr->shift = QSGMII_CFG(A); + break; + case 7: + pccr->shift = QSGMII_CFG(B); + break; + case 0: + case 4: + pccr->shift = QSGMII_CFG(C); + break; + case 1: + case 5: + pccr->shift = QSGMII_CFG(D); + break; + default: + return -EINVAL; + } + + pccr->offset = PCCR9; + pccr->width = 3; + break; + case LANE_MODE_10GBASER: + pccr->offset = PCCRB; + pccr->width = 3; + pccr->shift = XFI_CFG(lane); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int ls2088a_serdes1_get_pcvt_offset(int lane, enum lynx_lane_mode mode) +{ + switch (mode) { + case LANE_MODE_1000BASEX_SGMII: + case LANE_MODE_2500BASEX: + return SGMIIaCR0(lane); + case LANE_MODE_QSGMII: + switch (lane) { + case 2: + case 6: + return QSGMIIaCR0(A); + case 7: + return QSGMIIaCR0(B); + case 0: + case 4: + return QSGMIIaCR0(C); + case 1: + case 5: + return QSGMIIaCR0(D); + default: + return -EINVAL; + } + case LANE_MODE_10GBASER: + return XFIaCR0(lane); + default: + return -EINVAL; + } +} + +static const struct lynx_info lynx_info_ls2088a_serdes1 = { + .get_pccr = ls2088a_serdes1_get_pccr, + .get_pcvt_offset = ls2088a_serdes1_get_pcvt_offset, + .pll_read_configuration = lynx_10g_pll_read_configuration, + .lane_read_configuration = lynx_10g_lane_read_configuration, + .cdr_lock_check = lynx_10g_cdr_lock_check, + .num_lanes = 8, + .index = 1, +}; + +static int ls2088a_serdes2_get_pccr(enum lynx_lane_mode lane_mode, int lane, + struct lynx_pccr *pccr) +{ + switch (lane_mode) { + case LANE_MODE_1000BASEX_SGMII: + case LANE_MODE_2500BASEX: + pccr->offset = PCCR8; + pccr->width = 4; + pccr->shift = SGMII_CFG(lane); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int ls2088a_serdes2_get_pcvt_offset(int lane, enum lynx_lane_mode mode) +{ + switch (mode) { + case LANE_MODE_1000BASEX_SGMII: + case LANE_MODE_2500BASEX: + return SGMIIaCR0(lane); + default: + return -EINVAL; + } +} + +static const struct lynx_info lynx_info_ls2088a_serdes2 = { + .get_pccr = ls2088a_serdes2_get_pccr, + .get_pcvt_offset = ls2088a_serdes2_get_pcvt_offset, + .pll_read_configuration = lynx_10g_pll_read_configuration, + .lane_read_configuration = lynx_10g_lane_read_configuration, + .cdr_lock_check = lynx_10g_cdr_lock_check, + .num_lanes = 8, + .index = 2, +}; + +/* Halting puts the lane in a mode in which it can be reconfigured */ +static void lynx_10g_lane_halt(struct phy *phy) +{ + struct lynx_lane *lane = phy_get_drvdata(phy); + + /* Issue a reset request */ + lynx_lane_rmw(lane, LNaGCR0, + LNaGCR0_RRST_ON | LNaGCR0_TRST_ON, + LNaGCR0_RRST | LNaGCR0_TRST); + + /* The RM says to wait for at least 50ns */ + usleep_range(1, 2); +} + +static void lynx_10g_lane_reset(struct phy *phy) +{ + struct lynx_lane *lane = phy_get_drvdata(phy); + + /* Finalize the reset request */ + lynx_lane_rmw(lane, LNaGCR0, + LNaGCR0_RRST_OFF | LNaGCR0_TRST_OFF, + LNaGCR0_RRST | LNaGCR0_TRST); +} + +static int lynx_10g_power_off(struct phy *phy) +{ + struct lynx_lane *lane = phy_get_drvdata(phy); + + if (!lane->powered_up) + return 0; + + /* Issue a reset request with the power down bits set */ + lynx_lane_rmw(lane, LNaGCR0, + LNaGCR0_RRST_ON | LNaGCR0_TRST_ON | + LNaGCR0_RX_PD | LNaGCR0_TX_PD, + LNaGCR0_RRST | LNaGCR0_TRST | + LNaGCR0_RX_PD | LNaGCR0_TX_PD); + + /* The RM says to wait for at least 50ns */ + usleep_range(1, 2); + + lane->powered_up = false; + + return 0; +} + +static int lynx_10g_power_on(struct phy *phy) +{ + struct lynx_lane *lane = phy_get_drvdata(phy); + + if (lane->powered_up) + return 0; + + /* RM says that to enable a previously powered down lane, set + * LNmGCR0[{R,T}X_PD]=0, wait 15 us, then set LNmGCR0[{R,T}RST]=1. + */ + lynx_lane_rmw(lane, LNaGCR0, 0, LNaGCR0_RX_PD | LNaGCR0_TX_PD); + usleep_range(150, 300); + lynx_10g_lane_reset(phy); + + lane->powered_up = true; + + return 0; +} + +static void lynx_10g_lane_set_nrate(struct lynx_lane *lane, + struct lynx_pll *pll, + enum lynx_lane_mode mode) +{ + enum lynx_10g_rat_sel nrate; + + switch (pll->frate_sel) { + case PLLnCR0_FRATE_5G: + switch (mode) { + case LANE_MODE_1000BASEX_SGMII: + nrate = RAT_SEL_QUARTER; + break; + case LANE_MODE_QSGMII: + nrate = RAT_SEL_FULL; + break; + default: + return; + } + break; + case PLLnCR0_FRATE_3_125G: + switch (mode) { + case LANE_MODE_2500BASEX: + nrate = RAT_SEL_FULL; + break; + default: + return; + } + break; + case PLLnCR0_FRATE_5_15625G: + switch (mode) { + case LANE_MODE_10GBASER: + case LANE_MODE_USXGMII: + case LANE_MODE_10G_QXGMII: + nrate = RAT_SEL_DOUBLE; + break; + default: + return; + } + break; + default: + return; + } + + lynx_lane_rmw(lane, LNaGCR0, + FIELD_PREP(LNaGCR0_TRAT_SEL, nrate) | + FIELD_PREP(LNaGCR0_RRAT_SEL, nrate), + LNaGCR0_RRAT_SEL | LNaGCR0_TRAT_SEL); +} + +static void lynx_10g_lane_set_pll(struct lynx_lane *lane, + struct lynx_pll *pll) +{ + if (pll->id == 0) { + lynx_lane_rmw(lane, LNaGCR0, + LNaGCR0_RPLL_PLLF | LNaGCR0_TPLL_PLLF, + LNaGCR0_RPLL_MSK | LNaGCR0_TPLL_MSK); + } else { + lynx_lane_rmw(lane, LNaGCR0, + LNaGCR0_RPLL_PLLS | LNaGCR0_TPLL_PLLS, + LNaGCR0_RPLL_MSK | LNaGCR0_TPLL_MSK); + } +} + +static void lynx_10g_lane_remap_pll(struct lynx_lane *lane, + enum lynx_lane_mode lane_mode) +{ + struct lynx_priv *priv = lane->priv; + struct lynx_pll *pll; + + /* Switch to the PLL that works with this interface type */ + pll = lynx_pll_get(priv, lane_mode); + if (unlikely(!pll)) + return; + + lynx_10g_lane_set_pll(lane, pll); + + /* Choose the portion of clock net to be used on this lane */ + lynx_10g_lane_set_nrate(lane, pll, lane_mode); +} + +static void lynx_10g_lane_change_proto_conf(struct lynx_lane *lane, + enum lynx_lane_mode mode) +{ + const struct lynx_10g_proto_conf *conf = &lynx_10g_proto_conf[mode]; + + lynx_lane_rmw(lane, LNaGCR0, + FIELD_PREP(LNaGCR0_PROTS, conf->proto_sel) | + FIELD_PREP(LNaGCR0_IF20BIT_EN, conf->if20bit_en), + LNaGCR0_PROTS | LNaGCR0_IF20BIT_EN); + lynx_lane_rmw(lane, LNaGCR1, + FIELD_PREP(LNaGCR1_REIDL_TH, conf->reidl_th) | + FIELD_PREP(LNaGCR1_REIDL_ET_MSB, conf->reidl_et_msb) | + FIELD_PREP(LNaGCR1_REIDL_ET_SEL, conf->reidl_et_sel) | + FIELD_PREP(LNaGCR1_REIDL_EX_MSB, conf->reidl_ex_msb) | + FIELD_PREP(LNaGCR1_REIDL_EX_SEL, conf->reidl_ex_sel) | + FIELD_PREP(LNaGCR1_ISLEW_RCTL, conf->islew_rctl) | + FIELD_PREP(LNaGCR1_OSLEW_RCTL, conf->oslew_rctl), + LNaGCR1_REIDL_TH | + LNaGCR1_REIDL_ET_MSB | LNaGCR1_REIDL_ET_SEL | + LNaGCR1_REIDL_EX_MSB | LNaGCR1_REIDL_EX_SEL | + LNaGCR1_ISLEW_RCTL | LNaGCR1_OSLEW_RCTL); + lynx_lane_rmw(lane, LNaRECR0, + FIELD_PREP(LNaRECR0_RXEQ_BST, conf->rxeq_bst) | + FIELD_PREP(LNaRECR0_GK2OVD, conf->gk2ovd) | + FIELD_PREP(LNaRECR0_GK3OVD, conf->gk3ovd) | + FIELD_PREP(LNaRECR0_GK2OVD_EN, conf->gk2ovd_en) | + FIELD_PREP(LNaRECR0_GK3OVD_EN, conf->gk3ovd_en) | + FIELD_PREP(LNaRECR0_BASE_WAND, conf->base_wand), + LNaRECR0_RXEQ_BST | LNaRECR0_GK2OVD | LNaRECR0_GK3OVD | + LNaRECR0_GK2OVD_EN | LNaRECR0_GK3OVD_EN | + LNaRECR0_BASE_WAND); + lynx_lane_rmw(lane, LNaTECR0, + FIELD_PREP(LNaTECR0_TEQ_TYPE, conf->teq_type) | + FIELD_PREP(LNaTECR0_SGN_PREQ, conf->sgn_preq) | + FIELD_PREP(LNaTECR0_RATIO_PREQ, conf->ratio_preq) | + FIELD_PREP(LNaTECR0_SGN_POST1Q, conf->sgn_post1q) | + FIELD_PREP(LNaTECR0_RATIO_PST1Q, conf->ratio_post1q) | + FIELD_PREP(LNaTECR0_ADPT_EQ, conf->adpt_eq) | + FIELD_PREP(LNaTECR0_AMP_RED, conf->amp_red), + LNaTECR0_TEQ_TYPE | LNaTECR0_SGN_PREQ | + LNaTECR0_RATIO_PREQ | LNaTECR0_SGN_POST1Q | + LNaTECR0_RATIO_PST1Q | LNaTECR0_ADPT_EQ | + LNaTECR0_AMP_RED); + lynx_lane_write(lane, LNaTTLCR0, conf->ttlcr0); +} + +static int lynx_10g_lane_disable_pcvt(struct lynx_lane *lane, + enum lynx_lane_mode mode) +{ + struct lynx_priv *priv = lane->priv; + int err; + + spin_lock(&priv->pcc_lock); + + err = lynx_pccr_write(lane, mode, 0); + if (err) + goto out; + + switch (mode) { + case LANE_MODE_1000BASEX_SGMII: + case LANE_MODE_2500BASEX: + err = lynx_pcvt_rmw(lane, mode, CR(1), SGMIIaCR1_SGPCS_DIS, + SGMIIaCR1_SGPCS_EN); + if (err) + goto out; + + lynx_pcvt_rmw(lane, mode, CR(0), + SGMIIaCR0_RST_SGM_ON | SGMIIaCR0_PD_SGM, + SGMIIaCR0_RST_SGM | SGMIIaCR0_PD_SGM); + break; + case LANE_MODE_QSGMII: + err = lynx_pcvt_rmw(lane, mode, CR(0), + QSGMIIaCR0_RST_QSGM_ON | QSGMIIaCR0_PD_QSGM, + QSGMIIaCR0_RST_QSGM | QSGMIIaCR0_PD_QSGM); + if (err) + goto out; + break; + default: + err = 0; + } + +out: + spin_unlock(&priv->pcc_lock); + + return err; +} + +static int lynx_10g_lane_enable_pcvt(struct lynx_lane *lane, + enum lynx_lane_mode mode) +{ + struct lynx_priv *priv = lane->priv; + u32 val; + int err; + + spin_lock(&priv->pcc_lock); + + switch (mode) { + case LANE_MODE_1000BASEX_SGMII: + case LANE_MODE_2500BASEX: + err = lynx_pcvt_rmw(lane, mode, CR(1), SGMIIaCR1_SGPCS_EN, + SGMIIaCR1_SGPCS_EN); + if (err) + goto out; + + lynx_pcvt_rmw(lane, mode, CR(0), SGMIIaCR0_RST_SGM_OFF, + SGMIIaCR0_RST_SGM | SGMIIaCR0_PD_SGM); + break; + case LANE_MODE_QSGMII: + err = lynx_pcvt_rmw(lane, mode, CR(0), QSGMIIaCR0_RST_QSGM_OFF, + QSGMIIaCR0_RST_QSGM | QSGMIIaCR0_PD_QSGM); + if (err) + goto out; + break; + default: + err = 0; + } + + /* If the PCS was enabled at boot time, use the backed up PCCR value to + * re-enable it here, to preserve the muxing. + */ + if (lynx_10g_pccr_val_enabled(lane->default_pccr[mode])) { + err = lynx_pccr_write(lane, mode, lane->default_pccr[mode]); + goto out; + } + + /* If the PCS was not enabled, set the PCCR to a default value which + * enables it (1). The assumption is that this is the only PCS <-> + * SerDes lane muxing value possible. + * + * This is mostly useful for SGMII <-> 10GBase-R major protocol + * reconfiguration, where at boot time, either the SGMII or the + * 10GBase-R PCS is enabled for the lane, but not both. + * + * In fact, if there are multiple lane muxing options, this function + * will most likely not choose the right one. For correct functionality + * there, we assume that the PCS we are enabling here was found enabled + * at boot time (reset default, or through PBL, or...), and we preserve + * its muxing through the default_pccr branch above. + */ + val = 0; + + switch (mode) { + case LANE_MODE_1000BASEX_SGMII: + case LANE_MODE_2500BASEX: + val |= FIELD_PREP(PCCR8_SGMIIa_CFG, 1); + break; + case LANE_MODE_QSGMII: + val |= FIELD_PREP(PCCR9_QSGMIIa_CFG, 1); + break; + case LANE_MODE_10G_QXGMII: + val |= FIELD_PREP(PCCR9_QXGMIIa_CFG, 1); + break; + case LANE_MODE_10GBASER: + val |= FIELD_PREP(PCCRB_XFIa_CFG, 1); + break; + case LANE_MODE_USXGMII: + val |= FIELD_PREP(PCCRB_SXGMIIa_CFG, 1); + break; + default: + err = 0; + goto out; + } + + err = lynx_pccr_write(lane, mode, val); +out: + spin_unlock(&priv->pcc_lock); + + return err; +} + +static bool lynx_10g_lane_mode_needs_rcw_override(struct lynx_lane *lane, + enum lynx_lane_mode new) +{ + enum lynx_lane_mode curr = lane->mode; + + /* Major protocol changes, which involve changing the PCS connection to + * the GMII MAC with the one to the XGMII MAC, require an RCW override + * procedure to reconfigure an internal mux, as documented here: + * https://lore.kernel.org/linux-phy/20230810102631.bvozjer3t67r67iy@skbuf/ + * This is SoC-specific, and not yet implemented in drivers/soc/fsl/guts.c. + * + * So the supported set of protocols depends on the initial lane mode. + * + * Minor protocol changes (SGMII <-> 1000Base-X <-> 2500Base-X or + * 10GBase-R <-> USXGMII) are supported. + */ + if ((lynx_lane_mode_uses_gmii_mac(curr) && + lynx_lane_mode_uses_xgmii_mac(new)) || + (lynx_lane_mode_uses_xgmii_mac(curr) && + lynx_lane_mode_uses_gmii_mac(new))) + return true; + + return false; +} + +static int lynx_10g_validate(struct phy *phy, enum phy_mode mode, int submode, + union phy_configure_opts *opts) +{ + struct lynx_lane *lane = phy_get_drvdata(phy); + enum lynx_lane_mode lane_mode; + int err; + + err = lynx_phy_mode_to_lane_mode(phy, mode, submode, &lane_mode); + if (err) + return err; + + if (lynx_10g_lane_mode_needs_rcw_override(lane, lane_mode)) + return -EINVAL; + + return 0; +} + +static int lynx_10g_set_mode(struct phy *phy, enum phy_mode mode, int submode) +{ + struct lynx_lane *lane = phy_get_drvdata(phy); + bool powered_up = lane->powered_up; + enum lynx_lane_mode lane_mode; + int err; + + err = lynx_10g_validate(phy, mode, submode, NULL); + if (err) + return err; + + lane_mode = phy_interface_to_lane_mode(submode); + /* lynx_10g_validate() already made sure the lane_mode is supported */ + + if (lane_mode == lane->mode) + return 0; + + /* If the lane is powered up, put the lane into the halt state while + * the reconfiguration is being done. + */ + if (powered_up) + lynx_10g_lane_halt(phy); + + err = lynx_10g_lane_disable_pcvt(lane, lane->mode); + if (err) + goto out; + + lynx_10g_lane_change_proto_conf(lane, lane_mode); + lynx_10g_lane_remap_pll(lane, lane_mode); + WARN_ON(lynx_10g_lane_enable_pcvt(lane, lane_mode)); + + lane->mode = lane_mode; + +out: + if (powered_up) { + /* The RM says to wait for at least 120 ns */ + usleep_range(1, 2); + lynx_10g_lane_reset(phy); + } + + return err; +} + +static int lynx_10g_init(struct phy *phy) +{ + struct lynx_lane *lane = phy_get_drvdata(phy); + + /* Mark the fact that the lane was init */ + lane->init = true; + + /* SerDes lanes are powered on at boot time. Any lane that is + * managed by this driver will get powered off when its consumer + * calls phy_init(). + */ + lane->powered_up = true; + lynx_10g_power_off(phy); + + return 0; +} + +static int lynx_10g_exit(struct phy *phy) +{ + struct lynx_lane *lane = phy_get_drvdata(phy); + + /* The lane returns to the state where it isn't managed by the + * consumer, so we must treat is as if it isn't initialized, and always + * powered on. + */ + lane->init = false; + lane->powered_up = false; + lynx_10g_power_on(phy); + + return 0; +} + +static const struct phy_ops lynx_10g_ops = { + .init = lynx_10g_init, + .exit = lynx_10g_exit, + .power_on = lynx_10g_power_on, + .power_off = lynx_10g_power_off, + .set_mode = lynx_10g_set_mode, + .validate = lynx_10g_validate, + .owner = THIS_MODULE, +}; + +static int lynx_10g_probe(struct platform_device *pdev) +{ + return lynx_probe(pdev, of_device_get_match_data(&pdev->dev), + &lynx_10g_ops); +} + +static const struct of_device_id lynx_10g_of_match_table[] = { + { .compatible = "fsl,ls1028a-serdes", .data = &lynx_info_ls1028a }, + { .compatible = "fsl,ls1046a-serdes1", .data = &lynx_info_ls1046a_serdes1 }, + { .compatible = "fsl,ls1046a-serdes2", .data = &lynx_info_ls1046a_serdes2 }, + { .compatible = "fsl,ls1088a-serdes1", .data = &lynx_info_ls1088a_serdes1 }, + { .compatible = "fsl,ls2088a-serdes1", .data = &lynx_info_ls2088a_serdes1 }, + { .compatible = "fsl,ls2088a-serdes2", .data = &lynx_info_ls2088a_serdes2 }, + {} +}; +MODULE_DEVICE_TABLE(of, lynx_10g_of_match_table); + +static struct platform_driver lynx_10g_driver = { + .probe = lynx_10g_probe, + .remove = lynx_remove, + .driver = { + .name = "lynx-10g", + .of_match_table = lynx_10g_of_match_table, + }, +}; +module_platform_driver(lynx_10g_driver); + +MODULE_IMPORT_NS("PHY_FSL_LYNX"); +MODULE_AUTHOR("Ioana Ciornei <ioana.ciornei@nxp.com>"); +MODULE_AUTHOR("Vladimir Oltean <vladimir.oltean@nxp.com>"); +MODULE_DESCRIPTION("Lynx 10G SerDes PHY driver for Layerscape SoCs"); +MODULE_LICENSE("GPL"); diff --git a/drivers/phy/freescale/phy-fsl-lynx-28g.c b/drivers/phy/freescale/phy-fsl-lynx-28g.c index 63427fc34e268..38afcd081a2a7 100644 --- a/drivers/phy/freescale/phy-fsl-lynx-28g.c +++ b/drivers/phy/freescale/phy-fsl-lynx-28g.c @@ -9,8 +9,9 @@ #include <linux/platform_device.h> #include <linux/workqueue.h> +#include "phy-fsl-lynx-core.h" + #define LYNX_28G_NUM_LANE 8 -#define LYNX_28G_NUM_PLL 2 /* SoC IP wrapper for protocol converters */ #define PCC8 0x10a0 @@ -41,8 +42,8 @@ /* Per PLL registers */ #define PLLnRSTCTL(pll) (0x400 + (pll) * 0x100 + 0x0) -#define PLLnRSTCTL_DIS(rstctl) (((rstctl) & BIT(24)) >> 24) -#define PLLnRSTCTL_LOCK(rstctl) (((rstctl) & BIT(23)) >> 23) +#define PLLnRSTCTL_DIS BIT(24) +#define PLLnRSTCTL_LOCK BIT(23) #define PLLnCR0(pll) (0x400 + (pll) * 0x100 + 0x4) #define PLLnCR0_REFCLK_SEL GENMASK(20, 16) @@ -57,6 +58,7 @@ #define PLLnCR1_FRATE_5G_10GVCO 0x0 #define PLLnCR1_FRATE_5G_25GVCO 0x10 #define PLLnCR1_FRATE_10G_20GVCO 0x6 +#define PLLnCR1_FRATE_12G_25GVCO 0x16 /* Per SerDes lane registers */ /* Lane a General Control Register */ @@ -64,15 +66,19 @@ #define LNaGCR0_PROTO_SEL GENMASK(7, 3) #define LNaGCR0_PROTO_SEL_SGMII 0x1 #define LNaGCR0_PROTO_SEL_XFI 0xa +#define LNaGCR0_PROTO_SEL_25G 0x1a #define LNaGCR0_IF_WIDTH GENMASK(2, 0) #define LNaGCR0_IF_WIDTH_10_BIT 0x0 #define LNaGCR0_IF_WIDTH_20_BIT 0x2 +#define LNaGCR0_IF_WIDTH_40_BIT 0x4 /* Lane a Tx Reset Control Register */ #define LNaTRSTCTL(lane) (0x800 + (lane) * 0x100 + 0x20) -#define LNaTRSTCTL_HLT_REQ BIT(27) -#define LNaTRSTCTL_RST_DONE BIT(30) #define LNaTRSTCTL_RST_REQ BIT(31) +#define LNaTRSTCTL_RST_DONE BIT(30) +#define LNaTRSTCTL_HLT_REQ BIT(27) +#define LNaTRSTCTL_STP_REQ BIT(26) +#define LNaTRSTCTL_DIS BIT(24) /* Lane a Tx General Control Register */ #define LNaTGCR0(lane) (0x800 + (lane) * 0x100 + 0x24) @@ -83,6 +89,7 @@ #define LNaTGCR0_N_RATE_FULL 0x0 #define LNaTGCR0_N_RATE_HALF 0x1 #define LNaTGCR0_N_RATE_QUARTER 0x2 +#define LNaTGCR0_N_RATE_DOUBLE 0x3 #define LNaTECR0(lane) (0x800 + (lane) * 0x100 + 0x30) #define LNaTECR0_EQ_TYPE GENMASK(30, 28) @@ -98,9 +105,11 @@ /* Lane a Rx Reset Control Register */ #define LNaRRSTCTL(lane) (0x800 + (lane) * 0x100 + 0x40) -#define LNaRRSTCTL_HLT_REQ BIT(27) -#define LNaRRSTCTL_RST_DONE BIT(30) #define LNaRRSTCTL_RST_REQ BIT(31) +#define LNaRRSTCTL_RST_DONE BIT(30) +#define LNaRRSTCTL_HLT_REQ BIT(27) +#define LNaRRSTCTL_STP_REQ BIT(26) +#define LNaRRSTCTL_DIS BIT(24) #define LNaRRSTCTL_CDR_LOCK BIT(12) /* Lane a Rx General Control Register */ @@ -112,6 +121,7 @@ #define LNaRGCR0_N_RATE_FULL 0x0 #define LNaRGCR0_N_RATE_HALF 0x1 #define LNaRGCR0_N_RATE_QUARTER 0x2 +#define LNaRGCR0_N_RATE_DOUBLE 0x3 #define LNaRGCR1(lane) (0x800 + (lane) * 0x100 + 0x48) #define LNaRGCR1_RX_ORD_ELECIDLE BIT(31) @@ -249,6 +259,23 @@ #define CR(x) ((x) * 4) +#define LYNX_28G_LANE_HALT_SLEEP_US 100 +#define LYNX_28G_LANE_HALT_TIMEOUT_US 1000000 + +#define LYNX_28G_LANE_RESET_SLEEP_US 100 +#define LYNX_28G_LANE_RESET_TIMEOUT_US 1000000 + +#define LYNX_28G_LANE_STOP_SLEEP_US 100 +#define LYNX_28G_LANE_STOP_TIMEOUT_US 1000000 + +#define lynx_28g_lane_rmw lynx_lane_rmw +#define lynx_28g_lane_read lynx_lane_read +#define lynx_28g_lane_write lynx_lane_write + +#define lynx_28g_priv lynx_priv +#define lynx_28g_lane lynx_lane +#define lynx_28g_pll lynx_pll + enum lynx_28g_eq_type { EQ_TYPE_NO_EQ = 0, EQ_TYPE_2TAP = 1, @@ -264,14 +291,6 @@ enum lynx_28g_proto_sel { PROTO_SEL_25G_50G_100G = 0x1a, }; -enum lynx_lane_mode { - LANE_MODE_UNKNOWN, - LANE_MODE_1000BASEX_SGMII, - LANE_MODE_10GBASER, - LANE_MODE_USXGMII, - LANE_MODE_MAX, -}; - struct lynx_28g_proto_conf { /* LNaGCR0 */ int proto_sel; @@ -407,144 +426,48 @@ static const struct lynx_28g_proto_conf lynx_28g_proto_conf[LANE_MODE_MAX] = { .ttlcr0 = LNaTTLCR0_TTL_SLO_PM_BYP | LNaTTLCR0_DATA_IN_SSC, }, + [LANE_MODE_25GBASER] = { + .proto_sel = LNaGCR0_PROTO_SEL_25G, + .if_width = LNaGCR0_IF_WIDTH_40_BIT, + .teq_type = EQ_TYPE_3TAP, + .sgn_preq = 1, + .ratio_preq = 2, + .sgn_post1q = 1, + .ratio_post1q = 7, + .amp_red = 0, + .adpt_eq = 48, + .enter_idle_flt_sel = 0, + .exit_idle_flt_sel = 0, + .data_lost_th_sel = 0, + .gk2ovd = 0, + .gk3ovd = 0, + .gk4ovd = 5, + .gk2ovd_en = 0, + .gk3ovd_en = 0, + .gk4ovd_en = 1, + .eq_offset_ovd = 0x1f, + .eq_offset_ovd_en = 0, + .eq_offset_rng_dbl = 1, + .eq_blw_sel = 1, + .eq_boost = 2, + .spare_in = 3, + .smp_autoz_d1r = 2, + .smp_autoz_eg1r = 2, + .rccr0 = LNaRCCR0_CAL_EN | + LNaRCCR0_CAL_DC3_DIS | + LNaRCCR0_CAL_DC2_DIS | + LNaRCCR0_CAL_DC1_DIS | + LNaRCCR0_CAL_DC0_DIS, + .ttlcr0 = LNaTTLCR0_DATA_IN_SSC | + FIELD_PREP_CONST(LNaTTLCR0_CDR_MIN_SMP_ON, 1), + }, }; -struct lynx_pccr { - int offset; - int width; - int shift; -}; - -struct lynx_28g_priv; - -struct lynx_28g_pll { - struct lynx_28g_priv *priv; - u32 rstctl, cr0, cr1; - int id; - DECLARE_BITMAP(supported, LANE_MODE_MAX); -}; - -struct lynx_28g_lane { - struct lynx_28g_priv *priv; - struct phy *phy; - bool powered_up; - bool init; - unsigned int id; - enum lynx_lane_mode mode; -}; - -struct lynx_28g_priv { - void __iomem *base; - struct device *dev; - /* Serialize concurrent access to registers shared between lanes, - * like PCCn - */ - spinlock_t pcc_lock; - struct lynx_28g_pll pll[LYNX_28G_NUM_PLL]; - struct lynx_28g_lane lane[LYNX_28G_NUM_LANE]; - - struct delayed_work cdr_check; -}; - -static void lynx_28g_rmw(struct lynx_28g_priv *priv, unsigned long off, - u32 val, u32 mask) -{ - void __iomem *reg = priv->base + off; - u32 orig, tmp; - - orig = ioread32(reg); - tmp = orig & ~mask; - tmp |= val; - iowrite32(tmp, reg); -} - -#define lynx_28g_read(priv, off) \ - ioread32((priv)->base + (off)) -#define lynx_28g_write(priv, off, val) \ - iowrite32(val, (priv)->base + (off)) -#define lynx_28g_lane_rmw(lane, reg, val, mask) \ - lynx_28g_rmw((lane)->priv, reg(lane->id), val, mask) -#define lynx_28g_lane_read(lane, reg) \ - ioread32((lane)->priv->base + reg((lane)->id)) -#define lynx_28g_lane_write(lane, reg, val) \ - iowrite32(val, (lane)->priv->base + reg((lane)->id)) -#define lynx_28g_pll_read(pll, reg) \ - ioread32((pll)->priv->base + reg((pll)->id)) - -static const char *lynx_lane_mode_str(enum lynx_lane_mode lane_mode) -{ - switch (lane_mode) { - case LANE_MODE_1000BASEX_SGMII: - return "1000Base-X/SGMII"; - case LANE_MODE_10GBASER: - return "10GBase-R"; - case LANE_MODE_USXGMII: - return "USXGMII"; - default: - return "unknown"; - } -} - -static enum lynx_lane_mode phy_interface_to_lane_mode(phy_interface_t intf) -{ - switch (intf) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_1000BASEX: - return LANE_MODE_1000BASEX_SGMII; - case PHY_INTERFACE_MODE_10GBASER: - return LANE_MODE_10GBASER; - case PHY_INTERFACE_MODE_USXGMII: - return LANE_MODE_USXGMII; - default: - return LANE_MODE_UNKNOWN; - } -} - -static bool lynx_28g_supports_lane_mode(struct lynx_28g_priv *priv, - enum lynx_lane_mode mode) -{ - int i; - - for (i = 0; i < LYNX_28G_NUM_PLL; i++) { - if (PLLnRSTCTL_DIS(priv->pll[i].rstctl)) - continue; - - if (test_bit(mode, priv->pll[i].supported)) - return true; - } - - return false; -} - -static struct lynx_28g_pll *lynx_28g_pll_get(struct lynx_28g_priv *priv, - enum lynx_lane_mode mode) -{ - struct lynx_28g_pll *pll; - int i; - - for (i = 0; i < LYNX_28G_NUM_PLL; i++) { - pll = &priv->pll[i]; - - if (PLLnRSTCTL_DIS(pll->rstctl)) - continue; - - if (test_bit(mode, pll->supported)) - return pll; - } - - /* no pll supports requested mode, either caller forgot to check - * lynx_28g_supports_lane_mode, or this is a bug. - */ - dev_WARN_ONCE(priv->dev, 1, "no pll for lane mode %s\n", - lynx_lane_mode_str(mode)); - return NULL; -} - static void lynx_28g_lane_set_nrate(struct lynx_28g_lane *lane, struct lynx_28g_pll *pll, enum lynx_lane_mode lane_mode) { - switch (FIELD_GET(PLLnCR1_FRATE_SEL, pll->cr1)) { + switch (pll->frate_sel) { case PLLnCR1_FRATE_5G_10GVCO: case PLLnCR1_FRATE_5G_25GVCO: switch (lane_mode) { @@ -575,6 +498,20 @@ static void lynx_28g_lane_set_nrate(struct lynx_28g_lane *lane, break; } break; + case PLLnCR1_FRATE_12G_25GVCO: + switch (lane_mode) { + case LANE_MODE_25GBASER: + lynx_28g_lane_rmw(lane, LNaTGCR0, + FIELD_PREP(LNaTGCR0_N_RATE, LNaTGCR0_N_RATE_DOUBLE), + LNaTGCR0_N_RATE); + lynx_28g_lane_rmw(lane, LNaRGCR0, + FIELD_PREP(LNaRGCR0_N_RATE, LNaRGCR0_N_RATE_DOUBLE), + LNaRGCR0_N_RATE); + break; + default: + break; + } + break; default: break; } @@ -600,13 +537,39 @@ static void lynx_28g_lane_set_pll(struct lynx_28g_lane *lane, } } -static int lynx_28g_power_off(struct phy *phy) +static bool lynx_28g_lane_halt_done(struct lynx_28g_lane *lane) { - struct lynx_28g_lane *lane = phy_get_drvdata(phy); - u32 trstctl, rrstctl; + u32 trstctl = lynx_28g_lane_read(lane, LNaTRSTCTL); + u32 rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL); - if (!lane->powered_up) - return 0; + return !(trstctl & LNaTRSTCTL_HLT_REQ) && + !(rrstctl & LNaRRSTCTL_HLT_REQ); +} + +static bool lynx_28g_lane_stop_done(struct lynx_28g_lane *lane) +{ + u32 trstctl = lynx_28g_lane_read(lane, LNaTRSTCTL); + u32 rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL); + + return !(trstctl & LNaTRSTCTL_STP_REQ) && + !(rrstctl & LNaRRSTCTL_STP_REQ); +} + +static bool lynx_28g_lane_reset_done(struct lynx_28g_lane *lane) +{ + u32 trstctl = lynx_28g_lane_read(lane, LNaTRSTCTL); + u32 rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL); + + return (trstctl & LNaTRSTCTL_RST_DONE) && + (rrstctl & LNaRRSTCTL_RST_DONE); +} + +/* Halting puts the lane in a mode in which it can be reconfigured */ +static int lynx_28g_lane_halt(struct phy *phy) +{ + struct lynx_28g_lane *lane = phy_get_drvdata(phy); + bool done; + int err; /* Issue a halt request */ lynx_28g_lane_rmw(lane, LNaTRSTCTL, LNaTRSTCTL_HLT_REQ, @@ -615,11 +578,73 @@ static int lynx_28g_power_off(struct phy *phy) LNaRRSTCTL_HLT_REQ); /* Wait until the halting process is complete */ - do { - trstctl = lynx_28g_lane_read(lane, LNaTRSTCTL); - rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL); - } while ((trstctl & LNaTRSTCTL_HLT_REQ) || - (rrstctl & LNaRRSTCTL_HLT_REQ)); + err = read_poll_timeout(lynx_28g_lane_halt_done, done, done, + LYNX_28G_LANE_HALT_SLEEP_US, + LYNX_28G_LANE_HALT_TIMEOUT_US, + false, lane); + if (err) { + dev_err(&phy->dev, "Lane %c halt failed: %pe\n", + 'A' + lane->id, ERR_PTR(err)); + } + + return err; +} + +static int lynx_28g_lane_reset(struct phy *phy) +{ + struct lynx_28g_lane *lane = phy_get_drvdata(phy); + bool done; + int err; + + /* Issue a reset request on the lane */ + lynx_28g_lane_rmw(lane, LNaTRSTCTL, LNaTRSTCTL_RST_REQ, + LNaTRSTCTL_RST_REQ); + lynx_28g_lane_rmw(lane, LNaRRSTCTL, LNaRRSTCTL_RST_REQ, + LNaRRSTCTL_RST_REQ); + + /* Wait until the reset sequence is completed */ + err = read_poll_timeout(lynx_28g_lane_reset_done, done, done, + LYNX_28G_LANE_RESET_SLEEP_US, + LYNX_28G_LANE_RESET_TIMEOUT_US, + false, lane); + if (err) { + dev_err(&phy->dev, "Lane %c reset failed: %pe\n", + 'A' + lane->id, ERR_PTR(err)); + } + + return err; +} + +static int lynx_28g_power_off(struct phy *phy) +{ + struct lynx_28g_lane *lane = phy_get_drvdata(phy); + bool done; + int err; + + if (!lane->powered_up) + return 0; + + /* Issue a stop request */ + lynx_28g_lane_rmw(lane, LNaTRSTCTL, LNaTRSTCTL_STP_REQ, + LNaTRSTCTL_STP_REQ); + lynx_28g_lane_rmw(lane, LNaRRSTCTL, LNaRRSTCTL_STP_REQ, + LNaRRSTCTL_STP_REQ); + + /* Wait until the stop process is complete */ + err = read_poll_timeout(lynx_28g_lane_stop_done, done, done, + LYNX_28G_LANE_STOP_SLEEP_US, + LYNX_28G_LANE_STOP_TIMEOUT_US, + false, lane); + if (err) { + dev_err(&phy->dev, "Lane %c stop failed: %pe\n", + 'A' + lane->id, ERR_PTR(err)); + } + + /* Power down the RX and TX portions of the lane */ + lynx_28g_lane_rmw(lane, LNaRRSTCTL, LNaRRSTCTL_DIS, + LNaRRSTCTL_DIS); + lynx_28g_lane_rmw(lane, LNaTRSTCTL, LNaTRSTCTL_DIS, + LNaTRSTCTL_DIS); lane->powered_up = false; @@ -629,29 +654,29 @@ static int lynx_28g_power_off(struct phy *phy) static int lynx_28g_power_on(struct phy *phy) { struct lynx_28g_lane *lane = phy_get_drvdata(phy); - u32 trstctl, rrstctl; + int err; if (lane->powered_up) return 0; - /* Issue a reset request on the lane */ - lynx_28g_lane_rmw(lane, LNaTRSTCTL, LNaTRSTCTL_RST_REQ, - LNaTRSTCTL_RST_REQ); - lynx_28g_lane_rmw(lane, LNaRRSTCTL, LNaRRSTCTL_RST_REQ, - LNaRRSTCTL_RST_REQ); + /* Power up the RX and TX portions of the lane */ + lynx_28g_lane_rmw(lane, LNaRRSTCTL, 0, LNaRRSTCTL_DIS); + lynx_28g_lane_rmw(lane, LNaTRSTCTL, 0, LNaTRSTCTL_DIS); - /* Wait until the reset sequence is completed */ - do { - trstctl = lynx_28g_lane_read(lane, LNaTRSTCTL); - rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL); - } while (!(trstctl & LNaTRSTCTL_RST_DONE) || - !(rrstctl & LNaRRSTCTL_RST_DONE)); + err = lynx_28g_lane_reset(phy); + if (err) + return err; lane->powered_up = true; return 0; } +static int lynx_28g_e25g_pcvt(int lane) +{ + return 7 - lane; +} + static int lynx_28g_get_pccr(enum lynx_lane_mode lane_mode, int lane, struct lynx_pccr *pccr) { @@ -667,6 +692,11 @@ static int lynx_28g_get_pccr(enum lynx_lane_mode lane_mode, int lane, pccr->width = 4; pccr->shift = SXGMII_CFG(lane); break; + case LANE_MODE_25GBASER: + pccr->offset = PCCD; + pccr->width = 4; + pccr->shift = E25G_CFG(lynx_28g_e25g_pcvt(lane)); + break; default: return -EOPNOTSUPP; } @@ -682,108 +712,107 @@ static int lynx_28g_get_pcvt_offset(int lane, enum lynx_lane_mode lane_mode) case LANE_MODE_USXGMII: case LANE_MODE_10GBASER: return SXGMIIaCR0(lane); + case LANE_MODE_25GBASER: + return E25GaCR0(lynx_28g_e25g_pcvt(lane)); default: return -EOPNOTSUPP; } } -static int lynx_pccr_read(struct lynx_28g_lane *lane, enum lynx_lane_mode mode, - u32 *val) +static bool lx2160a_serdes1_lane_supports_mode(int lane, + enum lynx_lane_mode mode) { - struct lynx_28g_priv *priv = lane->priv; - struct lynx_pccr pccr; - u32 tmp; - int err; - - err = lynx_28g_get_pccr(mode, lane->id, &pccr); - if (err) - return err; - - tmp = lynx_28g_read(priv, pccr.offset); - *val = (tmp >> pccr.shift) & GENMASK(pccr.width - 1, 0); - - return 0; + switch (mode) { + case LANE_MODE_25GBASER: + return lane != 2 && lane != 3; + default: + return true; + } } -static int lynx_pccr_write(struct lynx_28g_lane *lane, - enum lynx_lane_mode lane_mode, u32 val) +static bool lx2160a_serdes2_lane_supports_mode(int lane, + enum lynx_lane_mode mode) { - struct lynx_28g_priv *priv = lane->priv; - struct lynx_pccr pccr; - u32 old, tmp, mask; - int err; - - err = lynx_28g_get_pccr(lane_mode, lane->id, &pccr); - if (err) - return err; - - old = lynx_28g_read(priv, pccr.offset); - mask = GENMASK(pccr.width - 1, 0) << pccr.shift; - tmp = (old & ~mask) | (val << pccr.shift); - lynx_28g_write(priv, pccr.offset, tmp); - - dev_dbg(&lane->phy->dev, "PCCR@0x%x: 0x%x -> 0x%x\n", - pccr.offset, old, tmp); - - return 0; + switch (mode) { + case LANE_MODE_1000BASEX_SGMII: + return true; + case LANE_MODE_USXGMII: + case LANE_MODE_10GBASER: + return lane == 6 || lane == 7; + default: + return false; + } } -static int lynx_pcvt_read(struct lynx_28g_lane *lane, - enum lynx_lane_mode lane_mode, int cr, u32 *val) +static bool lx2160a_serdes3_lane_supports_mode(int lane, + enum lynx_lane_mode mode) { - struct lynx_28g_priv *priv = lane->priv; - int offset; - - offset = lynx_28g_get_pcvt_offset(lane->id, lane_mode); - if (offset < 0) - return offset; - - *val = lynx_28g_read(priv, offset + cr); - - return 0; + /* + * Non-networking SerDes, and this driver supports only + * networking protocols + */ + return false; } -static int lynx_pcvt_write(struct lynx_28g_lane *lane, - enum lynx_lane_mode lane_mode, int cr, u32 val) +static bool lx2162a_serdes1_lane_supports_mode(int lane, + enum lynx_lane_mode mode) { - struct lynx_28g_priv *priv = lane->priv; - int offset; - - offset = lynx_28g_get_pcvt_offset(lane->id, lane_mode); - if (offset < 0) - return offset; + return true; +} - lynx_28g_write(priv, offset + cr, val); +static bool lx2162a_serdes2_lane_supports_mode(int lane, + enum lynx_lane_mode mode) +{ + return lx2160a_serdes2_lane_supports_mode(lane, mode); +} - return 0; +/* Feature set is not expected to grow for the deprecated compatible string */ +static bool lynx_28g_compat_lane_supports_mode(int lane, + enum lynx_lane_mode mode) +{ + switch (mode) { + case LANE_MODE_1000BASEX_SGMII: + case LANE_MODE_USXGMII: + case LANE_MODE_10GBASER: + return true; + default: + return false; + } } -static int lynx_pcvt_rmw(struct lynx_28g_lane *lane, - enum lynx_lane_mode lane_mode, - int cr, u32 val, u32 mask) +static void lynx_28g_cdr_lock_check(struct lynx_lane *lane) { + u32 rrstctl; int err; - u32 tmp; - err = lynx_pcvt_read(lane, lane_mode, cr, &tmp); - if (err) - return err; + rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL); + if (!!(rrstctl & LNaRRSTCTL_CDR_LOCK)) + return; - tmp &= ~mask; - tmp |= val; + lynx_28g_lane_rmw(lane, LNaRRSTCTL, LNaRRSTCTL_RST_REQ, + LNaRRSTCTL_RST_REQ); - return lynx_pcvt_write(lane, lane_mode, cr, tmp); + err = read_poll_timeout(lynx_28g_lane_read, rrstctl, + !!(rrstctl & LNaRRSTCTL_RST_DONE), + LYNX_28G_LANE_RESET_SLEEP_US, + LYNX_28G_LANE_RESET_TIMEOUT_US, + false, lane, LNaRRSTCTL); + if (err) { + dev_warn_once(&lane->phy->dev, + "Lane %c receiver reset failed: %pe\n", + 'A' + lane->id, ERR_PTR(err)); + } } -static void lynx_28g_lane_remap_pll(struct lynx_28g_lane *lane, +static void lynx_28g_lane_remap_pll(struct lynx_lane *lane, enum lynx_lane_mode lane_mode) { - struct lynx_28g_priv *priv = lane->priv; - struct lynx_28g_pll *pll; + struct lynx_priv *priv = lane->priv; + struct lynx_pll *pll; /* Switch to the PLL that works with this interface type */ - pll = lynx_28g_pll_get(priv, lane_mode); - if (unlikely(pll == NULL)) + pll = lynx_pll_get(priv, lane_mode); + if (unlikely(!pll)) return; lynx_28g_lane_set_pll(lane, pll); @@ -925,6 +954,9 @@ static int lynx_28g_lane_enable_pcvt(struct lynx_28g_lane *lane, case LANE_MODE_USXGMII: val |= PCCC_SXGMIIn_CFG; break; + case LANE_MODE_25GBASER: + val |= PCCD_E25Gn_CFG; + break; default: break; } @@ -936,23 +968,22 @@ static int lynx_28g_lane_enable_pcvt(struct lynx_28g_lane *lane, return err; } +static int lynx_28g_validate(struct phy *phy, enum phy_mode mode, int submode, + union phy_configure_opts *opts) +{ + return lynx_phy_mode_to_lane_mode(phy, mode, submode, NULL); +} + static int lynx_28g_set_mode(struct phy *phy, enum phy_mode mode, int submode) { - struct lynx_28g_lane *lane = phy_get_drvdata(phy); - struct lynx_28g_priv *priv = lane->priv; + struct lynx_lane *lane = phy_get_drvdata(phy); int powered_up = lane->powered_up; enum lynx_lane_mode lane_mode; - int err = 0; - - if (mode != PHY_MODE_ETHERNET) - return -EOPNOTSUPP; - - if (lane->mode == LANE_MODE_UNKNOWN) - return -EOPNOTSUPP; + int err; - lane_mode = phy_interface_to_lane_mode(submode); - if (!lynx_28g_supports_lane_mode(priv, lane_mode)) - return -EOPNOTSUPP; + err = lynx_phy_mode_to_lane_mode(phy, mode, submode, &lane_mode); + if (err) + return err; if (lane_mode == lane->mode) return 0; @@ -960,8 +991,11 @@ static int lynx_28g_set_mode(struct phy *phy, enum phy_mode mode, int submode) /* If the lane is powered up, put the lane into the halt state while * the reconfiguration is being done. */ - if (powered_up) - lynx_28g_power_off(phy); + if (powered_up) { + err = lynx_28g_lane_halt(phy); + if (err) + goto out; + } err = lynx_28g_lane_disable_pcvt(lane, lane->mode); if (err) @@ -975,28 +1009,11 @@ static int lynx_28g_set_mode(struct phy *phy, enum phy_mode mode, int submode) out: if (powered_up) - lynx_28g_power_on(phy); + lynx_28g_lane_reset(phy); return err; } -static int lynx_28g_validate(struct phy *phy, enum phy_mode mode, int submode, - union phy_configure_opts *opts __always_unused) -{ - struct lynx_28g_lane *lane = phy_get_drvdata(phy); - struct lynx_28g_priv *priv = lane->priv; - enum lynx_lane_mode lane_mode; - - if (mode != PHY_MODE_ETHERNET) - return -EOPNOTSUPP; - - lane_mode = phy_interface_to_lane_mode(submode); - if (!lynx_28g_supports_lane_mode(priv, lane_mode)) - return -EOPNOTSUPP; - - return 0; -} - static int lynx_28g_init(struct phy *phy) { struct lynx_28g_lane *lane = phy_get_drvdata(phy); @@ -1014,8 +1031,25 @@ static int lynx_28g_init(struct phy *phy) return 0; } +static int lynx_28g_exit(struct phy *phy) +{ + struct lynx_28g_lane *lane = phy_get_drvdata(phy); + + /* The lane returns to the state where it isn't managed by the + * consumer, so we must treat is as if it isn't initialized, and + * always powered on. + */ + lane->init = false; + lane->powered_up = false; + + lynx_28g_power_on(phy); + + return 0; +} + static const struct phy_ops lynx_28g_ops = { .init = lynx_28g_init, + .exit = lynx_28g_exit, .power_on = lynx_28g_power_on, .power_off = lynx_28g_power_off, .set_mode = lynx_28g_set_mode, @@ -1023,75 +1057,42 @@ static const struct phy_ops lynx_28g_ops = { .owner = THIS_MODULE, }; -static void lynx_28g_pll_read_configuration(struct lynx_28g_priv *priv) +static void lynx_28g_pll_read_configuration(struct lynx_pll *pll) { - struct lynx_28g_pll *pll; - int i; - - for (i = 0; i < LYNX_28G_NUM_PLL; i++) { - pll = &priv->pll[i]; - pll->priv = priv; - pll->id = i; - - pll->rstctl = lynx_28g_pll_read(pll, PLLnRSTCTL); - pll->cr0 = lynx_28g_pll_read(pll, PLLnCR0); - pll->cr1 = lynx_28g_pll_read(pll, PLLnCR1); - - if (PLLnRSTCTL_DIS(pll->rstctl)) - continue; - - switch (FIELD_GET(PLLnCR1_FRATE_SEL, pll->cr1)) { - case PLLnCR1_FRATE_5G_10GVCO: - case PLLnCR1_FRATE_5G_25GVCO: - /* 5GHz clock net */ - __set_bit(LANE_MODE_1000BASEX_SGMII, pll->supported); - break; - case PLLnCR1_FRATE_10G_20GVCO: - /* 10.3125GHz clock net */ - __set_bit(LANE_MODE_10GBASER, pll->supported); - __set_bit(LANE_MODE_USXGMII, pll->supported); - break; - default: - /* 6GHz, 12.890625GHz, 8GHz */ - break; - } - } -} - -#define work_to_lynx(w) container_of((w), struct lynx_28g_priv, cdr_check.work) - -static void lynx_28g_cdr_lock_check(struct work_struct *work) -{ - struct lynx_28g_priv *priv = work_to_lynx(work); - struct lynx_28g_lane *lane; - u32 rrstctl; - int i; + u32 val; - for (i = 0; i < LYNX_28G_NUM_LANE; i++) { - lane = &priv->lane[i]; - if (!lane->phy) - continue; + val = lynx_pll_read(pll, PLLnRSTCTL); + pll->enabled = !(val & PLLnRSTCTL_DIS); + pll->locked = !!(val & PLLnRSTCTL_LOCK); - mutex_lock(&lane->phy->mutex); + val = lynx_pll_read(pll, PLLnCR0); + pll->refclk_sel = FIELD_GET(PLLnCR0_REFCLK_SEL, val); - if (!lane->init || !lane->powered_up) { - mutex_unlock(&lane->phy->mutex); - continue; - } + val = lynx_pll_read(pll, PLLnCR1); + pll->frate_sel = FIELD_GET(PLLnCR1_FRATE_SEL, val); - rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL); - if (!(rrstctl & LNaRRSTCTL_CDR_LOCK)) { - lynx_28g_lane_rmw(lane, LNaRRSTCTL, LNaRRSTCTL_RST_REQ, - LNaRRSTCTL_RST_REQ); - do { - rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL); - } while (!(rrstctl & LNaRRSTCTL_RST_DONE)); - } + if (!pll->enabled) + return; - mutex_unlock(&lane->phy->mutex); + switch (pll->frate_sel) { + case PLLnCR1_FRATE_5G_10GVCO: + case PLLnCR1_FRATE_5G_25GVCO: + /* 5GHz clock net */ + __set_bit(LANE_MODE_1000BASEX_SGMII, pll->supported); + break; + case PLLnCR1_FRATE_10G_20GVCO: + /* 10.3125GHz clock net */ + __set_bit(LANE_MODE_10GBASER, pll->supported); + __set_bit(LANE_MODE_USXGMII, pll->supported); + break; + case PLLnCR1_FRATE_12G_25GVCO: + /* 12.890625GHz clock net */ + __set_bit(LANE_MODE_25GBASER, pll->supported); + break; + default: + /* 6GHz, 8GHz */ + break; } - queue_delayed_work(system_power_efficient_wq, &priv->cdr_check, - msecs_to_jiffies(1000)); } static void lynx_28g_lane_read_configuration(struct lynx_28g_lane *lane) @@ -1111,136 +1112,105 @@ static void lynx_28g_lane_read_configuration(struct lynx_28g_lane *lane) else lane->mode = LANE_MODE_USXGMII; break; + case LNaPSS_TYPE_25G: + lane->mode = LANE_MODE_25GBASER; + break; default: lane->mode = LANE_MODE_UNKNOWN; } } -static struct phy *lynx_28g_xlate(struct device *dev, - const struct of_phandle_args *args) -{ - struct lynx_28g_priv *priv = dev_get_drvdata(dev); - int idx; - - if (args->args_count == 0) - return of_phy_simple_xlate(dev, args); - else if (args->args_count != 1) - return ERR_PTR(-ENODEV); - - idx = args->args[0]; - - if (WARN_ON(idx >= LYNX_28G_NUM_LANE)) - return ERR_PTR(-EINVAL); +static const struct lynx_info lynx_info_compat = { + .get_pccr = lynx_28g_get_pccr, + .get_pcvt_offset = lynx_28g_get_pcvt_offset, + .lane_supports_mode = lynx_28g_compat_lane_supports_mode, + .pll_read_configuration = lynx_28g_pll_read_configuration, + .lane_read_configuration = lynx_28g_lane_read_configuration, + .cdr_lock_check = lynx_28g_cdr_lock_check, + .num_lanes = LYNX_28G_NUM_LANE, +}; - return priv->lane[idx].phy; -} +static const struct lynx_info lynx_info_lx2160a_serdes1 = { + .get_pccr = lynx_28g_get_pccr, + .get_pcvt_offset = lynx_28g_get_pcvt_offset, + .lane_supports_mode = lx2160a_serdes1_lane_supports_mode, + .pll_read_configuration = lynx_28g_pll_read_configuration, + .lane_read_configuration = lynx_28g_lane_read_configuration, + .cdr_lock_check = lynx_28g_cdr_lock_check, + .num_lanes = LYNX_28G_NUM_LANE, +}; -static int lynx_28g_probe_lane(struct lynx_28g_priv *priv, int id, - struct device_node *dn) -{ - struct lynx_28g_lane *lane = &priv->lane[id]; - struct phy *phy; +static const struct lynx_info lynx_info_lx2160a_serdes2 = { + .get_pccr = lynx_28g_get_pccr, + .get_pcvt_offset = lynx_28g_get_pcvt_offset, + .lane_supports_mode = lx2160a_serdes2_lane_supports_mode, + .pll_read_configuration = lynx_28g_pll_read_configuration, + .lane_read_configuration = lynx_28g_lane_read_configuration, + .cdr_lock_check = lynx_28g_cdr_lock_check, + .num_lanes = LYNX_28G_NUM_LANE, +}; - phy = devm_phy_create(priv->dev, dn, &lynx_28g_ops); - if (IS_ERR(phy)) - return PTR_ERR(phy); +static const struct lynx_info lynx_info_lx2160a_serdes3 = { + .get_pccr = lynx_28g_get_pccr, + .get_pcvt_offset = lynx_28g_get_pcvt_offset, + .lane_supports_mode = lx2160a_serdes3_lane_supports_mode, + .pll_read_configuration = lynx_28g_pll_read_configuration, + .lane_read_configuration = lynx_28g_lane_read_configuration, + .cdr_lock_check = lynx_28g_cdr_lock_check, + .num_lanes = LYNX_28G_NUM_LANE, +}; - lane->priv = priv; - lane->phy = phy; - lane->id = id; - phy_set_drvdata(phy, lane); - lynx_28g_lane_read_configuration(lane); +static const struct lynx_info lynx_info_lx2162a_serdes1 = { + .get_pccr = lynx_28g_get_pccr, + .get_pcvt_offset = lynx_28g_get_pcvt_offset, + .lane_supports_mode = lx2162a_serdes1_lane_supports_mode, + .pll_read_configuration = lynx_28g_pll_read_configuration, + .lane_read_configuration = lynx_28g_lane_read_configuration, + .cdr_lock_check = lynx_28g_cdr_lock_check, + .first_lane = 4, + .num_lanes = LYNX_28G_NUM_LANE, +}; - return 0; -} +static const struct lynx_info lynx_info_lx2162a_serdes2 = { + .get_pccr = lynx_28g_get_pccr, + .get_pcvt_offset = lynx_28g_get_pcvt_offset, + .lane_supports_mode = lx2162a_serdes2_lane_supports_mode, + .pll_read_configuration = lynx_28g_pll_read_configuration, + .lane_read_configuration = lynx_28g_lane_read_configuration, + .cdr_lock_check = lynx_28g_cdr_lock_check, + .num_lanes = LYNX_28G_NUM_LANE, +}; static int lynx_28g_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct phy_provider *provider; - struct lynx_28g_priv *priv; - struct device_node *dn; - int err; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->dev = dev; - dev_set_drvdata(dev, priv); - spin_lock_init(&priv->pcc_lock); - INIT_DELAYED_WORK(&priv->cdr_check, lynx_28g_cdr_lock_check); - - priv->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(priv->base)) - return PTR_ERR(priv->base); + const struct lynx_info *info; - lynx_28g_pll_read_configuration(priv); - - dn = dev_of_node(dev); - if (of_get_child_count(dn)) { - struct device_node *child; - - for_each_available_child_of_node(dn, child) { - u32 reg; - - /* PHY subnode name must be 'phy'. */ - if (!(of_node_name_eq(child, "phy"))) - continue; - - if (of_property_read_u32(child, "reg", ®)) { - dev_err(dev, "No \"reg\" property for %pOF\n", child); - of_node_put(child); - return -EINVAL; - } - - if (reg >= LYNX_28G_NUM_LANE) { - dev_err(dev, "\"reg\" property out of range for %pOF\n", child); - of_node_put(child); - return -EINVAL; - } - - err = lynx_28g_probe_lane(priv, reg, child); - if (err) { - of_node_put(child); - return err; - } - } - } else { - for (int i = 0; i < LYNX_28G_NUM_LANE; i++) { - err = lynx_28g_probe_lane(priv, i, NULL); - if (err) - return err; - } - } - - provider = devm_of_phy_provider_register(dev, lynx_28g_xlate); - if (IS_ERR(provider)) - return PTR_ERR(provider); - - queue_delayed_work(system_power_efficient_wq, &priv->cdr_check, - msecs_to_jiffies(1000)); - - return 0; -} - -static void lynx_28g_remove(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct lynx_28g_priv *priv = dev_get_drvdata(dev); + /* + * If we get here it means we probed on a device tree where + * "fsl,lynx-28g" wasn't the fallback, but the sole compatible string. + */ + info = of_device_get_match_data(dev); + if (info == &lynx_info_compat) + dev_warn(dev, "Please update device tree to use per-device compatible strings\n"); - cancel_delayed_work_sync(&priv->cdr_check); + return lynx_probe(pdev, info, &lynx_28g_ops); } static const struct of_device_id lynx_28g_of_match_table[] = { - { .compatible = "fsl,lynx-28g" }, + { .compatible = "fsl,lx2160a-serdes1", .data = &lynx_info_lx2160a_serdes1 }, + { .compatible = "fsl,lx2160a-serdes2", .data = &lynx_info_lx2160a_serdes2 }, + { .compatible = "fsl,lx2160a-serdes3", .data = &lynx_info_lx2160a_serdes3 }, + { .compatible = "fsl,lx2162a-serdes1", .data = &lynx_info_lx2162a_serdes1 }, + { .compatible = "fsl,lx2162a-serdes2", .data = &lynx_info_lx2162a_serdes2 }, + { .compatible = "fsl,lynx-28g", .data = &lynx_info_compat }, /* fallback, keep last */ { }, }; MODULE_DEVICE_TABLE(of, lynx_28g_of_match_table); static struct platform_driver lynx_28g_driver = { .probe = lynx_28g_probe, - .remove = lynx_28g_remove, + .remove = lynx_remove, .driver = { .name = "lynx-28g", .of_match_table = lynx_28g_of_match_table, @@ -1248,6 +1218,7 @@ static struct platform_driver lynx_28g_driver = { }; module_platform_driver(lynx_28g_driver); +MODULE_IMPORT_NS("PHY_FSL_LYNX"); MODULE_AUTHOR("Ioana Ciornei <ioana.ciornei@nxp.com>"); MODULE_DESCRIPTION("Lynx 28G SerDes PHY driver for Layerscape SoCs"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/phy/freescale/phy-fsl-lynx-core.c b/drivers/phy/freescale/phy-fsl-lynx-core.c new file mode 100644 index 0000000000000..2cfe9236ffc55 --- /dev/null +++ b/drivers/phy/freescale/phy-fsl-lynx-core.c @@ -0,0 +1,445 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* Copyright 2025-2026 NXP */ + +#include <linux/module.h> +#include <linux/platform_device.h> + +#include "phy-fsl-lynx-core.h" + +const char *lynx_lane_mode_str(enum lynx_lane_mode lane_mode) +{ + switch (lane_mode) { + case LANE_MODE_1000BASEX_SGMII: + return "1000Base-X/SGMII"; + case LANE_MODE_2500BASEX: + return "2500Base-X"; + case LANE_MODE_QSGMII: + return "QSGMII"; + case LANE_MODE_10G_QXGMII: + return "10G-QXGMII"; + case LANE_MODE_10GBASER: + return "10GBase-R"; + case LANE_MODE_USXGMII: + return "USXGMII"; + case LANE_MODE_25GBASER: + return "25GBase-R"; + default: + return "unknown"; + } +} +EXPORT_SYMBOL_NS_GPL(lynx_lane_mode_str, "PHY_FSL_LYNX"); + +enum lynx_lane_mode phy_interface_to_lane_mode(phy_interface_t intf) +{ + switch (intf) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + return LANE_MODE_1000BASEX_SGMII; + case PHY_INTERFACE_MODE_2500BASEX: + return LANE_MODE_2500BASEX; + case PHY_INTERFACE_MODE_QSGMII: + return LANE_MODE_QSGMII; + case PHY_INTERFACE_MODE_10G_QXGMII: + return LANE_MODE_10G_QXGMII; + case PHY_INTERFACE_MODE_10GBASER: + return LANE_MODE_10GBASER; + case PHY_INTERFACE_MODE_USXGMII: + return LANE_MODE_USXGMII; + case PHY_INTERFACE_MODE_25GBASER: + return LANE_MODE_25GBASER; + default: + return LANE_MODE_UNKNOWN; + } +} +EXPORT_SYMBOL_NS_GPL(phy_interface_to_lane_mode, "PHY_FSL_LYNX"); + +/* By default, assume that if we know how to get the PCCR register and + * protocol converter for a lane, that protocol is supported. + */ +static bool lynx_lane_supports_mode_default(struct lynx_lane *lane, + enum lynx_lane_mode mode) +{ + struct lynx_priv *priv = lane->priv; + struct lynx_pccr pccr; + + if (!priv->info->get_pccr || !priv->info->get_pcvt_offset) + return false; + + if (priv->info->get_pccr(mode, lane->id, &pccr) < 0) + return false; + + if (priv->info->get_pcvt_offset(lane->id, mode) < 0) + return false; + + return true; +} + +/* A lane mode is supported if we have a PLL that can provide its required + * clock net, and if there is a protocol converter for that mode on that lane. + */ +bool lynx_lane_supports_mode(struct lynx_lane *lane, enum lynx_lane_mode mode) +{ + struct lynx_priv *priv = lane->priv; + int i; + + if (priv->info->lane_supports_mode) { + if (!priv->info->lane_supports_mode(lane->id, mode)) + return false; + } else if (!lynx_lane_supports_mode_default(lane, mode)) { + return false; + } + + for (i = 0; i < LYNX_NUM_PLL; i++) { + if (!priv->pll[i].enabled) + continue; + + if (test_bit(mode, priv->pll[i].supported)) + return true; + } + + return false; +} +EXPORT_SYMBOL_NS_GPL(lynx_lane_supports_mode, "PHY_FSL_LYNX"); + +/* The quad protocols are fixed because the lane has multiple consumers, and + * one phy_set_mode_ext() affects the other consumers as well. We have no use + * case for dynamic protocol changing here, so disallow it. + */ +static enum lynx_lane_mode lynx_fixed_protocols[] = { + LANE_MODE_QSGMII, + LANE_MODE_10G_QXGMII, +}; + +static bool lynx_lane_restrict_fixed_mode_change(struct lynx_lane *lane, + enum lynx_lane_mode new) +{ + enum lynx_lane_mode curr = lane->mode; + + for (int i = 0; i < ARRAY_SIZE(lynx_fixed_protocols); i++) + if ((curr == lynx_fixed_protocols[i] || + new == lynx_fixed_protocols[i]) && + curr != new) + return true; + + return false; +} + +/* Translate the mode/submode from phy_validate() and phy_set_mode_ext() to a + * lane_mode and return 0 if it is supported and we can transition to it from + * the current lane mode, or return negative error otherwise. + */ +int lynx_phy_mode_to_lane_mode(struct phy *phy, enum phy_mode mode, + int submode, enum lynx_lane_mode *lane_mode) +{ + struct lynx_lane *lane = phy_get_drvdata(phy); + enum lynx_lane_mode tmp_lane_mode; + + /* The protocol configuration tables are incomplete for full lane + * reconfiguration from an arbitrary protocol. + */ + if (lane->mode == LANE_MODE_UNKNOWN) + return -EINVAL; + + if (mode != PHY_MODE_ETHERNET) + return -EINVAL; + + tmp_lane_mode = phy_interface_to_lane_mode(submode); + if (!lynx_lane_supports_mode(lane, tmp_lane_mode)) + return -EINVAL; + + if (lynx_lane_restrict_fixed_mode_change(lane, tmp_lane_mode)) + return -EINVAL; + + if (lane_mode) + *lane_mode = tmp_lane_mode; + + return 0; +} +EXPORT_SYMBOL_NS_GPL(lynx_phy_mode_to_lane_mode, "PHY_FSL_LYNX"); + +struct lynx_pll *lynx_pll_get(struct lynx_priv *priv, enum lynx_lane_mode mode) +{ + struct lynx_pll *pll; + int i; + + for (i = 0; i < LYNX_NUM_PLL; i++) { + pll = &priv->pll[i]; + + if (!pll->enabled) + continue; + + if (test_bit(mode, pll->supported)) + return pll; + } + + /* no pll supports requested mode, either caller forgot to check + * lynx_lane_supports_mode(), or this is a bug. + */ + dev_WARN_ONCE(priv->dev, 1, "no pll for lane mode %s\n", + lynx_lane_mode_str(mode)); + return NULL; +} +EXPORT_SYMBOL_NS_GPL(lynx_pll_get, "PHY_FSL_LYNX"); + +int lynx_pccr_read(struct lynx_lane *lane, enum lynx_lane_mode mode, u32 *val) +{ + struct lynx_priv *priv = lane->priv; + struct lynx_pccr pccr; + u32 tmp; + int err; + + err = priv->info->get_pccr(mode, lane->id, &pccr); + if (err) + return err; + + tmp = lynx_read(priv, pccr.offset); + *val = (tmp >> pccr.shift) & GENMASK(pccr.width - 1, 0); + + return 0; +} +EXPORT_SYMBOL_NS_GPL(lynx_pccr_read, "PHY_FSL_LYNX"); + +int lynx_pccr_write(struct lynx_lane *lane, enum lynx_lane_mode mode, u32 val) +{ + struct lynx_priv *priv = lane->priv; + struct lynx_pccr pccr; + u32 old, tmp, mask; + int err; + + err = priv->info->get_pccr(mode, lane->id, &pccr); + if (err) + return err; + + old = lynx_read(priv, pccr.offset); + mask = GENMASK(pccr.width - 1, 0) << pccr.shift; + tmp = (old & ~mask) | (val << pccr.shift); + lynx_write(priv, pccr.offset, tmp); + + dev_dbg(&lane->phy->dev, "PCCR@0x%x: 0x%x -> 0x%x\n", + pccr.offset, old, tmp); + + return 0; +} +EXPORT_SYMBOL_NS_GPL(lynx_pccr_write, "PHY_FSL_LYNX"); + +int lynx_pcvt_read(struct lynx_lane *lane, enum lynx_lane_mode mode, int cr, + u32 *val) +{ + struct lynx_priv *priv = lane->priv; + int offset; + + offset = priv->info->get_pcvt_offset(lane->id, mode); + if (offset < 0) + return offset; + + *val = lynx_read(priv, offset + cr); + + return 0; +} +EXPORT_SYMBOL_NS_GPL(lynx_pcvt_read, "PHY_FSL_LYNX"); + +int lynx_pcvt_write(struct lynx_lane *lane, enum lynx_lane_mode mode, int cr, + u32 val) +{ + struct lynx_priv *priv = lane->priv; + int offset; + + offset = priv->info->get_pcvt_offset(lane->id, mode); + if (offset < 0) + return offset; + + lynx_write(priv, offset + cr, val); + + return 0; +} +EXPORT_SYMBOL_NS_GPL(lynx_pcvt_write, "PHY_FSL_LYNX"); + +int lynx_pcvt_rmw(struct lynx_lane *lane, enum lynx_lane_mode mode, int cr, + u32 val, u32 mask) +{ + int err; + u32 tmp; + + err = lynx_pcvt_read(lane, mode, cr, &tmp); + if (err) + return err; + + tmp &= ~mask; + tmp |= val; + + return lynx_pcvt_write(lane, mode, cr, tmp); +} +EXPORT_SYMBOL_NS_GPL(lynx_pcvt_rmw, "PHY_FSL_LYNX"); + +#define work_to_lynx(w) container_of((w), struct lynx_priv, cdr_check.work) + +static void lynx_cdr_lock_check(struct work_struct *work) +{ + struct lynx_priv *priv = work_to_lynx(work); + struct lynx_lane *lane; + + for (int i = priv->info->first_lane; i < priv->info->num_lanes; i++) { + lane = &priv->lane[i]; + if (!lane->phy) + continue; + + mutex_lock(&lane->phy->mutex); + + if (!lane->init || !lane->powered_up) { + mutex_unlock(&lane->phy->mutex); + continue; + } + + priv->info->cdr_lock_check(lane); + + mutex_unlock(&lane->phy->mutex); + } + + queue_delayed_work(system_power_efficient_wq, &priv->cdr_check, + msecs_to_jiffies(1000)); +} + +static struct phy *lynx_xlate(struct device *dev, + const struct of_phandle_args *args) +{ + struct lynx_priv *priv = dev_get_drvdata(dev); + int idx; + + if (args->args_count == 0) + return of_phy_simple_xlate(dev, args); + else if (args->args_count != 1) + return ERR_PTR(-ENODEV); + + idx = args->args[0]; + + if (WARN_ON(idx >= priv->info->num_lanes || + idx < priv->info->first_lane)) + return ERR_PTR(-EINVAL); + + return priv->lane[idx].phy ?: ERR_PTR(-ENODEV); +} + +static int lynx_probe_lane(struct lynx_priv *priv, int id, + struct device_node *dn, + const struct phy_ops *phy_ops) +{ + struct lynx_lane *lane = &priv->lane[id]; + struct phy *phy; + + phy = devm_phy_create(priv->dev, dn, phy_ops); + if (IS_ERR(phy)) + return PTR_ERR(phy); + + lane->priv = priv; + lane->phy = phy; + lane->id = id; + phy_set_drvdata(phy, lane); + priv->info->lane_read_configuration(lane); + + return 0; +} + +int lynx_probe(struct platform_device *pdev, const struct lynx_info *info, + const struct phy_ops *phy_ops) +{ + struct device *dev = &pdev->dev; + struct phy_provider *provider; + struct device_node *dn; + struct lynx_priv *priv; + int err; + + dn = dev_of_node(dev); + if (!dn) { + dev_err(dev, "Device requires an OF node\n"); + return -EINVAL; + } + + if (!info) + return -ENODEV; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = dev; + priv->info = info; + priv->big_endian = device_property_read_bool(dev, "big-endian"); + dev_set_drvdata(dev, priv); + spin_lock_init(&priv->pcc_lock); + INIT_DELAYED_WORK(&priv->cdr_check, lynx_cdr_lock_check); + + priv->lane = devm_kcalloc(dev, priv->info->num_lanes, + sizeof(*priv->lane), GFP_KERNEL); + if (!priv->lane) + return -ENOMEM; + + priv->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + + for (int i = 0; i < LYNX_NUM_PLL; i++) { + struct lynx_pll *pll = &priv->pll[i]; + + pll->priv = priv; + pll->id = i; + priv->info->pll_read_configuration(pll); + } + + if (of_get_child_count(dn)) { + struct device_node *child; + + for_each_available_child_of_node(dn, child) { + u32 reg; + + /* PHY subnode name must be 'phy'. */ + if (!(of_node_name_eq(child, "phy"))) + continue; + + if (of_property_read_u32(child, "reg", ®)) { + dev_err(dev, "No \"reg\" property for %pOF\n", child); + of_node_put(child); + return -EINVAL; + } + + if (reg < priv->info->first_lane || reg >= priv->info->num_lanes) { + dev_err(dev, "\"reg\" property out of range for %pOF\n", child); + of_node_put(child); + return -EINVAL; + } + + err = lynx_probe_lane(priv, reg, child, phy_ops); + if (err) { + of_node_put(child); + return err; + } + } + } else { + for (int i = priv->info->first_lane; i < priv->info->num_lanes; i++) { + err = lynx_probe_lane(priv, i, NULL, phy_ops); + if (err) + return err; + } + } + + provider = devm_of_phy_provider_register(dev, lynx_xlate); + if (IS_ERR(provider)) + return PTR_ERR(provider); + + queue_delayed_work(system_power_efficient_wq, &priv->cdr_check, + msecs_to_jiffies(1000)); + + return 0; +} +EXPORT_SYMBOL_NS_GPL(lynx_probe, "PHY_FSL_LYNX"); + +void lynx_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct lynx_priv *priv = dev_get_drvdata(dev); + + cancel_delayed_work_sync(&priv->cdr_check); +} +EXPORT_SYMBOL_NS_GPL(lynx_remove, "PHY_FSL_LYNX"); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Freescale Lynx SerDes core functionality"); diff --git a/drivers/phy/freescale/phy-fsl-lynx-core.h b/drivers/phy/freescale/phy-fsl-lynx-core.h new file mode 100644 index 0000000000000..a60429ba93245 --- /dev/null +++ b/drivers/phy/freescale/phy-fsl-lynx-core.h @@ -0,0 +1,134 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright 2025-2026 NXP */ + +#ifndef _PHY_FSL_LYNX_CORE_H +#define _PHY_FSL_LYNX_CORE_H + +#include <linux/phy/phy.h> +#include <linux/phy.h> +#include <soc/fsl/phy-fsl-lynx.h> + +#define LYNX_NUM_PLL 2 +#define LYNX_QUIRK_HAS_HARDCODED_USXGMII BIT(0) + +struct lynx_priv; +struct lynx_lane; + +struct lynx_pccr { + int offset; + int width; + int shift; +}; + +struct lynx_pll { + struct lynx_priv *priv; + int id; + int refclk_sel; + int frate_sel; + bool enabled; + bool locked; + DECLARE_BITMAP(supported, LANE_MODE_MAX); +}; + +struct lynx_lane { + struct lynx_priv *priv; + struct phy *phy; + bool powered_up; + bool init; + unsigned int id; + enum lynx_lane_mode mode; + u32 default_pccr[LANE_MODE_MAX]; +}; + +struct lynx_info { + int (*get_pccr)(enum lynx_lane_mode lane_mode, int lane, + struct lynx_pccr *pccr); + int (*get_pcvt_offset)(int lane, enum lynx_lane_mode mode); + bool (*lane_supports_mode)(int lane, enum lynx_lane_mode mode); + void (*pll_read_configuration)(struct lynx_pll *pll); + void (*lane_read_configuration)(struct lynx_lane *lane); + void (*cdr_lock_check)(struct lynx_lane *lane); + int first_lane; + int num_lanes; + int index; + unsigned long quirks; +}; + +struct lynx_priv { + void __iomem *base; + struct device *dev; + const struct lynx_info *info; + /* Serialize concurrent access to registers shared between lanes, + * like PCCn + */ + spinlock_t pcc_lock; + bool big_endian; + struct lynx_pll pll[LYNX_NUM_PLL]; + struct lynx_lane *lane; + + struct delayed_work cdr_check; +}; + +static inline u32 lynx_read(struct lynx_priv *priv, unsigned long off) +{ + void __iomem *reg = priv->base + off; + + if (priv->big_endian) + return ioread32be(reg); + + return ioread32(reg); +} + +static inline void lynx_write(struct lynx_priv *priv, unsigned long off, u32 val) +{ + void __iomem *reg = priv->base + off; + + if (priv->big_endian) + return iowrite32be(val, reg); + + return iowrite32(val, reg); +} + +static inline void lynx_rmw(struct lynx_priv *priv, unsigned long off, u32 val, + u32 mask) +{ + u32 orig, tmp; + + orig = lynx_read(priv, off); + tmp = orig & ~mask; + tmp |= val; + if (orig != tmp) + lynx_write(priv, off, tmp); +} + +#define lynx_lane_rmw(lane, reg, val, mask) \ + lynx_rmw((lane)->priv, reg(lane->id), val, mask) +#define lynx_lane_read(lane, reg) \ + lynx_read((lane)->priv, reg((lane)->id)) +#define lynx_lane_write(lane, reg, val) \ + lynx_write((lane)->priv, reg((lane)->id), val) +#define lynx_pll_read(pll, reg) \ + lynx_read((pll)->priv, reg((pll)->id)) + +int lynx_probe(struct platform_device *pdev, const struct lynx_info *info, + const struct phy_ops *phy_ops); +void lynx_remove(struct platform_device *pdev); + +const char *lynx_lane_mode_str(enum lynx_lane_mode lane_mode); +enum lynx_lane_mode phy_interface_to_lane_mode(phy_interface_t intf); +bool lynx_lane_supports_mode(struct lynx_lane *lane, enum lynx_lane_mode mode); +int lynx_phy_mode_to_lane_mode(struct phy *phy, enum phy_mode mode, + int submode, enum lynx_lane_mode *lane_mode); + +struct lynx_pll *lynx_pll_get(struct lynx_priv *priv, enum lynx_lane_mode mode); + +int lynx_pccr_read(struct lynx_lane *lane, enum lynx_lane_mode mode, u32 *val); +int lynx_pccr_write(struct lynx_lane *lane, enum lynx_lane_mode mode, u32 val); +int lynx_pcvt_read(struct lynx_lane *lane, enum lynx_lane_mode mode, int cr, + u32 *val); +int lynx_pcvt_write(struct lynx_lane *lane, enum lynx_lane_mode mode, int cr, + u32 val); +int lynx_pcvt_rmw(struct lynx_lane *lane, enum lynx_lane_mode mode, int cr, + u32 val, u32 mask); + +#endif diff --git a/drivers/phy/mediatek/phy-mtk-xsphy.c b/drivers/phy/mediatek/phy-mtk-xsphy.c index c0ddb9273cc3f..cc1d66954212a 100644 --- a/drivers/phy/mediatek/phy-mtk-xsphy.c +++ b/drivers/phy/mediatek/phy-mtk-xsphy.c @@ -112,10 +112,10 @@ struct xsphy_instance { struct mtk_xsphy { struct device *dev; void __iomem *glb_base; /* only shared u3 sif */ - struct xsphy_instance **phys; - int nphys; int src_ref_clk; /* MHZ, reference clock for slew rate calibrate */ int src_coef; /* coefficient for slew rate calibrate */ + int nphys; + struct xsphy_instance *phys[] __counted_by(nphys); }; static void u2_phy_slew_rate_calibrate(struct mtk_xsphy *xsphy, @@ -515,18 +515,15 @@ static int mtk_xsphy_probe(struct platform_device *pdev) struct resource *glb_res; struct mtk_xsphy *xsphy; struct resource res; + size_t nphys; int port; - xsphy = devm_kzalloc(dev, sizeof(*xsphy), GFP_KERNEL); + nphys = of_get_child_count(np); + xsphy = devm_kzalloc(dev, struct_size(xsphy, phys, nphys), GFP_KERNEL); if (!xsphy) return -ENOMEM; - xsphy->nphys = of_get_child_count(np); - xsphy->phys = devm_kcalloc(dev, xsphy->nphys, - sizeof(*xsphy->phys), GFP_KERNEL); - if (!xsphy->phys) - return -ENOMEM; - + xsphy->nphys = nphys; xsphy->dev = dev; platform_set_drvdata(pdev, xsphy); diff --git a/drivers/phy/phy-airoha-pcie-regs.h b/drivers/phy/phy-airoha-pcie-regs.h index b938a7b468fee..58572c7937223 100644 --- a/drivers/phy/phy-airoha-pcie-regs.h +++ b/drivers/phy/phy-airoha-pcie-regs.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0-only +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2024 AIROHA Inc * Author: Lorenzo Bianconi <lorenzo@kernel.org> diff --git a/drivers/phy/phy-can-transceiver.c b/drivers/phy/phy-can-transceiver.c index 2b52e47f247a2..75dc49e75ca0e 100644 --- a/drivers/phy/phy-can-transceiver.c +++ b/drivers/phy/phy-can-transceiver.c @@ -5,12 +5,11 @@ * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com * */ -#include <linux/of.h> +#include <linux/gpio/consumer.h> #include <linux/phy/phy.h> #include <linux/platform_device.h> +#include <linux/property.h> #include <linux/module.h> -#include <linux/gpio.h> -#include <linux/gpio/consumer.h> #include <linux/mux/consumer.h> struct can_transceiver_data { @@ -97,35 +96,6 @@ static const struct can_transceiver_data tja1057_drvdata = { .flags = CAN_TRANSCEIVER_SILENT_PRESENT, }; -static const struct of_device_id can_transceiver_phy_ids[] = { - { - .compatible = "ti,tcan1042", - .data = &tcan1042_drvdata - }, - { - .compatible = "ti,tcan1043", - .data = &tcan1043_drvdata - }, - { - .compatible = "nxp,tja1048", - .data = &tja1048_drvdata - }, - { - .compatible = "nxp,tja1051", - .data = &tja1051_drvdata - }, - { - .compatible = "nxp,tja1057", - .data = &tja1057_drvdata - }, - { - .compatible = "nxp,tjr1443", - .data = &tcan1043_drvdata - }, - { } -}; -MODULE_DEVICE_TABLE(of, can_transceiver_phy_ids); - static struct phy *can_transceiver_phy_xlate(struct device *dev, const struct of_phandle_args *args) { @@ -152,19 +122,23 @@ static int can_transceiver_phy_probe(struct platform_device *pdev) struct can_transceiver_phy *can_transceiver_phy; struct can_transceiver_priv *priv; const struct can_transceiver_data *drvdata; - const struct of_device_id *match; struct phy *phy; struct gpio_desc *silent_gpio; struct gpio_desc *standby_gpio; struct gpio_desc *enable_gpio; struct mux_state *mux_state; - u32 max_bitrate = 0; - int err, i, num_ch = 1; + const char *propname; + int err, i, num_ch; + u32 max_bitrate; + + drvdata = device_get_match_data(dev); + if (!drvdata) + return -ENODEV; - match = of_match_node(can_transceiver_phy_ids, pdev->dev.of_node); - drvdata = match->data; if (drvdata->flags & CAN_TRANSCEIVER_DUAL_CH) num_ch = 2; + else + num_ch = 1; priv = devm_kzalloc(dev, struct_size(priv, can_transceiver_phy, num_ch), GFP_KERNEL); if (!priv) @@ -179,15 +153,23 @@ static int can_transceiver_phy_probe(struct platform_device *pdev) priv->mux_state = mux_state; - err = device_property_read_u32(dev, "max-bitrate", &max_bitrate); - if ((err != -EINVAL) && !max_bitrate) - dev_warn(dev, "Invalid value for transceiver max bitrate. Ignoring bitrate limit\n"); + propname = "max-bitrate"; + if (device_property_present(dev, propname)) { + err = device_property_read_u32(dev, propname, &max_bitrate); + if (err) + return dev_err_probe(dev, err, "failed to parse %s\n", propname); + + if (max_bitrate == 0) + dev_warn(dev, "Invalid value for transceiver max bitrate. Ignoring bitrate limit\n"); + } else { + max_bitrate = 0; + } for (i = 0; i < num_ch; i++) { can_transceiver_phy = &priv->can_transceiver_phy[i]; can_transceiver_phy->priv = priv; - phy = devm_phy_create(dev, dev->of_node, &can_transceiver_phy_ops); + phy = devm_phy_create(dev, NULL, &can_transceiver_phy_ops); if (IS_ERR(phy)) { dev_err(dev, "failed to create can transceiver phy\n"); return PTR_ERR(phy); @@ -231,6 +213,35 @@ static int can_transceiver_phy_probe(struct platform_device *pdev) return PTR_ERR_OR_ZERO(phy_provider); } +static const struct of_device_id can_transceiver_phy_ids[] = { + { + .compatible = "ti,tcan1042", + .data = &tcan1042_drvdata + }, + { + .compatible = "ti,tcan1043", + .data = &tcan1043_drvdata + }, + { + .compatible = "nxp,tja1048", + .data = &tja1048_drvdata + }, + { + .compatible = "nxp,tja1051", + .data = &tja1051_drvdata + }, + { + .compatible = "nxp,tja1057", + .data = &tja1057_drvdata + }, + { + .compatible = "nxp,tjr1443", + .data = &tcan1043_drvdata + }, + { } +}; +MODULE_DEVICE_TABLE(of, can_transceiver_phy_ids); + static struct platform_driver can_transceiver_phy_driver = { .probe = can_transceiver_phy_probe, .driver = { diff --git a/drivers/phy/phy-econet-pcie.c b/drivers/phy/phy-econet-pcie.c new file mode 100644 index 0000000000000..96be69d1ffeb9 --- /dev/null +++ b/drivers/phy/phy-econet-pcie.c @@ -0,0 +1,182 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Author: Caleb James DeLisle <cjd@cjdns.fr> + * Ahmed Naseef <naseefkm@gmail.com> + */ + +#include <linux/bitfield.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/phy/phy.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/bits.h> +#include <linux/delay.h> + +/* Rx detection timing for EN751221: 16*8 clock cycles */ +#define EN751221_RXDET_VAL 16 + +/* Rx detection timing when in power mode 3 */ +#define EN75_RXDET_P3_REG 0xa28 +#define EN75_RXDET_P3_MASK GENMASK(17, 9) + +/* Rx detection timing when in power mode 2 */ +#define EN75_RXDET_P2_REG 0xa2c +#define EN75_RXDET_P2_MASK GENMASK(8, 0) + +/* Rx impedance */ +#define EN75_RX_IMPEDANCE_REG 0xb2c +#define EN75_RX_IMPEDANCE_MASK GENMASK(13, 12) +enum en75_rx_impedance { + EN75_RX_IMPEDANCE_100_OHM = 0, + EN75_RX_IMPEDANCE_95_OHM = 1, + EN75_RX_IMPEDANCE_90_OHM = 2, +}; + +/* PLL Invert clock */ +#define EN75_PLL_PH_INV_REG 0x4a0 +#define EN75_PLL_PH_INV_MASK BIT(5) + +struct en75_phy_op { + u32 reg; + u32 mask; + u32 val; +}; + +struct en7528_pcie_phy { + struct regmap *regmap; + const struct en75_phy_op *data; +}; + +/* Port 0 PHY: set LCDDS_CLK_PH_INV for PLL operation */ +static const struct en75_phy_op en7528_phy_gen1[] = { + { + .reg = EN75_PLL_PH_INV_REG, + .mask = EN75_PLL_PH_INV_MASK, + .val = 1, + }, + { /* sentinel */ } +}; + +/* EN7528 Port 1 PHY: Rx impedance tuning, target R -5 Ohm */ +static const struct en75_phy_op en7528_phy_gen2[] = { + { + .reg = EN75_RX_IMPEDANCE_REG, + .mask = EN75_RX_IMPEDANCE_MASK, + .val = EN75_RX_IMPEDANCE_95_OHM, + }, + { /* sentinel */ } +}; + +/* EN751221 Port 1 PHY, set RX detect to 16*8 clock cycles */ +static const struct en75_phy_op en751221_phy_gen2[] = { + { + .reg = EN75_RXDET_P3_REG, + .mask = EN75_RXDET_P3_MASK, + .val = EN751221_RXDET_VAL, + }, + { + .reg = EN75_RXDET_P2_REG, + .mask = EN75_RXDET_P2_MASK, + .val = EN751221_RXDET_VAL, + }, + { /* sentinel */ } +}; + +static int en75_pcie_phy_init(struct phy *phy) +{ + struct en7528_pcie_phy *ephy = phy_get_drvdata(phy); + const struct en75_phy_op *data = ephy->data; + int i, ret; + u32 val; + + for (i = 0; data[i].mask || data[i].val; i++) { + if (i) + usleep_range(1000, 2000); + + val = field_prep(data[i].mask, data[i].val); + + ret = regmap_update_bits(ephy->regmap, data[i].reg, + data[i].mask, val); + if (ret) + return ret; + } + + return 0; +} + +static const struct phy_ops en75_pcie_phy_ops = { + .init = en75_pcie_phy_init, + .owner = THIS_MODULE, +}; + +static int en75_pcie_phy_probe(struct platform_device *pdev) +{ + struct regmap_config regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + }; + struct device *dev = &pdev->dev; + const struct en75_phy_op *data; + struct phy_provider *provider; + struct en7528_pcie_phy *ephy; + void __iomem *base; + struct phy *phy; + int i; + + data = of_device_get_match_data(dev); + if (!data) + return -EINVAL; + + ephy = devm_kzalloc(dev, sizeof(*ephy), GFP_KERNEL); + if (!ephy) + return -ENOMEM; + + ephy->data = data; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + /* Set max_register to highest used register */ + for (i = 0; data[i].mask || data[i].val; i++) + if (data[i].reg > regmap_config.max_register) + regmap_config.max_register = data[i].reg; + + ephy->regmap = devm_regmap_init_mmio(dev, base, ®map_config); + if (IS_ERR(ephy->regmap)) + return PTR_ERR(ephy->regmap); + + phy = devm_phy_create(dev, dev->of_node, &en75_pcie_phy_ops); + if (IS_ERR(phy)) + return PTR_ERR(phy); + + phy_set_drvdata(phy, ephy); + + provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + + return PTR_ERR_OR_ZERO(provider); +} + +static const struct of_device_id en75_pcie_phy_ids[] = { + { .compatible = "econet,en7528-pcie-gen1", .data = en7528_phy_gen1 }, + { .compatible = "econet,en7528-pcie-gen2", .data = en7528_phy_gen2 }, + { .compatible = "econet,en751221-pcie-gen1", .data = en7528_phy_gen1 }, + { .compatible = "econet,en751221-pcie-gen2", .data = en751221_phy_gen2 }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, en75_pcie_phy_ids); + +static struct platform_driver en75_pcie_phy_driver = { + .probe = en75_pcie_phy_probe, + .driver = { + .name = "econet-pcie-phy", + .of_match_table = en75_pcie_phy_ids, + }, +}; +module_platform_driver(en75_pcie_phy_driver); + +MODULE_AUTHOR("Caleb James DeLisle <cjd@cjdns.fr>"); +MODULE_DESCRIPTION("EcoNet PCIe PHY driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/phy/phy-eyeq5-eth.c b/drivers/phy/phy-eyeq5-eth.c new file mode 100644 index 0000000000000..c03d77c360f74 --- /dev/null +++ b/drivers/phy/phy-eyeq5-eth.c @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <linux/auxiliary_bus.h> +#include <linux/bitfield.h> +#include <linux/bits.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/errno.h> +#include <linux/gfp_types.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/iopoll.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/phy.h> +#include <linux/phy/phy.h> +#include <linux/slab.h> +#include <linux/types.h> + +#define EQ5_PHY_COUNT 2 + +#define EQ5_PHY0_GP 0x128 +#define EQ5_PHY1_GP 0x12c +#define EQ5_PHY0_SGMII 0x134 +#define EQ5_PHY1_SGMII 0x138 + +#define EQ5_GP_TX_SWRST_DIS BIT(0) // Tx SW reset +#define EQ5_GP_TX_M_CLKE BIT(1) // Tx M clock enable +#define EQ5_GP_SYS_SWRST_DIS BIT(2) // Sys SW reset +#define EQ5_GP_SYS_M_CLKE BIT(3) // Sys clock enable +#define EQ5_GP_SGMII_MODE BIT(4) // SGMII mode +#define EQ5_GP_RGMII_DRV GENMASK(8, 5) // RGMII drive strength + +#define EQ5_SGMII_PWR_EN BIT(0) +#define EQ5_SGMII_RST_DIS BIT(1) +#define EQ5_SGMII_PLL_EN BIT(2) +#define EQ5_SGMII_SIG_DET_SW BIT(3) +#define EQ5_SGMII_PWR_STATE BIT(4) +#define EQ5_SGMII_PLL_ACK BIT(18) +#define EQ5_SGMII_PWR_STATE_ACK GENMASK(24, 20) + +/* + * Instead of storing a phy_interface_t, we store this enum. + * + * We do not deal with RGMII timings in this generic PHY driver, + * it is all handled inside the net PHY. + */ +enum eq5_phy_submode { + EQ5_PHY_SUBMODE_SGMII, + EQ5_PHY_SUBMODE_RGMII, +}; + +struct eq5_phy_inst { + struct device *dev; + struct phy *phy; + void __iomem *gp, *sgmii; + enum eq5_phy_submode submode; + bool sgmii_support; +}; + +struct eq5_phy_private { + struct eq5_phy_inst phys[EQ5_PHY_COUNT]; +}; + +static int eq5_phy_exit(struct phy *phy) +{ + struct eq5_phy_inst *inst = phy_get_drvdata(phy); + + writel(0, inst->gp); + writel(0, inst->sgmii); + udelay(5); /* settling time */ + return 0; +} + +static int eq5_phy_init(struct phy *phy) +{ + struct eq5_phy_inst *inst = phy_get_drvdata(phy); + u32 reg; + + /* + * Hardware stops listening to our instructions once it is started. + * It must be reset to reconfigure it. + */ + eq5_phy_exit(phy); + + reg = EQ5_GP_TX_SWRST_DIS | EQ5_GP_TX_M_CLKE | + EQ5_GP_SYS_SWRST_DIS | EQ5_GP_SYS_M_CLKE | + FIELD_PREP(EQ5_GP_RGMII_DRV, 0x9); + writel(reg, inst->gp); + + return 0; +} + +static int eq5_phy_power_on(struct phy *phy) +{ + struct eq5_phy_inst *inst = phy_get_drvdata(phy); + u32 reg; + + if (inst->submode == EQ5_PHY_SUBMODE_SGMII) { + writel(readl(inst->gp) | EQ5_GP_SGMII_MODE, inst->gp); + + reg = EQ5_SGMII_PWR_EN | EQ5_SGMII_RST_DIS | EQ5_SGMII_PLL_EN; + writel(reg, inst->sgmii); + + if (readl_poll_timeout(inst->sgmii, reg, + reg & EQ5_SGMII_PLL_ACK, 1, 100)) { + dev_err(inst->dev, "PLL timeout\n"); + return -ETIMEDOUT; + } + + reg = readl(inst->sgmii); + reg |= EQ5_SGMII_PWR_STATE | EQ5_SGMII_SIG_DET_SW; + writel(reg, inst->sgmii); + } else { + writel(readl(inst->gp) & ~EQ5_GP_SGMII_MODE, inst->gp); + writel(0, inst->sgmii); + } + + return 0; +} + +static int eq5_phy_power_off(struct phy *phy) +{ + struct eq5_phy_inst *inst = phy_get_drvdata(phy); + + writel(readl(inst->gp) & ~EQ5_GP_SGMII_MODE, inst->gp); + writel(0, inst->sgmii); + + return 0; +} + +static int eq5_phy_validate(struct phy *phy, enum phy_mode mode, int submode, + union phy_configure_opts *opts) +{ + struct eq5_phy_inst *inst = phy_get_drvdata(phy); + + if (mode != PHY_MODE_ETHERNET) + return -EINVAL; + + if (phy_interface_mode_is_rgmii(submode)) + return 0; + + if (inst->sgmii_support && submode == PHY_INTERFACE_MODE_SGMII) + return 0; + + return -EINVAL; +} + +static int eq5_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode) +{ + struct eq5_phy_inst *inst = phy_get_drvdata(phy); + enum eq5_phy_submode target_submode; + int ret; + + ret = eq5_phy_validate(phy, mode, submode, NULL); + if (ret) + return ret; + + if (submode == PHY_INTERFACE_MODE_SGMII) + target_submode = EQ5_PHY_SUBMODE_SGMII; + else + target_submode = EQ5_PHY_SUBMODE_RGMII; + + if (target_submode == inst->submode) + return 0; + + inst->submode = target_submode; + + if (phy->power_count) { + eq5_phy_init(phy); + return eq5_phy_power_on(phy); + } + + return 0; +} + +static const struct phy_ops eq5_phy_ops = { + .init = eq5_phy_init, + .exit = eq5_phy_exit, + .power_on = eq5_phy_power_on, + .power_off = eq5_phy_power_off, + .set_mode = eq5_phy_set_mode, + .validate = eq5_phy_validate, +}; + +static struct phy *eq5_phy_xlate(struct device *dev, + const struct of_phandle_args *args) +{ + struct eq5_phy_private *priv = dev_get_drvdata(dev); + + if (args->args_count != 1 || args->args[0] >= EQ5_PHY_COUNT) + return ERR_PTR(-EINVAL); + + return priv->phys[args->args[0]].phy; +} + +static int eq5_phy_probe_phy(struct device *dev, struct eq5_phy_private *priv, + unsigned int index, void __iomem *base, + unsigned int gp, unsigned int sgmii, + bool sgmii_support) +{ + struct eq5_phy_inst *inst = &priv->phys[index]; + struct phy *phy; + + phy = devm_phy_create(dev, dev->of_node, &eq5_phy_ops); + if (IS_ERR(phy)) + return dev_err_probe(dev, PTR_ERR(phy), + "failed to create PHY %u\n", index); + + inst->dev = dev; + inst->phy = phy; + inst->gp = base + gp; + inst->sgmii = base + sgmii; + inst->sgmii_support = sgmii_support; + phy_set_drvdata(phy, inst); + + /* + * Init inst->submode based on probe hardware state, allowing + * consumers to power us on without first setting the mode. + */ + if (sgmii_support && (readl(inst->gp) & EQ5_GP_SGMII_MODE)) + inst->submode = EQ5_PHY_SUBMODE_SGMII; + else + inst->submode = EQ5_PHY_SUBMODE_RGMII; + + return 0; +} + +static int eq5_phy_probe(struct auxiliary_device *adev, + const struct auxiliary_device_id *id) +{ + struct device *dev = &adev->dev; + struct phy_provider *provider; + struct eq5_phy_private *priv; + void __iomem *base; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + dev_set_drvdata(dev, priv); + + base = (void __iomem *)dev_get_platdata(dev); + + ret = eq5_phy_probe_phy(dev, priv, 0, base, EQ5_PHY0_GP, + EQ5_PHY0_SGMII, true); + if (ret) + return ret; + + ret = eq5_phy_probe_phy(dev, priv, 1, base, EQ5_PHY1_GP, + EQ5_PHY1_SGMII, false); + if (ret) + return ret; + + provider = devm_of_phy_provider_register(dev, eq5_phy_xlate); + if (IS_ERR(provider)) + return dev_err_probe(dev, PTR_ERR(provider), + "registering provider failed\n"); + + return 0; +} + +static const struct auxiliary_device_id eq5_phy_id_table[] = { + { .name = "clk_eyeq.phy" }, + {} +}; +MODULE_DEVICE_TABLE(auxiliary, eq5_phy_id_table); + +static struct auxiliary_driver eq5_phy_driver = { + .probe = eq5_phy_probe, + .id_table = eq5_phy_id_table, +}; +module_auxiliary_driver(eq5_phy_driver); + +MODULE_DESCRIPTION("EyeQ5 Ethernet PHY driver"); +MODULE_AUTHOR("Théo Lebrun <theo.lebrun@bootlin.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/phy/phy-nxp-ptn3222.c b/drivers/phy/phy-nxp-ptn3222.c index c6179d8701e61..6cb79b5c4fdb8 100644 --- a/drivers/phy/phy-nxp-ptn3222.c +++ b/drivers/phy/phy-nxp-ptn3222.c @@ -97,7 +97,7 @@ static int ptn3222_probe(struct i2c_client *client) } static const struct i2c_device_id ptn3222_table[] = { - { "ptn3222" }, + { .name = "ptn3222" }, { } }; MODULE_DEVICE_TABLE(i2c, ptn3222_table); diff --git a/drivers/phy/phy-nxp-tja1145.c b/drivers/phy/phy-nxp-tja1145.c new file mode 100644 index 0000000000000..1e8bd169743ab --- /dev/null +++ b/drivers/phy/phy-nxp-tja1145.c @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2025 Liebherr-Electronics and Drives GmbH + */ +#include <linux/module.h> +#include <linux/regmap.h> + +#include <linux/phy/phy.h> +#include <linux/spi/spi.h> + +#define TJA1145_MODE_CTRL 0x01 +#define TJA1145_MODE_CTRL_MC GENMASK(2, 0) +#define TJA1145_MODE_CTRL_STBY BIT(2) +#define TJA1145_MODE_CTRL_NORMAL TJA1145_MODE_CTRL_MC + +#define TJA1145_CAN_CTRL 0x20 +#define TJA1145_CAN_CTRL_CMC GENMASK(1, 0) +#define TJA1145_CAN_CTRL_ACTIVE BIT(1) + +#define TJA1145_IDENT 0x7e +#define TJA1145_IDENT_TJA1145T 0x70 + +#define TJA1145_SPI_READ_BIT BIT(0) +#define TJA1145T_MAX_BITRATE 1000000 + +static int tja1145_phy_power_on(struct phy *phy) +{ + struct regmap *map = phy_get_drvdata(phy); + int ret; + + /* + * Switch operating mode to normal which is the active operating mode. + * In this mode, the device is fully operational. + */ + ret = regmap_update_bits(map, TJA1145_MODE_CTRL, TJA1145_MODE_CTRL_MC, + TJA1145_MODE_CTRL_NORMAL); + if (ret) + return ret; + + /* + * Switch to CAN operating mode active where the PHY can transmit and + * receive data. + */ + return regmap_update_bits(map, TJA1145_CAN_CTRL, TJA1145_CAN_CTRL_CMC, + TJA1145_CAN_CTRL_ACTIVE); +} + +static int tja1145_phy_power_off(struct phy *phy) +{ + struct regmap *map = phy_get_drvdata(phy); + + /* + * Switch to operating mode standby, the PHY is unable to transmit or + * receive data in standby mode. + */ + return regmap_update_bits(map, TJA1145_MODE_CTRL, TJA1145_MODE_CTRL_MC, + TJA1145_MODE_CTRL_STBY); +} + +static const struct phy_ops tja1145_phy_ops = { + .power_on = tja1145_phy_power_on, + .power_off = tja1145_phy_power_off, + .owner = THIS_MODULE, +}; + +static const struct regmap_range tja1145_wr_holes_ranges[] = { + regmap_reg_range(0x00, 0x00), + regmap_reg_range(0x02, 0x03), + regmap_reg_range(0x05, 0x05), + regmap_reg_range(0x0b, 0x1f), + regmap_reg_range(0x21, 0x22), + regmap_reg_range(0x24, 0x25), + regmap_reg_range(0x30, 0x4b), + regmap_reg_range(0x4d, 0x60), + regmap_reg_range(0x62, 0x62), + regmap_reg_range(0x65, 0x67), + regmap_reg_range(0x70, 0xff), +}; + +static const struct regmap_access_table tja1145_wr_table = { + .no_ranges = tja1145_wr_holes_ranges, + .n_no_ranges = ARRAY_SIZE(tja1145_wr_holes_ranges), +}; + +static const struct regmap_range tja1145_rd_holes_ranges[] = { + regmap_reg_range(0x00, 0x00), + regmap_reg_range(0x02, 0x02), + regmap_reg_range(0x05, 0x05), + regmap_reg_range(0x0b, 0x1f), + regmap_reg_range(0x21, 0x21), + regmap_reg_range(0x24, 0x25), + regmap_reg_range(0x30, 0x4a), + regmap_reg_range(0x4d, 0x5f), + regmap_reg_range(0x62, 0x62), + regmap_reg_range(0x65, 0x67), + regmap_reg_range(0x70, 0x7d), + regmap_reg_range(0x7f, 0xff), +}; + +static const struct regmap_access_table tja1145_rd_table = { + .no_ranges = tja1145_rd_holes_ranges, + .n_no_ranges = ARRAY_SIZE(tja1145_rd_holes_ranges), +}; + +static const struct regmap_config tja1145_regmap_config = { + .reg_bits = 8, + .reg_shift = -1, + .val_bits = 8, + .wr_table = &tja1145_wr_table, + .rd_table = &tja1145_rd_table, + .read_flag_mask = TJA1145_SPI_READ_BIT, + .max_register = TJA1145_IDENT, +}; + +static int tja1145_check_ident(struct device *dev, struct regmap *map) +{ + unsigned int val; + int ret; + + ret = regmap_read(map, TJA1145_IDENT, &val); + if (ret) + return ret; + + if (val != TJA1145_IDENT_TJA1145T) { + dev_err(dev, "Expected device id: 0x%02x, got: 0x%02x\n", + TJA1145_IDENT_TJA1145T, val); + return -ENODEV; + } + + return 0; +} + +static int tja1145_probe(struct spi_device *spi) +{ + struct phy_provider *phy_provider; + struct device *dev = &spi->dev; + struct regmap *map; + struct phy *phy; + int ret; + + map = devm_regmap_init_spi(spi, &tja1145_regmap_config); + if (IS_ERR(map)) + return dev_err_probe(dev, PTR_ERR(map), "failed to init regmap\n"); + + ret = tja1145_check_ident(dev, map); + if (ret) + return dev_err_probe(dev, ret, "failed to identify device\n"); + + phy = devm_phy_create(dev, dev->of_node, &tja1145_phy_ops); + if (IS_ERR(phy)) + return dev_err_probe(dev, PTR_ERR(phy), "failed to create PHY\n"); + + phy->attrs.max_link_rate = TJA1145T_MAX_BITRATE; + phy_set_drvdata(phy, map); + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + + return PTR_ERR_OR_ZERO(phy_provider); +} + +static const struct spi_device_id tja1145_spi_id[] = { + { "tja1145" }, + { } +}; +MODULE_DEVICE_TABLE(spi, tja1145_spi_id); + +static const struct of_device_id tja1145_of_match[] = { + { .compatible = "nxp,tja1145" }, + { } +}; +MODULE_DEVICE_TABLE(of, tja1145_of_match); + +static struct spi_driver tja1145_driver = { + .driver = { + .name = "tja1145", + .of_match_table = tja1145_of_match, + }, + .probe = tja1145_probe, + .id_table = tja1145_spi_id, +}; +module_spi_driver(tja1145_driver); + +MODULE_DESCRIPTION("NXP TJA1145 CAN transceiver PHY driver"); +MODULE_AUTHOR("Dimitri Fedrau <dimitri.fedrau@liebherr.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/phy/qualcomm/phy-qcom-m31-eusb2.c b/drivers/phy/qualcomm/phy-qcom-m31-eusb2.c index 68f1ba8fec4ad..0bec8657149c9 100644 --- a/drivers/phy/qualcomm/phy-qcom-m31-eusb2.c +++ b/drivers/phy/qualcomm/phy-qcom-m31-eusb2.c @@ -285,7 +285,7 @@ static int m31eusb2_phy_probe(struct platform_device *pdev) phy_set_drvdata(phy->phy, phy); - phy->repeater = devm_of_phy_get_by_index(dev, dev->of_node, 0); + phy->repeater = devm_phy_optional_get(dev, NULL); if (IS_ERR(phy->repeater)) return dev_err_probe(dev, PTR_ERR(phy->repeater), "failed to get repeater\n"); diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c index 93f1aa10d4008..cdcfad2e86b1d 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c @@ -3691,6 +3691,13 @@ static int qmp_combo_com_init(struct qmp_combo *qmp, bool force) if (ret) goto err_assert_reset; + /* In DP-only mode, the pipe clk is still required for USB2 */ + ret = clk_prepare_enable(qmp->pipe_clk); + if (ret) { + dev_err(qmp->dev, "pipe_clk enable failed err=%d\n", ret); + goto err_disable_clocks; + } + qphy_setbits(com, QPHY_V3_DP_COM_POWER_DOWN_CTRL, SW_PWRDN); /* override hardware control for reset of qmp phy */ @@ -3749,6 +3756,8 @@ static int qmp_combo_com_init(struct qmp_combo *qmp, bool force) return 0; +err_disable_clocks: + clk_bulk_disable_unprepare(qmp->num_clks, qmp->clks); err_assert_reset: reset_control_bulk_assert(cfg->num_resets, qmp->resets); err_disable_regulators: @@ -3768,6 +3777,7 @@ static int qmp_combo_com_exit(struct qmp_combo *qmp, bool force) reset_control_bulk_assert(cfg->num_resets, qmp->resets); + clk_disable_unprepare(qmp->pipe_clk); clk_bulk_disable_unprepare(qmp->num_clks, qmp->clks); regulator_bulk_disable(cfg->num_vregs, qmp->vregs); @@ -3871,12 +3881,6 @@ static int qmp_combo_usb_power_on(struct phy *phy) qmp_configure(qmp->dev, 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, tx, cfg->tx_tbl, cfg->tx_tbl_num, 1); qmp_configure_lane(qmp->dev, tx2, cfg->tx_tbl, cfg->tx_tbl_num, 2); @@ -3922,8 +3926,6 @@ static int qmp_combo_usb_power_off(struct phy *phy) struct qmp_combo *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); diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c index a7c65cfe31dfb..37e96493b722a 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c @@ -59,67 +59,67 @@ static const unsigned int pciephy_regs_layout[QPHY_LAYOUT_SIZE] = { }; static const struct qmp_phy_init_tbl msm8996_pcie_serdes_tbl[] = { - QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x1c), - QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10), - QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x33), - QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x42), - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff), - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x1f), - QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x01), - QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), - QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a), - QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x09), - QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x1a), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x0a), - QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x33), - QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x02), - QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1f), - QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x04), - QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), - QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), - QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), - QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), - QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), - QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), - QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), - QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x02), - QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0x2f), - QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x19), - QMP_PHY_INIT_CFG(QSERDES_COM_RESCODE_DIV_NUM, 0x15), - QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), - QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), - QMP_PHY_INIT_CFG(QSERDES_COM_CLK_EP_DIV, 0x19), - QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10), - QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_RESCODE_DIV_NUM, 0x40), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BIAS_EN_CLKBUFLR_EN, 0x1c), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CLK_ENABLE1, 0x10), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CLK_SELECT, 0x33), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CMN_CONFIG, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP_EN, 0x42), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_MAP, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_TIMER1, 0xff), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_TIMER2, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_HSCLK_SEL, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SVS_MODE_CLK_SEL, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CORE_CLK_EN, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CORECLK_DIV, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BG_TIMER, 0x09), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DEC_START_MODE0, 0x82), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START3_MODE0, 0x03), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START2_MODE0, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START1_MODE0, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP3_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP2_MODE0, 0x1a), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP1_MODE0, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CLK_SELECT, 0x33), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYS_CLK_CTRL, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYSCLK_BUF_ENABLE, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYSCLK_EN_SEL, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CP_CTRL_MODE0, 0x0b), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_CCTRL_MODE0, 0x28), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_INTEGLOOP_GAIN1_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_INTEGLOOP_GAIN0_MODE0, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_EN_CENTER, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_PER1, 0x31), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_PER2, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_ADJ_PER1, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_ADJ_PER2, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_STEP_SIZE1, 0x2f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_STEP_SIZE2, 0x19), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_RESCODE_DIV_NUM, 0x15), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BG_TRIM, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_IVCO, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CLK_EP_DIV, 0x19), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CLK_ENABLE1, 0x10), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_HSCLK_SEL, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_RESCODE_DIV_NUM, 0x40), }; static const struct qmp_phy_init_tbl msm8996_pcie_tx_tbl[] = { - QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), - QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V2_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), + QMP_PHY_INIT_CFG(QSERDES_V2_TX_LANE_MODE, 0x06), }; static const struct qmp_phy_init_tbl msm8996_pcie_rx_tbl[] = { - QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x1c), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x01), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x00), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xdb), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_BAND, 0x18), - QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x04), - QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN_HALF, 0x04), - QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), - QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x14), - QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x19), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_SIGDET_ENABLES, 0x1c), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL2, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL3, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL4, 0xdb), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_BAND, 0x18), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_UCDR_SO_GAIN, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_UCDR_SO_GAIN_HALF, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_SIGDET_DEGLITCH_CNTRL, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_SIGDET_LVL, 0x19), }; static const struct qmp_phy_init_tbl msm8996_pcie_pcs_tbl[] = { diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c index fed2fc9bb3110..d3effad7a074b 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c @@ -198,6 +198,112 @@ static const struct qmp_phy_init_tbl msm8998_pcie_pcs_tbl[] = { QMP_PHY_INIT_CFG(QPHY_V3_PCS_SIGDET_CNTRL, 0x03), }; +static const struct qmp_phy_init_tbl eliza_qmp_gen3x1_pcie_serdes_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE1, 0x93), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE1, 0x01), + 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, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE1, 0x1a), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x34), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE1, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE1, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE1, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE1_MODE1, 0xb4), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE2_MODE1, 0x03), + 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, 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, 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_VCO_TUNE1_MODE0, 0x24), + 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_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_SYSCLK_EN_SEL, 0x08), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x42), + 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, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_ADDITIONAL_MISC_3, 0x0f), +}; + +static const struct qmp_phy_init_tbl eliza_qmp_gen3x1_pcie_pcs_tbl[] = { + QMP_PHY_INIT_CFG(QPHY_V6_PCS_REFGEN_REQ_CONFIG1, 0x05), + QMP_PHY_INIT_CFG(QPHY_V6_PCS_G3S2_PRE_GAIN, 0x2e), + QMP_PHY_INIT_CFG(QPHY_V6_PCS_RX_SIGDET_LVL, 0x77), + QMP_PHY_INIT_CFG(QPHY_V6_PCS_RATE_SLEW_CNTRL1, 0x0b), + QMP_PHY_INIT_CFG(QPHY_V6_PCS_PCS_TX_RX_CONFIG, 0x0c), + QMP_PHY_INIT_CFG(QPHY_V6_PCS_EQ_CONFIG2, 0x0f), +}; + +static const struct qmp_phy_init_tbl eliza_qmp_gen3x1_pcie_misc_pcs_tbl[] = { + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_POWER_STATE_CONFIG2, 0x1d), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_INT_AUX_CLK_CONFIG1, 0x00), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_RXEQEVAL_TIME, 0x27), +}; + +static const struct qmp_phy_init_tbl eliza_qmp_gen3x1_pcie_tx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V6_TX_RES_CODE_LANE_OFFSET_TX, 0x17), + QMP_PHY_INIT_CFG(QSERDES_V6_TX_RES_CODE_LANE_OFFSET_RX, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V6_TX_LANE_MODE_1, 0x15), + QMP_PHY_INIT_CFG(QSERDES_V6_TX_LANE_MODE_4, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V6_TX_RCV_DETECT_LVL_2, 0x12), + QMP_PHY_INIT_CFG(QSERDES_V6_TX_PI_QEC_CTRL, 0x02), +}; + +static const struct qmp_phy_init_tbl eliza_qmp_gen3x1_pcie_rx_tbl[] = { + 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_SO_SATURATION_AND_ENABLE, 0x7f), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_PI_CONTROLS, 0xf0), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_SB2_THRESH1, 0x08), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_SB2_THRESH2, 0x08), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_AUX_DATA_TCOARSE_TFINE, 0x30), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_TX_ADAPT_POST_THRESH, 0xf0), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_VGA_CAL_CNTRL1, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_VGA_CAL_CNTRL2, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_GM_CAL, 0x0d), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0e), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_IDAC_TSETTLE_LOW, 0x07), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_SIDGET_ENABLES, 0x0c), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_LOW, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_HIGH, 0xbf), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_HIGH2, 0xbf), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_HIGH3, 0xb7), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_HIGH4, 0xea), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_LOW, 0xdc), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_HIGH, 0x5c), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_HIGH2, 0x9c), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_HIGH3, 0x1a), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_HIGH4, 0x89), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_10_HIGH, 0x94), + 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_DFE_CTLE_POST_CAL_OFFSET, 0x38), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_SIGDET_CAL_TRIM, 0x08), +}; + static const struct qmp_phy_init_tbl ipq6018_pcie_serdes_tbl[] = { QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER1, 0x7d), QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER2, 0x01), @@ -309,65 +415,65 @@ static const struct qmp_phy_init_tbl ipq6018_pcie_pcs_misc_tbl[] = { }; static const struct qmp_phy_init_tbl ipq8074_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, 0xa), - QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0xa), - 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, 0xD04), - QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x33), - 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, 0xb), - QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), - QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), - QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 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_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), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BIAS_EN_CLKBUFLR_EN, 0x18), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CLK_ENABLE1, 0x10), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BG_TRIM, 0xf), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP_EN, 0x1), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_MAP, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_TIMER1, 0xff), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_TIMER2, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CMN_CONFIG, 0x6), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_IVCO, 0xf), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_HSCLK_SEL, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SVS_MODE_CLK_SEL, 0x1), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CORE_CLK_EN, 0x20), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CORECLK_DIV, 0xa), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_RESETSM_CNTRL, 0x20), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BG_TIMER, 0xa), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYSCLK_EN_SEL, 0xa), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DEC_START_MODE0, 0x82), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START3_MODE0, 0x3), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START2_MODE0, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START1_MODE0, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP3_MODE0, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP2_MODE0, 0xD), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP1_MODE0, 0xD04), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CLK_SELECT, 0x33), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYS_CLK_CTRL, 0x2), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYSCLK_BUF_ENABLE, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CP_CTRL_MODE0, 0xb), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_CCTRL_MODE0, 0x28), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_INTEGLOOP_GAIN1_MODE0, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_INTEGLOOP_GAIN0_MODE0, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BIAS_EN_CTRL_BY_PSM, 0x1), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_EN_CENTER, 0x1), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_PER1, 0x31), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_PER2, 0x1), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_ADJ_PER1, 0x2), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_ADJ_PER2, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_STEP_SIZE1, 0x2f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_STEP_SIZE2, 0x19), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CLK_EP_DIV, 0x19), }; static const struct qmp_phy_init_tbl ipq8074_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), - QMP_PHY_INIT_CFG(QSERDES_TX_TX_EMP_POST1_LVL, 0x36), - QMP_PHY_INIT_CFG(QSERDES_TX_SLEW_CNTL, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V2_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), + QMP_PHY_INIT_CFG(QSERDES_V2_TX_LANE_MODE, 0x6), + QMP_PHY_INIT_CFG(QSERDES_V2_TX_RES_CODE_LANE_OFFSET, 0x2), + QMP_PHY_INIT_CFG(QSERDES_V2_TX_RCV_DETECT_LVL_2, 0x12), + QMP_PHY_INIT_CFG(QSERDES_V2_TX_TX_EMP_POST1_LVL, 0x36), + QMP_PHY_INIT_CFG(QSERDES_V2_TX_SLEW_CNTL, 0x0a), }; static const struct qmp_phy_init_tbl ipq8074_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_V2_RX_SIGDET_ENABLES, 0x1c), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_SIGDET_DEGLITCH_CNTRL, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL2, 0x1), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL3, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL4, 0xdb), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_UCDR_SO_GAIN, 0x4), }; static const struct qmp_phy_init_tbl ipq8074_pcie_pcs_tbl[] = { @@ -752,65 +858,65 @@ static const struct qmp_phy_init_tbl ipq9574_gen3x2_pcie_pcs_misc_tbl[] = { }; 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), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BIAS_EN_CLKBUFLR_EN, 0x18), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CLK_ENABLE1, 0x10), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BG_TRIM, 0xf), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP_EN, 0x1), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_MAP, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_TIMER1, 0xff), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_TIMER2, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CMN_CONFIG, 0x6), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_IVCO, 0xf), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_HSCLK_SEL, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SVS_MODE_CLK_SEL, 0x1), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CORE_CLK_EN, 0x20), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CORECLK_DIV, 0xa), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_RESETSM_CNTRL, 0x20), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BG_TIMER, 0x9), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYSCLK_EN_SEL, 0x4), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DEC_START_MODE0, 0x82), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START3_MODE0, 0x3), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START2_MODE0, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START1_MODE0, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP3_MODE0, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP2_MODE0, 0xd), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP1_MODE0, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CLK_SELECT, 0x35), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYS_CLK_CTRL, 0x2), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYSCLK_BUF_ENABLE, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CP_CTRL_MODE0, 0x4), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_CCTRL_MODE0, 0x30), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_INTEGLOOP_GAIN1_MODE0, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_INTEGLOOP_GAIN0_MODE0, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BIAS_EN_CTRL_BY_PSM, 0x1), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BG_TIMER, 0xa), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_EN_CENTER, 0x1), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_PER1, 0x31), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_PER2, 0x1), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_ADJ_PER1, 0x2), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_ADJ_PER2, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_STEP_SIZE1, 0x2f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_STEP_SIZE2, 0x19), + QMP_PHY_INIT_CFG(QSERDES_V2_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), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_SIGDET_ENABLES, 0x1c), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_SIGDET_DEGLITCH_CNTRL, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL2, 0x1), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL3, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL4, 0xdb), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_UCDR_SO_GAIN, 0x4), + QMP_PHY_INIT_CFG(QSERDES_V2_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), + QMP_PHY_INIT_CFG(QSERDES_V2_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), + QMP_PHY_INIT_CFG(QSERDES_V2_TX_LANE_MODE, 0x6), + QMP_PHY_INIT_CFG(QSERDES_V2_TX_RES_CODE_LANE_OFFSET, 0x2), + QMP_PHY_INIT_CFG(QSERDES_V2_TX_RCV_DETECT_LVL_2, 0x12), }; static const struct qmp_phy_init_tbl qcs615_pcie_pcs_tbl[] = { @@ -3532,6 +3638,33 @@ static const struct qmp_pcie_offsets qmp_pcie_offsets_v8_50 = { .txrxz = 0xd000, }; +static const struct qmp_phy_cfg eliza_qmp_gen3x1_pciephy_cfg = { + .lanes = 1, + + .offsets = &qmp_pcie_offsets_v5, + + .tbls = { + .serdes = eliza_qmp_gen3x1_pcie_serdes_tbl, + .serdes_num = ARRAY_SIZE(eliza_qmp_gen3x1_pcie_serdes_tbl), + .tx = eliza_qmp_gen3x1_pcie_tx_tbl, + .tx_num = ARRAY_SIZE(eliza_qmp_gen3x1_pcie_tx_tbl), + .rx = eliza_qmp_gen3x1_pcie_rx_tbl, + .rx_num = ARRAY_SIZE(eliza_qmp_gen3x1_pcie_rx_tbl), + .pcs = eliza_qmp_gen3x1_pcie_pcs_tbl, + .pcs_num = ARRAY_SIZE(eliza_qmp_gen3x1_pcie_pcs_tbl), + .pcs_misc = eliza_qmp_gen3x1_pcie_misc_pcs_tbl, + .pcs_misc_num = ARRAY_SIZE(eliza_qmp_gen3x1_pcie_misc_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_v6_regs_layout, + + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + .phy_status = PHYSTATUS, +}; + static const struct qmp_phy_cfg ipq8074_pciephy_cfg = { .lanes = 1, @@ -5399,6 +5532,12 @@ err_node_put: static const struct of_device_id qmp_pcie_of_match_table[] = { { + .compatible = "qcom,eliza-qmp-gen3x1-pcie-phy", + .data = &eliza_qmp_gen3x1_pciephy_cfg, + }, { + .compatible = "qcom,eliza-qmp-gen3x2-pcie-phy", + .data = &sm8550_qmp_gen3x2_pciephy_cfg, + }, { .compatible = "qcom,glymur-qmp-gen4x2-pcie-phy", .data = &glymur_qmp_gen4x2_pciephy_cfg, }, { 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 45397cb3c0c6f..17a0f9d18acf0 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6.h +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcs-pcie-v6.h @@ -12,6 +12,7 @@ #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_INT_AUX_CLK_CONFIG1 0x54 #define QPHY_PCIE_V6_PCS_PCIE_OSC_DTCT_ACTIONS 0x94 #define QPHY_PCIE_V6_PCS_LANE1_INSIG_SW_CTRL2 0x024 diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v2.h b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v2.h index 3ea1884f35dd5..cb599c113189c 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v2.h +++ b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v2.h @@ -34,6 +34,7 @@ #define QSERDES_V2_COM_LOCK_CMP3_MODE1 0x060 #define QSERDES_V2_COM_EP_CLOCK_DETECT_CTR 0x068 #define QSERDES_V2_COM_SYSCLK_DET_COMP_STATUS 0x06c +#define QSERDES_V2_COM_BG_TRIM 0x070 #define QSERDES_V2_COM_CLK_EP_DIV 0x074 #define QSERDES_V2_COM_CP_CTRL_MODE0 0x078 #define QSERDES_V2_COM_CP_CTRL_MODE1 0x07c @@ -47,6 +48,7 @@ #define QSERDES_V2_COM_CML_SYSCLK_SEL 0x0b0 #define QSERDES_V2_COM_RESETSM_CNTRL 0x0b4 #define QSERDES_V2_COM_RESETSM_CNTRL2 0x0b8 +#define QSERDES_V2_COM_RESCODE_DIV_NUM 0x0c4 #define QSERDES_V2_COM_LOCK_CMP_EN 0x0c8 #define QSERDES_V2_COM_LOCK_CMP_CFG 0x0cc #define QSERDES_V2_COM_DEC_START_MODE0 0x0d0 @@ -83,6 +85,7 @@ #define QSERDES_V2_COM_RESTRIM_CODE_STATUS 0x164 #define QSERDES_V2_COM_PLLCAL_CODE1_STATUS 0x168 #define QSERDES_V2_COM_PLLCAL_CODE2_STATUS 0x16c +#define QSERDES_V2_COM_BG_CTRL 0x170 #define QSERDES_V2_COM_CLK_SELECT 0x174 #define QSERDES_V2_COM_HSCLK_SEL 0x178 #define QSERDES_V2_COM_INTEGLOOP_BINCODE_STATUS 0x17c diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com.h b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com.h deleted file mode 100644 index 7fa5363feeb9b..0000000000000 --- a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com.h +++ /dev/null @@ -1,140 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (c) 2017, The Linux Foundation. All rights reserved. - */ - -#ifndef QCOM_PHY_QMP_QSERDES_COM_H_ -#define QCOM_PHY_QMP_QSERDES_COM_H_ - -/* Only for QMP V2 PHY - QSERDES COM registers */ -#define QSERDES_COM_ATB_SEL1 0x000 -#define QSERDES_COM_ATB_SEL2 0x004 -#define QSERDES_COM_FREQ_UPDATE 0x008 -#define QSERDES_COM_BG_TIMER 0x00c -#define QSERDES_COM_SSC_EN_CENTER 0x010 -#define QSERDES_COM_SSC_ADJ_PER1 0x014 -#define QSERDES_COM_SSC_ADJ_PER2 0x018 -#define QSERDES_COM_SSC_PER1 0x01c -#define QSERDES_COM_SSC_PER2 0x020 -#define QSERDES_COM_SSC_STEP_SIZE1 0x024 -#define QSERDES_COM_SSC_STEP_SIZE2 0x028 -#define QSERDES_COM_POST_DIV 0x02c -#define QSERDES_COM_POST_DIV_MUX 0x030 -#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN 0x034 -#define QSERDES_COM_CLK_ENABLE1 0x038 -#define QSERDES_COM_SYS_CLK_CTRL 0x03c -#define QSERDES_COM_SYSCLK_BUF_ENABLE 0x040 -#define QSERDES_COM_PLL_EN 0x044 -#define QSERDES_COM_PLL_IVCO 0x048 -#define QSERDES_COM_LOCK_CMP1_MODE0 0x04c -#define QSERDES_COM_LOCK_CMP2_MODE0 0x050 -#define QSERDES_COM_LOCK_CMP3_MODE0 0x054 -#define QSERDES_COM_LOCK_CMP1_MODE1 0x058 -#define QSERDES_COM_LOCK_CMP2_MODE1 0x05c -#define QSERDES_COM_LOCK_CMP3_MODE1 0x060 -#define QSERDES_COM_LOCK_CMP1_MODE2 0x064 -#define QSERDES_COM_CMN_RSVD0 0x064 -#define QSERDES_COM_LOCK_CMP2_MODE2 0x068 -#define QSERDES_COM_EP_CLOCK_DETECT_CTRL 0x068 -#define QSERDES_COM_LOCK_CMP3_MODE2 0x06c -#define QSERDES_COM_SYSCLK_DET_COMP_STATUS 0x06c -#define QSERDES_COM_BG_TRIM 0x070 -#define QSERDES_COM_CLK_EP_DIV 0x074 -#define QSERDES_COM_CP_CTRL_MODE0 0x078 -#define QSERDES_COM_CP_CTRL_MODE1 0x07c -#define QSERDES_COM_CP_CTRL_MODE2 0x080 -#define QSERDES_COM_CMN_RSVD1 0x080 -#define QSERDES_COM_PLL_RCTRL_MODE0 0x084 -#define QSERDES_COM_PLL_RCTRL_MODE1 0x088 -#define QSERDES_COM_PLL_RCTRL_MODE2 0x08c -#define QSERDES_COM_CMN_RSVD2 0x08c -#define QSERDES_COM_PLL_CCTRL_MODE0 0x090 -#define QSERDES_COM_PLL_CCTRL_MODE1 0x094 -#define QSERDES_COM_PLL_CCTRL_MODE2 0x098 -#define QSERDES_COM_CMN_RSVD3 0x098 -#define QSERDES_COM_PLL_CNTRL 0x09c -#define QSERDES_COM_PHASE_SEL_CTRL 0x0a0 -#define QSERDES_COM_PHASE_SEL_DC 0x0a4 -#define QSERDES_COM_CORE_CLK_IN_SYNC_SEL 0x0a8 -#define QSERDES_COM_BIAS_EN_CTRL_BY_PSM 0x0a8 -#define QSERDES_COM_SYSCLK_EN_SEL 0x0ac -#define QSERDES_COM_CML_SYSCLK_SEL 0x0b0 -#define QSERDES_COM_RESETSM_CNTRL 0x0b4 -#define QSERDES_COM_RESETSM_CNTRL2 0x0b8 -#define QSERDES_COM_RESTRIM_CTRL 0x0bc -#define QSERDES_COM_RESTRIM_CTRL2 0x0c0 -#define QSERDES_COM_RESCODE_DIV_NUM 0x0c4 -#define QSERDES_COM_LOCK_CMP_EN 0x0c8 -#define QSERDES_COM_LOCK_CMP_CFG 0x0cc -#define QSERDES_COM_DEC_START_MODE0 0x0d0 -#define QSERDES_COM_DEC_START_MODE1 0x0d4 -#define QSERDES_COM_DEC_START_MODE2 0x0d8 -#define QSERDES_COM_VCOCAL_DEADMAN_CTRL 0x0d8 -#define QSERDES_COM_DIV_FRAC_START1_MODE0 0x0dc -#define QSERDES_COM_DIV_FRAC_START2_MODE0 0x0e0 -#define QSERDES_COM_DIV_FRAC_START3_MODE0 0x0e4 -#define QSERDES_COM_DIV_FRAC_START1_MODE1 0x0e8 -#define QSERDES_COM_DIV_FRAC_START2_MODE1 0x0ec -#define QSERDES_COM_DIV_FRAC_START3_MODE1 0x0f0 -#define QSERDES_COM_DIV_FRAC_START1_MODE2 0x0f4 -#define QSERDES_COM_VCO_TUNE_MINVAL1 0x0f4 -#define QSERDES_COM_DIV_FRAC_START2_MODE2 0x0f8 -#define QSERDES_COM_VCO_TUNE_MINVAL2 0x0f8 -#define QSERDES_COM_DIV_FRAC_START3_MODE2 0x0fc -#define QSERDES_COM_CMN_RSVD4 0x0fc -#define QSERDES_COM_INTEGLOOP_INITVAL 0x100 -#define QSERDES_COM_INTEGLOOP_EN 0x104 -#define QSERDES_COM_INTEGLOOP_GAIN0_MODE0 0x108 -#define QSERDES_COM_INTEGLOOP_GAIN1_MODE0 0x10c -#define QSERDES_COM_INTEGLOOP_GAIN0_MODE1 0x110 -#define QSERDES_COM_INTEGLOOP_GAIN1_MODE1 0x114 -#define QSERDES_COM_INTEGLOOP_GAIN0_MODE2 0x118 -#define QSERDES_COM_VCO_TUNE_MAXVAL1 0x118 -#define QSERDES_COM_INTEGLOOP_GAIN1_MODE2 0x11c -#define QSERDES_COM_VCO_TUNE_MAXVAL2 0x11c -#define QSERDES_COM_RES_TRIM_CONTROL2 0x120 -#define QSERDES_COM_VCO_TUNE_CTRL 0x124 -#define QSERDES_COM_VCO_TUNE_MAP 0x128 -#define QSERDES_COM_VCO_TUNE1_MODE0 0x12c -#define QSERDES_COM_VCO_TUNE2_MODE0 0x130 -#define QSERDES_COM_VCO_TUNE1_MODE1 0x134 -#define QSERDES_COM_VCO_TUNE2_MODE1 0x138 -#define QSERDES_COM_VCO_TUNE1_MODE2 0x13c -#define QSERDES_COM_VCO_TUNE_INITVAL1 0x13c -#define QSERDES_COM_VCO_TUNE2_MODE2 0x140 -#define QSERDES_COM_VCO_TUNE_INITVAL2 0x140 -#define QSERDES_COM_VCO_TUNE_TIMER1 0x144 -#define QSERDES_COM_VCO_TUNE_TIMER2 0x148 -#define QSERDES_COM_SAR 0x14c -#define QSERDES_COM_SAR_CLK 0x150 -#define QSERDES_COM_SAR_CODE_OUT_STATUS 0x154 -#define QSERDES_COM_SAR_CODE_READY_STATUS 0x158 -#define QSERDES_COM_CMN_STATUS 0x15c -#define QSERDES_COM_RESET_SM_STATUS 0x160 -#define QSERDES_COM_RESTRIM_CODE_STATUS 0x164 -#define QSERDES_COM_PLLCAL_CODE1_STATUS 0x168 -#define QSERDES_COM_PLLCAL_CODE2_STATUS 0x16c -#define QSERDES_COM_BG_CTRL 0x170 -#define QSERDES_COM_CLK_SELECT 0x174 -#define QSERDES_COM_HSCLK_SEL 0x178 -#define QSERDES_COM_INTEGLOOP_BINCODE_STATUS 0x17c -#define QSERDES_COM_PLL_ANALOG 0x180 -#define QSERDES_COM_CORECLK_DIV 0x184 -#define QSERDES_COM_SW_RESET 0x188 -#define QSERDES_COM_CORE_CLK_EN 0x18c -#define QSERDES_COM_C_READY_STATUS 0x190 -#define QSERDES_COM_CMN_CONFIG 0x194 -#define QSERDES_COM_CMN_RATE_OVERRIDE 0x198 -#define QSERDES_COM_SVS_MODE_CLK_SEL 0x19c -#define QSERDES_COM_DEBUG_BUS0 0x1a0 -#define QSERDES_COM_DEBUG_BUS1 0x1a4 -#define QSERDES_COM_DEBUG_BUS2 0x1a8 -#define QSERDES_COM_DEBUG_BUS3 0x1ac -#define QSERDES_COM_DEBUG_BUS_SEL 0x1b0 -#define QSERDES_COM_CMN_MISC1 0x1b4 -#define QSERDES_COM_CMN_MISC2 0x1b8 -#define QSERDES_COM_CORECLK_DIV_MODE1 0x1bc -#define QSERDES_COM_CORECLK_DIV_MODE2 0x1c0 -#define QSERDES_COM_CMN_RSVD5 0x1c4 - -#endif diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v2.h b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v2.h index 34919720b7bc4..9ae0cf95e317e 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v2.h +++ b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-v2.h @@ -7,62 +7,199 @@ #define QCOM_PHY_QMP_QSERDES_TXRX_V2_H_ /* Only for QMP V2 PHY - TX registers */ -#define QSERDES_V2_TX_BIST_MODE_LANENO 0x000 -#define QSERDES_V2_TX_CLKBUF_ENABLE 0x008 -#define QSERDES_V2_TX_TX_EMP_POST1_LVL 0x00c -#define QSERDES_V2_TX_TX_DRV_LVL 0x01c -#define QSERDES_V2_TX_RESET_TSYNC_EN 0x024 -#define QSERDES_V2_TX_PRE_STALL_LDO_BOOST_EN 0x028 -#define QSERDES_V2_TX_TX_BAND 0x02c -#define QSERDES_V2_TX_SLEW_CNTL 0x030 -#define QSERDES_V2_TX_INTERFACE_SELECT 0x034 -#define QSERDES_V2_TX_RES_CODE_LANE_TX 0x03c -#define QSERDES_V2_TX_RES_CODE_LANE_RX 0x040 -#define QSERDES_V2_TX_RES_CODE_LANE_OFFSET_TX 0x044 -#define QSERDES_V2_TX_RES_CODE_LANE_OFFSET_RX 0x048 -#define QSERDES_V2_TX_DEBUG_BUS_SEL 0x058 -#define QSERDES_V2_TX_TRANSCEIVER_BIAS_EN 0x05c -#define QSERDES_V2_TX_HIGHZ_DRVR_EN 0x060 -#define QSERDES_V2_TX_TX_POL_INV 0x064 -#define QSERDES_V2_TX_PARRATE_REC_DETECT_IDLE_EN 0x068 -#define QSERDES_V2_TX_LANE_MODE_1 0x08c -#define QSERDES_V2_TX_LANE_MODE_2 0x090 -#define QSERDES_V2_TX_LANE_MODE_3 0x094 -#define QSERDES_V2_TX_RCV_DETECT_LVL_2 0x0a4 -#define QSERDES_V2_TX_TRAN_DRVR_EMP_EN 0x0c0 -#define QSERDES_V2_TX_TX_INTERFACE_MODE 0x0c4 -#define QSERDES_V2_TX_VMODE_CTRL1 0x0f0 +#define QSERDES_V2_TX_BIST_MODE_LANENO 0x000 +#define QSERDES_V2_TX_BIST_INVERT 0x004 +#define QSERDES_V2_TX_CLKBUF_ENABLE 0x008 +#define QSERDES_V2_TX_CMN_CONTROL_ONE 0x00c +#define QSERDES_V2_TX_CMN_CONTROL_TWO 0x010 +#define QSERDES_V2_TX_CMN_CONTROL_THREE 0x014 +#define QSERDES_V2_TX_TX_EMP_POST1_LVL 0x018 +#define QSERDES_V2_TX_TX_POST2_EMPH 0x01c +#define QSERDES_V2_TX_TX_BOOST_LVL_UP_DN 0x020 +#define QSERDES_V2_TX_HP_PD_ENABLES 0x024 +#define QSERDES_V2_TX_TX_IDLE_LVL_LARGE_AMP 0x028 +#define QSERDES_V2_TX_TX_DRV_LVL 0x02c +#define QSERDES_V2_TX_TX_DRV_LVL_OFFSET 0x030 +#define QSERDES_V2_TX_RESET_TSYNC_EN 0x034 +#define QSERDES_V2_TX_PRE_STALL_LDO_BOOST_EN 0x038 +#define QSERDES_V2_TX_TX_BAND 0x03c +#define QSERDES_V2_TX_SLEW_CNTL 0x040 +#define QSERDES_V2_TX_INTERFACE_SELECT 0x044 +#define QSERDES_V2_TX_LPB_EN 0x048 +#define QSERDES_V2_TX_RES_CODE_LANE_TX 0x04c +#define QSERDES_V2_TX_RES_CODE_LANE_RX 0x050 +#define QSERDES_V2_TX_RES_CODE_LANE_OFFSET 0x054 +#define QSERDES_V2_TX_PERL_LENGTH1 0x058 +#define QSERDES_V2_TX_PERL_LENGTH2 0x05c +#define QSERDES_V2_TX_SERDES_BYP_EN_OUT 0x060 +#define QSERDES_V2_TX_DEBUG_BUS_SEL 0x064 +#define QSERDES_V2_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN 0x068 +#define QSERDES_V2_TX_TX_POL_INV 0x06c +#define QSERDES_V2_TX_PARRATE_REC_DETECT_IDLE_EN 0x070 +#define QSERDES_V2_TX_BIST_PATTERN1 0x074 +#define QSERDES_V2_TX_BIST_PATTERN2 0x078 +#define QSERDES_V2_TX_BIST_PATTERN3 0x07c +#define QSERDES_V2_TX_BIST_PATTERN4 0x080 +#define QSERDES_V2_TX_BIST_PATTERN5 0x084 +#define QSERDES_V2_TX_BIST_PATTERN6 0x088 +#define QSERDES_V2_TX_BIST_PATTERN7 0x08c +#define QSERDES_V2_TX_BIST_PATTERN8 0x090 +#define QSERDES_V2_TX_LANE_MODE 0x094 +#define QSERDES_V2_TX_IDAC_CAL_LANE_MODE 0x098 +#define QSERDES_V2_TX_IDAC_CAL_LANE_MODE_CONFIGURATION 0x09c +#define QSERDES_V2_TX_ATB_SEL1 0x0a0 +#define QSERDES_V2_TX_ATB_SEL2 0x0a4 +#define QSERDES_V2_TX_RCV_DETECT_LVL 0x0a8 +#define QSERDES_V2_TX_RCV_DETECT_LVL_2 0x0ac +#define QSERDES_V2_TX_PRBS_SEED1 0x0b0 +#define QSERDES_V2_TX_PRBS_SEED2 0x0b4 +#define QSERDES_V2_TX_PRBS_SEED3 0x0b8 +#define QSERDES_V2_TX_PRBS_SEED4 0x0bc +#define QSERDES_V2_TX_RESET_GEN 0x0c0 +#define QSERDES_V2_TX_RESET_GEN_MUXES 0x0c4 +#define QSERDES_V2_TX_TRAN_DRVR_EMP_EN 0x0c8 +#define QSERDES_V2_TX_TX_INTERFACE_MODE 0x0cc +#define QSERDES_V2_TX_PWM_CTRL 0x0d0 +#define QSERDES_V2_TX_PWM_ENCODED_OR_DATA 0x0d4 +#define QSERDES_V2_TX_PWM_GEAR_1_DIVIDER_BAND2 0x0d8 +#define QSERDES_V2_TX_PWM_GEAR_2_DIVIDER_BAND2 0x0dc +#define QSERDES_V2_TX_PWM_GEAR_3_DIVIDER_BAND2 0x0e0 +#define QSERDES_V2_TX_PWM_GEAR_4_DIVIDER_BAND2 0x0e4 +#define QSERDES_V2_TX_PWM_GEAR_1_DIVIDER_BAND0_1 0x0e8 +#define QSERDES_V2_TX_PWM_GEAR_2_DIVIDER_BAND0_1 0x0ec +#define QSERDES_V2_TX_PWM_GEAR_3_DIVIDER_BAND0_1 0x0f0 +#define QSERDES_V2_TX_PWM_GEAR_4_DIVIDER_BAND0_1 0x0f4 +#define QSERDES_V2_TX_VMODE_CTRL1 0x0f8 +#define QSERDES_V2_TX_VMODE_CTRL2 0x0fc +#define QSERDES_V2_TX_TX_ALOG_INTF_OBSV_CNTL 0x100 +#define QSERDES_V2_TX_BIST_STATUS 0x104 +#define QSERDES_V2_TX_BIST_ERROR_COUNT1 0x108 +#define QSERDES_V2_TX_BIST_ERROR_COUNT2 0x10c +#define QSERDES_V2_TX_TX_ALOG_INTF_OBSV 0x110 /* Only for QMP V2 PHY - RX registers */ -#define QSERDES_V2_RX_UCDR_FO_GAIN 0x008 -#define QSERDES_V2_RX_UCDR_SO_GAIN_HALF 0x00c -#define QSERDES_V2_RX_UCDR_SO_GAIN 0x014 -#define QSERDES_V2_RX_UCDR_SVS_SO_GAIN_HALF 0x024 -#define QSERDES_V2_RX_UCDR_SVS_SO_GAIN_QUARTER 0x028 -#define QSERDES_V2_RX_UCDR_SVS_SO_GAIN 0x02c -#define QSERDES_V2_RX_UCDR_FASTLOCK_FO_GAIN 0x030 -#define QSERDES_V2_RX_UCDR_SO_SATURATION_AND_ENABLE 0x034 -#define QSERDES_V2_RX_UCDR_FASTLOCK_COUNT_LOW 0x03c -#define QSERDES_V2_RX_UCDR_FASTLOCK_COUNT_HIGH 0x040 -#define QSERDES_V2_RX_UCDR_PI_CONTROLS 0x044 -#define QSERDES_V2_RX_RX_TERM_BW 0x07c -#define QSERDES_V2_RX_VGA_CAL_CNTRL1 0x0bc -#define QSERDES_V2_RX_VGA_CAL_CNTRL2 0x0c0 -#define QSERDES_V2_RX_RX_EQ_GAIN2_LSB 0x0c8 -#define QSERDES_V2_RX_RX_EQ_GAIN2_MSB 0x0cc -#define QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL1 0x0d0 -#define QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL2 0x0d4 -#define QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL3 0x0d8 -#define QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL4 0x0dc -#define QSERDES_V2_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x0f8 -#define QSERDES_V2_RX_RX_OFFSET_ADAPTOR_CNTRL2 0x0fc -#define QSERDES_V2_RX_SIGDET_ENABLES 0x100 -#define QSERDES_V2_RX_SIGDET_CNTRL 0x104 -#define QSERDES_V2_RX_SIGDET_LVL 0x108 -#define QSERDES_V2_RX_SIGDET_DEGLITCH_CNTRL 0x10c -#define QSERDES_V2_RX_RX_BAND 0x110 -#define QSERDES_V2_RX_RX_INTERFACE_MODE 0x11c -#define QSERDES_V2_RX_RX_MODE_00 0x164 -#define QSERDES_V2_RX_RX_MODE_01 0x168 +#define QSERDES_V2_RX_UCDR_FO_GAIN_HALF 0x000 +#define QSERDES_V2_RX_UCDR_FO_GAIN_QUARTER 0x004 +#define QSERDES_V2_RX_UCDR_FO_GAIN_EIGHTH 0x008 +#define QSERDES_V2_RX_UCDR_FO_GAIN 0x00c +#define QSERDES_V2_RX_UCDR_SO_GAIN_HALF 0x010 +#define QSERDES_V2_RX_UCDR_SO_GAIN_QUARTER 0x014 +#define QSERDES_V2_RX_UCDR_SO_GAIN_EIGHTH 0x018 +#define QSERDES_V2_RX_UCDR_SO_GAIN 0x01c +#define QSERDES_V2_RX_UCDR_SVS_FO_GAIN_HALF 0x020 +#define QSERDES_V2_RX_UCDR_SVS_FO_GAIN_QUARTER 0x024 +#define QSERDES_V2_RX_UCDR_SVS_FO_GAIN_EIGHTH 0x028 +#define QSERDES_V2_RX_UCDR_SVS_FO_GAIN 0x02c +#define QSERDES_V2_RX_UCDR_SVS_SO_GAIN_HALF 0x030 +#define QSERDES_V2_RX_UCDR_SVS_SO_GAIN_QUARTER 0x034 +#define QSERDES_V2_RX_UCDR_SVS_SO_GAIN_EIGHTH 0x038 +#define QSERDES_V2_RX_UCDR_SVS_SO_GAIN 0x03c +#define QSERDES_V2_RX_UCDR_FASTLOCK_FO_GAIN 0x040 +#define QSERDES_V2_RX_UCDR_FD_GAIN 0x044 +#define QSERDES_V2_RX_UCDR_SO_SATURATION_AND_ENABLE 0x048 +#define QSERDES_V2_RX_UCDR_FO_TO_SO_DELAY 0x04c +#define QSERDES_V2_RX_UCDR_FASTLOCK_COUNT_LOW 0x050 +#define QSERDES_V2_RX_UCDR_FASTLOCK_COUNT_HIGH 0x054 +#define QSERDES_V2_RX_UCDR_MODULATE 0x058 +#define QSERDES_V2_RX_UCDR_PI_CONTROLS 0x05c +#define QSERDES_V2_RX_RBIST_CONTROL 0x060 +#define QSERDES_V2_RX_AUX_CONTROL 0x064 +#define QSERDES_V2_RX_AUX_DATA_TCOARSE 0x068 +#define QSERDES_V2_RX_AUX_DATA_TFINE_LSB 0x06c +#define QSERDES_V2_RX_AUX_DATA_TFINE_MSB 0x070 +#define QSERDES_V2_RX_RCLK_AUXDATA_SEL 0x074 +#define QSERDES_V2_RX_AC_JTAG_ENABLE 0x078 +#define QSERDES_V2_RX_AC_JTAG_INITP 0x07c +#define QSERDES_V2_RX_AC_JTAG_INITN 0x080 +#define QSERDES_V2_RX_AC_JTAG_LVL 0x084 +#define QSERDES_V2_RX_AC_JTAG_MODE 0x088 +#define QSERDES_V2_RX_AC_JTAG_RESET 0x08c +#define QSERDES_V2_RX_RX_TERM_BW 0x090 +#define QSERDES_V2_RX_RX_RCVR_IQ_EN 0x094 +#define QSERDES_V2_RX_RX_IDAC_I_DC_OFFSETS 0x098 +#define QSERDES_V2_RX_RX_IDAC_IBAR_DC_OFFSETS 0x09c +#define QSERDES_V2_RX_RX_IDAC_Q_DC_OFFSETS 0x0a0 +#define QSERDES_V2_RX_RX_IDAC_QBAR_DC_OFFSETS 0x0a4 +#define QSERDES_V2_RX_RX_IDAC_A_DC_OFFSETS 0x0a8 +#define QSERDES_V2_RX_RX_IDAC_ABAR_DC_OFFSETS 0x0ac +#define QSERDES_V2_RX_RX_IDAC_EN 0x0b0 +#define QSERDES_V2_RX_RX_IDAC_ENABLES 0x0b4 +#define QSERDES_V2_RX_RX_IDAC_SIGN 0x0b8 +#define QSERDES_V2_RX_RX_HIGHZ_HIGHRATE 0x0bc +#define QSERDES_V2_RX_RX_TERM_AC_BYPASS_DC_COUPLE_OFFSET 0x0c0 +#define QSERDES_V2_RX_RX_EQ_GAIN1_LSB 0x0c4 +#define QSERDES_V2_RX_RX_EQ_GAIN1_MSB 0x0c8 +#define QSERDES_V2_RX_RX_EQ_GAIN2_LSB 0x0cc +#define QSERDES_V2_RX_RX_EQ_GAIN2_MSB 0x0d0 +#define QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL1 0x0d4 +#define QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL2 0x0d8 +#define QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL3 0x0dc +#define QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL4 0x0e0 +#define QSERDES_V2_RX_RX_IDAC_CAL_CONFIGURATION 0x0e4 +#define QSERDES_V2_RX_RX_IDAC_TSETTLE_LOW 0x0e8 +#define QSERDES_V2_RX_RX_IDAC_TSETTLE_HIGH 0x0ec +#define QSERDES_V2_RX_RX_IDAC_ENDSAMP_LOW 0x0f0 +#define QSERDES_V2_RX_RX_IDAC_ENDSAMP_HIGH 0x0f4 +#define QSERDES_V2_RX_RX_IDAC_MIDPOINT_LOW 0x0f8 +#define QSERDES_V2_RX_RX_IDAC_MIDPOINT_HIGH 0x0fc +#define QSERDES_V2_RX_RX_EQ_OFFSET_LSB 0x100 +#define QSERDES_V2_RX_RX_EQ_OFFSET_MSB 0x104 +#define QSERDES_V2_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x108 +#define QSERDES_V2_RX_RX_OFFSET_ADAPTOR_CNTRL2 0x10c +#define QSERDES_V2_RX_SIGDET_ENABLES 0x110 +#define QSERDES_V2_RX_SIGDET_CNTRL 0x114 +#define QSERDES_V2_RX_SIGDET_LVL 0x118 +#define QSERDES_V2_RX_SIGDET_DEGLITCH_CNTRL 0x11c +#define QSERDES_V2_RX_RX_BAND 0x120 +#define QSERDES_V2_RX_CDR_FREEZE_UP_DN 0x124 +#define QSERDES_V2_RX_CDR_RESET_OVERRIDE 0x128 +#define QSERDES_V2_RX_RX_INTERFACE_MODE 0x12c +#define QSERDES_V2_RX_JITTER_GEN_MODE 0x130 +#define QSERDES_V2_RX_BUJ_AMP 0x134 +#define QSERDES_V2_RX_SJ_AMP1 0x138 +#define QSERDES_V2_RX_SJ_AMP2 0x13c +#define QSERDES_V2_RX_SJ_PER1 0x140 +#define QSERDES_V2_RX_SJ_PER2 0x144 +#define QSERDES_V2_RX_BUJ_STEP_FREQ1 0x148 +#define QSERDES_V2_RX_BUJ_STEP_FREQ2 0x14c +#define QSERDES_V2_RX_PPM_OFFSET1 0x150 +#define QSERDES_V2_RX_PPM_OFFSET2 0x154 +#define QSERDES_V2_RX_SIGN_PPM_PERIOD1 0x158 +#define QSERDES_V2_RX_SIGN_PPM_PERIOD2 0x15c +#define QSERDES_V2_RX_SSC_CTRL 0x160 +#define QSERDES_V2_RX_SSC_COUNT1 0x164 +#define QSERDES_V2_RX_SSC_COUNT2 0x168 +#define QSERDES_V2_RX_RX_ALOG_INTF_OBSV_CNTL 0x16c +#define QSERDES_V2_RX_RX_PWM_ENABLE_AND_DATA 0x170 +#define QSERDES_V2_RX_RX_PWM_GEAR1_TIMEOUT_COUNT 0x174 +#define QSERDES_V2_RX_RX_PWM_GEAR2_TIMEOUT_COUNT 0x178 +#define QSERDES_V2_RX_RX_PWM_GEAR3_TIMEOUT_COUNT 0x17c +#define QSERDES_V2_RX_RX_PWM_GEAR4_TIMEOUT_COUNT 0x180 +#define QSERDES_V2_RX_PI_CTRL1 0x184 +#define QSERDES_V2_RX_PI_CTRL2 0x188 +#define QSERDES_V2_RX_PI_QUAD 0x18c +#define QSERDES_V2_RX_IDATA1 0x190 +#define QSERDES_V2_RX_IDATA2 0x194 +#define QSERDES_V2_RX_AUX_DATA1 0x198 +#define QSERDES_V2_RX_AUX_DATA2 0x19c +#define QSERDES_V2_RX_AC_JTAG_OUTP 0x1a0 +#define QSERDES_V2_RX_AC_JTAG_OUTN 0x1a4 +#define QSERDES_V2_RX_RX_SIGDET 0x1a8 +#define QSERDES_V2_RX_RX_VDCOFF 0x1ac +#define QSERDES_V2_RX_IDAC_CAL_ON 0x1b0 +#define QSERDES_V2_RX_IDAC_STATUS_I 0x1b4 +#define QSERDES_V2_RX_IDAC_STATUS_IBAR 0x1b8 +#define QSERDES_V2_RX_IDAC_STATUS_Q 0x1bc +#define QSERDES_V2_RX_IDAC_STATUS_QBAR 0x1c0 +#define QSERDES_V2_RX_IDAC_STATUS_A 0x1c4 +#define QSERDES_V2_RX_IDAC_STATUS_ABAR 0x1c8 +#define QSERDES_V2_RX_CALST_STATUS_I 0x1cc +#define QSERDES_V2_RX_CALST_STATUS_Q 0x1d0 +#define QSERDES_V2_RX_CALST_STATUS_A 0x1d4 +#define QSERDES_V2_RX_RX_ALOG_INTF_OBSV 0x1d8 +#define QSERDES_V2_RX_READ_EQCODE 0x1dc +#define QSERDES_V2_RX_READ_OFFSETCODE 0x1e0 +#define QSERDES_V2_RX_IA_ERROR_COUNTER_LOW 0x1e4 +#define QSERDES_V2_RX_IA_ERROR_COUNTER_HIGH 0x1e8 #endif diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx.h b/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx.h deleted file mode 100644 index d20694513eb49..0000000000000 --- a/drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx.h +++ /dev/null @@ -1,205 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (c) 2017, The Linux Foundation. All rights reserved. - */ - -#ifndef QCOM_PHY_QMP_QSERDES_TXRX_H_ -#define QCOM_PHY_QMP_QSERDES_TXRX_H_ - -/* Only for QMP V2 PHY - TX registers */ -#define QSERDES_TX_BIST_MODE_LANENO 0x000 -#define QSERDES_TX_BIST_INVERT 0x004 -#define QSERDES_TX_CLKBUF_ENABLE 0x008 -#define QSERDES_TX_CMN_CONTROL_ONE 0x00c -#define QSERDES_TX_CMN_CONTROL_TWO 0x010 -#define QSERDES_TX_CMN_CONTROL_THREE 0x014 -#define QSERDES_TX_TX_EMP_POST1_LVL 0x018 -#define QSERDES_TX_TX_POST2_EMPH 0x01c -#define QSERDES_TX_TX_BOOST_LVL_UP_DN 0x020 -#define QSERDES_TX_HP_PD_ENABLES 0x024 -#define QSERDES_TX_TX_IDLE_LVL_LARGE_AMP 0x028 -#define QSERDES_TX_TX_DRV_LVL 0x02c -#define QSERDES_TX_TX_DRV_LVL_OFFSET 0x030 -#define QSERDES_TX_RESET_TSYNC_EN 0x034 -#define QSERDES_TX_PRE_STALL_LDO_BOOST_EN 0x038 -#define QSERDES_TX_TX_BAND 0x03c -#define QSERDES_TX_SLEW_CNTL 0x040 -#define QSERDES_TX_INTERFACE_SELECT 0x044 -#define QSERDES_TX_LPB_EN 0x048 -#define QSERDES_TX_RES_CODE_LANE_TX 0x04c -#define QSERDES_TX_RES_CODE_LANE_RX 0x050 -#define QSERDES_TX_RES_CODE_LANE_OFFSET 0x054 -#define QSERDES_TX_PERL_LENGTH1 0x058 -#define QSERDES_TX_PERL_LENGTH2 0x05c -#define QSERDES_TX_SERDES_BYP_EN_OUT 0x060 -#define QSERDES_TX_DEBUG_BUS_SEL 0x064 -#define QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN 0x068 -#define QSERDES_TX_TX_POL_INV 0x06c -#define QSERDES_TX_PARRATE_REC_DETECT_IDLE_EN 0x070 -#define QSERDES_TX_BIST_PATTERN1 0x074 -#define QSERDES_TX_BIST_PATTERN2 0x078 -#define QSERDES_TX_BIST_PATTERN3 0x07c -#define QSERDES_TX_BIST_PATTERN4 0x080 -#define QSERDES_TX_BIST_PATTERN5 0x084 -#define QSERDES_TX_BIST_PATTERN6 0x088 -#define QSERDES_TX_BIST_PATTERN7 0x08c -#define QSERDES_TX_BIST_PATTERN8 0x090 -#define QSERDES_TX_LANE_MODE 0x094 -#define QSERDES_TX_IDAC_CAL_LANE_MODE 0x098 -#define QSERDES_TX_IDAC_CAL_LANE_MODE_CONFIGURATION 0x09c -#define QSERDES_TX_ATB_SEL1 0x0a0 -#define QSERDES_TX_ATB_SEL2 0x0a4 -#define QSERDES_TX_RCV_DETECT_LVL 0x0a8 -#define QSERDES_TX_RCV_DETECT_LVL_2 0x0ac -#define QSERDES_TX_PRBS_SEED1 0x0b0 -#define QSERDES_TX_PRBS_SEED2 0x0b4 -#define QSERDES_TX_PRBS_SEED3 0x0b8 -#define QSERDES_TX_PRBS_SEED4 0x0bc -#define QSERDES_TX_RESET_GEN 0x0c0 -#define QSERDES_TX_RESET_GEN_MUXES 0x0c4 -#define QSERDES_TX_TRAN_DRVR_EMP_EN 0x0c8 -#define QSERDES_TX_TX_INTERFACE_MODE 0x0cc -#define QSERDES_TX_PWM_CTRL 0x0d0 -#define QSERDES_TX_PWM_ENCODED_OR_DATA 0x0d4 -#define QSERDES_TX_PWM_GEAR_1_DIVIDER_BAND2 0x0d8 -#define QSERDES_TX_PWM_GEAR_2_DIVIDER_BAND2 0x0dc -#define QSERDES_TX_PWM_GEAR_3_DIVIDER_BAND2 0x0e0 -#define QSERDES_TX_PWM_GEAR_4_DIVIDER_BAND2 0x0e4 -#define QSERDES_TX_PWM_GEAR_1_DIVIDER_BAND0_1 0x0e8 -#define QSERDES_TX_PWM_GEAR_2_DIVIDER_BAND0_1 0x0ec -#define QSERDES_TX_PWM_GEAR_3_DIVIDER_BAND0_1 0x0f0 -#define QSERDES_TX_PWM_GEAR_4_DIVIDER_BAND0_1 0x0f4 -#define QSERDES_TX_VMODE_CTRL1 0x0f8 -#define QSERDES_TX_VMODE_CTRL2 0x0fc -#define QSERDES_TX_TX_ALOG_INTF_OBSV_CNTL 0x100 -#define QSERDES_TX_BIST_STATUS 0x104 -#define QSERDES_TX_BIST_ERROR_COUNT1 0x108 -#define QSERDES_TX_BIST_ERROR_COUNT2 0x10c -#define QSERDES_TX_TX_ALOG_INTF_OBSV 0x110 - -/* Only for QMP V2 PHY - RX registers */ -#define QSERDES_RX_UCDR_FO_GAIN_HALF 0x000 -#define QSERDES_RX_UCDR_FO_GAIN_QUARTER 0x004 -#define QSERDES_RX_UCDR_FO_GAIN_EIGHTH 0x008 -#define QSERDES_RX_UCDR_FO_GAIN 0x00c -#define QSERDES_RX_UCDR_SO_GAIN_HALF 0x010 -#define QSERDES_RX_UCDR_SO_GAIN_QUARTER 0x014 -#define QSERDES_RX_UCDR_SO_GAIN_EIGHTH 0x018 -#define QSERDES_RX_UCDR_SO_GAIN 0x01c -#define QSERDES_RX_UCDR_SVS_FO_GAIN_HALF 0x020 -#define QSERDES_RX_UCDR_SVS_FO_GAIN_QUARTER 0x024 -#define QSERDES_RX_UCDR_SVS_FO_GAIN_EIGHTH 0x028 -#define QSERDES_RX_UCDR_SVS_FO_GAIN 0x02c -#define QSERDES_RX_UCDR_SVS_SO_GAIN_HALF 0x030 -#define QSERDES_RX_UCDR_SVS_SO_GAIN_QUARTER 0x034 -#define QSERDES_RX_UCDR_SVS_SO_GAIN_EIGHTH 0x038 -#define QSERDES_RX_UCDR_SVS_SO_GAIN 0x03c -#define QSERDES_RX_UCDR_FASTLOCK_FO_GAIN 0x040 -#define QSERDES_RX_UCDR_FD_GAIN 0x044 -#define QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE 0x048 -#define QSERDES_RX_UCDR_FO_TO_SO_DELAY 0x04c -#define QSERDES_RX_UCDR_FASTLOCK_COUNT_LOW 0x050 -#define QSERDES_RX_UCDR_FASTLOCK_COUNT_HIGH 0x054 -#define QSERDES_RX_UCDR_MODULATE 0x058 -#define QSERDES_RX_UCDR_PI_CONTROLS 0x05c -#define QSERDES_RX_RBIST_CONTROL 0x060 -#define QSERDES_RX_AUX_CONTROL 0x064 -#define QSERDES_RX_AUX_DATA_TCOARSE 0x068 -#define QSERDES_RX_AUX_DATA_TFINE_LSB 0x06c -#define QSERDES_RX_AUX_DATA_TFINE_MSB 0x070 -#define QSERDES_RX_RCLK_AUXDATA_SEL 0x074 -#define QSERDES_RX_AC_JTAG_ENABLE 0x078 -#define QSERDES_RX_AC_JTAG_INITP 0x07c -#define QSERDES_RX_AC_JTAG_INITN 0x080 -#define QSERDES_RX_AC_JTAG_LVL 0x084 -#define QSERDES_RX_AC_JTAG_MODE 0x088 -#define QSERDES_RX_AC_JTAG_RESET 0x08c -#define QSERDES_RX_RX_TERM_BW 0x090 -#define QSERDES_RX_RX_RCVR_IQ_EN 0x094 -#define QSERDES_RX_RX_IDAC_I_DC_OFFSETS 0x098 -#define QSERDES_RX_RX_IDAC_IBAR_DC_OFFSETS 0x09c -#define QSERDES_RX_RX_IDAC_Q_DC_OFFSETS 0x0a0 -#define QSERDES_RX_RX_IDAC_QBAR_DC_OFFSETS 0x0a4 -#define QSERDES_RX_RX_IDAC_A_DC_OFFSETS 0x0a8 -#define QSERDES_RX_RX_IDAC_ABAR_DC_OFFSETS 0x0ac -#define QSERDES_RX_RX_IDAC_EN 0x0b0 -#define QSERDES_RX_RX_IDAC_ENABLES 0x0b4 -#define QSERDES_RX_RX_IDAC_SIGN 0x0b8 -#define QSERDES_RX_RX_HIGHZ_HIGHRATE 0x0bc -#define QSERDES_RX_RX_TERM_AC_BYPASS_DC_COUPLE_OFFSET 0x0c0 -#define QSERDES_RX_RX_EQ_GAIN1_LSB 0x0c4 -#define QSERDES_RX_RX_EQ_GAIN1_MSB 0x0c8 -#define QSERDES_RX_RX_EQ_GAIN2_LSB 0x0cc -#define QSERDES_RX_RX_EQ_GAIN2_MSB 0x0d0 -#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1 0x0d4 -#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2 0x0d8 -#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3 0x0dc -#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4 0x0e0 -#define QSERDES_RX_RX_IDAC_CAL_CONFIGURATION 0x0e4 -#define QSERDES_RX_RX_IDAC_TSETTLE_LOW 0x0e8 -#define QSERDES_RX_RX_IDAC_TSETTLE_HIGH 0x0ec -#define QSERDES_RX_RX_IDAC_ENDSAMP_LOW 0x0f0 -#define QSERDES_RX_RX_IDAC_ENDSAMP_HIGH 0x0f4 -#define QSERDES_RX_RX_IDAC_MIDPOINT_LOW 0x0f8 -#define QSERDES_RX_RX_IDAC_MIDPOINT_HIGH 0x0fc -#define QSERDES_RX_RX_EQ_OFFSET_LSB 0x100 -#define QSERDES_RX_RX_EQ_OFFSET_MSB 0x104 -#define QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x108 -#define QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2 0x10c -#define QSERDES_RX_SIGDET_ENABLES 0x110 -#define QSERDES_RX_SIGDET_CNTRL 0x114 -#define QSERDES_RX_SIGDET_LVL 0x118 -#define QSERDES_RX_SIGDET_DEGLITCH_CNTRL 0x11c -#define QSERDES_RX_RX_BAND 0x120 -#define QSERDES_RX_CDR_FREEZE_UP_DN 0x124 -#define QSERDES_RX_CDR_RESET_OVERRIDE 0x128 -#define QSERDES_RX_RX_INTERFACE_MODE 0x12c -#define QSERDES_RX_JITTER_GEN_MODE 0x130 -#define QSERDES_RX_BUJ_AMP 0x134 -#define QSERDES_RX_SJ_AMP1 0x138 -#define QSERDES_RX_SJ_AMP2 0x13c -#define QSERDES_RX_SJ_PER1 0x140 -#define QSERDES_RX_SJ_PER2 0x144 -#define QSERDES_RX_BUJ_STEP_FREQ1 0x148 -#define QSERDES_RX_BUJ_STEP_FREQ2 0x14c -#define QSERDES_RX_PPM_OFFSET1 0x150 -#define QSERDES_RX_PPM_OFFSET2 0x154 -#define QSERDES_RX_SIGN_PPM_PERIOD1 0x158 -#define QSERDES_RX_SIGN_PPM_PERIOD2 0x15c -#define QSERDES_RX_SSC_CTRL 0x160 -#define QSERDES_RX_SSC_COUNT1 0x164 -#define QSERDES_RX_SSC_COUNT2 0x168 -#define QSERDES_RX_RX_ALOG_INTF_OBSV_CNTL 0x16c -#define QSERDES_RX_RX_PWM_ENABLE_AND_DATA 0x170 -#define QSERDES_RX_RX_PWM_GEAR1_TIMEOUT_COUNT 0x174 -#define QSERDES_RX_RX_PWM_GEAR2_TIMEOUT_COUNT 0x178 -#define QSERDES_RX_RX_PWM_GEAR3_TIMEOUT_COUNT 0x17c -#define QSERDES_RX_RX_PWM_GEAR4_TIMEOUT_COUNT 0x180 -#define QSERDES_RX_PI_CTRL1 0x184 -#define QSERDES_RX_PI_CTRL2 0x188 -#define QSERDES_RX_PI_QUAD 0x18c -#define QSERDES_RX_IDATA1 0x190 -#define QSERDES_RX_IDATA2 0x194 -#define QSERDES_RX_AUX_DATA1 0x198 -#define QSERDES_RX_AUX_DATA2 0x19c -#define QSERDES_RX_AC_JTAG_OUTP 0x1a0 -#define QSERDES_RX_AC_JTAG_OUTN 0x1a4 -#define QSERDES_RX_RX_SIGDET 0x1a8 -#define QSERDES_RX_RX_VDCOFF 0x1ac -#define QSERDES_RX_IDAC_CAL_ON 0x1b0 -#define QSERDES_RX_IDAC_STATUS_I 0x1b4 -#define QSERDES_RX_IDAC_STATUS_IBAR 0x1b8 -#define QSERDES_RX_IDAC_STATUS_Q 0x1bc -#define QSERDES_RX_IDAC_STATUS_QBAR 0x1c0 -#define QSERDES_RX_IDAC_STATUS_A 0x1c4 -#define QSERDES_RX_IDAC_STATUS_ABAR 0x1c8 -#define QSERDES_RX_CALST_STATUS_I 0x1cc -#define QSERDES_RX_CALST_STATUS_Q 0x1d0 -#define QSERDES_RX_CALST_STATUS_A 0x1d4 -#define QSERDES_RX_RX_ALOG_INTF_OBSV 0x1d8 -#define QSERDES_RX_READ_EQCODE 0x1dc -#define QSERDES_RX_READ_OFFSETCODE 0x1e0 -#define QSERDES_RX_IA_ERROR_COUNTER_LOW 0x1e4 -#define QSERDES_RX_IA_ERROR_COUNTER_HIGH 0x1e8 - -#endif diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c index b87314c8379dc..0f4ad24aa4058 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c @@ -147,71 +147,71 @@ static const struct qmp_phy_init_tbl milos_ufsphy_pcs[] = { }; static const struct qmp_phy_init_tbl msm8996_ufsphy_serdes[] = { - QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x0e), - QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0xd7), - 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_BIAS_EN_CLKBUFLR_EN, 0x08), - QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), - QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x05), - QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a), - QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV_MODE1, 0x0a), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x01), - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x10), - QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x20), - 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_TIMER1, 0xff), - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f), - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x54), - QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x05), - QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x00), - 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_VCO_TUNE1_MODE0, 0x28), - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE0, 0x02), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xff), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x0c), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE1, 0x98), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE1, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE1, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE1, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE1, 0x0b), - QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE1, 0x16), - QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE1, 0x28), - QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE1, 0x80), - QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE1, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE1, 0xd6), - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE1, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE1, 0x32), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE1, 0x0f), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CMN_CONFIG, 0x0e), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYSCLK_EN_SEL, 0xd7), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CLK_SELECT, 0x30), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYS_CLK_CTRL, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BIAS_EN_CLKBUFLR_EN, 0x08), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BG_TIMER, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_HSCLK_SEL, 0x05), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CORECLK_DIV, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CORECLK_DIV_MODE1, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP_EN, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_CTRL, 0x10), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_RESETSM_CNTRL, 0x20), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CORE_CLK_EN, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP_CFG, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_TIMER1, 0xff), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_TIMER2, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_MAP, 0x54), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SVS_MODE_CLK_SEL, 0x05), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DEC_START_MODE0, 0x82), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START1_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START2_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START3_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CP_CTRL_MODE0, 0x0b), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_CCTRL_MODE0, 0x28), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_INTEGLOOP_GAIN0_MODE0, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_INTEGLOOP_GAIN1_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE1_MODE0, 0x28), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE2_MODE0, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP1_MODE0, 0xff), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP2_MODE0, 0x0c), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP3_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DEC_START_MODE1, 0x98), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START1_MODE1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START2_MODE1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START3_MODE1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CP_CTRL_MODE1, 0x0b), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_RCTRL_MODE1, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_CCTRL_MODE1, 0x28), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_INTEGLOOP_GAIN0_MODE1, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_INTEGLOOP_GAIN1_MODE1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE1_MODE1, 0xd6), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE2_MODE1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP1_MODE1, 0x32), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP2_MODE1, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP3_MODE1, 0x00), }; static const struct qmp_phy_init_tbl msm8996_ufsphy_tx[] = { - QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), - QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V2_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), + QMP_PHY_INIT_CFG(QSERDES_V2_TX_LANE_MODE, 0x02), }; static const struct qmp_phy_init_tbl msm8996_ufsphy_rx[] = { - QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x24), - QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x02), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_INTERFACE_MODE, 0x00), - QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x18), - QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0B), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_TERM_BW, 0x5b), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_LSB, 0xff), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_MSB, 0x3f), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_LSB, 0xff), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_MSB, 0x0f), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0E), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_SIGDET_LVL, 0x24), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_SIGDET_CNTRL, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_INTERFACE_MODE, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_SIGDET_DEGLITCH_CNTRL, 0x18), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_UCDR_FASTLOCK_FO_GAIN, 0x0B), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_TERM_BW, 0x5b), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQ_GAIN1_LSB, 0xff), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQ_GAIN1_MSB, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQ_GAIN2_LSB, 0xff), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQ_GAIN2_MSB, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0E), }; static const struct qmp_phy_init_tbl sc7280_ufsphy_tx[] = { @@ -320,83 +320,83 @@ static const struct qmp_phy_init_tbl sc7280_ufsphy_hs_g4_rx[] = { }; static const struct qmp_phy_init_tbl sm6115_ufsphy_serdes[] = { - QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x0e), - QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14), - QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), - QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x02), - QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), - QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), - QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a), - QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV_MODE1, 0x0a), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x01), - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x20), - 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_TIMER1, 0xff), - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f), - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x04), - QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x05), - QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x00), - 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_VCO_TUNE1_MODE0, 0x28), - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE0, 0x02), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xff), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x0c), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE1, 0x98), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE1, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE1, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE1, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE1, 0x0b), - QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE1, 0x16), - QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE1, 0x28), - QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE1, 0x80), - QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE1, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE1, 0xd6), - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE1, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE1, 0x32), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE1, 0x0f), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE1, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), - QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_INITVAL1, 0xff), - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_INITVAL2, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CMN_CONFIG, 0x0e), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYSCLK_EN_SEL, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CLK_SELECT, 0x30), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYS_CLK_CTRL, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BIAS_EN_CLKBUFLR_EN, 0x08), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BG_TIMER, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_HSCLK_SEL, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CORECLK_DIV, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CORECLK_DIV_MODE1, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP_EN, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_CTRL, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_RESETSM_CNTRL, 0x20), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CORE_CLK_EN, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP_CFG, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_TIMER1, 0xff), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_TIMER2, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_MAP, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SVS_MODE_CLK_SEL, 0x05), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DEC_START_MODE0, 0x82), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START1_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START2_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START3_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CP_CTRL_MODE0, 0x0b), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_CCTRL_MODE0, 0x28), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_INTEGLOOP_GAIN0_MODE0, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_INTEGLOOP_GAIN1_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE1_MODE0, 0x28), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE2_MODE0, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP1_MODE0, 0xff), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP2_MODE0, 0x0c), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP3_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DEC_START_MODE1, 0x98), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START1_MODE1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START2_MODE1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START3_MODE1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CP_CTRL_MODE1, 0x0b), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_RCTRL_MODE1, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_CCTRL_MODE1, 0x28), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_INTEGLOOP_GAIN0_MODE1, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_INTEGLOOP_GAIN1_MODE1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE1_MODE1, 0xd6), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE2_MODE1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP1_MODE1, 0x32), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP2_MODE1, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP3_MODE1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_IVCO, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BG_TRIM, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_INITVAL1, 0xff), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_INITVAL2, 0x00), }; static const struct qmp_phy_init_tbl sm6115_ufsphy_hs_b_serdes[] = { - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x44), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_MAP, 0x44), }; static const struct qmp_phy_init_tbl sm6115_ufsphy_tx[] = { - QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), - QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V2_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), + QMP_PHY_INIT_CFG(QSERDES_V2_TX_LANE_MODE, 0x06), }; static const struct qmp_phy_init_tbl sm6115_ufsphy_rx[] = { - QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x24), - QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x0F), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_INTERFACE_MODE, 0x40), - QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E), - QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0B), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_TERM_BW, 0x5B), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_LSB, 0xFF), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_MSB, 0x3F), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_LSB, 0xFF), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_MSB, 0x3F), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0D), - QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN_HALF, 0x04), - QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN_QUARTER, 0x04), - QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN, 0x04), - QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x5B), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_SIGDET_LVL, 0x24), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_SIGDET_CNTRL, 0x0F), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_INTERFACE_MODE, 0x40), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_SIGDET_DEGLITCH_CNTRL, 0x1E), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_UCDR_FASTLOCK_FO_GAIN, 0x0B), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_TERM_BW, 0x5B), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQ_GAIN1_LSB, 0xFF), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQ_GAIN1_MSB, 0x3F), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQ_GAIN2_LSB, 0xFF), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQ_GAIN2_MSB, 0x3F), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0D), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_UCDR_SVS_SO_GAIN_HALF, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_UCDR_SVS_SO_GAIN_QUARTER, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_UCDR_SVS_SO_GAIN, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x5B), }; static const struct qmp_phy_init_tbl sm6115_ufsphy_pcs[] = { diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c index b0ecd5ba24648..c5507168e1354 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c @@ -244,59 +244,59 @@ static const struct qmp_phy_init_tbl glymur_usb3_uniphy_pcs_usb_tbl[] = { }; static const struct qmp_phy_init_tbl ipq9574_usb3_serdes_tbl[] = { - QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x1a), - 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_BG_TRIM, 0x0f), - QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), - 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_CMN_CONFIG, 0x06), - QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), - QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYSCLK_EN_SEL, 0x1a), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BIAS_EN_CLKBUFLR_EN, 0x08), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CLK_SELECT, 0x30), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BG_TRIM, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SVS_MODE_CLK_SEL, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_HSCLK_SEL, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CMN_CONFIG, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_IVCO, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYS_CLK_CTRL, 0x06), /* PLL and Loop filter settings */ - QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x68), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0xab), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0xaa), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x02), - QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x09), - 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, 0xa0), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xaa), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x29), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DEC_START_MODE0, 0x68), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START1_MODE0, 0xab), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START2_MODE0, 0xaa), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START3_MODE0, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CP_CTRL_MODE0, 0x09), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_CCTRL_MODE0, 0x28), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_INTEGLOOP_GAIN0_MODE0, 0xa0), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP1_MODE0, 0xaa), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP2_MODE0, 0x29), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP3_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CORE_CLK_EN, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP_CFG, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_MAP, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BG_TIMER, 0x0a), /* SSC settings */ - QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), - QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x7d), - 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, 0x0a), - QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x05), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_EN_CENTER, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_PER1, 0x7d), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_PER2, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_ADJ_PER1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_ADJ_PER2, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_STEP_SIZE1, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_STEP_SIZE2, 0x05), }; static const struct qmp_phy_init_tbl ipq9574_usb3_tx_tbl[] = { - QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), - QMP_PHY_INIT_CFG(QSERDES_TX_RCV_DETECT_LVL_2, 0x12), - QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V2_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), + QMP_PHY_INIT_CFG(QSERDES_V2_TX_RCV_DETECT_LVL_2, 0x12), + QMP_PHY_INIT_CFG(QSERDES_V2_TX_LANE_MODE, 0x06), }; static const struct qmp_phy_init_tbl ipq9574_usb3_rx_tbl[] = { - QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x06), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x6c), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4c), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xb8), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), - QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x03), - QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x16), - QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x0c), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_UCDR_SO_GAIN, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL3, 0x6c), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4c), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL4, 0xb8), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_SIGDET_CNTRL, 0x03), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_SIGDET_DEGLITCH_CNTRL, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_SIGDET_ENABLES, 0x0c), }; static const struct qmp_phy_init_tbl ipq9574_usb3_pcs_tbl[] = { @@ -326,52 +326,52 @@ static const struct qmp_phy_init_tbl ipq9574_usb3_pcs_tbl[] = { }; static const struct qmp_phy_init_tbl ipq8074_usb3_serdes_tbl[] = { - QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x1a), - 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_BG_TRIM, 0x0f), - QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), - 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_CMN_CONFIG, 0x06), - QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), - QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYSCLK_EN_SEL, 0x1a), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BIAS_EN_CLKBUFLR_EN, 0x08), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CLK_SELECT, 0x30), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BG_TRIM, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SVS_MODE_CLK_SEL, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_HSCLK_SEL, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CMN_CONFIG, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_IVCO, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYS_CLK_CTRL, 0x06), /* PLL and Loop filter settings */ - QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03), - QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), - QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), - QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), - QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x15), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x34), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DEC_START_MODE0, 0x82), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START1_MODE0, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START2_MODE0, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START3_MODE0, 0x03), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CP_CTRL_MODE0, 0x0b), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_CCTRL_MODE0, 0x28), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_INTEGLOOP_GAIN0_MODE0, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP1_MODE0, 0x15), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP2_MODE0, 0x34), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP3_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CORE_CLK_EN, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP_CFG, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_MAP, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BG_TIMER, 0x0a), /* SSC settings */ - QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), - QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), - QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), - QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0xde), - QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x07), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_EN_CENTER, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_PER1, 0x31), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_PER2, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_ADJ_PER1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_ADJ_PER2, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_STEP_SIZE1, 0xde), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_STEP_SIZE2, 0x07), }; static const struct qmp_phy_init_tbl ipq8074_usb3_rx_tbl[] = { - QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x06), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4c), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xb8), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), - QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x03), - QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x16), - QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x0), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_UCDR_SO_GAIN, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4c), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL4, 0xb8), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_SIGDET_CNTRL, 0x03), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_SIGDET_DEGLITCH_CNTRL, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_SIGDET_ENABLES, 0x0), }; static const struct qmp_phy_init_tbl ipq8074_usb3_pcs_tbl[] = { @@ -401,59 +401,59 @@ static const struct qmp_phy_init_tbl ipq8074_usb3_pcs_tbl[] = { }; static const struct qmp_phy_init_tbl msm8996_usb3_serdes_tbl[] = { - QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14), - QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), - QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), - QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), - QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), - QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), - QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), - QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYSCLK_EN_SEL, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BIAS_EN_CLKBUFLR_EN, 0x08), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CLK_SELECT, 0x30), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CMN_CONFIG, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SVS_MODE_CLK_SEL, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_HSCLK_SEL, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BG_TRIM, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_IVCO, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYS_CLK_CTRL, 0x04), /* PLL and Loop filter settings */ - QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03), - QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), - QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), - QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), - QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x15), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x34), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DEC_START_MODE0, 0x82), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START1_MODE0, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START2_MODE0, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START3_MODE0, 0x03), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CP_CTRL_MODE0, 0x0b), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_CCTRL_MODE0, 0x28), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_INTEGLOOP_GAIN0_MODE0, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_CTRL, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP1_MODE0, 0x15), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP2_MODE0, 0x34), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP3_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CORE_CLK_EN, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP_CFG, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_MAP, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BG_TIMER, 0x0a), /* SSC settings */ - QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), - QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), - QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), - QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0xde), - QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x07), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_EN_CENTER, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_PER1, 0x31), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_PER2, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_ADJ_PER1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_ADJ_PER2, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_STEP_SIZE1, 0xde), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_STEP_SIZE2, 0x07), }; static const struct qmp_phy_init_tbl msm8996_usb3_tx_tbl[] = { - QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), - QMP_PHY_INIT_CFG(QSERDES_TX_RCV_DETECT_LVL_2, 0x12), - QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V2_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), + QMP_PHY_INIT_CFG(QSERDES_V2_TX_RCV_DETECT_LVL_2, 0x12), + QMP_PHY_INIT_CFG(QSERDES_V2_TX_LANE_MODE, 0x06), }; static const struct qmp_phy_init_tbl msm8996_usb3_rx_tbl[] = { - QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), - QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x04), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4c), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xbb), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), - QMP_PHY_INIT_CFG(QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), - QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x03), - QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x18), - QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_UCDR_SO_GAIN, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4c), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQU_ADAPTOR_CNTRL4, 0xbb), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_SIGDET_CNTRL, 0x03), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_SIGDET_LVL, 0x18), + QMP_PHY_INIT_CFG(QSERDES_V2_RX_SIGDET_DEGLITCH_CNTRL, 0x16), }; static const struct qmp_phy_init_tbl msm8996_usb3_pcs_tbl[] = { diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c b/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c index dff27d30fc99a..ab3055bb5b0c1 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c @@ -177,44 +177,44 @@ static const struct qmp_phy_init_tbl msm8998_usb3_pcs_tbl[] = { }; 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), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYSCLK_EN_SEL, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BIAS_EN_CLKBUFLR_EN, 0x08), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CLK_SELECT, 0x30), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYS_CLK_CTRL, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_RESETSM_CNTRL, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_RESETSM_CNTRL2, 0x08), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BG_TRIM, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SVS_MODE_CLK_SEL, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_HSCLK_SEL, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DEC_START_MODE0, 0x82), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START1_MODE0, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START2_MODE0, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START3_MODE0, 0x03), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CP_CTRL_MODE0, 0x0b), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_CCTRL_MODE0, 0x28), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_INTEGLOOP_GAIN0_MODE0, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_INTEGLOOP_GAIN1_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CORECLK_DIV, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP1_MODE0, 0x15), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP2_MODE0, 0x34), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP3_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP_EN, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CORE_CLK_EN, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP_CFG, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_MAP, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BG_TIMER, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_EN_CENTER, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_PER1, 0x31), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_PER2, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_ADJ_PER1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_ADJ_PER2, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_STEP_SIZE1, 0xde), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SSC_STEP_SIZE2, 0x07), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_IVCO, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CMN_CONFIG, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_INTEGLOOP_INITVAL, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BIAS_EN_CTRL_BY_PSM, 0x01), }; static const struct qmp_phy_init_tbl qcm2290_usb3_tx_tbl[] = { @@ -290,81 +290,81 @@ static const struct qmp_phy_init_tbl qcm2290_usb3_pcs_tbl[] = { QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x88), }; -static const struct qmp_phy_init_tbl qmp_v2_dp_serdes_tbl[] = { - QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), - QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x37), - QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06), - QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x3f), - QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x0e), - QMP_PHY_INIT_CFG(QSERDES_COM_BG_CTRL, 0x0f), - QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_BUF_ENABLE, 0x06), - QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), - QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), - QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), - QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), - QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), - QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x40), - QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x08), - QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x05), - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE0, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE0, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x0f), - QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x02), +static const struct qmp_phy_init_tbl qcs615_dp_serdes_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SVS_MODE_CLK_SEL, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYSCLK_EN_SEL, 0x37), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CLK_SELECT, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYS_CLK_CTRL, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BIAS_EN_CLKBUFLR_EN, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CLK_ENABLE1, 0x0e), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BG_CTRL, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_SYSCLK_BUF_ENABLE, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CLK_SELECT, 0x30), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_IVCO, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_CCTRL_MODE0, 0x28), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CP_CTRL_MODE0, 0x0b), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_INTEGLOOP_GAIN0_MODE0, 0x40), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_INTEGLOOP_GAIN1_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_MAP, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_BG_TIMER, 0x08), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CORECLK_DIV, 0x05), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_CTRL, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE1_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE2_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_VCO_TUNE_CTRL, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CORE_CLK_EN, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_CMN_CONFIG, 0x02), }; -static const struct qmp_phy_init_tbl qmp_v2_dp_serdes_tbl_rbr[] = { - QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x2c), - QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x69), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x80), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x07), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xbf), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x21), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), +static const struct qmp_phy_init_tbl qcs615_dp_serdes_tbl_rbr[] = { + QMP_PHY_INIT_CFG(QSERDES_V2_COM_HSCLK_SEL, 0x2c), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DEC_START_MODE0, 0x69), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START1_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START2_MODE0, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START3_MODE0, 0x07), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP1_MODE0, 0xbf), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP2_MODE0, 0x21), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP3_MODE0, 0x00), }; -static const struct qmp_phy_init_tbl qmp_v2_dp_serdes_tbl_hbr[] = { - QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x24), - QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x69), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x80), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x07), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x3f), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x38), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), +static const struct qmp_phy_init_tbl qcs615_dp_serdes_tbl_hbr[] = { + QMP_PHY_INIT_CFG(QSERDES_V2_COM_HSCLK_SEL, 0x24), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DEC_START_MODE0, 0x69), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START1_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START2_MODE0, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START3_MODE0, 0x07), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP1_MODE0, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP2_MODE0, 0x38), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP3_MODE0, 0x00), }; -static const struct qmp_phy_init_tbl qmp_v2_dp_serdes_tbl_hbr2[] = { - QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x20), - QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x8c), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00), - QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x0a), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x7f), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x70), - QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), +static const struct qmp_phy_init_tbl qcs615_dp_serdes_tbl_hbr2[] = { + QMP_PHY_INIT_CFG(QSERDES_V2_COM_HSCLK_SEL, 0x20), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DEC_START_MODE0, 0x8c), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START1_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START2_MODE0, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_DIV_FRAC_START3_MODE0, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP1_MODE0, 0x7f), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP2_MODE0, 0x70), + QMP_PHY_INIT_CFG(QSERDES_V2_COM_LOCK_CMP3_MODE0, 0x00), }; -static const struct qmp_phy_init_tbl qmp_v2_dp_tx_tbl[] = { - QMP_PHY_INIT_CFG(QSERDES_V2_TX_TRANSCEIVER_BIAS_EN, 0x1a), - QMP_PHY_INIT_CFG(QSERDES_V2_TX_VMODE_CTRL1, 0x40), - QMP_PHY_INIT_CFG(QSERDES_V2_TX_PRE_STALL_LDO_BOOST_EN, 0x30), - QMP_PHY_INIT_CFG(QSERDES_V2_TX_INTERFACE_SELECT, 0x3d), - QMP_PHY_INIT_CFG(QSERDES_V2_TX_CLKBUF_ENABLE, 0x0f), - QMP_PHY_INIT_CFG(QSERDES_V2_TX_RESET_TSYNC_EN, 0x03), - QMP_PHY_INIT_CFG(QSERDES_V2_TX_TRAN_DRVR_EMP_EN, 0x03), - QMP_PHY_INIT_CFG(QSERDES_V2_TX_PARRATE_REC_DETECT_IDLE_EN, 0x00), - QMP_PHY_INIT_CFG(QSERDES_V2_TX_TX_INTERFACE_MODE, 0x00), - QMP_PHY_INIT_CFG(QSERDES_V2_TX_TX_EMP_POST1_LVL, 0x2b), - QMP_PHY_INIT_CFG(QSERDES_V2_TX_TX_DRV_LVL, 0x2f), - QMP_PHY_INIT_CFG(QSERDES_V2_TX_TX_BAND, 0x4), - QMP_PHY_INIT_CFG(QSERDES_V2_TX_RES_CODE_LANE_OFFSET_TX, 0x12), - QMP_PHY_INIT_CFG(QSERDES_V2_TX_RES_CODE_LANE_OFFSET_RX, 0x12), +static const struct qmp_phy_init_tbl qcs615_dp_tx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V3_TX_TRANSCEIVER_BIAS_EN, 0x1a), + QMP_PHY_INIT_CFG(QSERDES_V3_TX_VMODE_CTRL1, 0x40), + QMP_PHY_INIT_CFG(QSERDES_V3_TX_PRE_STALL_LDO_BOOST_EN, 0x30), + QMP_PHY_INIT_CFG(QSERDES_V3_TX_INTERFACE_SELECT, 0x3d), + QMP_PHY_INIT_CFG(QSERDES_V3_TX_CLKBUF_ENABLE, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V3_TX_RESET_TSYNC_EN, 0x03), + QMP_PHY_INIT_CFG(QSERDES_V3_TX_TRAN_DRVR_EMP_EN, 0x03), + QMP_PHY_INIT_CFG(QSERDES_V3_TX_PARRATE_REC_DETECT_IDLE_EN, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_INTERFACE_MODE, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_EMP_POST1_LVL, 0x2b), + QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_DRV_LVL, 0x2f), + QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_BAND, 0x4), + QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x12), + QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x12), }; struct qmp_usbc_offsets { @@ -555,14 +555,14 @@ static const struct qmp_usbc_offsets qmp_usbc_usb3dp_offsets_qcs615 = { .dp_dp_phy = 0x1000, }; -static const u8 qmp_v2_dp_pre_emphasis_hbr2_rbr[4][4] = { +static const u8 qcs615_dp_pre_emphasis_hbr2_rbr[4][4] = { {0x00, 0x0b, 0x12, 0xff}, {0x00, 0x0a, 0x12, 0xff}, {0x00, 0x0c, 0xff, 0xff}, {0xff, 0xff, 0xff, 0xff} }; -static const u8 qmp_v2_dp_voltage_swing_hbr2_rbr[4][4] = { +static const u8 qcs615_dp_voltage_swing_hbr2_rbr[4][4] = { {0x07, 0x0f, 0x14, 0xff}, {0x11, 0x1d, 0x1f, 0xff}, {0x18, 0x1f, 0xff, 0xff}, @@ -641,10 +641,10 @@ static const struct qmp_phy_cfg qcs615_usb3phy_cfg = { .regs = qmp_v3_usb3phy_regs_layout_qcm2290, }; -static void qmp_v2_dp_aux_init(struct qmp_usbc *qmp); -static void qmp_v2_configure_dp_tx(struct qmp_usbc *qmp); -static int qmp_v2_configure_dp_phy(struct qmp_usbc *qmp); -static int qmp_v2_calibrate_dp_phy(struct qmp_usbc *qmp); +static void qcs615_qmp_dp_aux_init(struct qmp_usbc *qmp); +static void qcs615_qmp_configure_dp_tx(struct qmp_usbc *qmp); +static int qcs615_qmp_configure_dp_phy(struct qmp_usbc *qmp); +static int qcs615_qmp_calibrate_dp_phy(struct qmp_usbc *qmp); static const struct qmp_phy_cfg qcs615_usb3dp_phy_cfg = { .offsets = &qmp_usbc_usb3dp_offsets_qcs615, @@ -660,25 +660,25 @@ static const struct qmp_phy_cfg qcs615_usb3dp_phy_cfg = { .regs = qmp_v3_usb3phy_regs_layout_qcm2290, - .dp_serdes_tbl = qmp_v2_dp_serdes_tbl, - .dp_serdes_tbl_num = ARRAY_SIZE(qmp_v2_dp_serdes_tbl), - .dp_tx_tbl = qmp_v2_dp_tx_tbl, - .dp_tx_tbl_num = ARRAY_SIZE(qmp_v2_dp_tx_tbl), + .dp_serdes_tbl = qcs615_dp_serdes_tbl, + .dp_serdes_tbl_num = ARRAY_SIZE(qcs615_dp_serdes_tbl), + .dp_tx_tbl = qcs615_dp_tx_tbl, + .dp_tx_tbl_num = ARRAY_SIZE(qcs615_dp_tx_tbl), - .serdes_tbl_rbr = qmp_v2_dp_serdes_tbl_rbr, - .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v2_dp_serdes_tbl_rbr), - .serdes_tbl_hbr = qmp_v2_dp_serdes_tbl_hbr, - .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v2_dp_serdes_tbl_hbr), - .serdes_tbl_hbr2 = qmp_v2_dp_serdes_tbl_hbr2, - .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v2_dp_serdes_tbl_hbr2), + .serdes_tbl_rbr = qcs615_dp_serdes_tbl_rbr, + .serdes_tbl_rbr_num = ARRAY_SIZE(qcs615_dp_serdes_tbl_rbr), + .serdes_tbl_hbr = qcs615_dp_serdes_tbl_hbr, + .serdes_tbl_hbr_num = ARRAY_SIZE(qcs615_dp_serdes_tbl_hbr), + .serdes_tbl_hbr2 = qcs615_dp_serdes_tbl_hbr2, + .serdes_tbl_hbr2_num = ARRAY_SIZE(qcs615_dp_serdes_tbl_hbr2), - .swing_tbl = &qmp_v2_dp_voltage_swing_hbr2_rbr, - .pre_emphasis_tbl = &qmp_v2_dp_pre_emphasis_hbr2_rbr, + .swing_tbl = &qcs615_dp_voltage_swing_hbr2_rbr, + .pre_emphasis_tbl = &qcs615_dp_pre_emphasis_hbr2_rbr, - .dp_aux_init = qmp_v2_dp_aux_init, - .configure_dp_tx = qmp_v2_configure_dp_tx, - .configure_dp_phy = qmp_v2_configure_dp_phy, - .calibrate_dp_phy = qmp_v2_calibrate_dp_phy, + .dp_aux_init = qcs615_qmp_dp_aux_init, + .configure_dp_tx = qcs615_qmp_configure_dp_tx, + .configure_dp_phy = qcs615_qmp_configure_dp_phy, + .calibrate_dp_phy = qcs615_qmp_calibrate_dp_phy, .reset_list = usb3dpphy_reset_l, .num_resets = ARRAY_SIZE(usb3dpphy_reset_l), @@ -744,7 +744,7 @@ static int qmp_usbc_com_exit(struct phy *phy) return 0; } -static void qmp_v2_dp_aux_init(struct qmp_usbc *qmp) +static void qcs615_qmp_dp_aux_init(struct qmp_usbc *qmp) { writel(DP_PHY_PD_CTL_AUX_PWRDN | DP_PHY_PD_CTL_LANE_0_1_PWRDN | DP_PHY_PD_CTL_LANE_2_3_PWRDN | @@ -774,7 +774,7 @@ static void qmp_v2_dp_aux_init(struct qmp_usbc *qmp) qmp->dp_dp_phy + QSERDES_V2_DP_PHY_AUX_INTERRUPT_MASK); } -static int qmp_v2_configure_dp_swing(struct qmp_usbc *qmp) +static int qcs615_qmp_configure_dp_swing(struct qmp_usbc *qmp) { const struct qmp_phy_cfg *cfg = qmp->cfg; const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; @@ -809,10 +809,10 @@ static int qmp_v2_configure_dp_swing(struct qmp_usbc *qmp) if (voltage_swing_cfg == 0xff && pre_emphasis_cfg == 0xff) return -EINVAL; - writel(voltage_swing_cfg, tx + QSERDES_V2_TX_TX_DRV_LVL); - writel(pre_emphasis_cfg, tx + QSERDES_V2_TX_TX_EMP_POST1_LVL); - writel(voltage_swing_cfg, tx2 + QSERDES_V2_TX_TX_DRV_LVL); - writel(pre_emphasis_cfg, tx2 + QSERDES_V2_TX_TX_EMP_POST1_LVL); + writel(voltage_swing_cfg, tx + QSERDES_V3_TX_TX_DRV_LVL); + writel(pre_emphasis_cfg, tx + QSERDES_V3_TX_TX_EMP_POST1_LVL); + writel(voltage_swing_cfg, tx2 + QSERDES_V3_TX_TX_DRV_LVL); + writel(pre_emphasis_cfg, tx2 + QSERDES_V3_TX_TX_EMP_POST1_LVL); return 0; } @@ -864,30 +864,30 @@ static int qmp_usbc_configure_dp_clocks(struct qmp_usbc *qmp) return 0; } -static void qmp_v2_configure_dp_tx(struct qmp_usbc *qmp) +static void qcs615_qmp_configure_dp_tx(struct qmp_usbc *qmp) { const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; void __iomem *tx = qmp->dp_tx; void __iomem *tx2 = qmp->dp_tx2; /* program default setting first */ - writel(0x2a, tx + QSERDES_V2_TX_TX_DRV_LVL); - writel(0x20, tx + QSERDES_V2_TX_TX_EMP_POST1_LVL); - writel(0x2a, tx2 + QSERDES_V2_TX_TX_DRV_LVL); - writel(0x20, tx2 + QSERDES_V2_TX_TX_EMP_POST1_LVL); + writel(0x2a, tx + QSERDES_V3_TX_TX_DRV_LVL); + writel(0x20, tx + QSERDES_V3_TX_TX_EMP_POST1_LVL); + writel(0x2a, tx2 + QSERDES_V3_TX_TX_DRV_LVL); + writel(0x20, tx2 + QSERDES_V3_TX_TX_EMP_POST1_LVL); if (dp_opts->link_rate >= 2700) { - writel(0xc4, tx + QSERDES_V2_TX_LANE_MODE_1); - writel(0xc4, tx2 + QSERDES_V2_TX_LANE_MODE_1); + writel(0xc4, tx + QSERDES_V3_TX_LANE_MODE_1); + writel(0xc4, tx2 + QSERDES_V3_TX_LANE_MODE_1); } else { - writel(0xc6, tx + QSERDES_V2_TX_LANE_MODE_1); - writel(0xc6, tx2 + QSERDES_V2_TX_LANE_MODE_1); + writel(0xc6, tx + QSERDES_V3_TX_LANE_MODE_1); + writel(0xc6, tx2 + QSERDES_V3_TX_LANE_MODE_1); } - qmp_v2_configure_dp_swing(qmp); + qcs615_qmp_configure_dp_swing(qmp); } -static int qmp_v2_configure_dp_phy(struct qmp_usbc *qmp) +static int qcs615_qmp_configure_dp_phy(struct qmp_usbc *qmp) { u32 status; int ret; @@ -906,9 +906,9 @@ static int qmp_v2_configure_dp_phy(struct qmp_usbc *qmp) writel(0x01, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); writel(0x09, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); - writel(0x20, qmp->dp_serdes + QSERDES_COM_RESETSM_CNTRL); + writel(0x20, qmp->dp_serdes + QSERDES_V2_COM_RESETSM_CNTRL); - if (readl_poll_timeout(qmp->dp_serdes + QSERDES_COM_C_READY_STATUS, + if (readl_poll_timeout(qmp->dp_serdes + QSERDES_V2_COM_C_READY_STATUS, status, ((status & BIT(0)) > 0), 500, @@ -917,7 +917,7 @@ static int qmp_v2_configure_dp_phy(struct qmp_usbc *qmp) return -ETIMEDOUT; } - if (readl_poll_timeout(qmp->dp_serdes + QSERDES_COM_CMN_STATUS, + if (readl_poll_timeout(qmp->dp_serdes + QSERDES_V2_COM_CMN_STATUS, status, ((status & BIT(0)) > 0), 500, @@ -926,7 +926,7 @@ static int qmp_v2_configure_dp_phy(struct qmp_usbc *qmp) return -ETIMEDOUT; } - if (readl_poll_timeout(qmp->dp_serdes + QSERDES_COM_CMN_STATUS, + if (readl_poll_timeout(qmp->dp_serdes + QSERDES_V2_COM_CMN_STATUS, status, ((status & BIT(1)) > 0), 500, @@ -955,12 +955,12 @@ static int qmp_v2_configure_dp_phy(struct qmp_usbc *qmp) return -ETIMEDOUT; } - writel(0x3f, qmp->dp_tx + QSERDES_V2_TX_TRANSCEIVER_BIAS_EN); - writel(0x10, qmp->dp_tx + QSERDES_V2_TX_HIGHZ_DRVR_EN); - writel(0x0a, qmp->dp_tx + QSERDES_V2_TX_TX_POL_INV); - writel(0x3f, qmp->dp_tx2 + QSERDES_V2_TX_TRANSCEIVER_BIAS_EN); - writel(0x10, qmp->dp_tx2 + QSERDES_V2_TX_HIGHZ_DRVR_EN); - writel(0x0a, qmp->dp_tx2 + QSERDES_V2_TX_TX_POL_INV); + writel(0x3f, qmp->dp_tx + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); + writel(0x10, qmp->dp_tx + QSERDES_V3_TX_HIGHZ_DRVR_EN); + writel(0x0a, qmp->dp_tx + QSERDES_V3_TX_TX_POL_INV); + writel(0x3f, qmp->dp_tx2 + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); + writel(0x10, qmp->dp_tx2 + QSERDES_V3_TX_HIGHZ_DRVR_EN); + writel(0x0a, qmp->dp_tx2 + QSERDES_V3_TX_TX_POL_INV); writel(0x18, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); writel(0x19, qmp->dp_dp_phy + QSERDES_DP_PHY_CFG); @@ -977,7 +977,7 @@ static int qmp_v2_configure_dp_phy(struct qmp_usbc *qmp) return 0; } -static int qmp_v2_calibrate_dp_phy(struct qmp_usbc *qmp) +static int qcs615_qmp_calibrate_dp_phy(struct qmp_usbc *qmp) { static const u8 cfg1_settings[] = {0x13, 0x23, 0x1d}; u8 val; diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h index a873bdd7bffe6..11b7e03b4fab7 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp.h +++ b/drivers/phy/qualcomm/phy-qcom-qmp.h @@ -6,9 +6,6 @@ #ifndef QCOM_PHY_QMP_H_ #define QCOM_PHY_QMP_H_ -#include "phy-qcom-qmp-qserdes-com.h" -#include "phy-qcom-qmp-qserdes-txrx.h" - #include "phy-qcom-qmp-qserdes-com-v2.h" #include "phy-qcom-qmp-qserdes-txrx-v2.h" diff --git a/drivers/phy/qualcomm/phy-qcom-usb-hs.c b/drivers/phy/qualcomm/phy-qcom-usb-hs.c index 98a18987f1bec..928a982a8a76c 100644 --- a/drivers/phy/qualcomm/phy-qcom-usb-hs.c +++ b/drivers/phy/qualcomm/phy-qcom-usb-hs.c @@ -34,9 +34,9 @@ struct qcom_usb_hs_phy { struct regulator *v1p8; struct regulator *v3p3; struct reset_control *reset; - struct ulpi_seq *init_seq; struct extcon_dev *vbus_edev; struct notifier_block vbus_notify; + struct ulpi_seq init_seq[]; }; static int qcom_usb_hs_phy_set_mode(struct phy *phy, @@ -209,19 +209,16 @@ static int qcom_usb_hs_phy_probe(struct ulpi *ulpi) int size; int ret; - uphy = devm_kzalloc(&ulpi->dev, sizeof(*uphy), GFP_KERNEL); + size = of_property_count_u8_elems(ulpi->dev.of_node, "qcom,init-seq"); + if (size < 0) + size = 0; + + uphy = devm_kzalloc(&ulpi->dev, struct_size(uphy, init_seq, (size / 2) + 1), GFP_KERNEL); if (!uphy) return -ENOMEM; ulpi_set_drvdata(ulpi, uphy); uphy->ulpi = ulpi; - size = of_property_count_u8_elems(ulpi->dev.of_node, "qcom,init-seq"); - if (size < 0) - size = 0; - uphy->init_seq = devm_kmalloc_array(&ulpi->dev, (size / 2) + 1, - sizeof(*uphy->init_seq), GFP_KERNEL); - if (!uphy->init_seq) - return -ENOMEM; ret = of_property_read_u8_array(ulpi->dev.of_node, "qcom,init-seq", (u8 *)uphy->init_seq, size); if (ret && size) diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c index 79e820e2fe55d..9a45d840efeb2 100644 --- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c +++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c @@ -314,13 +314,11 @@ static void rcar_gen3_init_from_a_peri_to_a_host(struct rcar_gen3_chan *ch) static bool rcar_gen3_check_id(struct rcar_gen3_chan *ch) { if (ch->phy_data->vblvl_ctrl) { - bool vbus_valid; - bool device; + u32 val = readl(ch->base + USB2_ADPCTRL); + bool vbus_valid = val & USB2_ADPCTRL_VBUSVALID; + bool device = val & USB2_ADPCTRL_IDDIG; - device = !!(readl(ch->base + USB2_ADPCTRL) & USB2_ADPCTRL_IDDIG); - vbus_valid = !!(readl(ch->base + USB2_ADPCTRL) & USB2_ADPCTRL_VBUSVALID); - - return vbus_valid ? device : !device; + return device == vbus_valid; } if (!ch->uses_otg_pins) diff --git a/drivers/phy/renesas/phy-rzg3e-usb3.c b/drivers/phy/renesas/phy-rzg3e-usb3.c index 6b3453ea0004c..060309547ea52 100644 --- a/drivers/phy/renesas/phy-rzg3e-usb3.c +++ b/drivers/phy/renesas/phy-rzg3e-usb3.c @@ -78,13 +78,11 @@ static void rzg3e_phy_usb2test_phy_init(void __iomem *base) writel(val, base + USB3_TEST_UTMICTRL2); val = readl(base + USB3_TEST_PRMCTRL5_R); - val &= ~USB3_TEST_PRMCTRL5_R_TXPREEMPAMPTUNE0_MASK; - val |= FIELD_PREP(USB3_TEST_PRMCTRL5_R_TXPREEMPAMPTUNE0_MASK, 2); + FIELD_MODIFY(USB3_TEST_PRMCTRL5_R_TXPREEMPAMPTUNE0_MASK, &val, 2); writel(val, base + USB3_TEST_PRMCTRL5_R); val = readl(base + USB3_TEST_PRMCTRL6_R); - val &= ~USB3_TEST_PRMCTRL6_R_OTGTUNE0_MASK; - val |= FIELD_PREP(USB3_TEST_PRMCTRL6_R_OTGTUNE0_MASK, 7); + FIELD_MODIFY(USB3_TEST_PRMCTRL6_R_OTGTUNE0_MASK, &val, 7); writel(val, base + USB3_TEST_PRMCTRL6_R); val = readl(base + USB3_TEST_RESET); @@ -256,4 +254,4 @@ module_platform_driver(rzg3e_phy_usb3_driver); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Renesas RZ/G3E USB3.0 PHY Driver"); -MODULE_AUTHOR("biju.das.jz@bp.renesas.com>"); +MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>"); diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c index 8f4c08e599aa2..7d8a533f24aea 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c @@ -170,7 +170,8 @@ struct rockchip_usb2phy_port_cfg { * @reg: the address offset of grf for usb-phy config. * @num_ports: specify how many ports that the phy has. * @phy_tuning: phy default parameters tuning. - * @clkout_ctl: keep on/turn off output clk of phy. + * @clkout_ctl: register to enable output clk of phy, when set in GRF + * @clkout_ctl_phy: register to enable output clk of phy, when set inside phy * @port_cfgs: usb-phy port configurations. * @chg_det: charger detection registers. */ @@ -179,6 +180,7 @@ struct rockchip_usb2phy_cfg { unsigned int num_ports; int (*phy_tuning)(struct rockchip_usb2phy *rphy); struct usb2phy_reg clkout_ctl; + struct usb2phy_reg clkout_ctl_phy; const struct rockchip_usb2phy_port_cfg port_cfgs[USB2PHY_NUM_PORTS]; const struct rockchip_chg_det_reg chg_det; }; @@ -228,7 +230,7 @@ struct rockchip_usb2phy_port { * struct rockchip_usb2phy - usb2.0 phy driver data. * @dev: pointer to device. * @grf: General Register Files regmap. - * @usbgrf: USB General Register Files regmap. + * @phy_base: USB PHY regmap. * @clks: array of phy input clocks. * @clk480m: clock struct of phy output clk. * @clk480m_hw: clock struct of phy output clk management. @@ -246,7 +248,7 @@ struct rockchip_usb2phy_port { struct rockchip_usb2phy { struct device *dev; struct regmap *grf; - struct regmap *usbgrf; + struct regmap *phy_base; struct clk_bulk_data *clks; struct clk *clk480m; struct clk_hw clk480m_hw; @@ -261,11 +263,6 @@ struct rockchip_usb2phy { struct rockchip_usb2phy_port ports[USB2PHY_NUM_PORTS]; }; -static inline struct regmap *get_reg_base(struct rockchip_usb2phy *rphy) -{ - return rphy->usbgrf == NULL ? rphy->grf : rphy->usbgrf; -} - static inline int property_enable(struct regmap *base, const struct usb2phy_reg *reg, bool en) { @@ -319,16 +316,33 @@ static void rockchip_usb2phy_clk_bulk_disable(void *data) clk_bulk_disable_unprepare(rphy->num_clks, rphy->clks); } -static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw) +static void +rockchip_usb2phy_clk480m_clkout_ctl(struct clk_hw *hw, struct regmap **base, + const struct usb2phy_reg **clkout_ctl) { struct rockchip_usb2phy *rphy = container_of(hw, struct rockchip_usb2phy, clk480m_hw); - struct regmap *base = get_reg_base(rphy); + + if (rphy->phy_cfg->clkout_ctl_phy.enable) { + *base = rphy->phy_base; + *clkout_ctl = &rphy->phy_cfg->clkout_ctl_phy; + } else { + *base = rphy->grf; + *clkout_ctl = &rphy->phy_cfg->clkout_ctl; + } +} + +static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw) +{ + const struct usb2phy_reg *clkout_ctl; + struct regmap *base; int ret; + rockchip_usb2phy_clk480m_clkout_ctl(hw, &base, &clkout_ctl); + /* turn on 480m clk output if it is off */ - if (!property_enabled(base, &rphy->phy_cfg->clkout_ctl)) { - ret = property_enable(base, &rphy->phy_cfg->clkout_ctl, true); + if (!property_enabled(base, clkout_ctl)) { + ret = property_enable(base, clkout_ctl, true); if (ret) return ret; @@ -341,21 +355,23 @@ static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw) static void rockchip_usb2phy_clk480m_unprepare(struct clk_hw *hw) { - struct rockchip_usb2phy *rphy = - container_of(hw, struct rockchip_usb2phy, clk480m_hw); - struct regmap *base = get_reg_base(rphy); + const struct usb2phy_reg *clkout_ctl; + struct regmap *base; + + rockchip_usb2phy_clk480m_clkout_ctl(hw, &base, &clkout_ctl); /* turn off 480m clk output */ - property_enable(base, &rphy->phy_cfg->clkout_ctl, false); + property_enable(base, clkout_ctl, false); } static int rockchip_usb2phy_clk480m_prepared(struct clk_hw *hw) { - struct rockchip_usb2phy *rphy = - container_of(hw, struct rockchip_usb2phy, clk480m_hw); - struct regmap *base = get_reg_base(rphy); + const struct usb2phy_reg *clkout_ctl; + struct regmap *base; - return property_enabled(base, &rphy->phy_cfg->clkout_ctl); + rockchip_usb2phy_clk480m_clkout_ctl(hw, &base, &clkout_ctl); + + return property_enabled(base, clkout_ctl); } static unsigned long @@ -574,7 +590,6 @@ static int rockchip_usb2phy_power_on(struct phy *phy) { struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy); struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); - struct regmap *base = get_reg_base(rphy); int ret; dev_dbg(&rport->phy->dev, "port power on\n"); @@ -586,7 +601,7 @@ static int rockchip_usb2phy_power_on(struct phy *phy) if (ret) return ret; - ret = property_enable(base, &rport->port_cfg->phy_sus, false); + ret = property_enable(rphy->grf, &rport->port_cfg->phy_sus, false); if (ret) { clk_disable_unprepare(rphy->clk480m); return ret; @@ -615,7 +630,6 @@ static int rockchip_usb2phy_power_off(struct phy *phy) { struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy); struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); - struct regmap *base = get_reg_base(rphy); int ret; dev_dbg(&rport->phy->dev, "port power off\n"); @@ -623,7 +637,7 @@ static int rockchip_usb2phy_power_off(struct phy *phy) if (rport->suspended) return 0; - ret = property_enable(base, &rport->port_cfg->phy_sus, true); + ret = property_enable(rphy->grf, &rport->port_cfg->phy_sus, true); if (ret) return ret; @@ -787,28 +801,22 @@ static const char *chg_to_string(enum power_supply_type chg_type) static void rockchip_chg_enable_dcd(struct rockchip_usb2phy *rphy, bool en) { - struct regmap *base = get_reg_base(rphy); - - property_enable(base, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en); - property_enable(base, &rphy->phy_cfg->chg_det.idp_src_en, en); + property_enable(rphy->grf, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en); + property_enable(rphy->grf, &rphy->phy_cfg->chg_det.idp_src_en, en); } static void rockchip_chg_enable_primary_det(struct rockchip_usb2phy *rphy, bool en) { - struct regmap *base = get_reg_base(rphy); - - property_enable(base, &rphy->phy_cfg->chg_det.vdp_src_en, en); - property_enable(base, &rphy->phy_cfg->chg_det.idm_sink_en, en); + property_enable(rphy->grf, &rphy->phy_cfg->chg_det.vdp_src_en, en); + property_enable(rphy->grf, &rphy->phy_cfg->chg_det.idm_sink_en, en); } static void rockchip_chg_enable_secondary_det(struct rockchip_usb2phy *rphy, bool en) { - struct regmap *base = get_reg_base(rphy); - - property_enable(base, &rphy->phy_cfg->chg_det.vdm_src_en, en); - property_enable(base, &rphy->phy_cfg->chg_det.idp_sink_en, en); + property_enable(rphy->grf, &rphy->phy_cfg->chg_det.vdm_src_en, en); + property_enable(rphy->grf, &rphy->phy_cfg->chg_det.idp_sink_en, en); } #define CHG_DCD_POLL_TIME (100 * HZ / 1000) @@ -820,7 +828,6 @@ static void rockchip_chg_detect_work(struct work_struct *work) struct rockchip_usb2phy_port *rport = container_of(work, struct rockchip_usb2phy_port, chg_work.work); struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); - struct regmap *base = get_reg_base(rphy); bool is_dcd, tmout, vout, vbus_attach; unsigned long delay; @@ -834,7 +841,7 @@ static void rockchip_chg_detect_work(struct work_struct *work) rockchip_usb2phy_power_off(rport->phy); /* put the controller in non-driving mode */ if (!vbus_attach) - property_enable(base, &rphy->phy_cfg->chg_det.opmode, false); + property_enable(rphy->grf, &rphy->phy_cfg->chg_det.opmode, false); /* Start DCD processing stage 1 */ rockchip_chg_enable_dcd(rphy, true); rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD; @@ -898,7 +905,7 @@ static void rockchip_chg_detect_work(struct work_struct *work) case USB_CHG_STATE_DETECTED: /* put the controller in normal mode */ if (!vbus_attach) - property_enable(base, &rphy->phy_cfg->chg_det.opmode, true); + property_enable(rphy->grf, &rphy->phy_cfg->chg_det.opmode, true); rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work); dev_dbg(&rport->phy->dev, "charger = %s\n", chg_to_string(rphy->chg_type)); @@ -1353,27 +1360,18 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev) if (!rphy) return -ENOMEM; - if (!dev->parent || !dev->parent->of_node) { + if (!dev->parent || !dev->parent->of_node || + of_property_present(np, "rockchip,usbgrf")) { + rphy->phy_base = device_node_to_regmap(np); + if (IS_ERR(rphy->phy_base)) + return PTR_ERR(rphy->phy_base); rphy->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,usbgrf"); - if (IS_ERR(rphy->grf)) { - dev_err(dev, "failed to locate usbgrf\n"); - return PTR_ERR(rphy->grf); - } } else { rphy->grf = syscon_node_to_regmap(dev->parent->of_node); - if (IS_ERR(rphy->grf)) - return PTR_ERR(rphy->grf); - } - - if (of_device_is_compatible(np, "rockchip,rv1108-usb2phy")) { - rphy->usbgrf = - syscon_regmap_lookup_by_phandle(dev->of_node, - "rockchip,usbgrf"); - if (IS_ERR(rphy->usbgrf)) - return PTR_ERR(rphy->usbgrf); - } else { - rphy->usbgrf = NULL; + rphy->phy_base = rphy->grf; } + if (IS_ERR(rphy->grf)) + return PTR_ERR(rphy->grf); if (of_property_read_u32_index(np, "reg", 0, ®)) { dev_err(dev, "the reg property is not assigned in %pOFn node\n", np); @@ -1514,6 +1512,38 @@ static int rk3128_usb2phy_tuning(struct rockchip_usb2phy *rphy) BIT(2) << BIT_WRITEABLE_SHIFT | 0); } +static int rk3528_usb2phy_tuning(struct rockchip_usb2phy *rphy) +{ + int ret; + + /* Turn off otg port differential receiver in suspend mode */ + ret = regmap_write(rphy->phy_base, 0x30, BIT(18) | 0x0000); + if (ret) + return ret; + + /* Turn off host port differential receiver in suspend mode */ + ret = regmap_write(rphy->phy_base, 0x430, BIT(18) | 0x0000); + if (ret) + return ret; + + /* Set otg port HS eye height to 400mv (default is 450mv) */ + ret = regmap_write(rphy->phy_base, 0x30, GENMASK(22, 20) | 0x0000); + if (ret) + return ret; + + /* Set host port HS eye height to 400mv (default is 450mv) */ + ret = regmap_write(rphy->phy_base, 0x430, GENMASK(22, 20) | 0x0000); + if (ret) + return ret; + + /* Choose the Tx fs/ls data as linestate from TX driver for otg port */ + ret = regmap_write(rphy->phy_base, 0x94, GENMASK(22, 19) | 0x0018); + if (ret) + return ret; + + return 0; +} + static int rk3576_usb2phy_tuning(struct rockchip_usb2phy *rphy) { int ret; @@ -1927,6 +1957,57 @@ static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = { { /* sentinel */ } }; +static const struct rockchip_usb2phy_cfg rk3528_phy_cfgs[] = { + { + .reg = 0xffdf0000, + .num_ports = 2, + .phy_tuning = rk3528_usb2phy_tuning, + .clkout_ctl_phy = { 0x041c, 7, 2, 0, 0x27 }, + .port_cfgs = { + [USB2PHY_PORT_OTG] = { + .phy_sus = { 0x004c, 8, 0, 0, 0x1d1 }, + .bvalid_det_en = { 0x0074, 3, 2, 0, 3 }, + .bvalid_det_st = { 0x0078, 3, 2, 0, 3 }, + .bvalid_det_clr = { 0x007c, 3, 2, 0, 3 }, + .idfall_det_en = { 0x0074, 5, 5, 0, 1 }, + .idfall_det_st = { 0x0078, 5, 5, 0, 1 }, + .idfall_det_clr = { 0x007c, 5, 5, 0, 1 }, + .idrise_det_en = { 0x0074, 4, 4, 0, 1 }, + .idrise_det_st = { 0x0078, 4, 4, 0, 1 }, + .idrise_det_clr = { 0x007c, 4, 4, 0, 1 }, + .ls_det_en = { 0x0074, 0, 0, 0, 1 }, + .ls_det_st = { 0x0078, 0, 0, 0, 1 }, + .ls_det_clr = { 0x007c, 0, 0, 0, 1 }, + .utmi_avalid = { 0x006c, 1, 1, 0, 1 }, + .utmi_bvalid = { 0x006c, 0, 0, 0, 1 }, + .utmi_id = { 0x006c, 6, 6, 0, 1 }, + .utmi_ls = { 0x006c, 5, 4, 0, 1 }, + }, + [USB2PHY_PORT_HOST] = { + .phy_sus = { 0x005c, 8, 0, 0x1d2, 0x1d1 }, + .ls_det_en = { 0x0090, 0, 0, 0, 1 }, + .ls_det_st = { 0x0094, 0, 0, 0, 1 }, + .ls_det_clr = { 0x0098, 0, 0, 0, 1 }, + .utmi_ls = { 0x006c, 13, 12, 0, 1 }, + .utmi_hstdet = { 0x006c, 15, 15, 0, 1 }, + } + }, + .chg_det = { + .opmode = { 0x004c, 3, 0, 5, 1 }, + .cp_det = { 0x006c, 19, 19, 0, 1 }, + .dcp_det = { 0x006c, 18, 18, 0, 1 }, + .dp_det = { 0x006c, 20, 20, 0, 1 }, + .idm_sink_en = { 0x0058, 1, 1, 0, 1 }, + .idp_sink_en = { 0x0058, 0, 0, 0, 1 }, + .idp_src_en = { 0x0058, 2, 2, 0, 1 }, + .rdm_pdwn_en = { 0x0058, 3, 3, 0, 1 }, + .vdm_src_en = { 0x0058, 5, 5, 0, 1 }, + .vdp_src_en = { 0x0058, 4, 4, 0, 1 }, + }, + }, + { /* sentinel */ } +}; + static const struct rockchip_usb2phy_cfg rk3562_phy_cfgs[] = { { .reg = 0xff740000, @@ -2294,6 +2375,7 @@ static const struct of_device_id rockchip_usb2phy_dt_match[] = { { .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs }, { .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs }, { .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs }, + { .compatible = "rockchip,rk3528-usb2phy", .data = &rk3528_phy_cfgs }, { .compatible = "rockchip,rk3562-usb2phy", .data = &rk3562_phy_cfgs }, { .compatible = "rockchip,rk3568-usb2phy", .data = &rk3568_phy_cfgs }, { .compatible = "rockchip,rk3576-usb2phy", .data = &rk3576_phy_cfgs }, diff --git a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c index b60d6bf3f33c5..2b0f152f54709 100644 --- a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c +++ b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c @@ -121,6 +121,7 @@ #define RK3568_PHYREG32_SSC_OFFSET_500PPM 1 #define RK3568_PHYREG33 0x80 +#define RK3568_PHYREG33_PLL_SSC_CTRL BIT(5) #define RK3568_PHYREG33_PLL_KVCO_MASK GENMASK(4, 2) #define RK3568_PHYREG33_PLL_KVCO_SHIFT 2 #define RK3568_PHYREG33_PLL_KVCO_VALUE 2 @@ -446,6 +447,74 @@ static int rockchip_combphy_probe(struct platform_device *pdev) return PTR_ERR_OR_ZERO(phy_provider); } +static void rk_combphy_common_cfg_ssc(struct rockchip_combphy_priv *priv, unsigned long rate) +{ + struct device_node *np = priv->dev->of_node; + u32 val; + + if (!priv->enable_ssc) + return; + + /* Set SSC downward spread spectrum for PCIe and USB3 */ + if (priv->type == PHY_TYPE_PCIE || priv->type == PHY_TYPE_USB3) { + val = FIELD_PREP(RK3568_PHYREG32_SSC_MASK, RK3568_PHYREG32_SSC_DOWNWARD); + rockchip_combphy_updatel(priv, RK3568_PHYREG32_SSC_MASK, val, RK3568_PHYREG32); + } + + /* Set SSC downward spread spectrum +500ppm for SATA in 100MHz */ + if (priv->type == PHY_TYPE_SATA && rate == REF_CLOCK_100MHz) { + val = FIELD_PREP(RK3568_PHYREG32_SSC_DIR_MASK, + RK3568_PHYREG32_SSC_DOWNWARD); + val |= FIELD_PREP(RK3568_PHYREG32_SSC_OFFSET_MASK, + RK3568_PHYREG32_SSC_OFFSET_500PPM); + rockchip_combphy_updatel(priv, RK3568_PHYREG32_SSC_MASK, val, + RK3568_PHYREG32); + } + + /* Enable SSC */ + val = readl(priv->mmio + RK3568_PHYREG8); + val |= RK3568_PHYREG8_SSC_EN; + writel(val, priv->mmio + RK3568_PHYREG8); + + /* Some SoCs need tuning PCIe SSC instead of default configuration in 24MHz */ + if (!of_device_is_compatible(np, "rockchip,rk3588-naneng-combphy") && + !of_device_is_compatible(np, "rockchip,rk3576-naneng-combphy")) + return; + + /* PLL control SSC module period should be set if need tuning */ + val = readl(priv->mmio + RK3568_PHYREG33); + val |= RK3568_PHYREG33_PLL_SSC_CTRL; + writel(val, priv->mmio + RK3568_PHYREG33); + + if (priv->type == PHY_TYPE_PCIE && rate == REF_CLOCK_24MHz) { + /* Set PLL loop divider */ + writel(0x00, priv->mmio + RK3576_PHYREG17); + writel(RK3568_PHYREG18_PLL_LOOP, priv->mmio + RK3568_PHYREG18); + + /* Set up rx_pck invert and rx msb to disable */ + writel(0x00, priv->mmio + RK3588_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 + RK3568_PHYREG11); + writel(0x02, priv->mmio + RK3568_PHYREG12); + writel(0x08, priv->mmio + RK3568_PHYREG13); + writel(0x57, priv->mmio + RK3568_PHYREG14); + writel(0x40, priv->mmio + RK3568_PHYREG15); + + writel(RK3568_PHYREG16_SSC_CNT_VALUE, priv->mmio + RK3568_PHYREG16); + + val = FIELD_PREP(RK3568_PHYREG33_PLL_KVCO_MASK, + RK3576_PHYREG33_PLL_KVCO_VALUE); + writel(val, priv->mmio + RK3568_PHYREG33); + } +} + static int rk3528_combphy_cfg(struct rockchip_combphy_priv *priv) { const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; @@ -600,21 +669,12 @@ static int rk3562_combphy_cfg(struct rockchip_combphy_priv *priv) switch (priv->type) { case PHY_TYPE_PCIE: - /* Set SSC downward spread spectrum */ - val = RK3568_PHYREG32_SSC_DOWNWARD << RK3568_PHYREG32_SSC_DIR_SHIFT; - rockchip_combphy_updatel(priv, RK3568_PHYREG32_SSC_MASK, val, RK3568_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 = RK3568_PHYREG32_SSC_DOWNWARD << RK3568_PHYREG32_SSC_DIR_SHIFT; - rockchip_combphy_updatel(priv, RK3568_PHYREG32_SSC_MASK, val, - RK3568_PHYREG32); - /* Enable adaptive CTLE for USB3.0 Rx */ rockchip_combphy_updatel(priv, RK3568_PHYREG15_CTLE_EN, RK3568_PHYREG15_CTLE_EN, RK3568_PHYREG15); @@ -706,11 +766,7 @@ static int rk3562_combphy_cfg(struct rockchip_combphy_priv *priv) } } - if (priv->enable_ssc) { - val = readl(priv->mmio + RK3568_PHYREG8); - val |= RK3568_PHYREG8_SSC_EN; - writel(val, priv->mmio + RK3568_PHYREG8); - } + rk_combphy_common_cfg_ssc(priv, rate); return 0; } @@ -755,11 +811,6 @@ static int rk3568_combphy_cfg(struct rockchip_combphy_priv *priv) switch (priv->type) { case PHY_TYPE_PCIE: - /* Set SSC downward spread spectrum. */ - val = RK3568_PHYREG32_SSC_DOWNWARD << RK3568_PHYREG32_SSC_DIR_SHIFT; - - rockchip_combphy_updatel(priv, RK3568_PHYREG32_SSC_MASK, val, RK3568_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); @@ -767,10 +818,6 @@ static int rk3568_combphy_cfg(struct rockchip_combphy_priv *priv) break; case PHY_TYPE_USB3: - /* Set SSC downward spread spectrum. */ - val = RK3568_PHYREG32_SSC_DOWNWARD << RK3568_PHYREG32_SSC_DIR_SHIFT, - rockchip_combphy_updatel(priv, RK3568_PHYREG32_SSC_MASK, val, RK3568_PHYREG32); - /* Enable adaptive CTLE for USB3.0 Rx. */ val = readl(priv->mmio + RK3568_PHYREG15); val |= RK3568_PHYREG15_CTLE_EN; @@ -880,13 +927,6 @@ static int rk3568_combphy_cfg(struct rockchip_combphy_priv *priv) writel(RK3568_PHYREG18_PLL_LOOP, priv->mmio + RK3568_PHYREG18); writel(RK3568_PHYREG11_SU_TRIM_0_7, priv->mmio + RK3568_PHYREG11); - } else if (priv->type == PHY_TYPE_SATA) { - /* downward spread spectrum +500ppm */ - val = RK3568_PHYREG32_SSC_DOWNWARD << RK3568_PHYREG32_SSC_DIR_SHIFT; - val |= RK3568_PHYREG32_SSC_OFFSET_500PPM << - RK3568_PHYREG32_SSC_OFFSET_SHIFT; - rockchip_combphy_updatel(priv, RK3568_PHYREG32_SSC_MASK, val, - RK3568_PHYREG32); } break; @@ -909,11 +949,7 @@ static int rk3568_combphy_cfg(struct rockchip_combphy_priv *priv) } } - if (priv->enable_ssc) { - val = readl(priv->mmio + RK3568_PHYREG8); - val |= RK3568_PHYREG8_SSC_EN; - writel(val, priv->mmio + RK3568_PHYREG8); - } + rk_combphy_common_cfg_ssc(priv, rate); return 0; } @@ -972,10 +1008,6 @@ static int rk3576_combphy_cfg(struct rockchip_combphy_priv *priv) switch (priv->type) { case PHY_TYPE_PCIE: - /* Set SSC downward spread spectrum */ - val = FIELD_PREP(RK3568_PHYREG32_SSC_MASK, RK3568_PHYREG32_SSC_DOWNWARD); - rockchip_combphy_updatel(priv, RK3568_PHYREG32_SSC_MASK, val, RK3568_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); @@ -983,10 +1015,6 @@ static int rk3576_combphy_cfg(struct rockchip_combphy_priv *priv) break; case PHY_TYPE_USB3: - /* Set SSC downward spread spectrum */ - val = FIELD_PREP(RK3568_PHYREG32_SSC_MASK, RK3568_PHYREG32_SSC_DOWNWARD); - rockchip_combphy_updatel(priv, RK3568_PHYREG32_SSC_MASK, val, RK3568_PHYREG32); - /* Enable adaptive CTLE for USB3.0 Rx */ val = readl(priv->mmio + RK3568_PHYREG15); val |= RK3568_PHYREG15_CTLE_EN; @@ -1110,14 +1138,6 @@ static int rk3576_combphy_cfg(struct rockchip_combphy_priv *priv) writel(0x88, priv->mmio + RK3568_PHYREG13); writel(0x56, priv->mmio + RK3568_PHYREG14); } else if (priv->type == PHY_TYPE_SATA) { - /* downward spread spectrum +500ppm */ - val = FIELD_PREP(RK3568_PHYREG32_SSC_DIR_MASK, - RK3568_PHYREG32_SSC_DOWNWARD); - val |= FIELD_PREP(RK3568_PHYREG32_SSC_OFFSET_MASK, - RK3568_PHYREG32_SSC_OFFSET_500PPM); - rockchip_combphy_updatel(priv, RK3568_PHYREG32_SSC_MASK, val, - RK3568_PHYREG32); - /* ssc ppm adjust to 3500ppm */ rockchip_combphy_updatel(priv, RK3576_PHYREG10_SSC_PCM_MASK, RK3576_PHYREG10_SSC_PCM_3500PPM, @@ -1156,39 +1176,7 @@ static int rk3576_combphy_cfg(struct rockchip_combphy_priv *priv) } } - if (priv->enable_ssc) { - val = readl(priv->mmio + RK3568_PHYREG8); - val |= RK3568_PHYREG8_SSC_EN; - writel(val, priv->mmio + RK3568_PHYREG8); - - if (priv->type == PHY_TYPE_PCIE && rate == REF_CLOCK_24MHz) { - /* Set PLL loop divider */ - writel(0x00, priv->mmio + RK3576_PHYREG17); - writel(RK3568_PHYREG18_PLL_LOOP, priv->mmio + RK3568_PHYREG18); - - /* Set up rx_pck invert and rx msb to disable */ - writel(0x00, priv->mmio + RK3588_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 + RK3568_PHYREG11); - writel(0x02, priv->mmio + RK3568_PHYREG12); - writel(0x08, priv->mmio + RK3568_PHYREG13); - writel(0x57, priv->mmio + RK3568_PHYREG14); - writel(0x40, priv->mmio + RK3568_PHYREG15); - - writel(RK3568_PHYREG16_SSC_CNT_VALUE, priv->mmio + RK3568_PHYREG16); - - val = FIELD_PREP(RK3568_PHYREG33_PLL_KVCO_MASK, - RK3576_PHYREG33_PLL_KVCO_VALUE); - writel(val, priv->mmio + RK3568_PHYREG33); - } - } + rk_combphy_common_cfg_ssc(priv, rate); return 0; } @@ -1255,10 +1243,6 @@ static int rk3588_combphy_cfg(struct rockchip_combphy_priv *priv) } break; case PHY_TYPE_USB3: - /* Set SSC downward spread spectrum */ - val = RK3568_PHYREG32_SSC_DOWNWARD << RK3568_PHYREG32_SSC_DIR_SHIFT; - rockchip_combphy_updatel(priv, RK3568_PHYREG32_SSC_MASK, val, RK3568_PHYREG32); - /* Enable adaptive CTLE for USB3.0 Rx. */ val = readl(priv->mmio + RK3568_PHYREG15); val |= RK3568_PHYREG15_CTLE_EN; @@ -1343,13 +1327,6 @@ static int rk3588_combphy_cfg(struct rockchip_combphy_priv *priv) /* Set up su_trim: */ writel(RK3568_PHYREG11_SU_TRIM_0_7, priv->mmio + RK3568_PHYREG11); - } else if (priv->type == PHY_TYPE_SATA) { - /* downward spread spectrum +500ppm */ - val = RK3568_PHYREG32_SSC_DOWNWARD << RK3568_PHYREG32_SSC_DIR_SHIFT; - val |= RK3568_PHYREG32_SSC_OFFSET_500PPM << - RK3568_PHYREG32_SSC_OFFSET_SHIFT; - rockchip_combphy_updatel(priv, RK3568_PHYREG32_SSC_MASK, val, - RK3568_PHYREG32); } break; default: @@ -1371,11 +1348,7 @@ static int rk3588_combphy_cfg(struct rockchip_combphy_priv *priv) } } - if (priv->enable_ssc) { - val = readl(priv->mmio + RK3568_PHYREG8); - val |= RK3568_PHYREG8_SSC_EN; - writel(val, priv->mmio + RK3568_PHYREG8); - } + rk_combphy_common_cfg_ssc(priv, rate); return 0; } diff --git a/drivers/phy/spacemit/phy-k1-usb2.c b/drivers/phy/spacemit/phy-k1-usb2.c index e8c1e26428a91..8df12eeb20b18 100644 --- a/drivers/phy/spacemit/phy-k1-usb2.c +++ b/drivers/phy/spacemit/phy-k1-usb2.c @@ -51,6 +51,9 @@ #define PHY_K1_HS_HOST_DISC 0x40 #define PHY_K1_HS_HOST_DISC_CLR BIT(0) +#define PHY_K3_HS_HOST_DISC 0x20 +#define PHY_K3_HS_HOST_DISC_CLR BIT(8) + #define PHY_PLL_DIV_CFG 0x98 #define PHY_FDIV_FRACT_8_15 GENMASK(7, 0) #define PHY_FDIV_FRACT_16_19 GENMASK(11, 8) @@ -144,7 +147,7 @@ static int spacemit_usb2phy_exit(struct phy *phy) return 0; } -static int spacemit_usb2phy_disconnect(struct phy *phy, int port) +static int spacemit_k1_usb2phy_disconnect(struct phy *phy, int port) { struct spacemit_usb2phy *sphy = phy_get_drvdata(phy); @@ -154,10 +157,27 @@ static int spacemit_usb2phy_disconnect(struct phy *phy, int port) return 0; } -static const struct phy_ops spacemit_usb2phy_ops = { +static int spacemit_k3_usb2phy_disconnect(struct phy *phy, int port) +{ + struct spacemit_usb2phy *sphy = phy_get_drvdata(phy); + + regmap_update_bits(sphy->regmap_base, PHY_K3_HS_HOST_DISC, + PHY_K3_HS_HOST_DISC_CLR, PHY_K3_HS_HOST_DISC_CLR); + + return 0; +} + +static const struct phy_ops spacemit_k1_usb2phy_ops = { .init = spacemit_usb2phy_init, .exit = spacemit_usb2phy_exit, - .disconnect = spacemit_usb2phy_disconnect, + .disconnect = spacemit_k1_usb2phy_disconnect, + .owner = THIS_MODULE, +}; + +static const struct phy_ops spacemit_k3_usb2phy_ops = { + .init = spacemit_usb2phy_init, + .exit = spacemit_usb2phy_exit, + .disconnect = spacemit_k3_usb2phy_disconnect, .owner = THIS_MODULE, }; @@ -166,12 +186,15 @@ static int spacemit_usb2phy_probe(struct platform_device *pdev) struct phy_provider *phy_provider; struct device *dev = &pdev->dev; struct spacemit_usb2phy *sphy; + const struct phy_ops *ops; void __iomem *base; sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL); if (!sphy) return -ENOMEM; + ops = device_get_match_data(dev); + sphy->clk = devm_clk_get_prepared(&pdev->dev, NULL); if (IS_ERR(sphy->clk)) return dev_err_probe(dev, PTR_ERR(sphy->clk), "Failed to get clock\n"); @@ -184,7 +207,7 @@ static int spacemit_usb2phy_probe(struct platform_device *pdev) if (IS_ERR(sphy->regmap_base)) return dev_err_probe(dev, PTR_ERR(sphy->regmap_base), "Failed to init regmap\n"); - sphy->phy = devm_phy_create(dev, NULL, &spacemit_usb2phy_ops); + sphy->phy = devm_phy_create(dev, NULL, ops); if (IS_ERR(sphy->phy)) return dev_err_probe(dev, PTR_ERR(sphy->phy), "Failed to create phy\n"); @@ -195,7 +218,8 @@ static int spacemit_usb2phy_probe(struct platform_device *pdev) } static const struct of_device_id spacemit_usb2phy_dt_match[] = { - { .compatible = "spacemit,k1-usb2-phy", }, + { .compatible = "spacemit,k1-usb2-phy", .data = &spacemit_k1_usb2phy_ops }, + { .compatible = "spacemit,k3-usb2-phy", .data = &spacemit_k3_usb2phy_ops }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, spacemit_usb2phy_dt_match); diff --git a/drivers/phy/st/Kconfig b/drivers/phy/st/Kconfig index 304614b6dabfc..49206185e5633 100644 --- a/drivers/phy/st/Kconfig +++ b/drivers/phy/st/Kconfig @@ -4,7 +4,7 @@ # config PHY_MIPHY28LP tristate "STMicroelectronics MIPHY28LP PHY driver for STiH407" - depends on ARCH_STI + depends on ARCH_STI || COMPILE_TEST select GENERIC_PHY help Enable this to support the miphy transceiver (for SATA/PCIE/USB3) diff --git a/drivers/phy/st/phy-miphy28lp.c b/drivers/phy/st/phy-miphy28lp.c index 43cef89af55ec..c576fc5569fe9 100644 --- a/drivers/phy/st/phy-miphy28lp.c +++ b/drivers/phy/st/phy-miphy28lp.c @@ -224,8 +224,8 @@ struct miphy28lp_dev { struct device *dev; struct regmap *regmap; struct mutex miphy_mutex; - struct miphy28lp_phy **phys; int nphys; + struct miphy28lp_phy *phys[] __counted_by(nphys); }; enum miphy_sata_gen { SATA_GEN1, SATA_GEN2, SATA_GEN3 }; @@ -1168,16 +1168,14 @@ static int miphy28lp_probe(struct platform_device *pdev) struct phy_provider *provider; struct phy *phy; int ret, port = 0; + size_t nphys; - miphy_dev = devm_kzalloc(&pdev->dev, sizeof(*miphy_dev), GFP_KERNEL); + nphys = of_get_child_count(np); + miphy_dev = devm_kzalloc(&pdev->dev, struct_size(miphy_dev, phys, nphys), GFP_KERNEL); if (!miphy_dev) return -ENOMEM; - miphy_dev->nphys = of_get_child_count(np); - miphy_dev->phys = devm_kcalloc(&pdev->dev, miphy_dev->nphys, - sizeof(*miphy_dev->phys), GFP_KERNEL); - if (!miphy_dev->phys) - return -ENOMEM; + miphy_dev->nphys = nphys; miphy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); if (IS_ERR(miphy_dev->regmap)) { diff --git a/drivers/phy/tegra/Kconfig b/drivers/phy/tegra/Kconfig index 342fb736da4b1..f0734415fc94c 100644 --- a/drivers/phy/tegra/Kconfig +++ b/drivers/phy/tegra/Kconfig @@ -3,7 +3,7 @@ config PHY_TEGRA_XUSB tristate "NVIDIA Tegra XUSB pad controller driver" depends on ARCH_TEGRA && USB_SUPPORT select USB_COMMON - select USB_CONN_GPIO + select USB_CONN_GPIO if GPIOLIB select USB_PHY help Choose this option if you have an NVIDIA Tegra SoC. diff --git a/drivers/phy/ti/Kconfig b/drivers/phy/ti/Kconfig index b40f280191314..b52c7eabe24cb 100644 --- a/drivers/phy/ti/Kconfig +++ b/drivers/phy/ti/Kconfig @@ -2,24 +2,29 @@ # # Phy drivers for TI platforms # -config PHY_DA8XX_USB - tristate "TI DA8xx USB PHY Driver" - depends on ARCH_DAVINCI_DA8XX || COMPILE_TEST - select GENERIC_PHY - select MFD_SYSCON +config OMAP_CONTROL_PHY + tristate "OMAP CONTROL PHY Driver" + depends on ARCH_OMAP2PLUS || COMPILE_TEST help - Enable this to support the USB PHY on DA8xx SoCs. - - This driver controls both the USB 1.1 PHY and the USB 2.0 PHY. + Enable this to add support for the PHY part present in the control + module. This driver has API to power on the USB2 PHY and to write to + the mailbox. The mailbox is present only in omap4 and the register to + power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an + additional register to power on USB3 PHY/SATA PHY/PCIE PHY + (PIPE3 PHY). -config PHY_DM816X_USB - tristate "TI dm816x USB PHY driver" - depends on ARCH_OMAP2PLUS || COMPILE_TEST +config OMAP_USB2 + tristate "OMAP USB2 PHY Driver" + depends on ARCH_OMAP2PLUS || ARCH_K3 || COMPILE_TEST depends on USB_SUPPORT select GENERIC_PHY select USB_PHY + select OMAP_CONTROL_PHY if ARCH_OMAP2PLUS || COMPILE_TEST help - Enable this for dm816x USB to work. + Enable this to support the transceiver that is part of SOC. This + driver takes care of all the PHY functionality apart from comparator. + The USB OTG controller communicates with the comparator using this + driver. config PHY_AM654_SERDES tristate "TI AM654 SERDES support" @@ -33,6 +38,25 @@ config PHY_AM654_SERDES This option enables support for TI AM654 SerDes PHY used for PCIe. +config PHY_DA8XX_USB + tristate "TI DA8xx USB PHY Driver" + depends on ARCH_DAVINCI_DA8XX || COMPILE_TEST + select GENERIC_PHY + select MFD_SYSCON + help + Enable this to support the USB PHY on DA8xx SoCs. + + This driver controls both the USB 1.1 PHY and the USB 2.0 PHY. + +config PHY_DM816X_USB + tristate "TI dm816x USB PHY driver" + depends on ARCH_OMAP2PLUS || COMPILE_TEST + depends on USB_SUPPORT + select GENERIC_PHY + select USB_PHY + help + Enable this for dm816x USB to work. + config PHY_J721E_WIZ tristate "TI J721E WIZ (SERDES Wrapper) support" depends on OF && (ARCH_K3 || COMPILE_TEST) @@ -49,29 +73,30 @@ config PHY_J721E_WIZ three clock selects (pll0, pll1, dig) and resets for each of the lanes. -config OMAP_CONTROL_PHY - tristate "OMAP CONTROL PHY Driver" - depends on ARCH_OMAP2PLUS || COMPILE_TEST +config PHY_TI_DS125DF111 + tristate "TI DS125DF111 2-Channel Retimer Driver" + depends on OF && I2C + select GENERIC_PHY help - Enable this to add support for the PHY part present in the control - module. This driver has API to power on the USB2 PHY and to write to - the mailbox. The mailbox is present only in omap4 and the register to - power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an - additional register to power on USB3 PHY/SATA PHY/PCIE PHY - (PIPE3 PHY). + Enable this to add support for configuration and runtime management + of the TI DS125DF111 Multi-Protocol 2-Channel Retimer. + The retimer is modeled as a Generic PHY and supports both 10G and 1G + link speeds. -config OMAP_USB2 - tristate "OMAP USB2 PHY Driver" - depends on ARCH_OMAP2PLUS || ARCH_K3 || COMPILE_TEST - depends on USB_SUPPORT +config PHY_TI_GMII_SEL + tristate select GENERIC_PHY - select USB_PHY - select OMAP_CONTROL_PHY if ARCH_OMAP2PLUS || COMPILE_TEST + select REGMAP help - Enable this to support the transceiver that is part of SOC. This - driver takes care of all the PHY functionality apart from comparator. - The USB OTG controller communicates with the comparator using this - driver. + This driver supports configuring of the TI CPSW Port mode depending on + the Ethernet PHY connected to the CPSW Port. + +config PHY_TUSB1210 + tristate "TI TUSB1210 ULPI PHY module" + depends on USB_ULPI_BUS + select GENERIC_PHY + help + Support for TI TUSB1210 USB ULPI PHY. config TI_PIPE3 tristate "TI PIPE3 PHY Driver" @@ -84,13 +109,6 @@ config TI_PIPE3 This driver interacts with the "OMAP Control PHY Driver" to power on/off the PHY. -config PHY_TUSB1210 - tristate "TI TUSB1210 ULPI PHY module" - depends on USB_ULPI_BUS - select GENERIC_PHY - help - Support for TI TUSB1210 USB ULPI PHY. - config TWL4030_USB tristate "TWL4030 USB Transceiver Driver" depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS @@ -103,11 +121,3 @@ config TWL4030_USB family chips (including the TWL5030 and TPS659x0 devices). This transceiver supports high and full speed devices plus, in host mode, low speed. - -config PHY_TI_GMII_SEL - tristate - select GENERIC_PHY - select REGMAP - help - This driver supports configuring of the TI CPSW Port mode depending on - the Ethernet PHY connected to the CPSW Port. diff --git a/drivers/phy/ti/Makefile b/drivers/phy/ti/Makefile index dcba2571c9bd8..a002ef8764a20 100644 --- a/drivers/phy/ti/Makefile +++ b/drivers/phy/ti/Makefile @@ -1,11 +1,12 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_PHY_DA8XX_USB) += phy-da8xx-usb.o -obj-$(CONFIG_PHY_DM816X_USB) += phy-dm816x-usb.o obj-$(CONFIG_OMAP_CONTROL_PHY) += phy-omap-control.o obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o -obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o -obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o -obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o obj-$(CONFIG_PHY_AM654_SERDES) += phy-am654-serdes.o -obj-$(CONFIG_PHY_TI_GMII_SEL) += phy-gmii-sel.o +obj-$(CONFIG_PHY_DA8XX_USB) += phy-da8xx-usb.o +obj-$(CONFIG_PHY_DM816X_USB) += phy-dm816x-usb.o obj-$(CONFIG_PHY_J721E_WIZ) += phy-j721e-wiz.o +obj-$(CONFIG_PHY_TI_DS125DF111) += phy-ds125df111.o +obj-$(CONFIG_PHY_TI_GMII_SEL) += phy-gmii-sel.o +obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o +obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o +obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o diff --git a/drivers/phy/ti/phy-ds125df111.c b/drivers/phy/ti/phy-ds125df111.c new file mode 100644 index 0000000000000..84ff96d7d589a --- /dev/null +++ b/drivers/phy/ti/phy-ds125df111.c @@ -0,0 +1,294 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright 2026 NXP */ + +#include <linux/bitfield.h> +#include <linux/bits.h> +#include <linux/i2c.h> +#include <linux/iopoll.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/phy.h> +#include <linux/phy/phy.h> +#include <linux/slab.h> + +#define DS125DF111_NUM_CH 2 +#define DS125DF111_NUM_VCO_GROUP_REG 5 + +#define DS125DF111_CH_SELECT 0xff +#define DS125DF111_CH_SELECT_TARGET_MASK GENMASK(3, 0) +#define DS125DF111_CH_SELECT_EN BIT(2) + +#define DS125DF111_CH_CTRL 0x00 +#define DS125DF111_CH_CTRL_RESET BIT(2) /* self clearing */ + +#define DS125DF111_CH_RST_SLEEP_US 10 +#define DS125DF111_CH_RST_TIMEOUT_US 10000 + +#define DS125DF111_VCO_GROUP_BASE 0x60 + +#define DS125DF111_RATIOS 0x2f +#define DS125DF111_RATIOS_RATE_MASK GENMASK(7, 6) +#define DS125DF111_RATIOS_SUBRATE_MASK GENMASK(5, 4) +#define DS125DF111_RATIOS_MASK GENMASK(7, 4) + +struct ds125df111_ch { + struct phy *phy; + struct ds125df111_priv *priv; + int idx; +}; + +struct ds125df111_priv { + struct ds125df111_ch ch[DS125DF111_NUM_CH]; + struct i2c_client *client; + struct mutex mutex; /* protects access to shared registers */ +}; + +enum ds125df111_mode { + FREQ_1G, + FREQ_10G, +}; + +static const struct ds125df111_config { + u8 vco_group[DS125DF111_NUM_VCO_GROUP_REG]; + u8 rate; + u8 subrate; +} ds125df111_cfg[] = { + [FREQ_1G] = { + /* VCO group #0 = 10GHz, VCO group #1 = 10GHz */ + .vco_group = {0x00, 0xB2, 0x00, 0xB2, 0xCC}, + /* By using the following combination of rate and subrate we + * select divide ratios of 1, 2, 4, 8 on both groups + */ + .rate = 0x1, + .subrate = 0x2, + }, + + [FREQ_10G] = { + /* VCO group #0 = 10.3125GHz, VCO group #1 = 10.3125GHz */ + .vco_group = {0x90, 0xB3, 0x90, 0xB3, 0xCD}, + /* By using the following combination of rate and subrate we + * select divide ratios of 1 on both groups + */ + .rate = 0x1, + .subrate = 0x3, + }, +}; + +static int ds125df111_rmw(struct ds125df111_priv *priv, u8 reg, u8 clr, u8 set) +{ + struct i2c_client *i2c = priv->client; + int err; + u8 val; + + err = i2c_smbus_read_byte_data(i2c, reg); + if (err < 0) + return err; + + val = (u8)err; + val &= ~clr; + val |= set; + + err = i2c_smbus_write_byte_data(i2c, reg, val); + if (err < 0) + return err; + + return 0; +} + +static int ds125df111_configure(struct phy *phy, + const struct ds125df111_config *cfg) +{ + struct ds125df111_ch *ch = phy_get_drvdata(phy); + struct ds125df111_priv *priv = ch->priv; + struct i2c_client *i2c = priv->client; + struct device *dev = &phy->dev; + u8 ratios_val; + int err, i; + int val; + + mutex_lock(&priv->mutex); + + /* Make sure that any subsequent read/write operation will be directed + * only to the registers of the selected channel + */ + err = ds125df111_rmw(priv, DS125DF111_CH_SELECT, + DS125DF111_CH_SELECT_TARGET_MASK, + DS125DF111_CH_SELECT_EN | ch->idx); + if (err < 0) { + dev_err(dev, "Unable to select channel: %pe\n", ERR_PTR(err)); + goto out; + } + + /* Reset channel registers and wait until the bit was cleared */ + err = ds125df111_rmw(priv, DS125DF111_CH_CTRL, 0, + DS125DF111_CH_CTRL_RESET); + if (err < 0) { + dev_err(dev, "Error resetting channel configuration: %pe\n", + ERR_PTR(err)); + goto out; + } + + err = read_poll_timeout(i2c_smbus_read_byte_data, val, + val < 0 || !(val & DS125DF111_CH_CTRL_RESET), + DS125DF111_CH_RST_SLEEP_US, + DS125DF111_CH_RST_TIMEOUT_US, false, i2c, + DS125DF111_CH_CTRL); + if (err) { + dev_err(dev, "Timed out waiting for channel reset: %pe\n", + ERR_PTR(err)); + goto out; + } + + if (val < 0) { + dev_err(dev, "Error reading reset status: %pe\n", ERR_PTR(val)); + err = val; + goto out; + } + + /* Program the VCO group frequencies */ + for (i = 0; i < DS125DF111_NUM_VCO_GROUP_REG; i++) { + err = i2c_smbus_write_byte_data(i2c, + DS125DF111_VCO_GROUP_BASE + i, + cfg->vco_group[i]); + if (err < 0) { + dev_err(dev, "Error programming VCO group: %pe\n", + ERR_PTR(err)); + goto out; + } + } + + /* Set the divide ratios for the VCO groups */ + ratios_val = FIELD_PREP(DS125DF111_RATIOS_RATE_MASK, cfg->rate) | + FIELD_PREP(DS125DF111_RATIOS_SUBRATE_MASK, cfg->subrate); + err = ds125df111_rmw(priv, DS125DF111_RATIOS, DS125DF111_RATIOS_MASK, + ratios_val); + if (err < 0) { + dev_err(dev, "Error programming the divide ratios: %pe\n", + ERR_PTR(err)); + goto out; + } + +out: + mutex_unlock(&priv->mutex); + + return err; +} + +static int ds125df111_set_mode(struct phy *phy, enum phy_mode mode, int submode) +{ + const struct ds125df111_config *cfg; + + if (mode != PHY_MODE_ETHERNET) + return -EINVAL; + + switch (submode) { + case PHY_INTERFACE_MODE_10GBASER: + cfg = &ds125df111_cfg[FREQ_10G]; + break; + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_SGMII: + cfg = &ds125df111_cfg[FREQ_1G]; + break; + default: + return -EINVAL; + } + + return ds125df111_configure(phy, cfg); +} + +static int ds125df111_validate(struct phy *phy, enum phy_mode mode, int submode, + union phy_configure_opts *opts __always_unused) +{ + if (mode != PHY_MODE_ETHERNET) + return -EINVAL; + + switch (submode) { + case PHY_INTERFACE_MODE_10GBASER: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_SGMII: + return 0; + default: + return -EINVAL; + } +} + +static const struct phy_ops ds125df111_ops = { + .validate = ds125df111_validate, + .set_mode = ds125df111_set_mode, + .owner = THIS_MODULE, +}; + +static struct phy *ds125df111_xlate(struct device *dev, + const struct of_phandle_args *args) +{ + struct ds125df111_priv *priv = dev_get_drvdata(dev); + u32 idx; + + if (args->args_count != 1) + return ERR_PTR(-EINVAL); + + idx = args->args[0]; + if (idx >= DS125DF111_NUM_CH) { + dev_err(dev, "Maximum number of channels is %d\n", + DS125DF111_NUM_CH); + return ERR_PTR(-EINVAL); + } + + return priv->ch[idx].phy; +} + +static int ds125df111_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct phy_provider *provider; + struct ds125df111_priv *priv; + int i, err; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + priv->client = client; + err = devm_mutex_init(dev, &priv->mutex); + if (err) + return err; + + i2c_set_clientdata(client, priv); + + for (i = 0; i < DS125DF111_NUM_CH; i++) { + struct ds125df111_ch *ch = &priv->ch[i]; + struct phy *phy; + + phy = devm_phy_create(dev, NULL, &ds125df111_ops); + if (IS_ERR(phy)) + return PTR_ERR(phy); + + ch->idx = i; + ch->priv = priv; + ch->phy = phy; + + phy_set_drvdata(phy, ch); + } + + provider = devm_of_phy_provider_register(dev, ds125df111_xlate); + + return PTR_ERR_OR_ZERO(provider); +} + +static const struct of_device_id ds125df111_dt_ids[] = { + { .compatible = "ti,ds125df111", }, + {} +}; +MODULE_DEVICE_TABLE(of, ds125df111_dt_ids); + +static struct i2c_driver ds125df111_driver = { + .driver = { + .name = "ds125df111", + .of_match_table = ds125df111_dt_ids, + }, + .probe = ds125df111_probe, +}; +module_i2c_driver(ds125df111_driver); + +MODULE_AUTHOR("Ioana Ciornei <ioana.ciornei@nxp.com>"); +MODULE_DESCRIPTION("TI DS125DF111 Retimer driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/phy/ti/phy-gmii-sel.c b/drivers/phy/ti/phy-gmii-sel.c index 6213c2b6005a5..c2865a6b1d7fb 100644 --- a/drivers/phy/ti/phy-gmii-sel.c +++ b/drivers/phy/ti/phy-gmii-sel.c @@ -252,6 +252,15 @@ struct phy_gmii_sel_soc_data phy_gmii_sel_soc_am654 = { }; static const +struct phy_gmii_sel_soc_data phy_gmii_sel_soc_j722s = { + .use_of_data = true, + .features = BIT(PHY_GMII_SEL_RGMII_ID_MODE) | + BIT(PHY_GMII_SEL_FIXED_TX_DELAY), + .regfields = phy_gmii_sel_fields_am654, + .extra_modes = BIT(PHY_INTERFACE_MODE_SGMII), +}; + +static const struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw5g_soc_j7200 = { .use_of_data = true, .features = BIT(PHY_GMII_SEL_RGMII_ID_MODE) | @@ -308,6 +317,10 @@ static const struct of_device_id phy_gmii_sel_id_table[] = { .data = &phy_gmii_sel_soc_am654, }, { + .compatible = "ti,j722s-phy-gmii-sel", + .data = &phy_gmii_sel_soc_j722s, + }, + { .compatible = "ti,j7200-cpsw5g-phy-gmii-sel", .data = &phy_gmii_sel_cpsw5g_soc_j7200, }, diff --git a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c index 6b584706b913a..7531a8a049123 100644 --- a/drivers/phy/ti/phy-j721e-wiz.c +++ b/drivers/phy/ti/phy-j721e-wiz.c @@ -331,6 +331,7 @@ enum wiz_type { J721E_WIZ_16G, J721E_WIZ_10G, /* Also for J7200 SR1.0 */ AM64_WIZ_10G, + J722S_WIZ_10G, J7200_WIZ_10G, /* J7200 SR2.0 */ J784S4_WIZ_10G, J721S2_WIZ_10G, @@ -1020,6 +1021,7 @@ static void wiz_clock_cleanup(struct wiz *wiz, struct device_node *node) switch (wiz->type) { case AM64_WIZ_10G: + case J722S_WIZ_10G: case J7200_WIZ_10G: case J784S4_WIZ_10G: case J721S2_WIZ_10G: @@ -1089,6 +1091,7 @@ static void wiz_clock_init(struct wiz *wiz) switch (wiz->type) { case AM64_WIZ_10G: + case J722S_WIZ_10G: case J7200_WIZ_10G: switch (rate) { case REF_CLK_100MHZ: @@ -1158,6 +1161,7 @@ static int wiz_clock_probe(struct wiz *wiz, struct device_node *node) switch (wiz->type) { case AM64_WIZ_10G: + case J722S_WIZ_10G: case J7200_WIZ_10G: case J784S4_WIZ_10G: case J721S2_WIZ_10G: @@ -1246,6 +1250,14 @@ static int wiz_phy_fullrt_div(struct wiz *wiz, int lane) if (wiz->lane_phy_type[lane] == PHY_TYPE_SGMII) return regmap_field_write(wiz->p0_fullrt_div[lane], 0x2); break; + + case J722S_WIZ_10G: + if (wiz->lane_phy_type[lane] == PHY_TYPE_PCIE) + return regmap_field_write(wiz->p0_fullrt_div[lane], 0x1); + if (wiz->lane_phy_type[lane] == PHY_TYPE_SGMII) + return regmap_field_write(wiz->p0_fullrt_div[lane], 0x2); + break; + default: return 0; } @@ -1350,6 +1362,15 @@ static struct wiz_data am64_10g_data = { .clk_div_sel_num = WIZ_DIV_NUM_CLOCKS_10G, }; +static struct wiz_data j722s_10g_data = { + .type = J722S_WIZ_10G, + .pll0_refclk_mux_sel = &pll0_refclk_mux_sel, + .pll1_refclk_mux_sel = &pll1_refclk_mux_sel, + .refclk_dig_sel = &refclk_dig_sel_10g, + .clk_mux_sel = clk_mux_sel_10g, + .clk_div_sel_num = WIZ_DIV_NUM_CLOCKS_10G, +}; + static struct wiz_data j7200_pg2_10g_data = { .type = J7200_WIZ_10G, .pll0_refclk_mux_sel = &sup_pll0_refclk_mux_sel, @@ -1390,6 +1411,9 @@ static const struct of_device_id wiz_id_table[] = { .compatible = "ti,am64-wiz-10g", .data = &am64_10g_data, }, { + .compatible = "ti,j722s-wiz-10g", .data = &j722s_10g_data, + }, + { .compatible = "ti,j7200-wiz-10g", .data = &j7200_pg2_10g_data, }, { diff --git a/drivers/phy/ti/phy-tusb1210.c b/drivers/phy/ti/phy-tusb1210.c index c3ae9d7948d7e..9956921c094be 100644 --- a/drivers/phy/ti/phy-tusb1210.c +++ b/drivers/phy/ti/phy-tusb1210.c @@ -197,7 +197,7 @@ static void tusb1210_chg_det_set_state(struct tusb1210 *tusb, tusb1210_chg_det_states[new_state], delay_ms); tusb->chg_det_state = new_state; - mod_delayed_work(system_long_wq, &tusb->chg_det_work, + mod_delayed_work(system_dfl_long_wq, &tusb->chg_det_work, msecs_to_jiffies(delay_ms)); } @@ -380,7 +380,7 @@ static int tusb1210_psy_notifier(struct notifier_block *nb, struct power_supply *psy = ptr; if (psy != tusb->psy && psy->desc->type == POWER_SUPPLY_TYPE_USB) - queue_delayed_work(system_long_wq, &tusb->chg_det_work, 0); + queue_delayed_work(system_dfl_long_wq, &tusb->chg_det_work, 0); return NOTIFY_OK; } @@ -458,7 +458,7 @@ static void tusb1210_probe_charger_detect(struct tusb1210 *tusb) */ tusb->chg_det_state = TUSB1210_CHG_DET_DISCONNECTED; INIT_DELAYED_WORK(&tusb->chg_det_work, tusb1210_chg_det_work); - queue_delayed_work(system_long_wq, &tusb->chg_det_work, 2 * HZ); + queue_delayed_work(system_dfl_long_wq, &tusb->chg_det_work, 2 * HZ); tusb->psy_nb.notifier_call = tusb1210_psy_notifier; power_supply_reg_notifier(&tusb->psy_nb); |
