usb: dwc3: add power down scale setting
Some SoC(e.g NXP imx8MQ) may have a wrong default power down scale setting so need init it to be the correct value, the power down scale setting description in DWC3 databook: Power Down Scale (PwrDnScale) The USB3 suspend_clk input replaces pipe3_rx_pclk as a clock source to a small part of the USB3 core that operates when the SS PHY is in its lowest power (P3) state, and therefore does not provide a clock. The Power Down Scale field specifies how many suspend_clk periods fit into a 16 kHz clock period. When performing the division, round up the remainder. For example, when using an 8-bit/16-bit/32-bit PHY and 25-MHz Suspend clock, Power Down Scale = 25000 kHz/16 kHz = 13'd1563 (rounder up) So use the suspend clock rate to calculate it. Reviewed-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com> Signed-off-by: Li Jun <jun.li@nxp.com> Link: https://lore.kernel.org/r/1654568404-3461-1-git-send-email-jun.li@nxp.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
8659ab3d93
commit
3497b9a5c8
|
@ -1029,6 +1029,37 @@ static void dwc3_set_incr_burst_type(struct dwc3 *dwc)
|
|||
dwc3_writel(dwc->regs, DWC3_GSBUSCFG0, cfg);
|
||||
}
|
||||
|
||||
static void dwc3_set_power_down_clk_scale(struct dwc3 *dwc)
|
||||
{
|
||||
u32 scale;
|
||||
u32 reg;
|
||||
|
||||
if (!dwc->susp_clk)
|
||||
return;
|
||||
|
||||
/*
|
||||
* The power down scale field specifies how many suspend_clk
|
||||
* periods fit into a 16KHz clock period. When performing
|
||||
* the division, round up the remainder.
|
||||
*
|
||||
* The power down scale value is calculated using the fastest
|
||||
* frequency of the suspend_clk. If it isn't fixed (but within
|
||||
* the accuracy requirement), the driver may not know the max
|
||||
* rate of the suspend_clk, so only update the power down scale
|
||||
* if the default is less than the calculated value from
|
||||
* clk_get_rate() or if the default is questionably high
|
||||
* (3x or more) to be within the requirement.
|
||||
*/
|
||||
scale = DIV_ROUND_UP(clk_get_rate(dwc->susp_clk), 16000);
|
||||
reg = dwc3_readl(dwc->regs, DWC3_GCTL);
|
||||
if ((reg & DWC3_GCTL_PWRDNSCALE_MASK) < DWC3_GCTL_PWRDNSCALE(scale) ||
|
||||
(reg & DWC3_GCTL_PWRDNSCALE_MASK) > DWC3_GCTL_PWRDNSCALE(scale*3)) {
|
||||
reg &= ~(DWC3_GCTL_PWRDNSCALE_MASK);
|
||||
reg |= DWC3_GCTL_PWRDNSCALE(scale);
|
||||
dwc3_writel(dwc->regs, DWC3_GCTL, reg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dwc3_core_init - Low-level initialization of DWC3 Core
|
||||
* @dwc: Pointer to our controller context structure
|
||||
|
@ -1105,6 +1136,9 @@ static int dwc3_core_init(struct dwc3 *dwc)
|
|||
if (ret)
|
||||
goto err1;
|
||||
|
||||
/* Set power down scale of suspend_clk */
|
||||
dwc3_set_power_down_clk_scale(dwc);
|
||||
|
||||
/* Adjust Frame Length */
|
||||
dwc3_frame_length_adjustment(dwc);
|
||||
|
||||
|
|
|
@ -231,6 +231,7 @@
|
|||
|
||||
/* Global Configuration Register */
|
||||
#define DWC3_GCTL_PWRDNSCALE(n) ((n) << 19)
|
||||
#define DWC3_GCTL_PWRDNSCALE_MASK GENMASK(31, 19)
|
||||
#define DWC3_GCTL_U2RSTECN BIT(16)
|
||||
#define DWC3_GCTL_RAMCLKSEL(x) (((x) & DWC3_GCTL_CLK_MASK) << 6)
|
||||
#define DWC3_GCTL_CLK_BUS (0)
|
||||
|
|
Loading…
Reference in New Issue