diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-05-22 09:28:16 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-05-22 09:28:16 +0200 |
commit | 14f3a5ccacdb4268764474d834ee353219dbd1a2 (patch) | |
tree | efbae1e87b82a81a5a72f13cfa770a8d92fa024e /drivers/phy/qualcomm | |
parent | e9ccc35b86653cb15e9bffbe2cbef8781ea2c1dd (diff) | |
parent | ac0a95a3ea7811f5cc4489924ddb54f0ea0f3007 (diff) | |
download | linux-14f3a5ccacdb4268764474d834ee353219dbd1a2.tar.gz linux-14f3a5ccacdb4268764474d834ee353219dbd1a2.tar.bz2 linux-14f3a5ccacdb4268764474d834ee353219dbd1a2.zip |
Merge tag 'phy-for-5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy into usb-next
Kishon writes:
phy: for 5.8
*) Add new PHY driver to support Cadence SALVO PHY which supports USB3 & USB2
*) Add new PHY driver to support Intel ComboPhy which supports PCIe, SATA and
EMAC
*) Add new PHY driver for Qualcomm IPQ40xx USB PHY
*) Add new PHY driver for Synopsys FemtoPHY V2 driver used in Qualcomm SOCs
*) Add support for Qualcomm SM8250 UFS PHY and SM8150 QMP USB3 PHY in
qcom-qmp-phy driver
*) Add support for Amlogic USB2 PHY on Meson8m2 in phy-meson8b-usb2 driver
*) Add DisplayPort mode support in Wiz (TI Cadence PHY wrapper), to enable eDP
in TI's J721E SoC
*) Add support for super speed USB PHY in TI's AM654 SoC
*) Add fix in Broadcom Stingray USB PHY to get USB PHY PLL lock reliably
*) Add fix in Samsung phy-s5pv210-usb2 to get USB working on s5pv210
*) Add fix in Amlogic phy-meson8b-usb2 to get host only mode working on Meson8
*) Add fix in Cadence phy-cadence-sierra to get USB3 device disconnect issue
*) Convert meson8b-usb2-phy, qcom-qmp-phy, rcar-gen3-phy-usb2 and
rcar-gen3-phy-usb3 device tree binding to YAML schema
*) Minor fixes and cleanups in phy-cpcap-usb, j721e-wiz, omap-usb2,
phy-bcm-sr-usb, phy-brcm-usb PHY driver
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
* tag 'phy-for-5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy: (43 commits)
phy: intel: Add driver support for ComboPhy
dt-bindings: phy: Add YAML schemas for Intel ComboPhy
dt-bindings: phy: Add PHY_TYPE_XPCS definition
phy: qcom-qmp: Add QMP V3 USB3 PHY support for SC7180
dt-bindings: phy: qcom,qmp-usb3-dp: Add support for SC7180
dt-bindings: phy: qcom,qmp-usb3-dp: Add dt bindings for USB3 DP PHY
dt-bindings: phy: qcom,qmp: Convert QMP PHY bindings to yaml
phy: cadence: sierra: Fix for USB3 U1/U2 state
phy: ti: am654: add support for USB super-speed
phy: ti: am654: show up in regmap debugfs
drivers: phy: sr-usb: do not use internal fsm for USB2 phy init
dt-bindings: phy: renesas: usb3-phy: add r8a77961 support
dt-bindings: phy: renesas: usb3-phy: convert bindings to json-schema
dt-bindings: phy: renesas: usb2-phy: add r8a77961 support
dt-bindings: phy: renesas: usb2-phy: convert bindings to json-schema
phy: qcom-qmp: Ensure register indirection arrays initialized
phy: omap-usb2: Clean up exported header
phy: phy-bcm-ns2-usbdrd: Constify phy_ops
phy: phy-brcm-usb: Constify static structs
phy: sr-usb: Constify phy_ops
...
Diffstat (limited to 'drivers/phy/qualcomm')
-rw-r--r-- | drivers/phy/qualcomm/Kconfig | 17 | ||||
-rw-r--r-- | drivers/phy/qualcomm/Makefile | 2 | ||||
-rw-r--r-- | drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c | 148 | ||||
-rw-r--r-- | drivers/phy/qualcomm/phy-qcom-qmp.c | 254 | ||||
-rw-r--r-- | drivers/phy/qualcomm/phy-qcom-qmp.h | 238 | ||||
-rw-r--r-- | drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c | 287 |
6 files changed, 902 insertions, 44 deletions
diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig index 98674ed094d9..ca9ce7e84a5c 100644 --- a/drivers/phy/qualcomm/Kconfig +++ b/drivers/phy/qualcomm/Kconfig @@ -18,6 +18,13 @@ config PHY_QCOM_APQ8064_SATA depends on OF select GENERIC_PHY +config PHY_QCOM_IPQ4019_USB + tristate "Qualcomm IPQ4019 USB PHY driver" + depends on OF && (ARCH_QCOM || COMPILE_TEST) + select GENERIC_PHY + help + Support for the USB PHY-s on Qualcomm IPQ40xx SoC-s. + config PHY_QCOM_IPQ806X_SATA tristate "Qualcomm IPQ806x SATA SerDes/PHY driver" depends on ARCH_QCOM @@ -85,6 +92,16 @@ config PHY_QCOM_USB_HS Support for the USB high-speed ULPI compliant phy on Qualcomm chipsets. +config PHY_QCOM_USB_SNPS_FEMTO_V2 + tristate "Qualcomm SNPS FEMTO USB HS PHY V2 module" + depends on OF && (ARCH_QCOM || COMPILE_TEST) + select GENERIC_PHY + help + Enable support for the USB high-speed SNPS Femto phy on Qualcomm + chipsets. This PHY has differences in the register map compared + to the V1 variants. The PHY is paired with a Synopsys DWC3 USB + controller on Qualcomm SOCs. + config PHY_QCOM_USB_HSIC tristate "Qualcomm USB HSIC ULPI PHY module" depends on USB_ULPI_BUS diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile index 1f14aeacbd70..86fb32efab79 100644 --- a/drivers/phy/qualcomm/Makefile +++ b/drivers/phy/qualcomm/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_PHY_ATH79_USB) += phy-ath79-usb.o obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o +obj-$(CONFIG_PHY_QCOM_IPQ4019_USB) += phy-qcom-ipq4019-usb.o obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o obj-$(CONFIG_PHY_QCOM_PCIE2) += phy-qcom-pcie2.o obj-$(CONFIG_PHY_QCOM_QMP) += phy-qcom-qmp.o @@ -12,3 +13,4 @@ obj-$(CONFIG_PHY_QCOM_USB_HS) += phy-qcom-usb-hs.o obj-$(CONFIG_PHY_QCOM_USB_HSIC) += phy-qcom-usb-hsic.o obj-$(CONFIG_PHY_QCOM_USB_HS_28NM) += phy-qcom-usb-hs-28nm.o obj-$(CONFIG_PHY_QCOM_USB_SS) += phy-qcom-usb-ss.o +obj-$(CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2)+= phy-qcom-snps-femto-v2.o diff --git a/drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c b/drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c new file mode 100644 index 000000000000..b8ef331e1545 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-ipq4019-usb.c @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2018 John Crispin <john@phrozen.org> + * + * Based on code from + * Allwinner Technology Co., Ltd. <www.allwinnertech.com> + * + */ + +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/of_platform.h> +#include <linux/of_device.h> +#include <linux/phy/phy.h> +#include <linux/platform_device.h> +#include <linux/reset.h> + +struct ipq4019_usb_phy { + struct device *dev; + struct phy *phy; + void __iomem *base; + struct reset_control *por_rst; + struct reset_control *srif_rst; +}; + +static int ipq4019_ss_phy_power_off(struct phy *_phy) +{ + struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy); + + reset_control_assert(phy->por_rst); + msleep(10); + + return 0; +} + +static int ipq4019_ss_phy_power_on(struct phy *_phy) +{ + struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy); + + ipq4019_ss_phy_power_off(_phy); + + reset_control_deassert(phy->por_rst); + + return 0; +} + +static struct phy_ops ipq4019_usb_ss_phy_ops = { + .power_on = ipq4019_ss_phy_power_on, + .power_off = ipq4019_ss_phy_power_off, +}; + +static int ipq4019_hs_phy_power_off(struct phy *_phy) +{ + struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy); + + reset_control_assert(phy->por_rst); + msleep(10); + + reset_control_assert(phy->srif_rst); + msleep(10); + + return 0; +} + +static int ipq4019_hs_phy_power_on(struct phy *_phy) +{ + struct ipq4019_usb_phy *phy = phy_get_drvdata(_phy); + + ipq4019_hs_phy_power_off(_phy); + + reset_control_deassert(phy->srif_rst); + msleep(10); + + reset_control_deassert(phy->por_rst); + + return 0; +} + +static struct phy_ops ipq4019_usb_hs_phy_ops = { + .power_on = ipq4019_hs_phy_power_on, + .power_off = ipq4019_hs_phy_power_off, +}; + +static const struct of_device_id ipq4019_usb_phy_of_match[] = { + { .compatible = "qcom,usb-hs-ipq4019-phy", .data = &ipq4019_usb_hs_phy_ops}, + { .compatible = "qcom,usb-ss-ipq4019-phy", .data = &ipq4019_usb_ss_phy_ops}, + { }, +}; +MODULE_DEVICE_TABLE(of, ipq4019_usb_phy_of_match); + +static int ipq4019_usb_phy_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct resource *res; + struct phy_provider *phy_provider; + struct ipq4019_usb_phy *phy; + + phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); + if (!phy) + return -ENOMEM; + + phy->dev = &pdev->dev; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + phy->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(phy->base)) { + dev_err(dev, "failed to remap register memory\n"); + return PTR_ERR(phy->base); + } + + phy->por_rst = devm_reset_control_get(phy->dev, "por_rst"); + if (IS_ERR(phy->por_rst)) { + if (PTR_ERR(phy->por_rst) != -EPROBE_DEFER) + dev_err(dev, "POR reset is missing\n"); + return PTR_ERR(phy->por_rst); + } + + phy->srif_rst = devm_reset_control_get_optional(phy->dev, "srif_rst"); + if (IS_ERR(phy->srif_rst)) + return PTR_ERR(phy->srif_rst); + + phy->phy = devm_phy_create(dev, NULL, of_device_get_match_data(dev)); + if (IS_ERR(phy->phy)) { + dev_err(dev, "failed to create PHY\n"); + return PTR_ERR(phy->phy); + } + phy_set_drvdata(phy->phy, phy); + + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + + return PTR_ERR_OR_ZERO(phy_provider); +} + +static struct platform_driver ipq4019_usb_phy_driver = { + .probe = ipq4019_usb_phy_probe, + .driver = { + .of_match_table = ipq4019_usb_phy_of_match, + .name = "ipq4019-usb-phy", + } +}; +module_platform_driver(ipq4019_usb_phy_driver); + +MODULE_DESCRIPTION("QCOM/IPQ4019 USB phy driver"); +MODULE_AUTHOR("John Crispin <john@phrozen.org>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c index c190406246ab..e91040af3394 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp.c @@ -119,14 +119,17 @@ enum qphy_reg_layout { QPHY_PCS_AUTONOMOUS_MODE_CTRL, QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR, QPHY_PCS_LFPS_RXTERM_IRQ_STATUS, + QPHY_PCS_POWER_DOWN_CONTROL, + /* Keep last to ensure regs_layout arrays are properly initialized */ + QPHY_LAYOUT_SIZE }; -static const unsigned int msm8996_ufsphy_regs_layout[] = { +static const unsigned int msm8996_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = { [QPHY_START_CTRL] = 0x00, [QPHY_PCS_READY_STATUS] = 0x168, }; -static const unsigned int pciephy_regs_layout[] = { +static const unsigned int pciephy_regs_layout[QPHY_LAYOUT_SIZE] = { [QPHY_COM_SW_RESET] = 0x400, [QPHY_COM_POWER_DOWN_CONTROL] = 0x404, [QPHY_COM_START_CONTROL] = 0x408, @@ -142,7 +145,7 @@ static const unsigned int pciephy_regs_layout[] = { [QPHY_PCS_STATUS] = 0x174, }; -static const unsigned int usb3phy_regs_layout[] = { +static const unsigned int usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { [QPHY_FLL_CNTRL1] = 0xc0, [QPHY_FLL_CNTRL2] = 0xc4, [QPHY_FLL_CNT_VAL_L] = 0xc8, @@ -156,7 +159,7 @@ static const unsigned int usb3phy_regs_layout[] = { [QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x178, }; -static const unsigned int qmp_v3_usb3phy_regs_layout[] = { +static const unsigned int qmp_v3_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { [QPHY_SW_RESET] = 0x00, [QPHY_START_CTRL] = 0x08, [QPHY_PCS_STATUS] = 0x174, @@ -165,27 +168,34 @@ static const unsigned int qmp_v3_usb3phy_regs_layout[] = { [QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x170, }; -static const unsigned int sdm845_qmp_pciephy_regs_layout[] = { +static const unsigned int sdm845_qmp_pciephy_regs_layout[QPHY_LAYOUT_SIZE] = { [QPHY_SW_RESET] = 0x00, [QPHY_START_CTRL] = 0x08, [QPHY_PCS_STATUS] = 0x174, }; -static const unsigned int sdm845_qhp_pciephy_regs_layout[] = { +static const unsigned int sdm845_qhp_pciephy_regs_layout[QPHY_LAYOUT_SIZE] = { [QPHY_SW_RESET] = 0x00, [QPHY_START_CTRL] = 0x08, [QPHY_PCS_STATUS] = 0x2ac, }; -static const unsigned int sdm845_ufsphy_regs_layout[] = { +static const unsigned int qmp_v4_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { + [QPHY_SW_RESET] = 0x00, + [QPHY_START_CTRL] = 0x44, + [QPHY_PCS_STATUS] = 0x14, + [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, +}; + +static const unsigned int sdm845_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = { [QPHY_START_CTRL] = 0x00, [QPHY_PCS_READY_STATUS] = 0x160, }; -static const unsigned int sm8150_ufsphy_regs_layout[] = { - [QPHY_START_CTRL] = QPHY_V4_PHY_START, - [QPHY_PCS_READY_STATUS] = QPHY_V4_PCS_READY_STATUS, - [QPHY_SW_RESET] = QPHY_V4_SW_RESET, +static const unsigned int sm8150_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = { + [QPHY_START_CTRL] = QPHY_V4_PCS_UFS_PHY_START, + [QPHY_PCS_READY_STATUS] = QPHY_V4_PCS_UFS_READY_STATUS, + [QPHY_SW_RESET] = QPHY_V4_PCS_UFS_SW_RESET, }; static const struct qmp_phy_init_tbl msm8996_pcie_serdes_tbl[] = { @@ -1272,13 +1282,121 @@ static const struct qmp_phy_init_tbl sm8150_ufsphy_rx_tbl[] = { }; static const struct qmp_phy_init_tbl sm8150_ufsphy_pcs_tbl[] = { - QMP_PHY_INIT_CFG(QPHY_V4_RX_SIGDET_CTRL2, 0x6d), - QMP_PHY_INIT_CFG(QPHY_V4_TX_LARGE_AMP_DRV_LVL, 0x0a), - QMP_PHY_INIT_CFG(QPHY_V4_TX_SMALL_AMP_DRV_LVL, 0x02), - QMP_PHY_INIT_CFG(QPHY_V4_TX_MID_TERM_CTRL1, 0x43), - QMP_PHY_INIT_CFG(QPHY_V4_DEBUG_BUS_CLKSEL, 0x1f), - QMP_PHY_INIT_CFG(QPHY_V4_RX_MIN_HIBERN8_TIME, 0xff), - QMP_PHY_INIT_CFG(QPHY_V4_MULTI_LANE_CTRL1, 0x02), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_RX_SIGDET_CTRL2, 0x6d), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0a), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_SMALL_AMP_DRV_LVL, 0x02), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_MID_TERM_CTRL1, 0x43), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_DEBUG_BUS_CLKSEL, 0x1f), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_RX_MIN_HIBERN8_TIME, 0xff), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_MULTI_LANE_CTRL1, 0x02), +}; + +static const struct qmp_phy_init_tbl sm8150_usb3_serdes_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0xde), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x07), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_IPTRIM, 0x20), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x1a), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x34), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x34), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x82), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x82), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0xab), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0xea), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xea), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0x24), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xca), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x1e), + QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), +}; + +static const struct qmp_phy_init_tbl sm8150_usb3_tx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_TX, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_RX, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xd5), + QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), + QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x20), +}; + +static const struct qmp_phy_init_tbl sm8150_usb3_rx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x05), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x05), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x05), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0e), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0xbf), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0xbf), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x94), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x0b), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb3), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0xa0), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V4_RX_VTH_CODE, 0x10), +}; + +static const struct qmp_phy_init_tbl sm8150_usb3_pcs_tbl[] = { + /* Lock Det settings */ + QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), + + QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), + QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), }; /* struct qmp_phy_cfg - per-PHY initialization config */ @@ -1445,6 +1563,10 @@ static const char * const sdm845_pciephy_clk_l[] = { "aux", "cfg_ahb", "ref", "refgen", }; +static const char * const qmp_v4_phy_clk_l[] = { + "aux", "ref_clk_src", "ref", "com_aux", +}; + static const char * const sdm845_ufs_phy_clk_l[] = { "ref", "ref_aux", }; @@ -1458,6 +1580,10 @@ static const char * const msm8996_usb3phy_reset_l[] = { "phy", "common", }; +static const char * const sc7180_usb3phy_reset_l[] = { + "phy", +}; + static const char * const sdm845_pciephy_reset_l[] = { "phy", }; @@ -1671,6 +1797,37 @@ static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = { .is_dual_lane_phy = true, }; +static const struct qmp_phy_cfg sc7180_usb3phy_cfg = { + .type = PHY_TYPE_USB3, + .nlanes = 1, + + .serdes_tbl = qmp_v3_usb3_serdes_tbl, + .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl), + .tx_tbl = qmp_v3_usb3_tx_tbl, + .tx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_tx_tbl), + .rx_tbl = qmp_v3_usb3_rx_tbl, + .rx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_rx_tbl), + .pcs_tbl = qmp_v3_usb3_pcs_tbl, + .pcs_tbl_num = ARRAY_SIZE(qmp_v3_usb3_pcs_tbl), + .clk_list = qmp_v3_phy_clk_l, + .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), + .reset_list = sc7180_usb3phy_reset_l, + .num_resets = ARRAY_SIZE(sc7180_usb3phy_reset_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = qmp_v3_usb3phy_regs_layout, + + .start_ctrl = SERDES_START | PCS_START, + .pwrdn_ctrl = SW_PWRDN, + + .has_pwrdn_delay = true, + .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, + .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, + + .has_phy_dp_com_ctrl = true, + .is_dual_lane_phy = true, +}; + static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = { .type = PHY_TYPE_USB3, .nlanes = 1, @@ -1798,6 +1955,37 @@ static const struct qmp_phy_cfg sm8150_ufsphy_cfg = { .is_dual_lane_phy = true, }; +static const struct qmp_phy_cfg sm8150_usb3phy_cfg = { + .type = PHY_TYPE_USB3, + .nlanes = 1, + + .serdes_tbl = sm8150_usb3_serdes_tbl, + .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl), + .tx_tbl = sm8150_usb3_tx_tbl, + .tx_tbl_num = ARRAY_SIZE(sm8150_usb3_tx_tbl), + .rx_tbl = sm8150_usb3_rx_tbl, + .rx_tbl_num = ARRAY_SIZE(sm8150_usb3_rx_tbl), + .pcs_tbl = sm8150_usb3_pcs_tbl, + .pcs_tbl_num = ARRAY_SIZE(sm8150_usb3_pcs_tbl), + .clk_list = qmp_v4_phy_clk_l, + .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), + .reset_list = msm8996_usb3phy_reset_l, + .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = qmp_v4_usb3phy_regs_layout, + + .start_ctrl = SERDES_START | PCS_START, + .pwrdn_ctrl = SW_PWRDN, + + .has_pwrdn_delay = true, + .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, + .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, + + .has_phy_dp_com_ctrl = true, + .is_dual_lane_phy = true, +}; + static void qcom_qmp_phy_configure(void __iomem *base, const unsigned int *regs, const struct qmp_phy_init_tbl tbl[], @@ -1880,11 +2068,18 @@ static int qcom_qmp_phy_com_init(struct qmp_phy *qphy) SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET); } - if (cfg->has_phy_com_ctrl) + if (cfg->has_phy_com_ctrl) { qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL], SW_PWRDN); - else - qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl); + } else { + if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) + qphy_setbits(pcs, + cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], + cfg->pwrdn_ctrl); + else + qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, + cfg->pwrdn_ctrl); + } /* Serdes configuration */ qcom_qmp_phy_configure(serdes, cfg->regs, cfg->serdes_tbl, @@ -2110,7 +2305,13 @@ static int qcom_qmp_phy_disable(struct phy *phy) qphy_clrbits(qphy->pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); /* Put PHY into POWER DOWN state: active low */ - qphy_clrbits(qphy->pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl); + if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) { + qphy_clrbits(qphy->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], + cfg->pwrdn_ctrl); + } else { + qphy_clrbits(qphy->pcs, QPHY_POWER_DOWN_CONTROL, + cfg->pwrdn_ctrl); + } if (cfg->has_lane_rst) reset_control_assert(qphy->lane_rst); @@ -2516,6 +2717,9 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = { .compatible = "qcom,ipq8074-qmp-pcie-phy", .data = &ipq8074_pciephy_cfg, }, { + .compatible = "qcom,sc7180-qmp-usb3-phy", + .data = &sc7180_usb3phy_cfg, + }, { .compatible = "qcom,sdm845-qhp-pcie-phy", .data = &sdm845_qhp_pciephy_cfg, }, { @@ -2536,6 +2740,12 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = { }, { .compatible = "qcom,sm8150-qmp-ufs-phy", .data = &sm8150_ufsphy_cfg, + }, { + .compatible = "qcom,sm8250-qmp-ufs-phy", + .data = &sm8150_ufsphy_cfg, + }, { + .compatible = "qcom,sm8150-qmp-usb3-phy", + .data = &sm8150_usb3phy_cfg, }, { }, }; diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h index dece0e67704b..6d017a0c0c8d 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp.h +++ b/drivers/phy/qualcomm/phy-qcom-qmp.h @@ -125,7 +125,7 @@ #define QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB 0x1DC #define QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB 0x1E0 -/* Only for QMP V3 PHY - DP COM registers */ +/* Only for QMP V3 & V4 PHY - DP COM registers */ #define QPHY_V3_DP_COM_PHY_MODE_CTRL 0x00 #define QPHY_V3_DP_COM_SW_RESET 0x04 #define QPHY_V3_DP_COM_POWER_DOWN_CTRL 0x08 @@ -314,6 +314,14 @@ #define QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG5 0x60 /* Only for QMP V4 PHY - QSERDES COM registers */ +#define QSERDES_V4_COM_SSC_EN_CENTER 0x010 +#define QSERDES_V4_COM_SSC_PER1 0x01c +#define QSERDES_V4_COM_SSC_PER2 0x020 +#define QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0 0x024 +#define QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0 0x028 +#define QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1 0x030 +#define QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1 0x034 +#define QSERDES_V4_COM_SYSCLK_BUF_ENABLE 0x050 #define QSERDES_V4_COM_PLL_IVCO 0x058 #define QSERDES_V4_COM_CMN_IPTRIM 0x060 #define QSERDES_V4_COM_CP_CTRL_MODE0 0x074 @@ -330,10 +338,22 @@ #define QSERDES_V4_COM_DEC_START_MODE0 0x0bc #define QSERDES_V4_COM_LOCK_CMP2_MODE1 0x0b8 #define QSERDES_V4_COM_DEC_START_MODE1 0x0c4 +#define QSERDES_V4_COM_DIV_FRAC_START1_MODE0 0x0cc +#define QSERDES_V4_COM_DIV_FRAC_START2_MODE0 0x0d0 +#define QSERDES_V4_COM_DIV_FRAC_START3_MODE0 0x0d4 +#define QSERDES_V4_COM_DIV_FRAC_START1_MODE1 0x0d8 +#define QSERDES_V4_COM_DIV_FRAC_START2_MODE1 0x0dc +#define QSERDES_V4_COM_DIV_FRAC_START3_MODE1 0x0e0 #define QSERDES_V4_COM_VCO_TUNE_MAP 0x10c +#define QSERDES_V4_COM_VCO_TUNE1_MODE0 0x110 +#define QSERDES_V4_COM_VCO_TUNE2_MODE0 0x114 +#define QSERDES_V4_COM_VCO_TUNE1_MODE1 0x118 +#define QSERDES_V4_COM_VCO_TUNE2_MODE1 0x11c #define QSERDES_V4_COM_VCO_TUNE_INITVAL2 0x124 #define QSERDES_V4_COM_HSCLK_SEL 0x158 #define QSERDES_V4_COM_HSCLK_HS_SWITCH_SEL 0x15c +#define QSERDES_V4_COM_CORECLK_DIV_MODE1 0x16c +#define QSERDES_V4_COM_SVS_MODE_CLK_SEL 0x184 #define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0 0x1ac #define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0 0x1b0 #define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1 0x1b4 @@ -341,12 +361,16 @@ #define QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1 0x1b8 /* Only for QMP V4 PHY - TX registers */ +#define QSERDES_V4_TX_RES_CODE_LANE_TX 0x34 +#define QSERDES_V4_TX_RES_CODE_LANE_RX 0x38 #define QSERDES_V4_TX_LANE_MODE_1 0x84 +#define QSERDES_V4_TX_RCV_DETECT_LVL_2 0x9c #define QSERDES_V4_TX_PWM_GEAR_1_DIVIDER_BAND0_1 0xd8 #define QSERDES_V4_TX_PWM_GEAR_2_DIVIDER_BAND0_1 0xdC #define QSERDES_V4_TX_PWM_GEAR_3_DIVIDER_BAND0_1 0xe0 #define QSERDES_V4_TX_PWM_GEAR_4_DIVIDER_BAND0_1 0xe4 #define QSERDES_V4_TX_TRAN_DRVR_EMP_EN 0xb8 +#define QSERDES_V4_TX_PI_QEC_CTRL 0x104 /* Only for QMP V4 PHY - RX registers */ #define QSERDES_V4_RX_UCDR_FO_GAIN 0x008 @@ -354,17 +378,27 @@ #define QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN 0x030 #define QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE 0x034 #define QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW 0x03c +#define QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH 0x040 #define QSERDES_V4_RX_UCDR_PI_CONTROLS 0x044 #define QSERDES_V4_RX_UCDR_PI_CTRL2 0x048 +#define QSERDES_V4_RX_UCDR_SB2_THRESH1 0x04c +#define QSERDES_V4_RX_UCDR_SB2_THRESH2 0x050 +#define QSERDES_V4_RX_UCDR_SB2_GAIN1 0x054 +#define QSERDES_V4_RX_UCDR_SB2_GAIN2 0x058 +#define QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE 0x060 #define QSERDES_V4_RX_AC_JTAG_ENABLE 0x068 #define QSERDES_V4_RX_AC_JTAG_MODE 0x078 #define QSERDES_V4_RX_RX_TERM_BW 0x080 +#define QSERDES_V4_RX_VGA_CAL_CNTRL1 0x0d4 +#define QSERDES_V4_RX_VGA_CAL_CNTRL2 0x0d8 +#define QSERDES_V4_RX_GM_CAL 0x0dc #define QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2 0x0ec #define QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3 0x0f0 #define QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4 0x0f4 #define QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW 0x0f8 #define QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH 0x0fc #define QSERDES_V4_RX_RX_IDAC_MEASURE_TIME 0x100 +#define QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x110 #define QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2 0x114 #define QSERDES_V4_RX_SIGDET_CNTRL 0x11c #define QSERDES_V4_RX_SIGDET_LVL 0x120 @@ -385,29 +419,32 @@ #define QSERDES_V4_RX_RX_MODE_10_HIGH2 0x1a0 #define QSERDES_V4_RX_RX_MODE_10_HIGH3 0x1a4 #define QSERDES_V4_RX_RX_MODE_10_HIGH4 0x1a8 +#define QSERDES_V4_RX_DFE_EN_TIMER 0x1b4 +#define QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET 0x1b8 #define QSERDES_V4_RX_DCC_CTRL1 0x1bc +#define QSERDES_V4_RX_VTH_CODE 0x1c4 -/* Only for QMP V4 PHY - PCS registers */ -#define QPHY_V4_PHY_START 0x000 -#define QPHY_V4_POWER_DOWN_CONTROL 0x004 -#define QPHY_V4_SW_RESET 0x008 -#define QPHY_V4_TIMER_20US_CORECLK_STEPS_MSB 0x00c -#define QPHY_V4_TIMER_20US_CORECLK_STEPS_LSB 0x010 -#define QPHY_V4_PLL_CNTL 0x02c -#define QPHY_V4_TX_LARGE_AMP_DRV_LVL 0x030 -#define QPHY_V4_TX_SMALL_AMP_DRV_LVL 0x038 -#define QPHY_V4_BIST_FIXED_PAT_CTRL 0x060 -#define QPHY_V4_TX_HSGEAR_CAPABILITY 0x074 -#define QPHY_V4_RX_HSGEAR_CAPABILITY 0x0b4 -#define QPHY_V4_DEBUG_BUS_CLKSEL 0x124 -#define QPHY_V4_LINECFG_DISABLE 0x148 -#define QPHY_V4_RX_MIN_HIBERN8_TIME 0x150 -#define QPHY_V4_RX_SIGDET_CTRL2 0x158 -#define QPHY_V4_TX_PWM_GEAR_BAND 0x160 -#define QPHY_V4_TX_HS_GEAR_BAND 0x168 -#define QPHY_V4_PCS_READY_STATUS 0x180 -#define QPHY_V4_TX_MID_TERM_CTRL1 0x1d8 -#define QPHY_V4_MULTI_LANE_CTRL1 0x1e0 +/* Only for QMP V4 PHY - UFS PCS registers */ +#define QPHY_V4_PCS_UFS_PHY_START 0x000 +#define QPHY_V4_PCS_UFS_POWER_DOWN_CONTROL 0x004 +#define QPHY_V4_PCS_UFS_SW_RESET 0x008 +#define QPHY_V4_PCS_UFS_TIMER_20US_CORECLK_STEPS_MSB 0x00c +#define QPHY_V4_PCS_UFS_TIMER_20US_CORECLK_STEPS_LSB 0x010 +#define QPHY_V4_PCS_UFS_PLL_CNTL 0x02c +#define QPHY_V4_PCS_UFS_TX_LARGE_AMP_DRV_LVL 0x030 +#define QPHY_V4_PCS_UFS_TX_SMALL_AMP_DRV_LVL 0x038 +#define QPHY_V4_PCS_UFS_BIST_FIXED_PAT_CTRL 0x060 +#define QPHY_V4_PCS_UFS_TX_HSGEAR_CAPABILITY 0x074 +#define QPHY_V4_PCS_UFS_RX_HSGEAR_CAPABILITY 0x0b4 +#define QPHY_V4_PCS_UFS_DEBUG_BUS_CLKSEL 0x124 +#define QPHY_V4_PCS_UFS_LINECFG_DISABLE 0x148 +#define QPHY_V4_PCS_UFS_RX_MIN_HIBERN8_TIME 0x150 +#define QPHY_V4_PCS_UFS_RX_SIGDET_CTRL2 0x158 +#define QPHY_V4_PCS_UFS_TX_PWM_GEAR_BAND 0x160 +#define QPHY_V4_PCS_UFS_TX_HS_GEAR_BAND 0x168 +#define QPHY_V4_PCS_UFS_READY_STATUS 0x180 +#define QPHY_V4_PCS_UFS_TX_MID_TERM_CTRL1 0x1d8 +#define QPHY_V4_PCS_UFS_MULTI_LANE_CTRL1 0x1e0 /* PCIE GEN3 COM registers */ #define PCIE_GEN3_QHP_COM_SSC_EN_CENTER 0x14 @@ -523,4 +560,161 @@ #define PCIE_GEN3_QHP_PHY_POWER_STATE_CONFIG5 0x16c #define PCIE_GEN3_QHP_PHY_PCS_TX_RX_CONFIG 0x174 +/* Only for QMP V4 PHY - USB/PCIe PCS registers */ +#define QPHY_V4_PCS_SW_RESET 0x000 +#define QPHY_V4_PCS_REVISION_ID0 0x004 +#define QPHY_V4_PCS_REVISION_ID1 0x008 +#define QPHY_V4_PCS_REVISION_ID2 0x00c +#define QPHY_V4_PCS_REVISION_ID3 0x010 +#define QPHY_V4_PCS_PCS_STATUS1 0x014 +#define QPHY_V4_PCS_PCS_STATUS2 0x018 +#define QPHY_V4_PCS_PCS_STATUS3 0x01c +#define QPHY_V4_PCS_PCS_STATUS4 0x020 +#define QPHY_V4_PCS_PCS_STATUS5 0x024 +#define QPHY_V4_PCS_PCS_STATUS6 0x028 +#define QPHY_V4_PCS_PCS_STATUS7 0x02c +#define QPHY_V4_PCS_DEBUG_BUS_0_STATUS 0x030 +#define QPHY_V4_PCS_DEBUG_BUS_1_STATUS 0x034 +#define QPHY_V4_PCS_DEBUG_BUS_2_STATUS 0x038 +#define QPHY_V4_PCS_DEBUG_BUS_3_STATUS 0x03c +#define QPHY_V4_PCS_POWER_DOWN_CONTROL 0x040 +#define QPHY_V4_PCS_START_CONTROL 0x044 +#define QPHY_V4_PCS_INSIG_SW_CTRL1 0x048 +#define QPHY_V4_PCS_INSIG_SW_CTRL2 0x04c +#define QPHY_V4_PCS_INSIG_SW_CTRL3 0x050 +#define QPHY_V4_PCS_INSIG_SW_CTRL4 0x054 +#define QPHY_V4_PCS_INSIG_SW_CTRL5 0x058 +#define QPHY_V4_PCS_INSIG_SW_CTRL6 0x05c +#define QPHY_V4_PCS_INSIG_SW_CTRL7 0x060 +#define QPHY_V4_PCS_INSIG_SW_CTRL8 0x064 +#define QPHY_V4_PCS_INSIG_MX_CTRL1 0x068 +#define QPHY_V4_PCS_INSIG_MX_CTRL2 0x06c +#define QPHY_V4_PCS_INSIG_MX_CTRL3 0x070 +#define QPHY_V4_PCS_INSIG_MX_CTRL4 0x074 +#define QPHY_V4_PCS_INSIG_MX_CTRL5 0x078 +#define QPHY_V4_PCS_INSIG_MX_CTRL7 0x07c +#define QPHY_V4_PCS_INSIG_MX_CTRL8 0x080 +#define QPHY_V4_PCS_OUTSIG_SW_CTRL1 0x084 +#define QPHY_V4_PCS_OUTSIG_MX_CTRL1 0x088 +#define QPHY_V4_PCS_CLAMP_ENABLE 0x08c +#define QPHY_V4_PCS_POWER_STATE_CONFIG1 0x090 +#define QPHY_V4_PCS_POWER_STATE_CONFIG2 0x094 +#define QPHY_V4_PCS_FLL_CNTRL1 0x098 +#define QPHY_V4_PCS_FLL_CNTRL2 0x09c +#define QPHY_V4_PCS_FLL_CNT_VAL_L 0x0a0 +#define QPHY_V4_PCS_FLL_CNT_VAL_H_TOL 0x0a4 +#define QPHY_V4_PCS_FLL_MAN_CODE 0x0a8 +#define QPHY_V4_PCS_TEST_CONTROL1 0x0ac +#define QPHY_V4_PCS_TEST_CONTROL2 0x0b0 +#define QPHY_V4_PCS_TEST_CONTROL3 0x0b4 +#define QPHY_V4_PCS_TEST_CONTROL4 0x0b8 +#define QPHY_V4_PCS_TEST_CONTROL5 0x0bc +#define QPHY_V4_PCS_TEST_CONTROL6 0x0c0 +#define QPHY_V4_PCS_LOCK_DETECT_CONFIG1 0x0c4 +#define QPHY_V4_PCS_LOCK_DETECT_CONFIG2 0x0c8 +#define QPHY_V4_PCS_LOCK_DETECT_CONFIG3 0x0cc +#define QPHY_V4_PCS_LOCK_DETECT_CONFIG4 0x0d0 +#define QPHY_V4_PCS_LOCK_DETECT_CONFIG5 0x0d4 +#define QPHY_V4_PCS_LOCK_DETECT_CONFIG6 0x0d8 +#define QPHY_V4_PCS_REFGEN_REQ_CONFIG1 0x0dc +#define QPHY_V4_PCS_REFGEN_REQ_CONFIG2 0x0e0 +#define QPHY_V4_PCS_REFGEN_REQ_CONFIG3 0x0e4 +#define QPHY_V4_PCS_BIST_CTRL 0x0e8 +#define QPHY_V4_PCS_PRBS_POLY0 0x0ec +#define QPHY_V4_PCS_PRBS_POLY1 0x0f0 +#define QPHY_V4_PCS_FIXED_PAT0 0x0f4 +#define QPHY_V4_PCS_FIXED_PAT1 0x0f8 +#define QPHY_V4_PCS_FIXED_PAT2 0x0fc +#define QPHY_V4_PCS_FIXED_PAT3 0x100 +#define QPHY_V4_PCS_FIXED_PAT4 0x104 +#define QPHY_V4_PCS_FIXED_PAT5 0x108 +#define QPHY_V4_PCS_FIXED_PAT6 0x10c +#define QPHY_V4_PCS_FIXED_PAT7 0x110 +#define QPHY_V4_PCS_FIXED_PAT8 0x114 +#define QPHY_V4_PCS_FIXED_PAT9 0x118 +#define QPHY_V4_PCS_FIXED_PAT10 0x11c +#define QPHY_V4_PCS_FIXED_PAT11 0x120 +#define QPHY_V4_PCS_FIXED_PAT12 0x124 +#define QPHY_V4_PCS_FIXED_PAT13 0x128 +#define QPHY_V4_PCS_FIXED_PAT14 0x12c +#define QPHY_V4_PCS_FIXED_PAT15 0x130 +#define QPHY_V4_PCS_TXMGN_CONFIG 0x134 +#define QPHY_V4_PCS_G12S1_TXMGN_V0 0x138 +#define QPHY_V4_PCS_G12S1_TXMGN_V1 0x13c +#define QPHY_V4_PCS_G12S1_TXMGN_V2 0x140 +#define QPHY_V4_PCS_G12S1_TXMGN_V3 0x144 +#define QPHY_V4_PCS_G12S1_TXMGN_V4 0x148 +#define QPHY_V4_PCS_G12S1_TXMGN_V0_RS 0x14c +#define QPHY_V4_PCS_G12S1_TXMGN_V1_RS 0x150 +#define QPHY_V4_PCS_G12S1_TXMGN_V2_RS 0x154 +#define QPHY_V4_PCS_G12S1_TXMGN_V3_RS 0x158 +#define QPHY_V4_PCS_G12S1_TXMGN_V4_RS 0x15c +#define QPHY_V4_PCS_G3S2_TXMGN_MAIN 0x160 +#define QPHY_V4_PCS_G3S2_TXMGN_MAIN_RS 0x164 +#define QPHY_V4_PCS_G12S1_TXDEEMPH_M6DB 0x168 +#define QPHY_V4_PCS_G12S1_TXDEEMPH_M3P5DB 0x16c +#define QPHY_V4_PCS_G3S2_PRE_GAIN 0x170 +#define QPHY_V4_PCS_G3S2_POST_GAIN 0x174 +#define QPHY_V4_PCS_G3S2_PRE_POST_OFFSET 0x178 +#define QPHY_V4_PCS_G3S2_PRE_GAIN_RS 0x17c +#define QPHY_V4_PCS_G3S2_POST_GAIN_RS 0x180 +#define QPHY_V4_PCS_G3S2_PRE_POST_OFFSET_RS 0x184 +#define QPHY_V4_PCS_RX_SIGDET_LVL 0x188 +#define QPHY_V4_PCS_RX_SIGDET_DTCT_CNTRL 0x18c +#define QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L 0x190 +#define QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H 0x194 +#define QPHY_V4_PCS_RATE_SLEW_CNTRL1 0x198 +#define QPHY_V4_PCS_RATE_SLEW_CNTRL2 0x19c +#define QPHY_V4_PCS_PWRUP_RESET_DLY_TIME_AUXCLK 0x1a0 +#define QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_L 0x1a4 +#define QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_H 0x1a8 +#define QPHY_V4_PCS_TSYNC_RSYNC_TIME 0x1ac +#define QPHY_V4_PCS_CDR_RESET_TIME 0x1b0 +#define QPHY_V4_PCS_TSYNC_DLY_TIME 0x1b4 +#define QPHY_V4_PCS_ELECIDLE_DLY_SEL 0x1b8 +#define QPHY_V4_PCS_CMN_ACK_OUT_SEL 0x1bc +#define QPHY_V4_PCS_ALIGN_DETECT_CONFIG1 0x1c0 +#define QPHY_V4_PCS_ALIGN_DETECT_CONFIG2 0x1c4 +#define QPHY_V4_PCS_ALIGN_DETECT_CONFIG3 0x1c8 +#define QPHY_V4_PCS_ALIGN_DETECT_CONFIG4 0x1cc +#define QPHY_V4_PCS_PCS_TX_RX_CONFIG 0x1d0 +#define QPHY_V4_PCS_RX_IDLE_DTCT_CNTRL 0x1d4 +#define QPHY_V4_PCS_RX_DCC_CAL_CONFIG 0x1d8 +#define QPHY_V4_PCS_EQ_CONFIG1 0x1dc +#define QPHY_V4_PCS_EQ_CONFIG2 0x1e0 +#define QPHY_V4_PCS_EQ_CONFIG3 0x1e4 +#define QPHY_V4_PCS_EQ_CONFIG4 0x1e8 +#define QPHY_V4_PCS_EQ_CONFIG5 0x1ec +#define QPHY_V4_PCS_USB3_POWER_STATE_CONFIG1 0x300 +#define QPHY_V4_PCS_USB3_AUTONOMOUS_MODE_STATUS 0x304 +#define QPHY_V4_PCS_USB3_AUTONOMOUS_MODE_CTRL 0x308 +#define QPHY_V4_PCS_USB3_AUTONOMOUS_MODE_CTRL2 0x30c +#define QPHY_V4_PCS_USB3_LFPS_RXTERM_IRQ_SOURCE_STATUS 0x310 +#define QPHY_V4_PCS_USB3_LFPS_RXTERM_IRQ_CLEAR 0x314 +#define QPHY_V4_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL 0x318 +#define QPHY_V4_PCS_USB3_LFPS_TX_ECSTART 0x31c +#define QPHY_V4_PCS_USB3_LFPS_PER_TIMER_VAL 0x320 +#define QPHY_V4_PCS_USB3_LFPS_TX_END_CNT_U3_START 0x324 +#define QPHY_V4_PCS_USB3_RXEQTRAINING_LOCK_TIME 0x328 +#define QPHY_V4_PCS_USB3_RXEQTRAINING_WAIT_TIME 0x32c +#define QPHY_V4_PCS_USB3_RXEQTRAINING_CTLE_TIME 0x330 +#define QPHY_V4_PCS_USB3_RXEQTRAINING_WAIT_TIME_S2 0x334 +#define QPHY_V4_PCS_USB3_RXEQTRAINING_DFE_TIME_S2 0x338 +#define QPHY_V4_PCS_USB3_RCVR_DTCT_DLY_U3_L 0x33c +#define QPHY_V4_PCS_USB3_RCVR_DTCT_DLY_U3_H 0x340 +#define QPHY_V4_PCS_USB3_ARCVR_DTCT_EN_PERIOD 0x344 +#define QPHY_V4_PCS_USB3_ARCVR_DTCT_CM_DLY 0x348 +#define QPHY_V4_PCS_USB3_TXONESZEROS_RUN_LENGTH 0x34c +#define QPHY_V4_PCS_USB3_ALFPS_DEGLITCH_VAL 0x350 +#define QPHY_V4_PCS_USB3_SIGDET_STARTUP_TIMER_VAL 0x354 +#define QPHY_V4_PCS_USB3_TEST_CONTROL 0x358 + +/* Only for QMP V4 PHY - PCS_MISC registers */ +#define QPHY_V4_PCS_MISC_TYPEC_CTRL 0x00 +#define QPHY_V4_PCS_MISC_TYPEC_PWRDN_CTRL 0x04 +#define QPHY_V4_PCS_MISC_PCS_MISC_CONFIG1 0x08 +#define QPHY_V4_PCS_MISC_CLAMP_ENABLE 0x0c +#define QPHY_V4_PCS_MISC_TYPEC_STATUS 0x10 +#define QPHY_V4_PCS_MISC_PLACEHOLDER_STATUS 0x14 + #endif diff --git a/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c b/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c new file mode 100644 index 000000000000..4d74045271eb --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c @@ -0,0 +1,287 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/phy/phy.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> +#include <linux/reset.h> +#include <linux/slab.h> + +#define USB2_PHY_USB_PHY_UTMI_CTRL0 (0x3c) +#define SLEEPM BIT(0) +#define OPMODE_MASK GENMASK(4, 3) +#define OPMODE_NORMAL (0x00) +#define OPMODE_NONDRIVING BIT(3) +#define TERMSEL BIT(5) + +#define USB2_PHY_USB_PHY_UTMI_CTRL1 (0x40) +#define XCVRSEL BIT(0) + +#define USB2_PHY_USB_PHY_UTMI_CTRL5 (0x50) +#define POR BIT(1) + +#define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON0 (0x54) +#define RETENABLEN BIT(3) +#define FSEL_MASK GENMASK(7, 5) +#define FSEL_DEFAULT (0x3 << 4) + +#define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON1 (0x58) +#define VBUSVLDEXTSEL0 BIT(4) +#define PLLBTUNE BIT(5) + +#define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON2 (0x5c) +#define VREGBYPASS BIT(0) + +#define USB2_PHY_USB_PHY_HS_PHY_CTRL1 (0x60) +#define VBUSVLDEXT0 BIT(0) + +#define USB2_PHY_USB_PHY_HS_PHY_CTRL2 (0x64) +#define USB2_AUTO_RESUME BIT(0) +#define USB2_SUSPEND_N BIT(2) +#define USB2_SUSPEND_N_SEL BIT(3) + +#define USB2_PHY_USB_PHY_CFG0 (0x94) +#define UTMI_PHY_DATAPATH_CTRL_OVERRIDE_EN BIT(0) +#define UTMI_PHY_CMN_CTRL_OVERRIDE_EN BIT(1) + +#define USB2_PHY_USB_PHY_REFCLK_CTRL (0xa0) +#define REFCLK_SEL_MASK GENMASK(1, 0) +#define REFCLK_SEL_DEFAULT (0x2 << 0) + +static const char * const qcom_snps_hsphy_vreg_names[] = { + "vdda-pll", "vdda33", "vdda18", +}; + +#define SNPS_HS_NUM_VREGS ARRAY_SIZE(qcom_snps_hsphy_vreg_names) + +/** + * struct qcom_snps_hsphy - snps hs phy attributes + * + * @phy: generic phy + * @base: iomapped memory space for snps hs phy + * + * @cfg_ahb_clk: AHB2PHY interface clock + * @ref_clk: phy reference clock + * @iface_clk: phy interface clock + * @phy_reset: phy reset control + * @vregs: regulator supplies bulk data + * @phy_initialized: if PHY has been initialized correctly + */ +struct qcom_snps_hsphy { + struct phy *phy; + void __iomem *base; + + struct clk *cfg_ahb_clk; + struct clk *ref_clk; + struct reset_control *phy_reset; + struct regulator_bulk_data vregs[SNPS_HS_NUM_VREGS]; + + bool phy_initialized; +}; + +static inline void qcom_snps_hsphy_write_mask(void __iomem *base, u32 offset, + u32 mask, u32 val) +{ + u32 reg; + + reg = readl_relaxed(base + offset); + reg &= ~mask; + reg |= val & mask; + writel_relaxed(reg, base + offset); + + /* Ensure above write is completed */ + readl_relaxed(base + offset); +} + +static int qcom_snps_hsphy_init(struct phy *phy) +{ + struct qcom_snps_hsphy *hsphy = phy_get_drvdata(phy); + int ret; + + dev_vdbg(&phy->dev, "%s(): Initializing SNPS HS phy\n", __func__); + + ret = regulator_bulk_enable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs); + if (ret) + return ret; + + ret = clk_prepare_enable(hsphy->cfg_ahb_clk); + if (ret) { + dev_err(&phy->dev, "failed to enable cfg ahb clock, %d\n", ret); + goto poweroff_phy; + } + + ret = reset_control_assert(hsphy->phy_reset); + if (ret) { + dev_err(&phy->dev, "failed to assert phy_reset, %d\n", ret); + goto disable_ahb_clk; + } + + usleep_range(100, 150); + + ret = reset_control_deassert(hsphy->phy_reset); + if (ret) { + dev_err(&phy->dev, "failed to de-assert phy_reset, %d\n", ret); + goto disable_ahb_clk; + } + + qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_CFG0, + UTMI_PHY_CMN_CTRL_OVERRIDE_EN, + UTMI_PHY_CMN_CTRL_OVERRIDE_EN); + qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_UTMI_CTRL5, + POR, POR); + qcom_snps_hsphy_write_mask(hsphy->base, + USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON0, + FSEL_MASK, 0); + qcom_snps_hsphy_write_mask(hsphy->base, + USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON1, + PLLBTUNE, PLLBTUNE); + qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_REFCLK_CTRL, + REFCLK_SEL_DEFAULT, REFCLK_SEL_MASK); + qcom_snps_hsphy_write_mask(hsphy->base, + USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON1, + VBUSVLDEXTSEL0, VBUSVLDEXTSEL0); + qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL1, + VBUSVLDEXT0, VBUSVLDEXT0); + + qcom_snps_hsphy_write_mask(hsphy->base, + USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON2, + VREGBYPASS, VREGBYPASS); + + qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL2, + USB2_SUSPEND_N_SEL | USB2_SUSPEND_N, + USB2_SUSPEND_N_SEL | USB2_SUSPEND_N); + + qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_UTMI_CTRL0, + SLEEPM, SLEEPM); + + qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_UTMI_CTRL5, + POR, 0); + + qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL2, + USB2_SUSPEND_N_SEL, 0); + + qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_CFG0, + UTMI_PHY_CMN_CTRL_OVERRIDE_EN, 0); + + hsphy->phy_initialized = true; + + return 0; + +disable_ahb_clk: + clk_disable_unprepare(hsphy->cfg_ahb_clk); +poweroff_phy: + regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs); + + return ret; +} + +static int qcom_snps_hsphy_exit(struct phy *phy) +{ + struct qcom_snps_hsphy *hsphy = phy_get_drvdata(phy); + + reset_control_assert(hsphy->phy_reset); + clk_disable_unprepare(hsphy->cfg_ahb_clk); + regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs); + hsphy->phy_initialized = false; + + return 0; +} + +static const struct phy_ops qcom_snps_hsphy_gen_ops = { + .init = qcom_snps_hsphy_init, + .exit = qcom_snps_hsphy_exit, + .owner = THIS_MODULE, +}; + +static const struct of_device_id qcom_snps_hsphy_of_match_table[] = { + { .compatible = "qcom,sm8150-usb-hs-phy", }, + { .compatible = "qcom,usb-snps-hs-7nm-phy", }, + { .compatible = "qcom,usb-snps-femto-v2-phy", }, + { } +}; +MODULE_DEVICE_TABLE(of, qcom_snps_hsphy_of_match_table); + +static int qcom_snps_hsphy_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct qcom_snps_hsphy *hsphy; + struct phy_provider *phy_provider; + struct phy *generic_phy; + int ret, i; + int num; + + hsphy = devm_kzalloc(dev, sizeof(*hsphy), GFP_KERNEL); + if (!hsphy) + return -ENOMEM; + + hsphy->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(hsphy->base)) + return PTR_ERR(hsphy->base); + + hsphy->ref_clk = devm_clk_get(dev, "ref"); + if (IS_ERR(hsphy->ref_clk)) { + ret = PTR_ERR(hsphy->ref_clk); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to get ref clk, %d\n", ret); + return ret; + } + + hsphy->phy_reset = devm_reset_control_get_exclusive(&pdev->dev, NULL); + if (IS_ERR(hsphy->phy_reset)) { + dev_err(dev, "failed to get phy core reset\n"); + return PTR_ERR(hsphy->phy_reset); + } + + num = ARRAY_SIZE(hsphy->vregs); + for (i = 0; i < num; i++) + hsphy->vregs[i].supply = qcom_snps_hsphy_vreg_names[i]; + + ret = devm_regulator_bulk_get(dev, num, hsphy->vregs); + if (ret) { + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to get regulator supplies: %d\n", + ret); + return ret; + } + + generic_phy = devm_phy_create(dev, NULL, &qcom_snps_hsphy_gen_ops); + if (IS_ERR(generic_phy)) { + ret = PTR_ERR(generic_phy); + dev_err(dev, "failed to create phy, %d\n", ret); + return ret; + } + hsphy->phy = generic_phy; + + dev_set_drvdata(dev, hsphy); + phy_set_drvdata(generic_phy, hsphy); + + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + if (!IS_ERR(phy_provider)) + dev_dbg(dev, "Registered Qcom-SNPS HS phy\n"); + + return PTR_ERR_OR_ZERO(phy_provider); +} + +static struct platform_driver qcom_snps_hsphy_driver = { + .probe = qcom_snps_hsphy_probe, + .driver = { + .name = "qcom-snps-hs-femto-v2-phy", + .of_match_table = qcom_snps_hsphy_of_match_table, + }, +}; + +module_platform_driver(qcom_snps_hsphy_driver); + +MODULE_DESCRIPTION("Qualcomm SNPS FEMTO USB HS PHY V2 driver"); +MODULE_LICENSE("GPL v2"); |