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_TIMEOUT);
181 dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
189 * Responds with an error status of ETIMEDOUT to all URBs in the non-periodic
190 * and periodic schedules. The QTD associated with each URB is removed from
191 * the schedule and freed. This function may be called when a disconnect is
192 * detected or when the HCD is being stopped.
194 static void kill_all_urbs(dwc_otg_hcd_t * hcd)
196 kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_inactive);
197 kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_active);
198 kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_inactive);
199 kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_ready);
200 kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_assigned);
201 kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_queued);
205 * Start the connection timer. An OTG host is required to display a
206 * message if the device does not connect within 10 seconds. The
207 * timer is deleted if a port connect interrupt occurs before the
210 static void dwc_otg_hcd_start_connect_timer(dwc_otg_hcd_t * hcd)
212 DWC_TIMER_SCHEDULE(hcd->conn_timer, 10000 /* 10 secs */ );
216 * HCD Callback function for disconnect of the HCD.
218 * @param p void pointer to the <code>struct usb_hcd</code>
220 static int32_t dwc_otg_hcd_session_start_cb(void *p)
222 dwc_otg_hcd_t *dwc_otg_hcd;
223 DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p);
225 dwc_otg_hcd_start_connect_timer(dwc_otg_hcd);
230 * HCD Callback function for starting the HCD when A-Cable is
233 * @param p void pointer to the <code>struct usb_hcd</code>
235 static int32_t dwc_otg_hcd_start_cb(void *p)
237 dwc_otg_hcd_t *dwc_otg_hcd = p;
238 dwc_otg_core_if_t *core_if;
240 uint32_t timeout = 50;
242 core_if = dwc_otg_hcd->core_if;
244 if (core_if->op_state == B_HOST) {
246 * Reset the port. During a HNP mode switch the reset
247 * needs to occur within 1ms and have a duration of at
250 hprt0.d32 = dwc_otg_read_hprt0(core_if);
252 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
253 if (core_if->otg_ver) {
255 hprt0.d32 = dwc_otg_read_hprt0(core_if);
257 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
260 /**@todo vahrama: Check the timeout value for OTG 2.0 */
261 if (core_if->otg_ver)
263 DWC_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg,
264 hcd_start_func, dwc_otg_hcd, timeout,
271 * HCD Callback function for disconnect of the HCD.
273 * @param p void pointer to the <code>struct usb_hcd</code>
275 static int32_t dwc_otg_hcd_disconnect_cb(void *p)
278 dwc_otg_hcd_t *dwc_otg_hcd = p;
281 * Set status flags for the hub driver.
283 dwc_otg_hcd->flags.b.port_connect_status_change = 1;
284 dwc_otg_hcd->flags.b.port_connect_status = 0;
287 * Shutdown any transfers in process by clearing the Tx FIFO Empty
288 * interrupt mask and status bits and disabling subsequent host
289 * channel interrupts.
292 intr.b.nptxfempty = 1;
293 intr.b.ptxfempty = 1;
295 DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk,
297 DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintsts,
301 * Turn off the vbus power only if the core has transitioned to device
302 * mode. If still in host mode, need to keep power on to detect a
305 if (dwc_otg_is_device_mode(dwc_otg_hcd->core_if)) {
306 if (dwc_otg_hcd->core_if->op_state != A_SUSPEND) {
307 hprt0_data_t hprt0 = {.d32 = 0 };
308 DWC_PRINTF("Disconnect: PortPower off\n");
310 DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0,
313 /** Delete timers if become device */
314 del_timers(dwc_otg_hcd);
315 dwc_otg_disable_host_interrupts(dwc_otg_hcd->core_if);
318 /* Respond with an error status to all URBs in the schedule. */
319 kill_all_urbs(dwc_otg_hcd);
321 if (dwc_otg_is_host_mode(dwc_otg_hcd->core_if)) {
322 /* Clean up any host channels that were in use. */
326 dwc_otg_hc_regs_t *hc_regs;
327 hcchar_data_t hcchar;
329 DWC_PRINTF("Disconnect cb-Host\n");
330 if (dwc_otg_hcd->core_if->otg_ver == 1)
331 del_xfer_timers(dwc_otg_hcd);
333 del_timers(dwc_otg_hcd);
335 num_channels = dwc_otg_hcd->core_if->core_params->host_channels;
337 if (!dwc_otg_hcd->core_if->dma_enable) {
338 /* Flush out any channel requests in slave mode. */
339 for (i = 0; i < num_channels; i++) {
340 channel = dwc_otg_hcd->hc_ptr_array[i];
341 if (DWC_CIRCLEQ_EMPTY_ENTRY
342 (channel, hc_list_entry)) {
344 dwc_otg_hcd->core_if->
347 DWC_READ_REG32(&hc_regs->hcchar);
360 for (i = 0; i < num_channels; i++) {
361 channel = dwc_otg_hcd->hc_ptr_array[i];
362 if (DWC_CIRCLEQ_EMPTY_ENTRY(channel, hc_list_entry)) {
364 dwc_otg_hcd->core_if->host_if->hc_regs[i];
365 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
367 /* Halt the channel. */
369 DWC_WRITE_REG32(&hc_regs->hcchar,
373 dwc_otg_hc_cleanup(dwc_otg_hcd->core_if,
375 DWC_CIRCLEQ_INSERT_TAIL
376 (&dwc_otg_hcd->free_hc_list, channel,
379 * Added for Descriptor DMA to prevent channel double cleanup
380 * in release_channel_ddma(). Which called from ep_disable
381 * when device disconnect.
388 if (dwc_otg_hcd->fops->disconnect) {
389 dwc_otg_hcd->fops->disconnect(dwc_otg_hcd);
396 * HCD Callback function for stopping the HCD.
398 * @param p void pointer to the <code>struct usb_hcd</code>
400 static int32_t dwc_otg_hcd_stop_cb(void *p)
402 dwc_otg_hcd_t *dwc_otg_hcd = p;
404 DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p);
405 dwc_otg_hcd_stop(dwc_otg_hcd);
409 #ifdef CONFIG_USB_DWC_OTG_LPM
411 * HCD Callback function for sleep of HCD.
413 * @param p void pointer to the <code>struct usb_hcd</code>
415 static int dwc_otg_hcd_sleep_cb(void *p)
417 dwc_otg_hcd_t *hcd = p;
419 dwc_otg_hcd_free_hc_from_lpm(hcd);
426 * HCD Callback function for Remote Wakeup.
428 * @param p void pointer to the <code>struct usb_hcd</code>
430 extern inline struct usb_hcd *dwc_otg_hcd_to_hcd(dwc_otg_hcd_t * dwc_otg_hcd);
431 static int dwc_otg_hcd_rem_wakeup_cb(void *p)
433 dwc_otg_hcd_t *dwc_otg_hcd = p;
434 struct usb_hcd *hcd = dwc_otg_hcd_to_hcd(dwc_otg_hcd);
436 if (dwc_otg_hcd->core_if->lx_state == DWC_OTG_L2) {
437 dwc_otg_hcd->flags.b.port_suspend_change = 1;
438 usb_hcd_resume_root_hub(hcd);
440 #ifdef CONFIG_USB_DWC_OTG_LPM
442 dwc_otg_hcd->flags.b.port_l1_change = 1;
449 * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
452 void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd)
454 hprt0_data_t hprt0 = {.d32 = 0 };
455 struct dwc_otg_platform_data *pldata;
456 pldata = hcd->core_if->otg_dev->pldata;
458 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD STOP\n");
461 * The root hub should be disconnected before this function is called.
462 * The disconnect will clear the QTD lists (via ..._hcd_urb_dequeue)
463 * and the QH lists (via ..._hcd_endpoint_disable).
466 /* Turn off all host-specific interrupts. */
467 dwc_otg_disable_host_interrupts(hcd->core_if);
469 /* Turn off the vbus power */
470 DWC_PRINTF("PortPower off\n");
472 DWC_WRITE_REG32(hcd->core_if->host_if->hprt0, hprt0.d32);
474 if(pldata->power_enable)
475 pldata->power_enable(0);
481 int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * hcd,
482 dwc_otg_hcd_urb_t * dwc_otg_urb, void **ep_handle,
485 dwc_irqflags_t flags;
488 gintmsk_data_t intr_mask = {.d32 = 0 };
490 if (!hcd->flags.b.port_connect_status) {
491 /* No longer connected. */
492 DWC_ERROR("Not connected\n");
493 return -DWC_E_NO_DEVICE;
496 qtd = dwc_otg_hcd_qtd_create(dwc_otg_urb, atomic_alloc);
498 DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n");
499 return -DWC_E_NO_MEMORY;
503 dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle, atomic_alloc);
505 DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
507 DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. "
508 "Error status %d\n", retval);
509 dwc_otg_hcd_qtd_free(qtd);
511 qtd->qh = *ep_handle;
513 intr_mask.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk);
514 if (!intr_mask.b.sofintr && retval == 0) {
515 dwc_otg_transaction_type_e tr_type;
516 if ((qtd->qh->ep_type == UE_BULK)
517 && !(qtd->urb->flags & URB_GIVEBACK_ASAP)) {
518 /* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */
522 tr_type = dwc_otg_hcd_select_transactions(hcd);
523 if (tr_type != DWC_OTG_TRANSACTION_NONE) {
524 dwc_otg_hcd_queue_transactions(hcd, tr_type);
528 DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
532 int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd,
533 dwc_otg_hcd_urb_t * dwc_otg_urb)
536 dwc_otg_qtd_t *urb_qtd;
538 urb_qtd = dwc_otg_urb->qtd;
539 if(((uint32_t)urb_qtd&0xf0000000) == 0){
540 DWC_PRINTF("%s error: urb_qtd is %p dwc_otg_urb %p!!!\n",
541 __func__, urb_qtd, dwc_otg_urb);
546 if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
547 if (urb_qtd->in_process) {
548 dump_channel_info(hcd, qh);
552 if (urb_qtd->in_process && qh->channel) {
553 /* The QTD is in process (it has been assigned to a channel). */
554 if (hcd->flags.b.port_connect_status) {
556 * If still connected (i.e. in host mode), halt the
557 * channel so it can be used for other transfers. If
558 * no longer connected, the host registers can't be
559 * written to halt the channel since the core is in
562 dwc_otg_hc_halt(hcd->core_if, qh->channel,
563 DWC_OTG_HC_XFER_URB_DEQUEUE);
568 * Free the QTD and clean up the associated QH. Leave the QH in the
569 * schedule if it has any remaining QTDs.
572 if (!hcd->core_if->dma_desc_enable) {
573 uint8_t b = urb_qtd->in_process;
574 dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);
576 dwc_otg_hcd_qh_deactivate(hcd, qh, 0);
578 } else if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
579 dwc_otg_hcd_qh_remove(hcd, qh);
582 dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);
587 int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle,
590 dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
592 dwc_irqflags_t flags;
595 retval = -DWC_E_INVALID;
600 retval = -DWC_E_INVALID;
604 DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
606 while (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list) && retry) {
607 DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
610 DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
613 dwc_otg_hcd_qh_remove(hcd, qh);
615 DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
617 * Split dwc_otg_hcd_qh_remove_and_free() into qh_remove
618 * and qh_free to prevent stack dump on DWC_DMA_FREE() with
619 * irq_disabled (spinlock_irqsave) in dwc_otg_hcd_desc_list_free()
620 * and dwc_otg_hcd_frame_list_alloc().
622 dwc_otg_hcd_qh_free(hcd, qh);
628 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
629 int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t * hcd, void *ep_handle)
632 dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
634 return -DWC_E_INVALID;
636 qh->data_toggle = DWC_OTG_HC_PID_DATA0;
642 * HCD Callback structure for handling mode switching.
644 static dwc_otg_cil_callbacks_t hcd_cil_callbacks = {
645 .start = dwc_otg_hcd_start_cb,
646 .stop = dwc_otg_hcd_stop_cb,
647 .disconnect = dwc_otg_hcd_disconnect_cb,
648 .session_start = dwc_otg_hcd_session_start_cb,
649 .resume_wakeup = dwc_otg_hcd_rem_wakeup_cb,
650 #ifdef CONFIG_USB_DWC_OTG_LPM
651 .sleep = dwc_otg_hcd_sleep_cb,
657 * Reset tasklet function
659 static void reset_tasklet_func(void *data)
661 dwc_otg_hcd_t *dwc_otg_hcd = (dwc_otg_hcd_t *) data;
662 dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
665 DWC_DEBUGPL(DBG_HCDV, "USB RESET tasklet called\n");
667 hprt0.d32 = dwc_otg_read_hprt0(core_if);
669 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
673 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
674 dwc_otg_hcd->flags.b.port_reset_change = 1;
677 static void qh_list_free(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
679 dwc_list_link_t *item;
681 dwc_irqflags_t flags;
683 if (!qh_list->next) {
684 /* The list hasn't been initialized yet. */
688 * Hold spinlock here. Not needed in that case if bellow
689 * function is being called from ISR
691 DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
692 /* Ensure there are no QTDs or URBs left. */
693 kill_urbs_in_qh_list(hcd, qh_list);
694 DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
696 DWC_LIST_FOREACH(item, qh_list) {
697 qh = DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
698 dwc_otg_hcd_qh_remove_and_free(hcd, qh);
703 * Exit from Hibernation if Host did not detect SRP from connected SRP capable
704 * Device during SRP time by host power up.
706 void dwc_otg_hcd_power_up(void *ptr)
708 gpwrdn_data_t gpwrdn = {.d32 = 0 };
709 dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
711 DWC_PRINTF("%s called\n", __FUNCTION__);
713 if (!core_if->hibernation_suspend) {
714 DWC_PRINTF("Already exited from Hibernation\n");
718 /* Switch on the voltage to the core */
719 gpwrdn.b.pwrdnswtch = 1;
720 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
725 gpwrdn.b.pwrdnrstn = 1;
726 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
729 /* Disable power clamps */
731 gpwrdn.b.pwrdnclmp = 1;
732 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
734 /* Remove reset the core signal */
736 gpwrdn.b.pwrdnrstn = 1;
737 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
740 /* Disable PMU interrupt */
742 gpwrdn.b.pmuintsel = 1;
743 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
745 core_if->hibernation_suspend = 0;
749 gpwrdn.b.pmuactv = 1;
750 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
755 gpwrdn.b.dis_vbus = 1;
756 DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
758 core_if->op_state = A_HOST;
759 dwc_otg_core_init(core_if);
760 dwc_otg_enable_global_interrupts(core_if);
761 cil_hcd_start(core_if);
765 * Frees secondary storage associated with the dwc_otg_hcd structure contained
766 * in the struct usb_hcd field.
768 static void dwc_otg_hcd_free(dwc_otg_hcd_t * dwc_otg_hcd)
772 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD FREE\n");
774 del_timers(dwc_otg_hcd);
776 /* Free memory for QH/QTD lists */
777 qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_inactive);
778 qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_active);
779 qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_inactive);
780 qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_ready);
781 qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_assigned);
782 qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_queued);
784 /* Free memory for the host channels. */
785 for (i = 0; i < MAX_EPS_CHANNELS; i++) {
786 dwc_hc_t *hc = dwc_otg_hcd->hc_ptr_array[i];
789 if (dwc_otg_hcd->core_if->hc_xfer_timer[i]) {
790 DWC_TIMER_FREE(dwc_otg_hcd->core_if->hc_xfer_timer[i]);
794 DWC_DEBUGPL(DBG_HCDV, "HCD Free channel #%i, hc=%p\n",
800 if (dwc_otg_hcd->core_if->dma_enable) {
801 if (dwc_otg_hcd->status_buf_dma) {
802 DWC_DMA_FREE(DWC_OTG_HCD_STATUS_BUF_SIZE,
803 dwc_otg_hcd->status_buf,
804 dwc_otg_hcd->status_buf_dma);
806 } else if (dwc_otg_hcd->status_buf != NULL) {
807 DWC_FREE(dwc_otg_hcd->status_buf);
809 DWC_SPINLOCK_FREE(dwc_otg_hcd->lock);
810 /* Set core_if's lock pointer to NULL */
811 dwc_otg_hcd->core_if->lock = NULL;
813 DWC_TIMER_FREE(dwc_otg_hcd->conn_timer);
814 DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet);
816 #ifdef DWC_DEV_SRPCAP
817 if (dwc_otg_hcd->core_if->power_down == 2 &&
818 dwc_otg_hcd->core_if->pwron_timer) {
819 DWC_TIMER_FREE(dwc_otg_hcd->core_if->pwron_timer);
822 DWC_FREE(dwc_otg_hcd);
825 int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if)
832 hcd->lock = DWC_SPINLOCK_ALLOC();
834 DWC_ERROR("Could not allocate lock for pcd");
836 retval = -DWC_E_NO_MEMORY;
839 hcd->core_if = core_if;
841 /* Register the HCD CIL Callbacks */
842 dwc_otg_cil_register_hcd_callbacks(hcd->core_if,
843 &hcd_cil_callbacks, hcd);
845 /* Initialize the non-periodic schedule. */
846 DWC_LIST_INIT(&hcd->non_periodic_sched_inactive);
847 DWC_LIST_INIT(&hcd->non_periodic_sched_active);
849 /* Initialize the periodic schedule. */
850 DWC_LIST_INIT(&hcd->periodic_sched_inactive);
851 DWC_LIST_INIT(&hcd->periodic_sched_ready);
852 DWC_LIST_INIT(&hcd->periodic_sched_assigned);
853 DWC_LIST_INIT(&hcd->periodic_sched_queued);
856 * Create a host channel descriptor for each host channel implemented
857 * in the controller. Initialize the channel descriptor array.
859 DWC_CIRCLEQ_INIT(&hcd->free_hc_list);
860 num_channels = hcd->core_if->core_params->host_channels;
861 DWC_MEMSET(hcd->hc_ptr_array, 0, sizeof(hcd->hc_ptr_array));
862 for (i = 0; i < num_channels; i++) {
863 channel = DWC_ALLOC(sizeof(dwc_hc_t));
864 if (channel == NULL) {
865 retval = -DWC_E_NO_MEMORY;
866 DWC_ERROR("%s: host channel allocation failed\n",
868 dwc_otg_hcd_free(hcd);
872 hcd->hc_ptr_array[i] = channel;
874 hcd->core_if->hc_xfer_timer[i] =
875 DWC_TIMER_ALLOC("hc timer", hc_xfer_timeout,
876 &hcd->core_if->hc_xfer_info[i]);
878 DWC_DEBUGPL(DBG_HCDV, "HCD Added channel #%d, hc=%p\n", i,
882 /* Initialize the Connection timeout timer. */
883 hcd->conn_timer = DWC_TIMER_ALLOC("Connection timer",
884 dwc_otg_hcd_connect_timeout, hcd);
886 /* Initialize reset tasklet. */
887 hcd->reset_tasklet = DWC_TASK_ALLOC("reset_tasklet", reset_tasklet_func, hcd);
888 #ifdef DWC_DEV_SRPCAP
889 if (hcd->core_if->power_down == 2) {
890 /* Initialize Power on timer for Host power up in case hibernation */
891 hcd->core_if->pwron_timer = DWC_TIMER_ALLOC("PWRON TIMER",
892 dwc_otg_hcd_power_up, core_if);
897 * Allocate space for storing data on status transactions. Normally no
898 * data is sent, but this space acts as a bit bucket. This must be
899 * done after usb_add_hcd since that function allocates the DMA buffer
902 if (hcd->core_if->dma_enable) {
904 DWC_DMA_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE,
905 &hcd->status_buf_dma);
907 hcd->status_buf = DWC_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE);
909 if (!hcd->status_buf) {
910 retval = -DWC_E_NO_MEMORY;
911 DWC_ERROR("%s: status_buf allocation failed\n", __func__);
912 dwc_otg_hcd_free(hcd);
917 hcd->frame_list = NULL;
918 hcd->frame_list_dma = 0;
919 hcd->periodic_qh_count = 0;
924 void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd)
926 /* Turn off all host-specific interrupts. */
927 dwc_otg_disable_host_interrupts(hcd->core_if);
929 dwc_otg_hcd_free(hcd);
933 * Initializes dynamic portions of the DWC_otg HCD state.
935 static void dwc_otg_hcd_reinit(dwc_otg_hcd_t * hcd)
940 dwc_hc_t *channel_tmp;
944 hcd->non_periodic_qh_ptr = &hcd->non_periodic_sched_active;
945 hcd->non_periodic_channels = 0;
946 hcd->periodic_channels = 0;
949 * Put all channels in the free channel list and clean up channel
952 DWC_CIRCLEQ_FOREACH_SAFE(channel, channel_tmp,
953 &hcd->free_hc_list, hc_list_entry) {
954 DWC_CIRCLEQ_REMOVE(&hcd->free_hc_list, channel, hc_list_entry);
957 num_channels = hcd->core_if->core_params->host_channels;
958 for (i = 0; i < num_channels; i++) {
959 channel = hcd->hc_ptr_array[i];
960 DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, channel,
962 dwc_otg_hc_cleanup(hcd->core_if, channel);
965 /* Initialize the DWC core for host mode operation. */
966 dwc_otg_core_host_init(hcd->core_if);
968 /* Set core_if's lock pointer to the hcd->lock */
969 hcd->core_if->lock = hcd->lock;
973 * Assigns transactions from a QTD to a free host channel and initializes the
974 * host channel to perform the transactions. The host channel is removed from
977 * @param hcd The HCD state structure.
978 * @param qh Transactions from the first QTD for this QH are selected and
979 * assigned to a free host channel.
981 static int assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
985 dwc_otg_hcd_urb_t *urb;
989 DWC_DEBUGPL(DBG_HCDV, "%s(%p,%p)\n", __func__, hcd, qh);
991 hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);
993 /* Remove the host channel from the free list. */
994 DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry);
996 qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
1000 printk("%s : urb is NULL\n", __func__);
1007 qtd->in_process = 1;
1010 * Use usb_pipedevice to determine device address. This address is
1011 * 0 before the SET_ADDRESS command and the correct address afterward.
1013 hc->dev_addr = dwc_otg_hcd_get_dev_addr(&urb->pipe_info);
1014 hc->ep_num = dwc_otg_hcd_get_ep_num(&urb->pipe_info);
1015 hc->speed = qh->dev_speed;
1016 hc->max_packet = dwc_max_packet(qh->maxp);
1018 hc->xfer_started = 0;
1019 hc->halt_status = DWC_OTG_HC_XFER_NO_HALT_STATUS;
1020 hc->error_state = (qtd->error_count > 0);
1021 hc->halt_on_queue = 0;
1022 hc->halt_pending = 0;
1026 * The following values may be modified in the transfer type section
1027 * below. The xfer_len value may be reduced when the transfer is
1028 * started to accommodate the max widths of the XferSize and PktCnt
1029 * fields in the HCTSIZn register.
1032 hc->ep_is_in = (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) != 0);
1036 hc->do_ping = qh->ping_state;
1039 hc->data_pid_start = qh->data_toggle;
1040 hc->multi_count = 1;
1042 if (hcd->core_if->dma_enable) {
1043 hc->xfer_buff = (uint8_t *) urb->dma + urb->actual_length;
1045 /* For non-dword aligned case */
1046 if (((unsigned long)hc->xfer_buff & 0x3)
1047 && !hcd->core_if->dma_desc_enable) {
1048 ptr = (uint8_t *) urb->buf + urb->actual_length;
1051 hc->xfer_buff = (uint8_t *) urb->buf + urb->actual_length;
1053 hc->xfer_len = urb->length - urb->actual_length;
1057 * Set the split attributes
1061 uint32_t hub_addr, port_addr;
1063 hc->xact_pos = qtd->isoc_split_pos;
1064 hc->complete_split = qtd->complete_split;
1065 hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &port_addr);
1066 hc->hub_addr = (uint8_t) hub_addr;
1067 hc->port_addr = (uint8_t) port_addr;
1070 switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) {
1072 hc->ep_type = DWC_OTG_EP_TYPE_CONTROL;
1073 switch (qtd->control_phase) {
1074 case DWC_OTG_CONTROL_SETUP:
1075 DWC_DEBUGPL(DBG_HCDV, " Control setup transaction\n");
1078 hc->data_pid_start = DWC_OTG_HC_PID_SETUP;
1079 if (hcd->core_if->dma_enable) {
1080 hc->xfer_buff = (uint8_t *) urb->setup_dma;
1082 hc->xfer_buff = (uint8_t *) urb->setup_packet;
1087 case DWC_OTG_CONTROL_DATA:
1088 DWC_DEBUGPL(DBG_HCDV, " Control data transaction\n");
1089 hc->data_pid_start = qtd->data_toggle;
1091 case DWC_OTG_CONTROL_STATUS:
1093 * Direction is opposite of data direction or IN if no
1096 DWC_DEBUGPL(DBG_HCDV, " Control status transaction\n");
1097 if (urb->length == 0) {
1101 dwc_otg_hcd_is_pipe_out(&urb->pipe_info);
1107 hc->data_pid_start = DWC_OTG_HC_PID_DATA1;
1110 if (hcd->core_if->dma_enable) {
1111 hc->xfer_buff = (uint8_t *) hcd->status_buf_dma;
1113 hc->xfer_buff = (uint8_t *) hcd->status_buf;
1120 hc->ep_type = DWC_OTG_EP_TYPE_BULK;
1123 hc->ep_type = DWC_OTG_EP_TYPE_INTR;
1125 case UE_ISOCHRONOUS:
1127 struct dwc_otg_hcd_iso_packet_desc *frame_desc;
1129 hc->ep_type = DWC_OTG_EP_TYPE_ISOC;
1131 if (hcd->core_if->dma_desc_enable)
1134 frame_desc = &urb->iso_descs[qtd->isoc_frame_index];
1136 frame_desc->status = 0;
1138 if (hcd->core_if->dma_enable) {
1139 hc->xfer_buff = (uint8_t *) urb->dma;
1141 hc->xfer_buff = (uint8_t *) urb->buf;
1144 frame_desc->offset + qtd->isoc_split_offset;
1146 frame_desc->length - qtd->isoc_split_offset;
1148 /* For non-dword aligned buffers */
1149 if (((unsigned long)hc->xfer_buff & 0x3)
1150 && hcd->core_if->dma_enable) {
1152 (uint8_t *) urb->buf + frame_desc->offset +
1153 qtd->isoc_split_offset;
1157 if (hc->xact_pos == DWC_HCSPLIT_XACTPOS_ALL) {
1158 if (hc->xfer_len <= 188) {
1159 hc->xact_pos = DWC_HCSPLIT_XACTPOS_ALL;
1162 DWC_HCSPLIT_XACTPOS_BEGIN;
1168 /* non DWORD-aligned buffer case */
1171 if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
1172 buf_size = hcd->core_if->core_params->max_transfer_size;
1176 if (!qh->dw_align_buf) {
1177 qh->dw_align_buf = DWC_DMA_ALLOC_ATOMIC(buf_size,
1178 &qh->dw_align_buf_dma);
1179 if (!qh->dw_align_buf) {
1181 ("%s: Failed to allocate memory to handle "
1182 "non-dword aligned buffer case\n",
1187 if (!hc->ep_is_in) {
1188 dwc_memcpy(qh->dw_align_buf, ptr, hc->xfer_len);
1190 hc->align_buff = qh->dw_align_buf_dma;
1195 if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
1196 hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
1198 * This value may be modified when the transfer is started to
1199 * reflect the actual transfer length.
1201 hc->multi_count = dwc_hb_mult(qh->maxp);
1204 if (hcd->core_if->dma_desc_enable)
1205 hc->desc_list_addr = qh->desc_list_dma;
1207 dwc_otg_hc_init(hcd->core_if, hc);
1213 * This function selects transactions from the HCD transfer schedule and
1214 * assigns them to available host channels. It is called from HCD interrupt
1215 * handler functions.
1217 * @param hcd The HCD state structure.
1219 * @return The types of new transactions that were assigned to host channels.
1221 dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
1223 dwc_list_link_t *qh_ptr;
1226 dwc_otg_transaction_type_e ret_val = DWC_OTG_TRANSACTION_NONE;
1230 DWC_DEBUGPL(DBG_HCD, " Select Transactions\n");
1233 /* Process entries in the periodic ready list. */
1234 qh_ptr = DWC_LIST_FIRST(&hcd->periodic_sched_ready);
1236 while (qh_ptr != &hcd->periodic_sched_ready &&
1237 !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
1239 qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
1240 assign_and_init_hc(hcd, qh);
1243 * Move the QH from the periodic ready schedule to the
1244 * periodic assigned schedule.
1246 qh_ptr = DWC_LIST_NEXT(qh_ptr);
1247 DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
1248 &qh->qh_list_entry);
1250 ret_val = DWC_OTG_TRANSACTION_PERIODIC;
1254 * Process entries in the inactive portion of the non-periodic
1255 * schedule. Some free host channels may not be used if they are
1256 * reserved for periodic transfers.
1258 qh_ptr = hcd->non_periodic_sched_inactive.next;
1259 num_channels = hcd->core_if->core_params->host_channels;
1260 while (qh_ptr != &hcd->non_periodic_sched_inactive &&
1261 (hcd->non_periodic_channels <
1262 num_channels - hcd->periodic_channels) &&
1263 !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
1265 qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
1267 err = assign_and_init_hc(hcd, qh);
1270 * Move the QH from the non-periodic inactive schedule to the
1271 * non-periodic active schedule.
1273 qh_ptr = DWC_LIST_NEXT(qh_ptr);
1276 DWC_LIST_MOVE_HEAD(&hcd->non_periodic_sched_active,
1277 &qh->qh_list_entry);
1279 if (ret_val == DWC_OTG_TRANSACTION_NONE) {
1280 ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC;
1282 ret_val = DWC_OTG_TRANSACTION_ALL;
1285 hcd->non_periodic_channels++;
1292 * Attempts to queue a single transaction request for a host channel
1293 * associated with either a periodic or non-periodic transfer. This function
1294 * assumes that there is space available in the appropriate request queue. For
1295 * an OUT transfer or SETUP transaction in Slave mode, it checks whether space
1296 * is available in the appropriate Tx FIFO.
1298 * @param hcd The HCD state structure.
1299 * @param hc Host channel descriptor associated with either a periodic or
1300 * non-periodic transfer.
1301 * @param fifo_dwords_avail Number of DWORDs available in the periodic Tx
1302 * FIFO for periodic transfers or the non-periodic Tx FIFO for non-periodic
1305 * @return 1 if a request is queued and more requests may be needed to
1306 * complete the transfer, 0 if no more requests are required for this
1307 * transfer, -1 if there is insufficient space in the Tx FIFO.
1309 static int queue_transaction(dwc_otg_hcd_t * hcd,
1310 dwc_hc_t * hc, uint16_t fifo_dwords_avail)
1314 if (hcd->core_if->dma_enable) {
1315 if (hcd->core_if->dma_desc_enable) {
1316 if (!hc->xfer_started
1317 || (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)) {
1318 dwc_otg_hcd_start_xfer_ddma(hcd, hc->qh);
1319 hc->qh->ping_state = 0;
1321 } else if (!hc->xfer_started) {
1322 dwc_otg_hc_start_transfer(hcd->core_if, hc);
1323 hc->qh->ping_state = 0;
1326 } else if (hc->halt_pending) {
1327 /* Don't queue a request if the channel has been halted. */
1329 } else if (hc->halt_on_queue) {
1330 dwc_otg_hc_halt(hcd->core_if, hc, hc->halt_status);
1332 } else if (hc->do_ping) {
1333 if (!hc->xfer_started) {
1334 dwc_otg_hc_start_transfer(hcd->core_if, hc);
1337 } else if (!hc->ep_is_in || hc->data_pid_start == DWC_OTG_HC_PID_SETUP) {
1338 if ((fifo_dwords_avail * 4) >= hc->max_packet) {
1339 if (!hc->xfer_started) {
1340 dwc_otg_hc_start_transfer(hcd->core_if, hc);
1344 dwc_otg_hc_continue_transfer(hcd->core_if,
1351 if (!hc->xfer_started) {
1352 dwc_otg_hc_start_transfer(hcd->core_if, hc);
1355 retval = dwc_otg_hc_continue_transfer(hcd->core_if, hc);
1363 * Processes periodic channels for the next frame and queues transactions for
1364 * these channels to the DWC_otg controller. After queueing transactions, the
1365 * Periodic Tx FIFO Empty interrupt is enabled if there are more transactions
1366 * to queue as Periodic Tx FIFO or request queue space becomes available.
1367 * Otherwise, the Periodic Tx FIFO Empty interrupt is disabled.
1369 static void process_periodic_channels(dwc_otg_hcd_t * hcd)
1371 hptxsts_data_t tx_status;
1372 dwc_list_link_t *qh_ptr;
1375 int no_queue_space = 0;
1376 int no_fifo_space = 0;
1378 dwc_otg_host_global_regs_t *host_regs;
1379 host_regs = hcd->core_if->host_if->host_global_regs;
1381 DWC_DEBUGPL(DBG_HCDV, "Queue periodic transactions\n");
1383 tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
1384 DWC_DEBUGPL(DBG_HCDV,
1385 " P Tx Req Queue Space Avail (before queue): %d\n",
1386 tx_status.b.ptxqspcavail);
1387 DWC_DEBUGPL(DBG_HCDV, " P Tx FIFO Space Avail (before queue): %d\n",
1388 tx_status.b.ptxfspcavail);
1391 qh_ptr = hcd->periodic_sched_assigned.next;
1392 while (qh_ptr != &hcd->periodic_sched_assigned) {
1393 tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
1394 if (tx_status.b.ptxqspcavail == 0) {
1399 qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
1402 * Set a flag if we're queuing high-bandwidth in slave mode.
1403 * The flag prevents any halts to get into the request queue in
1404 * the middle of multiple high-bandwidth packets getting queued.
1406 if (!hcd->core_if->dma_enable && qh->channel->multi_count > 1) {
1407 hcd->core_if->queuing_high_bandwidth = 1;
1410 queue_transaction(hcd, qh->channel,
1411 tx_status.b.ptxfspcavail);
1418 * In Slave mode, stay on the current transfer until there is
1419 * nothing more to do or the high-bandwidth request count is
1420 * reached. In DMA mode, only need to queue one request. The
1421 * controller automatically handles multiple packets for
1422 * high-bandwidth transfers.
1424 if (hcd->core_if->dma_enable || status == 0 ||
1425 qh->channel->requests == qh->channel->multi_count) {
1426 qh_ptr = qh_ptr->next;
1428 * Move the QH from the periodic assigned schedule to
1429 * the periodic queued schedule.
1431 DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_queued,
1432 &qh->qh_list_entry);
1434 /* done queuing high bandwidth */
1435 hcd->core_if->queuing_high_bandwidth = 0;
1439 if (!hcd->core_if->dma_enable) {
1440 dwc_otg_core_global_regs_t *global_regs;
1441 gintmsk_data_t intr_mask = {.d32 = 0 };
1443 global_regs = hcd->core_if->core_global_regs;
1444 intr_mask.b.ptxfempty = 1;
1446 tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
1447 DWC_DEBUGPL(DBG_HCDV,
1448 " P Tx Req Queue Space Avail (after queue): %d\n",
1449 tx_status.b.ptxqspcavail);
1450 DWC_DEBUGPL(DBG_HCDV,
1451 " P Tx FIFO Space Avail (after queue): %d\n",
1452 tx_status.b.ptxfspcavail);
1454 if (!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned) ||
1455 no_queue_space || no_fifo_space) {
1457 * May need to queue more transactions as the request
1458 * queue or Tx FIFO empties. Enable the periodic Tx
1459 * FIFO empty interrupt. (Always use the half-empty
1460 * level to ensure that new requests are loaded as
1461 * soon as possible.)
1463 DWC_MODIFY_REG32(&global_regs->gintmsk, 0,
1467 * Disable the Tx FIFO empty interrupt since there are
1468 * no more transactions that need to be queued right
1469 * now. This function is called from interrupt
1470 * handlers to queue more transactions as transfer
1473 DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32,
1480 * Processes active non-periodic channels and queues transactions for these
1481 * channels to the DWC_otg controller. After queueing transactions, the NP Tx
1482 * FIFO Empty interrupt is enabled if there are more transactions to queue as
1483 * NP Tx FIFO or request queue space becomes available. Otherwise, the NP Tx
1484 * FIFO Empty interrupt is disabled.
1486 static void process_non_periodic_channels(dwc_otg_hcd_t * hcd)
1488 gnptxsts_data_t tx_status;
1489 dwc_list_link_t *orig_qh_ptr;
1492 int no_queue_space = 0;
1493 int no_fifo_space = 0;
1496 dwc_otg_core_global_regs_t *global_regs =
1497 hcd->core_if->core_global_regs;
1499 DWC_DEBUGPL(DBG_HCDV, "Queue non-periodic transactions\n");
1501 tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
1502 DWC_DEBUGPL(DBG_HCDV,
1503 " NP Tx Req Queue Space Avail (before queue): %d\n",
1504 tx_status.b.nptxqspcavail);
1505 DWC_DEBUGPL(DBG_HCDV, " NP Tx FIFO Space Avail (before queue): %d\n",
1506 tx_status.b.nptxfspcavail);
1509 * Keep track of the starting point. Skip over the start-of-list
1512 if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {
1513 hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
1515 orig_qh_ptr = hcd->non_periodic_qh_ptr;
1518 * Process once through the active list or until no more space is
1519 * available in the request queue or the Tx FIFO.
1522 tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
1523 if (!hcd->core_if->dma_enable && tx_status.b.nptxqspcavail == 0) {
1528 qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t,
1531 queue_transaction(hcd, qh->channel,
1532 tx_status.b.nptxfspcavail);
1536 } else if (status < 0) {
1541 /* Advance to next QH, skipping start-of-list entry. */
1542 hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
1543 if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {
1544 hcd->non_periodic_qh_ptr =
1545 hcd->non_periodic_qh_ptr->next;
1548 } while (hcd->non_periodic_qh_ptr != orig_qh_ptr);
1550 if (!hcd->core_if->dma_enable) {
1551 gintmsk_data_t intr_mask = {.d32 = 0 };
1552 intr_mask.b.nptxfempty = 1;
1555 tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
1556 DWC_DEBUGPL(DBG_HCDV,
1557 " NP Tx Req Queue Space Avail (after queue): %d\n",
1558 tx_status.b.nptxqspcavail);
1559 DWC_DEBUGPL(DBG_HCDV,
1560 " NP Tx FIFO Space Avail (after queue): %d\n",
1561 tx_status.b.nptxfspcavail);
1563 if (more_to_do || no_queue_space || no_fifo_space) {
1565 * May need to queue more transactions as the request
1566 * queue or Tx FIFO empties. Enable the non-periodic
1567 * Tx FIFO empty interrupt. (Always use the half-empty
1568 * level to ensure that new requests are loaded as
1569 * soon as possible.)
1571 DWC_MODIFY_REG32(&global_regs->gintmsk, 0,
1575 * Disable the Tx FIFO empty interrupt since there are
1576 * no more transactions that need to be queued right
1577 * now. This function is called from interrupt
1578 * handlers to queue more transactions as transfer
1581 DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32,
1588 * This function processes the currently active host channels and queues
1589 * transactions for these channels to the DWC_otg controller. It is called
1590 * from HCD interrupt handler functions.
1592 * @param hcd The HCD state structure.
1593 * @param tr_type The type(s) of transactions to queue (non-periodic,
1594 * periodic, or both).
1596 void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
1597 dwc_otg_transaction_type_e tr_type)
1600 DWC_DEBUGPL(DBG_HCD, "Queue Transactions\n");
1602 /* Process host channels associated with periodic transfers. */
1603 if ((tr_type == DWC_OTG_TRANSACTION_PERIODIC ||
1604 tr_type == DWC_OTG_TRANSACTION_ALL) &&
1605 !DWC_LIST_EMPTY(&hcd->periodic_sched_assigned)) {
1607 process_periodic_channels(hcd);
1610 /* Process host channels associated with non-periodic transfers. */
1611 if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC ||
1612 tr_type == DWC_OTG_TRANSACTION_ALL) {
1613 if (!DWC_LIST_EMPTY(&hcd->non_periodic_sched_active)) {
1614 process_non_periodic_channels(hcd);
1617 * Ensure NP Tx FIFO empty interrupt is disabled when
1618 * there are no non-periodic transfers to process.
1620 gintmsk_data_t gintmsk = {.d32 = 0 };
1621 gintmsk.b.nptxfempty = 1;
1622 DWC_MODIFY_REG32(&hcd->core_if->
1623 core_global_regs->gintmsk, gintmsk.d32,
1629 #ifdef DWC_HS_ELECT_TST
1631 * Quick and dirty hack to implement the HS Electrical Test
1632 * SINGLE_STEP_GET_DEVICE_DESCRIPTOR feature.
1634 * This code was copied from our userspace app "hset". It sends a
1635 * Get Device Descriptor control sequence in two parts, first the
1636 * Setup packet by itself, followed some time later by the In and
1637 * Ack packets. Rather than trying to figure out how to add this
1638 * functionality to the normal driver code, we just hijack the
1639 * hardware, using these two function to drive the hardware
1643 static dwc_otg_core_global_regs_t *global_regs;
1644 static dwc_otg_host_global_regs_t *hc_global_regs;
1645 static dwc_otg_hc_regs_t *hc_regs;
1646 static uint32_t *data_fifo;
1648 static void do_setup(void)
1650 gintsts_data_t gintsts;
1651 hctsiz_data_t hctsiz;
1652 hcchar_data_t hcchar;
1657 DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001);
1660 DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3);
1663 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1666 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
1669 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
1672 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1675 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
1678 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
1681 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
1684 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1687 * Send Setup packet (Get Device Descriptor)
1690 /* Make sure channel is disabled */
1691 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1692 if (hcchar.b.chen) {
1694 // hcchar.b.chen = 1;
1695 DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
1700 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1703 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
1706 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
1709 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1712 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
1715 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
1718 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
1720 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1725 hctsiz.b.xfersize = 8;
1726 hctsiz.b.pktcnt = 1;
1727 hctsiz.b.pid = DWC_OTG_HC_PID_SETUP;
1728 DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
1731 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1732 hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
1737 DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
1739 /* Fill FIFO with Setup data for Get Device Descriptor */
1740 data_fifo = (uint32_t *) ((char *)global_regs + 0x1000);
1741 DWC_WRITE_REG32(data_fifo++, 0x01000680);
1742 DWC_WRITE_REG32(data_fifo++, 0x00080000);
1744 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1746 /* Wait for host channel interrupt */
1748 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1749 } while (gintsts.b.hcintr == 0);
1751 /* Disable HCINTs */
1752 DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000);
1754 /* Disable HAINTs */
1755 DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000);
1758 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
1761 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
1764 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1767 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
1770 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
1773 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
1776 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1779 static void do_in_ack(void)
1781 gintsts_data_t gintsts;
1782 hctsiz_data_t hctsiz;
1783 hcchar_data_t hcchar;
1786 host_grxsts_data_t grxsts;
1789 DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001);
1792 DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3);
1795 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1798 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
1801 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
1804 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1807 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
1810 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
1813 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
1816 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1819 * Receive Control In packet
1822 /* Make sure channel is disabled */
1823 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1824 if (hcchar.b.chen) {
1827 DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
1832 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1835 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
1838 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
1841 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1844 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
1847 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
1850 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
1852 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1857 hctsiz.b.xfersize = 8;
1858 hctsiz.b.pktcnt = 1;
1859 hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;
1860 DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
1863 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1864 hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
1869 DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
1871 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1873 /* Wait for receive status queue interrupt */
1875 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1876 } while (gintsts.b.rxstsqlvl == 0);
1879 grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp);
1881 /* Clear RXSTSQLVL in GINTSTS */
1883 gintsts.b.rxstsqlvl = 1;
1884 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
1886 switch (grxsts.b.pktsts) {
1887 case DWC_GRXSTS_PKTSTS_IN:
1888 /* Read the data into the host buffer */
1889 if (grxsts.b.bcnt > 0) {
1891 int word_count = (grxsts.b.bcnt + 3) / 4;
1893 data_fifo = (uint32_t *) ((char *)global_regs + 0x1000);
1895 for (i = 0; i < word_count; i++) {
1896 (void)DWC_READ_REG32(data_fifo++);
1905 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1907 /* Wait for receive status queue interrupt */
1909 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1910 } while (gintsts.b.rxstsqlvl == 0);
1913 grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp);
1915 /* Clear RXSTSQLVL in GINTSTS */
1917 gintsts.b.rxstsqlvl = 1;
1918 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
1920 switch (grxsts.b.pktsts) {
1921 case DWC_GRXSTS_PKTSTS_IN_XFER_COMP:
1928 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1930 /* Wait for host channel interrupt */
1932 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1933 } while (gintsts.b.hcintr == 0);
1936 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
1939 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
1942 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1945 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
1948 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
1951 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
1954 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1961 * Send handshake packet
1965 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
1968 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
1971 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1974 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
1977 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
1980 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
1983 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1985 /* Make sure channel is disabled */
1986 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1987 if (hcchar.b.chen) {
1990 DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
1995 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
1998 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
2001 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
2004 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
2007 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
2010 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
2013 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
2015 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
2020 hctsiz.b.xfersize = 0;
2021 hctsiz.b.pktcnt = 1;
2022 hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;
2023 DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
2026 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
2027 hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
2032 DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
2034 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
2036 /* Wait for host channel interrupt */
2038 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
2039 } while (gintsts.b.hcintr == 0);
2041 /* Disable HCINTs */
2042 DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000);
2044 /* Disable HAINTs */
2045 DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000);
2048 haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
2051 hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
2054 hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
2057 DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
2060 DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
2063 DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
2066 gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
2070 /** Handles hub class-specific requests. */
2071 int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd,
2074 uint16_t wIndex, uint8_t * buf, uint16_t wLength)
2078 dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
2079 usb_hub_descriptor_t *hub_desc;
2080 hprt0_data_t hprt0 = {.d32 = 0 };
2082 uint32_t port_status;
2085 case UCR_CLEAR_HUB_FEATURE:
2086 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2087 "ClearHubFeature 0x%x\n", wValue);
2089 case UHF_C_HUB_LOCAL_POWER:
2090 case UHF_C_HUB_OVER_CURRENT:
2091 /* Nothing required here */
2094 retval = -DWC_E_INVALID;
2095 DWC_ERROR("DWC OTG HCD - "
2096 "ClearHubFeature request %xh unknown\n",
2100 case UCR_CLEAR_PORT_FEATURE:
2101 #ifdef CONFIG_USB_DWC_OTG_LPM
2102 if (wValue != UHF_PORT_L1)
2104 if (!wIndex || wIndex > 1)
2108 case UHF_PORT_ENABLE:
2109 DWC_DEBUGPL(DBG_ANY, "DWC OTG HCD HUB CONTROL - "
2110 "ClearPortFeature USB_PORT_FEAT_ENABLE\n");
2111 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2113 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
2115 case UHF_PORT_SUSPEND:
2116 #if 0//def CONFIG_PM_RUNTIME
2119 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2120 "ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
2122 if (core_if->power_down == 2) {
2123 dwc_otg_host_hibernation_restore(core_if, 0, 0);
2125 DWC_WRITE_REG32(core_if->pcgcctl, 0);
2128 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2130 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
2131 hprt0.b.prtsusp = 0;
2132 /* Clear Resume bit */
2135 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
2138 #ifdef CONFIG_USB_DWC_OTG_LPM
2141 pcgcctl_data_t pcgcctl = {.d32 = 0 };
2142 glpmcfg_data_t lpmcfg = {.d32 = 0 };
2145 DWC_READ_REG32(&core_if->
2146 core_global_regs->glpmcfg);
2147 lpmcfg.b.en_utmi_sleep = 0;
2148 lpmcfg.b.hird_thres &= (~(1 << 4));
2149 lpmcfg.b.prt_sleep_sts = 1;
2150 DWC_WRITE_REG32(&core_if->
2151 core_global_regs->glpmcfg,
2154 /* Clear Enbl_L1Gating bit. */
2155 pcgcctl.b.enbl_sleep_gating = 1;
2156 DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32,
2161 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2163 DWC_WRITE_REG32(core_if->host_if->hprt0,
2165 /* This bit will be cleared in wakeup interrupt handle */
2169 case UHF_PORT_POWER:
2170 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2171 "ClearPortFeature USB_PORT_FEAT_POWER\n");
2172 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2174 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
2176 case UHF_PORT_INDICATOR:
2177 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2178 "ClearPortFeature USB_PORT_FEAT_INDICATOR\n");
2179 /* Port inidicator not supported */
2181 case UHF_C_PORT_CONNECTION:
2182 /* Clears drivers internal connect status change
2184 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2185 "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n");
2186 dwc_otg_hcd->flags.b.port_connect_status_change = 0;
2188 case UHF_C_PORT_RESET:
2189 /* Clears the driver's internal Port Reset Change
2191 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2192 "ClearPortFeature USB_PORT_FEAT_C_RESET\n");
2193 dwc_otg_hcd->flags.b.port_reset_change = 0;
2195 case UHF_C_PORT_ENABLE:
2196 /* Clears the driver's internal Port
2197 * Enable/Disable Change flag */
2198 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2199 "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n");
2200 dwc_otg_hcd->flags.b.port_enable_change = 0;
2202 case UHF_C_PORT_SUSPEND:
2203 /* Clears the driver's internal Port Suspend
2204 * Change flag, which is set when resume signaling on
2205 * the host port is complete */
2206 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2207 "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n");
2208 dwc_otg_hcd->flags.b.port_suspend_change = 0;
2210 #ifdef CONFIG_USB_DWC_OTG_LPM
2212 dwc_otg_hcd->flags.b.port_l1_change = 0;
2215 case UHF_C_PORT_OVER_CURRENT:
2216 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2217 "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n");
2218 dwc_otg_hcd->flags.b.port_over_current_change = 0;
2221 retval = -DWC_E_INVALID;
2222 DWC_ERROR("DWC OTG HCD - "
2223 "ClearPortFeature request %xh "
2224 "unknown or unsupported\n", wValue);
2227 case UCR_GET_HUB_DESCRIPTOR:
2228 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2229 "GetHubDescriptor\n");
2230 hub_desc = (usb_hub_descriptor_t *) buf;
2231 hub_desc->bDescLength = 9;
2232 hub_desc->bDescriptorType = 0x29;
2233 hub_desc->bNbrPorts = 1;
2234 USETW(hub_desc->wHubCharacteristics, 0x08);
2235 hub_desc->bPwrOn2PwrGood = 1;
2236 hub_desc->bHubContrCurrent = 0;
2237 hub_desc->DeviceRemovable[0] = 0;
2238 hub_desc->DeviceRemovable[1] = 0xff;
2240 case UCR_GET_HUB_STATUS:
2241 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2243 DWC_MEMSET(buf, 0, 4);
2245 case UCR_GET_PORT_STATUS:
2246 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2247 "GetPortStatus wIndex = 0x%04x FLAGS=0x%08x\n",
2248 wIndex, dwc_otg_hcd->flags.d32);
2249 if (!wIndex || wIndex > 1)
2254 if (dwc_otg_hcd->flags.b.port_connect_status_change)
2255 port_status |= (1 << UHF_C_PORT_CONNECTION);
2257 if (dwc_otg_hcd->flags.b.port_enable_change)
2258 port_status |= (1 << UHF_C_PORT_ENABLE);
2260 if (dwc_otg_hcd->flags.b.port_suspend_change)
2261 port_status |= (1 << UHF_C_PORT_SUSPEND);
2263 if (dwc_otg_hcd->flags.b.port_l1_change)
2264 port_status |= (1 << UHF_C_PORT_L1);
2266 if (dwc_otg_hcd->flags.b.port_reset_change) {
2267 port_status |= (1 << UHF_C_PORT_RESET);
2270 if (dwc_otg_hcd->flags.b.port_over_current_change) {
2271 DWC_WARN("Overcurrent change detected\n");
2272 port_status |= (1 << UHF_C_PORT_OVER_CURRENT);
2275 if (!dwc_otg_hcd->flags.b.port_connect_status) {
2277 * The port is disconnected, which means the core is
2278 * either in device mode or it soon will be. Just
2279 * return 0's for the remainder of the port status
2280 * since the port register can't be read if the core
2281 * is in device mode.
2283 *((__le32 *) buf) = dwc_cpu_to_le32(&port_status);
2287 hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
2288 DWC_DEBUGPL(DBG_HCDV, " HPRT0: 0x%08x\n", hprt0.d32);
2290 if (hprt0.b.prtconnsts)
2291 port_status |= (1 << UHF_PORT_CONNECTION);
2294 port_status |= (1 << UHF_PORT_ENABLE);
2296 if (hprt0.b.prtsusp)
2297 port_status |= (1 << UHF_PORT_SUSPEND);
2299 if (hprt0.b.prtovrcurract)
2300 port_status |= (1 << UHF_PORT_OVER_CURRENT);
2303 port_status |= (1 << UHF_PORT_RESET);
2306 port_status |= (1 << UHF_PORT_POWER);
2308 if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED)
2309 port_status |= (1 << UHF_PORT_HIGH_SPEED);
2310 else if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED)
2311 port_status |= (1 << UHF_PORT_LOW_SPEED);
2313 if (hprt0.b.prttstctl)
2314 port_status |= (1 << UHF_PORT_TEST);
2315 if (dwc_otg_get_lpm_portsleepstatus(dwc_otg_hcd->core_if)) {
2316 port_status |= (1 << UHF_PORT_L1);
2319 For Synopsys HW emulation of Power down wkup_control asserts the
2320 hreset_n and prst_n on suspned. This causes the HPRT0 to be zero.
2321 We intentionally tell the software that port is in L2Suspend state.
2324 if ((core_if->power_down == 2)
2325 && (core_if->hibernation_suspend == 1)) {
2326 port_status |= (1 << UHF_PORT_SUSPEND);
2328 /* USB_PORT_FEAT_INDICATOR unsupported always 0 */
2330 *((__le32 *) buf) = dwc_cpu_to_le32(&port_status);
2333 case UCR_SET_HUB_FEATURE:
2334 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2336 /* No HUB features supported */
2338 case UCR_SET_PORT_FEATURE:
2339 if (wValue != UHF_PORT_TEST && (!wIndex || wIndex > 1))
2342 if (!dwc_otg_hcd->flags.b.port_connect_status) {
2344 * The port is disconnected, which means the core is
2345 * either in device mode or it soon will be. Just
2346 * return without doing anything since the port
2347 * register can't be written if the core is in device
2354 case UHF_PORT_SUSPEND:
2355 #if 0//def CONFIG_PM_RUNTIME
2358 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2359 "SetPortFeature - USB_PORT_FEAT_SUSPEND\n");
2360 if (dwc_otg_hcd_otg_port(dwc_otg_hcd) != wIndex) {
2363 if (core_if->power_down == 2) {
2365 dwc_irqflags_t flags;
2366 pcgcctl_data_t pcgcctl = {.d32 = 0 };
2367 gpwrdn_data_t gpwrdn = {.d32 = 0 };
2368 gusbcfg_data_t gusbcfg = {.d32 = 0 };
2369 #ifdef DWC_DEV_SRPCAP
2370 int32_t otg_cap_param = core_if->core_params->otg_cap;
2372 DWC_PRINTF("Preparing for complete power-off\n");
2374 /* Save registers before hibernation */
2375 dwc_otg_save_global_regs(core_if);
2376 dwc_otg_save_host_regs(core_if);
2378 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2379 hprt0.b.prtsusp = 1;
2381 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
2382 /* Spin hprt0.b.prtsusp to became 1 */
2384 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2385 if (hprt0.b.prtsusp) {
2389 } while (--timeout);
2391 DWC_WARN("Suspend wasn't genereted\n");
2396 * We need to disable interrupts to prevent servicing of any IRQ
2397 * during going to hibernation
2399 DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
2400 core_if->lx_state = DWC_OTG_L2;
2401 #ifdef DWC_DEV_SRPCAP
2402 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2405 DWC_WRITE_REG32(core_if->host_if->hprt0,
2409 DWC_READ_REG32(&core_if->core_global_regs->
2411 if (gusbcfg.b.ulpi_utmi_sel == 1) {
2412 /* ULPI interface */
2413 /* Suspend the Phy Clock */
2415 pcgcctl.b.stoppclk = 1;
2416 DWC_MODIFY_REG32(core_if->pcgcctl, 0,
2419 gpwrdn.b.pmuactv = 1;
2420 DWC_MODIFY_REG32(&core_if->
2422 gpwrdn, 0, gpwrdn.d32);
2424 /* UTMI+ Interface */
2425 gpwrdn.b.pmuactv = 1;
2426 DWC_MODIFY_REG32(&core_if->
2428 gpwrdn, 0, gpwrdn.d32);
2430 pcgcctl.b.stoppclk = 1;
2431 DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
2434 #ifdef DWC_DEV_SRPCAP
2436 gpwrdn.b.dis_vbus = 1;
2437 DWC_MODIFY_REG32(&core_if->core_global_regs->
2438 gpwrdn, 0, gpwrdn.d32);
2441 gpwrdn.b.pmuintsel = 1;
2442 DWC_MODIFY_REG32(&core_if->core_global_regs->
2443 gpwrdn, 0, gpwrdn.d32);
2447 #ifdef DWC_DEV_SRPCAP
2448 gpwrdn.b.srp_det_msk = 1;
2450 gpwrdn.b.disconn_det_msk = 1;
2451 gpwrdn.b.lnstchng_msk = 1;
2452 gpwrdn.b.sts_chngint_msk = 1;
2453 DWC_MODIFY_REG32(&core_if->core_global_regs->
2454 gpwrdn, 0, gpwrdn.d32);
2457 /* Enable Power Down Clamp and all interrupts in GPWRDN */
2459 gpwrdn.b.pwrdnclmp = 1;
2460 DWC_MODIFY_REG32(&core_if->core_global_regs->
2461 gpwrdn, 0, gpwrdn.d32);
2464 /* Switch off VDD */
2466 gpwrdn.b.pwrdnswtch = 1;
2467 DWC_MODIFY_REG32(&core_if->core_global_regs->
2468 gpwrdn, 0, gpwrdn.d32);
2470 #ifdef DWC_DEV_SRPCAP
2471 if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE)
2473 core_if->pwron_timer_started = 1;
2474 DWC_TIMER_SCHEDULE(core_if->pwron_timer, 6000 /* 6 secs */ );
2477 /* Save gpwrdn register for further usage if stschng interrupt */
2478 core_if->gr_backup->gpwrdn_local =
2479 DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
2481 /* Set flag to indicate that we are in hibernation */
2482 core_if->hibernation_suspend = 1;
2483 DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock,flags);
2485 DWC_PRINTF("Host hibernation completed\n");
2486 // Exit from case statement
2490 if (dwc_otg_hcd_otg_port(dwc_otg_hcd) == wIndex &&
2491 dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) {
2492 gotgctl_data_t gotgctl = {.d32 = 0 };
2493 gotgctl.b.hstsethnpen = 1;
2494 DWC_MODIFY_REG32(&core_if->core_global_regs->
2495 gotgctl, 0, gotgctl.d32);
2496 core_if->op_state = A_SUSPEND;
2498 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2499 hprt0.b.prtsusp = 1;
2500 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
2502 dwc_irqflags_t flags;
2503 /* Update lx_state */
2504 DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
2505 core_if->lx_state = DWC_OTG_L2;
2506 DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
2508 /* Suspend the Phy Clock */
2509 if (core_if->otg_ver == 0) {
2510 pcgcctl_data_t pcgcctl = {.d32 = 0 };
2511 pcgcctl.b.stoppclk = 1;
2512 DWC_MODIFY_REG32(core_if->pcgcctl, 0,
2517 /* For HNP the bus must be suspended for at least 200ms. */
2518 if (dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) {
2519 pcgcctl_data_t pcgcctl = {.d32 = 0 };
2520 pcgcctl.b.stoppclk = 1;
2521 DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
2525 /** @todo - check how sw can wait for 1 sec to check asesvld??? */
2526 #if 0 //vahrama !!!!!!!!!!!!!!!!!!
2527 if (core_if->adp_enable) {
2528 gotgctl_data_t gotgctl = {.d32 = 0 };
2529 gpwrdn_data_t gpwrdn;
2531 while (gotgctl.b.asesvld == 1) {
2533 DWC_READ_REG32(&core_if->
2539 /* Enable Power Down Logic */
2541 gpwrdn.b.pmuactv = 1;
2542 DWC_MODIFY_REG32(&core_if->core_global_regs->
2543 gpwrdn, 0, gpwrdn.d32);
2545 /* Unmask SRP detected interrupt from Power Down Logic */
2547 gpwrdn.b.srp_det_msk = 1;
2548 DWC_MODIFY_REG32(&core_if->core_global_regs->
2549 gpwrdn, 0, gpwrdn.d32);
2551 dwc_otg_adp_probe_start(core_if);
2555 case UHF_PORT_POWER:
2556 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2557 "SetPortFeature - USB_PORT_FEAT_POWER\n");
2558 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2560 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
2562 case UHF_PORT_RESET:
2563 if ((core_if->power_down == 2)
2564 && (core_if->hibernation_suspend == 1)) {
2565 /* If we are going to exit from Hibernated
2566 * state via USB RESET.
2568 dwc_otg_host_hibernation_restore(core_if, 0, 1);
2570 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2572 DWC_DEBUGPL(DBG_HCD,
2573 "DWC OTG HCD HUB CONTROL - "
2574 "SetPortFeature - USB_PORT_FEAT_RESET\n");
2576 pcgcctl_data_t pcgcctl = {.d32 = 0 };
2577 pcgcctl.b.enbl_sleep_gating = 1;
2578 pcgcctl.b.stoppclk = 1;
2579 DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
2580 DWC_WRITE_REG32(core_if->pcgcctl, 0);
2582 #ifdef CONFIG_USB_DWC_OTG_LPM
2584 glpmcfg_data_t lpmcfg;
2586 DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
2587 if (lpmcfg.b.prt_sleep_sts) {
2588 lpmcfg.b.en_utmi_sleep = 0;
2589 lpmcfg.b.hird_thres &= (~(1 << 4));
2591 (&core_if->core_global_regs->glpmcfg,
2597 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2598 /* Clear suspend bit if resetting from suspended state. */
2599 hprt0.b.prtsusp = 0;
2600 /* When B-Host the Port reset bit is set in
2601 * the Start HCD Callback function, so that
2602 * the reset is started within 1ms of the HNP
2603 * success interrupt. */
2604 if (!dwc_otg_hcd_is_b_host(dwc_otg_hcd)) {
2607 DWC_PRINTF("Indeed it is in host mode hprt0 = %08x\n",hprt0.d32);
2608 DWC_WRITE_REG32(core_if->host_if->hprt0,
2611 /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */
2614 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
2615 core_if->lx_state = DWC_OTG_L0; /* Now back to the on state */
2618 #ifdef DWC_HS_ELECT_TST
2622 gintmsk_data_t gintmsk;
2624 t = (wIndex >> 8); /* MSB wIndex USB */
2625 DWC_DEBUGPL(DBG_HCD,
2626 "DWC OTG HCD HUB CONTROL - "
2627 "SetPortFeature - USB_PORT_FEAT_TEST %d\n",
2629 DWC_WARN("USB_PORT_FEAT_TEST %d\n", t);
2631 hprt0.d32 = dwc_otg_read_hprt0(core_if);
2632 hprt0.b.prttstctl = t;
2633 DWC_WRITE_REG32(core_if->host_if->hprt0,
2636 /* Setup global vars with reg addresses (quick and
2637 * dirty hack, should be cleaned up)
2639 global_regs = core_if->core_global_regs;
2641 core_if->host_if->host_global_regs;
2643 (dwc_otg_hc_regs_t *) ((char *)
2647 (uint32_t *) ((char *)global_regs +
2650 if (t == 6) { /* HS_HOST_PORT_SUSPEND_RESUME */
2651 /* Save current interrupt mask */
2654 (&global_regs->gintmsk);
2656 /* Disable all interrupts while we muck with
2657 * the hardware directly
2659 DWC_WRITE_REG32(&global_regs->gintmsk, 0);
2661 /* 15 second delay per the test spec */
2664 /* Drive suspend on the root port */
2666 dwc_otg_read_hprt0(core_if);
2667 hprt0.b.prtsusp = 1;
2669 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
2671 /* 15 second delay per the test spec */
2674 /* Drive resume on the root port */
2676 dwc_otg_read_hprt0(core_if);
2677 hprt0.b.prtsusp = 0;
2679 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
2682 /* Clear the resume bit */
2684 DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
2686 /* Restore interrupts */
2687 DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);
2688 } else if (t == 7) { /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */
2689 /* Save current interrupt mask */
2692 (&global_regs->gintmsk);
2694 /* Disable all interrupts while we muck with
2695 * the hardware directly
2697 DWC_WRITE_REG32(&global_regs->gintmsk, 0);
2699 /* 15 second delay per the test spec */
2702 /* Send the Setup packet */
2705 /* 15 second delay so nothing else happens for awhile */
2708 /* Restore interrupts */
2709 DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);
2710 } else if (t == 8) { /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */
2711 /* Save current interrupt mask */
2714 (&global_regs->gintmsk);
2716 /* Disable all interrupts while we muck with
2717 * the hardware directly
2719 DWC_WRITE_REG32(&global_regs->gintmsk, 0);
2721 /* Send the Setup packet */
2724 /* 15 second delay so nothing else happens for awhile */
2727 /* Send the In and Ack packets */
2730 /* 15 second delay so nothing else happens for awhile */
2733 /* Restore interrupts */
2734 DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);
2739 #endif /* DWC_HS_ELECT_TST */
2741 case UHF_PORT_INDICATOR:
2742 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
2743 "SetPortFeature - USB_PORT_FEAT_INDICATOR\n");
2747 retval = -DWC_E_INVALID;
2748 DWC_ERROR("DWC OTG HCD - "
2749 "SetPortFeature request %xh "
2750 "unknown or unsupported\n", wValue);
2754 #ifdef CONFIG_USB_DWC_OTG_LPM
2755 case UCR_SET_AND_TEST_PORT_FEATURE:
2756 if (wValue != UHF_PORT_L1) {
2760 int portnum, hird, devaddr, remwake;
2761 glpmcfg_data_t lpmcfg;
2762 uint32_t time_usecs;
2763 gintsts_data_t gintsts;
2764 gintmsk_data_t gintmsk;
2766 if (!dwc_otg_get_param_lpm_enable(core_if)) {
2769 if (wValue != UHF_PORT_L1 || wLength != 1) {
2772 /* Check if the port currently is in SLEEP state */
2774 DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
2775 if (lpmcfg.b.prt_sleep_sts) {
2776 DWC_INFO("Port is already in sleep mode\n");
2777 buf[0] = 0; /* Return success */
2781 portnum = wIndex & 0xf;
2782 hird = (wIndex >> 4) & 0xf;
2783 devaddr = (wIndex >> 8) & 0x7f;
2784 remwake = (wIndex >> 15);
2787 retval = -DWC_E_INVALID;
2789 ("Wrong port number(%d) in SetandTestPortFeature request\n",
2795 ("SetandTestPortFeature request: portnum = %d, hird = %d, devaddr = %d, rewake = %d\n",
2796 portnum, hird, devaddr, remwake);
2797 /* Disable LPM interrupt */
2799 gintmsk.b.lpmtranrcvd = 1;
2800 DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
2803 if (dwc_otg_hcd_send_lpm
2804 (dwc_otg_hcd, devaddr, hird, remwake)) {
2805 retval = -DWC_E_INVALID;
2809 time_usecs = 10 * (lpmcfg.b.retry_count + 1);
2810 /* We will consider timeout if time_usecs microseconds pass,
2811 * and we don't receive LPM transaction status.
2812 * After receiving non-error responce(ACK/NYET/STALL) from device,
2813 * core will set lpmtranrcvd bit.
2817 DWC_READ_REG32(&core_if->core_global_regs->gintsts);
2818 if (gintsts.b.lpmtranrcvd) {
2822 } while (--time_usecs);
2823 /* lpm_int bit will be cleared in LPM interrupt handler */
2830 if (!gintsts.b.lpmtranrcvd) {
2831 buf[0] = 0x3; /* Completion code is Timeout */
2832 dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd);
2835 DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
2836 if (lpmcfg.b.lpm_resp == 0x3) {
2837 /* ACK responce from the device */
2838 buf[0] = 0x00; /* Success */
2839 } else if (lpmcfg.b.lpm_resp == 0x2) {
2840 /* NYET responce from the device */
2843 /* Otherwise responce with Timeout */
2847 DWC_PRINTF("Device responce to LPM trans is %x\n",
2849 DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0,
2854 #endif /* CONFIG_USB_DWC_OTG_LPM */
2857 retval = -DWC_E_INVALID;
2858 DWC_WARN("DWC OTG HCD - "
2859 "Unknown hub control request type or invalid typeReq: %xh wIndex: %xh wValue: %xh\n",
2860 typeReq, wIndex, wValue);
2867 #ifdef CONFIG_USB_DWC_OTG_LPM
2868 /** Returns index of host channel to perform LPM transaction. */
2869 int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd, uint8_t devaddr)
2871 dwc_otg_core_if_t *core_if = hcd->core_if;
2873 hcchar_data_t hcchar;
2874 gintmsk_data_t gintmsk = {.d32 = 0 };
2876 if (DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
2877 DWC_PRINTF("No free channel to select for LPM transaction\n");
2881 hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);
2883 /* Mask host channel interrupts. */
2884 gintmsk.b.hcintr = 1;
2885 DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0);
2887 /* Fill fields that core needs for LPM transaction */
2888 hcchar.b.devaddr = devaddr;
2890 hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
2892 hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW);
2893 hcchar.b.epdir = 0; /* OUT */
2894 DWC_WRITE_REG32(&core_if->host_if->hc_regs[hc->hc_num]->hcchar,
2897 /* Remove the host channel from the free list. */
2898 DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry);
2900 DWC_PRINTF("hcnum = %d devaddr = %d\n", hc->hc_num, devaddr);
2905 /** Release hc after performing LPM transaction */
2906 void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd)
2909 glpmcfg_data_t lpmcfg;
2912 lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg);
2913 hc_num = lpmcfg.b.lpm_chan_index;
2915 hc = hcd->hc_ptr_array[hc_num];
2917 DWC_PRINTF("Freeing channel %d after LPM\n", hc_num);
2918 /* Return host channel to free list */
2919 DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
2922 int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr, uint8_t hird,
2923 uint8_t bRemoteWake)
2925 glpmcfg_data_t lpmcfg;
2926 pcgcctl_data_t pcgcctl = {.d32 = 0 };
2929 channel = dwc_otg_hcd_get_hc_for_lpm_tran(hcd, devaddr);
2934 pcgcctl.b.enbl_sleep_gating = 1;
2935 DWC_MODIFY_REG32(hcd->core_if->pcgcctl, 0, pcgcctl.d32);
2937 /* Read LPM config register */
2938 lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg);
2940 /* Program LPM transaction fields */
2941 lpmcfg.b.rem_wkup_en = bRemoteWake;
2942 lpmcfg.b.hird = hird;
2944 if(dwc_otg_get_param_besl_enable(hcd->core_if)) {
2945 lpmcfg.b.hird_thres = 0x16;
2946 lpmcfg.b.en_besl = 1;
2948 lpmcfg.b.hird_thres = 0x1c;
2951 lpmcfg.b.lpm_chan_index = channel;
2952 lpmcfg.b.en_utmi_sleep = 1;
2953 /* Program LPM config register */
2954 DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);
2956 /* Send LPM transaction */
2957 lpmcfg.b.send_lpm = 1;
2958 DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);
2963 #endif /* CONFIG_USB_DWC_OTG_LPM */
2965 int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port)
2970 return -DWC_E_INVALID;
2973 retval = (hcd->flags.b.port_connect_status_change ||
2974 hcd->flags.b.port_reset_change ||
2975 hcd->flags.b.port_enable_change ||
2976 hcd->flags.b.port_suspend_change ||
2977 hcd->flags.b.port_over_current_change);
2980 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB STATUS DATA:"
2981 " Root port status changed\n");
2982 DWC_DEBUGPL(DBG_HCDV, " port_connect_status_change: %d\n",
2983 hcd->flags.b.port_connect_status_change);
2984 DWC_DEBUGPL(DBG_HCDV, " port_reset_change: %d\n",
2985 hcd->flags.b.port_reset_change);
2986 DWC_DEBUGPL(DBG_HCDV, " port_enable_change: %d\n",
2987 hcd->flags.b.port_enable_change);
2988 DWC_DEBUGPL(DBG_HCDV, " port_suspend_change: %d\n",
2989 hcd->flags.b.port_suspend_change);
2990 DWC_DEBUGPL(DBG_HCDV, " port_over_current_change: %d\n",
2991 hcd->flags.b.port_over_current_change);
2997 int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * dwc_otg_hcd)
3001 DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->host_global_regs->
3005 DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD GET FRAME NUMBER %d\n",
3008 return hfnum.b.frnum;
3011 int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd,
3012 struct dwc_otg_hcd_function_ops *fops)
3017 if (!dwc_otg_is_device_mode(hcd->core_if) &&
3018 (!hcd->core_if->adp_enable || hcd->core_if->adp.adp_started)) {
3019 dwc_otg_hcd_reinit(hcd);
3021 retval = -DWC_E_NO_DEVICE;
3027 void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd)
3032 void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data)
3034 hcd->priv = priv_data;
3037 uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd)
3039 return hcd->otg_port;
3042 uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd)
3045 if (hcd->core_if->op_state == B_HOST) {
3054 dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd,
3055 int iso_desc_count, int atomic_alloc)
3057 dwc_otg_hcd_urb_t *dwc_otg_urb;
3061 sizeof(*dwc_otg_urb) +
3062 iso_desc_count * sizeof(struct dwc_otg_hcd_iso_packet_desc);
3064 dwc_otg_urb = DWC_ALLOC_ATOMIC(size);
3066 dwc_otg_urb = DWC_ALLOC(size);
3068 dwc_otg_urb->packet_count = iso_desc_count;
3073 void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * dwc_otg_urb,
3074 uint8_t dev_addr, uint8_t ep_num,
3075 uint8_t ep_type, uint8_t ep_dir, uint16_t mps)
3077 dwc_otg_hcd_fill_pipe(&dwc_otg_urb->pipe_info, dev_addr, ep_num,
3078 ep_type, ep_dir, mps);
3081 ("addr = %d, ep_num = %d, ep_dir = 0x%x, ep_type = 0x%x, mps = %d\n",
3082 dev_addr, ep_num, ep_dir, ep_type, mps);
3086 void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
3087 void *urb_handle, void *buf, dwc_dma_t dma,
3088 uint32_t buflen, void *setup_packet,
3089 dwc_dma_t setup_dma, uint32_t flags,
3092 dwc_otg_urb->priv = urb_handle;
3093 dwc_otg_urb->buf = buf;
3094 dwc_otg_urb->dma = dma;
3095 dwc_otg_urb->length = buflen;
3096 dwc_otg_urb->setup_packet = setup_packet;
3097 dwc_otg_urb->setup_dma = setup_dma;
3098 dwc_otg_urb->flags = flags;
3099 dwc_otg_urb->interval = interval;
3100 dwc_otg_urb->status = -DWC_E_IN_PROGRESS;
3103 uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb)
3105 return dwc_otg_urb->status;
3108 uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t * dwc_otg_urb)
3110 return dwc_otg_urb->actual_length;
3113 uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t * dwc_otg_urb)
3115 return dwc_otg_urb->error_count;
3118 void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
3119 int desc_num, uint32_t offset,
3122 dwc_otg_urb->iso_descs[desc_num].offset = offset;
3123 dwc_otg_urb->iso_descs[desc_num].length = length;
3126 uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t * dwc_otg_urb,
3129 return dwc_otg_urb->iso_descs[desc_num].status;
3132 uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t *
3133 dwc_otg_urb, int desc_num)
3135 return dwc_otg_urb->iso_descs[desc_num].actual_length;
3138 int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd, void *ep_handle)
3141 dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
3144 if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) {
3151 int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle)
3153 dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
3155 DWC_ASSERT(qh, "qh is not allocated\n");
3157 if (DWC_LIST_EMPTY(&qh->qh_list_entry)) {
3164 uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd, void *ep_handle)
3166 dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
3167 DWC_ASSERT(qh, "qh is not allocated\n");
3171 void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd)
3176 gnptxsts_data_t np_tx_status;
3177 hptxsts_data_t p_tx_status;
3179 num_channels = hcd->core_if->core_params->host_channels;
3182 ("************************************************************\n");
3183 DWC_PRINTF("HCD State:\n");
3184 DWC_PRINTF(" Num channels: %d\n", num_channels);
3185 for (i = 0; i < num_channels; i++) {
3186 dwc_hc_t *hc = hcd->hc_ptr_array[i];
3187 DWC_PRINTF(" Channel %d:\n", i);
3188 DWC_PRINTF(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
3189 hc->dev_addr, hc->ep_num, hc->ep_is_in);
3190 DWC_PRINTF(" speed: %d\n", hc->speed);
3191 DWC_PRINTF(" ep_type: %d\n", hc->ep_type);
3192 DWC_PRINTF(" max_packet: %d\n", hc->max_packet);
3193 DWC_PRINTF(" data_pid_start: %d\n", hc->data_pid_start);
3194 DWC_PRINTF(" multi_count: %d\n", hc->multi_count);
3195 DWC_PRINTF(" xfer_started: %d\n", hc->xfer_started);
3196 DWC_PRINTF(" xfer_buff: %p\n", hc->xfer_buff);
3197 DWC_PRINTF(" xfer_len: %d\n", hc->xfer_len);
3198 DWC_PRINTF(" xfer_count: %d\n", hc->xfer_count);
3199 DWC_PRINTF(" halt_on_queue: %d\n", hc->halt_on_queue);
3200 DWC_PRINTF(" halt_pending: %d\n", hc->halt_pending);
3201 DWC_PRINTF(" halt_status: %d\n", hc->halt_status);
3202 DWC_PRINTF(" do_split: %d\n", hc->do_split);
3203 DWC_PRINTF(" complete_split: %d\n", hc->complete_split);
3204 DWC_PRINTF(" hub_addr: %d\n", hc->hub_addr);
3205 DWC_PRINTF(" port_addr: %d\n", hc->port_addr);
3206 DWC_PRINTF(" xact_pos: %d\n", hc->xact_pos);
3207 DWC_PRINTF(" requests: %d\n", hc->requests);
3208 DWC_PRINTF(" qh: %p\n", hc->qh);
3209 if (hc->xfer_started) {
3211 hcchar_data_t hcchar;
3212 hctsiz_data_t hctsiz;
3214 hcintmsk_data_t hcintmsk;
3216 DWC_READ_REG32(&hcd->core_if->
3217 host_if->host_global_regs->hfnum);
3219 DWC_READ_REG32(&hcd->core_if->host_if->
3220 hc_regs[i]->hcchar);
3222 DWC_READ_REG32(&hcd->core_if->host_if->
3223 hc_regs[i]->hctsiz);
3225 DWC_READ_REG32(&hcd->core_if->host_if->
3228 DWC_READ_REG32(&hcd->core_if->host_if->
3229 hc_regs[i]->hcintmsk);
3230 DWC_PRINTF(" hfnum: 0x%08x\n", hfnum.d32);
3231 DWC_PRINTF(" hcchar: 0x%08x\n", hcchar.d32);
3232 DWC_PRINTF(" hctsiz: 0x%08x\n", hctsiz.d32);
3233 DWC_PRINTF(" hcint: 0x%08x\n", hcint.d32);
3234 DWC_PRINTF(" hcintmsk: 0x%08x\n", hcintmsk.d32);
3236 if (hc->xfer_started && hc->qh) {
3238 dwc_otg_hcd_urb_t *urb;
3240 DWC_CIRCLEQ_FOREACH(qtd, &hc->qh->qtd_list, qtd_list_entry) {
3241 if (!qtd->in_process)
3245 DWC_PRINTF(" URB Info:\n");
3246 DWC_PRINTF(" qtd: %p, urb: %p\n", qtd, urb);
3248 DWC_PRINTF(" Dev: %d, EP: %d %s\n",
3249 dwc_otg_hcd_get_dev_addr(&urb->
3251 dwc_otg_hcd_get_ep_num(&urb->
3253 dwc_otg_hcd_is_pipe_in(&urb->
3256 DWC_PRINTF(" Max packet size: %d\n",
3257 dwc_otg_hcd_get_mps(&urb->
3259 DWC_PRINTF(" transfer_buffer: %p\n",
3261 DWC_PRINTF(" transfer_dma: %p\n",
3263 DWC_PRINTF(" transfer_buffer_length: %d\n",
3265 DWC_PRINTF(" actual_length: %d\n",
3266 urb->actual_length);
3271 DWC_PRINTF(" non_periodic_channels: %d\n", hcd->non_periodic_channels);
3272 DWC_PRINTF(" periodic_channels: %d\n", hcd->periodic_channels);
3273 DWC_PRINTF(" periodic_usecs: %d\n", hcd->periodic_usecs);
3275 DWC_READ_REG32(&hcd->core_if->core_global_regs->gnptxsts);
3276 DWC_PRINTF(" NP Tx Req Queue Space Avail: %d\n",
3277 np_tx_status.b.nptxqspcavail);
3278 DWC_PRINTF(" NP Tx FIFO Space Avail: %d\n",
3279 np_tx_status.b.nptxfspcavail);
3281 DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hptxsts);
3282 DWC_PRINTF(" P Tx Req Queue Space Avail: %d\n",
3283 p_tx_status.b.ptxqspcavail);
3284 DWC_PRINTF(" P Tx FIFO Space Avail: %d\n", p_tx_status.b.ptxfspcavail);
3285 dwc_otg_hcd_dump_frrem(hcd);
3286 dwc_otg_dump_global_registers(hcd->core_if);
3287 dwc_otg_dump_host_registers(hcd->core_if);
3289 ("************************************************************\n");
3295 void dwc_print_setup_data(uint8_t * setup)
3298 if (CHK_DEBUG_LEVEL(DBG_HCD)) {
3299 DWC_PRINTF("Setup Data = MSB ");
3300 for (i = 7; i >= 0; i--)
3301 DWC_PRINTF("%02x ", setup[i]);
3303 DWC_PRINTF(" bmRequestType Tranfer = %s\n",
3304 (setup[0] & 0x80) ? "Device-to-Host" :
3306 DWC_PRINTF(" bmRequestType Type = ");
3307 switch ((setup[0] & 0x60) >> 5) {
3309 DWC_PRINTF("Standard\n");
3312 DWC_PRINTF("Class\n");
3315 DWC_PRINTF("Vendor\n");
3318 DWC_PRINTF("Reserved\n");
3321 DWC_PRINTF(" bmRequestType Recipient = ");
3322 switch (setup[0] & 0x1f) {
3324 DWC_PRINTF("Device\n");
3327 DWC_PRINTF("Interface\n");
3330 DWC_PRINTF("Endpoint\n");
3333 DWC_PRINTF("Other\n");
3336 DWC_PRINTF("Reserved\n");
3339 DWC_PRINTF(" bRequest = 0x%0x\n", setup[1]);
3340 DWC_PRINTF(" wValue = 0x%0x\n", *((uint16_t *) & setup[2]));
3341 DWC_PRINTF(" wIndex = 0x%0x\n", *((uint16_t *) & setup[4]));
3342 DWC_PRINTF(" wLength = 0x%0x\n\n", *((uint16_t *) & setup[6]));
3347 void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd)
3350 DWC_PRINTF("Frame remaining at SOF:\n");
3351 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3352 hcd->frrem_samples, hcd->frrem_accum,
3353 (hcd->frrem_samples > 0) ?
3354 hcd->frrem_accum / hcd->frrem_samples : 0);
3357 DWC_PRINTF("Frame remaining at start_transfer (uframe 7):\n");
3358 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3359 hcd->core_if->hfnum_7_samples,
3360 hcd->core_if->hfnum_7_frrem_accum,
3361 (hcd->core_if->hfnum_7_samples >
3362 0) ? hcd->core_if->hfnum_7_frrem_accum /
3363 hcd->core_if->hfnum_7_samples : 0);
3364 DWC_PRINTF("Frame remaining at start_transfer (uframe 0):\n");
3365 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3366 hcd->core_if->hfnum_0_samples,
3367 hcd->core_if->hfnum_0_frrem_accum,
3368 (hcd->core_if->hfnum_0_samples >
3369 0) ? hcd->core_if->hfnum_0_frrem_accum /
3370 hcd->core_if->hfnum_0_samples : 0);
3371 DWC_PRINTF("Frame remaining at start_transfer (uframe 1-6):\n");
3372 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3373 hcd->core_if->hfnum_other_samples,
3374 hcd->core_if->hfnum_other_frrem_accum,
3375 (hcd->core_if->hfnum_other_samples >
3376 0) ? hcd->core_if->hfnum_other_frrem_accum /
3377 hcd->core_if->hfnum_other_samples : 0);
3380 DWC_PRINTF("Frame remaining at sample point A (uframe 7):\n");
3381 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3382 hcd->hfnum_7_samples_a, hcd->hfnum_7_frrem_accum_a,
3383 (hcd->hfnum_7_samples_a > 0) ?
3384 hcd->hfnum_7_frrem_accum_a / hcd->hfnum_7_samples_a : 0);
3385 DWC_PRINTF("Frame remaining at sample point A (uframe 0):\n");
3386 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3387 hcd->hfnum_0_samples_a, hcd->hfnum_0_frrem_accum_a,
3388 (hcd->hfnum_0_samples_a > 0) ?
3389 hcd->hfnum_0_frrem_accum_a / hcd->hfnum_0_samples_a : 0);
3390 DWC_PRINTF("Frame remaining at sample point A (uframe 1-6):\n");
3391 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3392 hcd->hfnum_other_samples_a, hcd->hfnum_other_frrem_accum_a,
3393 (hcd->hfnum_other_samples_a > 0) ?
3394 hcd->hfnum_other_frrem_accum_a /
3395 hcd->hfnum_other_samples_a : 0);
3398 DWC_PRINTF("Frame remaining at sample point B (uframe 7):\n");
3399 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3400 hcd->hfnum_7_samples_b, hcd->hfnum_7_frrem_accum_b,
3401 (hcd->hfnum_7_samples_b > 0) ?
3402 hcd->hfnum_7_frrem_accum_b / hcd->hfnum_7_samples_b : 0);
3403 DWC_PRINTF("Frame remaining at sample point B (uframe 0):\n");
3404 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3405 hcd->hfnum_0_samples_b, hcd->hfnum_0_frrem_accum_b,
3406 (hcd->hfnum_0_samples_b > 0) ?
3407 hcd->hfnum_0_frrem_accum_b / hcd->hfnum_0_samples_b : 0);
3408 DWC_PRINTF("Frame remaining at sample point B (uframe 1-6):\n");
3409 DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
3410 hcd->hfnum_other_samples_b, hcd->hfnum_other_frrem_accum_b,
3411 (hcd->hfnum_other_samples_b > 0) ?
3412 hcd->hfnum_other_frrem_accum_b /
3413 hcd->hfnum_other_samples_b : 0);
3417 #endif /* DWC_DEVICE_ONLY */