1 /*****************************************************************************
2 ** FILE NAME : ifxhcd.c
3 ** PROJECT : IFX USB sub-system V3
4 ** MODULES : IFX USB sub-system Host and Device driver
7 ** AUTHOR : Chen, Howard
8 ** DESCRIPTION : This file contains the structures, constants, and
9 ** interfaces for the Host Contoller Driver (HCD).
11 ** The Host Controller Driver (HCD) is responsible for
12 ** translating requests from the USB Driver into the
13 ** appropriate actions on the IFXUSB controller.
14 ** It isolates the USBD from the specifics of the
15 ** controller by providing an API to the USBD.
18 ** REFERENCE : Synopsys DWC-OTG Driver 2.7
19 ** COPYRIGHT : Copyright (c) 2010
20 ** LANTIQ DEUTSCHLAND GMBH,
21 ** Am Campeon 3, 85579 Neubiberg, Germany
23 ** This program is free software; you can redistribute it and/or modify
24 ** it under the terms of the GNU General Public License as published by
25 ** the Free Software Foundation; either version 2 of the License, or
26 ** (at your option) any later version.
28 ** Version Control Section **
32 ** $Log$ Revision history
33 *****************************************************************************/
36 * This file contains code fragments from Synopsys HS OTG Linux Software Driver.
37 * For this code the following notice is applicable:
39 * ==========================================================================
41 * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
42 * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
43 * otherwise expressly agreed to in writing between Synopsys and you.
45 * The Software IS NOT an item of Licensed Software or Licensed Product under
46 * any End User Software License Agreement or Agreement for Licensed Product
47 * with Synopsys or any supplement thereto. You are permitted to use and
48 * redistribute this Software in source and binary forms, with or without
49 * modification, provided that redistributions of source code must retain this
50 * notice. You may not view, use, disclose, copy or distribute this file or
51 * any information contained herein except pursuant to this license grant from
52 * Synopsys. If you do not agree with this notice, including the disclaimer
53 * below, then you are not authorized to use the Software.
55 * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
56 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
57 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
58 * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
59 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
60 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
61 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
62 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
63 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
64 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
66 * ========================================================================== */
70 \ingroup IFXUSB_DRIVER_V3
71 \brief This file contains the implementation of the HCD. In Linux,
72 the HCD implements the hc_driver API.
75 #include <linux/version.h>
76 #include "ifxusb_version.h"
78 #include <linux/kernel.h>
79 #include <linux/module.h>
80 #include <linux/moduleparam.h>
81 #include <linux/init.h>
83 #include <linux/device.h>
85 #include <linux/errno.h>
86 #include <linux/list.h>
87 #include <linux/interrupt.h>
88 #include <linux/string.h>
90 #include <linux/dma-mapping.h>
93 #include "ifxusb_plat.h"
94 #include "ifxusb_regs.h"
95 #include "ifxusb_cif.h"
101 static void dump_urb_info(struct urb *_urb, char* _fn_name);
103 static void dump_channel_info(ifxhcd_hcd_t *_ifxhcd,
104 ifxhcd_epqh_t *_epqh);
108 static void ifxhcd_complete_urb_sub(ifxhcd_urbd_t *_urbd)
110 ifxhcd_hcd_t *ifxhcd;
111 struct urb *urb=NULL;
113 if (!list_empty(&_urbd->ql))
115 list_del_init(&_urbd->ql);
116 _urbd->epqh->urbd_count--;
119 IFX_ERROR("%s: urb(%p) not connect to any epqh\n",
122 ifxhcd=_urbd->epqh->ifxhcd;
125 IFX_ERROR("%s: invalid urb\n",__func__);
128 if(urb->hcpriv != _urbd)
129 IFX_ERROR("%s: invalid"
130 " urb(%p)->hcpriv(%p) != _urbd(%p)\n",
135 #if defined(__UNALIGNED_BUF_ADJ__)
137 // _urbd->using_aligned_buf &&
139 memcpy(_urbd->xfer_buff,
142 if(_urbd->aligned_buf)
143 ifxusb_free_buf_h(_urbd->aligned_buf);
146 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
147 urb->status=_urbd->status;
148 usb_hcd_giveback_urb(ifxhcd_to_syshcd(ifxhcd), urb);
150 usb_hcd_giveback_urb(ifxhcd_to_syshcd(ifxhcd), urb,
157 #ifdef __STRICT_ORDER__
158 static void ifxhcd_complete_urb_func(unsigned long data)
163 struct list_head *item;
167 epqh=((ifxhcd_epqh_t *)data);
169 while (!list_empty(&epqh->release_list) && count)
171 item = epqh->release_list.next;
172 urbd = list_entry(item, ifxhcd_urbd_t, ql);
174 IFX_ERROR("%s: invalid urbd\n",__func__);
175 else if (!urbd->epqh)
176 IFX_ERROR("%s: invalid epqd\n",__func__);
179 ifxhcd_epqh_t *epqh2;
181 local_irq_save(flags);
182 LOCK_URBD_LIST(epqh2);
183 ifxhcd_complete_urb_sub(urbd);
184 UNLOCK_URBD_LIST(epqh2);
185 local_irq_restore (flags);
189 if(!list_empty(&epqh->release_list))
190 tasklet_schedule(&epqh->complete_urb_sub);
194 \brief Sets the final status of an URB and returns it to the device
195 driver. Any required cleanup of the URB is performed.
197 void ifxhcd_complete_urb(ifxhcd_hcd_t *_ifxhcd,
198 ifxhcd_urbd_t *_urbd,
205 IFX_ERROR("%s: invalid urbd\n",__func__);
210 IFX_ERROR("%s: invalid epqh\n",__func__);
214 local_irq_save(flags);
215 LOCK_URBD_LIST(_urbd->epqh);
217 if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB))
219 IFX_PRINT("%s: ehqh %p _urbd %p, urb %p,"
220 " device %d, ep %d %s/%s, status=%d\n",
221 __func__,_urbd->epqh,
223 (_urbd->urb)?usb_pipedevice(_urbd->urb->pipe):-1,
224 (_urbd->urb)?usb_pipeendpoint(_urbd->urb->pipe):-1,
225 (_urbd->urb)?(usb_pipein(_urbd->urb->pipe) ? "IN" : "OUT"):"--",
226 (_urbd->is_in) ? "IN" : "OUT",
228 if ((_urbd->urb)&& _urbd->epqh->ep_type == IFXUSB_EP_TYPE_ISOC)
231 for (i = 0; i < _urbd->urb->number_of_packets; i++)
232 IFX_PRINT(" ISO Desc %d status: %d\n", i, _urbd->urb->iso_frame_desc[i].status);
236 _urbd->status = _status;
238 if(_urbd->phase!=URBD_FINISHING)
240 if(_urbd->phase!=URBD_DEQUEUEING && _urbd->phase!=URBD_COMPLETING)
241 printk(KERN_INFO "Warning: %s() Strange URBD PHASE %d\n",__func__,_urbd->phase);
244 if( _urbd->status == 0
245 && _urbd->phase==URBD_COMPLETING
248 list_move_tail(&_urbd->ql,&_urbd->epqh->release_list);
249 if(!_urbd->epqh->complete_urb_sub.func)
251 _urbd->epqh->complete_urb_sub.next = NULL;
252 _urbd->epqh->complete_urb_sub.state = 0;
253 atomic_set( &_urbd->epqh->complete_urb_sub.count, 0);
254 _urbd->epqh->complete_urb_sub.func = ifxhcd_complete_urb_func;
255 _urbd->epqh->complete_urb_sub.data = (unsigned long)_urbd->epqh;
257 tasklet_schedule(&_urbd->epqh->complete_urb_sub);
261 _urbd->phase=URBD_FINISHING;
262 ifxhcd_complete_urb_sub(_urbd);
264 UNLOCK_URBD_LIST(_urbd->epqh);
268 UNLOCK_URBD_LIST(_urbd->epqh);
274 printk(KERN_INFO "Warning: %s() Double Completing \n",__func__);
275 UNLOCK_URBD_LIST(_urbd->epqh);
278 local_irq_restore (flags);
281 static void ifxhcd_complete_urb_func(unsigned long data)
286 urbd=((ifxhcd_urbd_t *)data);
288 // local_irq_save(flags);
290 IFX_ERROR("%s: invalid urbd\n",__func__);
291 else if (!urbd->epqh)
292 IFX_ERROR("%s: invalid epqd\n",__func__);
295 local_irq_save(flags);
296 LOCK_URBD_LIST(urbd->epqh);
297 ifxhcd_complete_urb_sub(urbd);
298 UNLOCK_URBD_LIST(urbd->epqh);
299 local_irq_restore (flags);
301 // local_irq_restore (flags);
306 \brief Sets the final status of an URB and returns it to the device driver. Any
307 required cleanup of the URB is performed.
309 void ifxhcd_complete_urb(ifxhcd_hcd_t *_ifxhcd, ifxhcd_urbd_t *_urbd, int _status)
315 IFX_ERROR("%s: invalid urbd\n",__func__);
320 IFX_ERROR("%s: invalid epqh\n",__func__);
324 local_irq_save(flags);
325 LOCK_URBD_LIST(_urbd->epqh);
327 if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB))
329 IFX_PRINT("%s: ehqh %p _urbd %p, urb %p, device %d, ep %d %s/%s, status=%d\n",
330 __func__,_urbd->epqh, _urbd,_urbd->urb,
331 (_urbd->urb)?usb_pipedevice(_urbd->urb->pipe):-1,
332 (_urbd->urb)?usb_pipeendpoint(_urbd->urb->pipe):-1,
333 (_urbd->urb)?(usb_pipein(_urbd->urb->pipe) ? "IN" : "OUT"):"--",
334 (_urbd->is_in) ? "IN" : "OUT",
336 if ((_urbd->urb)&& _urbd->epqh->ep_type == IFXUSB_EP_TYPE_ISOC)
339 for (i = 0; i < _urbd->urb->number_of_packets; i++)
340 IFX_PRINT(" ISO Desc %d status: %d\n", i, _urbd->urb->iso_frame_desc[i].status);
344 _urbd->status = _status;
346 if(_urbd->phase!=URBD_FINISHING)
348 if(_urbd->phase!=URBD_DEQUEUEING && _urbd->phase!=URBD_COMPLETING)
349 printk(KERN_INFO "Warning: %s() Strange URBD PHASE %d\n",__func__,_urbd->phase);
352 if( _urbd->status == 0
353 && _urbd->phase==URBD_COMPLETING
356 if(_urbd->complete_urb_sub.func)
357 printk(KERN_INFO "Warning: %s() URBD Tasklet is on already\n",__func__);
358 _urbd->phase=URBD_FINISHING;
359 _urbd->complete_urb_sub.next = NULL;
360 _urbd->complete_urb_sub.state = 0;
361 atomic_set( &_urbd->complete_urb_sub.count, 0);
362 _urbd->complete_urb_sub.func = ifxhcd_complete_urb_func;
363 _urbd->complete_urb_sub.data = (unsigned long)_urbd;
364 tasklet_schedule(&_urbd->complete_urb_sub);
368 _urbd->phase=URBD_FINISHING;
369 ifxhcd_complete_urb_sub(_urbd);
376 printk(KERN_INFO "Warning: %s() Double Completing \n",__func__);
377 UNLOCK_URBD_LIST(_urbd->epqh);
378 local_irq_restore (flags);
383 \brief Processes all the URBs in a single EPQHs. Completes them with
384 status and frees the URBD.
387 void kill_all_urbs_in_epqh(ifxhcd_hcd_t *_ifxhcd, ifxhcd_epqh_t *_epqh, int _status)
389 struct list_head *item;
390 struct list_head *next;
396 IFX_DEBUGPL(DBG_HCDV, "%s %p\n",__func__,_epqh);
397 LOCK_URBD_LIST(_epqh);
398 list_for_each(item, &_epqh->urbd_list)
400 urbd = list_entry(item, ifxhcd_urbd_t, ql);
401 if( urbd->phase==URBD_IDLE
402 || urbd->phase==URBD_ACTIVE
403 // || urbd->phase==URBD_STARTING
405 urbd->phase=URBD_DEQUEUEING;
407 list_for_each_safe(item, next, &_epqh->urbd_list)
409 urbd = list_entry(item, ifxhcd_urbd_t, ql);
410 if(urbd->phase==URBD_DEQUEUEING)
412 urbd->urb->status = _status;
413 urbd->phase = URBD_FINISHING;
414 ifxhcd_complete_urb_sub(urbd);
416 else if( urbd->phase==URBD_STARTED
417 || urbd->phase==URBD_STARTING
418 // || urbd->phase==URBD_ACTIVE
421 if(ifxhcd_hc_halt(&_ifxhcd->core_if, _epqh->hc, HC_XFER_URB_DEQUEUE))
423 urbd->urb->status = _status;
424 urbd->phase=URBD_FINISHING;
425 ifxhcd_complete_urb_sub(urbd);
429 IFX_ERROR("%s: invalid urb phase:%d \n",__func__,urbd->phase);
431 UNLOCK_URBD_LIST(_epqh);
432 IFX_DEBUGPL(DBG_HCDV, "%s %p finish\n",__func__,_epqh);
437 \brief Free all EPS in one Processes all the URBs in a single list of EPQHs. Completes them with
438 -ETIMEDOUT and frees the URBD.
441 void epqh_list_free_1(ifxhcd_hcd_t *_ifxhcd, struct list_head *_epqh_list)
444 struct list_head *item;
450 IFX_DEBUGPL(DBG_HCDV, "%s %p\n",__func__,_epqh_list);
452 item = _epqh_list->next;
453 while(item != _epqh_list && item != item->next)
455 epqh = list_entry(item, ifxhcd_epqh_t, ql);
456 epqh->phase=EPQH_DISABLING;
458 kill_all_urbs_in_epqh(_ifxhcd, epqh, -ETIMEDOUT);
459 #ifdef __STRICT_ORDER__
460 if(list_empty(&epqh->urbd_list) && list_empty(&epqh->release_list))
462 if(list_empty(&epqh->urbd_list))
464 ifxhcd_epqh_free(epqh);
466 IFX_DEBUGPL(DBG_HCDV, "%s %p finish\n",__func__,_epqh_list);
467 /* Ensure there are no URBDs or URBs left. */
471 void epqh_list_free_2(ifxhcd_hcd_t *_ifxhcd, struct list_head *_epqh_list)
474 struct list_head *item;
475 struct list_head *next;
481 IFX_DEBUGPL(DBG_HCDV, "%s %p\n",__func__,_epqh_list);
482 list_for_each_safe(item, next, _epqh_list)
484 epqh = list_entry(item, ifxhcd_epqh_t, ql);
485 if(item == item->next)
487 ifxhcd_epqh_free(epqh);
491 uint32_t count=0x80000;
492 #ifdef __STRICT_ORDER__
493 for(;(!list_empty(&epqh->urbd_list) || !list_empty(&epqh->release_list))&& count> 0; count--) udelay(1);
495 for(;!list_empty(&epqh->urbd_list) && count> 0; count--) udelay(1);
498 IFX_ERROR("%s: unable to clear urbd in epqh \n",__func__);
499 ifxhcd_epqh_free(epqh);
502 IFX_DEBUGPL(DBG_HCDV, "%s %p finish\n",__func__,_epqh_list);
503 /* Ensure there are no URBDs or URBs left. */
507 void epqh_list_free_all_sub(unsigned long data)
509 ifxhcd_hcd_t *ifxhcd;
511 ifxhcd=(ifxhcd_hcd_t *)data;
512 epqh_list_free_1(ifxhcd, &ifxhcd->epqh_list_np );
513 epqh_list_free_1(ifxhcd, &ifxhcd->epqh_list_intr);
515 epqh_list_free_1(ifxhcd, &ifxhcd->epqh_list_isoc);
518 epqh_list_free_2(ifxhcd, &ifxhcd->epqh_list_np );
519 epqh_list_free_2(ifxhcd, &ifxhcd->epqh_list_intr);
521 epqh_list_free_2(ifxhcd, &ifxhcd->epqh_list_isoc);
526 void epqh_list_free_all(ifxhcd_hcd_t *_ifxhcd)
528 _ifxhcd->tasklet_free_epqh_list.next = NULL;
529 _ifxhcd->tasklet_free_epqh_list.state = 0;
530 atomic_set( &_ifxhcd->tasklet_free_epqh_list.count, 0);
531 _ifxhcd->tasklet_free_epqh_list.func=epqh_list_free_all_sub;
532 _ifxhcd->tasklet_free_epqh_list.data = (unsigned long)_ifxhcd;
533 tasklet_schedule(&_ifxhcd->tasklet_free_epqh_list);
538 \brief This function is called to handle the disconnection of host port.
540 int32_t ifxhcd_disconnect(ifxhcd_hcd_t *_ifxhcd)
542 IFX_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, _ifxhcd);
544 _ifxhcd->disconnecting=1;
545 /* Set status flags for the hub driver. */
546 _ifxhcd->flags.b.port_connect_status_change = 1;
547 _ifxhcd->flags.b.port_connect_status = 0;
550 * Shutdown any transfers in process by clearing the Tx FIFO Empty
551 * interrupt mask and status bits and disabling subsequent host
552 * channel interrupts.
555 gint_data_t intr = { .d32 = 0 };
556 intr.b.nptxfempty = 1;
557 intr.b.ptxfempty = 1;
559 ifxusb_mreg (&_ifxhcd->core_if.core_global_regs->gintmsk, intr.d32, 0);
560 ifxusb_mreg (&_ifxhcd->core_if.core_global_regs->gintsts, intr.d32, 0);
563 /* Respond with an error status to all URBs in the schedule. */
564 epqh_list_free_all(_ifxhcd);
566 /* Clean up any host channels that were in use. */
569 ifxhcd_hc_t *channel;
570 ifxusb_hc_regs_t *hc_regs;
571 hcchar_data_t hcchar;
574 num_channels = _ifxhcd->core_if.params.host_channels;
576 for (i = 0; i < num_channels; i++)
578 channel = &_ifxhcd->ifxhc[i];
579 hc_regs = _ifxhcd->core_if.hc_regs[i];
580 hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
582 printk(KERN_INFO "Warning: %s() HC still enabled\n",__func__);
583 ifxhcd_hc_cleanup(&_ifxhcd->core_if, channel);
586 IFX_DEBUGPL(DBG_HCDV, "%s(%p) finish\n", __func__, _ifxhcd);
592 \brief Frees secondary storage associated with the ifxhcd_hcd structure contained
593 in the struct usb_hcd field.
595 static void ifxhcd_freeextra(struct usb_hcd *_syshcd)
597 ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd(_syshcd);
599 IFX_DEBUGPL(DBG_HCD, "IFXUSB HCD FREE\n");
601 /* Free memory for EPQH/URBD lists */
602 epqh_list_free_all(ifxhcd);
604 /* Free memory for the host channels. */
605 ifxusb_free_buf_h(ifxhcd->status_buf);
610 \brief Initializes the HCD. This function allocates memory for and initializes the
611 static parts of the usb_hcd and ifxhcd_hcd structures. It also registers the
612 USB bus with the core and calls the hc_driver->start() function. It returns
613 a negative error on failure.
615 int ifxhcd_init(ifxhcd_hcd_t *_ifxhcd)
618 struct usb_hcd *syshcd = NULL;
620 IFX_DEBUGPL(DBG_HCD, "IFX USB HCD INIT\n");
622 INIT_EPQH_LIST_ALL(_ifxhcd);
623 INIT_EPQH_LIST(_ifxhcd);
625 init_timer(&_ifxhcd->autoprobe_timer);
626 init_timer(&_ifxhcd->host_probe_timer);
627 _ifxhcd->probe_sec = 5;
628 _ifxhcd->autoprobe_sec = 30;
630 _ifxhcd->hc_driver.description = _ifxhcd->core_if.core_name;
631 _ifxhcd->hc_driver.product_desc = "IFX USB Controller";
632 //_ifxhcd->hc_driver.hcd_priv_size = sizeof(ifxhcd_hcd_t);
633 _ifxhcd->hc_driver.hcd_priv_size = sizeof(unsigned long);
634 _ifxhcd->hc_driver.irq = ifxhcd_irq;
635 _ifxhcd->hc_driver.flags = HCD_MEMORY | HCD_USB2;
636 _ifxhcd->hc_driver.start = ifxhcd_start;
637 _ifxhcd->hc_driver.stop = ifxhcd_stop;
638 //_ifxhcd->hc_driver.reset =
639 //_ifxhcd->hc_driver.suspend =
640 //_ifxhcd->hc_driver.resume =
641 _ifxhcd->hc_driver.urb_enqueue = ifxhcd_urb_enqueue;
642 _ifxhcd->hc_driver.urb_dequeue = ifxhcd_urb_dequeue;
643 _ifxhcd->hc_driver.endpoint_disable = ifxhcd_endpoint_disable;
644 _ifxhcd->hc_driver.get_frame_number = ifxhcd_get_frame_number;
645 _ifxhcd->hc_driver.hub_status_data = ifxhcd_hub_status_data;
646 _ifxhcd->hc_driver.hub_control = ifxhcd_hub_control;
647 //_ifxhcd->hc_driver.hub_suspend =
648 //_ifxhcd->hc_driver.hub_resume =
649 _ifxhcd->pkt_remaining_reload_hs=PKT_REMAINING_RELOAD_HS;
650 _ifxhcd->pkt_remaining_reload_fs=PKT_REMAINING_RELOAD_FS;
651 _ifxhcd->pkt_remaining_reload_ls=PKT_REMAINING_RELOAD_LS;
652 _ifxhcd->pkt_count_limit_bo =8;
653 _ifxhcd->pkt_count_limit_bi =8;
655 /* Allocate memory for and initialize the base HCD and */
656 //syshcd = usb_create_hcd(&_ifxhcd->hc_driver, _ifxhcd->dev, _ifxhcd->dev->bus_id);
657 syshcd = usb_create_hcd(&_ifxhcd->hc_driver, _ifxhcd->dev, _ifxhcd->core_if.core_name);
665 syshcd->rsrc_start = (unsigned long)_ifxhcd->core_if.core_global_regs;
666 syshcd->regs = (void *)_ifxhcd->core_if.core_global_regs;
667 syshcd->self.otg_port = 0;
669 //*((unsigned long *)(&(syshcd->hcd_priv)))=(unsigned long)_ifxhcd;
670 //*((unsigned long *)(&(syshcd->hcd_priv[0])))=(unsigned long)_ifxhcd;
671 syshcd->hcd_priv[0]=(unsigned long)_ifxhcd;
672 _ifxhcd->syshcd=syshcd;
673 INIT_LIST_HEAD(&_ifxhcd->epqh_list_all );
674 INIT_LIST_HEAD(&_ifxhcd->epqh_list_np );
675 INIT_LIST_HEAD(&_ifxhcd->epqh_list_intr );
677 INIT_LIST_HEAD(&_ifxhcd->epqh_list_isoc);
681 * Create a host channel descriptor for each host channel implemented
682 * in the controller. Initialize the channel descriptor array.
685 int num_channels = _ifxhcd->core_if.params.host_channels;
687 for (i = 0; i < num_channels; i++)
689 _ifxhcd->ifxhc[i].hc_num = i;
690 IFX_DEBUGPL(DBG_HCDV, "HCD Added channel #%d\n", i);
694 /* Set device flags indicating whether the HCD supports DMA. */
695 if(_ifxhcd->dev->dma_mask)
696 *(_ifxhcd->dev->dma_mask) = ~0;
697 _ifxhcd->dev->coherent_dma_mask = ~0;
700 * Finish generic HCD initialization and start the HCD. This function
701 * allocates the DMA buffer pool, registers the USB bus, requests the
702 * IRQ line, and calls ifxusb_hcd_start method.
704 retval = usb_add_hcd(syshcd, _ifxhcd->core_if.irq, 0
712 * Allocate space for storing data on status transactions. Normally no
713 * data is sent, but this space acts as a bit bucket. This must be
714 * done after usb_add_hcd since that function allocates the DMA buffer
717 _ifxhcd->status_buf = ifxusb_alloc_buf_h(IFXHCD_STATUS_BUF_SIZE, 1);
719 if (_ifxhcd->status_buf)
721 IFX_DEBUGPL(DBG_HCD, "IFX USB HCD Initialized, bus=%s, usbbus=%d\n", _ifxhcd->core_if.core_name, syshcd->self.busnum);
724 IFX_ERROR("%s: status_buf allocation failed\n", __func__);
726 /* Error conditions */
727 usb_remove_hcd(syshcd);
729 ifxhcd_freeextra(syshcd);
736 \brief Removes the HCD.
737 Frees memory and resources associated with the HCD and deregisters the bus.
739 void ifxhcd_remove(ifxhcd_hcd_t *_ifxhcd)
741 struct usb_hcd *syshcd = ifxhcd_to_syshcd(_ifxhcd);
743 IFX_DEBUGPL(DBG_HCD, "IFX USB HCD REMOVE\n");
745 /* Turn off all interrupts */
746 ifxusb_wreg (&_ifxhcd->core_if.core_global_regs->gintmsk, 0);
747 ifxusb_mreg (&_ifxhcd->core_if.core_global_regs->gahbcfg, 1, 0);
749 usb_remove_hcd(syshcd);
750 ifxhcd_freeextra(syshcd);
757 /* =========================================================================
758 * Linux HC Driver Functions
759 * ========================================================================= */
762 \brief Initializes the IFXUSB controller and its root hub and prepares it for host
763 mode operation. Activates the root port. Returns 0 on success and a negative
764 error code on failure.
767 int ifxhcd_start(struct usb_hcd *_syshcd)
769 ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd (_syshcd);
770 ifxusb_core_if_t *core_if = &ifxhcd->core_if;
773 IFX_DEBUGPL(DBG_HCD, "IFX USB HCD START\n");
775 bus = hcd_to_bus(_syshcd);
777 /* Initialize the bus state. */
778 _syshcd->state = HC_STATE_RUNNING;
780 /* Initialize and connect root hub if one is not already attached */
783 IFX_DEBUGPL(DBG_HCD, "IFX USB HCD Has Root Hub\n");
784 /* Inform the HUB driver to resume. */
785 usb_hcd_resume_root_hub(_syshcd);
788 ifxhcd->flags.d32 = 0;
790 /* Put all channels in the free channel list and clean up channel states.*/
792 int num_channels = ifxhcd->core_if.params.host_channels;
794 for (i = 0; i < num_channels; i++)
796 ifxhcd_hc_t *channel;
797 channel = &ifxhcd->ifxhc[i];
798 ifxhcd_hc_cleanup(&ifxhcd->core_if, channel);
801 /* Initialize the USB core for host mode operation. */
803 ifxusb_host_enable_interrupts(core_if);
804 ifxusb_enable_global_interrupts_h(core_if);
805 ifxusb_phy_power_on_h (core_if);
807 ifxusb_vbus_init(core_if);
809 /* Turn on the vbus power. */
812 hprt0.d32 = ifxusb_read_hprt0(core_if);
814 IFX_PRINT("Init: Power Port (%d)\n", hprt0.b.prtpwr);
815 if (hprt0.b.prtpwr == 0 )
818 ifxusb_wreg(core_if->hprt0, hprt0.d32);
819 ifxusb_vbus_on(core_if);
826 \brief Halts the IFXUSB host mode operations in a clean manner. USB transfers are
829 #if defined(__IS_AR10__)
830 void ifxusb_oc_int_free(int port);
832 void ifxusb_oc_int_free(void);
835 void ifxhcd_stop(struct usb_hcd *_syshcd)
837 ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd(_syshcd);
838 hprt0_data_t hprt0 = { .d32=0 };
840 IFX_DEBUGPL(DBG_HCD, "IFX USB HCD STOP\n");
842 /* Turn off all interrupts. */
843 ifxusb_disable_global_interrupts_h(&ifxhcd->core_if );
844 ifxusb_host_disable_interrupts(&ifxhcd->core_if );
847 * The root hub should be disconnected before this function is called.
848 * The disconnect will clear the URBD lists (via ..._hcd_urb_dequeue)
849 * and the EPQH lists (via ..._hcd_endpoint_disable).
852 /* Turn off the vbus power */
853 IFX_PRINT("PortPower off\n");
855 ifxusb_vbus_off(&ifxhcd->core_if );
858 #if defined(__IS_AR10__)
859 ifxusb_oc_int_free(ifxhcd->core_if.core_no);
861 ifxusb_oc_int_free();
865 ifxusb_vbus_free(&ifxhcd->core_if );
867 ifxusb_wreg(ifxhcd->core_if.hprt0, hprt0.d32);
872 \brief Returns the current frame number
874 int ifxhcd_get_frame_number(struct usb_hcd *_syshcd)
876 ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd(_syshcd);
879 hfnum.d32 = ifxusb_rreg(&ifxhcd->core_if.host_global_regs->hfnum);
881 return hfnum.b.frnum;
885 \brief Starts processing a USB transfer request specified by a USB Request Block
886 (URB). mem_flags indicates the type of memory allocation to use while
889 int ifxhcd_urb_enqueue( struct usb_hcd *_syshcd,
890 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
891 struct usb_host_endpoint *_sysep,
896 ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd (_syshcd);
897 ifxhcd_epqh_t *epqh = NULL;
900 if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB))
901 dump_urb_info(_urb, "ifxusb_hcd_urb_enqueue");
904 if (!ifxhcd->flags.b.port_connect_status) /* No longer connected. */
907 #if !defined(__EN_ISOC__)
908 if(usb_pipetype(_urb->pipe) == PIPE_ISOCHRONOUS)
910 IFX_ERROR("ISOC transfer not supported!!!\n");
917 IFX_WARN("%s() Previous urb->hcpriv exist %p\n",__func__,_urb->hcpriv);
923 epqh=ifxhcd_urbd_create (ifxhcd,_urb);
926 IFX_ERROR("IFXUSB HCD URB Enqueue failed creating URBD\n");
929 if(epqh->phase==EPQH_DISABLING )
931 IFX_ERROR("Enqueue to a DISABLING EP!!!\n");
935 #ifdef __DYN_SOF_INTR__
936 ifxhcd->dyn_sof_count = DYN_SOF_COUNT_DEF;
938 //enable_sof(ifxhcd);
942 gintsts.b.sofintr = 1;
943 ifxusb_mreg(&ifxhcd->core_if.core_global_regs->gintmsk, 0,gintsts.d32);
946 if(epqh->phase==EPQH_IDLE || epqh->phase==EPQH_STDBY )
948 epqh->phase=EPQH_READY;
949 #ifdef __EPQD_DESTROY_TIMEOUT__
950 del_timer(&epqh->destroy_timer);
958 \brief Aborts/cancels a USB transfer request. Always returns 0 to indicate
961 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
962 int ifxhcd_urb_dequeue(struct usb_hcd *_syshcd, struct urb *_urb)
964 int ifxhcd_urb_dequeue(struct usb_hcd *_syshcd, struct urb *_urb, int status)
967 ifxhcd_hcd_t *ifxhcd;
968 struct usb_host_endpoint *sysep;
972 IFX_DEBUGPL(DBG_HCD, "IFXUSB HCD URB Dequeue\n");
973 #if !defined(__EN_ISOC__)
974 if(usb_pipetype(_urb->pipe) == PIPE_ISOCHRONOUS)
978 ifxhcd = syshcd_to_ifxhcd(_syshcd);
980 urbd = (ifxhcd_urbd_t *) _urb->hcpriv;
983 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
984 _urb->status=-ETIMEDOUT;
985 usb_hcd_giveback_urb(_syshcd, _urb);
987 // usb_hcd_giveback_urb(_syshcd, _urb,-ETIMEDOUT);
988 usb_hcd_giveback_urb(_syshcd, _urb,status);
993 sysep = ifxhcd_urb_to_endpoint(_urb);
996 LOCK_EPQH_LIST_ALL(ifxhcd);
997 epqh = sysep_to_epqh(ifxhcd,sysep);
998 UNLOCK_EPQH_LIST_ALL(ifxhcd);
1000 IFX_ERROR("%s inconsistant epqh %p %p\n",__func__,epqh,urbd->epqh);
1003 epqh = (ifxhcd_epqh_t *) urbd->epqh;
1004 if(!ifxhcd->flags.b.port_connect_status || !epqh)
1006 urbd->phase=URBD_DEQUEUEING;
1007 ifxhcd_complete_urb(ifxhcd, urbd, -ENODEV);
1011 LOCK_URBD_LIST(epqh);
1012 if( urbd->phase==URBD_IDLE
1013 || urbd->phase==URBD_ACTIVE
1014 // || urbd->phase==URBD_STARTING
1017 urbd->phase=URBD_DEQUEUEING;
1018 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
1019 ifxhcd_complete_urb(ifxhcd, urbd, -ETIMEDOUT);
1021 ifxhcd_complete_urb(ifxhcd, urbd, status);
1024 else if( urbd->phase==URBD_STARTED
1025 || urbd->phase==URBD_STARTING
1026 // || urbd->phase==URBD_ACTIVE
1029 if(ifxhcd_hc_halt(&ifxhcd->core_if, epqh->hc, HC_XFER_URB_DEQUEUE))
1031 urbd->phase=URBD_DEQUEUEING;
1032 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
1033 ifxhcd_complete_urb(ifxhcd, urbd, -ETIMEDOUT);
1035 ifxhcd_complete_urb(ifxhcd, urbd, status);
1037 ifxhcd_epqh_idle(epqh);
1040 UNLOCK_URBD_LIST(epqh);
1047 \brief Frees resources in the IFXUSB controller related to a given endpoint. Also
1048 clears state in the HCD related to the endpoint. Any URBs for the endpoint
1049 must already be dequeued.
1051 void ifxhcd_endpoint_disable( struct usb_hcd *_syshcd,
1052 struct usb_host_endpoint *_sysep)
1054 ifxhcd_hcd_t *ifxhcd;
1055 ifxhcd_epqh_t *epqh;
1057 IFX_DEBUGPL(DBG_HCD, "IFXUSB HCD EP DISABLE: _bEndpointAddress=0x%02x, "
1058 "endpoint=%d\n", _sysep->desc.bEndpointAddress,
1059 ifxhcd_ep_addr_to_endpoint(_sysep->desc.bEndpointAddress));
1061 ifxhcd = syshcd_to_ifxhcd(_syshcd);
1063 LOCK_EPQH_LIST_ALL(ifxhcd);
1064 epqh = sysep_to_epqh(ifxhcd,_sysep);
1065 UNLOCK_EPQH_LIST_ALL(ifxhcd);
1073 if (epqh->sysep!=_sysep)
1075 IFX_ERROR("%s inconsistant sysep %p %p %p\n",__func__,epqh,epqh->sysep,_sysep);
1079 epqh->phase=EPQH_DISABLING;
1080 kill_all_urbs_in_epqh(ifxhcd, epqh, -ETIMEDOUT);
1082 uint32_t count=0x80000;
1083 for(;!list_empty(&epqh->urbd_list) && count> 0; count--) udelay(1);
1085 IFX_ERROR("%s: unable to clear urbd in epqh \n",__func__);
1087 ifxhcd_epqh_free(epqh);
1089 IFX_DEBUGPL(DBG_HCD, "IFXUSB HCD EP DISABLE: done\n");
1094 \brief Handles host mode interrupts for the IFXUSB controller. Returns IRQ_NONE if
1095 there was no interrupt to handle. Returns IRQ_HANDLED if there was a valid
1098 This function is called by the USB core when an interrupt occurs
1100 irqreturn_t ifxhcd_irq(struct usb_hcd *_syshcd)
1102 ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd (_syshcd);
1105 //mask_and_ack_ifx_irq (ifxhcd->core_if.irq);
1106 retval = ifxhcd_handle_intr(ifxhcd);
1107 return IRQ_RETVAL(retval);
1113 \brief Creates Status Change bitmap for the root hub and root port. The bitmap is
1114 returned in buf. Bit 0 is the status change indicator for the root hub. Bit 1
1115 is the status change indicator for the single root port. Returns 1 if either
1116 change indicator is 1, otherwise returns 0.
1118 int ifxhcd_hub_status_data(struct usb_hcd *_syshcd, char *_buf)
1120 ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd (_syshcd);
1123 _buf[0] |= (ifxhcd->flags.b.port_connect_status_change ||
1124 ifxhcd->flags.b.port_reset_change ||
1125 ifxhcd->flags.b.port_enable_change ||
1126 ifxhcd->flags.b.port_suspend_change ||
1127 ifxhcd->flags.b.port_over_current_change) << 1;
1132 IFX_DEBUGPL(DBG_HCD, "IFXUSB HCD HUB STATUS DATA:"
1133 " Root port status changed\n");
1134 IFX_DEBUGPL(DBG_HCDV, " port_connect_status_change: %d\n",
1135 ifxhcd->flags.b.port_connect_status_change);
1136 IFX_DEBUGPL(DBG_HCDV, " port_reset_change: %d\n",
1137 ifxhcd->flags.b.port_reset_change);
1138 IFX_DEBUGPL(DBG_HCDV, " port_enable_change: %d\n",
1139 ifxhcd->flags.b.port_enable_change);
1140 IFX_DEBUGPL(DBG_HCDV, " port_suspend_change: %d\n",
1141 ifxhcd->flags.b.port_suspend_change);
1142 IFX_DEBUGPL(DBG_HCDV, " port_over_current_change: %d\n",
1143 ifxhcd->flags.b.port_over_current_change);
1146 hprt0.d32 = ifxusb_rreg(ifxhcd->core_if.hprt0);
1147 IFX_DEBUGPL(DBG_HCDV, " port reg :%08X\n",hprt0.d32);
1148 IFX_DEBUGPL(DBG_HCDV, " port reg :connect: %d/%d\n",hprt0.b.prtconnsts,hprt0.b.prtconndet);
1149 IFX_DEBUGPL(DBG_HCDV, " port reg :enable: %d/%d\n",hprt0.b.prtena,hprt0.b.prtenchng);
1150 IFX_DEBUGPL(DBG_HCDV, " port reg :OC: %d/%d\n",hprt0.b.prtovrcurract,hprt0.b.prtovrcurrchng);
1151 IFX_DEBUGPL(DBG_HCDV, " port reg :rsume/suspend/reset: %d/%d/%d\n",hprt0.b.prtres,hprt0.b.prtsusp,hprt0.b.prtrst);
1152 IFX_DEBUGPL(DBG_HCDV, " port reg :port power: %d/\n",hprt0.b.prtpwr);
1153 IFX_DEBUGPL(DBG_HCDV, " port reg :speed: %d/\n",hprt0.b.prtspd);
1157 return (_buf[0] != 0);
1160 #ifdef __WITH_HS_ELECT_TST__
1161 extern void do_setup(ifxusb_core_if_t *_core_if) ;
1162 extern void do_in_ack(ifxusb_core_if_t *_core_if);
1163 #endif //__WITH_HS_ELECT_TST__
1166 \brief Handles hub class-specific requests.
1168 int ifxhcd_hub_control( struct usb_hcd *_syshcd,
1176 ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd (_syshcd);
1177 ifxusb_core_if_t *core_if = &ifxhcd->core_if;
1178 struct usb_hub_descriptor *desc;
1179 hprt0_data_t hprt0 = {.d32 = 0};
1181 uint32_t port_status;
1185 case ClearHubFeature:
1186 IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1187 "ClearHubFeature 0x%x\n", _wValue);
1190 case C_HUB_LOCAL_POWER:
1191 case C_HUB_OVER_CURRENT:
1192 /* Nothing required here */
1196 IFX_ERROR ("IFXUSB HCD - "
1197 "ClearHubFeature request %xh unknown\n", _wValue);
1200 case ClearPortFeature:
1201 if (!_wIndex || _wIndex > 1)
1206 case USB_PORT_FEAT_ENABLE:
1207 IFX_DEBUGPL (DBG_ANY, "IFXUSB HCD HUB CONTROL - "
1208 "ClearPortFeature USB_PORT_FEAT_ENABLE\n");
1209 hprt0.d32 = ifxusb_read_hprt0 (core_if);
1211 ifxusb_wreg(core_if->hprt0, hprt0.d32);
1213 case USB_PORT_FEAT_SUSPEND:
1214 IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1215 "ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
1216 hprt0.d32 = ifxusb_read_hprt0 (core_if);
1218 ifxusb_wreg(core_if->hprt0, hprt0.d32);
1219 /* Clear Resume bit */
1222 ifxusb_wreg(core_if->hprt0, hprt0.d32);
1224 case USB_PORT_FEAT_POWER:
1225 IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1226 "ClearPortFeature USB_PORT_FEAT_POWER\n");
1228 ifxusb_vbus_off(core_if);
1230 ifxusb_vbus_off(core_if);
1232 hprt0.d32 = ifxusb_read_hprt0 (core_if);
1234 ifxusb_wreg(core_if->hprt0, hprt0.d32);
1236 case USB_PORT_FEAT_INDICATOR:
1237 IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1238 "ClearPortFeature USB_PORT_FEAT_INDICATOR\n");
1239 /* Port inidicator not supported */
1241 case USB_PORT_FEAT_C_CONNECTION:
1242 /* Clears drivers internal connect status change
1244 IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1245 "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n");
1246 ifxhcd->flags.b.port_connect_status_change = 0;
1248 case USB_PORT_FEAT_C_RESET:
1249 /* Clears the driver's internal Port Reset Change
1251 IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1252 "ClearPortFeature USB_PORT_FEAT_C_RESET\n");
1253 ifxhcd->flags.b.port_reset_change = 0;
1255 case USB_PORT_FEAT_C_ENABLE:
1256 /* Clears the driver's internal Port
1257 * Enable/Disable Change flag */
1258 IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1259 "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n");
1260 ifxhcd->flags.b.port_enable_change = 0;
1262 case USB_PORT_FEAT_C_SUSPEND:
1263 /* Clears the driver's internal Port Suspend
1264 * Change flag, which is set when resume signaling on
1265 * the host port is complete */
1266 IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1267 "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n");
1268 ifxhcd->flags.b.port_suspend_change = 0;
1270 case USB_PORT_FEAT_C_OVER_CURRENT:
1271 IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1272 "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n");
1273 ifxhcd->flags.b.port_over_current_change = 0;
1277 IFX_ERROR ("IFXUSB HCD - "
1278 "ClearPortFeature request %xh "
1279 "unknown or unsupported\n", _wValue);
1282 case GetHubDescriptor:
1283 IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1284 "GetHubDescriptor\n");
1285 desc = (struct usb_hub_descriptor *)_buf;
1286 desc->bDescLength = 9;
1287 desc->bDescriptorType = 0x29;
1288 desc->bNbrPorts = 1;
1289 desc->wHubCharacteristics = 0x08;
1290 desc->bPwrOn2PwrGood = 1;
1291 desc->bHubContrCurrent = 0;
1293 desc->u.hs.DeviceRemovable[0] = 0;
1294 desc->u.hs.DeviceRemovable[1] = 1;
1295 /*desc->bitmap[0] = 0;
1296 desc->bitmap[1] = 0xff;*/
1299 IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1301 memset (_buf, 0, 4);
1304 IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1306 if (!_wIndex || _wIndex > 1)
1309 if (ifxhcd->flags.b.port_connect_status_change)
1310 port_status |= (1 << USB_PORT_FEAT_C_CONNECTION);
1311 if (ifxhcd->flags.b.port_enable_change)
1312 port_status |= (1 << USB_PORT_FEAT_C_ENABLE);
1313 if (ifxhcd->flags.b.port_suspend_change)
1314 port_status |= (1 << USB_PORT_FEAT_C_SUSPEND);
1315 if (ifxhcd->flags.b.port_reset_change)
1316 port_status |= (1 << USB_PORT_FEAT_C_RESET);
1317 if (ifxhcd->flags.b.port_over_current_change)
1319 IFX_ERROR("Device Not Supported\n");
1320 port_status |= (1 << USB_PORT_FEAT_C_OVER_CURRENT);
1322 if (!ifxhcd->flags.b.port_connect_status)
1325 * The port is disconnected, which means the core is
1326 * either in device mode or it soon will be. Just
1327 * return 0's for the remainder of the port status
1328 * since the port register can't be read if the core
1329 * is in device mode.
1331 *((u32 *) _buf) = cpu_to_le32(port_status);
1335 hprt0.d32 = ifxusb_rreg(core_if->hprt0);
1336 IFX_DEBUGPL(DBG_HCDV, " HPRT0: 0x%08x\n", hprt0.d32);
1337 if (hprt0.b.prtconnsts)
1338 port_status |= (1 << USB_PORT_FEAT_CONNECTION);
1341 ifxhcd->disconnecting=0;
1342 port_status |= (1 << USB_PORT_FEAT_ENABLE);
1344 if (hprt0.b.prtsusp)
1345 port_status |= (1 << USB_PORT_FEAT_SUSPEND);
1346 if (hprt0.b.prtovrcurract)
1347 port_status |= (1 << USB_PORT_FEAT_OVER_CURRENT);
1349 port_status |= (1 << USB_PORT_FEAT_RESET);
1351 port_status |= (1 << USB_PORT_FEAT_POWER);
1352 if (hprt0.b.prtspd == IFXUSB_HPRT0_PRTSPD_HIGH_SPEED)
1353 port_status |= USB_PORT_STAT_HIGH_SPEED;
1354 else if (hprt0.b.prtspd == IFXUSB_HPRT0_PRTSPD_LOW_SPEED)
1355 port_status |= USB_PORT_STAT_LOW_SPEED;
1356 if (hprt0.b.prttstctl)
1357 port_status |= (1 << USB_PORT_FEAT_TEST);
1358 /* USB_PORT_FEAT_INDICATOR unsupported always 0 */
1359 *((u32 *) _buf) = cpu_to_le32(port_status);
1362 IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1364 /* No HUB features supported */
1366 case SetPortFeature:
1367 if (_wValue != USB_PORT_FEAT_TEST && (!_wIndex || _wIndex > 1))
1370 * The port is disconnected, which means the core is
1371 * either in device mode or it soon will be. Just
1372 * return without doing anything since the port
1373 * register can't be written if the core is in device
1376 if (!ifxhcd->flags.b.port_connect_status)
1380 case USB_PORT_FEAT_SUSPEND:
1381 IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1382 "SetPortFeature - USB_PORT_FEAT_SUSPEND\n");
1383 hprt0.d32 = ifxusb_read_hprt0 (core_if);
1384 hprt0.b.prtsusp = 1;
1385 ifxusb_wreg(core_if->hprt0, hprt0.d32);
1386 //IFX_PRINT( "SUSPEND: HPRT0=%0x\n", hprt0.d32);
1387 /* Suspend the Phy Clock */
1389 pcgcctl_data_t pcgcctl = {.d32=0};
1390 pcgcctl.b.stoppclk = 1;
1391 ifxusb_wreg(core_if->pcgcctl, pcgcctl.d32);
1394 case USB_PORT_FEAT_POWER:
1395 IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1396 "SetPortFeature - USB_PORT_FEAT_POWER\n");
1397 ifxusb_vbus_on (core_if);
1398 hprt0.d32 = ifxusb_read_hprt0 (core_if);
1400 ifxusb_wreg(core_if->hprt0, hprt0.d32);
1402 case USB_PORT_FEAT_RESET:
1403 IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1404 "SetPortFeature - USB_PORT_FEAT_RESET\n");
1405 hprt0.d32 = ifxusb_read_hprt0 (core_if);
1407 ifxusb_wreg(core_if->hprt0, hprt0.d32);
1408 /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */
1411 ifxusb_wreg(core_if->hprt0, hprt0.d32);
1413 #ifdef __WITH_HS_ELECT_TST__
1414 case USB_PORT_FEAT_TEST:
1417 gint_data_t gintmsk;
1418 t = (_wIndex >> 8); /* MSB wIndex USB */
1419 IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1420 "SetPortFeature - USB_PORT_FEAT_TEST %d\n", t);
1421 warn("USB_PORT_FEAT_TEST %d\n", t);
1424 hprt0.d32 = ifxusb_read_hprt0 (core_if);
1425 hprt0.b.prttstctl = t;
1426 ifxusb_wreg(core_if->hprt0, hprt0.d32);
1428 else if (t == 6) /* HS_HOST_PORT_SUSPEND_RESUME */
1430 /* Save current interrupt mask */
1431 gintmsk.d32 = ifxusb_rreg(&core_if->core_global_regs->gintmsk);
1433 /* Disable all interrupts while we muck with
1434 * the hardware directly
1436 ifxusb_wreg(&core_if->core_global_regs->gintmsk, 0);
1438 /* 15 second delay per the test spec */
1441 /* Drive suspend on the root port */
1442 hprt0.d32 = ifxusb_read_hprt0 (core_if);
1443 hprt0.b.prtsusp = 1;
1445 ifxusb_wreg(core_if->hprt0, hprt0.d32);
1447 /* 15 second delay per the test spec */
1450 /* Drive resume on the root port */
1451 hprt0.d32 = ifxusb_read_hprt0 (core_if);
1452 hprt0.b.prtsusp = 0;
1454 ifxusb_wreg(core_if->hprt0, hprt0.d32);
1457 /* Clear the resume bit */
1459 ifxusb_wreg(core_if->hprt0, hprt0.d32);
1461 /* Restore interrupts */
1462 ifxusb_wreg(&core_if->core_global_regs->gintmsk, gintmsk.d32);
1464 else if (t == 7) /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */
1466 /* Save current interrupt mask */
1467 gintmsk.d32 = ifxusb_rreg(&core_if->core_global_regs->gintmsk);
1469 /* Disable all interrupts while we muck with
1470 * the hardware directly
1472 ifxusb_wreg(&core_if->core_global_regs->gintmsk, 0);
1474 /* 15 second delay per the test spec */
1477 /* Send the Setup packet */
1480 /* 15 second delay so nothing else happens for awhile */
1483 /* Restore interrupts */
1484 ifxusb_wreg(&core_if->core_global_regs->gintmsk, gintmsk.d32);
1487 else if (t == 8) /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */
1489 /* Save current interrupt mask */
1490 gintmsk.d32 = ifxusb_rreg(&core_if->core_global_regs->gintmsk);
1492 /* Disable all interrupts while we muck with
1493 * the hardware directly
1495 ifxusb_wreg(&core_if->core_global_regs->gintmsk, 0);
1497 /* Send the Setup packet */
1500 /* 15 second delay so nothing else happens for awhile */
1503 /* Send the In and Ack packets */
1506 /* 15 second delay so nothing else happens for awhile */
1509 /* Restore interrupts */
1510 ifxusb_wreg(&core_if->core_global_regs->gintmsk, gintmsk.d32);
1514 #endif //__WITH_HS_ELECT_TST__
1515 case USB_PORT_FEAT_INDICATOR:
1516 IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1517 "SetPortFeature - USB_PORT_FEAT_INDICATOR\n");
1522 IFX_ERROR ("IFXUSB HCD - "
1523 "SetPortFeature request %xh "
1524 "unknown or unsupported\n", _wValue);
1530 IFX_WARN ("IFXUSB HCD - "
1531 "Unknown hub control request type or invalid typeReq: %xh wIndex: %xh wValue: %xh\n",
1532 _typeReq, _wIndex, _wValue);
1541 \brief This function trigger a data transfer for a host channel and
1542 starts the transfer.
1544 For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ
1545 register along with a packet count of 1 and the channel is enabled. This
1546 causes a single PING transaction to occur. Other fields in HCTSIZ are
1547 simply set to 0 since no data transfer occurs in this case.
1549 For a PING transfer in DMA mode, the HCTSIZ register is initialized with
1550 all the information required to perform the subsequent data transfer. In
1551 addition, the Do Ping bit is set in the HCTSIZ register. In this case, the
1552 controller performs the entire PING protocol, then starts the data
1554 \param _core_if Pointer of core_if structure
1555 \param _ifxhc Information needed to initialize the host channel. The xfer_len
1556 value may be reduced to accommodate the max widths of the XferSize and
1557 PktCnt fields in the HCTSIZn register. The multi_count value may be changed
1558 to reflect the final xfer_len value.
1560 void ifxhcd_hc_start(ifxhcd_hcd_t *_ifxhcd, ifxhcd_hc_t *_ifxhc)
1562 ifxusb_core_if_t *core_if = &_ifxhcd->core_if;
1563 uint32_t max_hc_xfer_size = core_if->params.max_transfer_size;
1564 uint16_t max_hc_pkt_count = core_if->params.max_packet_count;
1565 ifxusb_hc_regs_t *hc_regs = core_if->hc_regs[_ifxhc->hc_num];
1570 if(_ifxhc->epqh->urbd->phase==URBD_DEQUEUEING)
1573 hprt0.d32 = ifxusb_read_hprt0(core_if);
1575 if(_ifxhcd->pkt_remaining==0)
1579 if(_ifxhc->phase!=HC_WAITING)
1580 printk(KERN_INFO "%s() line %d: _ifxhc->phase!=HC_WAITING :%d\n",__func__,__LINE__,_ifxhc->phase);
1581 if(_ifxhc->epqh->urbd->phase==URBD_IDLE ) printk(KERN_INFO "%s() line %d: _ifxhc->epqh->urbd->phase==URBD_IDLE\n",__func__,__LINE__);
1582 // if(_ifxhc->epqh->urbd->phase==URBD_ACTIVE ) printk(KERN_INFO "%s() line %d: _ifxhc->epqh->urbd->phase==URBD_ACTIVE\n",__func__,__LINE__);
1583 if(_ifxhc->epqh->urbd->phase==URBD_STARTING ) printk(KERN_INFO "%s() line %d: _ifxhc->epqh->urbd->phase==URBD_STARTING\n",__func__,__LINE__);
1584 if(_ifxhc->epqh->urbd->phase==URBD_STARTED ) printk(KERN_INFO "%s() line %d: _ifxhc->epqh->urbd->phase==URBD_STARTED\n",__func__,__LINE__);
1585 if(_ifxhc->epqh->urbd->phase==URBD_COMPLETING) printk(KERN_INFO "%s() line %d: _ifxhc->epqh->urbd->phase==URBD_COMPLETING\n",__func__,__LINE__);
1586 if(_ifxhc->epqh->urbd->phase==URBD_DEQUEUEING) printk(KERN_INFO "%s() line %d: _ifxhc->epqh->urbd->phase==URBD_DEQUEUEING\n",__func__,__LINE__);
1587 if(_ifxhc->epqh->urbd->phase==URBD_FINISHING ) printk(KERN_INFO "%s() line %d: _ifxhc->epqh->urbd->phase==URBD_FINISHING\n",__func__,__LINE__);
1590 if (hprt0.b.prtspd == IFXUSB_HPRT0_PRTSPD_HIGH_SPEED)
1594 if(max_hc_pkt_count > _ifxhcd->pkt_remaining)
1595 max_hc_pkt_count = _ifxhcd->pkt_remaining;
1597 else if(_ifxhc->ep_type == IFXUSB_EP_TYPE_BULK)
1599 if( _ifxhc->is_in && _ifxhcd->pkt_count_limit_bi && max_hc_pkt_count > _ifxhcd->pkt_count_limit_bi)
1600 max_hc_pkt_count = _ifxhcd->pkt_count_limit_bi;
1601 if(!_ifxhc->is_in && _ifxhcd->pkt_count_limit_bo && max_hc_pkt_count > _ifxhcd->pkt_count_limit_bo)
1602 max_hc_pkt_count = _ifxhcd->pkt_count_limit_bo;
1603 if(max_hc_pkt_count*8 > _ifxhcd->pkt_remaining)
1604 max_hc_pkt_count = _ifxhcd->pkt_remaining/8;
1608 if(max_hc_pkt_count > _ifxhcd->pkt_remaining)
1609 max_hc_pkt_count = _ifxhcd->pkt_remaining;
1612 else if (hprt0.b.prtspd == IFXUSB_HPRT0_PRTSPD_LOW_SPEED)
1614 if(max_hc_pkt_count > _ifxhcd->pkt_remaining)
1615 max_hc_pkt_count = _ifxhcd->pkt_remaining;
1619 if(max_hc_pkt_count > _ifxhcd->pkt_remaining)
1620 max_hc_pkt_count = _ifxhcd->pkt_remaining;
1623 if(max_hc_pkt_count==0)
1626 if(max_hc_pkt_count * _ifxhc->mps < max_hc_xfer_size)
1627 max_hc_xfer_size = max_hc_pkt_count * _ifxhc->mps;
1629 _ifxhc->epqh->urbd->phase=URBD_STARTING;
1631 if(_ifxhc->is_in || _ifxhc->speed != IFXUSB_EP_SPEED_HIGH || _ifxhc->xfer_len==0)
1632 _ifxhc->epqh->do_ping=0;
1633 if(_ifxhc->ep_type == IFXUSB_EP_TYPE_INTR || _ifxhc->ep_type == IFXUSB_EP_TYPE_ISOC)
1634 _ifxhc->epqh->do_ping=0;
1635 if(_ifxhc->ep_type == IFXUSB_EP_TYPE_CTRL && _ifxhc->control_phase != IFXHCD_CONTROL_DATA )
1636 _ifxhc->epqh->do_ping=0;
1638 if (_ifxhc->split > 0)
1640 _ifxhc->start_pkt_count = 1;
1641 if(!_ifxhc->is_in && _ifxhc->split>1) // OUT CSPLIT
1642 _ifxhc->xfer_len = 0;
1643 if (_ifxhc->xfer_len > _ifxhc->mps)
1644 _ifxhc->xfer_len = _ifxhc->mps;
1645 if (_ifxhc->xfer_len > 188)
1646 _ifxhc->xfer_len = 188;
1648 else if(_ifxhc->is_in)
1650 _ifxhc->short_rw = 0;
1651 if (_ifxhc->xfer_len > 0)
1653 if (_ifxhc->xfer_len > max_hc_xfer_size)
1654 _ifxhc->xfer_len = max_hc_xfer_size - _ifxhc->mps + 1;
1655 _ifxhc->start_pkt_count = (_ifxhc->xfer_len + _ifxhc->mps - 1) / _ifxhc->mps;
1656 if (_ifxhc->start_pkt_count > max_hc_pkt_count)
1657 _ifxhc->start_pkt_count = max_hc_pkt_count;
1659 else /* Need 1 packet for transfer length of 0. */
1660 _ifxhc->start_pkt_count = 1;
1661 _ifxhc->xfer_len = _ifxhc->start_pkt_count * _ifxhc->mps;
1663 else //non-split out
1665 if (_ifxhc->xfer_len == 0)
1667 if(_ifxhc->short_rw==0)
1668 printk(KERN_INFO "Info: %s() line %d: ZLP write without short_rw set! xfer_count:%d/%d \n",__func__,__LINE__,
1670 _ifxhc->epqh->urbd->xfer_len);
1671 _ifxhc->start_pkt_count = 1;
1675 if (_ifxhc->xfer_len > max_hc_xfer_size)
1677 _ifxhc->start_pkt_count = (max_hc_xfer_size / _ifxhc->mps);
1678 _ifxhc->xfer_len = _ifxhc->start_pkt_count * _ifxhc->mps;
1682 _ifxhc->start_pkt_count = (_ifxhc->xfer_len+_ifxhc->mps-1) / _ifxhc->mps;
1683 // if(_ifxhc->start_pkt_count * _ifxhc->mps == _ifxhc->xfer_len )
1684 // _ifxhc->start_pkt_count += _ifxhc->short_rw;
1689 if (hprt0.b.prtspd == IFXUSB_HPRT0_PRTSPD_HIGH_SPEED)
1693 if( _ifxhcd->pkt_remaining > _ifxhc->start_pkt_count)
1694 _ifxhcd->pkt_remaining -= _ifxhc->start_pkt_count;
1696 _ifxhcd->pkt_remaining = 0;
1698 else if(_ifxhc->ep_type == IFXUSB_EP_TYPE_BULK)
1700 if( _ifxhcd->pkt_remaining*8 > _ifxhc->start_pkt_count)
1701 _ifxhcd->pkt_remaining -= (_ifxhc->start_pkt_count*8);
1703 _ifxhcd->pkt_remaining = 0;
1707 if( _ifxhcd->pkt_remaining > _ifxhc->start_pkt_count)
1708 _ifxhcd->pkt_remaining -= _ifxhc->start_pkt_count;
1710 _ifxhcd->pkt_remaining = 0;
1713 else if (hprt0.b.prtspd == IFXUSB_HPRT0_PRTSPD_LOW_SPEED)
1715 if( _ifxhcd->pkt_remaining > _ifxhc->start_pkt_count)
1716 _ifxhcd->pkt_remaining -= _ifxhc->start_pkt_count;
1718 _ifxhcd->pkt_remaining = 0;
1722 if( _ifxhcd->pkt_remaining > _ifxhc->start_pkt_count)
1723 _ifxhcd->pkt_remaining -= _ifxhc->start_pkt_count;
1725 _ifxhcd->pkt_remaining = 0;
1729 if (_ifxhc->ep_type == IFXUSB_EP_TYPE_ISOC)
1731 /* Set up the initial PID for the transfer. */
1733 _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA0;
1735 if (_ifxhc->speed == IFXUSB_EP_SPEED_HIGH)
1739 if (_ifxhc->multi_count == 1)
1740 _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA0;
1741 else if (_ifxhc->multi_count == 2)
1742 _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA1;
1744 _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA2;
1748 if (_ifxhc->multi_count == 1)
1749 _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA0;
1751 _ifxhc->data_pid_start = IFXUSB_HC_PID_MDATA;
1755 _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA0;
1760 IFX_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, _ifxhc->hc_num);
1762 hctsiz_data_t hctsiz= { .d32=0 };
1764 hctsiz.b.dopng = _ifxhc->epqh->do_ping;
1765 _ifxhc->epqh->do_ping=0;
1767 if(_ifxhc->is_in || _ifxhc->speed != IFXUSB_EP_SPEED_HIGH || _ifxhc->xfer_len==0)
1769 if(_ifxhc->ep_type == IFXUSB_EP_TYPE_INTR || _ifxhc->ep_type == IFXUSB_EP_TYPE_ISOC)
1771 if(_ifxhc->ep_type == IFXUSB_EP_TYPE_CTRL && _ifxhc->control_phase != IFXHCD_CONTROL_DATA )
1774 hctsiz.b.xfersize = _ifxhc->xfer_len;
1775 hctsiz.b.pktcnt = _ifxhc->start_pkt_count;
1776 hctsiz.b.pid = _ifxhc->data_pid_start;
1777 ifxusb_wreg(&hc_regs->hctsiz, hctsiz.d32);
1779 IFX_DEBUGPL(DBG_HCDV, " Xfer Size: %d\n", hctsiz.b.xfersize);
1780 IFX_DEBUGPL(DBG_HCDV, " Num Pkts: %d\n" , hctsiz.b.pktcnt);
1781 IFX_DEBUGPL(DBG_HCDV, " Start PID: %d\n", hctsiz.b.pid);
1783 IFX_DEBUGPL(DBG_HCDV, " DMA: 0x%08x\n", (uint32_t)(CPHYSADDR( ((uint32_t)(_ifxhc->xfer_buff))+ _ifxhc->xfer_count )));
1784 ifxusb_wreg(&hc_regs->hcdma, (uint32_t)(CPHYSADDR( ((uint32_t)(_ifxhc->xfer_buff))+ _ifxhc->xfer_count )));
1786 /* Start the split */
1787 if (_ifxhc->split>0)
1789 hcsplt_data_t hcsplt;
1790 hcsplt.d32 = ifxusb_rreg (&hc_regs->hcsplt);
1791 hcsplt.b.spltena = 1;
1792 if (_ifxhc->split>1)
1793 hcsplt.b.compsplt = 1;
1795 hcsplt.b.compsplt = 0;
1797 #if defined(__EN_ISOC__) && defined(__EN_ISOC_SPLIT__)
1798 if (_ifxhc->ep_type == IFXUSB_EP_TYPE_ISOC)
1799 hcsplt.b.xactpos = _ifxhc->isoc_xact_pos;
1802 hcsplt.b.xactpos = IFXUSB_HCSPLIT_XACTPOS_ALL;// if not ISO
1803 ifxusb_wreg(&hc_regs->hcsplt, hcsplt.d32);
1804 IFX_DEBUGPL(DBG_HCDV, " SPLIT: XACT_POS:0x%08x\n", hcsplt.d32);
1808 hcchar_data_t hcchar;
1809 hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
1810 // hcchar.b.multicnt = _ifxhc->multi_count;
1811 hcchar.b.multicnt = 1;
1813 if (_ifxhc->ep_type == IFXUSB_EP_TYPE_INTR || _ifxhc->ep_type == IFXUSB_EP_TYPE_ISOC)
1815 hfnum.d32 = ifxusb_rreg(&core_if->host_global_regs->hfnum);
1816 /* 1 if _next_ frame is odd, 0 if it's even */
1817 hcchar.b.oddfrm = (hfnum.b.frnum & 0x1) ? 0 : 1;
1821 _ifxhc->start_hcchar_val = hcchar.d32;
1823 IFX_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n",
1824 __func__, _ifxhc->hc_num, hcchar.d32);
1827 /* Set host channel enable after all other setup is complete. */
1830 hcchar.b.epdir = _ifxhc->is_in;
1831 _ifxhc->hcchar=hcchar.d32;
1834 IFX_DEBUGPL(DBG_HCDV, " HCCHART: 0x%08x\n", _ifxhc->hcchar);
1836 _ifxhc->phase=HC_STARTING;
1840 \brief Attempts to halt a host channel. This function should only be called
1841 to abort a transfer in DMA mode. Under normal circumstances in DMA mode, the
1842 controller halts the channel when the transfer is complete or a condition
1843 occurs that requires application intervention.
1845 In DMA mode, always sets the Channel Enable and Channel Disable bits of the
1846 HCCHARn register. The controller ensures there is space in the request
1847 queue before submitting the halt request.
1849 Some time may elapse before the core flushes any posted requests for this
1850 host channel and halts. The Channel Halted interrupt handler completes the
1851 deactivation of the host channel.
1853 int ifxhcd_hc_halt(ifxusb_core_if_t *_core_if,
1854 ifxhcd_hc_t *_ifxhc,
1855 ifxhcd_halt_status_e _halt_status)
1857 hcchar_data_t hcchar;
1858 ifxusb_hc_regs_t *hc_regs;
1859 hc_regs = _core_if->hc_regs[_ifxhc->hc_num];
1861 WARN_ON(_halt_status == HC_XFER_NO_HALT_STATUS);
1865 hprt0.d32 = ifxusb_rreg(_core_if->hprt0);
1866 if(hprt0.b.prtena == 0)
1870 if (_halt_status == HC_XFER_URB_DEQUEUE ||
1871 _halt_status == HC_XFER_AHB_ERR)
1874 * Disable all channel interrupts except Ch Halted. The URBD
1875 * and EPQH state associated with this transfer has been cleared
1876 * (in the case of URB_DEQUEUE), so the channel needs to be
1877 * shut down carefully to prevent crashes.
1879 hcint_data_t hcintmsk;
1881 hcintmsk.b.chhltd = 1;
1882 ifxusb_wreg(&hc_regs->hcintmsk, hcintmsk.d32);
1885 * Make sure no other interrupts besides halt are currently
1886 * pending. Handling another interrupt could cause a crash due
1887 * to the URBD and EPQH state.
1889 ifxusb_wreg(&hc_regs->hcint, ~hcintmsk.d32);
1892 * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR
1893 * even if the channel was already halted for some other
1896 _ifxhc->halt_status = _halt_status;
1899 hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
1900 if (hcchar.b.chen == 0)
1903 * The channel is either already halted or it hasn't
1904 * started yet. In DMA mode, the transfer may halt if
1905 * it finishes normally or a condition occurs that
1906 * requires driver intervention. Don't want to halt
1907 * the channel again. In either Slave or DMA mode,
1908 * it's possible that the transfer has been assigned
1909 * to a channel, but not started yet when an URB is
1910 * dequeued. Don't want to halt a channel that hasn't
1913 _ifxhc->phase=HC_IDLE;
1917 if (_ifxhc->phase==HC_STOPPING)
1920 * A halt has already been issued for this channel. This might
1921 * happen when a transfer is aborted by a higher level in
1925 IFX_PRINT("*** %s: Channel %d, double halt a channel***\n",
1926 __func__, _ifxhc->hc_num);
1930 hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
1934 ifxusb_wreg(&hc_regs->hcchar, hcchar.d32);
1936 _ifxhc->halt_status = _halt_status;
1937 _ifxhc->phase=HC_STOPPING;
1939 IFX_DEBUGPL(DBG_HCDV, "%s: Channel %d\n" , __func__, _ifxhc->hc_num);
1940 IFX_DEBUGPL(DBG_HCDV, " hcchar: 0x%08x\n" , hcchar.d32);
1941 IFX_DEBUGPL(DBG_HCDV, " halt_status: %d\n" , _ifxhc->halt_status);
1947 \brief Clears a host channel.
1949 void ifxhcd_hc_cleanup(ifxusb_core_if_t *_core_if, ifxhcd_hc_t *_ifxhc)
1951 ifxusb_hc_regs_t *hc_regs;
1953 _ifxhc->phase=HC_IDLE;
1957 * Clear channel interrupt enables and any unhandled channel interrupt
1960 hc_regs = _core_if->hc_regs[_ifxhc->hc_num];
1961 ifxusb_wreg(&hc_regs->hcintmsk, 0);
1962 ifxusb_wreg(&hc_regs->hcint, 0xFFFFFFFF);
1966 hcchar_data_t hcchar;
1967 hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
1969 IFX_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n", __func__, _ifxhc->hc_num, hcchar.d32);
1979 static void dump_urb_info(struct urb *_urb, char* _fn_name)
1981 IFX_PRINT("%s, urb %p\n" , _fn_name, _urb);
1982 IFX_PRINT(" Device address: %d\n", usb_pipedevice(_urb->pipe));
1983 IFX_PRINT(" Endpoint: %d, %s\n" , usb_pipeendpoint(_urb->pipe),
1984 (usb_pipein(_urb->pipe) ? "IN" : "OUT"));
1985 IFX_PRINT(" Endpoint type: %s\n",
1987 switch (usb_pipetype(_urb->pipe)) {
1988 case PIPE_CONTROL: pipetype = "CONTROL"; break;
1989 case PIPE_BULK: pipetype = "BULK"; break;
1990 case PIPE_INTERRUPT: pipetype = "INTERRUPT"; break;
1991 case PIPE_ISOCHRONOUS: pipetype = "ISOCHRONOUS"; break;
1992 default: pipetype = "UNKNOWN"; break;
1996 IFX_PRINT(" Speed: %s\n",
1998 switch (_urb->dev->speed) {
1999 case USB_SPEED_HIGH: speed = "HIGH"; break;
2000 case USB_SPEED_FULL: speed = "FULL"; break;
2001 case USB_SPEED_LOW: speed = "LOW"; break;
2002 default: speed = "UNKNOWN"; break;
2006 IFX_PRINT(" Max packet size: %d\n",
2007 usb_maxpacket(_urb->dev, _urb->pipe, usb_pipeout(_urb->pipe)));
2008 IFX_PRINT(" Data buffer length: %d\n", _urb->transfer_buffer_length);
2009 IFX_PRINT(" Transfer buffer: %p, Transfer DMA: %p\n",
2010 _urb->transfer_buffer, (void *)_urb->transfer_dma);
2011 IFX_PRINT(" Setup buffer: %p, Setup DMA: %p\n",
2012 _urb->setup_packet, (void *)_urb->setup_dma);
2013 IFX_PRINT(" Interval: %d\n", _urb->interval);
2014 if (usb_pipetype(_urb->pipe) == PIPE_ISOCHRONOUS)
2017 for (i = 0; i < _urb->number_of_packets; i++)
2019 IFX_PRINT(" ISO Desc %d:\n", i);
2020 IFX_PRINT(" offset: %d, length %d\n",
2021 _urb->iso_frame_desc[i].offset,
2022 _urb->iso_frame_desc[i].length);
2028 static void dump_channel_info(ifxhcd_hcd_t *_ifxhcd, ifxhcd_epqh_t *_epqh)
2030 if (_epqh->hc != NULL)
2032 ifxhcd_hc_t *hc = _epqh->hc;
2033 struct list_head *item;
2034 ifxhcd_epqh_t *epqh_item;
2036 ifxusb_hc_regs_t *hc_regs;
2038 hcchar_data_t hcchar;
2039 hcsplt_data_t hcsplt;
2040 hctsiz_data_t hctsiz;
2043 hc_regs = _ifxhcd->core_if.hc_regs[hc->hc_num];
2044 hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
2045 hcsplt.d32 = ifxusb_rreg(&hc_regs->hcsplt);
2046 hctsiz.d32 = ifxusb_rreg(&hc_regs->hctsiz);
2047 hcdma = ifxusb_rreg(&hc_regs->hcdma);
2049 IFX_PRINT(" Assigned to channel %d:\n" , hc->hc_num);
2050 IFX_PRINT(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, hcsplt.d32);
2051 IFX_PRINT(" hctsiz 0x%08x, hcdma 0x%08x\n" , hctsiz.d32, hcdma);
2052 IFX_PRINT(" dev_addr: %d, ep_num: %d, is_in: %d\n",
2053 hc->dev_addr, hc->ep_num, hc->is_in);
2054 IFX_PRINT(" ep_type: %d\n" , hc->ep_type);
2055 IFX_PRINT(" max_packet_size: %d\n", hc->mps);
2056 IFX_PRINT(" data_pid_start: %d\n" , hc->data_pid_start);
2057 IFX_PRINT(" halt_status: %d\n" , hc->halt_status);
2058 IFX_PRINT(" xfer_buff: %p\n" , hc->xfer_buff);
2059 IFX_PRINT(" xfer_len: %d\n" , hc->xfer_len);
2060 IFX_PRINT(" epqh: %p\n" , hc->epqh);
2061 IFX_PRINT(" NP :\n");
2062 list_for_each(item, &_ifxhcd->epqh_list_np)
2064 epqh_item = list_entry(item, ifxhcd_epqh_t, ql);
2065 IFX_PRINT(" %p\n", epqh_item);
2067 IFX_PRINT(" INTR :\n");
2068 list_for_each(item, &_ifxhcd->epqh_list_intr)
2070 epqh_item = list_entry(item, ifxhcd_epqh_t, ql);
2071 IFX_PRINT(" %p\n", epqh_item);
2074 IFX_PRINT(" ISOC:\n");
2075 list_for_each(item, &_ifxhcd->epqh_list_isoc)
2077 epqh_item = list_entry(item, ifxhcd_epqh_t, ql);
2078 IFX_PRINT(" %p\n", epqh_item);
2088 \brief This function writes a packet into the Tx FIFO associated with the Host
2089 Channel. For a channel associated with a non-periodic EP, the non-periodic
2090 Tx FIFO is written. For a channel associated with a periodic EP, the
2091 periodic Tx FIFO is written. This function should only be called in Slave
2094 Upon return the xfer_buff and xfer_count fields in _hc are incremented by
2095 then number of bytes written to the Tx FIFO.
2098 #ifdef __ENABLE_DUMP__
2099 void ifxhcd_dump_state(ifxhcd_hcd_t *_ifxhcd)
2103 num_channels = _ifxhcd->core_if.params.host_channels;
2105 IFX_PRINT("************************************************************\n");
2106 IFX_PRINT("HCD State:\n");
2107 IFX_PRINT(" Num channels: %d\n", num_channels);
2108 for (i = 0; i < num_channels; i++) {
2109 ifxhcd_hc_t *hc = &_ifxhcd->ifxhc[i];
2110 IFX_PRINT(" Channel %d:\n", hc->hc_num);
2111 IFX_PRINT(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
2112 hc->dev_addr, hc->ep_num, hc->is_in);
2113 IFX_PRINT(" speed: %d\n" , hc->speed);
2114 IFX_PRINT(" ep_type: %d\n" , hc->ep_type);
2115 IFX_PRINT(" mps: %d\n", hc->mps);
2116 IFX_PRINT(" data_pid_start: %d\n" , hc->data_pid_start);
2117 IFX_PRINT(" xfer_buff: %p\n" , hc->xfer_buff);
2118 IFX_PRINT(" xfer_len: %d\n" , hc->xfer_len);
2119 IFX_PRINT(" xfer_count: %d\n" , hc->xfer_count);
2120 IFX_PRINT(" halt_status: %d\n" , hc->halt_status);
2121 IFX_PRINT(" split: %d\n" , hc->split);
2122 IFX_PRINT(" hub_addr: %d\n" , hc->hub_addr);
2123 IFX_PRINT(" port_addr: %d\n" , hc->port_addr);
2124 #if defined(__EN_ISOC__) && defined(__EN_ISOC_SPLIT__)
2125 IFX_PRINT(" isoc_xact_pos: %d\n" , hc->isoc_xact_pos);
2128 IFX_PRINT(" epqh: %p\n" , hc->epqh);
2129 IFX_PRINT(" short_rw: %d\n" , hc->short_rw);
2130 IFX_PRINT(" control_phase: %d\n" , hc->control_phase);
2133 IFX_PRINT(" do_ping: %d\n" , hc->epqh->do_ping);
2135 IFX_PRINT(" start_pkt_count: %d\n" , hc->start_pkt_count);
2137 IFX_PRINT("************************************************************\n");
2140 #endif //__ENABLE_DUMP__