[PATCH 2/2] phy: sprd: Add Spreadtrum usb20 hsphy driver

From: Pu Li
Date: Wed Nov 01 2023 - 01:46:00 EST


Add Spreadtrum platform USB20 HSPHY driver support. This driver
takes care of all the PHY functionality, normally paired with
DesignWare USB20 (DRD) Controller or Spreadtrum musb phy (DRD )controller.

Signed-off-by: Pu Li <pu.li@xxxxxxxxxx>
---
drivers/phy/Kconfig | 1 +
drivers/phy/Makefile | 1 +
drivers/phy/sprd/Kconfig | 14 +
drivers/phy/sprd/Makefile | 6 +
drivers/phy/sprd/phy-sprd-usb20-hs.c | 1324 ++++++++++++++++++++++++++
drivers/phy/sprd/phy-sprd-usb20-hs.h | 525 ++++++++++
6 files changed, 1871 insertions(+)
create mode 100644 drivers/phy/sprd/Kconfig
create mode 100644 drivers/phy/sprd/Makefile
create mode 100644 drivers/phy/sprd/phy-sprd-usb20-hs.c
create mode 100644 drivers/phy/sprd/phy-sprd-usb20-hs.h

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index d1670bbe6d6b..309eb623f8b3 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -92,6 +92,7 @@ source "drivers/phy/renesas/Kconfig"
source "drivers/phy/rockchip/Kconfig"
source "drivers/phy/samsung/Kconfig"
source "drivers/phy/socionext/Kconfig"
+source "drivers/phy/sprd/Kconfig"
source "drivers/phy/st/Kconfig"
source "drivers/phy/starfive/Kconfig"
source "drivers/phy/sunplus/Kconfig"
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 868a220ed0f6..d83cb5917d08 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -31,6 +31,7 @@ obj-y += allwinner/ \
rockchip/ \
samsung/ \
socionext/ \
+ sprd/ \
st/ \
starfive/ \
sunplus/ \
diff --git a/drivers/phy/sprd/Kconfig b/drivers/phy/sprd/Kconfig
new file mode 100644
index 000000000000..c43884012ef8
--- /dev/null
+++ b/drivers/phy/sprd/Kconfig
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Phy drivers for Spreadtrum platforms
+#
+
+config SPRD_USB20_HSPHY
+ tristate "Spreadtrum USB20 HSPHY Driver"
+ select USB_PHY
+ depends on ARCH_SPRD || COMPILE_TEST
+ help
+ Enable this to support the SPRD USB20 High Speed PHY that is part of SOC.
+ This driver takes care of all the PHY functionality,
+ normally paired with DesignWare USB20 (DRD) Controller or
+ Spreadtrum musb phy (DRD )controller.
diff --git a/drivers/phy/sprd/Makefile b/drivers/phy/sprd/Makefile
new file mode 100644
index 000000000000..b102f3515d47
--- /dev/null
+++ b/drivers/phy/sprd/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for physical layer drivers
+#
+
+obj-$(CONFIG_SPRD_USB20_HSPHY) += phy-sprd-usb20-hs.o
diff --git a/drivers/phy/sprd/phy-sprd-usb20-hs.c b/drivers/phy/sprd/phy-sprd-usb20-hs.c
new file mode 100644
index 000000000000..8262a745fc74
--- /dev/null
+++ b/drivers/phy/sprd/phy-sprd-usb20-hs.c
@@ -0,0 +1,1324 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2020-2023 Unisoc Inc.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/iio/consumer.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/usb/otg.h>
+#include <uapi/linux/usb/charger.h>
+
+#include "phy-sprd-usb20-hs.h"
+
+static const struct sprd_hsphy_cfg *phy_cfg;
+
+/* phy_v1 cfg ops */
+static void phy_v1_usb_enable_ctrl(struct sprd_hsphy *phy, int on) {}
+
+static void phy_v1_usb_phy_power_ctrl(struct sprd_hsphy *phy, int on)
+{
+ u32 reg, msk;
+
+ if (on == CTRL0) {
+ reg = msk = phy_cfg->masks[MASK_AON_APB_USB_PHY_PD_L] |
+ phy_cfg->masks[MASK_AON_APB_USB_PHY_PD_S];
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_PWR_CTRL], msk, reg);
+
+ if (phy_cfg->owner == PIKE2) {
+ reg = readl_relaxed(phy->base + phy_cfg->regs[REG_AP_AHB_OTG_CTRL0]);
+ reg &= ~0x1;
+ writel_relaxed(reg, phy->base + phy_cfg->regs[REG_AP_AHB_OTG_CTRL0]);
+ }
+ } else if (on == CTRL1) {
+ if (phy_cfg->owner == PIKE2) {
+ reg = readl_relaxed(phy->base + phy_cfg->regs[REG_AP_AHB_OTG_CTRL0]);
+ reg |= 0x1;
+ writel_relaxed(reg, phy->base + phy_cfg->regs[REG_AP_AHB_OTG_CTRL0]);
+ }
+
+ msk = phy_cfg->masks[MASK_AON_APB_USB_PHY_PD_L] |
+ phy_cfg->masks[MASK_AON_APB_USB_PHY_PD_S];
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_PWR_CTRL], msk, 0);
+ } else if (on == CTRL2) {
+ reg = msk = phy_cfg->masks[MASK_AON_APB_USB_PHY_PD_L] |
+ phy_cfg->masks[MASK_AON_APB_USB_PHY_PD_S];
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_PWR_CTRL], msk, reg);
+ }
+}
+
+static void phy_v1_usb_vbus_ctrl(struct sprd_hsphy *phy, int on)
+{
+ u32 reg;
+
+ reg = readl_relaxed(phy->base + phy_cfg->regs[REG_AP_AHB_OTG_PHY_TEST]);
+ if (on) {
+ reg |= (phy_cfg->masks[MASK_AP_AHB_OTG_VBUS_VALID_EXT] |
+ phy_cfg->masks[MASK_AP_AHB_OTG_VBUS_VALID_PHYREG]);
+ } else {
+ reg &= ~(phy_cfg->masks[MASK_AP_AHB_OTG_VBUS_VALID_EXT] |
+ phy_cfg->masks[MASK_AP_AHB_OTG_VBUS_VALID_PHYREG]);
+ }
+ writel_relaxed(reg, phy->base + phy_cfg->regs[REG_AP_AHB_OTG_PHY_TEST]);
+}
+
+static void phy_v1_utmi_width_sel(struct sprd_hsphy *phy)
+{
+ u32 reg;
+
+ reg = readl_relaxed(phy->base + phy_cfg->regs[REG_AP_AHB_OTG_PHY_CTRL]);
+ reg &= ~(phy_cfg->masks[MASK_AP_AHB_UTMI_WIDTH_SEL] |
+ phy_cfg->masks[MASK_AP_AHB_USB2_DATABUS16_8]);
+ writel_relaxed(reg, phy->base + phy_cfg->regs[REG_AP_AHB_OTG_PHY_CTRL]);
+}
+
+static void phy_v1_reset_core(struct sprd_hsphy *phy)
+{
+ u32 reg;
+
+ reg = readl_relaxed(phy->base + phy_cfg->regs[REG_AP_AHB_AHB_RST]);
+ reg = phy_cfg->masks[MASK_AP_AHB_OTG_PHY_SOFT_RST] |
+ phy_cfg->masks[MASK_AP_AHB_OTG_UTMI_SOFT_RST] |
+ phy_cfg->masks[MASK_AP_AHB_OTG_SOFT_RST];
+ writel_relaxed(reg, phy->base + phy_cfg->regs[REG_AP_AHB_AHB_RST] + 0x1000);
+
+ usleep_range(20000, 30000);
+ writel_relaxed(reg, phy->base + phy_cfg->regs[REG_AP_AHB_AHB_RST] + 0x2000);
+}
+
+static int phy_v1_set_mode(struct sprd_hsphy *phy, int on)
+{
+ u32 reg;
+
+ if (on) {
+ reg = phy->host_otg_ctrl0;
+ writel_relaxed(reg, phy->base + phy_cfg->regs[REG_AP_AHB_OTG_CTRL0]);
+ reg = phy->host_otg_ctrl1;
+ writel_relaxed(reg, phy->base + phy_cfg->regs[REG_AP_AHB_OTG_CTRL1]);
+
+ reg = readl_relaxed(phy->base + phy_cfg->regs[REG_AP_AHB_OTG_PHY_CTRL]);
+ reg &= ~phy_cfg->masks[MASK_AP_AHB_USB2_PHY_IDDIG];
+ reg |= phy_cfg->masks[MASK_AP_AHB_OTG_DPPULLDOWN] |
+ phy_cfg->masks[MASK_AP_AHB_OTG_DMPULLDOWN];
+ writel_relaxed(reg, phy->base + phy_cfg->regs[REG_AP_AHB_OTG_PHY_CTRL]);
+
+ reg = readl_relaxed(phy->base + phy_cfg->regs[REG_AP_AHB_OTG_CTRL0]);
+ reg |= 0x200;
+ writel_relaxed(reg, phy->base + phy_cfg->regs[REG_AP_AHB_OTG_CTRL0]);
+ phy->is_host = true;
+ } else {
+ reg = phy->device_otg_ctrl0;
+ writel_relaxed(reg, phy->base + phy_cfg->regs[REG_AP_AHB_OTG_CTRL0]);
+ reg = phy->device_otg_ctrl1;
+ writel_relaxed(reg, phy->base + phy_cfg->regs[REG_AP_AHB_OTG_CTRL1]);
+
+ reg = readl_relaxed(phy->base + phy_cfg->regs[REG_AP_AHB_OTG_PHY_CTRL]);
+ reg |= phy_cfg->masks[MASK_AP_AHB_USB2_PHY_IDDIG];
+ reg &= ~(phy_cfg->masks[MASK_AP_AHB_OTG_DPPULLDOWN] |
+ phy_cfg->masks[MASK_AP_AHB_OTG_DMPULLDOWN]);
+ writel_relaxed(reg, phy->base + phy_cfg->regs[REG_AP_AHB_OTG_PHY_CTRL]);
+
+ reg = readl_relaxed(phy->base + phy_cfg->regs[REG_AP_AHB_OTG_CTRL0]);
+ reg &= ~0x200;
+ writel_relaxed(reg, phy->base + phy_cfg->regs[REG_AP_AHB_OTG_CTRL0]);
+ phy->is_host = false;
+ }
+ return 0;
+}
+
+static const struct sprd_hsphy_cfg_ops phy_v1_cfg_ops = {
+ .usb_enable_ctrl = phy_v1_usb_enable_ctrl,
+ .usb_phy_power_ctrl = phy_v1_usb_phy_power_ctrl,
+ .usb_vbus_ctrl = phy_v1_usb_vbus_ctrl,
+ .utmi_width_sel = phy_v1_utmi_width_sel,
+ .reset_core = phy_v1_reset_core,
+ .set_mode = phy_v1_set_mode,
+};
+
+/* phy_v2 cfg ops */
+static void phy_v2_usb_enable_ctrl(struct sprd_hsphy *phy, int on)
+{
+ u32 reg, msk;
+
+ if (on == CTRL0) {
+ msk = phy_cfg->masks[MASK_AON_APB_OTG_REF_EB];
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_APB_EB2], msk, 0);
+ } else if (on == CTRL1) {
+ reg = msk = phy_cfg->masks[MASK_AON_APB_OTG_REF_EB];
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_APB_EB2], msk, reg);
+ } else if (on == CTRL2) {
+ reg = msk = phy_cfg->masks[MASK_AP_AHB_OTG_EB];
+ regmap_update_bits(phy->ap_ahb, phy_cfg->regs[REG_AP_AHB_AHB_EB], msk, reg);
+ reg = msk = phy_cfg->masks[MASK_AON_APB_ANLG_APB_EB] |
+ phy_cfg->masks[MASK_AON_APB_ANLG_EB] |
+ phy_cfg->masks[MASK_AON_APB_OTG_REF_EB];
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_APB_EB2], msk, reg);
+ }
+}
+
+static void phy_v2_usb_phy_power_ctrl(struct sprd_hsphy *phy, int on)
+{
+ u32 reg, msk;
+
+ if (on == CTRL0) {
+ reg = msk = phy_cfg->masks[MASK_AON_APB_USB_ISO_SW_EN];
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_PWR_CTRL], msk, reg);
+ usleep_range(10000, 15000);
+ reg = msk = phy_cfg->masks[MASK_AON_APB_USB_PHY_PD_L] |
+ phy_cfg->masks[MASK_AON_APB_USB_PHY_PD_S];
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_PWR_CTRL], msk, reg);
+ } else if (on == CTRL1) {
+ msk = phy_cfg->masks[MASK_AON_APB_USB_PHY_PD_L] |
+ phy_cfg->masks[MASK_AON_APB_USB_PHY_PD_S] |
+ phy_cfg->masks[MASK_AON_APB_USB_ISO_SW_EN];
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_PWR_CTRL], msk, 0);
+ } else if (on == CTRL2) {
+ reg = msk = phy_cfg->masks[MASK_AON_APB_USB_PHY_PD_L] |
+ phy_cfg->masks[MASK_AON_APB_USB_PHY_PD_S];
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_PWR_CTRL], msk, reg);
+ }
+}
+
+static void phy_v2_usb_vbus_ctrl(struct sprd_hsphy *phy, int on)
+{
+ u32 reg, msk;
+
+ if (on) {
+ reg = readl_relaxed(phy->base + phy_cfg->regs[REG_AP_AHB_OTG_PHY_TEST]);
+ reg |= phy_cfg->masks[MASK_AP_AHB_OTG_VBUS_VALID_PHYREG];
+ writel_relaxed(reg, phy->base + phy_cfg->regs[REG_AP_AHB_OTG_PHY_TEST]);
+
+ reg = msk = phy_cfg->masks[MASK_ANALOG_USB20_USB20_VBUSVLDEXT];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_USB20_UTMI_CTL1], msk, reg);
+ } else {
+ reg = readl_relaxed(phy->base + phy_cfg->regs[REG_AP_AHB_OTG_PHY_TEST]);
+ reg &= ~phy_cfg->masks[MASK_AP_AHB_OTG_VBUS_VALID_PHYREG];
+ writel_relaxed(reg, phy->base + phy_cfg->regs[REG_AP_AHB_OTG_PHY_TEST]);
+
+ msk = phy_cfg->masks[MASK_ANALOG_USB20_USB20_VBUSVLDEXT];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_USB20_UTMI_CTL1], msk, 0);
+ }
+}
+
+static void phy_v2_utmi_width_sel(struct sprd_hsphy *phy)
+{
+ u32 reg, msk;
+
+ reg = msk = phy_cfg->masks[MASK_ANALOG_USB20_USB20_DATABUS16_8];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_USB20_UTMI_CTL1], msk, reg);
+
+ reg = readl_relaxed(phy->base + phy_cfg->regs[REG_AP_AHB_OTG_PHY_CTRL]);
+ reg |= phy_cfg->masks[MASK_AP_AHB_UTMI_WIDTH_SEL];
+ writel_relaxed(reg, phy->base + phy_cfg->regs[REG_AP_AHB_OTG_PHY_CTRL]);
+}
+
+static void phy_v2_reset_core(struct sprd_hsphy *phy)
+{
+ u32 msk1, msk2;
+
+ msk1 = phy_cfg->masks[MASK_AP_AHB_OTG_UTMI_SOFT_RST] |
+ phy_cfg->masks[MASK_AP_AHB_OTG_SOFT_RST];
+ regmap_update_bits(phy->ap_ahb, phy_cfg->regs[REG_AP_AHB_AHB_RST], msk1, msk1);
+ msk2 = phy_cfg->masks[MASK_AON_APB_OTG_PHY_SOFT_RST];
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_APB_RST2], msk2, msk2);
+
+ usleep_range(20000, 30000);
+ regmap_update_bits(phy->ap_ahb, phy_cfg->regs[REG_AP_AHB_AHB_RST], msk1, 0);
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_APB_RST2], msk2, 0);
+}
+
+static int phy_v2_set_mode(struct sprd_hsphy *phy, int on)
+{
+ u32 reg, msk;
+
+ if (on) {
+ reg = phy->host_eye_pattern;
+ regmap_write(phy->analog, phy_cfg->regs[REG_ANALOG_USB20_USB20_TRIMMING], reg);
+
+ msk = phy_cfg->masks[MASK_ANALOG_USB20_UTMIOTG_IDDG];
+ regmap_update_bits(phy->analog, phy_cfg->regs[REG_ANALOG_USB20_IDDG], msk, 0);
+
+ reg = msk = phy_cfg->masks[MASK_DBG_SEL_ANALOG_USB20_USB20_DMPULLDOWN] |
+ phy_cfg->masks[MASK_DBG_SEL_ANALOG_USB20_USB20_DPPULLDOWN];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_REG_SEL_CFG_0], msk, reg);
+ reg = msk = phy_cfg->masks[MASK_ANALOG_USB20_USB20_DMPULLDOWN] |
+ phy_cfg->masks[MASK_ANALOG_USB20_USB20_DPPULLDOWN];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_USB20_UTMI_CTL2], msk, reg);
+
+ msk = 0x200;
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_USB20_UTMI_CTL1], msk, msk);
+ phy->is_host = true;
+ } else {
+ reg = phy->device_eye_pattern;
+ regmap_write(phy->analog, phy_cfg->regs[REG_ANALOG_USB20_USB20_TRIMMING], reg);
+
+ reg = msk = phy_cfg->masks[MASK_ANALOG_USB20_UTMIOTG_IDDG];
+ regmap_update_bits(phy->analog, phy_cfg->regs[REG_ANALOG_USB20_IDDG], msk, reg);
+
+ reg = msk = phy_cfg->masks[MASK_DBG_SEL_ANALOG_USB20_USB20_DMPULLDOWN] |
+ phy_cfg->masks[MASK_DBG_SEL_ANALOG_USB20_USB20_DPPULLDOWN];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_REG_SEL_CFG_0], msk, reg);
+ msk = phy_cfg->masks[MASK_ANALOG_USB20_USB20_DMPULLDOWN] |
+ phy_cfg->masks[MASK_ANALOG_USB20_USB20_DPPULLDOWN];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_USB20_UTMI_CTL2], msk, 0);
+
+ msk = 0x200;
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_USB20_UTMI_CTL1], msk, 0);
+ phy->is_host = false;
+ }
+ return 0;
+}
+
+static const struct sprd_hsphy_cfg_ops phy_v2_cfg_ops = {
+ .usb_enable_ctrl = phy_v2_usb_enable_ctrl,
+ .usb_phy_power_ctrl = phy_v2_usb_phy_power_ctrl,
+ .usb_vbus_ctrl = phy_v2_usb_vbus_ctrl,
+ .utmi_width_sel = phy_v2_utmi_width_sel,
+ .reset_core = phy_v2_reset_core,
+ .set_mode = phy_v2_set_mode,
+};
+
+/* phy_v3 cfg ops */
+static void phy_v3_usb_enable_ctrl(struct sprd_hsphy *phy, int on)
+{
+ u32 reg, msk;
+
+ if (on == CTRL0) {
+ msk = phy_cfg->masks[MASK_AON_APB_CGM_OTG_REF_EN] |
+ phy_cfg->masks[MASK_AON_APB_CGM_DPHY_REF_EN];
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_CGM_REG1], msk, 0);
+ } else if (on == CTRL1) {
+ reg = msk = phy_cfg->masks[MASK_AON_APB_OTG_UTMI_EB];
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_APB_EB1], msk, reg);
+ reg = msk = phy_cfg->masks[MASK_AON_APB_CGM_OTG_REF_EN] |
+ phy_cfg->masks[MASK_AON_APB_CGM_DPHY_REF_EN];
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_CGM_REG1], msk, reg);
+ } else if (on == CTRL2) {
+ reg = msk = phy_cfg->masks[MASK_AON_APB_OTG_UTMI_EB] |
+ phy_cfg->masks[MASK_AON_APB_ANA_EB];
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_APB_EB1], msk, reg);
+ reg = msk = phy_cfg->masks[MASK_AON_APB_CGM_OTG_REF_EN] |
+ phy_cfg->masks[MASK_AON_APB_CGM_DPHY_REF_EN];
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_CGM_REG1], msk, reg);
+ }
+}
+
+static void phy_v3_usb_phy_power_ctrl(struct sprd_hsphy *phy, int on)
+{
+ u32 reg, msk;
+
+ if (on == CTRL0) {
+ reg = msk = phy_cfg->masks[MASK_ANALOG_USB20_USB20_PS_PD_L] |
+ phy_cfg->masks[MASK_ANALOG_USB20_USB20_PS_PD_S];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_USB20_BATTER_PLL], msk, reg);
+ reg = msk = phy_cfg->masks[MASK_ANALOG_USB20_USB20_ISO_SW_EN];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_USB20_ISO_SW], msk, reg);
+ } else if (on == CTRL1) {
+ msk = phy_cfg->masks[MASK_ANALOG_USB20_USB20_ISO_SW_EN];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_USB20_ISO_SW], msk, 0);
+ msk = phy_cfg->masks[MASK_ANALOG_USB20_USB20_PS_PD_L] |
+ phy_cfg->masks[MASK_ANALOG_USB20_USB20_PS_PD_S];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_USB20_BATTER_PLL], msk, 0);
+ } else if (on == CTRL2) {
+ reg = msk = phy_cfg->masks[MASK_ANALOG_USB20_USB20_PS_PD_L] |
+ phy_cfg->masks[MASK_ANALOG_USB20_USB20_PS_PD_S];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_USB20_BATTER_PLL], msk, reg);
+ }
+}
+
+static void phy_v3_usb_vbus_ctrl(struct sprd_hsphy *phy, int on)
+{
+ u32 reg, msk;
+
+ msk = phy_cfg->masks[MASK_AON_APB_OTG_VBUS_VALID_PHYREG];
+ reg = on ? msk : 0;
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_OTG_PHY_TEST], msk, reg);
+
+ msk = phy_cfg->masks[MASK_ANALOG_USB20_USB20_VBUSVLDEXT];
+ reg = on ? msk : 0;
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_USB20_UTMI_CTL1], msk, reg);
+}
+
+static void phy_v3_utmi_width_sel(struct sprd_hsphy *phy)
+{
+ u32 reg, msk;
+
+ reg = msk = phy_cfg->masks[MASK_AON_APB_UTMI_WIDTH_SEL];
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_OTG_PHY_CTRL], msk, reg);
+
+ reg = msk = phy_cfg->masks[MASK_ANALOG_USB20_USB20_DATABUS16_8];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_USB20_UTMI_CTL1], msk, reg);
+}
+
+static void phy_v3_reset_core(struct sprd_hsphy *phy)
+{
+ u32 reg, msk;
+
+ reg = msk = phy_cfg->masks[MASK_AON_APB_OTG_PHY_SOFT_RST] |
+ phy_cfg->masks[MASK_AON_APB_OTG_UTMI_SOFT_RST];
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_APB_RST1], msk, reg);
+
+ usleep_range(20000, 30000);
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_APB_RST1], msk, 0);
+}
+
+static int phy_v3_set_mode(struct sprd_hsphy *phy, int on)
+{
+ u32 reg, msk;
+
+ if (on) {
+ reg = phy->host_eye_pattern;
+ regmap_write(phy->analog, phy_cfg->regs[REG_ANALOG_USB20_USB20_TRIMMING], reg);
+
+ msk = phy_cfg->masks[MASK_AON_APB_USB2_PHY_IDDIG];
+ regmap_update_bits(phy->aon_apb,
+ phy_cfg->regs[REG_AON_APB_OTG_PHY_CTRL], msk, 0);
+
+ reg = msk = phy_cfg->masks[MASK_DBG_SEL_ANALOG_USB20_USB20_DMPULLDOWN] |
+ phy_cfg->masks[MASK_DBG_SEL_ANALOG_USB20_USB20_DPPULLDOWN];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_REG_SEL_CFG_0], msk, reg);
+ reg = msk = phy_cfg->masks[MASK_ANALOG_USB20_USB20_DMPULLDOWN] |
+ phy_cfg->masks[MASK_ANALOG_USB20_USB20_DPPULLDOWN];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_USB20_UTMI_CTL2], msk, reg);
+
+ reg = 0x200;
+ msk = phy_cfg->masks[MASK_ANALOG_USB20_USB20_RESERVED];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_USB20_UTMI_CTL1], msk, reg);
+ phy->is_host = true;
+ } else {
+ reg = phy->device_eye_pattern;
+ regmap_write(phy->analog, phy_cfg->regs[REG_ANALOG_USB20_USB20_TRIMMING], reg);
+
+ reg = msk = phy_cfg->masks[MASK_AON_APB_USB2_PHY_IDDIG];
+ regmap_update_bits(phy->aon_apb,
+ phy_cfg->regs[REG_AON_APB_OTG_PHY_CTRL], msk, reg);
+
+ reg = msk = phy_cfg->masks[MASK_DBG_SEL_ANALOG_USB20_USB20_DMPULLDOWN] |
+ phy_cfg->masks[MASK_DBG_SEL_ANALOG_USB20_USB20_DPPULLDOWN];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_REG_SEL_CFG_0], msk, reg);
+ msk = phy_cfg->masks[MASK_ANALOG_USB20_USB20_DMPULLDOWN] |
+ phy_cfg->masks[MASK_ANALOG_USB20_USB20_DPPULLDOWN];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_USB20_UTMI_CTL2], msk, 0);
+
+ msk = phy_cfg->masks[MASK_ANALOG_USB20_USB20_RESERVED];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_USB20_UTMI_CTL1], msk, 0);
+ phy->is_host = false;
+ }
+ return 0;
+}
+
+static const struct sprd_hsphy_cfg_ops phy_v3_cfg_ops = {
+ .usb_enable_ctrl = phy_v3_usb_enable_ctrl,
+ .usb_phy_power_ctrl = phy_v3_usb_phy_power_ctrl,
+ .usb_vbus_ctrl = phy_v3_usb_vbus_ctrl,
+ .utmi_width_sel = phy_v3_utmi_width_sel,
+ .reset_core = phy_v3_reset_core,
+ .set_mode = phy_v3_set_mode,
+};
+
+/* phy_v4 cfg ops */
+static void phy_v4_usb_enable_ctrl(struct sprd_hsphy *phy, int on)
+{
+ u32 reg, msk;
+
+ if (on == CTRL0) {
+ if (phy_cfg->owner == UIS8520)
+ msk = phy_cfg->masks[MASK_AON_APB_CGM_OTG_REF_EN];
+ else
+ msk = phy_cfg->masks[MASK_AON_APB_CGM_OTG_REF_EN] |
+ phy_cfg->masks[MASK_AON_APB_CGM_DPHY_REF_EN];
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_CGM_REG1], msk, 0);
+ msk = phy_cfg->masks[MASK_AON_APB_AON_USB2_TOP_EB] |
+ phy_cfg->masks[MASK_AON_APB_OTG_PHY_EB];
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_APB_EB1], msk, 0);
+ } else if (on == CTRL1) {
+ reg = msk = phy_cfg->masks[MASK_AON_APB_AON_USB2_TOP_EB] |
+ phy_cfg->masks[MASK_AON_APB_OTG_PHY_EB];
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_APB_EB1], msk, reg);
+ if (phy_cfg->owner == UIS8520)
+ reg = msk = phy_cfg->masks[MASK_AON_APB_CGM_OTG_REF_EN];
+ else
+ reg = msk = phy_cfg->masks[MASK_AON_APB_CGM_OTG_REF_EN] |
+ phy_cfg->masks[MASK_AON_APB_CGM_DPHY_REF_EN];
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_CGM_REG1], msk, reg);
+ }
+}
+
+static void phy_v4_usb_phy_power_ctrl(struct sprd_hsphy *phy, int on)
+{
+ u32 reg, msk;
+
+ if (on == CTRL0) {
+ reg = msk = phy_cfg->masks[MASK_AON_APB_USB20_ISO_SW_EN];
+ regmap_update_bits(phy->aon_apb,
+ phy_cfg->regs[REG_AON_APB_AON_SOC_USB_CTRL], msk, reg);
+ reg = msk = phy_cfg->masks[MASK_ANALOG_USB20_USB20_ISO_SW_EN];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_USB20_PHY], msk, reg);
+
+ reg = msk = phy_cfg->masks[MASK_AON_APB_C2G_ANALOG_USB20_USB20_PS_PD_L] |
+ phy_cfg->masks[MASK_AON_APB_C2G_ANALOG_USB20_USB20_PS_PD_S];
+ regmap_update_bits(phy->aon_apb,
+ phy_cfg->regs[REG_AON_APB_MIPI_CSI_POWER_CTRL], msk, reg);
+ } else if (on == CTRL1) {
+ msk = phy_cfg->masks[MASK_AON_APB_C2G_ANALOG_USB20_USB20_PS_PD_L] |
+ phy_cfg->masks[MASK_AON_APB_C2G_ANALOG_USB20_USB20_PS_PD_S];
+ regmap_update_bits(phy->aon_apb,
+ phy_cfg->regs[REG_AON_APB_MIPI_CSI_POWER_CTRL], msk, 0);
+
+ msk = phy_cfg->masks[MASK_ANALOG_USB20_USB20_ISO_SW_EN];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_USB20_PHY], msk, 0);
+ msk = phy_cfg->masks[MASK_AON_APB_USB20_ISO_SW_EN];
+ regmap_update_bits(phy->aon_apb,
+ phy_cfg->regs[REG_AON_APB_AON_SOC_USB_CTRL], msk, 0);
+ }
+}
+
+static void phy_v4_usb_vbus_ctrl(struct sprd_hsphy *phy, int on)
+{
+ u32 reg, msk;
+
+ msk = phy_cfg->masks[MASK_AON_APB_OTG_VBUS_VALID_PHYREG];
+ reg = on ? msk : 0;
+ regmap_update_bits(phy->aon_apb,
+ phy_cfg->regs[REG_AON_APB_OTG_PHY_TEST], msk, reg);
+
+ msk = phy_cfg->masks[MASK_ANALOG_USB20_USB20_VBUSVLDEXT];
+ reg = on ? msk : 0;
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_USB20_UTMI_CTL1], msk, reg);
+}
+
+static void phy_v4_utmi_width_sel(struct sprd_hsphy *phy)
+{
+ u32 reg, msk;
+
+ if (phy_cfg->owner == UIS8520)
+ return;
+
+ reg = msk = phy_cfg->masks[MASK_AON_APB_UTMI_WIDTH_SEL];
+ regmap_update_bits(phy->aon_apb,
+ phy_cfg->regs[REG_AON_APB_OTG_PHY_CTRL], msk, reg);
+
+ reg = msk = phy_cfg->masks[MASK_ANALOG_USB20_USB20_DATABUS16_8];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_USB20_UTMI_CTL1], msk, reg);
+}
+
+static void phy_v4_reset_core(struct sprd_hsphy *phy)
+{
+ u32 reg, msk;
+
+ reg = msk = phy_cfg->masks[MASK_AON_APB_OTG_PHY_SOFT_RST] |
+ phy_cfg->masks[MASK_AON_APB_OTG_UTMI_SOFT_RST];
+
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_APB_RST1], msk, reg);
+
+ usleep_range(20000, 30000);
+ regmap_update_bits(phy->aon_apb, phy_cfg->regs[REG_AON_APB_APB_RST1], msk, 0);
+}
+
+static int phy_v4_set_mode(struct sprd_hsphy *phy, int on)
+{
+ u32 reg, msk;
+
+ if (on) {
+ reg = phy->host_eye_pattern;
+ regmap_write(phy->analog, phy_cfg->regs[REG_ANALOG_USB20_USB20_TRIMMING], reg);
+
+ msk = phy_cfg->masks[MASK_AON_APB_USB2_PHY_IDDIG];
+ regmap_update_bits(phy->aon_apb,
+ phy_cfg->regs[REG_AON_APB_OTG_PHY_CTRL], msk, 0);
+
+ reg = msk = phy_cfg->masks[MASK_DBG_SEL_ANALOG_USB20_USB20_DMPULLDOWN] |
+ phy_cfg->masks[MASK_DBG_SEL_ANALOG_USB20_USB20_DPPULLDOWN];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_REG_SEL_CFG_0], msk, reg);
+ reg = msk = phy_cfg->masks[MASK_ANALOG_USB20_USB20_DMPULLDOWN] |
+ phy_cfg->masks[MASK_ANALOG_USB20_USB20_DPPULLDOWN];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_USB20_UTMI_CTL2], msk, reg);
+
+ reg = 0x200;
+ msk = phy_cfg->masks[MASK_ANALOG_USB20_USB20_RESERVED];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_USB20_UTMI_CTL1], msk, reg);
+ phy->is_host = true;
+ } else {
+ reg = phy->device_eye_pattern;
+ regmap_write(phy->analog, phy_cfg->regs[REG_ANALOG_USB20_USB20_TRIMMING], reg);
+
+ reg = msk = phy_cfg->masks[MASK_AON_APB_USB2_PHY_IDDIG];
+ regmap_update_bits(phy->aon_apb,
+ phy_cfg->regs[REG_AON_APB_OTG_PHY_CTRL], msk, reg);
+
+ reg = msk = phy_cfg->masks[MASK_DBG_SEL_ANALOG_USB20_USB20_DMPULLDOWN] |
+ phy_cfg->masks[MASK_DBG_SEL_ANALOG_USB20_USB20_DPPULLDOWN];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_REG_SEL_CFG_0], msk, reg);
+ msk = phy_cfg->masks[MASK_ANALOG_USB20_USB20_DMPULLDOWN] |
+ phy_cfg->masks[MASK_ANALOG_USB20_USB20_DPPULLDOWN];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_USB20_UTMI_CTL2], msk, 0);
+
+ msk = phy_cfg->masks[MASK_ANALOG_USB20_USB20_RESERVED];
+ regmap_update_bits(phy->analog,
+ phy_cfg->regs[REG_ANALOG_USB20_USB20_UTMI_CTL1], msk, 0);
+ phy->is_host = false;
+ }
+ return 0;
+}
+
+static const struct sprd_hsphy_cfg_ops phy_v4_cfg_ops = {
+ .usb_enable_ctrl = phy_v4_usb_enable_ctrl,
+ .usb_phy_power_ctrl = phy_v4_usb_phy_power_ctrl,
+ .usb_vbus_ctrl = phy_v4_usb_vbus_ctrl,
+ .utmi_width_sel = phy_v4_utmi_width_sel,
+ .reset_core = phy_v4_reset_core,
+ .set_mode = phy_v4_set_mode,
+};
+
+static const struct sprd_hsphy_cfg pike2_phy_cfg = {
+ .regs = pike2_regs_layout,
+ .masks = pike2_masks_layout,
+ .cfg_ops = &phy_v1_cfg_ops,
+ .parameters = phy_pike2_parameters,
+ .phy_version = VERSION1,
+ .owner = PIKE2,
+};
+
+static const struct sprd_hsphy_cfg sharkle_phy_cfg = {
+ .regs = sharkle_regs_layout,
+ .masks = sharkle_masks_layout,
+ .cfg_ops = &phy_v1_cfg_ops,
+ .parameters = phy_sharkle_parameters,
+ .phy_version = VERSION1,
+ .owner = SHARKLE,
+};
+
+static const struct sprd_hsphy_cfg sharkl3_phy_cfg = {
+ .regs = sharkl3_regs_layout,
+ .masks = sharkl3_masks_layout,
+ .cfg_ops = &phy_v2_cfg_ops,
+ .parameters = phy_sharkl3_parameters,
+ .phy_version = VERSION2,
+ .owner = SHARKL3,
+};
+
+static const struct sprd_hsphy_cfg sharkl5_phy_cfg = {
+ .regs = sharkl5_regs_layout,
+ .masks = sharkl5_masks_layout,
+ .cfg_ops = &phy_v3_cfg_ops,
+ .parameters = phy_sharkl5_parameters,
+ .phy_version = VERSION3,
+ .owner = SHARKL5,
+};
+
+static const struct sprd_hsphy_cfg sharkl5pro_phy_cfg = {
+ .regs = sharkl5pro_regs_layout,
+ .masks = sharkl5pro_masks_layout,
+ .cfg_ops = &phy_v3_cfg_ops,
+ .parameters = phy_sharkl5pro_parameters,
+ .phy_version = VERSION3,
+ .owner = SHARKL5PRO,
+};
+
+static const struct sprd_hsphy_cfg qogirl6_phy_cfg = {
+ .regs = qogirl6_regs_layout,
+ .masks = qogirl6_masks_layout,
+ .cfg_ops = &phy_v3_cfg_ops,
+ .parameters = phy_qogirl6_parameters,
+ .phy_version = VERSION3,
+ .owner = QOGIRL6,
+};
+
+static const struct sprd_hsphy_cfg qogirn6lite_phy_cfg = {
+ .regs = qogirn6lite_regs_layout,
+ .masks = qogirn6lite_masks_layout,
+ .cfg_ops = &phy_v4_cfg_ops,
+ .parameters = phy_qogirn6lite_parameters,
+ .phy_version = VERSION4,
+ .owner = QOGIRN6LITE,
+};
+
+static const struct sprd_hsphy_cfg uis8520_phy_cfg = {
+ .regs = uis8520_regs_layout,
+ .masks = uis8520_masks_layout,
+ .cfg_ops = &phy_v4_cfg_ops,
+ .parameters = phy_uis8520_parameters,
+ .phy_version = VERSION4,
+ .owner = UIS8520,
+};
+
+static void sprd_hsphy_charger_detect_work(struct work_struct *work)
+{
+ struct sprd_hsphy *phy = container_of(work, struct sprd_hsphy, work);
+ struct usb_phy *usb_phy = &phy->phy;
+
+ __pm_stay_awake(phy->wake_lock);
+ if (phy->event)
+ usb_phy_set_charger_state(usb_phy, USB_CHARGER_PRESENT);
+ else
+ usb_phy_set_charger_state(usb_phy, USB_CHARGER_ABSENT);
+ __pm_relax(phy->wake_lock);
+}
+
+static int sprd_hsphy_vbus_notify(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct usb_phy *usb_phy = container_of(nb, struct usb_phy, vbus_nb);
+ struct sprd_hsphy *phy = container_of(usb_phy, struct sprd_hsphy, phy);
+ const struct sprd_hsphy_cfg_ops *cfg_ops = phy_cfg->cfg_ops;
+
+ if (phy->is_host || usb_phy->last_event == USB_EVENT_ID) {
+ dev_info(phy->dev, "USB PHY is host mode\n");
+ return 0;
+ }
+ dev_info(usb_phy->dev, "[%s] enters!\n", __func__);
+
+ pm_wakeup_event(phy->dev, 400);
+
+ if (event)
+ /* usb vbus valid */
+ cfg_ops->usb_vbus_ctrl(phy, CTRL1);
+ else
+ cfg_ops->usb_vbus_ctrl(phy, CTRL0);
+
+ phy->event = event;
+ queue_work(system_unbound_wq, &phy->work);
+
+ return 0;
+}
+
+static int sprd_hostphy_set(struct usb_phy *x, int on)
+{
+ struct sprd_hsphy *phy = container_of(x, struct sprd_hsphy, phy);
+ const struct sprd_hsphy_cfg_ops *cfg_ops = phy_cfg->cfg_ops;
+
+ dev_info(x->dev, "[%s] enters!\n", __func__);
+ return cfg_ops->set_mode(phy, on);
+}
+
+static int sprd_hsphy_init(struct usb_phy *x)
+{
+ struct sprd_hsphy *phy = container_of(x, struct sprd_hsphy, phy);
+ const struct sprd_hsphy_cfg_ops *cfg_ops = phy_cfg->cfg_ops;
+ u32 reg = 0;
+ int ret = 0;
+
+ if (atomic_read(&phy->inited)) {
+ dev_dbg(x->dev, "%s is already inited!\n", __func__);
+ return 0;
+ }
+ dev_info(x->dev, "[%s] enters!\n", __func__);
+
+ /* Turn On VDD */
+ regulator_set_voltage(phy->vdd, phy->vdd_vol, phy->vdd_vol);
+ ret = regulator_enable(phy->vdd);
+ if (ret)
+ return ret;
+
+ /* usb enable */
+ cfg_ops->usb_enable_ctrl(phy, CTRL1);
+
+ /* usb phy power on */
+ cfg_ops->usb_phy_power_ctrl(phy, CTRL1);
+
+ /* Restore PHY tunes */
+ if (phy_cfg->phy_version == VERSION1) {
+ writel_relaxed(phy->phy_tune, phy->base + phy_cfg->regs[REG_AP_AHB_OTG_PHY_TUNE]);
+ /* USB PHY write register need to delay 2ms~3ms */
+ usleep_range(2000, 3000);
+ }
+
+ /* usb vbus valid */
+ cfg_ops->usb_vbus_ctrl(phy, CTRL1);
+
+ /* for SPRD phy utmi_width sel */
+ cfg_ops->utmi_width_sel(phy);
+
+ /* for SPRD phy sampler sel */
+ if (phy_cfg->phy_version == VERSION1) {
+ reg = readl_relaxed(phy->base + phy_cfg->regs[REG_AP_AHB_OTG_CTRL1]);
+ reg |= phy_cfg->masks[MASK_AP_AHB_USB20_SAMPLER_SEL];
+ writel_relaxed(reg, phy->base + phy_cfg->regs[REG_AP_AHB_OTG_CTRL1]);
+ }
+
+ if (!atomic_read(&phy->reset)) {
+ /* USB PHY write register need to delay 2ms~3ms */
+ if (phy_cfg->phy_version == VERSION1)
+ usleep_range(2000, 3000);
+
+ cfg_ops->reset_core(phy);
+ atomic_set(&phy->reset, 1);
+ }
+
+ atomic_set(&phy->inited, 1);
+ return 0;
+}
+
+static void sprd_hsphy_shutdown(struct usb_phy *x)
+{
+ struct sprd_hsphy *phy = container_of(x, struct sprd_hsphy, phy);
+ const struct sprd_hsphy_cfg_ops *cfg_ops = phy_cfg->cfg_ops;
+
+ if (!atomic_read(&phy->inited)) {
+ dev_info(x->dev, "%s is already shut down\n", __func__);
+ return;
+ }
+ dev_info(x->dev, "[%s] enters!\n", __func__);
+
+ /* usb vbus invalid*/
+ cfg_ops->usb_vbus_ctrl(phy, CTRL0);
+
+ /* usb power down */
+ cfg_ops->usb_phy_power_ctrl(phy, CTRL0);
+
+ /* Backup PHY Tune value */
+ if (phy_cfg->phy_version == VERSION1)
+ phy->phy_tune = readl(phy->base + phy_cfg->regs[REG_AP_AHB_OTG_PHY_TUNE]);
+
+ cfg_ops->usb_enable_ctrl(phy, CTRL0);
+
+ regulator_disable(phy->vdd);
+
+ atomic_set(&phy->inited, 0);
+ atomic_set(&phy->reset, 0);
+}
+
+static ssize_t phy_tune_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sprd_hsphy *phy = dev_get_drvdata(dev);
+
+ if (!phy)
+ return -EINVAL;
+
+ return snprintf(buf, PAGE_SIZE, "0x%x\n", phy->phy_tune);
+}
+
+static ssize_t phy_tune_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct sprd_hsphy *phy = dev_get_drvdata(dev);
+
+ if (!phy)
+ return -EINVAL;
+
+ if (kstrtouint(buf, 16, &phy->phy_tune) < 0)
+ return -EINVAL;
+
+ return size;
+}
+static DEVICE_ATTR_RW(phy_tune);
+
+static ssize_t vdd_voltage_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct sprd_hsphy *phy = dev_get_drvdata(dev);
+
+ if (!phy)
+ return -EINVAL;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", phy->vdd_vol);
+}
+
+static ssize_t vdd_voltage_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct sprd_hsphy *phy = dev_get_drvdata(dev);
+ u32 vol;
+
+ if (!phy)
+ return -EINVAL;
+
+ if (kstrtouint(buf, 10, &vol) < 0)
+ return -EINVAL;
+
+ if (vol < 1200000 || vol > 3750000) {
+ dev_err(dev, "Invalid voltage value %d\n", vol);
+ return -EINVAL;
+ }
+ phy->vdd_vol = vol;
+
+ return size;
+}
+static DEVICE_ATTR_RW(vdd_voltage);
+
+static ssize_t hsphy_device_eye_pattern_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct sprd_hsphy *phy = dev_get_drvdata(dev);
+
+ if (!phy)
+ return -EINVAL;
+
+ return snprintf(buf, PAGE_SIZE, "0x%x\n", phy->device_eye_pattern);
+}
+
+static ssize_t hsphy_device_eye_pattern_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct sprd_hsphy *phy = dev_get_drvdata(dev);
+
+ if (!phy)
+ return -EINVAL;
+
+ if (kstrtouint(buf, 16, &phy->device_eye_pattern) < 0)
+ return -EINVAL;
+
+ return size;
+}
+static DEVICE_ATTR_RW(hsphy_device_eye_pattern);
+
+static ssize_t hsphy_host_eye_pattern_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct sprd_hsphy *phy = dev_get_drvdata(dev);
+
+ if (!phy)
+ return -EINVAL;
+
+ return snprintf(buf, PAGE_SIZE, "0x%x\n", phy->host_eye_pattern);
+}
+
+static ssize_t hsphy_host_eye_pattern_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct sprd_hsphy *phy = dev_get_drvdata(dev);
+
+ if (!phy)
+ return -EINVAL;
+
+ if (kstrtouint(buf, 16, &phy->host_eye_pattern) < 0)
+ return -EINVAL;
+
+ return size;
+}
+
+static DEVICE_ATTR_RW(hsphy_host_eye_pattern);
+
+static struct attribute *usb_hsphy_attrs[] = {
+ &dev_attr_phy_tune.attr,
+ &dev_attr_vdd_voltage.attr,
+ &dev_attr_hsphy_device_eye_pattern.attr,
+ &dev_attr_hsphy_host_eye_pattern.attr,
+ NULL
+};
+ATTRIBUTE_GROUPS(usb_hsphy);
+
+static int sprd_eyepatt_tunehsamp_set(struct sprd_hsphy *phy, struct device *dev)
+{
+ int ret = 0;
+ u8 val[2];
+
+ ret = of_property_read_u8_array(dev->of_node, "sprd,hsphy-tunehsamp", val, 2);
+
+ if (ret < 0) {
+ dev_err(dev, "unable to get hsphy-device-tunehsamp\n");
+ return ret;
+ }
+
+ if (phy_cfg->phy_version == VERSION1) {
+ /* device setting */
+ phy->device_otg_ctrl0 &= ~phy_cfg->masks[MASK_AP_AHB_USB20_TUNEHSAMP];
+ phy->device_otg_ctrl0 |= (u32)val[0] << phy_cfg->parameters[TUNEHSAMP_SHIFT];
+
+ /* host setting */
+ phy->host_otg_ctrl0 &= ~phy_cfg->masks[MASK_AP_AHB_USB20_TUNEHSAMP];
+ phy->host_otg_ctrl0 |= (u32)val[1] << phy_cfg->parameters[TUNEHSAMP_SHIFT];
+
+ } else if (phy_cfg->phy_version == VERSION2 ||
+ phy_cfg->phy_version == VERSION3 ||
+ phy_cfg->phy_version == VERSION4) {
+ /* device setting */
+ phy->device_eye_pattern &= ~phy_cfg->masks[MASK_ANALOG_USB20_USB20_TUNEHSAMP];
+ phy->device_eye_pattern |= (u32)val[0] << phy_cfg->parameters[TUNEHSAMP_SHIFT];
+
+ /* host setting */
+ phy->host_eye_pattern &= ~phy_cfg->masks[MASK_ANALOG_USB20_USB20_TUNEHSAMP];
+ phy->host_eye_pattern |= (u32)val[1] << phy_cfg->parameters[TUNEHSAMP_SHIFT];
+ }
+
+ return 0;
+}
+
+static int sprd_eyepatt_tuneeq_set(struct sprd_hsphy *phy, struct device *dev)
+{
+ int ret = 0;
+ u8 val[2];
+
+ ret = of_property_read_u8_array(dev->of_node, "sprd,hsphy-tuneeq", val, 2);
+
+ if (ret < 0) {
+ dev_err(dev, "unable to get hsphy-tuneeq\n");
+ return ret;
+ }
+
+ if (phy_cfg->phy_version == VERSION1) {
+ /* device setting */
+ phy->device_otg_ctrl1 &= ~phy_cfg->masks[MASK_AP_AHB_USB20_TUNEEQ];
+ phy->device_otg_ctrl1 |= (u32)val[0] << phy_cfg->parameters[TUNEEQ_SHIFT];
+
+ /* host setting */
+ phy->host_otg_ctrl1 &= ~phy_cfg->masks[MASK_AP_AHB_USB20_TUNEEQ];
+ phy->host_otg_ctrl1 |= (u32)val[1] << phy_cfg->parameters[TUNEEQ_SHIFT];
+
+ } else if (phy_cfg->phy_version == VERSION2 ||
+ phy_cfg->phy_version == VERSION3 ||
+ phy_cfg->phy_version == VERSION4) {
+ /* device setting */
+ phy->device_eye_pattern &= ~phy_cfg->masks[MASK_ANALOG_USB20_USB20_TUNEEQ];
+ phy->device_eye_pattern |= (u32)val[0] << phy_cfg->parameters[TUNEEQ_SHIFT];
+
+ /* host setting */
+ phy->host_eye_pattern &= ~phy_cfg->masks[MASK_ANALOG_USB20_USB20_TUNEEQ];
+ phy->host_eye_pattern |= (u32)val[1] << phy_cfg->parameters[TUNEEQ_SHIFT];
+ }
+
+ return 0;
+}
+
+static int sprd_eyepatt_tfregres_set(struct sprd_hsphy *phy, struct device *dev)
+{
+ int ret = 0;
+ u8 val[2];
+
+ ret = of_property_read_u8_array(dev->of_node, "sprd,hsphy-tfregres", val, 2);
+
+ if (ret < 0) {
+ dev_err(dev, "unable to get hsphy-tfregres\n");
+ return ret;
+ }
+
+ if (phy_cfg->phy_version == VERSION1) {
+ /* device setting */
+ phy->device_otg_ctrl1 &= ~phy_cfg->masks[MASK_AP_AHB_USB20_TFREGRES];
+ phy->device_otg_ctrl1 |= (u32)val[0] << phy_cfg->parameters[TFREGRES_SHIFT];
+
+ /* host setting */
+ phy->host_otg_ctrl1 &= ~phy_cfg->masks[MASK_AP_AHB_USB20_TFREGRES];
+ phy->host_otg_ctrl1 |= (u32)val[1] << phy_cfg->parameters[TFREGRES_SHIFT];
+ } else if (phy_cfg->phy_version == VERSION2 ||
+ phy_cfg->phy_version == VERSION3 ||
+ phy_cfg->phy_version == VERSION4) {
+ /* device setting */
+ phy->device_eye_pattern &= ~phy_cfg->masks[MASK_ANALOG_USB20_USB20_TFREGRES];
+ phy->device_eye_pattern |= (u32)val[0] << phy_cfg->parameters[TFREGRES_SHIFT];
+
+ /* host setting */
+ phy->host_eye_pattern &= ~phy_cfg->masks[MASK_ANALOG_USB20_USB20_TFREGRES];
+ phy->host_eye_pattern |= (u32)val[1] << phy_cfg->parameters[TFREGRES_SHIFT];
+ }
+
+ return 0;
+}
+
+static int sprd_eye_pattern_prepared(struct sprd_hsphy *phy, struct device *dev)
+{
+ int ret = 0;
+
+ if (phy_cfg->phy_version == VERSION1) {
+ /* set default OTG_CTRL */
+ phy->device_otg_ctrl0 = readl_relaxed(phy->base +
+ phy_cfg->regs[REG_AP_AHB_OTG_CTRL0]);
+ phy->device_otg_ctrl1 = readl_relaxed(phy->base +
+ phy_cfg->regs[REG_AP_AHB_OTG_CTRL1]);
+
+ phy->host_otg_ctrl0 = readl_relaxed(phy->base +
+ phy_cfg->regs[REG_AP_AHB_OTG_CTRL0]);
+ phy->host_otg_ctrl1 = readl_relaxed(phy->base +
+ phy_cfg->regs[REG_AP_AHB_OTG_CTRL1]);
+ } else if (phy_cfg->phy_version == VERSION2 ||
+ phy_cfg->phy_version == VERSION3 ||
+ phy_cfg->phy_version == VERSION4) {
+ /* set default eyepatt */
+ regmap_read(phy->analog, phy_cfg->regs[REG_ANALOG_USB20_USB20_TRIMMING],
+ &phy->device_eye_pattern);
+
+ regmap_read(phy->analog, phy_cfg->regs[REG_ANALOG_USB20_USB20_TRIMMING],
+ &phy->host_eye_pattern);
+ }
+
+ /* set eyepatt tunehsamp */
+ ret |= sprd_eyepatt_tunehsamp_set(phy, dev);
+
+ /* set eyepatt tuneeq */
+ ret |= sprd_eyepatt_tuneeq_set(phy, dev);
+
+ /* set eyepatt tfregres */
+ ret |= sprd_eyepatt_tfregres_set(phy, dev);
+
+ return ret;
+}
+
+static int sprd_hsphy_cali_mode(void)
+{
+ struct device_node *cmdline_node;
+ const char *cmdline, *mode;
+ int ret;
+
+ cmdline_node = of_find_node_by_path("/chosen");
+ ret = of_property_read_string(cmdline_node, "bootargs", &cmdline);
+
+ if (ret) {
+ pr_err("Can't not parse bootargs\n");
+ return 0;
+ }
+
+ mode = strstr(cmdline, "androidboot.mode=cali");
+ if (mode)
+ return 1;
+
+ mode = strstr(cmdline, "sprdboot.mode=cali");
+ if (mode)
+ return 1;
+
+ return 0;
+}
+
+static int sprd_hsphy_probe(struct platform_device *pdev)
+{
+ struct sprd_hsphy *phy;
+ struct resource *res;
+ struct device *dev = &pdev->dev;
+ int ret = 0, calimode = 0;
+ struct usb_otg *otg;
+
+ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+ if (!phy)
+ return -ENOMEM;
+
+ otg = devm_kzalloc(dev, sizeof(*otg), GFP_KERNEL);
+ if (!otg)
+ return -ENOMEM;
+
+ /* phy cfg data */
+ phy_cfg = of_device_get_match_data(dev);
+ if (!phy_cfg) {
+ dev_err(dev, "no matching driver data found\n");
+ return -EINVAL;
+ }
+
+ /* set vdd */
+ ret = of_property_read_u32(dev->of_node, "sprd,vdd-voltage",
+ &phy->vdd_vol);
+ if (ret < 0) {
+ dev_err(dev, "unable to read hsphy vdd voltage\n");
+ return ret;
+ }
+
+ calimode = sprd_hsphy_cali_mode();
+ if (calimode) {
+ phy->vdd_vol = phy_cfg->parameters[FULLSPEED_USB33_TUNE];
+ dev_info(dev, "calimode vdd_vol:%d\n", phy->vdd_vol);
+ }
+
+ phy->vdd = devm_regulator_get(dev, "vdd");
+ if (IS_ERR(phy->vdd)) {
+ dev_err(dev, "unable to get hsphy vdd supply\n");
+ return PTR_ERR(phy->vdd);
+ }
+
+ ret = regulator_set_voltage(phy->vdd, phy->vdd_vol, phy->vdd_vol);
+ if (ret < 0) {
+ dev_err(dev, "fail to set hsphy vdd voltage at %dmV\n",
+ phy->vdd_vol);
+ return ret;
+ }
+
+ /* phy tune */
+ if (phy_cfg->phy_version == VERSION1) {
+ ret = of_property_read_u32(dev->of_node, "sprd,tune-value",
+ &phy->phy_tune);
+ if (ret < 0) {
+ dev_err(dev, "unable to read hsphy usb phy tune\n");
+ return ret;
+ }
+ }
+
+ /* phy base */
+ if (phy_cfg->phy_version == VERSION1 ||
+ phy_cfg->phy_version == VERSION2) {
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_glb_regs");
+ if (!res) {
+ dev_err(dev, "missing USB PHY registers resource\n");
+ return -ENODEV;
+ }
+
+ phy->base = devm_ioremap(dev, res->start, resource_size(res));
+ if (IS_ERR(phy->base)) {
+ dev_err(dev, "unable to get phy base!\n");
+ return PTR_ERR(phy->base);
+ }
+ }
+
+ /* analog & aoapb & apahb regmap */
+ phy->aon_apb = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "sprd,syscon-enable");
+ if (IS_ERR(phy->aon_apb)) {
+ dev_err(dev, "USB aon apb syscon failed!\n");
+ return PTR_ERR(phy->aon_apb);
+ }
+
+ if (phy_cfg->phy_version == VERSION2) {
+ phy->ap_ahb = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "sprd,syscon-apahb");
+ if (IS_ERR(phy->ap_ahb)) {
+ dev_err(dev, "USB apahb syscon failed!\n");
+ return PTR_ERR(phy->ap_ahb);
+ }
+ }
+
+ if (phy_cfg->phy_version != VERSION1) {
+ phy->analog = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "sprd,syscon-ana");
+ if (IS_ERR(phy->analog)) {
+ dev_err(dev, "USB analog syscon failed!\n");
+ return PTR_ERR(phy->analog);
+ }
+ }
+
+ /* prepare eye pattern */
+ ret = sprd_eye_pattern_prepared(phy, dev);
+ if (ret < 0)
+ dev_warn(dev, "sprd_eye_pattern_prepared failed, ret = %d\n", ret);
+
+ /* enable usb module */
+ if (phy_cfg->phy_version == VERSION2 ||
+ phy_cfg->phy_version == VERSION3) {
+ phy_cfg->cfg_ops->usb_enable_ctrl(phy, CTRL2);
+ }
+
+ /* usb phy power down */
+ if (phy_cfg->phy_version != VERSION4)
+ phy_cfg->cfg_ops->usb_phy_power_ctrl(phy, CTRL2);
+
+ phy->dev = dev;
+ phy->phy.dev = dev;
+ phy->phy.label = "sprd-hsphy";
+ phy->phy.otg = otg;
+ phy->phy.init = sprd_hsphy_init;
+ phy->phy.shutdown = sprd_hsphy_shutdown;
+ phy->phy.set_vbus = sprd_hostphy_set;
+ phy->phy.type = USB_PHY_TYPE_USB2;
+ phy->phy.vbus_nb.notifier_call = sprd_hsphy_vbus_notify;
+ otg->usb_phy = &phy->phy;
+
+ device_init_wakeup(phy->dev, true);
+ phy->wake_lock = wakeup_source_register(phy->dev, "sprd-hsphy");
+ if (!phy->wake_lock) {
+ dev_err(dev, "fail to register wakeup lock.\n");
+ return -ENOMEM;
+ }
+ INIT_WORK(&phy->work, sprd_hsphy_charger_detect_work);
+ platform_set_drvdata(pdev, phy);
+
+ ret = usb_add_phy_dev(&phy->phy);
+ if (ret) {
+ dev_err(dev, "fail to add phy\n");
+ return ret;
+ }
+
+ ret = sysfs_create_groups(&dev->kobj, usb_hsphy_groups);
+ if (ret)
+ dev_warn(dev, "failed to create usb hsphy attributes\n");
+
+ if (extcon_get_state(phy->phy.edev, EXTCON_USB) > 0)
+ usb_phy_set_charger_state(&phy->phy, USB_CHARGER_PRESENT);
+
+ dev_info(dev, "sprd usb phy probe ok !\n");
+
+ return ret;
+}
+
+static int sprd_hsphy_remove(struct platform_device *pdev)
+{
+ struct sprd_hsphy *phy = platform_get_drvdata(pdev);
+
+ sysfs_remove_groups(&pdev->dev.kobj, usb_hsphy_groups);
+ usb_remove_phy(&phy->phy);
+ if (regulator_is_enabled(phy->vdd))
+ regulator_disable(phy->vdd);
+
+ return 0;
+}
+
+static const struct of_device_id sprd_hsphy_match[] = {
+ { .compatible = "sprd,pike2-phy", .data = &pike2_phy_cfg,},
+ { .compatible = "sprd,sharkle-phy", .data = &sharkle_phy_cfg,},
+ { .compatible = "sprd,sharkl3-phy", .data = &sharkl3_phy_cfg,},
+ { .compatible = "sprd,sharkl5-phy", .data = &sharkl5_phy_cfg,},
+ { .compatible = "sprd,sharkl5pro-phy", .data = &sharkl5pro_phy_cfg,},
+ { .compatible = "sprd,qogirl6-phy", .data = &qogirl6_phy_cfg,},
+ { .compatible = "sprd,qogirn6lite-phy", .data = &qogirn6lite_phy_cfg,},
+ { .compatible = "sprd,uis8520-phy", .data = &uis8520_phy_cfg,},
+ {},
+};
+MODULE_DEVICE_TABLE(of, sprd_hsphy_match);
+
+static struct platform_driver sprd_hsphy_driver = {
+ .probe = sprd_hsphy_probe,
+ .remove = sprd_hsphy_remove,
+ .driver = {
+ .name = "sprd-hsphy",
+ .of_match_table = sprd_hsphy_match,
+ },
+};
+
+static int __init sprd_hsphy_driver_init(void)
+{
+ return platform_driver_register(&sprd_hsphy_driver);
+}
+
+static void __exit sprd_hsphy_driver_exit(void)
+{
+ platform_driver_unregister(&sprd_hsphy_driver);
+}
+
+late_initcall(sprd_hsphy_driver_init);
+module_exit(sprd_hsphy_driver_exit);
+
+MODULE_ALIAS("platform:spreadtrum-usb20-hsphy");
+MODULE_AUTHOR("Pu Li <lip308226@xxxxxxxxx>");
+MODULE_DESCRIPTION("Spreadtrum USB20 HSPHY driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/sprd/phy-sprd-usb20-hs.h b/drivers/phy/sprd/phy-sprd-usb20-hs.h
new file mode 100644
index 000000000000..897ee5e64482
--- /dev/null
+++ b/drivers/phy/sprd/phy-sprd-usb20-hs.h
@@ -0,0 +1,525 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * phy-sprd-usb20-hs.h - Spreadtrum usb20 phy Glue layer h file
+ *
+ * Copyright 2020-2023 Unisoc Inc.
+ */
+
+#ifndef __SPRD_USB20_HS_H
+#define __SPRD_USB20_HS_H
+
+#include <linux/regmap.h>
+#include <linux/usb/phy.h>
+
+struct sprd_hsphy {
+ struct device *dev;
+ struct usb_phy phy;
+ void __iomem *base;
+ struct regulator *vdd;
+ struct regmap *aon_apb;
+ struct regmap *ap_ahb;
+ struct regmap *analog;
+ struct wakeup_source *wake_lock;
+ struct work_struct work;
+ unsigned long event;
+ u32 vdd_vol;
+ u32 phy_tune;
+ u32 host_eye_pattern;
+ u32 device_eye_pattern;
+ u32 host_otg_ctrl0;
+ u32 device_otg_ctrl0;
+ u32 host_otg_ctrl1;
+ u32 device_otg_ctrl1;
+ atomic_t reset;
+ atomic_t inited;
+ bool is_host;
+};
+
+enum hsphy_parameters {
+ TUNEHSAMP_SHIFT,
+ TUNEEQ_SHIFT,
+ TFREGRES_SHIFT,
+ FULLSPEED_USB33_TUNE,
+};
+
+enum sprd_hsphy_reg_layout {
+ REG_AON_APB_APB_RST1,
+ REG_AON_APB_APB_RST2,
+ REG_AON_APB_APB_EB1,
+ REG_AON_APB_APB_EB2,
+ REG_AON_APB_CGM_REG1,
+ REG_AON_APB_OTG_PHY_TEST,
+ REG_AON_APB_OTG_PHY_CTRL,
+ REG_AON_APB_PWR_CTRL,
+ REG_AON_APB_AON_SOC_USB_CTRL,
+ REG_AON_APB_MIPI_CSI_POWER_CTRL,
+ REG_AP_AHB_AHB_EB,
+ REG_AP_AHB_AHB_RST,
+ REG_AP_AHB_OTG_CTRL0,
+ REG_AP_AHB_OTG_CTRL1,
+ REG_AP_AHB_OTG_PHY_CTRL,
+ REG_AP_AHB_OTG_PHY_TUNE,
+ REG_AP_AHB_OTG_PHY_TEST,
+ REG_ANALOG_USB20_USB20_ISO_SW,
+ REG_ANALOG_USB20_USB20_BATTER_PLL,
+ REG_ANALOG_USB20_USB20_UTMI_CTL1,
+ REG_ANALOG_USB20_USB20_TRIMMING,
+ REG_ANALOG_USB20_USB20_UTMI_CTL2,
+ REG_ANALOG_USB20_REG_SEL_CFG_0,
+ REG_ANALOG_USB20_IDDG,
+ REG_ANALOG_USB20_USB20_PHY,
+};
+
+enum sprd_hsphy_mask_layout {
+ MASK_AON_APB_USB_PHY_PD_S,
+ MASK_AON_APB_USB_PHY_PD_L,
+ MASK_AON_APB_ANLG_APB_EB,
+ MASK_AON_APB_ANLG_EB,
+ MASK_AON_APB_OTG_REF_EB,
+ MASK_AON_APB_ANA_EB,
+ MASK_AON_APB_OTG_UTMI_EB,
+ MASK_AON_APB_AON_USB2_TOP_EB,
+ MASK_AON_APB_OTG_PHY_EB,
+ MASK_AON_APB_CGM_OTG_REF_EN,
+ MASK_AON_APB_CGM_DPHY_REF_EN,
+ MASK_AON_APB_USB_ISO_SW_EN,
+ MASK_AON_APB_OTG_PHY_SOFT_RST,
+ MASK_AON_APB_OTG_UTMI_SOFT_RST,
+ MASK_AON_APB_OTG_VBUS_VALID_PHYREG,
+ MASK_AON_APB_USB2_PHY_IDDIG,
+ MASK_AON_APB_UTMI_WIDTH_SEL,
+ MASK_AON_APB_USB20_CTRL_MUX_REG,
+ MASK_AON_APB_USB20_ISO_SW_EN,
+ MASK_AON_APB_C2G_ANALOG_USB20_USB20_PS_PD_S,
+ MASK_AON_APB_C2G_ANALOG_USB20_USB20_PS_PD_L,
+ MASK_AP_AHB_OTG_EB,
+ MASK_AP_AHB_OTG_PHY_SOFT_RST,
+ MASK_AP_AHB_OTG_UTMI_SOFT_RST,
+ MASK_AP_AHB_OTG_SOFT_RST,
+ MASK_AP_AHB_USB2_PHY_IDDIG,
+ MASK_AP_AHB_OTG_DPPULLDOWN,
+ MASK_AP_AHB_OTG_DMPULLDOWN,
+ MASK_AP_AHB_OTG_VBUS_VALID_EXT,
+ MASK_AP_AHB_OTG_VBUS_VALID_PHYREG,
+ MASK_AP_AHB_UTMI_WIDTH_SEL,
+ MASK_AP_AHB_USB2_DATABUS16_8,
+ MASK_AP_AHB_USB20_SAMPLER_SEL,
+ MASK_AP_AHB_USB20_TUNEHSAMP,
+ MASK_AP_AHB_USB20_TUNEEQ,
+ MASK_AP_AHB_USB20_TFREGRES,
+ MASK_ANALOG_USB20_USB20_VBUSVLDEXT,
+ MASK_ANALOG_USB20_USB20_DATABUS16_8,
+ MASK_DBG_SEL_ANALOG_USB20_USB20_DMPULLDOWN,
+ MASK_DBG_SEL_ANALOG_USB20_USB20_DPPULLDOWN,
+ MASK_ANALOG_USB20_USB20_DMPULLDOWN,
+ MASK_ANALOG_USB20_USB20_DPPULLDOWN,
+ MASK_ANALOG_USB20_UTMIOTG_IDDG,
+ MASK_ANALOG_USB20_USB20_PS_PD_S,
+ MASK_ANALOG_USB20_USB20_PS_PD_L,
+ MASK_ANALOG_USB20_USB20_RESERVED,
+ MASK_ANALOG_USB20_USB20_ISO_SW_EN,
+ MASK_ANALOG_USB20_USB20_TUNEHSAMP,
+ MASK_ANALOG_USB20_USB20_TUNEEQ,
+ MASK_ANALOG_USB20_USB20_TFREGRES,
+};
+
+enum {
+ CTRL0 = 0,
+ CTRL1,
+ CTRL2,
+};
+
+struct sprd_hsphy_cfg_ops {
+ void (*usb_enable_ctrl)(struct sprd_hsphy *phy, int on);
+ void (*usb_phy_power_ctrl)(struct sprd_hsphy *phy, int on);
+ void (*usb_vbus_ctrl)(struct sprd_hsphy *phy, int on);
+ void (*utmi_width_sel)(struct sprd_hsphy *phy);
+ void (*reset_core)(struct sprd_hsphy *phy);
+ int (*set_mode)(struct sprd_hsphy *phy, int on);
+};
+
+enum hsphy_ip_version {
+ VERSION1,
+ VERSION2,
+ VERSION3,
+ VERSION4,
+};
+
+enum hsphy_owner {
+ PIKE2,
+ SHARKLE,
+ SHARKL3,
+ SHARKL5,
+ SHARKL5PRO,
+ QOGIRL6,
+ QOGIRN6LITE,
+ UIS8520,
+};
+
+struct sprd_hsphy_cfg {
+ /* array of registers with different offsets */
+ const unsigned int *regs;
+
+ const unsigned int *masks;
+
+ /* private ops for each SOC */
+ const struct sprd_hsphy_cfg_ops *cfg_ops;
+
+ const unsigned int *parameters;
+
+ enum hsphy_ip_version phy_version;
+
+ enum hsphy_owner owner;
+};
+
+static const unsigned int pike2_regs_layout[] = {
+ [REG_AON_APB_PWR_CTRL] = 0x0024,
+ [REG_AP_AHB_AHB_RST] = 0x0004,
+ [REG_AP_AHB_OTG_CTRL0] = 0x302c,
+ [REG_AP_AHB_OTG_CTRL1] = 0x3030,
+ [REG_AP_AHB_OTG_PHY_CTRL] = 0x3028,
+ [REG_AP_AHB_OTG_PHY_TUNE] = 0x3020,
+ [REG_AP_AHB_OTG_PHY_TEST] = 0x3024,
+};
+
+static const unsigned int sharkle_regs_layout[] = {
+ [REG_AON_APB_PWR_CTRL] = 0x0024,
+ [REG_AP_AHB_AHB_RST] = 0x0004,
+ [REG_AP_AHB_OTG_CTRL0] = 0x302c,
+ [REG_AP_AHB_OTG_CTRL1] = 0x3030,
+ [REG_AP_AHB_OTG_PHY_CTRL] = 0x3028,
+ [REG_AP_AHB_OTG_PHY_TUNE] = 0x3020,
+ [REG_AP_AHB_OTG_PHY_TEST] = 0x3024,
+};
+
+static const unsigned int sharkl3_regs_layout[] = {
+ [REG_AON_APB_APB_RST2] = 0x0130,
+ [REG_AON_APB_APB_EB2] = 0x00b0,
+ [REG_AON_APB_PWR_CTRL] = 0x0024,
+ [REG_AP_AHB_AHB_EB] = 0x0000,
+ [REG_AP_AHB_AHB_RST] = 0x0004,
+ [REG_AP_AHB_OTG_PHY_CTRL] = 0x3028,
+ [REG_AP_AHB_OTG_PHY_TEST] = 0x3024,
+ [REG_ANALOG_USB20_USB20_UTMI_CTL1] = 0x009c,
+ [REG_ANALOG_USB20_USB20_TRIMMING] = 0x00a8,
+ [REG_ANALOG_USB20_USB20_UTMI_CTL2] = 0x00a4,
+ [REG_ANALOG_USB20_REG_SEL_CFG_0] = 0x00b0,
+ [REG_ANALOG_USB20_IDDG] = 0x00bc,
+};
+
+static const unsigned int sharkl5_regs_layout[] = {
+ [REG_AON_APB_APB_RST1] = 0x0010,
+ [REG_AON_APB_APB_EB1] = 0x0004,
+ [REG_AON_APB_CGM_REG1] = 0x0138,
+ [REG_AON_APB_OTG_PHY_TEST] = 0x0204,
+ [REG_AON_APB_OTG_PHY_CTRL] = 0x0208,
+ [REG_ANALOG_USB20_USB20_ISO_SW] = 0x0070,
+ [REG_ANALOG_USB20_USB20_BATTER_PLL] = 0x005c,
+ [REG_ANALOG_USB20_USB20_UTMI_CTL1] = 0x0058,
+ [REG_ANALOG_USB20_USB20_TRIMMING] = 0x0064,
+ [REG_ANALOG_USB20_USB20_UTMI_CTL2] = 0x0060,
+ [REG_ANALOG_USB20_REG_SEL_CFG_0] = 0x0074,
+};
+
+static const unsigned int sharkl5pro_regs_layout[] = {
+ [REG_AON_APB_APB_RST1] = 0x0010,
+ [REG_AON_APB_APB_EB1] = 0x0004,
+ [REG_AON_APB_CGM_REG1] = 0x0138,
+ [REG_AON_APB_OTG_PHY_TEST] = 0x0204,
+ [REG_AON_APB_OTG_PHY_CTRL] = 0x0208,
+ [REG_ANALOG_USB20_USB20_ISO_SW] = 0x0070,
+ [REG_ANALOG_USB20_USB20_BATTER_PLL] = 0x005c,
+ [REG_ANALOG_USB20_USB20_UTMI_CTL1] = 0x0058,
+ [REG_ANALOG_USB20_USB20_TRIMMING] = 0x0064,
+ [REG_ANALOG_USB20_USB20_UTMI_CTL2] = 0x0060,
+ [REG_ANALOG_USB20_REG_SEL_CFG_0] = 0x0074,
+};
+
+static const unsigned int qogirl6_regs_layout[] = {
+ [REG_AON_APB_APB_RST1] = 0x0010,
+ [REG_AON_APB_APB_EB1] = 0x0004,
+ [REG_AON_APB_CGM_REG1] = 0x0138,
+ [REG_AON_APB_OTG_PHY_TEST] = 0x0204,
+ [REG_AON_APB_OTG_PHY_CTRL] = 0x0208,
+ [REG_ANALOG_USB20_USB20_ISO_SW] = 0x001c,
+ [REG_ANALOG_USB20_USB20_BATTER_PLL] = 0x0008,
+ [REG_ANALOG_USB20_USB20_UTMI_CTL1] = 0x0004,
+ [REG_ANALOG_USB20_USB20_TRIMMING] = 0x0010,
+ [REG_ANALOG_USB20_USB20_UTMI_CTL2] = 0x000c,
+ [REG_ANALOG_USB20_REG_SEL_CFG_0] = 0x0020,
+};
+
+static const unsigned int qogirn6lite_regs_layout[] = {
+ [REG_AON_APB_APB_RST1] = 0x0010,
+ [REG_AON_APB_APB_EB1] = 0x0004,
+ [REG_AON_APB_CGM_REG1] = 0x0138,
+ [REG_AON_APB_OTG_PHY_TEST] = 0x0204,
+ [REG_AON_APB_OTG_PHY_CTRL] = 0x0208,
+ [REG_AON_APB_AON_SOC_USB_CTRL] = 0x0190,
+ [REG_AON_APB_MIPI_CSI_POWER_CTRL] = 0x0350,
+ [REG_ANALOG_USB20_USB20_UTMI_CTL1] = 0x0004,
+ [REG_ANALOG_USB20_USB20_TRIMMING] = 0x0010,
+ [REG_ANALOG_USB20_USB20_UTMI_CTL2] = 0x000c,
+ [REG_ANALOG_USB20_REG_SEL_CFG_0] = 0x0020,
+ [REG_ANALOG_USB20_USB20_PHY] = 0x001C,
+};
+
+static const unsigned int uis8520_regs_layout[] = {
+ [REG_AON_APB_APB_RST1] = 0x0010,
+ [REG_AON_APB_APB_EB1] = 0x0004,
+ [REG_AON_APB_CGM_REG1] = 0x0138,
+ [REG_AON_APB_OTG_PHY_TEST] = 0x0204,
+ [REG_AON_APB_OTG_PHY_CTRL] = 0x0208,
+ [REG_AON_APB_AON_SOC_USB_CTRL] = 0x0190,
+ [REG_AON_APB_MIPI_CSI_POWER_CTRL] = 0x0350,
+ [REG_ANALOG_USB20_USB20_UTMI_CTL1] = 0x0008,
+ [REG_ANALOG_USB20_USB20_TRIMMING] = 0x0018,
+ [REG_ANALOG_USB20_USB20_UTMI_CTL2] = 0x0010,
+ [REG_ANALOG_USB20_REG_SEL_CFG_0] = 0x0028,
+ [REG_ANALOG_USB20_USB20_PHY] = 0x0024,
+};
+
+static const unsigned int pike2_masks_layout[] = {
+ [MASK_AON_APB_USB_PHY_PD_S] = 0x20000,
+ [MASK_AON_APB_USB_PHY_PD_L] = 0x10000,
+ [MASK_AP_AHB_OTG_PHY_SOFT_RST] = 0x40,
+ [MASK_AP_AHB_OTG_UTMI_SOFT_RST] = 0x20,
+ [MASK_AP_AHB_OTG_SOFT_RST] = 0x10,
+ [MASK_AP_AHB_USB2_PHY_IDDIG] = 0x8,
+ [MASK_AP_AHB_OTG_DPPULLDOWN] = 0x100000,
+ [MASK_AP_AHB_OTG_DMPULLDOWN] = 0x200000,
+ [MASK_AP_AHB_OTG_VBUS_VALID_EXT] = 0x400000,
+ [MASK_AP_AHB_OTG_VBUS_VALID_PHYREG] = 0x1000000,
+ [MASK_AP_AHB_UTMI_WIDTH_SEL] = 0x40000000,
+ [MASK_AP_AHB_USB2_DATABUS16_8] = 0x20000000,
+ [MASK_AP_AHB_USB20_SAMPLER_SEL] = 0x100000,
+ [MASK_AP_AHB_USB20_TUNEHSAMP] = 0xc0000000,
+ [MASK_AP_AHB_USB20_TUNEEQ] = 0x7,
+ [MASK_AP_AHB_USB20_TFREGRES] = 0x3f00,
+};
+
+static const unsigned int sharkle_masks_layout[] = {
+ [MASK_AON_APB_USB_PHY_PD_S] = 0x20000,
+ [MASK_AON_APB_USB_PHY_PD_L] = 0x10000,
+ [MASK_AP_AHB_OTG_PHY_SOFT_RST] = 0x40,
+ [MASK_AP_AHB_OTG_UTMI_SOFT_RST] = 0x20,
+ [MASK_AP_AHB_OTG_SOFT_RST] = 0x10,
+ [MASK_AP_AHB_USB2_PHY_IDDIG] = 0x8,
+ [MASK_AP_AHB_OTG_DPPULLDOWN] = 0x100000,
+ [MASK_AP_AHB_OTG_DMPULLDOWN] = 0x200000,
+ [MASK_AP_AHB_OTG_VBUS_VALID_EXT] = 0x400000,
+ [MASK_AP_AHB_OTG_VBUS_VALID_PHYREG] = 0x1000000,
+ [MASK_AP_AHB_UTMI_WIDTH_SEL] = 0x40000000,
+ [MASK_AP_AHB_USB2_DATABUS16_8] = 0x20000000,
+ [MASK_AP_AHB_USB20_SAMPLER_SEL] = 0x100000,
+ [MASK_AP_AHB_USB20_TUNEHSAMP] = 0xc0000000,
+ [MASK_AP_AHB_USB20_TUNEEQ] = 0x7,
+ [MASK_AP_AHB_USB20_TFREGRES] = 0x3f00,
+};
+
+static const unsigned int sharkl3_masks_layout[] = {
+ [MASK_AON_APB_USB_PHY_PD_S] = 0x20000,
+ [MASK_AON_APB_USB_PHY_PD_L] = 0x10000,
+ [MASK_AON_APB_ANLG_APB_EB] = 0x2000,
+ [MASK_AON_APB_ANLG_EB] = 0x800,
+ [MASK_AON_APB_OTG_REF_EB] = 0x4000000,
+ [MASK_AON_APB_OTG_PHY_SOFT_RST] = 0x8000000,
+ [MASK_AON_APB_USB_ISO_SW_EN] = 0x10000000,
+ [MASK_AP_AHB_OTG_EB] = 0x10,
+ [MASK_AP_AHB_OTG_UTMI_SOFT_RST] = 0x20,
+ [MASK_AP_AHB_OTG_SOFT_RST] = 0x10,
+ [MASK_AP_AHB_OTG_VBUS_VALID_PHYREG] = 0x10000000,
+ [MASK_AP_AHB_UTMI_WIDTH_SEL] = 0x40000000,
+ [MASK_ANALOG_USB20_USB20_VBUSVLDEXT] = 0x10000,
+ [MASK_ANALOG_USB20_USB20_DATABUS16_8] = 0x10000000,
+ [MASK_DBG_SEL_ANALOG_USB20_USB20_DMPULLDOWN] = 0x1,
+ [MASK_DBG_SEL_ANALOG_USB20_USB20_DPPULLDOWN] = 0x2,
+ [MASK_ANALOG_USB20_USB20_DMPULLDOWN] = 0x4,
+ [MASK_ANALOG_USB20_USB20_DPPULLDOWN] = 0x8,
+ [MASK_ANALOG_USB20_UTMIOTG_IDDG] = 0x1,
+ [MASK_ANALOG_USB20_USB20_TUNEHSAMP] = 0x18000000,
+ [MASK_ANALOG_USB20_USB20_TUNEEQ] = 0x1c,
+ [MASK_ANALOG_USB20_USB20_TFREGRES] = 0x7e00000,
+};
+
+static const unsigned int sharkl5_masks_layout[] = {
+ [MASK_AON_APB_ANA_EB] = 0x1000,
+ [MASK_AON_APB_OTG_UTMI_EB] = 0x100,
+ [MASK_AON_APB_CGM_OTG_REF_EN] = 0x1000,
+ [MASK_AON_APB_CGM_DPHY_REF_EN] = 0x400,
+ [MASK_AON_APB_OTG_PHY_SOFT_RST] = 0x200,
+ [MASK_AON_APB_OTG_UTMI_SOFT_RST] = 0x100,
+ [MASK_AON_APB_OTG_VBUS_VALID_PHYREG] = 0x1000000,
+ [MASK_AON_APB_UTMI_WIDTH_SEL] = 0x40000000,
+ [MASK_AON_APB_USB2_PHY_IDDIG] = 0x8,
+ [MASK_ANALOG_USB20_USB20_VBUSVLDEXT] = 0x10000,
+ [MASK_ANALOG_USB20_USB20_DATABUS16_8] = 0x10000000,
+ [MASK_DBG_SEL_ANALOG_USB20_USB20_DMPULLDOWN] = 0x2,
+ [MASK_DBG_SEL_ANALOG_USB20_USB20_DPPULLDOWN] = 0x4,
+ [MASK_ANALOG_USB20_USB20_DMPULLDOWN] = 0x8,
+ [MASK_ANALOG_USB20_USB20_DPPULLDOWN] = 0x10,
+ [MASK_ANALOG_USB20_USB20_PS_PD_S] = 0x10,
+ [MASK_ANALOG_USB20_USB20_PS_PD_L] = 0x8,
+ [MASK_ANALOG_USB20_USB20_RESERVED] = 0xffff,
+ [MASK_ANALOG_USB20_USB20_ISO_SW_EN] = 0x1,
+ [MASK_ANALOG_USB20_USB20_TUNEHSAMP] = 0x06000000,
+ [MASK_ANALOG_USB20_USB20_TUNEEQ] = 0x7,
+ [MASK_ANALOG_USB20_USB20_TFREGRES] = 0x01f80000,
+};
+
+static const unsigned int sharkl5pro_masks_layout[] = {
+ [MASK_AON_APB_ANA_EB] = 0x1000,
+ [MASK_AON_APB_OTG_UTMI_EB] = 0x100,
+ [MASK_AON_APB_CGM_OTG_REF_EN] = 0x1000,
+ [MASK_AON_APB_CGM_DPHY_REF_EN] = 0x400,
+ [MASK_AON_APB_OTG_PHY_SOFT_RST] = 0x200,
+ [MASK_AON_APB_OTG_UTMI_SOFT_RST] = 0x100,
+ [MASK_AON_APB_OTG_VBUS_VALID_PHYREG] = 0x1000000,
+ [MASK_AON_APB_UTMI_WIDTH_SEL] = 0x40000000,
+ [MASK_AON_APB_USB2_PHY_IDDIG] = 0x8,
+ [MASK_ANALOG_USB20_USB20_VBUSVLDEXT] = 0x10000,
+ [MASK_ANALOG_USB20_USB20_DATABUS16_8] = 0x10000000,
+ [MASK_DBG_SEL_ANALOG_USB20_USB20_DMPULLDOWN] = 0x2,
+ [MASK_DBG_SEL_ANALOG_USB20_USB20_DPPULLDOWN] = 0x4,
+ [MASK_ANALOG_USB20_USB20_DMPULLDOWN] = 0x8,
+ [MASK_ANALOG_USB20_USB20_DPPULLDOWN] = 0x10,
+ [MASK_ANALOG_USB20_USB20_PS_PD_S] = 0x10,
+ [MASK_ANALOG_USB20_USB20_PS_PD_L] = 0x8,
+ [MASK_ANALOG_USB20_USB20_RESERVED] = 0xffff,
+ [MASK_ANALOG_USB20_USB20_ISO_SW_EN] = 0x1,
+ [MASK_ANALOG_USB20_USB20_TUNEHSAMP] = 0x06000000,
+ [MASK_ANALOG_USB20_USB20_TUNEEQ] = 0x7,
+ [MASK_ANALOG_USB20_USB20_TFREGRES] = 0x01f80000,
+};
+
+static const unsigned int qogirl6_masks_layout[] = {
+ [MASK_AON_APB_ANA_EB] = 0x1000,
+ [MASK_AON_APB_OTG_UTMI_EB] = 0x100,
+ [MASK_AON_APB_CGM_OTG_REF_EN] = 0x1000,
+ [MASK_AON_APB_CGM_DPHY_REF_EN] = 0x400,
+ [MASK_AON_APB_OTG_PHY_SOFT_RST] = 0x200,
+ [MASK_AON_APB_OTG_UTMI_SOFT_RST] = 0x100,
+ [MASK_AON_APB_OTG_VBUS_VALID_PHYREG] = 0x1000000,
+ [MASK_AON_APB_UTMI_WIDTH_SEL] = 0x40000000,
+ [MASK_AON_APB_USB2_PHY_IDDIG] = 0x8,
+ [MASK_ANALOG_USB20_USB20_VBUSVLDEXT] = 0x10000,
+ [MASK_ANALOG_USB20_USB20_DATABUS16_8] = 0x10000000,
+ [MASK_DBG_SEL_ANALOG_USB20_USB20_DMPULLDOWN] = 0x2,
+ [MASK_DBG_SEL_ANALOG_USB20_USB20_DPPULLDOWN] = 0x4,
+ [MASK_ANALOG_USB20_USB20_DMPULLDOWN] = 0x8,
+ [MASK_ANALOG_USB20_USB20_DPPULLDOWN] = 0x10,
+ [MASK_ANALOG_USB20_USB20_PS_PD_S] = 0x10,
+ [MASK_ANALOG_USB20_USB20_PS_PD_L] = 0x8,
+ [MASK_ANALOG_USB20_USB20_RESERVED] = 0xffff,
+ [MASK_ANALOG_USB20_USB20_ISO_SW_EN] = 0x1,
+ [MASK_ANALOG_USB20_USB20_TUNEHSAMP] = 0x06000000,
+ [MASK_ANALOG_USB20_USB20_TUNEEQ] = 0x7,
+ [MASK_ANALOG_USB20_USB20_TFREGRES] = 0x01f80000,
+};
+
+static const unsigned int qogirn6lite_masks_layout[] = {
+ [MASK_AON_APB_AON_USB2_TOP_EB] = 0x0100,
+ [MASK_AON_APB_OTG_PHY_EB] = 0x0200,
+ [MASK_AON_APB_CGM_OTG_REF_EN] = 0x1000,
+ [MASK_AON_APB_CGM_DPHY_REF_EN] = 0x400,
+ [MASK_AON_APB_OTG_PHY_SOFT_RST] = 0x200,
+ [MASK_AON_APB_OTG_UTMI_SOFT_RST] = 0x100,
+ [MASK_AON_APB_OTG_VBUS_VALID_PHYREG] = 0x1000000,
+ [MASK_AON_APB_USB2_PHY_IDDIG] = 0x8,
+ [MASK_AON_APB_USB20_CTRL_MUX_REG] = 0x0008,
+ [MASK_AON_APB_USB20_ISO_SW_EN] = 0x0010,
+ [MASK_AON_APB_C2G_ANALOG_USB20_USB20_PS_PD_S] = 0x0002,
+ [MASK_AON_APB_C2G_ANALOG_USB20_USB20_PS_PD_L] = 0x0001,
+ [MASK_ANALOG_USB20_USB20_VBUSVLDEXT] = 0x10000,
+ [MASK_DBG_SEL_ANALOG_USB20_USB20_DMPULLDOWN] = 0x4,
+ [MASK_DBG_SEL_ANALOG_USB20_USB20_DPPULLDOWN] = 0x8,
+ [MASK_ANALOG_USB20_USB20_DMPULLDOWN] = 0x8,
+ [MASK_ANALOG_USB20_USB20_DPPULLDOWN] = 0x10,
+ [MASK_ANALOG_USB20_USB20_RESERVED] = 0x0000FFFF,
+ [MASK_ANALOG_USB20_USB20_ISO_SW_EN] = 0x1,
+ [MASK_ANALOG_USB20_USB20_TUNEHSAMP] = 0x06000000,
+ [MASK_ANALOG_USB20_USB20_TUNEEQ] = 0x7,
+ [MASK_ANALOG_USB20_USB20_TFREGRES] = 0x01f80000,
+};
+
+static const unsigned int uis8520_masks_layout[] = {
+ [MASK_AON_APB_AON_USB2_TOP_EB] = 0x0100,
+ [MASK_AON_APB_OTG_PHY_EB] = 0x0200,
+ [MASK_AON_APB_CGM_OTG_REF_EN] = 0x1000,
+ [MASK_AON_APB_OTG_PHY_SOFT_RST] = 0x200,
+ [MASK_AON_APB_OTG_UTMI_SOFT_RST] = 0x100,
+ [MASK_AON_APB_OTG_VBUS_VALID_PHYREG] = 0x1000000,
+ [MASK_AON_APB_USB2_PHY_IDDIG] = 0x8,
+ [MASK_AON_APB_USB20_CTRL_MUX_REG] = 0x0008,
+ [MASK_AON_APB_USB20_ISO_SW_EN] = 0x0010,
+ [MASK_AON_APB_C2G_ANALOG_USB20_USB20_PS_PD_S] = 0x0002,
+ [MASK_AON_APB_C2G_ANALOG_USB20_USB20_PS_PD_L] = 0x0001,
+ [MASK_ANALOG_USB20_USB20_VBUSVLDEXT] = 0x10000,
+ [MASK_DBG_SEL_ANALOG_USB20_USB20_DMPULLDOWN] = 0x4,
+ [MASK_DBG_SEL_ANALOG_USB20_USB20_DPPULLDOWN] = 0x8,
+ [MASK_ANALOG_USB20_USB20_DMPULLDOWN] = 0x8,
+ [MASK_ANALOG_USB20_USB20_DPPULLDOWN] = 0x10,
+ [MASK_ANALOG_USB20_USB20_RESERVED] = 0x0000FFFF,
+ [MASK_ANALOG_USB20_USB20_ISO_SW_EN] = 0x1,
+ [MASK_ANALOG_USB20_USB20_TUNEHSAMP] = 0xC0,
+ [MASK_ANALOG_USB20_USB20_TUNEEQ] = 0x7,
+ [MASK_ANALOG_USB20_USB20_TFREGRES] = 0x1F,
+};
+
+static const unsigned int phy_pike2_parameters[] = {
+ [TUNEHSAMP_SHIFT] = 30,
+ [TUNEEQ_SHIFT] = 0,
+ [TFREGRES_SHIFT] = 8,
+ [FULLSPEED_USB33_TUNE] = 2700000,
+};
+
+static const unsigned int phy_sharkle_parameters[] = {
+ [TUNEHSAMP_SHIFT] = 30,
+ [TUNEEQ_SHIFT] = 0,
+ [TFREGRES_SHIFT] = 8,
+ [FULLSPEED_USB33_TUNE] = 2700000,
+};
+
+static const unsigned int phy_sharkl3_parameters[] = {
+ [TUNEHSAMP_SHIFT] = 27,
+ [TUNEEQ_SHIFT] = 2,
+ [TFREGRES_SHIFT] = 21,
+ [FULLSPEED_USB33_TUNE] = 2700000,
+};
+
+static const unsigned int phy_sharkl5_parameters[] = {
+ [TUNEHSAMP_SHIFT] = 25,
+ [TUNEEQ_SHIFT] = 0,
+ [TFREGRES_SHIFT] = 19,
+ [FULLSPEED_USB33_TUNE] = 2700000,
+};
+
+static const unsigned int phy_sharkl5pro_parameters[] = {
+ [TUNEHSAMP_SHIFT] = 25,
+ [TUNEEQ_SHIFT] = 0,
+ [TFREGRES_SHIFT] = 19,
+ [FULLSPEED_USB33_TUNE] = 2700000,
+};
+
+static const unsigned int phy_qogirl6_parameters[] = {
+ [TUNEHSAMP_SHIFT] = 25,
+ [TUNEEQ_SHIFT] = 0,
+ [TFREGRES_SHIFT] = 19,
+ [FULLSPEED_USB33_TUNE] = 2700000,
+};
+
+static const unsigned int phy_qogirn6lite_parameters[] = {
+ [TUNEHSAMP_SHIFT] = 25,
+ [TUNEEQ_SHIFT] = 0,
+ [TFREGRES_SHIFT] = 19,
+ [FULLSPEED_USB33_TUNE] = 3300000,
+};
+
+static const unsigned int phy_uis8520_parameters[] = {
+ [TUNEHSAMP_SHIFT] = 6,
+ [TUNEEQ_SHIFT] = 0,
+ [TFREGRES_SHIFT] = 0,
+ [FULLSPEED_USB33_TUNE] = 3300000,
+};
+
+#endif
--
2.17.1