// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * hcd.c - DesignWare HS OTG Controller host-mode routines * * Copyright (C) 2004-2013 Synopsys, Inc. */ /* * This file contains the core HCD code, and implements the Linux hc_driver * API */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/spinlock.h> #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/dma-mapping.h> #include <linux/delay.h> #include <linux/io.h> #include <linux/slab.h> #include <linux/usb.h> #include <linux/usb/hcd.h> #include <linux/usb/ch11.h> #include <linux/usb/of.h> #include "core.h" #include "hcd.h" /* * ========================================================================= * Host Core Layer Functions * ========================================================================= */ /** * dwc2_enable_common_interrupts() - Initializes the commmon interrupts, * used in both device and host modes * * @hsotg: Programming view of the DWC_otg controller */ static void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg) { … } static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg) { … } static void dwc2_gusbcfg_init(struct dwc2_hsotg *hsotg) { … } static int dwc2_vbus_supply_init(struct dwc2_hsotg *hsotg) { … } static int dwc2_vbus_supply_exit(struct dwc2_hsotg *hsotg) { … } /** * dwc2_enable_host_interrupts() - Enables the Host mode interrupts * * @hsotg: Programming view of DWC_otg controller */ static void dwc2_enable_host_interrupts(struct dwc2_hsotg *hsotg) { … } /** * dwc2_disable_host_interrupts() - Disables the Host Mode interrupts * * @hsotg: Programming view of DWC_otg controller */ static void dwc2_disable_host_interrupts(struct dwc2_hsotg *hsotg) { … } /* * dwc2_calculate_dynamic_fifo() - Calculates the default fifo size * For system that have a total fifo depth that is smaller than the default * RX + TX fifo size. * * @hsotg: Programming view of DWC_otg controller */ static void dwc2_calculate_dynamic_fifo(struct dwc2_hsotg *hsotg) { … } static void dwc2_config_fifos(struct dwc2_hsotg *hsotg) { … } /** * dwc2_calc_frame_interval() - Calculates the correct frame Interval value for * the HFIR register according to PHY type and speed * * @hsotg: Programming view of DWC_otg controller * * NOTE: The caller can modify the value of the HFIR register only after the * Port Enable bit of the Host Port Control and Status register (HPRT.EnaPort) * has been set */ u32 dwc2_calc_frame_interval(struct dwc2_hsotg *hsotg) { … } /** * dwc2_read_packet() - Reads a packet from the Rx FIFO into the destination * buffer * * @hsotg: Programming view of DWC_otg controller * @dest: Destination buffer for the packet * @bytes: Number of bytes to copy to the destination */ void dwc2_read_packet(struct dwc2_hsotg *hsotg, u8 *dest, u16 bytes) { … } /** * dwc2_dump_channel_info() - Prints the state of a host channel * * @hsotg: Programming view of DWC_otg controller * @chan: Pointer to the channel to dump * * Must be called with interrupt disabled and spinlock held * * NOTE: This function will be removed once the peripheral controller code * is integrated and the driver is stable */ static void dwc2_dump_channel_info(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) { … } static int _dwc2_hcd_start(struct usb_hcd *hcd); static void dwc2_host_start(struct dwc2_hsotg *hsotg) { … } static void dwc2_host_disconnect(struct dwc2_hsotg *hsotg) { … } static void dwc2_host_hub_info(struct dwc2_hsotg *hsotg, void *context, int *hub_addr, int *hub_port) { … } /* * ========================================================================= * Low Level Host Channel Access Functions * ========================================================================= */ static void dwc2_hc_enable_slave_ints(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) { … } static void dwc2_hc_enable_dma_ints(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) { … } static void dwc2_hc_enable_ints(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) { … } /** * dwc2_hc_init() - Prepares a host channel for transferring packets to/from * a specific endpoint * * @hsotg: Programming view of DWC_otg controller * @chan: Information needed to initialize the host channel * * The HCCHARn register is set up with the characteristics specified in chan. * Host channel interrupts that may need to be serviced while this transfer is * in progress are enabled. */ static void dwc2_hc_init(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) { … } /** * dwc2_hc_halt() - Attempts to halt a host channel * * @hsotg: Controller register interface * @chan: Host channel to halt * @halt_status: Reason for halting the channel * * This function should only be called in Slave mode or to abort a transfer in * either Slave mode or DMA mode. Under normal circumstances in DMA mode, the * controller halts the channel when the transfer is complete or a condition * occurs that requires application intervention. * * In slave mode, checks for a free request queue entry, then sets the Channel * Enable and Channel Disable bits of the Host Channel Characteristics * register of the specified channel to intiate the halt. If there is no free * request queue entry, sets only the Channel Disable bit of the HCCHARn * register to flush requests for this channel. In the latter case, sets a * flag to indicate that the host channel needs to be halted when a request * queue slot is open. * * In DMA mode, always sets the Channel Enable and Channel Disable bits of the * HCCHARn register. The controller ensures there is space in the request * queue before submitting the halt request. * * Some time may elapse before the core flushes any posted requests for this * host channel and halts. The Channel Halted interrupt handler completes the * deactivation of the host channel. */ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, enum dwc2_halt_status halt_status) { … } /** * dwc2_hc_cleanup() - Clears the transfer state for a host channel * * @hsotg: Programming view of DWC_otg controller * @chan: Identifies the host channel to clean up * * This function is normally called after a transfer is done and the host * channel is being released */ void dwc2_hc_cleanup(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) { … } /** * dwc2_hc_set_even_odd_frame() - Sets the channel property that indicates in * which frame a periodic transfer should occur * * @hsotg: Programming view of DWC_otg controller * @chan: Identifies the host channel to set up and its properties * @hcchar: Current value of the HCCHAR register for the specified host channel * * This function has no effect on non-periodic transfers */ static void dwc2_hc_set_even_odd_frame(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, u32 *hcchar) { … } static void dwc2_set_pid_isoc(struct dwc2_host_chan *chan) { … } /** * dwc2_hc_write_packet() - Writes a packet into the Tx FIFO associated with * the Host Channel * * @hsotg: Programming view of DWC_otg controller * @chan: Information needed to initialize the host channel * * This function should only be called in Slave mode. For a channel associated * with a non-periodic EP, the non-periodic Tx FIFO is written. For a channel * associated with a periodic EP, the periodic Tx FIFO is written. * * Upon return the xfer_buf and xfer_count fields in chan are incremented by * the number of bytes written to the Tx FIFO. */ static void dwc2_hc_write_packet(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) { … } /** * dwc2_hc_do_ping() - Starts a PING transfer * * @hsotg: Programming view of DWC_otg controller * @chan: Information needed to initialize the host channel * * This function should only be called in Slave mode. The Do Ping bit is set in * the HCTSIZ register, then the channel is enabled. */ static void dwc2_hc_do_ping(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) { … } /** * dwc2_hc_start_transfer() - Does the setup for a data transfer for a host * channel and starts the transfer * * @hsotg: Programming view of DWC_otg controller * @chan: Information needed to initialize the host channel. The xfer_len value * may be reduced to accommodate the max widths of the XferSize and * PktCnt fields in the HCTSIZn register. The multi_count value may be * changed to reflect the final xfer_len value. * * This function may be called in either Slave mode or DMA mode. In Slave mode, * the caller must ensure that there is sufficient space in the request queue * and Tx Data FIFO. * * For an OUT transfer in Slave mode, it loads a data packet into the * appropriate FIFO. If necessary, additional data packets are loaded in the * Host ISR. * * For an IN transfer in Slave mode, a data packet is requested. The data * packets are unloaded from the Rx FIFO in the Host ISR. If necessary, * additional data packets are requested in the Host ISR. * * For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ * register along with a packet count of 1 and the channel is enabled. This * causes a single PING transaction to occur. Other fields in HCTSIZ are * simply set to 0 since no data transfer occurs in this case. * * For a PING transfer in DMA mode, the HCTSIZ register is initialized with * all the information required to perform the subsequent data transfer. In * addition, the Do Ping bit is set in the HCTSIZ register. In this case, the * controller performs the entire PING protocol, then starts the data * transfer. */ static void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) { … } /** * dwc2_hc_start_transfer_ddma() - Does the setup for a data transfer for a * host channel and starts the transfer in Descriptor DMA mode * * @hsotg: Programming view of DWC_otg controller * @chan: Information needed to initialize the host channel * * Initializes HCTSIZ register. For a PING transfer the Do Ping bit is set. * Sets PID and NTD values. For periodic transfers initializes SCHED_INFO field * with micro-frame bitmap. * * Initializes HCDMA register with descriptor list address and CTD value then * starts the transfer via enabling the channel. */ void dwc2_hc_start_transfer_ddma(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) { … } /** * dwc2_hc_continue_transfer() - Continues a data transfer that was started by * a previous call to dwc2_hc_start_transfer() * * @hsotg: Programming view of DWC_otg controller * @chan: Information needed to initialize the host channel * * The caller must ensure there is sufficient space in the request queue and Tx * Data FIFO. This function should only be called in Slave mode. In DMA mode, * the controller acts autonomously to complete transfers programmed to a host * channel. * * For an OUT transfer, a new data packet is loaded into the appropriate FIFO * if there is any data remaining to be queued. For an IN transfer, another * data packet is always requested. For the SETUP phase of a control transfer, * this function does nothing. * * Return: 1 if a new request is queued, 0 if no more requests are required * for this transfer */ static int dwc2_hc_continue_transfer(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) { … } /* * ========================================================================= * HCD * ========================================================================= */ /* * Processes all the URBs in a single list of QHs. Completes them with * -ETIMEDOUT and frees the QTD. * * Must be called with interrupt disabled and spinlock held */ static void dwc2_kill_urbs_in_qh_list(struct dwc2_hsotg *hsotg, struct list_head *qh_list) { … } static void dwc2_qh_list_free(struct dwc2_hsotg *hsotg, struct list_head *qh_list) { … } /* * Responds with an error status of -ETIMEDOUT to all URBs in the non-periodic * and periodic schedules. The QTD associated with each URB is removed from * the schedule and freed. This function may be called when a disconnect is * detected or when the HCD is being stopped. * * Must be called with interrupt disabled and spinlock held */ static void dwc2_kill_all_urbs(struct dwc2_hsotg *hsotg) { … } /** * dwc2_hcd_start() - Starts the HCD when switching to Host mode * * @hsotg: Pointer to struct dwc2_hsotg */ void dwc2_hcd_start(struct dwc2_hsotg *hsotg) { … } /* Must be called with interrupt disabled and spinlock held */ static void dwc2_hcd_cleanup_channels(struct dwc2_hsotg *hsotg) { … } /** * dwc2_hcd_connect() - Handles connect of the HCD * * @hsotg: Pointer to struct dwc2_hsotg * * Must be called with interrupt disabled and spinlock held */ void dwc2_hcd_connect(struct dwc2_hsotg *hsotg) { … } /** * dwc2_hcd_disconnect() - Handles disconnect of the HCD * * @hsotg: Pointer to struct dwc2_hsotg * @force: If true, we won't try to reconnect even if we see device connected. * * Must be called with interrupt disabled and spinlock held */ void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg, bool force) { … } /** * dwc2_hcd_rem_wakeup() - Handles Remote Wakeup * * @hsotg: Pointer to struct dwc2_hsotg */ static void dwc2_hcd_rem_wakeup(struct dwc2_hsotg *hsotg) { … } /** * dwc2_hcd_stop() - Halts the DWC_otg host mode operations in a clean manner * * @hsotg: Pointer to struct dwc2_hsotg * * Must be called with interrupt disabled and spinlock held */ void dwc2_hcd_stop(struct dwc2_hsotg *hsotg) { … } /* Caller must hold driver lock */ static int dwc2_hcd_urb_enqueue(struct dwc2_hsotg *hsotg, struct dwc2_hcd_urb *urb, struct dwc2_qh *qh, struct dwc2_qtd *qtd) { … } /* Must be called with interrupt disabled and spinlock held */ static int dwc2_hcd_urb_dequeue(struct dwc2_hsotg *hsotg, struct dwc2_hcd_urb *urb) { … } /* Must NOT be called with interrupt disabled or spinlock held */ static int dwc2_hcd_endpoint_disable(struct dwc2_hsotg *hsotg, struct usb_host_endpoint *ep, int retry) { … } /* Must be called with interrupt disabled and spinlock held */ static int dwc2_hcd_endpoint_reset(struct dwc2_hsotg *hsotg, struct usb_host_endpoint *ep) { … } /** * dwc2_core_init() - Initializes the DWC_otg controller registers and * prepares the core for device mode or host mode operation * * @hsotg: Programming view of the DWC_otg controller * @initial_setup: If true then this is the first init for this instance. */ int dwc2_core_init(struct dwc2_hsotg *hsotg, bool initial_setup) { … } /** * dwc2_core_host_init() - Initializes the DWC_otg controller registers for * Host mode * * @hsotg: Programming view of DWC_otg controller * * This function flushes the Tx and Rx FIFOs and flushes any entries in the * request queues. Host channels are reset to ensure that they are ready for * performing transfers. */ static void dwc2_core_host_init(struct dwc2_hsotg *hsotg) { … } /* * Initializes dynamic portions of the DWC_otg HCD state * * Must be called with interrupt disabled and spinlock held */ static void dwc2_hcd_reinit(struct dwc2_hsotg *hsotg) { … } static void dwc2_hc_init_split(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb) { … } static void dwc2_hc_init_xfer(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, struct dwc2_qtd *qtd) { … } static int dwc2_alloc_split_dma_aligned_buf(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, struct dwc2_host_chan *chan) { … } #define DWC2_USB_DMA_ALIGN … static void dwc2_free_dma_aligned_buffer(struct urb *urb) { … } static int dwc2_alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags) { … } static int dwc2_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) { … } static void dwc2_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) { … } /** * dwc2_assign_and_init_hc() - Assigns transactions from a QTD to a free host * channel and initializes the host channel to perform the transactions. The * host channel is removed from the free list. * * @hsotg: The HCD state structure * @qh: Transactions from the first QTD for this QH are selected and assigned * to a free host channel */ static int dwc2_assign_and_init_hc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) { … } /** * dwc2_hcd_select_transactions() - Selects transactions from the HCD transfer * schedule and assigns them to available host channels. Called from the HCD * interrupt handler functions. * * @hsotg: The HCD state structure * * Return: The types of new transactions that were assigned to host channels */ enum dwc2_transaction_type dwc2_hcd_select_transactions( struct dwc2_hsotg *hsotg) { … } /** * dwc2_queue_transaction() - Attempts to queue a single transaction request for * a host channel associated with either a periodic or non-periodic transfer * * @hsotg: The HCD state structure * @chan: Host channel descriptor associated with either a periodic or * non-periodic transfer * @fifo_dwords_avail: Number of DWORDs available in the periodic Tx FIFO * for periodic transfers or the non-periodic Tx FIFO * for non-periodic transfers * * Return: 1 if a request is queued and more requests may be needed to * complete the transfer, 0 if no more requests are required for this * transfer, -1 if there is insufficient space in the Tx FIFO * * This function assumes that there is space available in the appropriate * request queue. For an OUT transfer or SETUP transaction in Slave mode, * it checks whether space is available in the appropriate Tx FIFO. * * Must be called with interrupt disabled and spinlock held */ static int dwc2_queue_transaction(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan, u16 fifo_dwords_avail) { … } /* * Processes periodic channels for the next frame and queues transactions for * these channels to the DWC_otg controller. After queueing transactions, the * Periodic Tx FIFO Empty interrupt is enabled if there are more transactions * to queue as Periodic Tx FIFO or request queue space becomes available. * Otherwise, the Periodic Tx FIFO Empty interrupt is disabled. * * Must be called with interrupt disabled and spinlock held */ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg) { … } /* * Processes active non-periodic channels and queues transactions for these * channels to the DWC_otg controller. After queueing transactions, the NP Tx * FIFO Empty interrupt is enabled if there are more transactions to queue as * NP Tx FIFO or request queue space becomes available. Otherwise, the NP Tx * FIFO Empty interrupt is disabled. * * Must be called with interrupt disabled and spinlock held */ static void dwc2_process_non_periodic_channels(struct dwc2_hsotg *hsotg) { … } /** * dwc2_hcd_queue_transactions() - Processes the currently active host channels * and queues transactions for these channels to the DWC_otg controller. Called * from the HCD interrupt handler functions. * * @hsotg: The HCD state structure * @tr_type: The type(s) of transactions to queue (non-periodic, periodic, * or both) * * Must be called with interrupt disabled and spinlock held */ void dwc2_hcd_queue_transactions(struct dwc2_hsotg *hsotg, enum dwc2_transaction_type tr_type) { … } static void dwc2_conn_id_status_change(struct work_struct *work) { … } static void dwc2_wakeup_detected(struct timer_list *t) { … } static int dwc2_host_is_b_hnp_enabled(struct dwc2_hsotg *hsotg) { … } /** * dwc2_port_suspend() - Put controller in suspend mode for host. * * @hsotg: Programming view of the DWC_otg controller * @windex: The control request wIndex field * * Return: non-zero if failed to enter suspend mode for host. * * This function is for entering Host mode suspend. * Must NOT be called with interrupt disabled or spinlock held. */ int dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex) { … } /** * dwc2_port_resume() - Exit controller from suspend mode for host. * * @hsotg: Programming view of the DWC_otg controller * * Return: non-zero if failed to exit suspend mode for host. * * This function is for exiting Host mode suspend. * Must NOT be called with interrupt disabled or spinlock held. */ int dwc2_port_resume(struct dwc2_hsotg *hsotg) { … } /* Handles hub class-specific requests */ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, u16 wvalue, u16 windex, char *buf, u16 wlength) { … } static int dwc2_hcd_is_status_changed(struct dwc2_hsotg *hsotg, int port) { … } int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg) { … } int dwc2_hcd_get_future_frame_number(struct dwc2_hsotg *hsotg, int us) { … } int dwc2_hcd_is_b_host(struct dwc2_hsotg *hsotg) { … } static struct dwc2_hcd_urb *dwc2_hcd_urb_alloc(struct dwc2_hsotg *hsotg, int iso_desc_count, gfp_t mem_flags) { … } static void dwc2_hcd_urb_set_pipeinfo(struct dwc2_hsotg *hsotg, struct dwc2_hcd_urb *urb, u8 dev_addr, u8 ep_num, u8 ep_type, u8 ep_dir, u16 maxp, u16 maxp_mult) { … } /* * NOTE: This function will be removed once the peripheral controller code * is integrated and the driver is stable */ void dwc2_hcd_dump_state(struct dwc2_hsotg *hsotg) { … } struct wrapper_priv_data { … }; /* Gets the dwc2_hsotg from a usb_hcd */ static struct dwc2_hsotg *dwc2_hcd_to_hsotg(struct usb_hcd *hcd) { … } /** * dwc2_host_get_tt_info() - Get the dwc2_tt associated with context * * This will get the dwc2_tt structure (and ttport) associated with the given * context (which is really just a struct urb pointer). * * The first time this is called for a given TT we allocate memory for our * structure. When everyone is done and has called dwc2_host_put_tt_info() * then the refcount for the structure will go to 0 and we'll free it. * * @hsotg: The HCD state structure for the DWC OTG controller. * @context: The priv pointer from a struct dwc2_hcd_urb. * @mem_flags: Flags for allocating memory. * @ttport: We'll return this device's port number here. That's used to * reference into the bitmap if we're on a multi_tt hub. * * Return: a pointer to a struct dwc2_tt. Don't forget to call * dwc2_host_put_tt_info()! Returns NULL upon memory alloc failure. */ struct dwc2_tt *dwc2_host_get_tt_info(struct dwc2_hsotg *hsotg, void *context, gfp_t mem_flags, int *ttport) { … } /** * dwc2_host_put_tt_info() - Put the dwc2_tt from dwc2_host_get_tt_info() * * Frees resources allocated by dwc2_host_get_tt_info() if all current holders * of the structure are done. * * It's OK to call this with NULL. * * @hsotg: The HCD state structure for the DWC OTG controller. * @dwc_tt: The pointer returned by dwc2_host_get_tt_info. */ void dwc2_host_put_tt_info(struct dwc2_hsotg *hsotg, struct dwc2_tt *dwc_tt) { … } int dwc2_host_get_speed(struct dwc2_hsotg *hsotg, void *context) { … } static void dwc2_allocate_bus_bandwidth(struct usb_hcd *hcd, u16 bw, struct urb *urb) { … } static void dwc2_free_bus_bandwidth(struct usb_hcd *hcd, u16 bw, struct urb *urb) { … } /* * Sets the final status of an URB and returns it to the upper layer. Any * required cleanup of the URB is performed. * * Must be called with interrupt disabled and spinlock held */ void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, int status) { … } /* * Work queue function for starting the HCD when A-Cable is connected */ static void dwc2_hcd_start_func(struct work_struct *work) { … } /* * Reset work queue function */ static void dwc2_hcd_reset_func(struct work_struct *work) { … } static void dwc2_hcd_phy_reset_func(struct work_struct *work) { … } /* * ========================================================================= * Linux HC Driver Functions * ========================================================================= */ /* * Initializes the DWC_otg controller and its root hub and prepares it for host * mode operation. Activates the root port. Returns 0 on success and a negative * error code on failure. */ static int _dwc2_hcd_start(struct usb_hcd *hcd) { … } /* * Halts the DWC_otg host mode operations in a clean manner. USB transfers are * stopped. */ static void _dwc2_hcd_stop(struct usb_hcd *hcd) { … } static int _dwc2_hcd_suspend(struct usb_hcd *hcd) { … } static int _dwc2_hcd_resume(struct usb_hcd *hcd) { … } /* Returns the current frame number */ static int _dwc2_hcd_get_frame_number(struct usb_hcd *hcd) { … } static void dwc2_dump_urb_info(struct usb_hcd *hcd, struct urb *urb, char *fn_name) { … } /* * Starts processing a USB transfer request specified by a USB Request Block * (URB). mem_flags indicates the type of memory allocation to use while * processing this URB. */ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) { … } /* * Aborts/cancels a USB transfer request. Always returns 0 to indicate success. */ static int _dwc2_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) { … } /* * Frees resources in the DWC_otg controller related to a given endpoint. Also * clears state in the HCD related to the endpoint. Any URBs for the endpoint * must already be dequeued. */ static void _dwc2_hcd_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep) { … } /* * Resets endpoint specific parameter values, in current version used to reset * the data toggle (as a WA). This function can be called from usb_clear_halt * routine. */ static void _dwc2_hcd_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) { … } /* * Handles host mode interrupts for the DWC_otg controller. Returns IRQ_NONE if * there was no interrupt to handle. Returns IRQ_HANDLED if there was a valid * interrupt. * * This function is called by the USB core when an interrupt occurs */ static irqreturn_t _dwc2_hcd_irq(struct usb_hcd *hcd) { … } /* * Creates Status Change bitmap for the root hub and root port. The bitmap is * returned in buf. Bit 0 is the status change indicator for the root hub. Bit 1 * is the status change indicator for the single root port. Returns 1 if either * change indicator is 1, otherwise returns 0. */ static int _dwc2_hcd_hub_status_data(struct usb_hcd *hcd, char *buf) { … } /* Handles hub class-specific requests */ static int _dwc2_hcd_hub_control(struct usb_hcd *hcd, u16 typereq, u16 wvalue, u16 windex, char *buf, u16 wlength) { … } /* Handles hub TT buffer clear completions */ static void _dwc2_hcd_clear_tt_buffer_complete(struct usb_hcd *hcd, struct usb_host_endpoint *ep) { … } /* * HPRT0_SPD_HIGH_SPEED: high speed * HPRT0_SPD_FULL_SPEED: full speed */ static void dwc2_change_bus_speed(struct usb_hcd *hcd, int speed) { … } static void dwc2_free_dev(struct usb_hcd *hcd, struct usb_device *udev) { … } static int dwc2_reset_device(struct usb_hcd *hcd, struct usb_device *udev) { … } static struct hc_driver dwc2_hc_driver = …; /* * Frees secondary storage associated with the dwc2_hsotg structure contained * in the struct usb_hcd field */ static void dwc2_hcd_free(struct dwc2_hsotg *hsotg) { … } static void dwc2_hcd_release(struct dwc2_hsotg *hsotg) { … } /* * Initializes the HCD. This function allocates memory for and initializes the * static parts of the usb_hcd and dwc2_hsotg structures. It also registers the * USB bus with the core and calls the hc_driver->start() function. It returns * a negative error on failure. */ int dwc2_hcd_init(struct dwc2_hsotg *hsotg) { … } /* * Removes the HCD. * Frees memory and resources associated with the HCD and deregisters the bus. */ void dwc2_hcd_remove(struct dwc2_hsotg *hsotg) { … } /** * dwc2_backup_host_registers() - Backup controller host registers. * When suspending usb bus, registers needs to be backuped * if controller power is disabled once suspended. * * @hsotg: Programming view of the DWC_otg controller */ int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg) { … } /** * dwc2_restore_host_registers() - Restore controller host registers. * When resuming usb bus, device registers needs to be restored * if controller power were disabled. * * @hsotg: Programming view of the DWC_otg controller */ int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg) { … } /** * dwc2_host_enter_hibernation() - Put controller in Hibernation. * * @hsotg: Programming view of the DWC_otg controller */ int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg) { … } /* * dwc2_host_exit_hibernation() * * @hsotg: Programming view of the DWC_otg controller * @rem_wakeup: indicates whether resume is initiated by Device or Host. * @param reset: indicates whether resume is initiated by Reset. * * Return: non-zero if failed to enter to hibernation. * * This function is for exiting from Host mode hibernation by * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup. */ int dwc2_host_exit_hibernation(struct dwc2_hsotg *hsotg, int rem_wakeup, int reset) { … } bool dwc2_host_can_poweroff_phy(struct dwc2_hsotg *dwc2) { … } /** * dwc2_host_enter_partial_power_down() - Put controller in partial * power down. * * @hsotg: Programming view of the DWC_otg controller * * Return: non-zero if failed to enter host partial power down. * * This function is for entering Host mode partial power down. */ int dwc2_host_enter_partial_power_down(struct dwc2_hsotg *hsotg) { … } /* * dwc2_host_exit_partial_power_down() - Exit controller from host partial * power down. * * @hsotg: Programming view of the DWC_otg controller * @rem_wakeup: indicates whether resume is initiated by Reset. * @restore: indicates whether need to restore the registers or not. * * Return: non-zero if failed to exit host partial power down. * * This function is for exiting from Host mode partial power down. */ int dwc2_host_exit_partial_power_down(struct dwc2_hsotg *hsotg, int rem_wakeup, bool restore) { … } /** * dwc2_host_enter_clock_gating() - Put controller in clock gating. * * @hsotg: Programming view of the DWC_otg controller * * This function is for entering Host mode clock gating. */ void dwc2_host_enter_clock_gating(struct dwc2_hsotg *hsotg) { … } /** * dwc2_host_exit_clock_gating() - Exit controller from clock gating. * * @hsotg: Programming view of the DWC_otg controller * @rem_wakeup: indicates whether resume is initiated by remote wakeup * * This function is for exiting Host mode clock gating. */ void dwc2_host_exit_clock_gating(struct dwc2_hsotg *hsotg, int rem_wakeup) { … }