Message ID | 20240718102637.3964232-1-xu.yang_2@nxp.com |
---|---|
State | New |
Headers | show |
Series | [1/6] usb: phy: mxs: Using regulator phy-3p0 | expand |
On Thu, Jul 18, 2024 at 11:00:06AM -0400, Frank Li wrote: > On Thu, Jul 18, 2024 at 06:26:33PM +0800, Xu Yang wrote: > > Per IC engineer request, we need to keep USBPHY2's clk always on, > > "IP require keep keep USBPHY2's clk always on." > > Not personal request, even it is IC expert. It should base on the "fact" > instead of personal's opinion. Okay. > > > in this way, the USBPHY2 (PLL7) power can be controlled by > > hardware suspend signal totally. It is benefit of USB remote wakeup > > case which needs the resume signal be sent out as soon as > > possible (without software interfere). Without this, we may see usb > > remote wakeup issue since the host does not send resume in time. > > So USBPHY2 (PLL7) power can be controlled by suspend signal. USB remote > wakeup needs resume signal be sent out as soon as possible to match > > "spec requirement" or some other requirement. Will change. > > > > > Signed-off-by: Xu Yang <xu.yang_2@nxp.com> > > --- > > drivers/usb/phy/phy-mxs-usb.c | 36 ++++++++++++++++++++++++++++------- > > 1 file changed, 29 insertions(+), 7 deletions(-) > > > > diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c > > index 42fcc8ad9492..b6868cc22c1e 100644 > > --- a/drivers/usb/phy/phy-mxs-usb.c > > +++ b/drivers/usb/phy/phy-mxs-usb.c > > @@ -150,6 +150,16 @@ > > #define MXS_PHY_TX_D_CAL_MIN 79 > > #define MXS_PHY_TX_D_CAL_MAX 119 > > > > +/* > > + * At some versions, the PHY2's clock is controlled by hardware directly, > > It better declear which version, for example, which chip use if no version > info in IP. Okay, will add. > > > + * eg, according to PHY's suspend status. In these PHYs, we only need to > > + * open the clock at the initialization and close it at its shutdown routine. > > + * It will be benefit for remote wakeup case which needs to send resume > > + * signal as soon as possible, and in this case, the resume signal can be sent > > + * out without software interfere. > > These PHYs can send resume signal without software interfere if not gate > clock. Will change. > > > + */ > > +#define MXS_PHY_HARDWARE_CONTROL_PHY2_CLK BIT(4) > > + > > struct mxs_phy_data { > > unsigned int flags; > > }; > > @@ -161,12 +171,14 @@ static const struct mxs_phy_data imx23_phy_data = { > > static const struct mxs_phy_data imx6q_phy_data = { > > .flags = MXS_PHY_SENDING_SOF_TOO_FAST | > > MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS | > > - MXS_PHY_NEED_IP_FIX, > > + MXS_PHY_NEED_IP_FIX | > > + MXS_PHY_HARDWARE_CONTROL_PHY2_CLK, > > }; > > > > static const struct mxs_phy_data imx6sl_phy_data = { > > .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS | > > - MXS_PHY_NEED_IP_FIX, > > + MXS_PHY_NEED_IP_FIX | > > + MXS_PHY_HARDWARE_CONTROL_PHY2_CLK, > > }; > > > > static const struct mxs_phy_data vf610_phy_data = { > > @@ -175,7 +187,8 @@ static const struct mxs_phy_data vf610_phy_data = { > > }; > > > > static const struct mxs_phy_data imx6sx_phy_data = { > > - .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS, > > + .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS | > > + MXS_PHY_HARDWARE_CONTROL_PHY2_CLK, > > }; > > > > static const struct mxs_phy_data imx6ul_phy_data = { > > @@ -206,6 +219,7 @@ struct mxs_phy { > > u32 tx_reg_set; > > u32 tx_reg_mask; > > struct regulator *phy_3p0; > > + bool hardware_control_phy2_clk; > > Needn't it. just check MXS_PHY_HARDWARE_CONTROL_PHY2_CLK flag is enough. Okay. > > > }; > > > > static inline bool is_imx6q_phy(struct mxs_phy *mxs_phy) > > @@ -518,12 +532,17 @@ static int mxs_phy_suspend(struct usb_phy *x, int suspend) > > } > > writel(BM_USBPHY_CTRL_CLKGATE, > > x->io_priv + HW_USBPHY_CTRL_SET); > > - clk_disable_unprepare(mxs_phy->clk); > > + if (!(mxs_phy->port_id == 1 && > > + mxs_phy->hardware_control_phy2_clk)) > > + clk_disable_unprepare(mxs_phy->clk); > > } else { > > mxs_phy_clock_switch_delay(); > > - ret = clk_prepare_enable(mxs_phy->clk); > > - if (ret) > > - return ret; > > + if (!(mxs_phy->port_id == 1 && > > + mxs_phy->hardware_control_phy2_clk)) { > > + ret = clk_prepare_enable(mxs_phy->clk); > > + if (ret) > > + return ret; > > + } > > writel(BM_USBPHY_CTRL_CLKGATE, > > x->io_priv + HW_USBPHY_CTRL_CLR); > > writel(0, x->io_priv + HW_USBPHY_PWD); > > @@ -819,6 +838,9 @@ static int mxs_phy_probe(struct platform_device *pdev) > > if (mxs_phy->phy_3p0) > > regulator_set_voltage(mxs_phy->phy_3p0, 3200000, 3200000); > > > > + if (mxs_phy->data->flags & MXS_PHY_HARDWARE_CONTROL_PHY2_CLK) > > + mxs_phy->hardware_control_phy2_clk = true; > > + > > Needn't it. Okay. Will remove this. > > > platform_set_drvdata(pdev, mxs_phy); > > > > device_set_wakeup_capable(&pdev->dev, true); > > -- > > 2.34.1 > >
diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c index 920a32cd094d..42fcc8ad9492 100644 --- a/drivers/usb/phy/phy-mxs-usb.c +++ b/drivers/usb/phy/phy-mxs-usb.c @@ -18,6 +18,7 @@ #include <linux/regmap.h> #include <linux/mfd/syscon.h> #include <linux/iopoll.h> +#include <linux/regulator/consumer.h> #define DRIVER_NAME "mxs_phy" @@ -204,6 +205,7 @@ struct mxs_phy { int port_id; u32 tx_reg_set; u32 tx_reg_mask; + struct regulator *phy_3p0; }; static inline bool is_imx6q_phy(struct mxs_phy *mxs_phy) @@ -288,6 +290,16 @@ static int mxs_phy_hw_init(struct mxs_phy *mxs_phy) if (ret) goto disable_pll; + if (mxs_phy->phy_3p0) { + ret = regulator_enable(mxs_phy->phy_3p0); + if (ret) { + dev_err(mxs_phy->phy.dev, + "Failed to enable 3p0 regulator, ret=%d\n", + ret); + return ret; + } + } + /* Power up the PHY */ writel(0, base + HW_USBPHY_PWD); @@ -448,6 +460,9 @@ static void mxs_phy_shutdown(struct usb_phy *phy) if (is_imx7ulp_phy(mxs_phy)) mxs_phy_pll_enable(phy->io_priv, false); + if (mxs_phy->phy_3p0) + regulator_disable(mxs_phy->phy_3p0); + clk_disable_unprepare(mxs_phy->clk); } @@ -789,6 +804,21 @@ static int mxs_phy_probe(struct platform_device *pdev) mxs_phy->clk = clk; mxs_phy->data = of_device_get_match_data(&pdev->dev); + mxs_phy->phy_3p0 = devm_regulator_get(&pdev->dev, "phy-3p0"); + if (PTR_ERR(mxs_phy->phy_3p0) == -EPROBE_DEFER) { + return -EPROBE_DEFER; + } else if (PTR_ERR(mxs_phy->phy_3p0) == -ENODEV) { + /* not exist */ + mxs_phy->phy_3p0 = NULL; + } else if (IS_ERR(mxs_phy->phy_3p0)) { + dev_err(&pdev->dev, "Getting regulator error: %ld\n", + PTR_ERR(mxs_phy->phy_3p0)); + return PTR_ERR(mxs_phy->phy_3p0); + } + + if (mxs_phy->phy_3p0) + regulator_set_voltage(mxs_phy->phy_3p0, 3200000, 3200000); + platform_set_drvdata(pdev, mxs_phy); device_set_wakeup_capable(&pdev->dev, true);
It is one of PHY's power, and we need to enable it to keep signal quality good, and pass eye diagram test. Signed-off-by: Xu Yang <xu.yang_2@nxp.com> --- drivers/usb/phy/phy-mxs-usb.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)