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 if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list))
179 qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
180 if (qtd->urb != NULL) {
181 hcd->fops->complete(hcd, qtd->urb->priv,
182 qtd->urb, -DWC_E_SHUTDOWN);
183 dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
193 * Responds with an error status of ETIMEDOUT to all URBs in the non-periodic
194 * and periodic schedules. The QTD associated with each URB is removed from
195 * the schedule and freed. This function may be called when a disconnect is
196 * detected or when the HCD is being stopped.
198 static void kill_all_urbs(dwc_otg_hcd_t *hcd)
200 kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_inactive);
201 kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_active);
202 kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_inactive);
203 kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_ready);
204 kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_assigned);
205 kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_queued);
209 * Start the connection timer. An OTG host is required to display a
210 * message if the device does not connect within 10 seconds. The
211 * timer is deleted if a port connect interrupt occurs before the
214 static void dwc_otg_hcd_start_connect_timer(dwc_otg_hcd_t *hcd)
216 DWC_TIMER_SCHEDULE(hcd->conn_timer, 10000 /* 10 secs */);
220 * HCD Callback function for disconnect of the HCD.
222 * @param p void pointer to the <code>struct usb_hcd</code>
224 static int32_t dwc_otg_hcd_session_start_cb(void *p)
226 dwc_otg_hcd_t *dwc_otg_hcd;
227 DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p);
229 dwc_otg_hcd_start_connect_timer(dwc_otg_hcd);
234 * HCD Callback function for starting the HCD when A-Cable is
237 * @param p void pointer to the <code>struct usb_hcd</code>
239 static int32_t dwc_otg_hcd_start_cb(void *p)
241 dwc_otg_hcd_t *dwc_otg_hcd = p;
242 dwc_otg_core_if_t *core_if;
244 uint32_t timeout = 50;
246 core_if = dwc_otg_hcd->core_if;
248 if (core_if->op_state == B_HOST) {
250 * Reset the port. During a HNP mode switch the reset
251 * needs to occur within 1ms and have a duration of at
254 hprt0.d32 = dwc_otg_read_hprt0(core_if);
256 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
257 if (core_if->otg_ver) {
259 hprt0.d32 = dwc_otg_read_hprt0(core_if);
261 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
264 /**@todo vahrama: Check the timeout value for OTG 2.0 */
265 if (core_if->otg_ver)
267 DWC_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg,
268 hcd_start_func, dwc_otg_hcd, timeout,
275 * HCD Callback function for disconnect of the HCD.
277 * @param p void pointer to the <code>struct usb_hcd</code>
279 static int32_t dwc_otg_hcd_disconnect_cb(void *p)
282 dwc_otg_hcd_t *dwc_otg_hcd = p;
285 dwc_otg_hcd->non_periodic_qh_ptr = &dwc_otg_hcd->non_periodic_sched_active;
286 dwc_otg_hcd->non_periodic_channels = 0;
287 dwc_otg_hcd->periodic_channels = 0;
288 dwc_otg_hcd->frame_number =0;
290 hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);
291 /* In some case, we don't disconnect a usb device, but
292 * disconnect intr was triggered, so check hprt0 here. */
293 if (((!hprt0.b.prtenchng)
294 && (!hprt0.b.prtconndet)
295 && hprt0.b.prtconnsts)
296 || !hprt0.b.prtenchng) {
297 DWC_PRINTF("%s: Invalid disconnect interrupt "
298 "hprt0 = 0x%08x\n", __func__, hprt0.d32);
302 * Set status flags for the hub driver.
304 dwc_otg_hcd->flags.b.port_connect_status_change = 1;
305 dwc_otg_hcd->flags.b.port_connect_status = 0;
308 * Shutdown any transfers in process by clearing the Tx FIFO Empty
309 * interrupt mask and status bits and disabling subsequent host
310 * channel interrupts.
313 intr.b.nptxfempty = 1;
314 intr.b.ptxfempty = 1;
316 DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk,
318 DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintsts,
322 * Turn off the vbus power only if the core has transitioned to device
323 * mode. If still in host mode, need to keep power on to detect a
326 if (dwc_otg_is_device_mode(dwc_otg_hcd->core_if)) {
327 if (dwc_otg_hcd->core_if->op_state != A_SUSPEND) {
328 hprt0_data_t hprt0 = {.d32 = 0 };
329 DWC_PRINTF("Disconnect: PortPower off\n");
331 DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0,
334 /** Delete timers if become device */
335 del_timers(dwc_otg_hcd);
336 dwc_otg_disable_host_interrupts(dwc_otg_hcd->core_if);
340 /* Respond with an error status to all URBs in the schedule. */
341 kill_all_urbs(dwc_otg_hcd);
343 if (dwc_otg_is_host_mode(dwc_otg_hcd->core_if)) {
344 /* Clean up any host channels that were in use. */
348 dwc_otg_hc_regs_t *hc_regs;
349 hcchar_data_t hcchar;
351 DWC_PRINTF("Disconnect cb-Host\n");
352 if (dwc_otg_hcd->core_if->otg_ver == 1)
353 del_xfer_timers(dwc_otg_hcd);
355 del_timers(dwc_otg_hcd);
357 num_channels = dwc_otg_hcd->core_if->core_params->host_channels;
359 if (!dwc_otg_hcd->core_if->dma_enable) {
360 /* Flush out any channel requests in slave mode. */
361 for (i = 0; i < num_channels; i++) {
362 channel = dwc_otg_hcd->hc_ptr_array[i];
363 if (DWC_CIRCLEQ_EMPTY_ENTRY
364 (channel, hc_list_entry)) {
366 dwc_otg_hcd->core_if->host_if->
369 DWC_READ_REG32(&hc_regs->hcchar);
382 for (i = 0; i < num_channels; i++) {
383 channel = dwc_otg_hcd->hc_ptr_array[i];
384 if (DWC_CIRCLEQ_EMPTY_ENTRY(channel, hc_list_entry)) {
386 dwc_otg_hcd->core_if->host_if->hc_regs[i];
387 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
389 /* Halt the channel. */
391 DWC_WRITE_REG32(&hc_regs->hcchar,
395 dwc_otg_hc_cleanup(dwc_otg_hcd->core_if,
397 DWC_CIRCLEQ_INSERT_TAIL
398 (&dwc_otg_hcd->free_hc_list, channel,
401 * Added for Descriptor DMA to prevent channel double cleanup
402 * in release_channel_ddma(). Which called from ep_disable
403 * when device disconnect.
411 if (dwc_otg_hcd->fops->disconnect) {
412 dwc_otg_hcd->fops->disconnect(dwc_otg_hcd);
419 * HCD Callback function for stopping the HCD.
421 * @param p void pointer to the <code>struct usb_hcd</code>
423 static int32_t dwc_otg_hcd_stop_cb(void *p)
425 dwc_otg_hcd_t *dwc_otg_hcd = p;
427 DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p);
428 dwc_otg_hcd_stop(dwc_otg_hcd);
432 #ifdef CONFIG_USB_DWC_OTG_LPM
434 * HCD Callback function for sleep of HCD.
436 * @param p void pointer to the <code>struct usb_hcd</code>
438 static int dwc_otg_hcd_sleep_cb(void *p)
440 dwc_otg_hcd_t *hcd = p;
442 dwc_otg_hcd_free_hc_from_lpm(hcd);
449 * HCD Callback function for Remote Wakeup.
451 * @param p void pointer to the <code>struct usb_hcd</code>
453 static int dwc_otg_hcd_rem_wakeup_cb(void *p)
455 dwc_otg_hcd_t *dwc_otg_hcd = p;
456 struct usb_hcd *hcd = dwc_otg_hcd_get_priv_data(dwc_otg_hcd);
458 if (dwc_otg_hcd->core_if->lx_state == DWC_OTG_L2) {
459 dwc_otg_hcd->flags.b.port_suspend_change = 1;
460 usb_hcd_resume_root_hub(hcd);
462 #ifdef CONFIG_USB_DWC_OTG_LPM
464 dwc_otg_hcd->flags.b.port_l1_change = 1;
471 * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
474 void dwc_otg_hcd_stop(dwc_otg_hcd_t *hcd)
476 hprt0_data_t hprt0 = {.d32 = 0 };
477 struct dwc_otg_platform_data *pldata;
478 dwc_irqflags_t flags;
480 pldata = hcd->core_if->otg_dev->pldata;
481 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD STOP\n");
484 * Set status flags for the hub driver.
486 hcd->flags.b.port_connect_status_change = 1;
487 hcd->flags.b.port_connect_status = 0;
490 * The root hub should be disconnected before this function is called.
491 * The disconnect will clear the QTD lists (via ..._hcd_urb_dequeue)
492 * and the QH lists (via ..._hcd_endpoint_disable).
494 DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
495 /* Turn off all host-specific interrupts. */
496 dwc_otg_disable_host_interrupts(hcd->core_if);
499 DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
501 /* Turn off the vbus power */
502 DWC_PRINTF("PortPower off\n");
504 DWC_WRITE_REG32(hcd->core_if->host_if->hprt0, hprt0.d32);
506 if (pldata->power_enable)
507 pldata->power_enable(0);
512 int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t *hcd,
513 dwc_otg_hcd_urb_t *dwc_otg_urb, void **ep_handle,
516 dwc_irqflags_t flags;
519 gintmsk_data_t intr_mask = {.d32 = 0 };
521 if (!hcd->flags.b.port_connect_status) {
522 /* No longer connected. */
523 DWC_DEBUG("Not connected\n");
524 return -DWC_E_NO_DEVICE;
527 qtd = dwc_otg_hcd_qtd_create(dwc_otg_urb, atomic_alloc);
529 DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n");
530 return -DWC_E_NO_MEMORY;
532 DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
534 dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle, 1);
537 DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. "
538 "Error status %d\n", retval);
539 dwc_otg_hcd_qtd_free(qtd);
542 DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk);
543 if (!intr_mask.b.sofintr && retval == 0) {
544 dwc_otg_transaction_type_e tr_type;
545 if ((qtd->qh->ep_type == UE_BULK)
546 && !(qtd->urb->flags & URB_GIVEBACK_ASAP)) {
547 /* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */
551 tr_type = dwc_otg_hcd_select_transactions(hcd);
552 if (tr_type != DWC_OTG_TRANSACTION_NONE) {
553 dwc_otg_hcd_queue_transactions(hcd, tr_type);
557 DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
561 int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t *hcd,
562 dwc_otg_hcd_urb_t *dwc_otg_urb)
565 dwc_otg_qtd_t *urb_qtd;
567 urb_qtd = dwc_otg_urb->qtd;
569 DWC_PRINTF("%s error: urb_qtd is %p dwc_otg_urb %p!!!\n",
570 __func__, urb_qtd, dwc_otg_urb);
575 if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
576 if (urb_qtd->in_process) {
577 dump_channel_info(hcd, qh);
581 if (urb_qtd->in_process && qh->channel) {
582 /* The QTD is in process (it has been assigned to a channel). */
583 if (hcd->flags.b.port_connect_status) {
585 * If still connected (i.e. in host mode), halt the
586 * channel so it can be used for other transfers. If
587 * no longer connected, the host registers can't be
588 * written to halt the channel since the core is in
591 dwc_otg_hc_halt(hcd->core_if, qh->channel,
592 DWC_OTG_HC_XFER_URB_DEQUEUE);
597 * Free the QTD and clean up the associated QH. Leave the QH in the
598 * schedule if it has any remaining QTDs.
601 if (!hcd->core_if->dma_desc_enable) {
602 uint8_t b = urb_qtd->in_process;
603 dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);
605 dwc_otg_hcd_qh_deactivate(hcd, qh, 0);
607 } else if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
608 dwc_otg_hcd_qh_remove(hcd, qh);
611 dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);
616 int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t *hcd, void *ep_handle,
619 dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
621 dwc_irqflags_t flags;
624 retval = -DWC_E_INVALID;
629 retval = -DWC_E_INVALID;
633 DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
635 while (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list) && retry) {
636 DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
639 DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
642 dwc_otg_hcd_qh_remove(hcd, qh);
644 DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
646 * Split dwc_otg_hcd_qh_remove_and_free() into qh_remove
647 * and qh_free to prevent stack dump on DWC_DMA_FREE() with
648 * irq_disabled (spinlock_irqsave) in dwc_otg_hcd_desc_list_free()
649 * and dwc_otg_hcd_frame_list_alloc().
651 dwc_otg_hcd_qh_free(hcd, qh);
657 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
658 int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t *hcd, void *ep_handle)
661 dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
663 return -DWC_E_INVALID;
665 qh->data_toggle = DWC_OTG_HC_PID_DATA0;
671 * HCD Callback structure for handling mode switching.
673 static dwc_otg_cil_callbacks_t hcd_cil_callbacks = {
674 .start = dwc_otg_hcd_start_cb,
675 .stop = dwc_otg_hcd_stop_cb,
676 .disconnect = dwc_otg_hcd_disconnect_cb,
677 .session_start = dwc_otg_hcd_session_start_cb,
678 .resume_wakeup = dwc_otg_hcd_rem_wakeup_cb,
679 #ifdef CONFIG_USB_DWC_OTG_LPM
680 .sleep = dwc_otg_hcd_sleep_cb,
686 * Reset tasklet function
688 static void reset_tasklet_func(void *data)
690 dwc_otg_hcd_t *dwc_otg_hcd = (dwc_otg_hcd_t *) data;
691 dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
694 DWC_DEBUGPL(DBG_HCDV, "USB RESET tasklet called\n");
696 hprt0.d32 = dwc_otg_read_hprt0(core_if);
698 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
702 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
703 dwc_otg_hcd->flags.b.port_reset_change = 1;
706 static void qh_list_free(dwc_otg_hcd_t *hcd, dwc_list_link_t *qh_list)
708 dwc_list_link_t *item;
710 dwc_irqflags_t flags;
712 if (!qh_list->next) {
713 /* The list hasn't been initialized yet. */
717 * Hold spinlock here. Not needed in that case if bellow
718 * function is being called from ISR
720 DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
721 /* Ensure there are no QTDs or URBs left. */
722 kill_urbs_in_qh_list(hcd, qh_list);
723 DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
725 DWC_LIST_FOREACH(item, qh_list) {
726 qh = DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
727 dwc_otg_hcd_qh_remove_and_free(hcd, qh);
732 * Exit from Hibernation if Host did not detect SRP from connected SRP capable
733 * Device during SRP time by host power up.
735 void dwc_otg_hcd_power_up(void *ptr)
737 gpwrdn_data_t gpwrdn = {.d32 = 0 };
738 dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
740 DWC_PRINTF("%s called\n", __FUNCTION__);
742 if (!core_if->hibernation_suspend) {
743 DWC_PRINTF("Already exited from Hibernation\n");
747 /* Switch on the voltage to the core */
748 gpwrdn.b.pwrdnswtch = 1;
749 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
754 gpwrdn.b.pwrdnrstn = 1;
755 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
758 /* Disable power clamps */
760 gpwrdn.b.pwrdnclmp = 1;
761 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
763 /* Remove reset the core signal */
765 gpwrdn.b.pwrdnrstn = 1;
766 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
769 /* Disable PMU interrupt */
771 gpwrdn.b.pmuintsel = 1;
772 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
774 core_if->hibernation_suspend = 0;
778 gpwrdn.b.pmuactv = 1;
779 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
784 gpwrdn.b.dis_vbus = 1;
785 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
787 core_if->op_state = A_HOST;
788 dwc_otg_core_init(core_if);
789 dwc_otg_enable_global_interrupts(core_if);
790 cil_hcd_start(core_if);
794 * Frees secondary storage associated with the dwc_otg_hcd structure contained
795 * in the struct usb_hcd field.
797 static void dwc_otg_hcd_free(dwc_otg_hcd_t *dwc_otg_hcd)
801 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD FREE\n");
803 del_timers(dwc_otg_hcd);
805 /* Free memory for QH/QTD lists */
806 qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_inactive);
807 qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_active);
808 qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_inactive);
809 qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_ready);
810 qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_assigned);
811 qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_queued);
813 /* Free memory for the host channels. */
814 for (i = 0; i < MAX_EPS_CHANNELS; i++) {
815 dwc_hc_t *hc = dwc_otg_hcd->hc_ptr_array[i];
818 if (dwc_otg_hcd->core_if->hc_xfer_timer[i]) {
819 DWC_TIMER_FREE(dwc_otg_hcd->core_if->hc_xfer_timer[i]);
823 DWC_DEBUGPL(DBG_HCDV, "HCD Free channel #%i, hc=%p\n",
829 if (dwc_otg_hcd->core_if->dma_enable) {
830 if (dwc_otg_hcd->status_buf_dma) {
831 DWC_DEV_DMA_FREE(DWC_OTG_HCD_STATUS_BUF_SIZE,
832 dwc_otg_hcd->status_buf,
833 dwc_otg_hcd->status_buf_dma);
835 } else if (dwc_otg_hcd->status_buf != NULL) {
836 DWC_FREE(dwc_otg_hcd->status_buf);
838 DWC_SPINLOCK_FREE(dwc_otg_hcd->lock);
839 /* Set core_if's lock pointer to NULL */
840 dwc_otg_hcd->core_if->lock = NULL;
842 DWC_TIMER_FREE(dwc_otg_hcd->conn_timer);
843 DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet);
845 #ifdef DWC_DEV_SRPCAP
846 if (dwc_otg_hcd->core_if->power_down == 2 &&
847 dwc_otg_hcd->core_if->pwron_timer) {
848 DWC_TIMER_FREE(dwc_otg_hcd->core_if->pwron_timer);
851 DWC_FREE(dwc_otg_hcd);
854 int dwc_otg_hcd_init(dwc_otg_hcd_t *hcd, dwc_otg_core_if_t *core_if)
861 hcd->lock = DWC_SPINLOCK_ALLOC();
863 DWC_ERROR("Could not allocate lock for pcd");
865 retval = -DWC_E_NO_MEMORY;
868 hcd->core_if = core_if;
870 /* Register the HCD CIL Callbacks */
871 dwc_otg_cil_register_hcd_callbacks(hcd->core_if,
872 &hcd_cil_callbacks, hcd);
874 /* Initialize the non-periodic schedule. */
875 DWC_LIST_INIT(&hcd->non_periodic_sched_inactive);
876 DWC_LIST_INIT(&hcd->non_periodic_sched_active);
878 /* Initialize the periodic schedule. */
879 DWC_LIST_INIT(&hcd->periodic_sched_inactive);
880 DWC_LIST_INIT(&hcd->periodic_sched_ready);
881 DWC_LIST_INIT(&hcd->periodic_sched_assigned);
882 DWC_LIST_INIT(&hcd->periodic_sched_queued);
885 * Create a host channel descriptor for each host channel implemented
886 * in the controller. Initialize the channel descriptor array.
888 DWC_CIRCLEQ_INIT(&hcd->free_hc_list);
889 num_channels = hcd->core_if->core_params->host_channels;
890 DWC_MEMSET(hcd->hc_ptr_array, 0, sizeof(hcd->hc_ptr_array));
891 for (i = 0; i < num_channels; i++) {
892 channel = DWC_ALLOC(sizeof(dwc_hc_t));
893 if (channel == NULL) {
894 retval = -DWC_E_NO_MEMORY;
895 DWC_ERROR("%s: host channel allocation failed\n",
897 dwc_otg_hcd_free(hcd);
901 hcd->hc_ptr_array[i] = channel;
903 hcd->core_if->hc_xfer_timer[i] =
904 DWC_TIMER_ALLOC("hc timer", hc_xfer_timeout,
905 &hcd->core_if->hc_xfer_info[i]);
907 DWC_DEBUGPL(DBG_HCDV, "HCD Added channel #%d, hc=%p\n", i,
911 /* Initialize the Connection timeout timer. */
912 hcd->conn_timer = DWC_TIMER_ALLOC("Connection timer",
913 dwc_otg_hcd_connect_timeout, hcd);
915 /* Initialize reset tasklet. */
917 DWC_TASK_ALLOC("reset_tasklet", reset_tasklet_func, hcd);
918 #ifdef DWC_DEV_SRPCAP
919 if (hcd->core_if->power_down == 2) {
920 /* Initialize Power on timer for Host power up in case hibernation */
921 hcd->core_if->pwron_timer = DWC_TIMER_ALLOC("PWRON TIMER",
922 dwc_otg_hcd_power_up,
928 * Allocate space for storing data on status transactions. Normally no
929 * data is sent, but this space acts as a bit bucket. This must be
930 * done after usb_add_hcd since that function allocates the DMA buffer
933 if (hcd->core_if->dma_enable) {
935 DWC_DEV_DMA_ALLOC_ATOMIC(DWC_OTG_HCD_STATUS_BUF_SIZE,
936 &hcd->status_buf_dma);
938 hcd->status_buf = DWC_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE);
940 if (!hcd->status_buf) {
941 retval = -DWC_E_NO_MEMORY;
942 DWC_ERROR("%s: status_buf allocation failed\n", __func__);
943 dwc_otg_hcd_free(hcd);
948 hcd->frame_list = NULL;
949 hcd->frame_list_dma = 0;
950 hcd->periodic_qh_count = 0;
955 void dwc_otg_hcd_remove(dwc_otg_hcd_t *hcd)
957 /* Turn off all host-specific interrupts. */
958 dwc_otg_disable_host_interrupts(hcd->core_if);
960 dwc_otg_hcd_free(hcd);
964 * Initializes dynamic portions of the DWC_otg HCD state.
966 static void dwc_otg_hcd_reinit(dwc_otg_hcd_t *hcd)
971 dwc_hc_t *channel_tmp;
972 dwc_irqflags_t flags;
973 dwc_spinlock_t *temp_lock;
976 hcd->non_periodic_qh_ptr = &hcd->non_periodic_sched_active;
977 hcd->non_periodic_channels = 0;
978 hcd->periodic_channels = 0;
980 DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
982 * Put all channels in the free channel list and clean up channel
985 DWC_CIRCLEQ_FOREACH_SAFE(channel, channel_tmp,
986 &hcd->free_hc_list, hc_list_entry) {
987 DWC_CIRCLEQ_REMOVE(&hcd->free_hc_list, channel, hc_list_entry);
990 num_channels = hcd->core_if->core_params->host_channels;
991 for (i = 0; i < num_channels; i++) {
992 channel = hcd->hc_ptr_array[i];
993 DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, channel,
995 dwc_otg_hc_cleanup(hcd->core_if, channel);
997 DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
998 /* Initialize the DWC core for host mode operation. */
999 dwc_otg_core_host_init(hcd->core_if);
1001 /* Set core_if's lock pointer to the hcd->lock */
1002 /* Should get this lock before modify it */
1003 if (hcd->core_if->lock) {
1004 DWC_SPINLOCK_IRQSAVE(hcd->core_if->lock, &flags);
1005 temp_lock = hcd->core_if->lock;
1006 hcd->core_if->lock = hcd->lock;
1007 DWC_SPINUNLOCK_IRQRESTORE(temp_lock, flags);
1009 hcd->core_if->lock = hcd->lock;
1014 * Assigns transactions from a QTD to a free host channel and initializes the
1015 * host channel to perform the transactions. The host channel is removed from
1018 * @param hcd The HCD state structure.
1019 * @param qh Transactions from the first QTD for this QH are selected and
1020 * assigned to a free host channel.
1022 static int assign_and_init_hc(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh)
1026 dwc_otg_hcd_urb_t *urb;
1030 DWC_DEBUGPL(DBG_HCDV, "%s(%p,%p)\n", __func__, hcd, qh);
1032 hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);
1034 /* Remove the host channel from the free list. */
1035 DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry);
1037 qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
1041 printk("%s : urb is NULL\n", __func__);
1048 qtd->in_process = 1;
1051 * Use usb_pipedevice to determine device address. This address is
1052 * 0 before the SET_ADDRESS command and the correct address afterward.
1054 hc->dev_addr = dwc_otg_hcd_get_dev_addr(&urb->pipe_info);
1055 hc->ep_num = dwc_otg_hcd_get_ep_num(&urb->pipe_info);
1056 hc->speed = qh->dev_speed;
1057 hc->max_packet = dwc_max_packet(qh->maxp);
1059 hc->xfer_started = 0;
1060 hc->halt_status = DWC_OTG_HC_XFER_NO_HALT_STATUS;
1061 hc->error_state = (qtd->error_count > 0);
1062 hc->halt_on_queue = 0;
1063 hc->halt_pending = 0;
1067 * The following values may be modified in the transfer type section
1068 * below. The xfer_len value may be reduced when the transfer is
1069 * started to accommodate the max widths of the XferSize and PktCnt
1070 * fields in the HCTSIZn register.
1073 hc->ep_is_in = (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) != 0);
1077 hc->do_ping = qh->ping_state;
1079 hc->data_pid_start = qh->data_toggle;
1080 hc->multi_count = 1;
1082 if (hcd->core_if->dma_enable) {
1083 hc->xfer_buff = (uint8_t *) urb->dma + urb->actual_length;
1085 /* For non-dword aligned case */
1086 if (((unsigned long)hc->xfer_buff & 0x3)
1087 && !hcd->core_if->dma_desc_enable) {
1088 ptr = (uint8_t *) urb->buf + urb->actual_length;
1091 hc->xfer_buff = (uint8_t *) urb->buf + urb->actual_length;
1093 hc->xfer_len = urb->length - urb->actual_length;
1097 * Set the split attributes
1102 uint32_t hub_addr, port_addr;
1104 hc->xact_pos = qtd->isoc_split_pos;
1105 hc->complete_split = qtd->complete_split;
1106 hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &port_addr);
1107 hc->hub_addr = (uint8_t) hub_addr;
1108 hc->port_addr = (uint8_t) port_addr;
1111 switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) {
1113 hc->ep_type = DWC_OTG_EP_TYPE_CONTROL;
1114 switch (qtd->control_phase) {
1115 case DWC_OTG_CONTROL_SETUP:
1116 DWC_DEBUGPL(DBG_HCDV, " Control setup transaction\n");
1119 hc->data_pid_start = DWC_OTG_HC_PID_SETUP;
1120 if (hcd->core_if->dma_enable)
1121 hc->xfer_buff = (uint8_t *) urb->setup_dma;
1123 hc->xfer_buff = (uint8_t *) urb->setup_packet;
1128 case DWC_OTG_CONTROL_DATA:
1129 DWC_DEBUGPL(DBG_HCDV, " Control data transaction\n");
1130 hc->data_pid_start = qtd->data_toggle;
1132 case DWC_OTG_CONTROL_STATUS:
1134 * Direction is opposite of data direction or IN if no
1137 DWC_DEBUGPL(DBG_HCDV, " Control status transaction\n");
1138 if (urb->length == 0) {
1142 dwc_otg_hcd_is_pipe_out(&urb->pipe_info);
1147 hc->data_pid_start = DWC_OTG_HC_PID_DATA1;
1150 if (hcd->core_if->dma_enable)
1151 hc->xfer_buff = (uint8_t *) hcd->status_buf_dma;
1153 hc->xfer_buff = (uint8_t *) hcd->status_buf;
1160 hc->ep_type = DWC_OTG_EP_TYPE_BULK;
1163 hc->ep_type = DWC_OTG_EP_TYPE_INTR;
1165 case UE_ISOCHRONOUS:
1167 struct dwc_otg_hcd_iso_packet_desc *frame_desc;
1169 hc->ep_type = DWC_OTG_EP_TYPE_ISOC;
1171 if (hcd->core_if->dma_desc_enable)
1174 frame_desc = &urb->iso_descs[qtd->isoc_frame_index];
1176 frame_desc->status = 0;
1178 if (hcd->core_if->dma_enable) {
1179 hc->xfer_buff = (uint8_t *) urb->dma;
1181 hc->xfer_buff = (uint8_t *) urb->buf;
1184 frame_desc->offset + qtd->isoc_split_offset;
1186 frame_desc->length - qtd->isoc_split_offset;
1188 /* For non-dword aligned buffers */
1189 if (((unsigned long)hc->xfer_buff & 0x3)
1190 && hcd->core_if->dma_enable) {
1192 (uint8_t *) urb->buf + frame_desc->offset +
1193 qtd->isoc_split_offset;
1197 if (hc->xact_pos == DWC_HCSPLIT_XACTPOS_ALL) {
1198 if (hc->xfer_len <= 188) {
1199 hc->xact_pos = DWC_HCSPLIT_XACTPOS_ALL;
1202 DWC_HCSPLIT_XACTPOS_BEGIN;
1208 /* non DWORD-aligned buffer case */
1211 if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
1212 buf_size = hcd->core_if->core_params->max_transfer_size;
1216 if (!qh->dw_align_buf) {
1218 DWC_DEV_DMA_ALLOC_ATOMIC(buf_size,
1221 if (!qh->dw_align_buf) {
1223 ("%s: Failed to allocate memory to handle "
1224 "non-dword aligned buffer case\n",
1229 if (!hc->ep_is_in) {
1230 dwc_memcpy(qh->dw_align_buf, ptr, hc->xfer_len);
1232 hc->align_buff = qh->dw_align_buf_dma;
1237 if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
1238 hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
1240 * This value may be modified when the transfer is started to
1241 * reflect the actual transfer length.
1243 hc->multi_count = dwc_hb_mult(qh->maxp);
1246 if (hcd->core_if->dma_desc_enable)
1247 hc->desc_list_addr = qh->desc_list_dma;
1249 dwc_otg_hc_init(hcd->core_if, hc);
1255 * This function selects transactions from the HCD transfer schedule and
1256 * assigns them to available host channels. It is called from HCD interrupt
1257 * handler functions.
1259 * @param hcd The HCD state structure.
1261 * @return The types of new transactions that were assigned to host channels.
1263 dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t *hcd)
1265 dwc_list_link_t *qh_ptr;
1268 dwc_otg_transaction_type_e ret_val = DWC_OTG_TRANSACTION_NONE;
1272 DWC_DEBUGPL(DBG_HCD, " Select Transactions\n");
1275 /* Process entries in the periodic ready list. */
1276 qh_ptr = DWC_LIST_FIRST(&hcd->periodic_sched_ready);
1278 while (qh_ptr != &hcd->periodic_sched_ready &&
1279 !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
1281 qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
1282 assign_and_init_hc(hcd, qh);
1285 * Move the QH from the periodic ready schedule to the
1286 * periodic assigned schedule.
1288 qh_ptr = DWC_LIST_NEXT(qh_ptr);
1289 DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
1290 &qh->qh_list_entry);
1292 ret_val = DWC_OTG_TRANSACTION_PERIODIC;
1296 * Process entries in the inactive portion of the non-periodic
1297 * schedule. Some free host channels may not be used if they are
1298 * reserved for periodic transfers.
1300 qh_ptr = hcd->non_periodic_sched_inactive.next;
1301 num_channels = hcd->core_if->core_params->host_channels;
1302 while (qh_ptr != &hcd->non_periodic_sched_inactive &&
1303 (hcd->non_periodic_channels <
1304 num_channels - hcd->periodic_channels) &&
1305 !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
1307 qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
1309 err = assign_and_init_hc(hcd, qh);
1312 * Move the QH from the non-periodic inactive schedule to the
1313 * non-periodic active schedule.
1315 qh_ptr = DWC_LIST_NEXT(qh_ptr);
1318 DWC_LIST_MOVE_HEAD(&hcd->non_periodic_sched_active,
1319 &qh->qh_list_entry);
1321 if (ret_val == DWC_OTG_TRANSACTION_NONE) {
1322 ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC;
1324 ret_val = DWC_OTG_TRANSACTION_ALL;
1327 hcd->non_periodic_channels++;
1334 * Attempts to queue a single transaction request for a host channel
1335 * associated with either a periodic or non-periodic transfer. This function
1336 * assumes that there is space available in the appropriate request queue. For
1337 * an OUT transfer or SETUP transaction in Slave mode, it checks whether space
1338 * is available in the appropriate Tx FIFO.
1340 * @param hcd The HCD state structure.
1341 * @param hc Host channel descriptor associated with either a periodic or
1342 * non-periodic transfer.
1343 * @param fifo_dwords_avail Number of DWORDs available in the periodic Tx
1344 * FIFO for periodic transfers or the non-periodic Tx FIFO for non-periodic
1347 * @return 1 if a request is queued and more requests may be needed to
1348 * complete the transfer, 0 if no more requests are required for this
1349 * transfer, -1 if there is insufficient space in the Tx FIFO.
1351 static int queue_transaction(dwc_otg_hcd_t *hcd,
1352 dwc_hc_t *hc, uint16_t fifo_dwords_avail)
1355 if (!hc || !(hc->qh))
1357 if (hcd->core_if->dma_enable) {
1358 if (hcd->core_if->dma_desc_enable) {
1359 if (!hc->xfer_started
1360 || (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)) {
1361 dwc_otg_hcd_start_xfer_ddma(hcd, hc->qh);
1362 hc->qh->ping_state = 0;
1364 } else if (!hc->xfer_started) {
1365 if (!hc || !(hc->qh))
1367 dwc_otg_hc_start_transfer(hcd->core_if, hc);
1368 hc->qh->ping_state = 0;
1371 } else if (hc->halt_pending) {
1372 /* Don't queue a request if the channel has been halted. */
1374 } else if (hc->halt_on_queue) {
1375 dwc_otg_hc_halt(hcd->core_if, hc, hc->halt_status);
1377 } else if (hc->do_ping) {
1378 if (!hc->xfer_started) {
1379 dwc_otg_hc_start_transfer(hcd->core_if, hc);
1382 } else if (!hc->ep_is_in || hc->data_pid_start == DWC_OTG_HC_PID_SETUP) {
1383 if ((fifo_dwords_avail * 4) >= hc->max_packet) {
1384 if (!hc->xfer_started) {
1385 dwc_otg_hc_start_transfer(hcd->core_if, hc);
1389 dwc_otg_hc_continue_transfer(hcd->core_if,
1396 if (!hc->xfer_started) {
1397 dwc_otg_hc_start_transfer(hcd->core_if, hc);
1400 retval = dwc_otg_hc_continue_transfer(hcd->core_if, hc);
1408 * Processes periodic channels for the next frame and queues transactions for
1409 * these channels to the DWC_otg controller. After queueing transactions, the
1410 * Periodic Tx FIFO Empty interrupt is enabled if there are more transactions
1411 * to queue as Periodic Tx FIFO or request queue space becomes available.
1412 * Otherwise, the Periodic Tx FIFO Empty interrupt is disabled.
1414 static void process_periodic_channels(dwc_otg_hcd_t *hcd)
1416 hptxsts_data_t tx_status;
1417 dwc_list_link_t *qh_ptr;
1420 int no_queue_space = 0;
1421 int no_fifo_space = 0;
1423 dwc_otg_host_global_regs_t *host_regs;
1424 host_regs = hcd->core_if->host_if->host_global_regs;
1426 DWC_DEBUGPL(DBG_HCDV, "Queue periodic transactions\n");
1428 tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
1429 DWC_DEBUGPL(DBG_HCDV,
1430 " P Tx Req Queue Space Avail (before queue): %d\n",
1431 tx_status.b.ptxqspcavail);
1432 DWC_DEBUGPL(DBG_HCDV, " P Tx FIFO Space Avail (before queue): %d\n",
1433 tx_status.b.ptxfspcavail);
1436 qh_ptr = hcd->periodic_sched_assigned.next;
1437 while (qh_ptr != &hcd->periodic_sched_assigned) {
1438 tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
1439 if (tx_status.b.ptxqspcavail == 0) {
1444 qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
1447 * Set a flag if we're queuing high-bandwidth in slave mode.
1448 * The flag prevents any halts to get into the request queue in
1449 * the middle of multiple high-bandwidth packets getting queued.
1451 if (!hcd->core_if->dma_enable && qh->channel->multi_count > 1) {
1452 hcd->core_if->queuing_high_bandwidth = 1;
1455 queue_transaction(hcd, qh->channel,
1456 tx_status.b.ptxfspcavail);
1463 * In Slave mode, stay on the current transfer until there is
1464 * nothing more to do or the high-bandwidth request count is
1465 * reached. In DMA mode, only need to queue one request. The
1466 * controller automatically handles multiple packets for
1467 * high-bandwidth transfers.
1469 if (hcd->core_if->dma_enable || status == 0 ||
1470 qh->channel->requests == qh->channel->multi_count) {
1471 qh_ptr = qh_ptr->next;
1473 * Move the QH from the periodic assigned schedule to
1474 * the periodic queued schedule.
1476 DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_queued,
1477 &qh->qh_list_entry);
1479 /* done queuing high bandwidth */
1480 hcd->core_if->queuing_high_bandwidth = 0;
1484 if (!hcd->core_if->dma_enable) {
1485 dwc_otg_core_global_regs_t *global_regs;
1486 gintmsk_data_t intr_mask = {.d32 = 0 };
1488 global_regs = hcd->core_if->core_global_regs;
1489 intr_mask.b.ptxfempty = 1;
1491 tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
1492 DWC_DEBUGPL(DBG_HCDV,
1493 " P Tx Req Queue Space Avail (after queue): %d\n",
1494 tx_status.b.ptxqspcavail);
1495 DWC_DEBUGPL(DBG_HCDV,
1496 " P Tx FIFO Space Avail (after queue): %d\n",
1497 tx_status.b.ptxfspcavail);
1499 if (!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned) ||
1500 no_queue_space || no_fifo_space) {
1502 * May need to queue more transactions as the request
1503 * queue or Tx FIFO empties. Enable the periodic Tx
1504 * FIFO empty interrupt. (Always use the half-empty
1505 * level to ensure that new requests are loaded as
1506 * soon as possible.)
1508 DWC_MODIFY_REG32(&global_regs->gintmsk, 0,
1512 * Disable the Tx FIFO empty interrupt since there are
1513 * no more transactions that need to be queued right
1514 * now. This function is called from interrupt
1515 * handlers to queue more transactions as transfer
1518 DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32,
1525 * Processes active non-periodic channels and queues transactions for these
1526 * channels to the DWC_otg controller. After queueing transactions, the NP Tx
1527 * FIFO Empty interrupt is enabled if there are more transactions to queue as
1528 * NP Tx FIFO or request queue space becomes available. Otherwise, the NP Tx
1529 * FIFO Empty interrupt is disabled.
1531 static void process_non_periodic_channels(dwc_otg_hcd_t *hcd)
1533 gnptxsts_data_t tx_status;
1534 dwc_list_link_t *orig_qh_ptr;
1537 int no_queue_space = 0;
1538 int no_fifo_space = 0;
1541 dwc_otg_core_global_regs_t *global_regs =
1542 hcd->core_if->core_global_regs;
1544 DWC_DEBUGPL(DBG_HCDV, "Queue non-periodic transactions\n");
1546 tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
1547 DWC_DEBUGPL(DBG_HCDV,
1548 " NP Tx Req Queue Space Avail (before queue): %d\n",
1549 tx_status.b.nptxqspcavail);
1550 DWC_DEBUGPL(DBG_HCDV, " NP Tx FIFO Space Avail (before queue): %d\n",
1551 tx_status.b.nptxfspcavail);
1554 * Keep track of the starting point. Skip over the start-of-list
1557 if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {
1558 hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
1560 orig_qh_ptr = hcd->non_periodic_qh_ptr;
1563 * Process once through the active list or until no more space is
1564 * available in the request queue or the Tx FIFO.
1567 tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
1568 if (!hcd->core_if->dma_enable && tx_status.b.nptxqspcavail == 0) {
1573 qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t,
1576 queue_transaction(hcd, qh->channel,
1577 tx_status.b.nptxfspcavail);
1581 } else if (status < 0) {
1586 /* Advance to next QH, skipping start-of-list entry. */
1587 hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
1588 if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {
1589 hcd->non_periodic_qh_ptr =
1590 hcd->non_periodic_qh_ptr->next;
1593 } while (hcd->non_periodic_qh_ptr != orig_qh_ptr);
1595 if (!hcd->core_if->dma_enable) {
1596 gintmsk_data_t intr_mask = {.d32 = 0 };
1597 intr_mask.b.nptxfempty = 1;
1600 tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
1601 DWC_DEBUGPL(DBG_HCDV,
1602 " NP Tx Req Queue Space Avail (after queue): %d\n",
1603 tx_status.b.nptxqspcavail);
1604 DWC_DEBUGPL(DBG_HCDV,
1605 " NP Tx FIFO Space Avail (after queue): %d\n",
1606 tx_status.b.nptxfspcavail);
1608 if (more_to_do || no_queue_space || no_fifo_space) {
1610 * May need to queue more transactions as the request
1611 * queue or Tx FIFO empties. Enable the non-periodic
1612 * Tx FIFO empty interrupt. (Always use the half-empty
1613 * level to ensure that new requests are loaded as
1614 * soon as possible.)
1616 DWC_MODIFY_REG32(&global_regs->gintmsk, 0,
1620 * Disable the Tx FIFO empty interrupt since there are
1621 * no more transactions that need to be queued right
1622 * now. This function is called from interrupt
1623 * handlers to queue more transactions as transfer
1626 DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32,
1633 * This function processes the currently active host channels and queues
1634 * transactions for these channels to the DWC_otg controller. It is called
1635 * from HCD interrupt handler functions.
1637 * @param hcd The HCD state structure.
1638 * @param tr_type The type(s) of transactions to queue (non-periodic,
1639 * periodic, or both).
1641 void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t *hcd,
1642 dwc_otg_transaction_type_e tr_type)
1645 DWC_DEBUGPL(DBG_HCD, "Queue Transactions\n");
1647 /* Process host channels associated with periodic transfers. */
1648 if ((tr_type == DWC_OTG_TRANSACTION_PERIODIC ||
1649 tr_type == DWC_OTG_TRANSACTION_ALL) &&
1650 !DWC_LIST_EMPTY(&hcd->periodic_sched_assigned)) {
1652 process_periodic_channels(hcd);
1655 /* Process host channels associated with non-periodic transfers. */
1656 if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC ||
1657 tr_type == DWC_OTG_TRANSACTION_ALL) {
1658 if (!DWC_LIST_EMPTY(&hcd->non_periodic_sched_active)) {
1659 process_non_periodic_channels(hcd);
1662 * Ensure NP Tx FIFO empty interrupt is disabled when
1663 * there are no non-periodic transfers to process.
1665 gintmsk_data_t gintmsk = {.d32 = 0 };
1666 gintmsk.b.nptxfempty = 1;
1667 DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->
1668 gintmsk, gintmsk.d32, 0);
1673 #ifdef DWC_HS_ELECT_TST
1675 * Quick and dirty hack to implement the HS Electrical Test
1676 * SINGLE_STEP_GET_DEVICE_DESCRIPTOR feature.
1678 * This code was copied from our userspace app "hset". It sends a
1679 * Get Device Descriptor control sequence in two parts, first the
1680 * Setup packet by itself, followed some time later by the In and
1681 * Ack packets. Rather than trying to figure out how to add this
1682 * functionality to the normal driver code, we just hijack the
1683 * hardware, using these two function to drive the hardware
1687 static dwc_otg_core_global_regs_t *global_regs;
1688 static dwc_otg_host_global_regs_t *hc_global_regs;
1689 static dwc_otg_hc_regs_t *hc_regs;
1690 static uint32_t *data_fifo;
1692 static void do_setup(void)
1694 gintsts_data_t gintsts;
1695 hctsiz_data_t hctsiz;
1696 hcchar_data_t hcchar;
1701 DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001);
1704 DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3);
1707 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1710 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
1713 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
1716 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1719 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
1722 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
1725 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
1728 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1731 * Send Setup packet (Get Device Descriptor)
1734 /* Make sure channel is disabled */
1735 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1736 if (hcchar.b.chen) {
1738 /* hcchar.b.chen = 1; */
1739 DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
1744 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1747 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
1750 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
1753 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1756 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
1759 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
1762 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
1764 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1769 hctsiz.b.xfersize = 8;
1770 hctsiz.b.pktcnt = 1;
1771 hctsiz.b.pid = DWC_OTG_HC_PID_SETUP;
1772 DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
1775 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1776 hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
1781 DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
1783 /* Fill FIFO with Setup data for Get Device Descriptor */
1784 data_fifo = (uint32_t *) ((char *)global_regs + 0x1000);
1785 DWC_WRITE_REG32(data_fifo++, 0x01000680);
1786 DWC_WRITE_REG32(data_fifo++, 0x00080000);
1788 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1790 /* Wait for host channel interrupt */
1792 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1793 } while (gintsts.b.hcintr == 0);
1795 /* Disable HCINTs */
1796 DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000);
1798 /* Disable HAINTs */
1799 DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000);
1802 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
1805 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
1808 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1811 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
1814 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
1817 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
1820 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1823 static void do_in_ack(void)
1825 gintsts_data_t gintsts;
1826 hctsiz_data_t hctsiz;
1827 hcchar_data_t hcchar;
1830 host_grxsts_data_t grxsts;
1833 DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001);
1836 DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3);
1839 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1842 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
1845 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
1848 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1851 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
1854 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
1857 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
1860 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1863 * Receive Control In packet
1866 /* Make sure channel is disabled */
1867 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1868 if (hcchar.b.chen) {
1871 DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
1876 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1879 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
1882 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
1885 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1888 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
1891 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
1894 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
1896 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1901 hctsiz.b.xfersize = 8;
1902 hctsiz.b.pktcnt = 1;
1903 hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;
1904 DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
1907 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1908 hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
1913 DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
1915 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1917 /* Wait for receive status queue interrupt */
1919 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1920 } while (gintsts.b.rxstsqlvl == 0);
1923 grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp);
1925 /* Clear RXSTSQLVL in GINTSTS */
1927 gintsts.b.rxstsqlvl = 1;
1928 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
1930 switch (grxsts.b.pktsts) {
1931 case DWC_GRXSTS_PKTSTS_IN:
1932 /* Read the data into the host buffer */
1933 if (grxsts.b.bcnt > 0) {
1935 int word_count = (grxsts.b.bcnt + 3) / 4;
1937 data_fifo = (uint32_t *) ((char *)global_regs + 0x1000);
1939 for (i = 0; i < word_count; i++) {
1940 (void)DWC_READ_REG32(data_fifo++);
1949 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1951 /* Wait for receive status queue interrupt */
1953 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1954 } while (gintsts.b.rxstsqlvl == 0);
1957 grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp);
1959 /* Clear RXSTSQLVL in GINTSTS */
1961 gintsts.b.rxstsqlvl = 1;
1962 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
1964 switch (grxsts.b.pktsts) {
1965 case DWC_GRXSTS_PKTSTS_IN_XFER_COMP:
1972 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1974 /* Wait for host channel interrupt */
1976 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1977 } while (gintsts.b.hcintr == 0);
1980 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
1983 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
1986 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1989 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
1992 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
1995 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
1998 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
2000 /* usleep(100000); */
2005 * Send handshake packet
2009 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
2012 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
2015 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
2018 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
2021 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
2024 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
2027 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
2029 /* Make sure channel is disabled */
2030 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
2031 if (hcchar.b.chen) {
2034 DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
2039 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
2042 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
2045 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
2048 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
2051 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
2054 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
2057 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
2059 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
2064 hctsiz.b.xfersize = 0;
2065 hctsiz.b.pktcnt = 1;
2066 hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;
2067 DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
2070 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
2071 hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
2076 DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
2078 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
2080 /* Wait for host channel interrupt */
2082 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
2083 } while (gintsts.b.hcintr == 0);
2085 /* Disable HCINTs */
2086 DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000);
2088 /* Disable HAINTs */
2089 DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000);
2092 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
2095 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
2098 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
2101 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
2104 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
2107 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
2110 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
2114 /** Handles hub class-specific requests. */
2115 int dwc_otg_hcd_hub_control(dwc_otg_hcd_t *dwc_otg_hcd,
2118 uint16_t wIndex, uint8_t *buf, uint16_t wLength)
2122 dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
2123 usb_hub_descriptor_t *hub_desc;
2124 hprt0_data_t hprt0 = {.d32 = 0 };
2126 uint32_t port_status;
2129 case UCR_CLEAR_HUB_FEATURE:
2130 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2131 "ClearHubFeature 0x%x\n", wValue);
2133 case UHF_C_HUB_LOCAL_POWER:
2134 case UHF_C_HUB_OVER_CURRENT:
2135 /* Nothing required here */
2138 retval = -DWC_E_INVALID;
2139 DWC_ERROR("DWC OTG HCD - "
2140 "ClearHubFeature request %xh unknown\n",
2144 case UCR_CLEAR_PORT_FEATURE:
2145 #ifdef CONFIG_USB_DWC_OTG_LPM
2146 if (wValue != UHF_PORT_L1)
2148 if (!wIndex || wIndex > 1)
2152 case UHF_PORT_ENABLE:
2153 DWC_DEBUGPL(DBG_ANY, "DWC OTG HCD HUB CONTROL - "
2154 "ClearPortFeature USB_PORT_FEAT_ENABLE\n");
2155 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2157 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
2159 case UHF_PORT_SUSPEND:
2160 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2161 "ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
2163 if (core_if->power_down == 2) {
2164 dwc_otg_host_hibernation_restore(core_if, 0, 0);
2166 DWC_WRITE_REG32(core_if->pcgcctl, 0);
2169 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2171 DWC_WRITE_REG32(core_if->host_if->hprt0,
2173 hprt0.b.prtsusp = 0;
2174 /* Clear Resume bit */
2177 DWC_WRITE_REG32(core_if->host_if->hprt0,
2181 #ifdef CONFIG_USB_DWC_OTG_LPM
2184 pcgcctl_data_t pcgcctl = {.d32 = 0 };
2185 glpmcfg_data_t lpmcfg = {.d32 = 0 };
2188 DWC_READ_REG32(&core_if->core_global_regs->
2190 lpmcfg.b.en_utmi_sleep = 0;
2191 lpmcfg.b.hird_thres &= (~(1 << 4));
2192 lpmcfg.b.prt_sleep_sts = 1;
2193 DWC_WRITE_REG32(&core_if->core_global_regs->
2194 glpmcfg, lpmcfg.d32);
2196 /* Clear Enbl_L1Gating bit. */
2197 pcgcctl.b.enbl_sleep_gating = 1;
2198 DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32,
2203 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2205 DWC_WRITE_REG32(core_if->host_if->hprt0,
2207 /* This bit will be cleared in wakeup interrupt handle */
2211 case UHF_PORT_POWER:
2212 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2213 "ClearPortFeature USB_PORT_FEAT_POWER\n");
2214 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2216 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
2218 case UHF_PORT_INDICATOR:
2219 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2220 "ClearPortFeature USB_PORT_FEAT_INDICATOR\n");
2221 /* Port inidicator not supported */
2223 case UHF_C_PORT_CONNECTION:
2224 /* Clears drivers internal connect status change
2226 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2227 "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n");
2228 dwc_otg_hcd->flags.b.port_connect_status_change = 0;
2230 case UHF_C_PORT_RESET:
2231 /* Clears the driver's internal Port Reset Change
2233 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2234 "ClearPortFeature USB_PORT_FEAT_C_RESET\n");
2235 dwc_otg_hcd->flags.b.port_reset_change = 0;
2237 case UHF_C_PORT_ENABLE:
2238 /* Clears the driver's internal Port
2239 * Enable/Disable Change flag */
2240 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2241 "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n");
2242 dwc_otg_hcd->flags.b.port_enable_change = 0;
2244 case UHF_C_PORT_SUSPEND:
2245 /* Clears the driver's internal Port Suspend
2246 * Change flag, which is set when resume signaling on
2247 * the host port is complete */
2248 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2249 "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n");
2250 dwc_otg_hcd->flags.b.port_suspend_change = 0;
2252 #ifdef CONFIG_USB_DWC_OTG_LPM
2254 dwc_otg_hcd->flags.b.port_l1_change = 0;
2257 case UHF_C_PORT_OVER_CURRENT:
2258 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2259 "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n");
2260 dwc_otg_hcd->flags.b.port_over_current_change = 0;
2263 retval = -DWC_E_INVALID;
2264 DWC_ERROR("DWC OTG HCD - "
2265 "ClearPortFeature request %xh "
2266 "unknown or unsupported\n", wValue);
2269 case UCR_GET_HUB_DESCRIPTOR:
2270 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2271 "GetHubDescriptor\n");
2272 hub_desc = (usb_hub_descriptor_t *) buf;
2273 hub_desc->bDescLength = 9;
2274 hub_desc->bDescriptorType = 0x29;
2275 hub_desc->bNbrPorts = 1;
2276 USETW(hub_desc->wHubCharacteristics, 0x08);
2277 hub_desc->bPwrOn2PwrGood = 1;
2278 hub_desc->bHubContrCurrent = 0;
2279 hub_desc->DeviceRemovable[0] = 0;
2280 hub_desc->DeviceRemovable[1] = 0xff;
2282 case UCR_GET_HUB_STATUS:
2283 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2285 DWC_MEMSET(buf, 0, 4);
2287 case UCR_GET_PORT_STATUS:
2288 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2289 "GetPortStatus wIndex = 0x%04x FLAGS=0x%08x\n",
2290 wIndex, dwc_otg_hcd->flags.d32);
2291 if (!wIndex || wIndex > 1)
2296 if (dwc_otg_hcd->flags.b.port_connect_status_change)
2297 port_status |= (1 << UHF_C_PORT_CONNECTION);
2299 if (dwc_otg_hcd->flags.b.port_enable_change)
2300 port_status |= (1 << UHF_C_PORT_ENABLE);
2302 if (dwc_otg_hcd->flags.b.port_suspend_change)
2303 port_status |= (1 << UHF_C_PORT_SUSPEND);
2305 if (dwc_otg_hcd->flags.b.port_l1_change)
2306 port_status |= (1 << UHF_C_PORT_L1);
2308 if (dwc_otg_hcd->flags.b.port_reset_change) {
2309 port_status |= (1 << UHF_C_PORT_RESET);
2312 if (dwc_otg_hcd->flags.b.port_over_current_change) {
2313 DWC_WARN("Overcurrent change detected\n");
2314 port_status |= (1 << UHF_C_PORT_OVER_CURRENT);
2317 if (!dwc_otg_hcd->flags.b.port_connect_status) {
2319 * The port is disconnected, which means the core is
2320 * either in device mode or it soon will be. Just
2321 * return 0's for the remainder of the port status
2322 * since the port register can't be read if the core
2323 * is in device mode.
2325 *((__le32 *) buf) = dwc_cpu_to_le32(&port_status);
2329 hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
2330 DWC_DEBUGPL(DBG_HCDV, " HPRT0: 0x%08x\n", hprt0.d32);
2332 if (hprt0.b.prtconnsts)
2333 port_status |= (1 << UHF_PORT_CONNECTION);
2336 port_status |= (1 << UHF_PORT_ENABLE);
2338 if (hprt0.b.prtsusp)
2339 port_status |= (1 << UHF_PORT_SUSPEND);
2341 if (hprt0.b.prtovrcurract)
2342 port_status |= (1 << UHF_PORT_OVER_CURRENT);
2345 port_status |= (1 << UHF_PORT_RESET);
2348 port_status |= (1 << UHF_PORT_POWER);
2350 if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED)
2351 port_status |= (1 << UHF_PORT_HIGH_SPEED);
2352 else if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED)
2353 port_status |= (1 << UHF_PORT_LOW_SPEED);
2355 if (hprt0.b.prttstctl)
2356 port_status |= (1 << UHF_PORT_TEST);
2357 if (dwc_otg_get_lpm_portsleepstatus(dwc_otg_hcd->core_if)) {
2358 port_status |= (1 << UHF_PORT_L1);
2361 For Synopsys HW emulation of Power down wkup_control asserts the
2362 hreset_n and prst_n on suspned. This causes the HPRT0 to be zero.
2363 We intentionally tell the software that port is in L2Suspend state.
2366 if ((core_if->power_down == 2)
2367 && (core_if->hibernation_suspend == 1)) {
2368 port_status |= (1 << UHF_PORT_SUSPEND);
2370 /* USB_PORT_FEAT_INDICATOR unsupported always 0 */
2372 *((__le32 *) buf) = dwc_cpu_to_le32(&port_status);
2375 case UCR_SET_HUB_FEATURE:
2376 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2378 /* No HUB features supported */
2380 case UCR_SET_PORT_FEATURE:
2381 if (wValue != UHF_PORT_TEST && (!wIndex || wIndex > 1))
2384 if (!dwc_otg_hcd->flags.b.port_connect_status) {
2386 * The port is disconnected, which means the core is
2387 * either in device mode or it soon will be. Just
2388 * return without doing anything since the port
2389 * register can't be written if the core is in device
2396 case UHF_PORT_SUSPEND:
2397 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2398 "SetPortFeature - USB_PORT_FEAT_SUSPEND\n");
2399 if (dwc_otg_hcd_otg_port(dwc_otg_hcd) != wIndex) {
2402 if (core_if->power_down == 2) {
2404 dwc_irqflags_t flags;
2405 pcgcctl_data_t pcgcctl = {.d32 = 0 };
2406 gpwrdn_data_t gpwrdn = {.d32 = 0 };
2407 gusbcfg_data_t gusbcfg = {.d32 = 0 };
2408 #ifdef DWC_DEV_SRPCAP
2409 int32_t otg_cap_param =
2410 core_if->core_params->otg_cap;
2413 ("Preparing for complete power-off\n");
2415 /* Save registers before hibernation */
2416 dwc_otg_save_global_regs(core_if);
2417 dwc_otg_save_host_regs(core_if);
2419 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2420 hprt0.b.prtsusp = 1;
2422 DWC_WRITE_REG32(core_if->host_if->hprt0,
2424 /* Spin hprt0.b.prtsusp to became 1 */
2426 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2427 if (hprt0.b.prtsusp) {
2431 } while (--timeout);
2433 DWC_WARN("Suspend wasn't genereted\n");
2438 * We need to disable interrupts to prevent servicing of any IRQ
2439 * during going to hibernation
2441 DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
2442 core_if->lx_state = DWC_OTG_L2;
2443 #ifdef DWC_DEV_SRPCAP
2444 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2447 DWC_WRITE_REG32(core_if->host_if->hprt0,
2451 DWC_READ_REG32(&core_if->
2452 core_global_regs->gusbcfg);
2453 if (gusbcfg.b.ulpi_utmi_sel == 1) {
2454 /* ULPI interface */
2455 /* Suspend the Phy Clock */
2457 pcgcctl.b.stoppclk = 1;
2458 DWC_MODIFY_REG32(core_if->pcgcctl, 0,
2461 gpwrdn.b.pmuactv = 1;
2463 (&core_if->core_global_regs->gpwrdn,
2466 /* UTMI+ Interface */
2467 gpwrdn.b.pmuactv = 1;
2469 (&core_if->core_global_regs->gpwrdn,
2472 pcgcctl.b.stoppclk = 1;
2473 DWC_MODIFY_REG32(core_if->pcgcctl, 0,
2477 #ifdef DWC_DEV_SRPCAP
2479 gpwrdn.b.dis_vbus = 1;
2480 DWC_MODIFY_REG32(&core_if->
2481 core_global_regs->gpwrdn, 0,
2485 gpwrdn.b.pmuintsel = 1;
2486 DWC_MODIFY_REG32(&core_if->
2487 core_global_regs->gpwrdn, 0,
2492 #ifdef DWC_DEV_SRPCAP
2493 gpwrdn.b.srp_det_msk = 1;
2495 gpwrdn.b.disconn_det_msk = 1;
2496 gpwrdn.b.lnstchng_msk = 1;
2497 gpwrdn.b.sts_chngint_msk = 1;
2498 DWC_MODIFY_REG32(&core_if->
2499 core_global_regs->gpwrdn, 0,
2503 /* Enable Power Down Clamp and all interrupts in GPWRDN */
2505 gpwrdn.b.pwrdnclmp = 1;
2506 DWC_MODIFY_REG32(&core_if->
2507 core_global_regs->gpwrdn, 0,
2511 /* Switch off VDD */
2513 gpwrdn.b.pwrdnswtch = 1;
2514 DWC_MODIFY_REG32(&core_if->
2515 core_global_regs->gpwrdn, 0,
2518 #ifdef DWC_DEV_SRPCAP
2519 if (otg_cap_param ==
2520 DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
2521 core_if->pwron_timer_started = 1;
2522 DWC_TIMER_SCHEDULE(core_if->pwron_timer,
2526 /* Save gpwrdn register for further usage if stschng interrupt */
2527 core_if->gr_backup->gpwrdn_local =
2528 DWC_READ_REG32(&core_if->core_global_regs->
2531 /* Set flag to indicate that we are in hibernation */
2532 core_if->hibernation_suspend = 1;
2533 DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock,
2536 DWC_PRINTF("Host hibernation completed\n");
2537 /* Exit from case statement */
2541 if (dwc_otg_hcd_otg_port(dwc_otg_hcd) == wIndex &&
2542 dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) {
2543 gotgctl_data_t gotgctl = {.d32 = 0 };
2544 gotgctl.b.hstsethnpen = 1;
2545 DWC_MODIFY_REG32(&core_if->
2546 core_global_regs->gotgctl, 0,
2548 core_if->op_state = A_SUSPEND;
2550 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2551 hprt0.b.prtsusp = 1;
2552 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
2554 dwc_irqflags_t flags;
2555 /* Update lx_state */
2556 DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
2557 core_if->lx_state = DWC_OTG_L2;
2558 DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock,
2561 /* Suspend the Phy Clock */
2562 if (core_if->otg_ver == 0) {
2563 pcgcctl_data_t pcgcctl = {.d32 = 0 };
2564 pcgcctl.b.stoppclk = 1;
2565 DWC_MODIFY_REG32(core_if->pcgcctl, 0,
2570 /* For HNP the bus must be suspended for at least 200ms. */
2571 if (dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) {
2572 pcgcctl_data_t pcgcctl = {.d32 = 0 };
2573 pcgcctl.b.stoppclk = 1;
2574 DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32,
2579 /** @todo - check how sw can wait for 1 sec to check asesvld??? */
2581 if (core_if->adp_enable) {
2582 gotgctl_data_t gotgctl = {.d32 = 0 };
2583 gpwrdn_data_t gpwrdn;
2585 while (gotgctl.b.asesvld == 1) {
2588 (&core_if->core_global_regs->gotgctl);
2592 /* Enable Power Down Logic */
2594 gpwrdn.b.pmuactv = 1;
2595 DWC_MODIFY_REG32(&core_if->
2596 core_global_regs->gpwrdn, 0,
2599 /* Unmask SRP detected interrupt from Power Down Logic */
2601 gpwrdn.b.srp_det_msk = 1;
2602 DWC_MODIFY_REG32(&core_if->
2603 core_global_regs->gpwrdn, 0,
2606 dwc_otg_adp_probe_start(core_if);
2610 case UHF_PORT_POWER:
2611 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2612 "SetPortFeature - USB_PORT_FEAT_POWER\n");
2613 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2615 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
2617 case UHF_PORT_RESET:
2618 if ((core_if->power_down == 2)
2619 && (core_if->hibernation_suspend == 1)) {
2620 /* If we are going to exit from Hibernated
2621 * state via USB RESET.
2623 dwc_otg_host_hibernation_restore(core_if, 0, 1);
2625 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2627 DWC_DEBUGPL(DBG_HCD,
2628 "DWC OTG HCD HUB CONTROL - "
2629 "SetPortFeature - USB_PORT_FEAT_RESET\n");
2631 pcgcctl_data_t pcgcctl = {.d32 = 0 };
2632 pcgcctl.b.enbl_sleep_gating = 1;
2633 pcgcctl.b.stoppclk = 1;
2634 DWC_MODIFY_REG32(core_if->pcgcctl,
2636 DWC_WRITE_REG32(core_if->pcgcctl, 0);
2638 #ifdef CONFIG_USB_DWC_OTG_LPM
2640 glpmcfg_data_t lpmcfg;
2642 DWC_READ_REG32(&core_if->
2645 if (lpmcfg.b.prt_sleep_sts) {
2646 lpmcfg.b.en_utmi_sleep = 0;
2647 lpmcfg.b.hird_thres &=
2649 DWC_WRITE_REG32(&core_if->
2657 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2658 /* Clear suspend bit if resetting from suspended state. */
2659 hprt0.b.prtsusp = 0;
2660 /* When B-Host the Port reset bit is set in
2661 * the Start HCD Callback function, so that
2662 * the reset is started within 1ms of the HNP
2663 * success interrupt. */
2664 if (!dwc_otg_hcd_is_b_host(dwc_otg_hcd)) {
2668 ("Indeed it is in host mode hprt0 = %08x\n",
2670 DWC_WRITE_REG32(core_if->host_if->hprt0,
2673 /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */
2676 DWC_WRITE_REG32(core_if->host_if->hprt0,
2678 core_if->lx_state = DWC_OTG_L0; /* Now back to the on state */
2681 #ifdef DWC_HS_ELECT_TST
2685 gintmsk_data_t gintmsk;
2687 t = (wIndex >> 8); /* MSB wIndex USB */
2688 DWC_DEBUGPL(DBG_HCD,
2689 "DWC OTG HCD HUB CONTROL - "
2690 "SetPortFeature - USB_PORT_FEAT_TEST %d\n",
2692 DWC_WARN("USB_PORT_FEAT_TEST %d\n", t);
2694 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2695 hprt0.b.prttstctl = t;
2696 DWC_WRITE_REG32(core_if->host_if->hprt0,
2699 /* Setup global vars with reg addresses (quick and
2700 * dirty hack, should be cleaned up)
2702 global_regs = core_if->core_global_regs;
2704 core_if->host_if->host_global_regs;
2706 (dwc_otg_hc_regs_t *) ((char *)
2710 (uint32_t *) ((char *)global_regs +
2713 if (t == 6) { /* HS_HOST_PORT_SUSPEND_RESUME */
2714 /* Save current interrupt mask */
2717 (&global_regs->gintmsk);
2719 /* Disable all interrupts while we muck with
2720 * the hardware directly
2722 DWC_WRITE_REG32(&global_regs->
2725 /* 15 second delay per the test spec */
2728 /* Drive suspend on the root port */
2730 dwc_otg_read_hprt0(core_if);
2731 hprt0.b.prtsusp = 1;
2733 DWC_WRITE_REG32(core_if->
2737 /* 15 second delay per the test spec */
2740 /* Drive resume on the root port */
2742 dwc_otg_read_hprt0(core_if);
2743 hprt0.b.prtsusp = 0;
2745 DWC_WRITE_REG32(core_if->
2750 /* Clear the resume bit */
2752 DWC_WRITE_REG32(core_if->
2756 /* Restore interrupts */
2757 DWC_WRITE_REG32(&global_regs->
2760 } else if (t == 7) { /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */
2761 /* Save current interrupt mask */
2764 (&global_regs->gintmsk);
2766 /* Disable all interrupts while we muck with
2767 * the hardware directly
2769 DWC_WRITE_REG32(&global_regs->
2772 /* 15 second delay per the test spec */
2775 /* Send the Setup packet */
2778 /* 15 second delay so nothing else happens for awhile */
2781 /* Restore interrupts */
2782 DWC_WRITE_REG32(&global_regs->
2785 } else if (t == 8) { /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */
2786 /* Save current interrupt mask */
2789 (&global_regs->gintmsk);
2791 /* Disable all interrupts while we muck with
2792 * the hardware directly
2794 DWC_WRITE_REG32(&global_regs->
2797 /* Send the Setup packet */
2800 /* 15 second delay so nothing else happens for awhile */
2803 /* Send the In and Ack packets */
2806 /* 15 second delay so nothing else happens for awhile */
2809 /* Restore interrupts */
2810 DWC_WRITE_REG32(&global_regs->
2817 #endif /* DWC_HS_ELECT_TST */
2819 case UHF_PORT_INDICATOR:
2820 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2821 "SetPortFeature - USB_PORT_FEAT_INDICATOR\n");
2825 retval = -DWC_E_INVALID;
2826 DWC_ERROR("DWC OTG HCD - "
2827 "SetPortFeature request %xh "
2828 "unknown or unsupported\n", wValue);
2832 #ifdef CONFIG_USB_DWC_OTG_LPM
2833 case UCR_SET_AND_TEST_PORT_FEATURE:
2834 if (wValue != UHF_PORT_L1) {
2838 int portnum, hird, devaddr, remwake;
2839 glpmcfg_data_t lpmcfg;
2840 uint32_t time_usecs;
2841 gintsts_data_t gintsts;
2842 gintmsk_data_t gintmsk;
2844 if (!dwc_otg_get_param_lpm_enable(core_if)) {
2847 if (wValue != UHF_PORT_L1 || wLength != 1) {
2850 /* Check if the port currently is in SLEEP state */
2852 DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
2853 if (lpmcfg.b.prt_sleep_sts) {
2854 DWC_INFO("Port is already in sleep mode\n");
2855 buf[0] = 0; /* Return success */
2859 portnum = wIndex & 0xf;
2860 hird = (wIndex >> 4) & 0xf;
2861 devaddr = (wIndex >> 8) & 0x7f;
2862 remwake = (wIndex >> 15);
2865 retval = -DWC_E_INVALID;
2867 ("Wrong port number(%d) in SetandTestPortFeature request\n",
2873 ("SetandTestPortFeature request: portnum = %d, hird = %d, devaddr = %d, rewake = %d\n",
2874 portnum, hird, devaddr, remwake);
2875 /* Disable LPM interrupt */
2877 gintmsk.b.lpmtranrcvd = 1;
2878 DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
2881 if (dwc_otg_hcd_send_lpm
2882 (dwc_otg_hcd, devaddr, hird, remwake)) {
2883 retval = -DWC_E_INVALID;
2887 time_usecs = 10 * (lpmcfg.b.retry_count + 1);
2888 /* We will consider timeout if time_usecs microseconds pass,
2889 * and we don't receive LPM transaction status.
2890 * After receiving non-error responce(ACK/NYET/STALL) from device,
2891 * core will set lpmtranrcvd bit.
2895 DWC_READ_REG32(&core_if->core_global_regs->
2897 if (gintsts.b.lpmtranrcvd) {
2901 } while (--time_usecs);
2902 /* lpm_int bit will be cleared in LPM interrupt handler */
2909 if (!gintsts.b.lpmtranrcvd) {
2910 buf[0] = 0x3; /* Completion code is Timeout */
2911 dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd);
2914 DWC_READ_REG32(&core_if->core_global_regs->
2916 if (lpmcfg.b.lpm_resp == 0x3) {
2917 /* ACK responce from the device */
2918 buf[0] = 0x00; /* Success */
2919 } else if (lpmcfg.b.lpm_resp == 0x2) {
2920 /* NYET responce from the device */
2923 /* Otherwise responce with Timeout */
2927 DWC_PRINTF("Device responce to LPM trans is %x\n",
2929 DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0,
2934 #endif /* CONFIG_USB_DWC_OTG_LPM */
2937 retval = -DWC_E_INVALID;
2938 DWC_WARN("DWC OTG HCD - "
2939 "Unknown hub control request type or invalid typeReq: %xh wIndex: %xh wValue: %xh\n",
2940 typeReq, wIndex, wValue);
2947 #ifdef CONFIG_USB_DWC_OTG_LPM
2948 /** Returns index of host channel to perform LPM transaction. */
2949 int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t *hcd, uint8_t devaddr)
2951 dwc_otg_core_if_t *core_if = hcd->core_if;
2953 hcchar_data_t hcchar;
2954 gintmsk_data_t gintmsk = {.d32 = 0 };
2956 if (DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
2957 DWC_PRINTF("No free channel to select for LPM transaction\n");
2961 hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);
2963 /* Mask host channel interrupts. */
2964 gintmsk.b.hcintr = 1;
2965 DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0);
2967 /* Fill fields that core needs for LPM transaction */
2968 hcchar.b.devaddr = devaddr;
2970 hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
2972 hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW);
2973 hcchar.b.epdir = 0; /* OUT */
2974 DWC_WRITE_REG32(&core_if->host_if->hc_regs[hc->hc_num]->hcchar,
2977 /* Remove the host channel from the free list. */
2978 DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry);
2980 DWC_PRINTF("hcnum = %d devaddr = %d\n", hc->hc_num, devaddr);
2985 /** Release hc after performing LPM transaction */
2986 void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t *hcd)
2989 glpmcfg_data_t lpmcfg;
2992 lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg);
2993 hc_num = lpmcfg.b.lpm_chan_index;
2995 hc = hcd->hc_ptr_array[hc_num];
2997 DWC_PRINTF("Freeing channel %d after LPM\n", hc_num);
2998 /* Return host channel to free list */
2999 DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
3002 int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t *hcd, uint8_t devaddr, uint8_t hird,
3003 uint8_t bRemoteWake)
3005 glpmcfg_data_t lpmcfg;
3006 pcgcctl_data_t pcgcctl = {.d32 = 0 };
3009 channel = dwc_otg_hcd_get_hc_for_lpm_tran(hcd, devaddr);
3014 pcgcctl.b.enbl_sleep_gating = 1;
3015 DWC_MODIFY_REG32(hcd->core_if->pcgcctl, 0, pcgcctl.d32);
3017 /* Read LPM config register */
3018 lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg);
3020 /* Program LPM transaction fields */
3021 lpmcfg.b.rem_wkup_en = bRemoteWake;
3022 lpmcfg.b.hird = hird;
3024 if (dwc_otg_get_param_besl_enable(hcd->core_if)) {
3025 lpmcfg.b.hird_thres = 0x16;
3026 lpmcfg.b.en_besl = 1;
3028 lpmcfg.b.hird_thres = 0x1c;
3031 lpmcfg.b.lpm_chan_index = channel;
3032 lpmcfg.b.en_utmi_sleep = 1;
3033 /* Program LPM config register */
3034 DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);
3036 /* Send LPM transaction */
3037 lpmcfg.b.send_lpm = 1;
3038 DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);
3043 #endif /* CONFIG_USB_DWC_OTG_LPM */
3045 int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t *hcd, int port)
3050 return -DWC_E_INVALID;
3053 retval = (hcd->flags.b.port_connect_status_change ||
3054 hcd->flags.b.port_reset_change ||
3055 hcd->flags.b.port_enable_change ||
3056 hcd->flags.b.port_suspend_change ||
3057 hcd->flags.b.port_over_current_change);
3060 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB STATUS DATA:"
3061 " Root port status changed\n");
3062 DWC_DEBUGPL(DBG_HCDV, " port_connect_status_change: %d\n",
3063 hcd->flags.b.port_connect_status_change);
3064 DWC_DEBUGPL(DBG_HCDV, " port_reset_change: %d\n",
3065 hcd->flags.b.port_reset_change);
3066 DWC_DEBUGPL(DBG_HCDV, " port_enable_change: %d\n",
3067 hcd->flags.b.port_enable_change);
3068 DWC_DEBUGPL(DBG_HCDV, " port_suspend_change: %d\n",
3069 hcd->flags.b.port_suspend_change);
3070 DWC_DEBUGPL(DBG_HCDV, " port_over_current_change: %d\n",
3071 hcd->flags.b.port_over_current_change);
3077 int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t *dwc_otg_hcd)
3081 DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->
3082 host_global_regs->hfnum);
3085 DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD GET FRAME NUMBER %d\n",
3088 return hfnum.b.frnum;
3091 int dwc_otg_hcd_start(dwc_otg_hcd_t *hcd,
3092 struct dwc_otg_hcd_function_ops *fops)
3097 if (!dwc_otg_is_device_mode(hcd->core_if) &&
3098 (!hcd->core_if->adp_enable || hcd->core_if->adp.adp_started)) {
3099 dwc_otg_hcd_reinit(hcd);
3101 retval = -DWC_E_NO_DEVICE;
3107 void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t *hcd)
3112 void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t *hcd, void *priv_data)
3114 hcd->priv = priv_data;
3117 uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t *hcd)
3119 return hcd->otg_port;
3122 uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t *hcd)
3125 if (hcd->core_if->op_state == B_HOST) {
3134 dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t *hcd,
3135 int iso_desc_count, int atomic_alloc)
3137 dwc_otg_hcd_urb_t *dwc_otg_urb;
3141 sizeof(*dwc_otg_urb) +
3142 iso_desc_count * sizeof(struct dwc_otg_hcd_iso_packet_desc);
3144 dwc_otg_urb = DWC_ALLOC_ATOMIC(size);
3146 dwc_otg_urb = DWC_ALLOC(size);
3148 dwc_otg_urb->packet_count = iso_desc_count;
3153 void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t *dwc_otg_urb,
3154 uint8_t dev_addr, uint8_t ep_num,
3155 uint8_t ep_type, uint8_t ep_dir, uint16_t mps)
3157 dwc_otg_hcd_fill_pipe(&dwc_otg_urb->pipe_info, dev_addr, ep_num,
3158 ep_type, ep_dir, mps);
3161 ("addr = %d, ep_num = %d, ep_dir = 0x%x, ep_type = 0x%x, mps = %d\n",
3162 dev_addr, ep_num, ep_dir, ep_type, mps);
3166 void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t *dwc_otg_urb,
3167 void *urb_handle, void *buf, dwc_dma_t dma,
3168 uint32_t buflen, void *setup_packet,
3169 dwc_dma_t setup_dma, uint32_t flags,
3172 dwc_otg_urb->priv = urb_handle;
3173 dwc_otg_urb->buf = buf;
3174 dwc_otg_urb->dma = dma;
3175 dwc_otg_urb->length = buflen;
3176 dwc_otg_urb->setup_packet = setup_packet;
3177 dwc_otg_urb->setup_dma = setup_dma;
3178 dwc_otg_urb->flags = flags;
3179 dwc_otg_urb->interval = interval;
3180 dwc_otg_urb->status = -DWC_E_IN_PROGRESS;
3183 uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t *dwc_otg_urb)
3185 return dwc_otg_urb->status;
3188 uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t *dwc_otg_urb)
3190 return dwc_otg_urb->actual_length;
3193 uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t *dwc_otg_urb)
3195 return dwc_otg_urb->error_count;
3198 void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t *dwc_otg_urb,
3199 int desc_num, uint32_t offset,
3202 dwc_otg_urb->iso_descs[desc_num].offset = offset;
3203 dwc_otg_urb->iso_descs[desc_num].length = length;
3206 uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t *dwc_otg_urb,
3209 return dwc_otg_urb->iso_descs[desc_num].status;
3212 uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t *
3213 dwc_otg_urb, int desc_num)
3215 return dwc_otg_urb->iso_descs[desc_num].actual_length;
3218 int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t *hcd, void *ep_handle)
3221 dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
3224 if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) {
3231 int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t *hcd, void *ep_handle)
3233 dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
3235 DWC_ASSERT(qh, "qh is not allocated\n");
3237 if (DWC_LIST_EMPTY(&qh->qh_list_entry)) {
3244 uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t *hcd, void *ep_handle)
3246 dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
3247 DWC_ASSERT(qh, "qh is not allocated\n");
3251 void dwc_otg_hcd_dump_state(dwc_otg_hcd_t *hcd)
3256 gnptxsts_data_t np_tx_status;
3257 hptxsts_data_t p_tx_status;
3259 num_channels = hcd->core_if->core_params->host_channels;
3262 ("************************************************************\n");
3263 DWC_PRINTF("HCD State:\n");
3264 DWC_PRINTF(" Num channels: %d\n", num_channels);
3265 for (i = 0; i < num_channels; i++) {
3266 dwc_hc_t *hc = hcd->hc_ptr_array[i];
3267 DWC_PRINTF(" Channel %d:\n", i);
3268 DWC_PRINTF(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
3269 hc->dev_addr, hc->ep_num, hc->ep_is_in);
3270 DWC_PRINTF(" speed: %d\n", hc->speed);
3271 DWC_PRINTF(" ep_type: %d\n", hc->ep_type);
3272 DWC_PRINTF(" max_packet: %d\n", hc->max_packet);
3273 DWC_PRINTF(" data_pid_start: %d\n", hc->data_pid_start);
3274 DWC_PRINTF(" multi_count: %d\n", hc->multi_count);
3275 DWC_PRINTF(" xfer_started: %d\n", hc->xfer_started);
3276 DWC_PRINTF(" xfer_buff: %p\n", hc->xfer_buff);
3277 DWC_PRINTF(" xfer_len: %d\n", hc->xfer_len);
3278 DWC_PRINTF(" xfer_count: %d\n", hc->xfer_count);
3279 DWC_PRINTF(" halt_on_queue: %d\n", hc->halt_on_queue);
3280 DWC_PRINTF(" halt_pending: %d\n", hc->halt_pending);
3281 DWC_PRINTF(" halt_status: %d\n", hc->halt_status);
3282 DWC_PRINTF(" do_split: %d\n", hc->do_split);
3283 DWC_PRINTF(" complete_split: %d\n", hc->complete_split);
3284 DWC_PRINTF(" hub_addr: %d\n", hc->hub_addr);
3285 DWC_PRINTF(" port_addr: %d\n", hc->port_addr);
3286 DWC_PRINTF(" xact_pos: %d\n", hc->xact_pos);
3287 DWC_PRINTF(" requests: %d\n", hc->requests);
3288 DWC_PRINTF(" qh: %p\n", hc->qh);
3289 if (hc->xfer_started) {
3291 hcchar_data_t hcchar;
3292 hctsiz_data_t hctsiz;
3294 hcintmsk_data_t hcintmsk;
3296 DWC_READ_REG32(&hcd->core_if->host_if->
3297 host_global_regs->hfnum);
3299 DWC_READ_REG32(&hcd->core_if->host_if->hc_regs[i]->
3302 DWC_READ_REG32(&hcd->core_if->host_if->hc_regs[i]->
3305 DWC_READ_REG32(&hcd->core_if->host_if->hc_regs[i]->
3308 DWC_READ_REG32(&hcd->core_if->host_if->hc_regs[i]->
3310 DWC_PRINTF(" hfnum: 0x%08x\n", hfnum.d32);
3311 DWC_PRINTF(" hcchar: 0x%08x\n", hcchar.d32);
3312 DWC_PRINTF(" hctsiz: 0x%08x\n", hctsiz.d32);
3313 DWC_PRINTF(" hcint: 0x%08x\n", hcint.d32);
3314 DWC_PRINTF(" hcintmsk: 0x%08x\n", hcintmsk.d32);
3316 if (hc->xfer_started && hc->qh) {
3318 dwc_otg_hcd_urb_t *urb;
3320 DWC_CIRCLEQ_FOREACH(qtd, &hc->qh->qtd_list,
3322 if (!qtd->in_process)
3326 DWC_PRINTF(" URB Info:\n");
3327 DWC_PRINTF(" qtd: %p, urb: %p\n", qtd,
3330 DWC_PRINTF(" Dev: %d, EP: %d %s\n",
3331 dwc_otg_hcd_get_dev_addr
3333 dwc_otg_hcd_get_ep_num
3335 dwc_otg_hcd_is_pipe_in
3336 (&urb->pipe_info) ? "IN" :
3339 (" Max packet size: %d\n",
3343 (" transfer_buffer: %p\n",
3345 DWC_PRINTF(" transfer_dma: %p\n",
3348 (" transfer_buffer_length: %d\n",
3350 DWC_PRINTF(" actual_length: %d\n",
3351 urb->actual_length);
3356 DWC_PRINTF(" non_periodic_channels: %d\n", hcd->non_periodic_channels);
3357 DWC_PRINTF(" periodic_channels: %d\n", hcd->periodic_channels);
3358 DWC_PRINTF(" periodic_usecs: %d\n", hcd->periodic_usecs);
3360 DWC_READ_REG32(&hcd->core_if->core_global_regs->gnptxsts);
3361 DWC_PRINTF(" NP Tx Req Queue Space Avail: %d\n",
3362 np_tx_status.b.nptxqspcavail);
3363 DWC_PRINTF(" NP Tx FIFO Space Avail: %d\n",
3364 np_tx_status.b.nptxfspcavail);
3366 DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hptxsts);
3367 DWC_PRINTF(" P Tx Req Queue Space Avail: %d\n",
3368 p_tx_status.b.ptxqspcavail);
3369 DWC_PRINTF(" P Tx FIFO Space Avail: %d\n", p_tx_status.b.ptxfspcavail);
3370 dwc_otg_hcd_dump_frrem(hcd);
3371 dwc_otg_dump_global_registers(hcd->core_if);
3372 dwc_otg_dump_host_registers(hcd->core_if);
3374 ("************************************************************\n");
3380 void dwc_print_setup_data(uint8_t *setup)
3383 if (CHK_DEBUG_LEVEL(DBG_HCD)) {
3384 DWC_PRINTF("Setup Data = MSB ");
3385 for (i = 7; i >= 0; i--)
3386 DWC_PRINTF("%02x ", setup[i]);
3388 DWC_PRINTF(" bmRequestType Tranfer = %s\n",
3389 (setup[0] & 0x80) ? "Device-to-Host" :
3391 DWC_PRINTF(" bmRequestType Type = ");
3392 switch ((setup[0] & 0x60) >> 5) {
3394 DWC_PRINTF("Standard\n");
3397 DWC_PRINTF("Class\n");
3400 DWC_PRINTF("Vendor\n");
3403 DWC_PRINTF("Reserved\n");
3406 DWC_PRINTF(" bmRequestType Recipient = ");
3407 switch (setup[0] & 0x1f) {
3409 DWC_PRINTF("Device\n");
3412 DWC_PRINTF("Interface\n");
3415 DWC_PRINTF("Endpoint\n");
3418 DWC_PRINTF("Other\n");
3421 DWC_PRINTF("Reserved\n");
3424 DWC_PRINTF(" bRequest = 0x%0x\n", setup[1]);
3425 DWC_PRINTF(" wValue = 0x%0x\n", *((uint16_t *)&setup[2]));
3426 DWC_PRINTF(" wIndex = 0x%0x\n", *((uint16_t *)&setup[4]));
3427 DWC_PRINTF(" wLength = 0x%0x\n\n", *((uint16_t *)&setup[6]));
3432 void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t *hcd)
3435 DWC_PRINTF("Frame remaining at SOF:\n");
3436 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3437 hcd->frrem_samples, hcd->frrem_accum,
3438 (hcd->frrem_samples > 0) ?
3439 hcd->frrem_accum / hcd->frrem_samples : 0);
3442 DWC_PRINTF("Frame remaining at start_transfer (uframe 7):\n");
3443 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3444 hcd->core_if->hfnum_7_samples,
3445 hcd->core_if->hfnum_7_frrem_accum,
3446 (hcd->core_if->hfnum_7_samples >
3447 0) ? hcd->core_if->hfnum_7_frrem_accum /
3448 hcd->core_if->hfnum_7_samples : 0);
3449 DWC_PRINTF("Frame remaining at start_transfer (uframe 0):\n");
3450 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3451 hcd->core_if->hfnum_0_samples,
3452 hcd->core_if->hfnum_0_frrem_accum,
3453 (hcd->core_if->hfnum_0_samples >
3454 0) ? hcd->core_if->hfnum_0_frrem_accum /
3455 hcd->core_if->hfnum_0_samples : 0);
3456 DWC_PRINTF("Frame remaining at start_transfer (uframe 1-6):\n");
3457 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3458 hcd->core_if->hfnum_other_samples,
3459 hcd->core_if->hfnum_other_frrem_accum,
3460 (hcd->core_if->hfnum_other_samples >
3461 0) ? hcd->core_if->hfnum_other_frrem_accum /
3462 hcd->core_if->hfnum_other_samples : 0);
3465 DWC_PRINTF("Frame remaining at sample point A (uframe 7):\n");
3466 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3467 hcd->hfnum_7_samples_a, hcd->hfnum_7_frrem_accum_a,
3468 (hcd->hfnum_7_samples_a > 0) ?
3469 hcd->hfnum_7_frrem_accum_a / hcd->hfnum_7_samples_a : 0);
3470 DWC_PRINTF("Frame remaining at sample point A (uframe 0):\n");
3471 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3472 hcd->hfnum_0_samples_a, hcd->hfnum_0_frrem_accum_a,
3473 (hcd->hfnum_0_samples_a > 0) ?
3474 hcd->hfnum_0_frrem_accum_a / hcd->hfnum_0_samples_a : 0);
3475 DWC_PRINTF("Frame remaining at sample point A (uframe 1-6):\n");
3476 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3477 hcd->hfnum_other_samples_a, hcd->hfnum_other_frrem_accum_a,
3478 (hcd->hfnum_other_samples_a > 0) ?
3479 hcd->hfnum_other_frrem_accum_a /
3480 hcd->hfnum_other_samples_a : 0);
3483 DWC_PRINTF("Frame remaining at sample point B (uframe 7):\n");
3484 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3485 hcd->hfnum_7_samples_b, hcd->hfnum_7_frrem_accum_b,
3486 (hcd->hfnum_7_samples_b > 0) ?
3487 hcd->hfnum_7_frrem_accum_b / hcd->hfnum_7_samples_b : 0);
3488 DWC_PRINTF("Frame remaining at sample point B (uframe 0):\n");
3489 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3490 hcd->hfnum_0_samples_b, hcd->hfnum_0_frrem_accum_b,
3491 (hcd->hfnum_0_samples_b > 0) ?
3492 hcd->hfnum_0_frrem_accum_b / hcd->hfnum_0_samples_b : 0);
3493 DWC_PRINTF("Frame remaining at sample point B (uframe 1-6):\n");
3494 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3495 hcd->hfnum_other_samples_b, hcd->hfnum_other_frrem_accum_b,
3496 (hcd->hfnum_other_samples_b > 0) ?
3497 hcd->hfnum_other_frrem_accum_b /
3498 hcd->hfnum_other_samples_b : 0);
3502 #endif /* DWC_DEVICE_ONLY */