drivers/usb/roles/intel-xhci-usb-role-switch.c
Source file repositories/reference/linux-study-clean/drivers/usb/roles/intel-xhci-usb-role-switch.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/usb/roles/intel-xhci-usb-role-switch.c- Extension
.c- Size
- 5672 bytes
- Lines
- 228
- 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.
- 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.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/acpi.hlinux/delay.hlinux/err.hlinux/io.hlinux/kernel.hlinux/module.hlinux/platform_device.hlinux/pm_runtime.hlinux/property.hlinux/usb/role.h
Detected Declarations
struct intel_xhci_usb_datafunction intel_xhci_usb_set_rolefunction intel_xhci_usb_get_rolefunction intel_xhci_usb_probefunction intel_xhci_usb_remove
Annotated Snippet
struct intel_xhci_usb_data {
struct device *dev;
struct usb_role_switch *role_sw;
void __iomem *base;
bool enable_sw_switch;
};
static const struct software_node intel_xhci_usb_node = {
"intel-xhci-usb-sw",
};
static int intel_xhci_usb_set_role(struct usb_role_switch *sw,
enum usb_role role)
{
struct intel_xhci_usb_data *data = usb_role_switch_get_drvdata(sw);
unsigned long timeout;
acpi_status status;
u32 glk, val;
u32 drd_config = DRD_CONFIG_DYNAMIC;
/*
* On many CHT devices ACPI event (_AEI) handlers read / modify /
* write the cfg0 register, just like we do. Take the ACPI lock
* to avoid us racing with the AML code.
*/
status = acpi_acquire_global_lock(ACPI_WAIT_FOREVER, &glk);
if (ACPI_FAILURE(status) && status != AE_NOT_CONFIGURED) {
dev_err(data->dev, "Error could not acquire lock\n");
return -EIO;
}
pm_runtime_get_sync(data->dev);
/*
* Set idpin value as requested.
* Since some devices rely on firmware setting DRD_CONFIG and
* SW_SWITCH_EN bits to be zero for role switch,
* do not set these bits for those devices.
*/
val = readl(data->base + DUAL_ROLE_CFG0);
switch (role) {
case USB_ROLE_NONE:
val |= SW_IDPIN;
val &= ~SW_VBUS_VALID;
drd_config = DRD_CONFIG_DYNAMIC;
break;
case USB_ROLE_HOST:
val &= ~SW_IDPIN;
val &= ~SW_VBUS_VALID;
drd_config = DRD_CONFIG_STATIC_HOST;
break;
case USB_ROLE_DEVICE:
val |= SW_IDPIN;
val |= SW_VBUS_VALID;
drd_config = DRD_CONFIG_STATIC_DEVICE;
break;
}
val |= SW_IDPIN_EN;
if (data->enable_sw_switch) {
val &= ~DRD_CONFIG_MASK;
val |= SW_SWITCH_EN | drd_config;
}
writel(val, data->base + DUAL_ROLE_CFG0);
acpi_release_global_lock(glk);
/* In most case it takes about 600ms to finish mode switching */
timeout = jiffies + msecs_to_jiffies(DUAL_ROLE_CFG1_POLL_TIMEOUT);
/* Polling on CFG1 register to confirm mode switch.*/
do {
val = readl(data->base + DUAL_ROLE_CFG1);
if (!!(val & HOST_MODE) == (role == USB_ROLE_HOST)) {
pm_runtime_put(data->dev);
return 0;
}
/* Interval for polling is set to about 5 - 10 ms */
usleep_range(5000, 10000);
} while (time_before(jiffies, timeout));
pm_runtime_put(data->dev);
dev_warn(data->dev, "Timeout waiting for role-switch\n");
return -ETIMEDOUT;
}
static enum usb_role intel_xhci_usb_get_role(struct usb_role_switch *sw)
{
struct intel_xhci_usb_data *data = usb_role_switch_get_drvdata(sw);
Annotation
- Immediate include surface: `linux/acpi.h`, `linux/delay.h`, `linux/err.h`, `linux/io.h`, `linux/kernel.h`, `linux/module.h`, `linux/platform_device.h`, `linux/pm_runtime.h`.
- Detected declarations: `struct intel_xhci_usb_data`, `function intel_xhci_usb_set_role`, `function intel_xhci_usb_get_role`, `function intel_xhci_usb_probe`, `function intel_xhci_usb_remove`.
- Atlas domain: Driver Families / drivers/usb.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.