STRUCT DWC2_HSOTG(9)
πΈ NAME πΈ
struct dwc2_hsotg β bestie, this is the struct. It holds the state of the driver, including the non-periodic and periodic schedules. It's from the Kernel API Manual, section 9 (yes, struct dwc2_hsotg(9), that's the whole vibe) π
β¨ SYNOPSIS β¨
Ok so picture this: one giant struct, and it's giving main character energy. Here's the whole thing, copy-pasted exactly, no cap:
struct dwc2_hsotg {
struct device *dev;
void __iomem *regs;
struct dwc2_hw_params hw_params;
struct dwc2_core_params params;
enum usb_otg_state op_state;
enum usb_dr_mode dr_mode;
struct usb_role_switch *role_sw;
enum usb_dr_mode role_sw_default_mode;
unsigned int hcd_enabled:1;
unsigned int gadget_enabled:1;
unsigned int ll_hw_enabled:1;
unsigned int hibernated:1;
unsigned int in_ppd:1;
bool bus_suspended;
unsigned int reset_phy_on_wake:1;
unsigned int need_phy_for_wake:1;
unsigned int phy_off_for_suspend:1;
u16 frame_number;
struct phy *phy;
struct usb_phy *uphy;
struct dwc2_hsotg_plat *plat;
struct regulator_bulk_data supplies[DWC2_NUM_SUPPLIES];
struct regulator *vbus_supply;
struct regulator *usb33d;
spinlock_t lock;
void *priv;
int irq;
struct clk *clk;
struct clk *utmi_clk;
struct reset_control *reset;
struct reset_control *reset_ecc;
unsigned int queuing_high_bandwidth:1;
unsigned int srp_success:1;
struct workqueue_struct *wq_otg;
struct work_struct wf_otg;
struct timer_list wkp_timer;
enum dwc2_lx_state lx_state;
struct dwc2_gregs_backup gr_backup;
struct dwc2_dregs_backup dr_backup;
struct dwc2_hregs_backup hr_backup;
struct dentry *debug_root;
struct debugfs_regset32 *regset;
bool needs_byte_swap;
#define DWC2_CORE_REV_4_30a 0x4f54430a;
#define DWC2_CORE_REV_2_71a 0x4f54271a;
#define DWC2_CORE_REV_2_72a 0x4f54272a;
#define DWC2_CORE_REV_2_80a 0x4f54280a;
#define DWC2_CORE_REV_2_90a 0x4f54290a;
#define DWC2_CORE_REV_2_91a 0x4f54291a;
#define DWC2_CORE_REV_2_92a 0x4f54292a;
#define DWC2_CORE_REV_2_94a 0x4f54294a;
#define DWC2_CORE_REV_3_00a 0x4f54300a;
#define DWC2_CORE_REV_3_10a 0x4f54310a;
#define DWC2_CORE_REV_4_00a 0x4f54400a;
#define DWC2_CORE_REV_4_20a 0x4f54420a;
#define DWC2_CORE_REV_5_00a 0x4f54500a;
#define DWC2_FS_IOT_REV_1_00a 0x5531100a;
#define DWC2_HS_IOT_REV_1_00a 0x5532100a;
#define DWC2_HS_IOT_REV_5_00a 0x5532500a;
#define DWC2_CORE_REV_MASK 0x0000ffff;
#define DWC2_OTG_ID 0x4f540000;
#define DWC2_FS_IOT_ID 0x55310000;
#define DWC2_HS_IOT_ID 0x55320000;
#define DWC2_RESTORE_DCTL BIT(0);
#define DWC2_RESTORE_DCFG BIT(1);
#if IS_ENABLED(CONFIG_USB_DWC2_HOST) ||
IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE);
union dwc2_hcd_internal_flags {
u32 d32;
struct {
unsigned port_connect_status_change:1;
unsigned port_connect_status:1;
unsigned port_reset_change:1;
unsigned port_enable_change:1;
unsigned port_suspend_change:1;
unsigned port_over_current_change:1;
unsigned port_l1_change:1;
unsigned reserved:25;
} b;
} flags;
struct list_head non_periodic_sched_inactive;
struct list_head non_periodic_sched_waiting;
struct list_head non_periodic_sched_active;
struct list_head *non_periodic_qh_ptr;
struct list_head periodic_sched_inactive;
struct list_head periodic_sched_ready;
struct list_head periodic_sched_assigned;
struct list_head periodic_sched_queued;
struct list_head split_order;
u16 periodic_usecs;
unsigned long hs_periodic_bitmap[BITS_TO_LONGS(
DWC2_HS_SCHEDULE_US)];
u16 periodic_qh_count;
bool new_connection;
u16 last_frame_num;
#ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS;
#define FRAME_NUM_ARRAY_SIZE 1000;
u16 *frame_num_array;
u16 *last_frame_num_array;
int frame_num_idx;
int dumped_frame_num_array;
#endif;
struct list_head free_hc_list;
int periodic_channels;
int non_periodic_channels;
int available_host_channels;
struct dwc2_host_chan *hc_ptr_array[MAX_EPS_CHANNELS];
u8 *status_buf;
dma_addr_t status_buf_dma;
#define DWC2_HCD_STATUS_BUF_SIZE 64;
struct delayed_work start_work;
struct delayed_work reset_work;
struct work_struct phy_reset_work;
u8 otg_port;
u32 *frame_list;
dma_addr_t frame_list_dma;
u32 frame_list_sz;
struct kmem_cache *desc_gen_cache;
struct kmem_cache *desc_hsisoc_cache;
struct kmem_cache *unaligned_cache;
#define DWC2_KMEM_UNALIGNED_BUF_SIZE 1024;
#endif ;
#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) ||
IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE);
struct usb_gadget_driver *driver;
int fifo_mem;
unsigned int dedicated_fifos:1;
unsigned char num_of_eps;
u32 fifo_map;
struct usb_request *ep0_reply;
struct usb_request *ctrl_req;
void *ep0_buff;
void *ctrl_buff;
enum dwc2_ep0_state ep0_state;
unsigned delayed_status : 1;
u8 test_mode;
dma_addr_t setup_desc_dma[2];
struct dwc2_dma_desc *setup_desc[2];
dma_addr_t ctrl_in_desc_dma;
struct dwc2_dma_desc *ctrl_in_desc;
dma_addr_t ctrl_out_desc_dma;
struct dwc2_dma_desc *ctrl_out_desc;
struct usb_gadget gadget;
unsigned int enabled:1;
unsigned int connected:1;
unsigned int remote_wakeup_allowed:1;
struct dwc2_hsotg_ep *eps_in[MAX_EPS_CHANNELS];
struct dwc2_hsotg_ep *eps_out[MAX_EPS_CHANNELS];
#endif ;
};
π MEMBERS π
Ok now the part where we meet everyone individually, like a little cast of characters π«Ά
devβ Thestruct devicepointer. The whole device situation.regsβ Pointer to controller regs. Where the registers live.hw_paramsβ Parameters that were autodetected from the hardware registers β the hardware basically introduced itself β¨paramsβ Parameters that define how the core should be configured.op_stateβ The operational State. During transitions (a_host=>a_peripheral and b_device=>b_host) this may not match the core, but it allows the software to determine transitions. It's giving "trust me, I know where we're going" energy.dr_modeβ Requested mode of operation, one of following:USB_DR_MODE_PERIPHERALUSB_DR_MODE_HOSTUSB_DR_MODE_OTG
role_swβusb_role_switchhandle.role_sw_default_modeβ default operation mode of controller while usb role isUSB_ROLE_NONE.hcd_enabledβ Host mode sub-driver initialization indicator.gadget_enabledβ Peripheral mode sub-driver initialization indicator.ll_hw_enabledβ Status of low-level hardware resources.hibernatedβ True if core is hibernated π΄in_ppdβ True if core is partial power down mode.bus_suspendedβ True if bus is suspended.reset_phy_on_wakeβ Quirk saying that we should assert PHY reset on a remote wakeup.need_phy_for_wakeβ Quirk saying that we should keep the PHY on at suspend if we need USB to wake us up.phy_off_for_suspendβ Status of whether we turned the PHY off at suspend.frame_numberβ Frame number read from the core. For both device and host modes. The value ranges are from0toHFNUM_MAX_FRNUM.phyβ The otg phy transceiver structure for phy control.uphyβ The otg phy transceiver structure for old USB phy control.platβ The platform specific configuration data. This can be removed once all SoCs support usb transceiver.suppliesβ Definition of USB power supplies.vbus_supplyβ Regulator supplying vbus.usb33dβ Optional 3.3v regulator used on some stm32 devices to supply ID and VBUS detection hardware.lockβ Spinlock that protects all the driver data structures. Do not mess with it, fr fr πprivβ Stores a pointer to thestruct usb_hcd.irqβ Interrupt request line number.clkβ Pointer to otg clock.utmi_clkβ Pointer toutmi_clkclock.resetβ Pointer to dwc2 reset controller.reset_eccβ Pointer to dwc2 optional reset controller in Stratix10.queuing_high_bandwidthβ True if multiple packets of a high-bandwidth transfer are in process of being queued.srp_successβ Stores status of SRP request in the case of a FS PHY with an I2C interface.wq_otgβ Workqueue object used for handling of some interrupts.wf_otgβ Work object for handling Connector ID Status Change interrupt.wkp_timerβ Timer object for handling Wakeup Detected interrupt.lx_stateβ Lx state of connected device.gr_backupβ Backup of global registers during suspend.dr_backupβ Backup of device registers during suspend.hr_backupβ Backup of host registers during suspend.debug_rootβ Root directrory for debugfs.regsetβ A pointer to astruct debugfs_regset32, which contains a pointer to an array of register definitions, the array size and the base address where the register bank is to be found.needs_byte_swapβ Specifies whether the opposite endianness.flagsβ Flags for handling root port state changes.flags.d32β Contain all root port flags.flags.bβ Separate root port flags from each other.flags.b.port_connect_status_changeβ True if root port connect status changed.flags.b.port_connect_statusβ True if device connected to root port.flags.b.port_reset_changeβ True if root port reset status changed.flags.b.port_enable_changeβ True if root port enable status changed.flags.b.port_suspend_changeβ True if root port suspend status changed.flags.b.port_over_current_changeβ True if root port over current state changed.flags.b.port_l1_changeβ True if root port l1 status changed.flags.b.reservedβ Reserved bits of root port register.non_periodic_sched_inactiveβ Inactive QHs in the non-periodic schedule. Transfers associated with these QHs are not currently assigned to a host channel.non_periodic_sched_waitingβ Waiting QHs in the non-periodic schedule. Transfers associated with these QHs are not currently assigned to a host channel.non_periodic_sched_activeβ Active QHs in the non-periodic schedule. Transfers associated with these QHs are currently assigned to a host channel.non_periodic_qh_ptrβ pointer to the next QH to process in the active non-periodic schedule. your little bookmark in the non-periodic queue πperiodic_sched_inactiveβ the inactive QHs in the periodic schedule, aka a list of QHs for periodic transfers that are not scheduled for the next frame. every QH in this list has an interval counter that decides when it needs to get scheduled for execution. and yeah, this whole scheduling mechanism only allows a simple calculation for the periodic bandwidth used (i.e. you must assume that all periodic transfers may need to execute in the same frame). but like β it greatly simplifies scheduling and should be sufficient for the vast majority of OTG hosts, which only need to connect to a small number of peripherals at one time. items move from this list toperiodic_sched_readywhen the QH interval counter is0at SOF. π«periodic_sched_readyβ list of periodic QHs that are ready for execution in the next frame but haven't been assigned to host channels yet. items move from this list toperiodic_sched_assignedas host channels become available during the current frame. they're literally just waiting for their turn π«Άperiodic_sched_assignedβ list of periodic QHs to be executed in the next frame that are assigned to host channels. items move from this list toperiodic_sched_queuedas the transactions for the QH get queued to theDWC_otgcontroller. glow-up complete β¨periodic_sched_queuedβ list of periodic QHs that have been queued for execution. items move from this list to eitherperiodic_sched_inactiveorperiodic_sched_readywhen the channel associated with the transfer is released. if the interval for the QH is1, the item moves toperiodic_sched_readybecause it must be rescheduled for the next frame. otherwise, the item moves toperiodic_sched_inactive. no cap, those are the only two destinations πsplit_orderβ list keeping track of channels doing splits, in order.periodic_usecsβ total bandwidth claimed so far for periodic transfers. this value is in microseconds per (micro)frame. the assumption here is that all periodic transfers may occur in the same (micro)frame. π₯hs_periodic_bitmapβ bitmap used by the microframe scheduler any time the host is in high speed mode; low speed schedules are stored elsewhere since we need one per TT.periodic_qh_countβ count of periodic QHs, if using several eps. used for SOF enable/disable.new_connectionβ used in host mode.Trueif there are new connected device. new friend detected π¦last_frame_numβ number of last frame. range from0to32768.frame_num_arrayβ used only ifCONFIG_USB_DWC2_TRACK_MISSED_SOFSis defined, for missed SOFs tracking. array holds that frame numbers, which not equal tolast_frame_num +1. (yes i'm quoting it exactly, bestie, the grammar is not the vibe but the facts are sacred π)last_frame_num_arrayβ used only ifCONFIG_USB_DWC2_TRACK_MISSED_SOFSis defined, for missed SOFs tracking. ifcurrent_frame_number != last_frame_num+1thenlast_frame_numadded to this array.frame_num_idxβ actual size offrame_num_arrayandlast_frame_num_array.dumped_frame_num_arrayβ1β if missed SOFs frame numbersdumbed;0β if missed SOFs frame numbers notdumbed. π (their spelling, not mine, i love them for it)free_hc_listβ free host channels in the controller. this is a list ofstruct dwc2_host_chanitems.periodic_channelsβ number of host channels assigned to periodic transfers. currently assuming that there is a dedicated host channel for each periodic transaction and at least one host channel is available for non-periodic transactions.non_periodic_channelsβ number of host channels assigned to non-periodic transfers.available_host_channelsβ number of host channels available for the microframe scheduler to use.hc_ptr_arrayβ array of pointers to the host channel descriptors. lets you access a host channel descriptor given the host channel number. this is useful in interrupt handlers. genuinely iconic for that πstatus_bufβ buffer used for data received during the status phase of a control transfer.status_buf_dmaβ DMA address forstatus_buf.start_workβ delayed work for handling host A-cable connection.reset_workβ delayed work for handling a port reset.phy_reset_workβ work structure for doing a PHY reset.otg_portβ OTG port number.frame_listβ frame list.frame_list_dmaβ frame list DMA address.frame_list_szβ frame list size.desc_gen_cacheβ kmem cache for generic descriptors.desc_hsisoc_cacheβ kmem cache for hs isochronous descriptors.unaligned_cacheβ kmem cache for DMA mode to handle non-aligned buf.driverβ USB gadget driver.fifo_memβ total internal RAM for FIFOs (bytes).dedicated_fifosβ set if the hardware has dedicated IN-EP fifos.num_of_epsβ number of available EPs (excluding EP0).fifo_mapβ each bit intend for concrete fifo. if that bit is set, then that fifo is used.ep0_replyβ request used for ep0 reply.ctrl_reqβ request for EP0 control packets.ep0_buffβ buffer for EP0 reply data, if needed.ctrl_buffβ buffer for EP0 control requests.ep0_stateβ EP0 control transfers state.delayed_statusβtruewhen gadget driver asks for delayed status.test_modeβ USB test mode requested by the host.setup_desc_dmaβ EP0 setup stage desc chain DMA address.setup_descβ EP0 setup stage desc chain pointer.ctrl_in_desc_dmaβ EP0 IN data phase desc chain DMA address.ctrl_in_descβ EP0 IN data phase desc chain pointer.ctrl_out_desc_dmaβ EP0 OUT data phase desc chain DMA address.ctrl_out_descβ EP0 OUT data phase desc chain pointer.gadgetβ represents a usb gadget device.enabledβ indicates the enabling state of controller.connectedβ used in slave mode.Trueif device connected with host.remote_wakeup_allowedβTrueif device is allowed to wake-up host by remote-wakeup signalling.eps_inβ the IN endpoints being supplied to the gadget framework.eps_outβ the OUT endpoints being supplied to the gadget framework.
π DESCRIPTION π
okay so the page literally buckets everything into three groups, and here they are, word for word, no extra lore added by me:
- these are common for both host and peripheral modes:
- these are for host mode:
- these are for peripheral mode:
and that's genuinely all it says β the buckets are empty in this listing, so don't come for me, i'm just the messenger π
π¦ SEE ALSO π¦
kernel file ./drivers/usb/dwc2/core.h
struct dwc2_hsotg_ep(9)struct dwc2_hsotg_req(9)struct dwc2_core_params(9)struct dwc2_hw_params(9)struct dwc2_gregs_backup(9)struct dwc2_dregs_backup(9)struct dwc2_hregs_backup(9)
go read them, they're all in the same friend group fr fr β¨
πΈ and that's a wrap on struct dwc2_hsotg(9)! this cutie lives in ./drivers/usb/dwc2, dated October 2026 β main character energy from the future, we love to see it. mwah, go touch some USB π
π
π¦ where this page comes from
- nixpkgs unstable: linux-manual 7.3.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms