1 /* ==========================================================================
2 * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.c $
7 * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
8 * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
9 * otherwise expressly agreed to in writing between Synopsys and you.
11 * The Software IS NOT an item of Licensed Software or Licensed Product under
12 * any End User Software License Agreement or Agreement for Licensed Product
13 * with Synopsys or any supplement thereto. You are permitted to use and
14 * redistribute this Software in source and binary forms, with or without
15 * modification, provided that redistributions of source code must retain this
16 * notice. You may not view, use, disclose, copy or distribute this file or
17 * any information contained herein except pursuant to this license grant from
18 * Synopsys. If you do not agree with this notice, including the disclaimer
19 * below, then you are not authorized to use the Software.
21 * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 * ========================================================================== */
33 #ifndef DWC_DEVICE_ONLY
36 * This file implements HCD Core. All code in this file is portable and doesn't
37 * use any OS specific functions.
38 * Interface provided by HCD Core is defined in <code><hcd_if.h></code>
42 #include "dwc_otg_hcd.h"
43 #include "dwc_otg_regs.h"
44 #include "usbdev_rk.h"
45 #include "dwc_otg_driver.h"
46 #include <linux/usb.h>
47 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
48 #include <../drivers/usb/core/hcd.h>
50 #include <linux/usb/hcd.h>
53 dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void)
55 return DWC_ALLOC(sizeof(dwc_otg_hcd_t));
59 * Connection timeout function. An OTG host is required to display a
60 * message if the device does not connect within 10 seconds.
62 void dwc_otg_hcd_connect_timeout(void *ptr)
65 DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, ptr);
66 DWC_PRINTF("Connect Timeout\n");
67 __DWC_ERROR("Device Not Connected/Responding\n");
68 /** Remove buspower after 10s */
70 if (hcd->core_if->otg_ver)
71 dwc_otg_set_prtpower(hcd->core_if, 0);
75 static void dump_channel_info(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh)
77 if (qh->channel != NULL) {
78 dwc_hc_t *hc = qh->channel;
79 dwc_list_link_t *item;
80 dwc_otg_qh_t *qh_item;
81 int num_channels = hcd->core_if->core_params->host_channels;
84 dwc_otg_hc_regs_t *hc_regs;
90 hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num];
91 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
92 hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
93 hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
94 hcdma = DWC_READ_REG32(&hc_regs->hcdma);
96 DWC_PRINTF(" Assigned to channel %p:\n", hc);
97 DWC_PRINTF(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32,
99 DWC_PRINTF(" hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32,
101 DWC_PRINTF(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
102 hc->dev_addr, hc->ep_num, hc->ep_is_in);
103 DWC_PRINTF(" ep_type: %d\n", hc->ep_type);
104 DWC_PRINTF(" max_packet: %d\n", hc->max_packet);
105 DWC_PRINTF(" data_pid_start: %d\n", hc->data_pid_start);
106 DWC_PRINTF(" xfer_started: %d\n", hc->xfer_started);
107 DWC_PRINTF(" halt_status: %d\n", hc->halt_status);
108 DWC_PRINTF(" xfer_buff: %p\n", hc->xfer_buff);
109 DWC_PRINTF(" xfer_len: %d\n", hc->xfer_len);
110 DWC_PRINTF(" qh: %p\n", hc->qh);
111 DWC_PRINTF(" NP inactive sched:\n");
112 DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_inactive) {
114 DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
115 DWC_PRINTF(" %p\n", qh_item);
117 DWC_PRINTF(" NP active sched:\n");
118 DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_active) {
120 DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
121 DWC_PRINTF(" %p\n", qh_item);
123 DWC_PRINTF(" Channels: \n");
124 for (i = 0; i < num_channels; i++) {
125 dwc_hc_t *hc = hcd->hc_ptr_array[i];
126 DWC_PRINTF(" %2d: %p\n", i, hc);
133 * Work queue function for starting the HCD when A-Cable is connected.
134 * The hcd_start() must be called in a process context.
136 static void hcd_start_func(void *_vp)
138 dwc_otg_hcd_t *hcd = (dwc_otg_hcd_t *) _vp;
140 DWC_DEBUGPL(DBG_HCDV, "%s() %p\n", __func__, hcd);
142 hcd->fops->start(hcd);
146 static void del_xfer_timers(dwc_otg_hcd_t *hcd)
150 int num_channels = hcd->core_if->core_params->host_channels;
151 for (i = 0; i < num_channels; i++) {
152 DWC_TIMER_CANCEL(hcd->core_if->hc_xfer_timer[i]);
157 static void del_timers(dwc_otg_hcd_t *hcd)
159 del_xfer_timers(hcd);
160 DWC_TIMER_CANCEL(hcd->conn_timer);
164 * Processes all the URBs in a single list of QHs. Completes them with
165 * -ETIMEDOUT and frees the QTD.
167 static void kill_urbs_in_qh_list(dwc_otg_hcd_t *hcd, dwc_list_link_t *qh_list)
169 dwc_list_link_t *qh_item;
171 dwc_otg_qtd_t *qtd, *qtd_tmp;
173 DWC_LIST_FOREACH(qh_item, qh_list) {
174 qh = DWC_LIST_ENTRY(qh_item, dwc_otg_qh_t, qh_list_entry);
175 DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp,
176 &qh->qtd_list, qtd_list_entry) {
177 qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
178 if (qtd->urb != NULL) {
179 hcd->fops->complete(hcd, qtd->urb->priv,
180 qtd->urb, -DWC_E_SHUTDOWN);
181 dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
191 * Responds with an error status of ETIMEDOUT to all URBs in the non-periodic
192 * and periodic schedules. The QTD associated with each URB is removed from
193 * the schedule and freed. This function may be called when a disconnect is
194 * detected or when the HCD is being stopped.
196 static void kill_all_urbs(dwc_otg_hcd_t *hcd)
198 kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_inactive);
199 kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_active);
200 kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_inactive);
201 kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_ready);
202 kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_assigned);
203 kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_queued);
207 * Start the connection timer. An OTG host is required to display a
208 * message if the device does not connect within 10 seconds. The
209 * timer is deleted if a port connect interrupt occurs before the
212 static void dwc_otg_hcd_start_connect_timer(dwc_otg_hcd_t *hcd)
214 DWC_TIMER_SCHEDULE(hcd->conn_timer, 10000 /* 10 secs */);
218 * HCD Callback function for disconnect of the HCD.
220 * @param p void pointer to the <code>struct usb_hcd</code>
222 static int32_t dwc_otg_hcd_session_start_cb(void *p)
224 dwc_otg_hcd_t *dwc_otg_hcd;
225 DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p);
227 dwc_otg_hcd_start_connect_timer(dwc_otg_hcd);
232 * HCD Callback function for starting the HCD when A-Cable is
235 * @param p void pointer to the <code>struct usb_hcd</code>
237 static int32_t dwc_otg_hcd_start_cb(void *p)
239 dwc_otg_hcd_t *dwc_otg_hcd = p;
240 dwc_otg_core_if_t *core_if;
242 uint32_t timeout = 50;
244 core_if = dwc_otg_hcd->core_if;
246 if (core_if->op_state == B_HOST) {
248 * Reset the port. During a HNP mode switch the reset
249 * needs to occur within 1ms and have a duration of at
252 hprt0.d32 = dwc_otg_read_hprt0(core_if);
254 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
255 if (core_if->otg_ver) {
257 hprt0.d32 = dwc_otg_read_hprt0(core_if);
259 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
262 /**@todo vahrama: Check the timeout value for OTG 2.0 */
263 if (core_if->otg_ver)
265 DWC_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg,
266 hcd_start_func, dwc_otg_hcd, timeout,
273 * HCD Callback function for disconnect of the HCD.
275 * @param p void pointer to the <code>struct usb_hcd</code>
277 static int32_t dwc_otg_hcd_disconnect_cb(void *p)
280 dwc_otg_hcd_t *dwc_otg_hcd = p;
283 dwc_otg_hcd->non_periodic_qh_ptr = &dwc_otg_hcd->non_periodic_sched_active;
284 dwc_otg_hcd->non_periodic_channels = 0;
285 dwc_otg_hcd->periodic_channels = 0;
286 dwc_otg_hcd->frame_number =0;
288 hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);
289 /* In some case, we don't disconnect a usb device, but
290 * disconnect intr was triggered, so check hprt0 here. */
291 if ((!hprt0.b.prtenchng)
292 && (!hprt0.b.prtconndet)
293 && hprt0.b.prtconnsts) {
294 DWC_PRINTF("%s: hprt0 = 0x%08x\n", __func__, hprt0.d32);
298 * Set status flags for the hub driver.
300 dwc_otg_hcd->flags.b.port_connect_status_change = 1;
301 dwc_otg_hcd->flags.b.port_connect_status = 0;
304 * Shutdown any transfers in process by clearing the Tx FIFO Empty
305 * interrupt mask and status bits and disabling subsequent host
306 * channel interrupts.
309 intr.b.nptxfempty = 1;
310 intr.b.ptxfempty = 1;
312 DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk,
314 DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintsts,
318 * Turn off the vbus power only if the core has transitioned to device
319 * mode. If still in host mode, need to keep power on to detect a
322 if (dwc_otg_is_device_mode(dwc_otg_hcd->core_if)) {
323 if (dwc_otg_hcd->core_if->op_state != A_SUSPEND) {
324 hprt0_data_t hprt0 = {.d32 = 0 };
325 DWC_PRINTF("Disconnect: PortPower off\n");
327 DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0,
330 /** Delete timers if become device */
331 del_timers(dwc_otg_hcd);
332 dwc_otg_disable_host_interrupts(dwc_otg_hcd->core_if);
336 /* Respond with an error status to all URBs in the schedule. */
337 kill_all_urbs(dwc_otg_hcd);
339 if (dwc_otg_is_host_mode(dwc_otg_hcd->core_if)) {
340 /* Clean up any host channels that were in use. */
344 dwc_otg_hc_regs_t *hc_regs;
345 hcchar_data_t hcchar;
347 DWC_PRINTF("Disconnect cb-Host\n");
348 if (dwc_otg_hcd->core_if->otg_ver == 1)
349 del_xfer_timers(dwc_otg_hcd);
351 del_timers(dwc_otg_hcd);
353 num_channels = dwc_otg_hcd->core_if->core_params->host_channels;
355 if (!dwc_otg_hcd->core_if->dma_enable) {
356 /* Flush out any channel requests in slave mode. */
357 for (i = 0; i < num_channels; i++) {
358 channel = dwc_otg_hcd->hc_ptr_array[i];
359 if (DWC_CIRCLEQ_EMPTY_ENTRY
360 (channel, hc_list_entry)) {
362 dwc_otg_hcd->core_if->host_if->
365 DWC_READ_REG32(&hc_regs->hcchar);
378 for (i = 0; i < num_channels; i++) {
379 channel = dwc_otg_hcd->hc_ptr_array[i];
380 if (DWC_CIRCLEQ_EMPTY_ENTRY(channel, hc_list_entry)) {
382 dwc_otg_hcd->core_if->host_if->hc_regs[i];
383 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
385 /* Halt the channel. */
387 DWC_WRITE_REG32(&hc_regs->hcchar,
391 dwc_otg_hc_cleanup(dwc_otg_hcd->core_if,
393 DWC_CIRCLEQ_INSERT_TAIL
394 (&dwc_otg_hcd->free_hc_list, channel,
397 * Added for Descriptor DMA to prevent channel double cleanup
398 * in release_channel_ddma(). Which called from ep_disable
399 * when device disconnect.
407 if (dwc_otg_hcd->fops->disconnect) {
408 dwc_otg_hcd->fops->disconnect(dwc_otg_hcd);
415 * HCD Callback function for stopping the HCD.
417 * @param p void pointer to the <code>struct usb_hcd</code>
419 static int32_t dwc_otg_hcd_stop_cb(void *p)
421 dwc_otg_hcd_t *dwc_otg_hcd = p;
423 DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p);
424 dwc_otg_hcd_stop(dwc_otg_hcd);
428 #ifdef CONFIG_USB_DWC_OTG_LPM
430 * HCD Callback function for sleep of HCD.
432 * @param p void pointer to the <code>struct usb_hcd</code>
434 static int dwc_otg_hcd_sleep_cb(void *p)
436 dwc_otg_hcd_t *hcd = p;
438 dwc_otg_hcd_free_hc_from_lpm(hcd);
445 * HCD Callback function for Remote Wakeup.
447 * @param p void pointer to the <code>struct usb_hcd</code>
449 static int dwc_otg_hcd_rem_wakeup_cb(void *p)
451 dwc_otg_hcd_t *dwc_otg_hcd = p;
452 struct usb_hcd *hcd = dwc_otg_hcd_get_priv_data(dwc_otg_hcd);
454 if (dwc_otg_hcd->core_if->lx_state == DWC_OTG_L2) {
455 dwc_otg_hcd->flags.b.port_suspend_change = 1;
456 usb_hcd_resume_root_hub(hcd);
458 #ifdef CONFIG_USB_DWC_OTG_LPM
460 dwc_otg_hcd->flags.b.port_l1_change = 1;
467 * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
470 void dwc_otg_hcd_stop(dwc_otg_hcd_t *hcd)
472 hprt0_data_t hprt0 = {.d32 = 0 };
473 struct dwc_otg_platform_data *pldata;
474 pldata = hcd->core_if->otg_dev->pldata;
476 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD STOP\n");
479 * The root hub should be disconnected before this function is called.
480 * The disconnect will clear the QTD lists (via ..._hcd_urb_dequeue)
481 * and the QH lists (via ..._hcd_endpoint_disable).
484 /* Turn off all host-specific interrupts. */
485 dwc_otg_disable_host_interrupts(hcd->core_if);
487 /* Turn off the vbus power */
488 DWC_PRINTF("PortPower off\n");
490 DWC_WRITE_REG32(hcd->core_if->host_if->hprt0, hprt0.d32);
492 if (pldata->power_enable)
493 pldata->power_enable(0);
498 int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t *hcd,
499 dwc_otg_hcd_urb_t *dwc_otg_urb, void **ep_handle,
502 dwc_irqflags_t flags;
505 gintmsk_data_t intr_mask = {.d32 = 0 };
507 if (!hcd->flags.b.port_connect_status) {
508 /* No longer connected. */
509 DWC_DEBUG("Not connected\n");
510 return -DWC_E_NO_DEVICE;
513 qtd = dwc_otg_hcd_qtd_create(dwc_otg_urb, atomic_alloc);
515 DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n");
516 return -DWC_E_NO_MEMORY;
518 DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
520 dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle, 1);
523 DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. "
524 "Error status %d\n", retval);
525 dwc_otg_hcd_qtd_free(qtd);
528 DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk);
529 if (!intr_mask.b.sofintr && retval == 0) {
530 dwc_otg_transaction_type_e tr_type;
531 if ((qtd->qh->ep_type == UE_BULK)
532 && !(qtd->urb->flags & URB_GIVEBACK_ASAP)) {
533 /* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */
537 tr_type = dwc_otg_hcd_select_transactions(hcd);
538 if (tr_type != DWC_OTG_TRANSACTION_NONE) {
539 dwc_otg_hcd_queue_transactions(hcd, tr_type);
543 DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
547 int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t *hcd,
548 dwc_otg_hcd_urb_t *dwc_otg_urb)
551 dwc_otg_qtd_t *urb_qtd;
553 urb_qtd = dwc_otg_urb->qtd;
554 if (((uint32_t) urb_qtd & 0xf0000000) == 0) {
555 DWC_PRINTF("%s error: urb_qtd is %p dwc_otg_urb %p!!!\n",
556 __func__, urb_qtd, dwc_otg_urb);
561 if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
562 if (urb_qtd->in_process) {
563 dump_channel_info(hcd, qh);
567 if (urb_qtd->in_process && qh->channel) {
568 /* The QTD is in process (it has been assigned to a channel). */
569 if (hcd->flags.b.port_connect_status) {
571 * If still connected (i.e. in host mode), halt the
572 * channel so it can be used for other transfers. If
573 * no longer connected, the host registers can't be
574 * written to halt the channel since the core is in
577 dwc_otg_hc_halt(hcd->core_if, qh->channel,
578 DWC_OTG_HC_XFER_URB_DEQUEUE);
583 * Free the QTD and clean up the associated QH. Leave the QH in the
584 * schedule if it has any remaining QTDs.
587 if (!hcd->core_if->dma_desc_enable) {
588 uint8_t b = urb_qtd->in_process;
589 dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);
591 dwc_otg_hcd_qh_deactivate(hcd, qh, 0);
593 } else if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
594 dwc_otg_hcd_qh_remove(hcd, qh);
597 dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);
602 int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t *hcd, void *ep_handle,
605 dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
607 dwc_irqflags_t flags;
610 retval = -DWC_E_INVALID;
615 retval = -DWC_E_INVALID;
619 DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
621 while (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list) && retry) {
622 DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
625 DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
628 dwc_otg_hcd_qh_remove(hcd, qh);
630 DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
632 * Split dwc_otg_hcd_qh_remove_and_free() into qh_remove
633 * and qh_free to prevent stack dump on DWC_DMA_FREE() with
634 * irq_disabled (spinlock_irqsave) in dwc_otg_hcd_desc_list_free()
635 * and dwc_otg_hcd_frame_list_alloc().
637 dwc_otg_hcd_qh_free(hcd, qh);
643 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
644 int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t *hcd, void *ep_handle)
647 dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
649 return -DWC_E_INVALID;
651 qh->data_toggle = DWC_OTG_HC_PID_DATA0;
657 * HCD Callback structure for handling mode switching.
659 static dwc_otg_cil_callbacks_t hcd_cil_callbacks = {
660 .start = dwc_otg_hcd_start_cb,
661 .stop = dwc_otg_hcd_stop_cb,
662 .disconnect = dwc_otg_hcd_disconnect_cb,
663 .session_start = dwc_otg_hcd_session_start_cb,
664 .resume_wakeup = dwc_otg_hcd_rem_wakeup_cb,
665 #ifdef CONFIG_USB_DWC_OTG_LPM
666 .sleep = dwc_otg_hcd_sleep_cb,
672 * Reset tasklet function
674 static void reset_tasklet_func(void *data)
676 dwc_otg_hcd_t *dwc_otg_hcd = (dwc_otg_hcd_t *) data;
677 dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
680 DWC_DEBUGPL(DBG_HCDV, "USB RESET tasklet called\n");
682 hprt0.d32 = dwc_otg_read_hprt0(core_if);
684 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
688 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
689 dwc_otg_hcd->flags.b.port_reset_change = 1;
692 static void qh_list_free(dwc_otg_hcd_t *hcd, dwc_list_link_t *qh_list)
694 dwc_list_link_t *item;
696 dwc_irqflags_t flags;
698 if (!qh_list->next) {
699 /* The list hasn't been initialized yet. */
703 * Hold spinlock here. Not needed in that case if bellow
704 * function is being called from ISR
706 DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
707 /* Ensure there are no QTDs or URBs left. */
708 kill_urbs_in_qh_list(hcd, qh_list);
709 DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
711 DWC_LIST_FOREACH(item, qh_list) {
712 qh = DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
713 dwc_otg_hcd_qh_remove_and_free(hcd, qh);
718 * Exit from Hibernation if Host did not detect SRP from connected SRP capable
719 * Device during SRP time by host power up.
721 void dwc_otg_hcd_power_up(void *ptr)
723 gpwrdn_data_t gpwrdn = {.d32 = 0 };
724 dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
726 DWC_PRINTF("%s called\n", __FUNCTION__);
728 if (!core_if->hibernation_suspend) {
729 DWC_PRINTF("Already exited from Hibernation\n");
733 /* Switch on the voltage to the core */
734 gpwrdn.b.pwrdnswtch = 1;
735 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
740 gpwrdn.b.pwrdnrstn = 1;
741 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
744 /* Disable power clamps */
746 gpwrdn.b.pwrdnclmp = 1;
747 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
749 /* Remove reset the core signal */
751 gpwrdn.b.pwrdnrstn = 1;
752 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
755 /* Disable PMU interrupt */
757 gpwrdn.b.pmuintsel = 1;
758 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
760 core_if->hibernation_suspend = 0;
764 gpwrdn.b.pmuactv = 1;
765 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
770 gpwrdn.b.dis_vbus = 1;
771 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
773 core_if->op_state = A_HOST;
774 dwc_otg_core_init(core_if);
775 dwc_otg_enable_global_interrupts(core_if);
776 cil_hcd_start(core_if);
780 * Frees secondary storage associated with the dwc_otg_hcd structure contained
781 * in the struct usb_hcd field.
783 static void dwc_otg_hcd_free(dwc_otg_hcd_t *dwc_otg_hcd)
787 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD FREE\n");
789 del_timers(dwc_otg_hcd);
791 /* Free memory for QH/QTD lists */
792 qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_inactive);
793 qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_active);
794 qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_inactive);
795 qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_ready);
796 qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_assigned);
797 qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_queued);
799 /* Free memory for the host channels. */
800 for (i = 0; i < MAX_EPS_CHANNELS; i++) {
801 dwc_hc_t *hc = dwc_otg_hcd->hc_ptr_array[i];
804 if (dwc_otg_hcd->core_if->hc_xfer_timer[i]) {
805 DWC_TIMER_FREE(dwc_otg_hcd->core_if->hc_xfer_timer[i]);
809 DWC_DEBUGPL(DBG_HCDV, "HCD Free channel #%i, hc=%p\n",
815 if (dwc_otg_hcd->core_if->dma_enable) {
816 if (dwc_otg_hcd->status_buf_dma) {
817 DWC_DMA_FREE(DWC_OTG_HCD_STATUS_BUF_SIZE,
818 dwc_otg_hcd->status_buf,
819 dwc_otg_hcd->status_buf_dma);
821 } else if (dwc_otg_hcd->status_buf != NULL) {
822 DWC_FREE(dwc_otg_hcd->status_buf);
824 DWC_SPINLOCK_FREE(dwc_otg_hcd->lock);
825 /* Set core_if's lock pointer to NULL */
826 dwc_otg_hcd->core_if->lock = NULL;
828 DWC_TIMER_FREE(dwc_otg_hcd->conn_timer);
829 DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet);
831 #ifdef DWC_DEV_SRPCAP
832 if (dwc_otg_hcd->core_if->power_down == 2 &&
833 dwc_otg_hcd->core_if->pwron_timer) {
834 DWC_TIMER_FREE(dwc_otg_hcd->core_if->pwron_timer);
837 DWC_FREE(dwc_otg_hcd);
840 int dwc_otg_hcd_init(dwc_otg_hcd_t *hcd, dwc_otg_core_if_t *core_if)
847 hcd->lock = DWC_SPINLOCK_ALLOC();
849 DWC_ERROR("Could not allocate lock for pcd");
851 retval = -DWC_E_NO_MEMORY;
854 hcd->core_if = core_if;
856 /* Register the HCD CIL Callbacks */
857 dwc_otg_cil_register_hcd_callbacks(hcd->core_if,
858 &hcd_cil_callbacks, hcd);
860 /* Initialize the non-periodic schedule. */
861 DWC_LIST_INIT(&hcd->non_periodic_sched_inactive);
862 DWC_LIST_INIT(&hcd->non_periodic_sched_active);
864 /* Initialize the periodic schedule. */
865 DWC_LIST_INIT(&hcd->periodic_sched_inactive);
866 DWC_LIST_INIT(&hcd->periodic_sched_ready);
867 DWC_LIST_INIT(&hcd->periodic_sched_assigned);
868 DWC_LIST_INIT(&hcd->periodic_sched_queued);
871 * Create a host channel descriptor for each host channel implemented
872 * in the controller. Initialize the channel descriptor array.
874 DWC_CIRCLEQ_INIT(&hcd->free_hc_list);
875 num_channels = hcd->core_if->core_params->host_channels;
876 DWC_MEMSET(hcd->hc_ptr_array, 0, sizeof(hcd->hc_ptr_array));
877 for (i = 0; i < num_channels; i++) {
878 channel = DWC_ALLOC(sizeof(dwc_hc_t));
879 if (channel == NULL) {
880 retval = -DWC_E_NO_MEMORY;
881 DWC_ERROR("%s: host channel allocation failed\n",
883 dwc_otg_hcd_free(hcd);
887 hcd->hc_ptr_array[i] = channel;
889 hcd->core_if->hc_xfer_timer[i] =
890 DWC_TIMER_ALLOC("hc timer", hc_xfer_timeout,
891 &hcd->core_if->hc_xfer_info[i]);
893 DWC_DEBUGPL(DBG_HCDV, "HCD Added channel #%d, hc=%p\n", i,
897 /* Initialize the Connection timeout timer. */
898 hcd->conn_timer = DWC_TIMER_ALLOC("Connection timer",
899 dwc_otg_hcd_connect_timeout, hcd);
901 /* Initialize reset tasklet. */
903 DWC_TASK_ALLOC("reset_tasklet", reset_tasklet_func, hcd);
904 #ifdef DWC_DEV_SRPCAP
905 if (hcd->core_if->power_down == 2) {
906 /* Initialize Power on timer for Host power up in case hibernation */
907 hcd->core_if->pwron_timer = DWC_TIMER_ALLOC("PWRON TIMER",
908 dwc_otg_hcd_power_up,
914 * Allocate space for storing data on status transactions. Normally no
915 * data is sent, but this space acts as a bit bucket. This must be
916 * done after usb_add_hcd since that function allocates the DMA buffer
919 if (hcd->core_if->dma_enable) {
921 DWC_DMA_ALLOC_ATOMIC(DWC_OTG_HCD_STATUS_BUF_SIZE,
922 &hcd->status_buf_dma);
924 hcd->status_buf = DWC_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE);
926 if (!hcd->status_buf) {
927 retval = -DWC_E_NO_MEMORY;
928 DWC_ERROR("%s: status_buf allocation failed\n", __func__);
929 dwc_otg_hcd_free(hcd);
934 hcd->frame_list = NULL;
935 hcd->frame_list_dma = 0;
936 hcd->periodic_qh_count = 0;
941 void dwc_otg_hcd_remove(dwc_otg_hcd_t *hcd)
943 /* Turn off all host-specific interrupts. */
944 dwc_otg_disable_host_interrupts(hcd->core_if);
946 dwc_otg_hcd_free(hcd);
950 * Initializes dynamic portions of the DWC_otg HCD state.
952 static void dwc_otg_hcd_reinit(dwc_otg_hcd_t *hcd)
957 dwc_hc_t *channel_tmp;
958 dwc_irqflags_t flags;
962 hcd->non_periodic_qh_ptr = &hcd->non_periodic_sched_active;
963 hcd->non_periodic_channels = 0;
964 hcd->periodic_channels = 0;
966 DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
968 * Put all channels in the free channel list and clean up channel
971 DWC_CIRCLEQ_FOREACH_SAFE(channel, channel_tmp,
972 &hcd->free_hc_list, hc_list_entry) {
973 DWC_CIRCLEQ_REMOVE(&hcd->free_hc_list, channel, hc_list_entry);
976 num_channels = hcd->core_if->core_params->host_channels;
977 for (i = 0; i < num_channels; i++) {
978 channel = hcd->hc_ptr_array[i];
979 DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, channel,
981 dwc_otg_hc_cleanup(hcd->core_if, channel);
983 DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
984 /* Initialize the DWC core for host mode operation. */
985 dwc_otg_core_host_init(hcd->core_if);
987 /* Set core_if's lock pointer to the hcd->lock */
988 hcd->core_if->lock = hcd->lock;
992 * Assigns transactions from a QTD to a free host channel and initializes the
993 * host channel to perform the transactions. The host channel is removed from
996 * @param hcd The HCD state structure.
997 * @param qh Transactions from the first QTD for this QH are selected and
998 * assigned to a free host channel.
1000 static int assign_and_init_hc(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh)
1004 dwc_otg_hcd_urb_t *urb;
1008 DWC_DEBUGPL(DBG_HCDV, "%s(%p,%p)\n", __func__, hcd, qh);
1010 hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);
1012 /* Remove the host channel from the free list. */
1013 DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry);
1015 qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
1019 printk("%s : urb is NULL\n", __func__);
1026 qtd->in_process = 1;
1029 * Use usb_pipedevice to determine device address. This address is
1030 * 0 before the SET_ADDRESS command and the correct address afterward.
1032 hc->dev_addr = dwc_otg_hcd_get_dev_addr(&urb->pipe_info);
1033 hc->ep_num = dwc_otg_hcd_get_ep_num(&urb->pipe_info);
1034 hc->speed = qh->dev_speed;
1035 hc->max_packet = dwc_max_packet(qh->maxp);
1037 hc->xfer_started = 0;
1038 hc->halt_status = DWC_OTG_HC_XFER_NO_HALT_STATUS;
1039 hc->error_state = (qtd->error_count > 0);
1040 hc->halt_on_queue = 0;
1041 hc->halt_pending = 0;
1045 * The following values may be modified in the transfer type section
1046 * below. The xfer_len value may be reduced when the transfer is
1047 * started to accommodate the max widths of the XferSize and PktCnt
1048 * fields in the HCTSIZn register.
1051 hc->ep_is_in = (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) != 0);
1055 hc->do_ping = qh->ping_state;
1057 hc->data_pid_start = qh->data_toggle;
1058 hc->multi_count = 1;
1060 if (hcd->core_if->dma_enable) {
1061 hc->xfer_buff = (uint8_t *) urb->dma + urb->actual_length;
1063 /* For non-dword aligned case */
1064 if (((unsigned long)hc->xfer_buff & 0x3)
1065 && !hcd->core_if->dma_desc_enable) {
1066 ptr = (uint8_t *) urb->buf + urb->actual_length;
1069 hc->xfer_buff = (uint8_t *) urb->buf + urb->actual_length;
1071 hc->xfer_len = urb->length - urb->actual_length;
1075 * Set the split attributes
1080 uint32_t hub_addr, port_addr;
1082 hc->xact_pos = qtd->isoc_split_pos;
1083 hc->complete_split = qtd->complete_split;
1084 hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &port_addr);
1085 hc->hub_addr = (uint8_t) hub_addr;
1086 hc->port_addr = (uint8_t) port_addr;
1089 switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) {
1091 hc->ep_type = DWC_OTG_EP_TYPE_CONTROL;
1092 switch (qtd->control_phase) {
1093 case DWC_OTG_CONTROL_SETUP:
1094 DWC_DEBUGPL(DBG_HCDV, " Control setup transaction\n");
1097 hc->data_pid_start = DWC_OTG_HC_PID_SETUP;
1098 if (hcd->core_if->dma_enable)
1099 hc->xfer_buff = (uint8_t *) urb->setup_dma;
1101 hc->xfer_buff = (uint8_t *) urb->setup_packet;
1106 case DWC_OTG_CONTROL_DATA:
1107 DWC_DEBUGPL(DBG_HCDV, " Control data transaction\n");
1108 hc->data_pid_start = qtd->data_toggle;
1110 case DWC_OTG_CONTROL_STATUS:
1112 * Direction is opposite of data direction or IN if no
1115 DWC_DEBUGPL(DBG_HCDV, " Control status transaction\n");
1116 if (urb->length == 0) {
1120 dwc_otg_hcd_is_pipe_out(&urb->pipe_info);
1125 hc->data_pid_start = DWC_OTG_HC_PID_DATA1;
1128 if (hcd->core_if->dma_enable)
1129 hc->xfer_buff = (uint8_t *) hcd->status_buf_dma;
1131 hc->xfer_buff = (uint8_t *) hcd->status_buf;
1138 hc->ep_type = DWC_OTG_EP_TYPE_BULK;
1141 hc->ep_type = DWC_OTG_EP_TYPE_INTR;
1143 case UE_ISOCHRONOUS:
1145 struct dwc_otg_hcd_iso_packet_desc *frame_desc;
1147 hc->ep_type = DWC_OTG_EP_TYPE_ISOC;
1149 if (hcd->core_if->dma_desc_enable)
1152 frame_desc = &urb->iso_descs[qtd->isoc_frame_index];
1154 frame_desc->status = 0;
1156 if (hcd->core_if->dma_enable) {
1157 hc->xfer_buff = (uint8_t *) urb->dma;
1159 hc->xfer_buff = (uint8_t *) urb->buf;
1162 frame_desc->offset + qtd->isoc_split_offset;
1164 frame_desc->length - qtd->isoc_split_offset;
1166 /* For non-dword aligned buffers */
1167 if (((unsigned long)hc->xfer_buff & 0x3)
1168 && hcd->core_if->dma_enable) {
1170 (uint8_t *) urb->buf + frame_desc->offset +
1171 qtd->isoc_split_offset;
1175 if (hc->xact_pos == DWC_HCSPLIT_XACTPOS_ALL) {
1176 if (hc->xfer_len <= 188) {
1177 hc->xact_pos = DWC_HCSPLIT_XACTPOS_ALL;
1180 DWC_HCSPLIT_XACTPOS_BEGIN;
1186 /* non DWORD-aligned buffer case */
1189 if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
1190 buf_size = hcd->core_if->core_params->max_transfer_size;
1194 if (!qh->dw_align_buf) {
1195 qh->dw_align_buf = DWC_DMA_ALLOC_ATOMIC(buf_size,
1198 if (!qh->dw_align_buf) {
1200 ("%s: Failed to allocate memory to handle "
1201 "non-dword aligned buffer case\n",
1206 if (!hc->ep_is_in) {
1207 dwc_memcpy(qh->dw_align_buf, ptr, hc->xfer_len);
1209 hc->align_buff = qh->dw_align_buf_dma;
1214 if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
1215 hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
1217 * This value may be modified when the transfer is started to
1218 * reflect the actual transfer length.
1220 hc->multi_count = dwc_hb_mult(qh->maxp);
1223 if (hcd->core_if->dma_desc_enable)
1224 hc->desc_list_addr = qh->desc_list_dma;
1226 dwc_otg_hc_init(hcd->core_if, hc);
1232 * This function selects transactions from the HCD transfer schedule and
1233 * assigns them to available host channels. It is called from HCD interrupt
1234 * handler functions.
1236 * @param hcd The HCD state structure.
1238 * @return The types of new transactions that were assigned to host channels.
1240 dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t *hcd)
1242 dwc_list_link_t *qh_ptr;
1245 dwc_otg_transaction_type_e ret_val = DWC_OTG_TRANSACTION_NONE;
1249 DWC_DEBUGPL(DBG_HCD, " Select Transactions\n");
1252 /* Process entries in the periodic ready list. */
1253 qh_ptr = DWC_LIST_FIRST(&hcd->periodic_sched_ready);
1255 while (qh_ptr != &hcd->periodic_sched_ready &&
1256 !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
1258 qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
1259 assign_and_init_hc(hcd, qh);
1262 * Move the QH from the periodic ready schedule to the
1263 * periodic assigned schedule.
1265 qh_ptr = DWC_LIST_NEXT(qh_ptr);
1266 DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
1267 &qh->qh_list_entry);
1269 ret_val = DWC_OTG_TRANSACTION_PERIODIC;
1273 * Process entries in the inactive portion of the non-periodic
1274 * schedule. Some free host channels may not be used if they are
1275 * reserved for periodic transfers.
1277 qh_ptr = hcd->non_periodic_sched_inactive.next;
1278 num_channels = hcd->core_if->core_params->host_channels;
1279 while (qh_ptr != &hcd->non_periodic_sched_inactive &&
1280 (hcd->non_periodic_channels <
1281 num_channels - hcd->periodic_channels) &&
1282 !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
1284 qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
1286 err = assign_and_init_hc(hcd, qh);
1289 * Move the QH from the non-periodic inactive schedule to the
1290 * non-periodic active schedule.
1292 qh_ptr = DWC_LIST_NEXT(qh_ptr);
1295 DWC_LIST_MOVE_HEAD(&hcd->non_periodic_sched_active,
1296 &qh->qh_list_entry);
1298 if (ret_val == DWC_OTG_TRANSACTION_NONE) {
1299 ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC;
1301 ret_val = DWC_OTG_TRANSACTION_ALL;
1304 hcd->non_periodic_channels++;
1311 * Attempts to queue a single transaction request for a host channel
1312 * associated with either a periodic or non-periodic transfer. This function
1313 * assumes that there is space available in the appropriate request queue. For
1314 * an OUT transfer or SETUP transaction in Slave mode, it checks whether space
1315 * is available in the appropriate Tx FIFO.
1317 * @param hcd The HCD state structure.
1318 * @param hc Host channel descriptor associated with either a periodic or
1319 * non-periodic transfer.
1320 * @param fifo_dwords_avail Number of DWORDs available in the periodic Tx
1321 * FIFO for periodic transfers or the non-periodic Tx FIFO for non-periodic
1324 * @return 1 if a request is queued and more requests may be needed to
1325 * complete the transfer, 0 if no more requests are required for this
1326 * transfer, -1 if there is insufficient space in the Tx FIFO.
1328 static int queue_transaction(dwc_otg_hcd_t *hcd,
1329 dwc_hc_t *hc, uint16_t fifo_dwords_avail)
1333 if (hcd->core_if->dma_enable) {
1334 if (hcd->core_if->dma_desc_enable) {
1335 if (!hc->xfer_started
1336 || (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)) {
1337 dwc_otg_hcd_start_xfer_ddma(hcd, hc->qh);
1338 hc->qh->ping_state = 0;
1340 } else if (!hc->xfer_started) {
1341 if (!hc || !(hc->qh))
1343 dwc_otg_hc_start_transfer(hcd->core_if, hc);
1344 hc->qh->ping_state = 0;
1347 } else if (hc->halt_pending) {
1348 /* Don't queue a request if the channel has been halted. */
1350 } else if (hc->halt_on_queue) {
1351 dwc_otg_hc_halt(hcd->core_if, hc, hc->halt_status);
1353 } else if (hc->do_ping) {
1354 if (!hc->xfer_started) {
1355 dwc_otg_hc_start_transfer(hcd->core_if, hc);
1358 } else if (!hc->ep_is_in || hc->data_pid_start == DWC_OTG_HC_PID_SETUP) {
1359 if ((fifo_dwords_avail * 4) >= hc->max_packet) {
1360 if (!hc->xfer_started) {
1361 dwc_otg_hc_start_transfer(hcd->core_if, hc);
1365 dwc_otg_hc_continue_transfer(hcd->core_if,
1372 if (!hc->xfer_started) {
1373 dwc_otg_hc_start_transfer(hcd->core_if, hc);
1376 retval = dwc_otg_hc_continue_transfer(hcd->core_if, hc);
1384 * Processes periodic channels for the next frame and queues transactions for
1385 * these channels to the DWC_otg controller. After queueing transactions, the
1386 * Periodic Tx FIFO Empty interrupt is enabled if there are more transactions
1387 * to queue as Periodic Tx FIFO or request queue space becomes available.
1388 * Otherwise, the Periodic Tx FIFO Empty interrupt is disabled.
1390 static void process_periodic_channels(dwc_otg_hcd_t *hcd)
1392 hptxsts_data_t tx_status;
1393 dwc_list_link_t *qh_ptr;
1396 int no_queue_space = 0;
1397 int no_fifo_space = 0;
1399 dwc_otg_host_global_regs_t *host_regs;
1400 host_regs = hcd->core_if->host_if->host_global_regs;
1402 DWC_DEBUGPL(DBG_HCDV, "Queue periodic transactions\n");
1404 tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
1405 DWC_DEBUGPL(DBG_HCDV,
1406 " P Tx Req Queue Space Avail (before queue): %d\n",
1407 tx_status.b.ptxqspcavail);
1408 DWC_DEBUGPL(DBG_HCDV, " P Tx FIFO Space Avail (before queue): %d\n",
1409 tx_status.b.ptxfspcavail);
1412 qh_ptr = hcd->periodic_sched_assigned.next;
1413 while (qh_ptr != &hcd->periodic_sched_assigned) {
1414 tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
1415 if (tx_status.b.ptxqspcavail == 0) {
1420 qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
1423 * Set a flag if we're queuing high-bandwidth in slave mode.
1424 * The flag prevents any halts to get into the request queue in
1425 * the middle of multiple high-bandwidth packets getting queued.
1427 if (!hcd->core_if->dma_enable && qh->channel->multi_count > 1) {
1428 hcd->core_if->queuing_high_bandwidth = 1;
1431 queue_transaction(hcd, qh->channel,
1432 tx_status.b.ptxfspcavail);
1439 * In Slave mode, stay on the current transfer until there is
1440 * nothing more to do or the high-bandwidth request count is
1441 * reached. In DMA mode, only need to queue one request. The
1442 * controller automatically handles multiple packets for
1443 * high-bandwidth transfers.
1445 if (hcd->core_if->dma_enable || status == 0 ||
1446 qh->channel->requests == qh->channel->multi_count) {
1447 qh_ptr = qh_ptr->next;
1449 * Move the QH from the periodic assigned schedule to
1450 * the periodic queued schedule.
1452 DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_queued,
1453 &qh->qh_list_entry);
1455 /* done queuing high bandwidth */
1456 hcd->core_if->queuing_high_bandwidth = 0;
1460 if (!hcd->core_if->dma_enable) {
1461 dwc_otg_core_global_regs_t *global_regs;
1462 gintmsk_data_t intr_mask = {.d32 = 0 };
1464 global_regs = hcd->core_if->core_global_regs;
1465 intr_mask.b.ptxfempty = 1;
1467 tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
1468 DWC_DEBUGPL(DBG_HCDV,
1469 " P Tx Req Queue Space Avail (after queue): %d\n",
1470 tx_status.b.ptxqspcavail);
1471 DWC_DEBUGPL(DBG_HCDV,
1472 " P Tx FIFO Space Avail (after queue): %d\n",
1473 tx_status.b.ptxfspcavail);
1475 if (!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned) ||
1476 no_queue_space || no_fifo_space) {
1478 * May need to queue more transactions as the request
1479 * queue or Tx FIFO empties. Enable the periodic Tx
1480 * FIFO empty interrupt. (Always use the half-empty
1481 * level to ensure that new requests are loaded as
1482 * soon as possible.)
1484 DWC_MODIFY_REG32(&global_regs->gintmsk, 0,
1488 * Disable the Tx FIFO empty interrupt since there are
1489 * no more transactions that need to be queued right
1490 * now. This function is called from interrupt
1491 * handlers to queue more transactions as transfer
1494 DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32,
1501 * Processes active non-periodic channels and queues transactions for these
1502 * channels to the DWC_otg controller. After queueing transactions, the NP Tx
1503 * FIFO Empty interrupt is enabled if there are more transactions to queue as
1504 * NP Tx FIFO or request queue space becomes available. Otherwise, the NP Tx
1505 * FIFO Empty interrupt is disabled.
1507 static void process_non_periodic_channels(dwc_otg_hcd_t *hcd)
1509 gnptxsts_data_t tx_status;
1510 dwc_list_link_t *orig_qh_ptr;
1513 int no_queue_space = 0;
1514 int no_fifo_space = 0;
1517 dwc_otg_core_global_regs_t *global_regs =
1518 hcd->core_if->core_global_regs;
1520 DWC_DEBUGPL(DBG_HCDV, "Queue non-periodic transactions\n");
1522 tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
1523 DWC_DEBUGPL(DBG_HCDV,
1524 " NP Tx Req Queue Space Avail (before queue): %d\n",
1525 tx_status.b.nptxqspcavail);
1526 DWC_DEBUGPL(DBG_HCDV, " NP Tx FIFO Space Avail (before queue): %d\n",
1527 tx_status.b.nptxfspcavail);
1530 * Keep track of the starting point. Skip over the start-of-list
1533 if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {
1534 hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
1536 orig_qh_ptr = hcd->non_periodic_qh_ptr;
1539 * Process once through the active list or until no more space is
1540 * available in the request queue or the Tx FIFO.
1543 tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
1544 if (!hcd->core_if->dma_enable && tx_status.b.nptxqspcavail == 0) {
1549 qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t,
1552 queue_transaction(hcd, qh->channel,
1553 tx_status.b.nptxfspcavail);
1557 } else if (status < 0) {
1562 /* Advance to next QH, skipping start-of-list entry. */
1563 hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
1564 if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {
1565 hcd->non_periodic_qh_ptr =
1566 hcd->non_periodic_qh_ptr->next;
1569 } while (hcd->non_periodic_qh_ptr != orig_qh_ptr);
1571 if (!hcd->core_if->dma_enable) {
1572 gintmsk_data_t intr_mask = {.d32 = 0 };
1573 intr_mask.b.nptxfempty = 1;
1576 tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
1577 DWC_DEBUGPL(DBG_HCDV,
1578 " NP Tx Req Queue Space Avail (after queue): %d\n",
1579 tx_status.b.nptxqspcavail);
1580 DWC_DEBUGPL(DBG_HCDV,
1581 " NP Tx FIFO Space Avail (after queue): %d\n",
1582 tx_status.b.nptxfspcavail);
1584 if (more_to_do || no_queue_space || no_fifo_space) {
1586 * May need to queue more transactions as the request
1587 * queue or Tx FIFO empties. Enable the non-periodic
1588 * Tx FIFO empty interrupt. (Always use the half-empty
1589 * level to ensure that new requests are loaded as
1590 * soon as possible.)
1592 DWC_MODIFY_REG32(&global_regs->gintmsk, 0,
1596 * Disable the Tx FIFO empty interrupt since there are
1597 * no more transactions that need to be queued right
1598 * now. This function is called from interrupt
1599 * handlers to queue more transactions as transfer
1602 DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32,
1609 * This function processes the currently active host channels and queues
1610 * transactions for these channels to the DWC_otg controller. It is called
1611 * from HCD interrupt handler functions.
1613 * @param hcd The HCD state structure.
1614 * @param tr_type The type(s) of transactions to queue (non-periodic,
1615 * periodic, or both).
1617 void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t *hcd,
1618 dwc_otg_transaction_type_e tr_type)
1621 DWC_DEBUGPL(DBG_HCD, "Queue Transactions\n");
1623 /* Process host channels associated with periodic transfers. */
1624 if ((tr_type == DWC_OTG_TRANSACTION_PERIODIC ||
1625 tr_type == DWC_OTG_TRANSACTION_ALL) &&
1626 !DWC_LIST_EMPTY(&hcd->periodic_sched_assigned)) {
1628 process_periodic_channels(hcd);
1631 /* Process host channels associated with non-periodic transfers. */
1632 if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC ||
1633 tr_type == DWC_OTG_TRANSACTION_ALL) {
1634 if (!DWC_LIST_EMPTY(&hcd->non_periodic_sched_active)) {
1635 process_non_periodic_channels(hcd);
1638 * Ensure NP Tx FIFO empty interrupt is disabled when
1639 * there are no non-periodic transfers to process.
1641 gintmsk_data_t gintmsk = {.d32 = 0 };
1642 gintmsk.b.nptxfempty = 1;
1643 DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->
1644 gintmsk, gintmsk.d32, 0);
1649 #ifdef DWC_HS_ELECT_TST
1651 * Quick and dirty hack to implement the HS Electrical Test
1652 * SINGLE_STEP_GET_DEVICE_DESCRIPTOR feature.
1654 * This code was copied from our userspace app "hset". It sends a
1655 * Get Device Descriptor control sequence in two parts, first the
1656 * Setup packet by itself, followed some time later by the In and
1657 * Ack packets. Rather than trying to figure out how to add this
1658 * functionality to the normal driver code, we just hijack the
1659 * hardware, using these two function to drive the hardware
1663 static dwc_otg_core_global_regs_t *global_regs;
1664 static dwc_otg_host_global_regs_t *hc_global_regs;
1665 static dwc_otg_hc_regs_t *hc_regs;
1666 static uint32_t *data_fifo;
1668 static void do_setup(void)
1670 gintsts_data_t gintsts;
1671 hctsiz_data_t hctsiz;
1672 hcchar_data_t hcchar;
1677 DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001);
1680 DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3);
1683 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1686 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
1689 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
1692 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1695 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
1698 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
1701 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
1704 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1707 * Send Setup packet (Get Device Descriptor)
1710 /* Make sure channel is disabled */
1711 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1712 if (hcchar.b.chen) {
1714 /* hcchar.b.chen = 1; */
1715 DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
1720 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1723 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
1726 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
1729 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1732 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
1735 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
1738 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
1740 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1745 hctsiz.b.xfersize = 8;
1746 hctsiz.b.pktcnt = 1;
1747 hctsiz.b.pid = DWC_OTG_HC_PID_SETUP;
1748 DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
1751 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1752 hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
1757 DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
1759 /* Fill FIFO with Setup data for Get Device Descriptor */
1760 data_fifo = (uint32_t *) ((char *)global_regs + 0x1000);
1761 DWC_WRITE_REG32(data_fifo++, 0x01000680);
1762 DWC_WRITE_REG32(data_fifo++, 0x00080000);
1764 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1766 /* Wait for host channel interrupt */
1768 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1769 } while (gintsts.b.hcintr == 0);
1771 /* Disable HCINTs */
1772 DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000);
1774 /* Disable HAINTs */
1775 DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000);
1778 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
1781 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
1784 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1787 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
1790 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
1793 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
1796 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1799 static void do_in_ack(void)
1801 gintsts_data_t gintsts;
1802 hctsiz_data_t hctsiz;
1803 hcchar_data_t hcchar;
1806 host_grxsts_data_t grxsts;
1809 DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001);
1812 DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3);
1815 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1818 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
1821 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
1824 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1827 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
1830 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
1833 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
1836 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1839 * Receive Control In packet
1842 /* Make sure channel is disabled */
1843 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1844 if (hcchar.b.chen) {
1847 DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
1852 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1855 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
1858 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
1861 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1864 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
1867 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
1870 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
1872 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1877 hctsiz.b.xfersize = 8;
1878 hctsiz.b.pktcnt = 1;
1879 hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;
1880 DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
1883 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1884 hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
1889 DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
1891 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1893 /* Wait for receive status queue interrupt */
1895 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1896 } while (gintsts.b.rxstsqlvl == 0);
1899 grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp);
1901 /* Clear RXSTSQLVL in GINTSTS */
1903 gintsts.b.rxstsqlvl = 1;
1904 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
1906 switch (grxsts.b.pktsts) {
1907 case DWC_GRXSTS_PKTSTS_IN:
1908 /* Read the data into the host buffer */
1909 if (grxsts.b.bcnt > 0) {
1911 int word_count = (grxsts.b.bcnt + 3) / 4;
1913 data_fifo = (uint32_t *) ((char *)global_regs + 0x1000);
1915 for (i = 0; i < word_count; i++) {
1916 (void)DWC_READ_REG32(data_fifo++);
1925 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1927 /* Wait for receive status queue interrupt */
1929 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1930 } while (gintsts.b.rxstsqlvl == 0);
1933 grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp);
1935 /* Clear RXSTSQLVL in GINTSTS */
1937 gintsts.b.rxstsqlvl = 1;
1938 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
1940 switch (grxsts.b.pktsts) {
1941 case DWC_GRXSTS_PKTSTS_IN_XFER_COMP:
1948 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1950 /* Wait for host channel interrupt */
1952 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1953 } while (gintsts.b.hcintr == 0);
1956 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
1959 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
1962 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1965 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
1968 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
1971 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
1974 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1976 /* usleep(100000); */
1981 * Send handshake packet
1985 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
1988 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
1991 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1994 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
1997 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
2000 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
2003 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
2005 /* Make sure channel is disabled */
2006 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
2007 if (hcchar.b.chen) {
2010 DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
2015 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
2018 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
2021 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
2024 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
2027 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
2030 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
2033 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
2035 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
2040 hctsiz.b.xfersize = 0;
2041 hctsiz.b.pktcnt = 1;
2042 hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;
2043 DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
2046 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
2047 hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
2052 DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
2054 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
2056 /* Wait for host channel interrupt */
2058 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
2059 } while (gintsts.b.hcintr == 0);
2061 /* Disable HCINTs */
2062 DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000);
2064 /* Disable HAINTs */
2065 DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000);
2068 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
2071 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
2074 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
2077 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
2080 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
2083 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
2086 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
2090 /** Handles hub class-specific requests. */
2091 int dwc_otg_hcd_hub_control(dwc_otg_hcd_t *dwc_otg_hcd,
2094 uint16_t wIndex, uint8_t *buf, uint16_t wLength)
2098 dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
2099 usb_hub_descriptor_t *hub_desc;
2100 hprt0_data_t hprt0 = {.d32 = 0 };
2102 uint32_t port_status;
2105 case UCR_CLEAR_HUB_FEATURE:
2106 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2107 "ClearHubFeature 0x%x\n", wValue);
2109 case UHF_C_HUB_LOCAL_POWER:
2110 case UHF_C_HUB_OVER_CURRENT:
2111 /* Nothing required here */
2114 retval = -DWC_E_INVALID;
2115 DWC_ERROR("DWC OTG HCD - "
2116 "ClearHubFeature request %xh unknown\n",
2120 case UCR_CLEAR_PORT_FEATURE:
2121 #ifdef CONFIG_USB_DWC_OTG_LPM
2122 if (wValue != UHF_PORT_L1)
2124 if (!wIndex || wIndex > 1)
2128 case UHF_PORT_ENABLE:
2129 DWC_DEBUGPL(DBG_ANY, "DWC OTG HCD HUB CONTROL - "
2130 "ClearPortFeature USB_PORT_FEAT_ENABLE\n");
2131 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2133 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
2135 case UHF_PORT_SUSPEND:
2136 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2137 "ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
2139 if (core_if->power_down == 2) {
2140 dwc_otg_host_hibernation_restore(core_if, 0, 0);
2142 DWC_WRITE_REG32(core_if->pcgcctl, 0);
2145 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2147 DWC_WRITE_REG32(core_if->host_if->hprt0,
2149 hprt0.b.prtsusp = 0;
2150 /* Clear Resume bit */
2153 DWC_WRITE_REG32(core_if->host_if->hprt0,
2157 #ifdef CONFIG_USB_DWC_OTG_LPM
2160 pcgcctl_data_t pcgcctl = {.d32 = 0 };
2161 glpmcfg_data_t lpmcfg = {.d32 = 0 };
2164 DWC_READ_REG32(&core_if->core_global_regs->
2166 lpmcfg.b.en_utmi_sleep = 0;
2167 lpmcfg.b.hird_thres &= (~(1 << 4));
2168 lpmcfg.b.prt_sleep_sts = 1;
2169 DWC_WRITE_REG32(&core_if->core_global_regs->
2170 glpmcfg, lpmcfg.d32);
2172 /* Clear Enbl_L1Gating bit. */
2173 pcgcctl.b.enbl_sleep_gating = 1;
2174 DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32,
2179 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2181 DWC_WRITE_REG32(core_if->host_if->hprt0,
2183 /* This bit will be cleared in wakeup interrupt handle */
2187 case UHF_PORT_POWER:
2188 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2189 "ClearPortFeature USB_PORT_FEAT_POWER\n");
2190 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2192 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
2194 case UHF_PORT_INDICATOR:
2195 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2196 "ClearPortFeature USB_PORT_FEAT_INDICATOR\n");
2197 /* Port inidicator not supported */
2199 case UHF_C_PORT_CONNECTION:
2200 /* Clears drivers internal connect status change
2202 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2203 "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n");
2204 dwc_otg_hcd->flags.b.port_connect_status_change = 0;
2206 case UHF_C_PORT_RESET:
2207 /* Clears the driver's internal Port Reset Change
2209 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2210 "ClearPortFeature USB_PORT_FEAT_C_RESET\n");
2211 dwc_otg_hcd->flags.b.port_reset_change = 0;
2213 case UHF_C_PORT_ENABLE:
2214 /* Clears the driver's internal Port
2215 * Enable/Disable Change flag */
2216 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2217 "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n");
2218 dwc_otg_hcd->flags.b.port_enable_change = 0;
2220 case UHF_C_PORT_SUSPEND:
2221 /* Clears the driver's internal Port Suspend
2222 * Change flag, which is set when resume signaling on
2223 * the host port is complete */
2224 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2225 "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n");
2226 dwc_otg_hcd->flags.b.port_suspend_change = 0;
2228 #ifdef CONFIG_USB_DWC_OTG_LPM
2230 dwc_otg_hcd->flags.b.port_l1_change = 0;
2233 case UHF_C_PORT_OVER_CURRENT:
2234 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2235 "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n");
2236 dwc_otg_hcd->flags.b.port_over_current_change = 0;
2239 retval = -DWC_E_INVALID;
2240 DWC_ERROR("DWC OTG HCD - "
2241 "ClearPortFeature request %xh "
2242 "unknown or unsupported\n", wValue);
2245 case UCR_GET_HUB_DESCRIPTOR:
2246 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2247 "GetHubDescriptor\n");
2248 hub_desc = (usb_hub_descriptor_t *) buf;
2249 hub_desc->bDescLength = 9;
2250 hub_desc->bDescriptorType = 0x29;
2251 hub_desc->bNbrPorts = 1;
2252 USETW(hub_desc->wHubCharacteristics, 0x08);
2253 hub_desc->bPwrOn2PwrGood = 1;
2254 hub_desc->bHubContrCurrent = 0;
2255 hub_desc->DeviceRemovable[0] = 0;
2256 hub_desc->DeviceRemovable[1] = 0xff;
2258 case UCR_GET_HUB_STATUS:
2259 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2261 DWC_MEMSET(buf, 0, 4);
2263 case UCR_GET_PORT_STATUS:
2264 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2265 "GetPortStatus wIndex = 0x%04x FLAGS=0x%08x\n",
2266 wIndex, dwc_otg_hcd->flags.d32);
2267 if (!wIndex || wIndex > 1)
2272 if (dwc_otg_hcd->flags.b.port_connect_status_change)
2273 port_status |= (1 << UHF_C_PORT_CONNECTION);
2275 if (dwc_otg_hcd->flags.b.port_enable_change)
2276 port_status |= (1 << UHF_C_PORT_ENABLE);
2278 if (dwc_otg_hcd->flags.b.port_suspend_change)
2279 port_status |= (1 << UHF_C_PORT_SUSPEND);
2281 if (dwc_otg_hcd->flags.b.port_l1_change)
2282 port_status |= (1 << UHF_C_PORT_L1);
2284 if (dwc_otg_hcd->flags.b.port_reset_change) {
2285 port_status |= (1 << UHF_C_PORT_RESET);
2288 if (dwc_otg_hcd->flags.b.port_over_current_change) {
2289 DWC_WARN("Overcurrent change detected\n");
2290 port_status |= (1 << UHF_C_PORT_OVER_CURRENT);
2293 if (!dwc_otg_hcd->flags.b.port_connect_status) {
2295 * The port is disconnected, which means the core is
2296 * either in device mode or it soon will be. Just
2297 * return 0's for the remainder of the port status
2298 * since the port register can't be read if the core
2299 * is in device mode.
2301 *((__le32 *) buf) = dwc_cpu_to_le32(&port_status);
2305 hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
2306 DWC_DEBUGPL(DBG_HCDV, " HPRT0: 0x%08x\n", hprt0.d32);
2308 if (hprt0.b.prtconnsts)
2309 port_status |= (1 << UHF_PORT_CONNECTION);
2312 port_status |= (1 << UHF_PORT_ENABLE);
2314 if (hprt0.b.prtsusp)
2315 port_status |= (1 << UHF_PORT_SUSPEND);
2317 if (hprt0.b.prtovrcurract)
2318 port_status |= (1 << UHF_PORT_OVER_CURRENT);
2321 port_status |= (1 << UHF_PORT_RESET);
2324 port_status |= (1 << UHF_PORT_POWER);
2326 if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED)
2327 port_status |= (1 << UHF_PORT_HIGH_SPEED);
2328 else if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED)
2329 port_status |= (1 << UHF_PORT_LOW_SPEED);
2331 if (hprt0.b.prttstctl)
2332 port_status |= (1 << UHF_PORT_TEST);
2333 if (dwc_otg_get_lpm_portsleepstatus(dwc_otg_hcd->core_if)) {
2334 port_status |= (1 << UHF_PORT_L1);
2337 For Synopsys HW emulation of Power down wkup_control asserts the
2338 hreset_n and prst_n on suspned. This causes the HPRT0 to be zero.
2339 We intentionally tell the software that port is in L2Suspend state.
2342 if ((core_if->power_down == 2)
2343 && (core_if->hibernation_suspend == 1)) {
2344 port_status |= (1 << UHF_PORT_SUSPEND);
2346 /* USB_PORT_FEAT_INDICATOR unsupported always 0 */
2348 *((__le32 *) buf) = dwc_cpu_to_le32(&port_status);
2351 case UCR_SET_HUB_FEATURE:
2352 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2354 /* No HUB features supported */
2356 case UCR_SET_PORT_FEATURE:
2357 if (wValue != UHF_PORT_TEST && (!wIndex || wIndex > 1))
2360 if (!dwc_otg_hcd->flags.b.port_connect_status) {
2362 * The port is disconnected, which means the core is
2363 * either in device mode or it soon will be. Just
2364 * return without doing anything since the port
2365 * register can't be written if the core is in device
2372 case UHF_PORT_SUSPEND:
2373 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2374 "SetPortFeature - USB_PORT_FEAT_SUSPEND\n");
2375 if (dwc_otg_hcd_otg_port(dwc_otg_hcd) != wIndex) {
2378 if (core_if->power_down == 2) {
2380 dwc_irqflags_t flags;
2381 pcgcctl_data_t pcgcctl = {.d32 = 0 };
2382 gpwrdn_data_t gpwrdn = {.d32 = 0 };
2383 gusbcfg_data_t gusbcfg = {.d32 = 0 };
2384 #ifdef DWC_DEV_SRPCAP
2385 int32_t otg_cap_param =
2386 core_if->core_params->otg_cap;
2389 ("Preparing for complete power-off\n");
2391 /* Save registers before hibernation */
2392 dwc_otg_save_global_regs(core_if);
2393 dwc_otg_save_host_regs(core_if);
2395 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2396 hprt0.b.prtsusp = 1;
2398 DWC_WRITE_REG32(core_if->host_if->hprt0,
2400 /* Spin hprt0.b.prtsusp to became 1 */
2402 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2403 if (hprt0.b.prtsusp) {
2407 } while (--timeout);
2409 DWC_WARN("Suspend wasn't genereted\n");
2414 * We need to disable interrupts to prevent servicing of any IRQ
2415 * during going to hibernation
2417 DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
2418 core_if->lx_state = DWC_OTG_L2;
2419 #ifdef DWC_DEV_SRPCAP
2420 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2423 DWC_WRITE_REG32(core_if->host_if->hprt0,
2427 DWC_READ_REG32(&core_if->
2428 core_global_regs->gusbcfg);
2429 if (gusbcfg.b.ulpi_utmi_sel == 1) {
2430 /* ULPI interface */
2431 /* Suspend the Phy Clock */
2433 pcgcctl.b.stoppclk = 1;
2434 DWC_MODIFY_REG32(core_if->pcgcctl, 0,
2437 gpwrdn.b.pmuactv = 1;
2439 (&core_if->core_global_regs->gpwrdn,
2442 /* UTMI+ Interface */
2443 gpwrdn.b.pmuactv = 1;
2445 (&core_if->core_global_regs->gpwrdn,
2448 pcgcctl.b.stoppclk = 1;
2449 DWC_MODIFY_REG32(core_if->pcgcctl, 0,
2453 #ifdef DWC_DEV_SRPCAP
2455 gpwrdn.b.dis_vbus = 1;
2456 DWC_MODIFY_REG32(&core_if->
2457 core_global_regs->gpwrdn, 0,
2461 gpwrdn.b.pmuintsel = 1;
2462 DWC_MODIFY_REG32(&core_if->
2463 core_global_regs->gpwrdn, 0,
2468 #ifdef DWC_DEV_SRPCAP
2469 gpwrdn.b.srp_det_msk = 1;
2471 gpwrdn.b.disconn_det_msk = 1;
2472 gpwrdn.b.lnstchng_msk = 1;
2473 gpwrdn.b.sts_chngint_msk = 1;
2474 DWC_MODIFY_REG32(&core_if->
2475 core_global_regs->gpwrdn, 0,
2479 /* Enable Power Down Clamp and all interrupts in GPWRDN */
2481 gpwrdn.b.pwrdnclmp = 1;
2482 DWC_MODIFY_REG32(&core_if->
2483 core_global_regs->gpwrdn, 0,
2487 /* Switch off VDD */
2489 gpwrdn.b.pwrdnswtch = 1;
2490 DWC_MODIFY_REG32(&core_if->
2491 core_global_regs->gpwrdn, 0,
2494 #ifdef DWC_DEV_SRPCAP
2495 if (otg_cap_param ==
2496 DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
2497 core_if->pwron_timer_started = 1;
2498 DWC_TIMER_SCHEDULE(core_if->pwron_timer,
2502 /* Save gpwrdn register for further usage if stschng interrupt */
2503 core_if->gr_backup->gpwrdn_local =
2504 DWC_READ_REG32(&core_if->core_global_regs->
2507 /* Set flag to indicate that we are in hibernation */
2508 core_if->hibernation_suspend = 1;
2509 DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock,
2512 DWC_PRINTF("Host hibernation completed\n");
2513 /* Exit from case statement */
2517 if (dwc_otg_hcd_otg_port(dwc_otg_hcd) == wIndex &&
2518 dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) {
2519 gotgctl_data_t gotgctl = {.d32 = 0 };
2520 gotgctl.b.hstsethnpen = 1;
2521 DWC_MODIFY_REG32(&core_if->
2522 core_global_regs->gotgctl, 0,
2524 core_if->op_state = A_SUSPEND;
2526 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2527 hprt0.b.prtsusp = 1;
2528 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
2530 dwc_irqflags_t flags;
2531 /* Update lx_state */
2532 DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
2533 core_if->lx_state = DWC_OTG_L2;
2534 DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock,
2537 /* Suspend the Phy Clock */
2538 if (core_if->otg_ver == 0) {
2539 pcgcctl_data_t pcgcctl = {.d32 = 0 };
2540 pcgcctl.b.stoppclk = 1;
2541 DWC_MODIFY_REG32(core_if->pcgcctl, 0,
2546 /* For HNP the bus must be suspended for at least 200ms. */
2547 if (dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) {
2548 pcgcctl_data_t pcgcctl = {.d32 = 0 };
2549 pcgcctl.b.stoppclk = 1;
2550 DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32,
2555 /** @todo - check how sw can wait for 1 sec to check asesvld??? */
2557 if (core_if->adp_enable) {
2558 gotgctl_data_t gotgctl = {.d32 = 0 };
2559 gpwrdn_data_t gpwrdn;
2561 while (gotgctl.b.asesvld == 1) {
2564 (&core_if->core_global_regs->gotgctl);
2568 /* Enable Power Down Logic */
2570 gpwrdn.b.pmuactv = 1;
2571 DWC_MODIFY_REG32(&core_if->
2572 core_global_regs->gpwrdn, 0,
2575 /* Unmask SRP detected interrupt from Power Down Logic */
2577 gpwrdn.b.srp_det_msk = 1;
2578 DWC_MODIFY_REG32(&core_if->
2579 core_global_regs->gpwrdn, 0,
2582 dwc_otg_adp_probe_start(core_if);
2586 case UHF_PORT_POWER:
2587 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2588 "SetPortFeature - USB_PORT_FEAT_POWER\n");
2589 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2591 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
2593 case UHF_PORT_RESET:
2594 if ((core_if->power_down == 2)
2595 && (core_if->hibernation_suspend == 1)) {
2596 /* If we are going to exit from Hibernated
2597 * state via USB RESET.
2599 dwc_otg_host_hibernation_restore(core_if, 0, 1);
2601 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2603 DWC_DEBUGPL(DBG_HCD,
2604 "DWC OTG HCD HUB CONTROL - "
2605 "SetPortFeature - USB_PORT_FEAT_RESET\n");
2607 pcgcctl_data_t pcgcctl = {.d32 = 0 };
2608 pcgcctl.b.enbl_sleep_gating = 1;
2609 pcgcctl.b.stoppclk = 1;
2610 DWC_MODIFY_REG32(core_if->pcgcctl,
2612 DWC_WRITE_REG32(core_if->pcgcctl, 0);
2614 #ifdef CONFIG_USB_DWC_OTG_LPM
2616 glpmcfg_data_t lpmcfg;
2618 DWC_READ_REG32(&core_if->
2621 if (lpmcfg.b.prt_sleep_sts) {
2622 lpmcfg.b.en_utmi_sleep = 0;
2623 lpmcfg.b.hird_thres &=
2625 DWC_WRITE_REG32(&core_if->
2633 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2634 /* Clear suspend bit if resetting from suspended state. */
2635 hprt0.b.prtsusp = 0;
2636 /* When B-Host the Port reset bit is set in
2637 * the Start HCD Callback function, so that
2638 * the reset is started within 1ms of the HNP
2639 * success interrupt. */
2640 if (!dwc_otg_hcd_is_b_host(dwc_otg_hcd)) {
2644 ("Indeed it is in host mode hprt0 = %08x\n",
2646 DWC_WRITE_REG32(core_if->host_if->hprt0,
2649 /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */
2652 DWC_WRITE_REG32(core_if->host_if->hprt0,
2654 core_if->lx_state = DWC_OTG_L0; /* Now back to the on state */
2657 #ifdef DWC_HS_ELECT_TST
2661 gintmsk_data_t gintmsk;
2663 t = (wIndex >> 8); /* MSB wIndex USB */
2664 DWC_DEBUGPL(DBG_HCD,
2665 "DWC OTG HCD HUB CONTROL - "
2666 "SetPortFeature - USB_PORT_FEAT_TEST %d\n",
2668 DWC_WARN("USB_PORT_FEAT_TEST %d\n", t);
2670 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2671 hprt0.b.prttstctl = t;
2672 DWC_WRITE_REG32(core_if->host_if->hprt0,
2675 /* Setup global vars with reg addresses (quick and
2676 * dirty hack, should be cleaned up)
2678 global_regs = core_if->core_global_regs;
2680 core_if->host_if->host_global_regs;
2682 (dwc_otg_hc_regs_t *) ((char *)
2686 (uint32_t *) ((char *)global_regs +
2689 if (t == 6) { /* HS_HOST_PORT_SUSPEND_RESUME */
2690 /* Save current interrupt mask */
2693 (&global_regs->gintmsk);
2695 /* Disable all interrupts while we muck with
2696 * the hardware directly
2698 DWC_WRITE_REG32(&global_regs->
2701 /* 15 second delay per the test spec */
2704 /* Drive suspend on the root port */
2706 dwc_otg_read_hprt0(core_if);
2707 hprt0.b.prtsusp = 1;
2709 DWC_WRITE_REG32(core_if->
2713 /* 15 second delay per the test spec */
2716 /* Drive resume on the root port */
2718 dwc_otg_read_hprt0(core_if);
2719 hprt0.b.prtsusp = 0;
2721 DWC_WRITE_REG32(core_if->
2726 /* Clear the resume bit */
2728 DWC_WRITE_REG32(core_if->
2732 /* Restore interrupts */
2733 DWC_WRITE_REG32(&global_regs->
2736 } else if (t == 7) { /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */
2737 /* Save current interrupt mask */
2740 (&global_regs->gintmsk);
2742 /* Disable all interrupts while we muck with
2743 * the hardware directly
2745 DWC_WRITE_REG32(&global_regs->
2748 /* 15 second delay per the test spec */
2751 /* Send the Setup packet */
2754 /* 15 second delay so nothing else happens for awhile */
2757 /* Restore interrupts */
2758 DWC_WRITE_REG32(&global_regs->
2761 } else if (t == 8) { /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */
2762 /* Save current interrupt mask */
2765 (&global_regs->gintmsk);
2767 /* Disable all interrupts while we muck with
2768 * the hardware directly
2770 DWC_WRITE_REG32(&global_regs->
2773 /* Send the Setup packet */
2776 /* 15 second delay so nothing else happens for awhile */
2779 /* Send the In and Ack packets */
2782 /* 15 second delay so nothing else happens for awhile */
2785 /* Restore interrupts */
2786 DWC_WRITE_REG32(&global_regs->
2793 #endif /* DWC_HS_ELECT_TST */
2795 case UHF_PORT_INDICATOR:
2796 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2797 "SetPortFeature - USB_PORT_FEAT_INDICATOR\n");
2801 retval = -DWC_E_INVALID;
2802 DWC_ERROR("DWC OTG HCD - "
2803 "SetPortFeature request %xh "
2804 "unknown or unsupported\n", wValue);
2808 #ifdef CONFIG_USB_DWC_OTG_LPM
2809 case UCR_SET_AND_TEST_PORT_FEATURE:
2810 if (wValue != UHF_PORT_L1) {
2814 int portnum, hird, devaddr, remwake;
2815 glpmcfg_data_t lpmcfg;
2816 uint32_t time_usecs;
2817 gintsts_data_t gintsts;
2818 gintmsk_data_t gintmsk;
2820 if (!dwc_otg_get_param_lpm_enable(core_if)) {
2823 if (wValue != UHF_PORT_L1 || wLength != 1) {
2826 /* Check if the port currently is in SLEEP state */
2828 DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
2829 if (lpmcfg.b.prt_sleep_sts) {
2830 DWC_INFO("Port is already in sleep mode\n");
2831 buf[0] = 0; /* Return success */
2835 portnum = wIndex & 0xf;
2836 hird = (wIndex >> 4) & 0xf;
2837 devaddr = (wIndex >> 8) & 0x7f;
2838 remwake = (wIndex >> 15);
2841 retval = -DWC_E_INVALID;
2843 ("Wrong port number(%d) in SetandTestPortFeature request\n",
2849 ("SetandTestPortFeature request: portnum = %d, hird = %d, devaddr = %d, rewake = %d\n",
2850 portnum, hird, devaddr, remwake);
2851 /* Disable LPM interrupt */
2853 gintmsk.b.lpmtranrcvd = 1;
2854 DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
2857 if (dwc_otg_hcd_send_lpm
2858 (dwc_otg_hcd, devaddr, hird, remwake)) {
2859 retval = -DWC_E_INVALID;
2863 time_usecs = 10 * (lpmcfg.b.retry_count + 1);
2864 /* We will consider timeout if time_usecs microseconds pass,
2865 * and we don't receive LPM transaction status.
2866 * After receiving non-error responce(ACK/NYET/STALL) from device,
2867 * core will set lpmtranrcvd bit.
2871 DWC_READ_REG32(&core_if->core_global_regs->
2873 if (gintsts.b.lpmtranrcvd) {
2877 } while (--time_usecs);
2878 /* lpm_int bit will be cleared in LPM interrupt handler */
2885 if (!gintsts.b.lpmtranrcvd) {
2886 buf[0] = 0x3; /* Completion code is Timeout */
2887 dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd);
2890 DWC_READ_REG32(&core_if->core_global_regs->
2892 if (lpmcfg.b.lpm_resp == 0x3) {
2893 /* ACK responce from the device */
2894 buf[0] = 0x00; /* Success */
2895 } else if (lpmcfg.b.lpm_resp == 0x2) {
2896 /* NYET responce from the device */
2899 /* Otherwise responce with Timeout */
2903 DWC_PRINTF("Device responce to LPM trans is %x\n",
2905 DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0,
2910 #endif /* CONFIG_USB_DWC_OTG_LPM */
2913 retval = -DWC_E_INVALID;
2914 DWC_WARN("DWC OTG HCD - "
2915 "Unknown hub control request type or invalid typeReq: %xh wIndex: %xh wValue: %xh\n",
2916 typeReq, wIndex, wValue);
2923 #ifdef CONFIG_USB_DWC_OTG_LPM
2924 /** Returns index of host channel to perform LPM transaction. */
2925 int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t *hcd, uint8_t devaddr)
2927 dwc_otg_core_if_t *core_if = hcd->core_if;
2929 hcchar_data_t hcchar;
2930 gintmsk_data_t gintmsk = {.d32 = 0 };
2932 if (DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
2933 DWC_PRINTF("No free channel to select for LPM transaction\n");
2937 hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);
2939 /* Mask host channel interrupts. */
2940 gintmsk.b.hcintr = 1;
2941 DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0);
2943 /* Fill fields that core needs for LPM transaction */
2944 hcchar.b.devaddr = devaddr;
2946 hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
2948 hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW);
2949 hcchar.b.epdir = 0; /* OUT */
2950 DWC_WRITE_REG32(&core_if->host_if->hc_regs[hc->hc_num]->hcchar,
2953 /* Remove the host channel from the free list. */
2954 DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry);
2956 DWC_PRINTF("hcnum = %d devaddr = %d\n", hc->hc_num, devaddr);
2961 /** Release hc after performing LPM transaction */
2962 void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t *hcd)
2965 glpmcfg_data_t lpmcfg;
2968 lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg);
2969 hc_num = lpmcfg.b.lpm_chan_index;
2971 hc = hcd->hc_ptr_array[hc_num];
2973 DWC_PRINTF("Freeing channel %d after LPM\n", hc_num);
2974 /* Return host channel to free list */
2975 DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
2978 int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t *hcd, uint8_t devaddr, uint8_t hird,
2979 uint8_t bRemoteWake)
2981 glpmcfg_data_t lpmcfg;
2982 pcgcctl_data_t pcgcctl = {.d32 = 0 };
2985 channel = dwc_otg_hcd_get_hc_for_lpm_tran(hcd, devaddr);
2990 pcgcctl.b.enbl_sleep_gating = 1;
2991 DWC_MODIFY_REG32(hcd->core_if->pcgcctl, 0, pcgcctl.d32);
2993 /* Read LPM config register */
2994 lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg);
2996 /* Program LPM transaction fields */
2997 lpmcfg.b.rem_wkup_en = bRemoteWake;
2998 lpmcfg.b.hird = hird;
3000 if (dwc_otg_get_param_besl_enable(hcd->core_if)) {
3001 lpmcfg.b.hird_thres = 0x16;
3002 lpmcfg.b.en_besl = 1;
3004 lpmcfg.b.hird_thres = 0x1c;
3007 lpmcfg.b.lpm_chan_index = channel;
3008 lpmcfg.b.en_utmi_sleep = 1;
3009 /* Program LPM config register */
3010 DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);
3012 /* Send LPM transaction */
3013 lpmcfg.b.send_lpm = 1;
3014 DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);
3019 #endif /* CONFIG_USB_DWC_OTG_LPM */
3021 int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t *hcd, int port)
3026 return -DWC_E_INVALID;
3029 retval = (hcd->flags.b.port_connect_status_change ||
3030 hcd->flags.b.port_reset_change ||
3031 hcd->flags.b.port_enable_change ||
3032 hcd->flags.b.port_suspend_change ||
3033 hcd->flags.b.port_over_current_change);
3036 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB STATUS DATA:"
3037 " Root port status changed\n");
3038 DWC_DEBUGPL(DBG_HCDV, " port_connect_status_change: %d\n",
3039 hcd->flags.b.port_connect_status_change);
3040 DWC_DEBUGPL(DBG_HCDV, " port_reset_change: %d\n",
3041 hcd->flags.b.port_reset_change);
3042 DWC_DEBUGPL(DBG_HCDV, " port_enable_change: %d\n",
3043 hcd->flags.b.port_enable_change);
3044 DWC_DEBUGPL(DBG_HCDV, " port_suspend_change: %d\n",
3045 hcd->flags.b.port_suspend_change);
3046 DWC_DEBUGPL(DBG_HCDV, " port_over_current_change: %d\n",
3047 hcd->flags.b.port_over_current_change);
3053 int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t *dwc_otg_hcd)
3057 DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->
3058 host_global_regs->hfnum);
3061 DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD GET FRAME NUMBER %d\n",
3064 return hfnum.b.frnum;
3067 int dwc_otg_hcd_start(dwc_otg_hcd_t *hcd,
3068 struct dwc_otg_hcd_function_ops *fops)
3073 if (!dwc_otg_is_device_mode(hcd->core_if) &&
3074 (!hcd->core_if->adp_enable || hcd->core_if->adp.adp_started)) {
3075 dwc_otg_hcd_reinit(hcd);
3077 retval = -DWC_E_NO_DEVICE;
3083 void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t *hcd)
3088 void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t *hcd, void *priv_data)
3090 hcd->priv = priv_data;
3093 uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t *hcd)
3095 return hcd->otg_port;
3098 uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t *hcd)
3101 if (hcd->core_if->op_state == B_HOST) {
3110 dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t *hcd,
3111 int iso_desc_count, int atomic_alloc)
3113 dwc_otg_hcd_urb_t *dwc_otg_urb;
3117 sizeof(*dwc_otg_urb) +
3118 iso_desc_count * sizeof(struct dwc_otg_hcd_iso_packet_desc);
3120 dwc_otg_urb = DWC_ALLOC_ATOMIC(size);
3122 dwc_otg_urb = DWC_ALLOC(size);
3124 dwc_otg_urb->packet_count = iso_desc_count;
3129 void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t *dwc_otg_urb,
3130 uint8_t dev_addr, uint8_t ep_num,
3131 uint8_t ep_type, uint8_t ep_dir, uint16_t mps)
3133 dwc_otg_hcd_fill_pipe(&dwc_otg_urb->pipe_info, dev_addr, ep_num,
3134 ep_type, ep_dir, mps);
3137 ("addr = %d, ep_num = %d, ep_dir = 0x%x, ep_type = 0x%x, mps = %d\n",
3138 dev_addr, ep_num, ep_dir, ep_type, mps);
3142 void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t *dwc_otg_urb,
3143 void *urb_handle, void *buf, dwc_dma_t dma,
3144 uint32_t buflen, void *setup_packet,
3145 dwc_dma_t setup_dma, uint32_t flags,
3148 dwc_otg_urb->priv = urb_handle;
3149 dwc_otg_urb->buf = buf;
3150 dwc_otg_urb->dma = dma;
3151 dwc_otg_urb->length = buflen;
3152 dwc_otg_urb->setup_packet = setup_packet;
3153 dwc_otg_urb->setup_dma = setup_dma;
3154 dwc_otg_urb->flags = flags;
3155 dwc_otg_urb->interval = interval;
3156 dwc_otg_urb->status = -DWC_E_IN_PROGRESS;
3159 uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t *dwc_otg_urb)
3161 return dwc_otg_urb->status;
3164 uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t *dwc_otg_urb)
3166 return dwc_otg_urb->actual_length;
3169 uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t *dwc_otg_urb)
3171 return dwc_otg_urb->error_count;
3174 void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t *dwc_otg_urb,
3175 int desc_num, uint32_t offset,
3178 dwc_otg_urb->iso_descs[desc_num].offset = offset;
3179 dwc_otg_urb->iso_descs[desc_num].length = length;
3182 uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t *dwc_otg_urb,
3185 return dwc_otg_urb->iso_descs[desc_num].status;
3188 uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t *
3189 dwc_otg_urb, int desc_num)
3191 return dwc_otg_urb->iso_descs[desc_num].actual_length;
3194 int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t *hcd, void *ep_handle)
3197 dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
3200 if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) {
3207 int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t *hcd, void *ep_handle)
3209 dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
3211 DWC_ASSERT(qh, "qh is not allocated\n");
3213 if (DWC_LIST_EMPTY(&qh->qh_list_entry)) {
3220 uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t *hcd, void *ep_handle)
3222 dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
3223 DWC_ASSERT(qh, "qh is not allocated\n");
3227 void dwc_otg_hcd_dump_state(dwc_otg_hcd_t *hcd)
3232 gnptxsts_data_t np_tx_status;
3233 hptxsts_data_t p_tx_status;
3235 num_channels = hcd->core_if->core_params->host_channels;
3238 ("************************************************************\n");
3239 DWC_PRINTF("HCD State:\n");
3240 DWC_PRINTF(" Num channels: %d\n", num_channels);
3241 for (i = 0; i < num_channels; i++) {
3242 dwc_hc_t *hc = hcd->hc_ptr_array[i];
3243 DWC_PRINTF(" Channel %d:\n", i);
3244 DWC_PRINTF(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
3245 hc->dev_addr, hc->ep_num, hc->ep_is_in);
3246 DWC_PRINTF(" speed: %d\n", hc->speed);
3247 DWC_PRINTF(" ep_type: %d\n", hc->ep_type);
3248 DWC_PRINTF(" max_packet: %d\n", hc->max_packet);
3249 DWC_PRINTF(" data_pid_start: %d\n", hc->data_pid_start);
3250 DWC_PRINTF(" multi_count: %d\n", hc->multi_count);
3251 DWC_PRINTF(" xfer_started: %d\n", hc->xfer_started);
3252 DWC_PRINTF(" xfer_buff: %p\n", hc->xfer_buff);
3253 DWC_PRINTF(" xfer_len: %d\n", hc->xfer_len);
3254 DWC_PRINTF(" xfer_count: %d\n", hc->xfer_count);
3255 DWC_PRINTF(" halt_on_queue: %d\n", hc->halt_on_queue);
3256 DWC_PRINTF(" halt_pending: %d\n", hc->halt_pending);
3257 DWC_PRINTF(" halt_status: %d\n", hc->halt_status);
3258 DWC_PRINTF(" do_split: %d\n", hc->do_split);
3259 DWC_PRINTF(" complete_split: %d\n", hc->complete_split);
3260 DWC_PRINTF(" hub_addr: %d\n", hc->hub_addr);
3261 DWC_PRINTF(" port_addr: %d\n", hc->port_addr);
3262 DWC_PRINTF(" xact_pos: %d\n", hc->xact_pos);
3263 DWC_PRINTF(" requests: %d\n", hc->requests);
3264 DWC_PRINTF(" qh: %p\n", hc->qh);
3265 if (hc->xfer_started) {
3267 hcchar_data_t hcchar;
3268 hctsiz_data_t hctsiz;
3270 hcintmsk_data_t hcintmsk;
3272 DWC_READ_REG32(&hcd->core_if->host_if->
3273 host_global_regs->hfnum);
3275 DWC_READ_REG32(&hcd->core_if->host_if->hc_regs[i]->
3278 DWC_READ_REG32(&hcd->core_if->host_if->hc_regs[i]->
3281 DWC_READ_REG32(&hcd->core_if->host_if->hc_regs[i]->
3284 DWC_READ_REG32(&hcd->core_if->host_if->hc_regs[i]->
3286 DWC_PRINTF(" hfnum: 0x%08x\n", hfnum.d32);
3287 DWC_PRINTF(" hcchar: 0x%08x\n", hcchar.d32);
3288 DWC_PRINTF(" hctsiz: 0x%08x\n", hctsiz.d32);
3289 DWC_PRINTF(" hcint: 0x%08x\n", hcint.d32);
3290 DWC_PRINTF(" hcintmsk: 0x%08x\n", hcintmsk.d32);
3292 if (hc->xfer_started && hc->qh) {
3294 dwc_otg_hcd_urb_t *urb;
3296 DWC_CIRCLEQ_FOREACH(qtd, &hc->qh->qtd_list,
3298 if (!qtd->in_process)
3302 DWC_PRINTF(" URB Info:\n");
3303 DWC_PRINTF(" qtd: %p, urb: %p\n", qtd,
3306 DWC_PRINTF(" Dev: %d, EP: %d %s\n",
3307 dwc_otg_hcd_get_dev_addr
3309 dwc_otg_hcd_get_ep_num
3311 dwc_otg_hcd_is_pipe_in
3312 (&urb->pipe_info) ? "IN" :
3315 (" Max packet size: %d\n",
3319 (" transfer_buffer: %p\n",
3321 DWC_PRINTF(" transfer_dma: %p\n",
3324 (" transfer_buffer_length: %d\n",
3326 DWC_PRINTF(" actual_length: %d\n",
3327 urb->actual_length);
3332 DWC_PRINTF(" non_periodic_channels: %d\n", hcd->non_periodic_channels);
3333 DWC_PRINTF(" periodic_channels: %d\n", hcd->periodic_channels);
3334 DWC_PRINTF(" periodic_usecs: %d\n", hcd->periodic_usecs);
3336 DWC_READ_REG32(&hcd->core_if->core_global_regs->gnptxsts);
3337 DWC_PRINTF(" NP Tx Req Queue Space Avail: %d\n",
3338 np_tx_status.b.nptxqspcavail);
3339 DWC_PRINTF(" NP Tx FIFO Space Avail: %d\n",
3340 np_tx_status.b.nptxfspcavail);
3342 DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hptxsts);
3343 DWC_PRINTF(" P Tx Req Queue Space Avail: %d\n",
3344 p_tx_status.b.ptxqspcavail);
3345 DWC_PRINTF(" P Tx FIFO Space Avail: %d\n", p_tx_status.b.ptxfspcavail);
3346 dwc_otg_hcd_dump_frrem(hcd);
3347 dwc_otg_dump_global_registers(hcd->core_if);
3348 dwc_otg_dump_host_registers(hcd->core_if);
3350 ("************************************************************\n");
3356 void dwc_print_setup_data(uint8_t *setup)
3359 if (CHK_DEBUG_LEVEL(DBG_HCD)) {
3360 DWC_PRINTF("Setup Data = MSB ");
3361 for (i = 7; i >= 0; i--)
3362 DWC_PRINTF("%02x ", setup[i]);
3364 DWC_PRINTF(" bmRequestType Tranfer = %s\n",
3365 (setup[0] & 0x80) ? "Device-to-Host" :
3367 DWC_PRINTF(" bmRequestType Type = ");
3368 switch ((setup[0] & 0x60) >> 5) {
3370 DWC_PRINTF("Standard\n");
3373 DWC_PRINTF("Class\n");
3376 DWC_PRINTF("Vendor\n");
3379 DWC_PRINTF("Reserved\n");
3382 DWC_PRINTF(" bmRequestType Recipient = ");
3383 switch (setup[0] & 0x1f) {
3385 DWC_PRINTF("Device\n");
3388 DWC_PRINTF("Interface\n");
3391 DWC_PRINTF("Endpoint\n");
3394 DWC_PRINTF("Other\n");
3397 DWC_PRINTF("Reserved\n");
3400 DWC_PRINTF(" bRequest = 0x%0x\n", setup[1]);
3401 DWC_PRINTF(" wValue = 0x%0x\n", *((uint16_t *)&setup[2]));
3402 DWC_PRINTF(" wIndex = 0x%0x\n", *((uint16_t *)&setup[4]));
3403 DWC_PRINTF(" wLength = 0x%0x\n\n", *((uint16_t *)&setup[6]));
3408 void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t *hcd)
3411 DWC_PRINTF("Frame remaining at SOF:\n");
3412 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3413 hcd->frrem_samples, hcd->frrem_accum,
3414 (hcd->frrem_samples > 0) ?
3415 hcd->frrem_accum / hcd->frrem_samples : 0);
3418 DWC_PRINTF("Frame remaining at start_transfer (uframe 7):\n");
3419 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3420 hcd->core_if->hfnum_7_samples,
3421 hcd->core_if->hfnum_7_frrem_accum,
3422 (hcd->core_if->hfnum_7_samples >
3423 0) ? hcd->core_if->hfnum_7_frrem_accum /
3424 hcd->core_if->hfnum_7_samples : 0);
3425 DWC_PRINTF("Frame remaining at start_transfer (uframe 0):\n");
3426 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3427 hcd->core_if->hfnum_0_samples,
3428 hcd->core_if->hfnum_0_frrem_accum,
3429 (hcd->core_if->hfnum_0_samples >
3430 0) ? hcd->core_if->hfnum_0_frrem_accum /
3431 hcd->core_if->hfnum_0_samples : 0);
3432 DWC_PRINTF("Frame remaining at start_transfer (uframe 1-6):\n");
3433 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3434 hcd->core_if->hfnum_other_samples,
3435 hcd->core_if->hfnum_other_frrem_accum,
3436 (hcd->core_if->hfnum_other_samples >
3437 0) ? hcd->core_if->hfnum_other_frrem_accum /
3438 hcd->core_if->hfnum_other_samples : 0);
3441 DWC_PRINTF("Frame remaining at sample point A (uframe 7):\n");
3442 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3443 hcd->hfnum_7_samples_a, hcd->hfnum_7_frrem_accum_a,
3444 (hcd->hfnum_7_samples_a > 0) ?
3445 hcd->hfnum_7_frrem_accum_a / hcd->hfnum_7_samples_a : 0);
3446 DWC_PRINTF("Frame remaining at sample point A (uframe 0):\n");
3447 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3448 hcd->hfnum_0_samples_a, hcd->hfnum_0_frrem_accum_a,
3449 (hcd->hfnum_0_samples_a > 0) ?
3450 hcd->hfnum_0_frrem_accum_a / hcd->hfnum_0_samples_a : 0);
3451 DWC_PRINTF("Frame remaining at sample point A (uframe 1-6):\n");
3452 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3453 hcd->hfnum_other_samples_a, hcd->hfnum_other_frrem_accum_a,
3454 (hcd->hfnum_other_samples_a > 0) ?
3455 hcd->hfnum_other_frrem_accum_a /
3456 hcd->hfnum_other_samples_a : 0);
3459 DWC_PRINTF("Frame remaining at sample point B (uframe 7):\n");
3460 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3461 hcd->hfnum_7_samples_b, hcd->hfnum_7_frrem_accum_b,
3462 (hcd->hfnum_7_samples_b > 0) ?
3463 hcd->hfnum_7_frrem_accum_b / hcd->hfnum_7_samples_b : 0);
3464 DWC_PRINTF("Frame remaining at sample point B (uframe 0):\n");
3465 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3466 hcd->hfnum_0_samples_b, hcd->hfnum_0_frrem_accum_b,
3467 (hcd->hfnum_0_samples_b > 0) ?
3468 hcd->hfnum_0_frrem_accum_b / hcd->hfnum_0_samples_b : 0);
3469 DWC_PRINTF("Frame remaining at sample point B (uframe 1-6):\n");
3470 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3471 hcd->hfnum_other_samples_b, hcd->hfnum_other_frrem_accum_b,
3472 (hcd->hfnum_other_samples_b > 0) ?
3473 hcd->hfnum_other_frrem_accum_b /
3474 hcd->hfnum_other_samples_b : 0);
3478 #endif /* DWC_DEVICE_ONLY */