diff --git a/drivers/phy/phy-rockchip-inno-usb3.c b/drivers/phy/phy-rockchip-inno-usb3.c index 62e71a2bf9c5..ab80ce059233 100644 --- a/drivers/phy/phy-rockchip-inno-usb3.c +++ b/drivers/phy/phy-rockchip-inno-usb3.c @@ -118,6 +118,8 @@ struct rockchip_u3phy_cfg { int (*phy_tuning)(struct rockchip_u3phy *, struct rockchip_u3phy_port *, struct device_node *); + int (*phy_cp_test)(struct rockchip_u3phy *, + struct rockchip_u3phy_port *); }; struct rockchip_u3phy_port { @@ -360,6 +362,33 @@ static int rockchip_u3phy_power_off(struct phy *phy) return 0; } +static int rockchip_u3phy_cp_test(struct phy *phy) +{ + struct rockchip_u3phy_port *u3phy_port = phy_get_drvdata(phy); + struct rockchip_u3phy *u3phy = dev_get_drvdata(phy->dev.parent); + int ret; + + if (u3phy->cfgs->phy_cp_test) { + /* + * When do USB3 compliance test, we may connect the oscilloscope + * front panel Aux Out to the DUT SSRX+, the Aux Out of the + * oscilloscope outputs a negative pulse whose width is between + * 300- 400 ns which may trigger some DUTs to change the CP test + * pattern. + * + * The Inno USB3 PHY disable the function to detect the negative + * pulse in SSRX+ by default, so we need to enable the function + * to toggle the CP test pattern before do USB3 compliance test. + */ + dev_dbg(u3phy->dev, "prepare for u3phy compliance test\n"); + ret = u3phy->cfgs->phy_cp_test(u3phy, u3phy_port); + if (ret) + return ret; + } + + return 0; +} + static __maybe_unused struct phy *rockchip_u3phy_xlate(struct device *dev, struct of_phandle_args *args) @@ -394,6 +423,7 @@ static struct phy_ops rockchip_u3phy_ops = { .exit = rockchip_u3phy_exit, .power_on = rockchip_u3phy_power_on, .power_off = rockchip_u3phy_power_off, + .cp_test = rockchip_u3phy_cp_test, .owner = THIS_MODULE, }; @@ -928,6 +958,19 @@ static int rk3328_u3phy_tuning(struct rockchip_u3phy *u3phy, return 0; } +static int rk322xh_u3phy_cp_test_enable(struct rockchip_u3phy *u3phy, + struct rockchip_u3phy_port *u3phy_port) +{ + if (u3phy_port->type == U3PHY_TYPE_PIPE) { + writel(0x0c, u3phy_port->base + 0x408); + } else { + dev_err(u3phy->dev, "The u3phy type is not pipe\n"); + return -EINVAL; + } + + return 0; +} + static const struct rockchip_u3phy_cfg rk3328_u3phy_cfgs[] = { { .reg = 0xff470000, @@ -945,6 +988,7 @@ static const struct rockchip_u3phy_cfg rk3328_u3phy_cfgs[] = { }, .phy_pipe_power = rk3328_u3phy_pipe_power, .phy_tuning = rk3328_u3phy_tuning, + .phy_cp_test = rk322xh_u3phy_cp_test_enable, }, { /* sentinel */ } };