drivers/usb/dwc3/dwc3-am62.c

Source file repositories/reference/linux-study-clean/drivers/usb/dwc3/dwc3-am62.c

File Facts

System
Linux kernel
Corpus path
drivers/usb/dwc3/dwc3-am62.c
Extension
.c
Size
10919 bytes
Lines
415
Domain
Driver Families
Bucket
drivers/usb
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct dwc3_am62 {
	struct device *dev;
	void __iomem *usbss;
	struct clk *usb2_refclk;
	int rate_code;
	struct regmap *syscon;
	unsigned int offset;
	unsigned int vbus_divider;
	u32 wakeup_stat;
	void __iomem *phy_regs;
};

static const int dwc3_ti_rate_table[] = {	/* in KHZ */
	9600,
	10000,
	12000,
	19200,
	20000,
	24000,
	25000,
	26000,
	38400,
	40000,
	58000,
	50000,
	52000,
};

static inline u32 dwc3_ti_readl(struct dwc3_am62 *am62, u32 offset)
{
	return readl((am62->usbss) + offset);
}

static inline void dwc3_ti_writel(struct dwc3_am62 *am62, u32 offset, u32 value)
{
	writel(value, (am62->usbss) + offset);
}

static int phy_syscon_pll_refclk(struct dwc3_am62 *am62)
{
	struct device *dev = am62->dev;
	struct device_node *node = dev->of_node;
	struct regmap *syscon;
	int ret;

	syscon = syscon_regmap_lookup_by_phandle_args(node, "ti,syscon-phy-pll-refclk",
						      1, &am62->offset);
	if (IS_ERR(syscon)) {
		dev_err(dev, "unable to get ti,syscon-phy-pll-refclk regmap\n");
		return PTR_ERR(syscon);
	}

	am62->syscon = syscon;

	/* Core voltage. PHY_CORE_VOLTAGE bit Recommended to be 0 always */
	ret = regmap_update_bits(am62->syscon, am62->offset, PHY_CORE_VOLTAGE_MASK, 0);
	if (ret) {
		dev_err(dev, "failed to set phy core voltage\n");
		return ret;
	}

	ret = regmap_update_bits(am62->syscon, am62->offset, PHY_PLL_REFCLK_MASK, am62->rate_code);
	if (ret) {
		dev_err(dev, "failed to set phy pll reference clock rate\n");
		return ret;
	}

	return 0;
}

static int dwc3_ti_init(struct dwc3_am62 *am62)
{
	int ret;
	u32 reg;

	/* Read the syscon property and set the rate code */
	ret = phy_syscon_pll_refclk(am62);
	if (ret)
		return ret;

	/* Workaround Errata i2409 */
	if (am62->phy_regs) {
		reg = readl(am62->phy_regs + USB_PHY_PLL_REG12);
		reg |= USB_PHY_PLL_LDO_REF_EN | USB_PHY_PLL_LDO_REF_EN_EN;
		writel(reg, am62->phy_regs + USB_PHY_PLL_REG12);
	}

	/* VBUS divider select */
	reg = dwc3_ti_readl(am62, USBSS_PHY_CONFIG);
	if (am62->vbus_divider)

Annotation

Implementation Notes