drivers/usb/dwc3/dwc3-rtk.c

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

File Facts

System
Linux kernel
Corpus path
drivers/usb/dwc3/dwc3-rtk.c
Extension
.c
Size
11059 bytes
Lines
460
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_rtk {
	struct device *dev;
	void __iomem *regs;
	size_t regs_size;
	void __iomem *pm_base;

	struct dwc3 *dwc;

	enum usb_role cur_role;
	struct usb_role_switch *role_switch;
};

static void switch_usb2_role(struct dwc3_rtk *rtk, enum usb_role role)
{
	void __iomem *reg;
	int val;

	reg = rtk->regs + WRAP_USB2_PHY_REG;
	val = ~USB2_PHY_SWITCH_MASK & readl(reg);

	switch (role) {
	case USB_ROLE_DEVICE:
		writel(USB2_PHY_SWITCH_DEVICE | val, reg);
		break;
	case USB_ROLE_HOST:
		writel(USB2_PHY_SWITCH_HOST | val, reg);
		break;
	default:
		dev_dbg(rtk->dev, "%s: role=%d\n", __func__, role);
		break;
	}
}

static void switch_dwc3_role(struct dwc3_rtk *rtk, enum usb_role role)
{
	if (!rtk->dwc->role_sw)
		return;

	usb_role_switch_set_role(rtk->dwc->role_sw, role);
}

static enum usb_role dwc3_rtk_get_role(struct dwc3_rtk *rtk)
{
	enum usb_role role;

	role = rtk->cur_role;

	if (rtk->dwc && rtk->dwc->role_sw)
		role = usb_role_switch_get_role(rtk->dwc->role_sw);
	else
		dev_dbg(rtk->dev, "%s not usb_role_switch role=%d\n", __func__, role);

	return role;
}

static void dwc3_rtk_set_role(struct dwc3_rtk *rtk, enum usb_role role)
{
	rtk->cur_role = role;

	switch_dwc3_role(rtk, role);
	mdelay(10);
	switch_usb2_role(rtk, role);
}

#if IS_ENABLED(CONFIG_USB_ROLE_SWITCH)
static int dwc3_usb_role_switch_set(struct usb_role_switch *sw, enum usb_role role)
{
	struct dwc3_rtk *rtk = usb_role_switch_get_drvdata(sw);

	dwc3_rtk_set_role(rtk, role);

	return 0;
}

static enum usb_role dwc3_usb_role_switch_get(struct usb_role_switch *sw)
{
	struct dwc3_rtk *rtk = usb_role_switch_get_drvdata(sw);

	return dwc3_rtk_get_role(rtk);
}

static int dwc3_rtk_setup_role_switch(struct dwc3_rtk *rtk)
{
	struct usb_role_switch_desc dwc3_role_switch = {NULL};

	dwc3_role_switch.name = dev_name(rtk->dev);
	dwc3_role_switch.driver_data = rtk;
	dwc3_role_switch.allow_userspace_control = true;
	dwc3_role_switch.fwnode = dev_fwnode(rtk->dev);
	dwc3_role_switch.set = dwc3_usb_role_switch_set;

Annotation

Implementation Notes