Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

usb: dwc3-am62: add workaround for Errata i2409

All AM62 devices have Errata i2409 [1] due to which
USB2 PHY may lock up due to short suspend.

Workaround involves setting bit 5 and 4 PLL_REG12
in PHY2 register space after USB controller is brought
out of LPSC reset but before controller initialization.

Handle this workaround.

[1] - https://www.ti.com/lit/er/sprz487d/sprz487d.pdf

Signed-off-by: Roger Quadros <rogerq@kernel.org>
Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
Link: https://lore.kernel.org/r/20240227-for-v6-9-am62-usb-errata-3-0-v4-4-0ada8ddb0767@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Roger Quadros and committed by
Greg Kroah-Hartman
f0b9c578 d78ff375

+18 -1
+18 -1
drivers/usb/dwc3/dwc3-am62.c
··· 101 101 #define PHY_CORE_VOLTAGE_MASK BIT(31) 102 102 #define PHY_PLL_REFCLK_MASK GENMASK(3, 0) 103 103 104 + /* USB PHY2 register offsets */ 105 + #define USB_PHY_PLL_REG12 0x130 106 + #define USB_PHY_PLL_LDO_REF_EN BIT(5) 107 + #define USB_PHY_PLL_LDO_REF_EN_EN BIT(4) 108 + 104 109 #define DWC3_AM62_AUTOSUSPEND_DELAY 100 105 110 106 111 struct dwc3_am62 { ··· 189 184 struct device *dev = &pdev->dev; 190 185 struct device_node *node = pdev->dev.of_node; 191 186 struct dwc3_am62 *am62; 192 - int i, ret; 193 187 unsigned long rate; 188 + void __iomem *phy; 189 + int i, ret; 194 190 u32 reg; 195 191 196 192 am62 = devm_kzalloc(dev, sizeof(*am62), GFP_KERNEL); ··· 232 226 ret = phy_syscon_pll_refclk(am62); 233 227 if (ret) 234 228 return ret; 229 + 230 + /* Workaround Errata i2409 */ 231 + phy = devm_platform_ioremap_resource(pdev, 1); 232 + if (IS_ERR(phy)) { 233 + dev_err(dev, "can't map PHY IOMEM resource. Won't apply i2409 fix.\n"); 234 + phy = NULL; 235 + } else { 236 + reg = readl(phy + USB_PHY_PLL_REG12); 237 + reg |= USB_PHY_PLL_LDO_REF_EN | USB_PHY_PLL_LDO_REF_EN_EN; 238 + writel(reg, phy + USB_PHY_PLL_REG12); 239 + } 235 240 236 241 /* VBUS divider select */ 237 242 am62->vbus_divider = device_property_read_bool(dev, "ti,vbus-divider");