Root/target/linux/lantiq/files/drivers/usb/ifxhcd/ifxhcd.c

1/*****************************************************************************
2 ** FILE NAME : ifxhcd.c
3 ** PROJECT : IFX USB sub-system V3
4 ** MODULES : IFX USB sub-system Host and Device driver
5 ** SRC VERSION : 1.0
6 ** DATE : 1/Jan/2009
7 ** AUTHOR : Chen, Howard
8 ** DESCRIPTION : This file contains the structures, constants, and interfaces for
9 ** the Host Contoller Driver (HCD).
10 **
11 ** The Host Controller Driver (HCD) is responsible for translating requests
12 ** from the USB Driver into the appropriate actions on the IFXUSB controller.
13 ** It isolates the USBD from the specifics of the controller by providing an
14 ** API to the USBD.
15 *****************************************************************************/
16
17/*!
18  \file ifxhcd.c
19  \ingroup IFXUSB_DRIVER_V3
20  \brief This file contains the implementation of the HCD. In Linux,
21   the HCD implements the hc_driver API.
22*/
23
24#include <linux/version.h>
25#include "ifxusb_version.h"
26
27#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/moduleparam.h>
30#include <linux/init.h>
31
32#include <linux/device.h>
33
34#include <linux/errno.h>
35#include <linux/list.h>
36#include <linux/interrupt.h>
37#include <linux/string.h>
38
39#include <linux/dma-mapping.h>
40
41
42#include "ifxusb_plat.h"
43#include "ifxusb_regs.h"
44#include "ifxusb_cif.h"
45#include "ifxhcd.h"
46
47#include <asm/irq.h>
48
49#ifdef CONFIG_AVM_POWERMETER
50#include <linux/avm_power.h>
51#endif /*--- #ifdef CONFIG_AVM_POWERMETER ---*/
52
53#ifdef __DEBUG__
54    static void dump_urb_info(struct urb *_urb, char* _fn_name);
55    static void dump_channel_info(ifxhcd_hcd_t *_ifxhcd, ifxhcd_epqh_t *_epqh);
56#endif
57
58
59/*!
60 \brief Sets the final status of an URB and returns it to the device driver. Any
61  required cleanup of the URB is performed.
62 */
63void ifxhcd_complete_urb(ifxhcd_hcd_t *_ifxhcd, ifxhcd_urbd_t *_urbd, int _status)
64{
65    struct urb *urb=NULL;
66    unsigned long flags = 0;
67
68    /*== AVM/BC 20101111 Function called with Lock ==*/
69    //SPIN_LOCK_IRQSAVE(&_ifxhcd->lock, flags);
70
71    if (!list_empty(&_urbd->urbd_list_entry))
72        list_del_init (&_urbd->urbd_list_entry);
73
74    if(!_urbd->urb)
75    {
76        IFX_ERROR("%s: invalid urb\n",__func__);
77        /*== AVM/BC 20101111 Function called with Lock ==*/
78        //SPIN_UNLOCK_IRQRESTORE(&_ifxhcd->lock, flags);
79        return;
80    }
81
82    urb=_urbd->urb;
83
84    #ifdef __DEBUG__
85        if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB))
86        {
87            IFX_PRINT("%s: _urbd %p, urb %p, device %d, ep %d %s/%s, status=%d\n",
88                  __func__, _urbd,_urbd->urb, usb_pipedevice(_urbd->urb->pipe),
89                  usb_pipeendpoint(_urbd->urb->pipe),
90                  usb_pipein(_urbd->urb->pipe) ? "IN" : "OUT",
91                  (_urbd->is_in) ? "IN" : "OUT",
92                   _status);
93            if (_urbd->epqh->ep_type == IFXUSB_EP_TYPE_ISOC)
94            {
95                int i;
96                for (i = 0; i < _urbd->urb->number_of_packets; i++)
97                    IFX_PRINT(" ISO Desc %d status: %d\n", i, _urbd->urb->iso_frame_desc[i].status);
98            }
99        }
100    #endif
101
102    if (!_urbd->epqh)
103        IFX_ERROR("%s: invalid epqd\n",__func__);
104
105    #if defined(__UNALIGNED_BUFFER_ADJ__)
106        else if(_urbd->is_active)
107        {
108            if( _urbd->epqh->aligned_checked &&
109                _urbd->epqh->using_aligned_buf &&
110                _urbd->xfer_buff &&
111                _urbd->is_in )
112                memcpy(_urbd->xfer_buff,_urbd->epqh->aligned_buf,_urbd->xfer_len);
113            _urbd->epqh->using_aligned_buf=0;
114            _urbd->epqh->using_aligned_setup=0;
115            _urbd->epqh->aligned_checked=0;
116        }
117    #endif
118
119    urb->status = _status;
120    urb->hcpriv=NULL;
121    kfree(_urbd);
122
123    usb_hcd_unlink_urb_from_ep(ifxhcd_to_syshcd(_ifxhcd), urb);
124    SPIN_UNLOCK_IRQRESTORE(&_ifxhcd->lock, flags);
125
126// usb_hcd_giveback_urb(ifxhcd_to_syshcd(_ifxhcd), urb);
127    usb_hcd_giveback_urb(ifxhcd_to_syshcd(_ifxhcd), urb, _status);
128
129    /*== AVM/BC 20100630 - 2.6.28 needs HCD link/unlink URBs ==*/
130    SPIN_LOCK_IRQSAVE(&_ifxhcd->lock, flags);
131}
132
133/*== AVM/BC 20101111 URB Complete deferred
134 * Must be called with Spinlock
135 */
136
137/*!
138 \brief Inserts an urbd structur in the completion list. The urbd will be
139  later completed by select_eps_sub
140 */
141void defer_ifxhcd_complete_urb(ifxhcd_hcd_t *_ifxhcd, ifxhcd_urbd_t *_urbd, int _status)
142{
143
144    _urbd->status = _status;
145
146    //Unlink Urbd from epqh / Insert it into the complete list
147    list_move_tail(&_urbd->urbd_list_entry, &_ifxhcd->urbd_complete_list);
148
149}
150
151/*!
152 \brief Processes all the URBs in a single EPQHs. Completes them with
153        status and frees the URBD.
154 */
155//static
156void kill_all_urbs_in_epqh(ifxhcd_hcd_t *_ifxhcd, ifxhcd_epqh_t *_epqh, int _status)
157{
158    struct list_head *urbd_item;
159    ifxhcd_urbd_t *urbd;
160
161    if(!_epqh)
162        return;
163
164    for (urbd_item = _epqh->urbd_list.next;
165         urbd_item != &_epqh->urbd_list;
166         urbd_item = _epqh->urbd_list.next)
167    {
168        urbd = list_entry(urbd_item, ifxhcd_urbd_t, urbd_list_entry);
169        ifxhcd_complete_urb(_ifxhcd, urbd, _status);
170    }
171}
172
173
174/*!
175 \brief Free all EPS in one Processes all the URBs in a single list of EPQHs. Completes them with
176        -ETIMEDOUT and frees the URBD.
177 */
178//static
179void epqh_list_free(ifxhcd_hcd_t *_ifxhcd, struct list_head *_epqh_list)
180{
181        struct list_head *item;
182        ifxhcd_epqh_t *epqh;
183
184        if (!_epqh_list)
185            return;
186        if (_epqh_list->next == NULL) /* The list hasn't been initialized yet. */
187            return;
188
189    /* Ensure there are no URBDs or URBs left. */
190    for (item = _epqh_list->next; item != _epqh_list; item = _epqh_list->next)
191    {
192        epqh = list_entry(item, ifxhcd_epqh_t, epqh_list_entry);
193        kill_all_urbs_in_epqh(_ifxhcd, epqh, -ETIMEDOUT);
194        ifxhcd_epqh_free(epqh);
195    }
196}
197
198
199
200//static
201void epqh_list_free_all(ifxhcd_hcd_t *_ifxhcd)
202{
203    unsigned long flags;
204
205    /*== AVM/BC 20101111 - 2.6.28 Needs Spinlock ==*/
206    SPIN_LOCK_IRQSAVE(&_ifxhcd->lock, flags);
207
208    epqh_list_free(_ifxhcd, &_ifxhcd->epqh_np_active );
209    epqh_list_free(_ifxhcd, &_ifxhcd->epqh_np_ready );
210    epqh_list_free(_ifxhcd, &_ifxhcd->epqh_intr_active );
211    epqh_list_free(_ifxhcd, &_ifxhcd->epqh_intr_ready );
212    #ifdef __EN_ISOC__
213        epqh_list_free(_ifxhcd, &_ifxhcd->epqh_isoc_active );
214        epqh_list_free(_ifxhcd, &_ifxhcd->epqh_isoc_ready );
215    #endif
216    epqh_list_free(_ifxhcd, &_ifxhcd->epqh_stdby );
217
218    SPIN_UNLOCK_IRQRESTORE(&_ifxhcd->lock, flags);
219
220}
221
222
223/*!
224   \brief This function is called to handle the disconnection of host port.
225 */
226int32_t ifxhcd_disconnect(ifxhcd_hcd_t *_ifxhcd)
227{
228    IFX_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, _ifxhcd);
229
230    /* Set status flags for the hub driver. */
231    _ifxhcd->flags.b.port_connect_status_change = 1;
232    _ifxhcd->flags.b.port_connect_status = 0;
233
234    /*
235     * Shutdown any transfers in process by clearing the Tx FIFO Empty
236     * interrupt mask and status bits and disabling subsequent host
237     * channel interrupts.
238     */
239     {
240        gint_data_t intr = { .d32 = 0 };
241        intr.b.nptxfempty = 1;
242        intr.b.ptxfempty = 1;
243        intr.b.hcintr = 1;
244        ifxusb_mreg (&_ifxhcd->core_if.core_global_regs->gintmsk, intr.d32, 0);
245        ifxusb_mreg (&_ifxhcd->core_if.core_global_regs->gintsts, intr.d32, 0);
246    }
247
248    /* Respond with an error status to all URBs in the schedule. */
249    epqh_list_free_all(_ifxhcd);
250
251    /* Clean up any host channels that were in use. */
252    {
253        int num_channels;
254        ifxhcd_hc_t *channel;
255        ifxusb_hc_regs_t *hc_regs;
256        hcchar_data_t hcchar;
257        int i;
258
259        num_channels = _ifxhcd->core_if.params.host_channels;
260
261        for (i = 0; i < num_channels; i++)
262        {
263            channel = &_ifxhcd->ifxhc[i];
264            if (list_empty(&channel->hc_list_entry))
265            {
266                hc_regs = _ifxhcd->core_if.hc_regs[i];
267                hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
268                if (hcchar.b.chen)
269                {
270                    /* Halt the channel. */
271                    hcchar.b.chdis = 1;
272                    ifxusb_wreg(&hc_regs->hcchar, hcchar.d32);
273                }
274                list_add_tail(&channel->hc_list_entry, &_ifxhcd->free_hc_list);
275                ifxhcd_hc_cleanup(&_ifxhcd->core_if, channel);
276            }
277        }
278    }
279    return 1;
280}
281
282
283/*!
284   \brief Frees secondary storage associated with the ifxhcd_hcd structure contained
285          in the struct usb_hcd field.
286 */
287static void ifxhcd_freeextra(struct usb_hcd *_syshcd)
288{
289    ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd(_syshcd);
290
291    IFX_DEBUGPL(DBG_HCD, "IFXUSB HCD FREE\n");
292
293    /* Free memory for EPQH/URBD lists */
294    epqh_list_free_all(ifxhcd);
295
296    /* Free memory for the host channels. */
297    ifxusb_free_buf(ifxhcd->status_buf);
298    return;
299}
300#ifdef __USE_TIMER_4_SOF__
301static enum hrtimer_restart ifxhcd_timer_func(struct hrtimer *timer) {
302    ifxhcd_hcd_t *ifxhcd = container_of(timer, ifxhcd_hcd_t, hr_timer);
303    
304    ifxhcd_handle_intr(ifxhcd);
305
306    return HRTIMER_NORESTART;
307}
308#endif
309
310/*!
311   \brief Initializes the HCD. This function allocates memory for and initializes the
312  static parts of the usb_hcd and ifxhcd_hcd structures. It also registers the
313  USB bus with the core and calls the hc_driver->start() function. It returns
314  a negative error on failure.
315 */
316int ifxhcd_init(ifxhcd_hcd_t *_ifxhcd)
317{
318    int retval = 0;
319    struct usb_hcd *syshcd = NULL;
320
321    IFX_DEBUGPL(DBG_HCD, "IFX USB HCD INIT\n");
322
323    spin_lock_init(&_ifxhcd->lock);
324#ifdef __USE_TIMER_4_SOF__
325    hrtimer_init(&_ifxhcd->hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
326    _ifxhcd->hr_timer.function = ifxhcd_timer_func;
327#endif
328    _ifxhcd->hc_driver.description = _ifxhcd->core_if.core_name;
329    _ifxhcd->hc_driver.product_desc = "IFX USB Controller";
330    //_ifxhcd->hc_driver.hcd_priv_size = sizeof(ifxhcd_hcd_t);
331    _ifxhcd->hc_driver.hcd_priv_size = sizeof(unsigned long);
332    _ifxhcd->hc_driver.irq = ifxhcd_irq;
333    _ifxhcd->hc_driver.flags = HCD_MEMORY | HCD_USB2;
334    _ifxhcd->hc_driver.start = ifxhcd_start;
335    _ifxhcd->hc_driver.stop = ifxhcd_stop;
336    //_ifxhcd->hc_driver.reset =
337    //_ifxhcd->hc_driver.suspend =
338    //_ifxhcd->hc_driver.resume =
339    _ifxhcd->hc_driver.urb_enqueue = ifxhcd_urb_enqueue;
340    _ifxhcd->hc_driver.urb_dequeue = ifxhcd_urb_dequeue;
341    _ifxhcd->hc_driver.endpoint_disable = ifxhcd_endpoint_disable;
342    _ifxhcd->hc_driver.get_frame_number = ifxhcd_get_frame_number;
343    _ifxhcd->hc_driver.hub_status_data = ifxhcd_hub_status_data;
344    _ifxhcd->hc_driver.hub_control = ifxhcd_hub_control;
345    //_ifxhcd->hc_driver.hub_suspend =
346    //_ifxhcd->hc_driver.hub_resume =
347
348    /* Allocate memory for and initialize the base HCD and */
349#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
350    syshcd = usb_create_hcd(&_ifxhcd->hc_driver, _ifxhcd->dev, _ifxhcd->core_if.core_name);
351#else
352    syshcd = usb_create_hcd(&_ifxhcd->hc_driver, _ifxhcd->dev, _ifxhcd->dev->bus_id);
353#endif
354
355    if (syshcd == NULL)
356    {
357        retval = -ENOMEM;
358        goto error1;
359    }
360    
361#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
362    syshcd->has_tt = 1;
363#endif
364
365    syshcd->rsrc_start = (unsigned long)_ifxhcd->core_if.core_global_regs;
366    syshcd->regs = (void *)_ifxhcd->core_if.core_global_regs;
367    syshcd->self.otg_port = 0;
368
369    //*((unsigned long *)(&(syshcd->hcd_priv)))=(unsigned long)_ifxhcd;
370    //*((unsigned long *)(&(syshcd->hcd_priv[0])))=(unsigned long)_ifxhcd;
371    syshcd->hcd_priv[0]=(unsigned long)_ifxhcd;
372    _ifxhcd->syshcd=syshcd;
373
374    INIT_LIST_HEAD(&_ifxhcd->epqh_np_active );
375    INIT_LIST_HEAD(&_ifxhcd->epqh_np_ready );
376    INIT_LIST_HEAD(&_ifxhcd->epqh_intr_active );
377    INIT_LIST_HEAD(&_ifxhcd->epqh_intr_ready );
378    #ifdef __EN_ISOC__
379        INIT_LIST_HEAD(&_ifxhcd->epqh_isoc_active );
380        INIT_LIST_HEAD(&_ifxhcd->epqh_isoc_ready );
381    #endif
382    INIT_LIST_HEAD(&_ifxhcd->epqh_stdby );
383    INIT_LIST_HEAD(&_ifxhcd->urbd_complete_list);
384
385    /*
386     * Create a host channel descriptor for each host channel implemented
387     * in the controller. Initialize the channel descriptor array.
388     */
389    INIT_LIST_HEAD(&_ifxhcd->free_hc_list);
390    {
391        int num_channels = _ifxhcd->core_if.params.host_channels;
392        int i;
393        for (i = 0; i < num_channels; i++)
394        {
395            _ifxhcd->ifxhc[i].hc_num = i;
396            IFX_DEBUGPL(DBG_HCDV, "HCD Added channel #%d\n", i);
397        }
398    }
399
400    /* Set device flags indicating whether the HCD supports DMA. */
401    if(_ifxhcd->dev->dma_mask)
402        *(_ifxhcd->dev->dma_mask) = ~0;
403    _ifxhcd->dev->coherent_dma_mask = ~0;
404
405    /*
406     * Finish generic HCD initialization and start the HCD. This function
407     * allocates the DMA buffer pool, registers the USB bus, requests the
408     * IRQ line, and calls ifxusb_hcd_start method.
409     */
410// retval = usb_add_hcd(syshcd, _ifxhcd->core_if.irq, SA_INTERRUPT|SA_SHIRQ);
411    retval = usb_add_hcd(syshcd, _ifxhcd->core_if.irq, IRQF_DISABLED | IRQF_SHARED );
412    if (retval < 0)
413        goto error2;
414
415    /*
416     * Allocate space for storing data on status transactions. Normally no
417     * data is sent, but this space acts as a bit bucket. This must be
418     * done after usb_add_hcd since that function allocates the DMA buffer
419     * pool.
420     */
421    _ifxhcd->status_buf = ifxusb_alloc_buf(IFXHCD_STATUS_BUF_SIZE, 1);
422
423    if (_ifxhcd->status_buf)
424    {
425#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
426        IFX_DEBUGPL(DBG_HCD, "IFX USB HCD Initialized, bus=%s, usbbus=%d\n", _ifxhcd->core_if.core_name, syshcd->self.busnum);
427#else
428        IFX_DEBUGPL(DBG_HCD, "IFX USB HCD Initialized, bus=%s, usbbus=%d\n", _ifxhcd->dev->bus_id, syshcd->self.busnum);
429#endif
430        return 0;
431    }
432    IFX_ERROR("%s: status_buf allocation failed\n", __func__);
433
434    /* Error conditions */
435    usb_remove_hcd(syshcd);
436error2:
437    ifxhcd_freeextra(syshcd);
438    usb_put_hcd(syshcd);
439error1:
440    return retval;
441}
442
443/*!
444   \brief Removes the HCD.
445  Frees memory and resources associated with the HCD and deregisters the bus.
446 */
447void ifxhcd_remove(ifxhcd_hcd_t *_ifxhcd)
448{
449    struct usb_hcd *syshcd = ifxhcd_to_syshcd(_ifxhcd);
450
451    IFX_DEBUGPL(DBG_HCD, "IFX USB HCD REMOVE\n");
452
453/* == AVM/WK 20100709 - Fix: Order changed, disable IRQs not before remove_hcd == */
454
455    usb_remove_hcd(syshcd);
456
457    /* Turn off all interrupts */
458    ifxusb_wreg (&_ifxhcd->core_if.core_global_regs->gintmsk, 0);
459    ifxusb_mreg (&_ifxhcd->core_if.core_global_regs->gahbcfg, 1, 0);
460
461    ifxhcd_freeextra(syshcd);
462
463    usb_put_hcd(syshcd);
464
465    return;
466}
467
468
469/* =========================================================================
470 * Linux HC Driver Functions
471 * ========================================================================= */
472
473/*!
474   \brief Initializes the IFXUSB controller and its root hub and prepares it for host
475 mode operation. Activates the root port. Returns 0 on success and a negative
476 error code on failure.
477 Called by USB stack.
478 */
479int ifxhcd_start(struct usb_hcd *_syshcd)
480{
481    ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd (_syshcd);
482    ifxusb_core_if_t *core_if = &ifxhcd->core_if;
483    struct usb_bus *bus;
484
485    IFX_DEBUGPL(DBG_HCD, "IFX USB HCD START\n");
486
487    bus = hcd_to_bus(_syshcd);
488
489    /* Initialize the bus state. */
490    _syshcd->state = HC_STATE_RUNNING;
491
492    /* Initialize and connect root hub if one is not already attached */
493    if (bus->root_hub)
494    {
495        IFX_DEBUGPL(DBG_HCD, "IFX USB HCD Has Root Hub\n");
496        /* Inform the HUB driver to resume. */
497        usb_hcd_resume_root_hub(_syshcd);
498    }
499
500    ifxhcd->flags.d32 = 0;
501
502    /* Put all channels in the free channel list and clean up channel states.*/
503    {
504        struct list_head *item;
505        item = ifxhcd->free_hc_list.next;
506        while (item != &ifxhcd->free_hc_list)
507        {
508            list_del(item);
509            item = ifxhcd->free_hc_list.next;
510        }
511    }
512    {
513        int num_channels = ifxhcd->core_if.params.host_channels;
514        int i;
515        for (i = 0; i < num_channels; i++)
516        {
517            ifxhcd_hc_t *channel;
518            channel = &ifxhcd->ifxhc[i];
519            list_add_tail(&channel->hc_list_entry, &ifxhcd->free_hc_list);
520            ifxhcd_hc_cleanup(&ifxhcd->core_if, channel);
521        }
522    }
523    /* Initialize the USB core for host mode operation. */
524
525    ifxusb_host_enable_interrupts(core_if);
526    ifxusb_enable_global_interrupts(core_if);
527    ifxusb_phy_power_on (core_if);
528
529    ifxusb_vbus_init(core_if);
530
531    /* Turn on the vbus power. */
532    {
533        hprt0_data_t hprt0;
534        hprt0.d32 = ifxusb_read_hprt0(core_if);
535
536        IFX_PRINT("Init: Power Port (%d)\n", hprt0.b.prtpwr);
537        if (hprt0.b.prtpwr == 0 )
538        {
539            hprt0.b.prtpwr = 1;
540            ifxusb_wreg(core_if->hprt0, hprt0.d32);
541            ifxusb_vbus_on(core_if);
542        }
543    }
544    return 0;
545}
546
547
548/*!
549   \brief Halts the IFXUSB host mode operations in a clean manner. USB transfers are
550 stopped.
551 */
552void ifxhcd_stop(struct usb_hcd *_syshcd)
553{
554    ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd(_syshcd);
555    hprt0_data_t hprt0 = { .d32=0 };
556
557    IFX_DEBUGPL(DBG_HCD, "IFX USB HCD STOP\n");
558
559    /* Turn off all interrupts. */
560    ifxusb_disable_global_interrupts(&ifxhcd->core_if );
561    ifxusb_host_disable_interrupts(&ifxhcd->core_if );
562#ifdef __USE_TIMER_4_SOF__
563    hrtimer_cancel(&ifxhcd->hr_timer);
564#endif
565    /*
566     * The root hub should be disconnected before this function is called.
567     * The disconnect will clear the URBD lists (via ..._hcd_urb_dequeue)
568     * and the EPQH lists (via ..._hcd_endpoint_disable).
569     */
570
571    /* Turn off the vbus power */
572    IFX_PRINT("PortPower off\n");
573
574    ifxusb_vbus_off(&ifxhcd->core_if );
575
576    ifxusb_vbus_free(&ifxhcd->core_if );
577
578    hprt0.b.prtpwr = 0;
579    ifxusb_wreg(ifxhcd->core_if.hprt0, hprt0.d32);
580    return;
581}
582
583/*!
584   \brief Returns the current frame number
585 */
586int ifxhcd_get_frame_number(struct usb_hcd *_syshcd)
587{
588    ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd(_syshcd);
589    hfnum_data_t hfnum;
590
591    hfnum.d32 = ifxusb_rreg(&ifxhcd->core_if.host_global_regs->hfnum);
592
593    return hfnum.b.frnum;
594}
595
596/*!
597   \brief Starts processing a USB transfer request specified by a USB Request Block
598  (URB). mem_flags indicates the type of memory allocation to use while
599  processing this URB.
600 */
601int ifxhcd_urb_enqueue( struct usb_hcd *_syshcd,
602                        /*--- struct usb_host_endpoint *_sysep, Parameter im 2.6.28 entfallen ---*/
603                        struct urb *_urb,
604                        gfp_t _mem_flags)
605{
606    int retval = 0;
607    ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd (_syshcd);
608    struct usb_host_endpoint *_sysep = ifxhcd_urb_to_endpoint(_urb);
609    ifxhcd_epqh_t *epqh;
610
611    #ifdef __DEBUG__
612        if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB))
613            dump_urb_info(_urb, "ifxusb_hcd_urb_enqueue");
614    #endif //__DEBUG__
615
616    if (!ifxhcd->flags.b.port_connect_status) /* No longer connected. */
617        return -ENODEV;
618
619    #ifndef __EN_ISOC__
620        if(usb_pipetype(_urb->pipe) == PIPE_ISOCHRONOUS)
621        {
622            IFX_ERROR("ISOC transfer not supported!!!\n");
623            return -ENODEV;
624        }
625    #endif
626
627    retval=ifxhcd_urbd_create (ifxhcd,_urb);
628
629    if (retval)
630    {
631        IFX_ERROR("IFXUSB HCD URB Enqueue failed creating URBD\n");
632        return retval;
633    }
634    epqh = (ifxhcd_epqh_t *) _sysep->hcpriv;
635    ifxhcd_epqh_ready(ifxhcd, epqh);
636
637    select_eps(ifxhcd);
638    //enable_sof(ifxhcd);
639    {
640        gint_data_t gintsts;
641        gintsts.d32=0;
642        gintsts.b.sofintr = 1;
643        ifxusb_mreg(&ifxhcd->core_if.core_global_regs->gintmsk, 0,gintsts.d32);
644    }
645
646    return retval;
647}
648
649/*!
650   \brief Aborts/cancels a USB transfer request. Always returns 0 to indicate
651  success.
652 */
653int ifxhcd_urb_dequeue( struct usb_hcd *_syshcd,
654                        struct urb *_urb, int status /* Parameter neu in 2.6.28 */)
655{
656    unsigned long flags;
657    ifxhcd_hcd_t *ifxhcd;
658    ifxhcd_urbd_t *urbd;
659    ifxhcd_epqh_t *epqh;
660    int is_active=0;
661    int rc;
662
663    struct usb_host_endpoint *_sysep;
664
665    IFX_DEBUGPL(DBG_HCD, "IFXUSB HCD URB Dequeue\n");
666
667    #ifndef __EN_ISOC__
668        if(usb_pipetype(_urb->pipe) == PIPE_ISOCHRONOUS)
669            return 0;
670    #endif
671
672    _sysep = ifxhcd_urb_to_endpoint(_urb);
673
674    ifxhcd = syshcd_to_ifxhcd(_syshcd);
675
676    SPIN_LOCK_IRQSAVE(&ifxhcd->lock, flags);
677
678    /*== AVM/BC 20100630 - 2.6.28 needs HCD link/unlink URBs ==*/
679    rc = usb_hcd_check_unlink_urb(_syshcd, _urb, status);
680    if (rc) {
681        SPIN_UNLOCK_IRQRESTORE(&ifxhcd->lock, flags);
682        return rc;
683    }
684
685    urbd = (ifxhcd_urbd_t *) _urb->hcpriv;
686
687    if(_sysep)
688        epqh = (ifxhcd_epqh_t *) _sysep->hcpriv;
689    else
690        epqh = (ifxhcd_epqh_t *) urbd->epqh;
691
692    if(epqh!=urbd->epqh)
693        IFX_ERROR("%s inconsistant epqh %p %p\n",__func__,epqh,urbd->epqh);
694
695    #ifdef __DEBUG__
696        if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB))
697        {
698            dump_urb_info(_urb, "ifxhcd_urb_dequeue");
699            if (epqh->is_active)
700                dump_channel_info(ifxhcd, epqh);
701        }
702    #endif //__DEBUG__
703
704    if(!epqh->hc)
705        epqh->is_active=0;
706    else if (!ifxhcd->flags.b.port_connect_status)
707            epqh->is_active=0;
708    else if (epqh->is_active && urbd->is_active)
709    {
710        /*== AVM/WK 20100709 - halt channel only if really started ==*/
711        //if (epqh->hc->xfer_started && !epqh->hc->wait_for_sof) {
712        /*== AVM/WK 20101112 - halt channel if started ==*/
713        if (epqh->hc->xfer_started) {
714            /*
715             * If still connected (i.e. in host mode), halt the
716             * channel so it can be used for other transfers. If
717             * no longer connected, the host registers can't be
718             * written to halt the channel since the core is in
719             * device mode.
720             */
721            /* == 20110803 AVM/WK FIX propagate status == */
722            if (_urb->status == -EINPROGRESS) {
723                _urb->status = status;
724            }
725            ifxhcd_hc_halt(&ifxhcd->core_if, epqh->hc, HC_XFER_URB_DEQUEUE);
726            epqh->hc = NULL;
727            is_active=1;
728        }
729    }
730
731    if(is_active)
732    {
733        SPIN_UNLOCK_IRQRESTORE(&ifxhcd->lock, flags);
734    }
735    else
736    {
737        list_del_init(&urbd->urbd_list_entry);
738        kfree (urbd);
739
740        /*== AVM/BC 20100630 - 2.6.28 needs HCD link/unlink URBs ==*/
741        usb_hcd_unlink_urb_from_ep(_syshcd, _urb);
742
743        SPIN_UNLOCK_IRQRESTORE(&ifxhcd->lock, flags);
744        _urb->hcpriv = NULL;
745// usb_hcd_giveback_urb(_syshcd, _urb);
746        usb_hcd_giveback_urb(_syshcd, _urb, status /* neu in 2.6.28 */);
747        select_eps(ifxhcd);
748    }
749
750    return 0;
751}
752
753
754
755/*!
756   \brief Frees resources in the IFXUSB controller related to a given endpoint. Also
757  clears state in the HCD related to the endpoint. Any URBs for the endpoint
758  must already be dequeued.
759 */
760void ifxhcd_endpoint_disable( struct usb_hcd *_syshcd,
761                              struct usb_host_endpoint *_sysep)
762{
763    ifxhcd_epqh_t *epqh;
764    ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd(_syshcd);
765    unsigned long flags;
766
767    int retry = 0;
768
769    IFX_DEBUGPL(DBG_HCD, "IFXUSB HCD EP DISABLE: _bEndpointAddress=0x%02x, "
770        "endpoint=%d\n", _sysep->desc.bEndpointAddress,
771            ifxhcd_ep_addr_to_endpoint(_sysep->desc.bEndpointAddress));
772
773    SPIN_LOCK_IRQSAVE(&ifxhcd->lock, flags);
774    if((uint32_t)_sysep>=0x80000000 && (uint32_t)_sysep->hcpriv>=(uint32_t)0x80000000)
775    {
776        epqh = (ifxhcd_epqh_t *)(_sysep->hcpriv);
777        if (epqh && epqh->sysep==_sysep)
778        {
779
780#if 1 /*== AVM/BC 20101111 CHG Option active: Kill URBs when disabling EP ==*/
781            while (!list_empty(&epqh->urbd_list))
782            {
783                if (retry++ > 250)
784                {
785                    IFX_WARN("IFXUSB HCD EP DISABLE:"
786                         " URBD List for this endpoint is not empty\n");
787                    break;
788                }
789                kill_all_urbs_in_epqh(ifxhcd, epqh, -ETIMEDOUT);
790            }
791#else
792            while (!list_empty(&epqh->urbd_list))
793            {
794                /** Check that the QTD list is really empty */
795                if (retry++ > 250)
796                {
797                    IFX_WARN("IFXUSB HCD EP DISABLE:"
798                         " URBD List for this endpoint is not empty\n");
799                    break;
800                }
801                SPIN_UNLOCK_IRQRESTORE(&ifxhcd->lock, flags);
802                schedule_timeout_uninterruptible(1);
803                SPIN_LOCK_IRQSAVE(&ifxhcd->lock, flags);
804            }
805#endif
806
807            ifxhcd_epqh_free(epqh);
808            _sysep->hcpriv = NULL;
809        }
810    }
811    SPIN_UNLOCK_IRQRESTORE(&ifxhcd->lock, flags);
812}
813
814
815/*!
816   \brief Handles host mode interrupts for the IFXUSB controller. Returns IRQ_NONE if
817 * there was no interrupt to handle. Returns IRQ_HANDLED if there was a valid
818 * interrupt.
819 *
820 * This function is called by the USB core when an interrupt occurs
821 */
822irqreturn_t ifxhcd_irq(struct usb_hcd *_syshcd)
823{
824    ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd (_syshcd);
825    int32_t retval=0;
826
827    //mask_and_ack_ifx_irq (ifxhcd->core_if.irq);
828    retval = ifxhcd_handle_intr(ifxhcd);
829    return IRQ_RETVAL(retval);
830}
831
832
833/*!
834   \brief Handles host mode Over Current Interrupt
835 */
836irqreturn_t ifxhcd_oc_irq(int _irq , void *_dev)
837{
838    ifxhcd_hcd_t *ifxhcd = _dev;
839    int32_t retval=1;
840
841    ifxhcd->flags.b.port_over_current_change = 1;
842    ifxusb_vbus_off(&ifxhcd->core_if);
843    IFX_DEBUGP("OC INTERRUPT # %d\n",ifxhcd->core_if.core_no);
844
845    //mask_and_ack_ifx_irq (_irq);
846    return IRQ_RETVAL(retval);
847}
848
849/*!
850 \brief Creates Status Change bitmap for the root hub and root port. The bitmap is
851  returned in buf. Bit 0 is the status change indicator for the root hub. Bit 1
852  is the status change indicator for the single root port. Returns 1 if either
853  change indicator is 1, otherwise returns 0.
854 */
855int ifxhcd_hub_status_data(struct usb_hcd *_syshcd, char *_buf)
856{
857    ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd (_syshcd);
858
859    _buf[0] = 0;
860    _buf[0] |= (ifxhcd->flags.b.port_connect_status_change ||
861                ifxhcd->flags.b.port_reset_change ||
862                ifxhcd->flags.b.port_enable_change ||
863                ifxhcd->flags.b.port_suspend_change ||
864                ifxhcd->flags.b.port_over_current_change) << 1;
865
866    #ifdef __DEBUG__
867        if (_buf[0])
868        {
869            IFX_DEBUGPL(DBG_HCD, "IFXUSB HCD HUB STATUS DATA:"
870                    " Root port status changed\n");
871            IFX_DEBUGPL(DBG_HCDV, " port_connect_status_change: %d\n",
872                    ifxhcd->flags.b.port_connect_status_change);
873            IFX_DEBUGPL(DBG_HCDV, " port_reset_change: %d\n",
874                    ifxhcd->flags.b.port_reset_change);
875            IFX_DEBUGPL(DBG_HCDV, " port_enable_change: %d\n",
876                    ifxhcd->flags.b.port_enable_change);
877            IFX_DEBUGPL(DBG_HCDV, " port_suspend_change: %d\n",
878                    ifxhcd->flags.b.port_suspend_change);
879            IFX_DEBUGPL(DBG_HCDV, " port_over_current_change: %d\n",
880                    ifxhcd->flags.b.port_over_current_change);
881        }
882    #endif //__DEBUG__
883    return (_buf[0] != 0);
884}
885
886#ifdef __WITH_HS_ELECT_TST__
887    extern void do_setup(ifxusb_core_if_t *_core_if) ;
888    extern void do_in_ack(ifxusb_core_if_t *_core_if);
889#endif //__WITH_HS_ELECT_TST__
890
891/*!
892 \brief Handles hub class-specific requests.
893 */
894int ifxhcd_hub_control( struct usb_hcd *_syshcd,
895                        u16 _typeReq,
896                        u16 _wValue,
897                        u16 _wIndex,
898                        char *_buf,
899                        u16 _wLength)
900{
901    int retval = 0;
902
903    ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd (_syshcd);
904    ifxusb_core_if_t *core_if = &ifxhcd->core_if;
905    struct usb_hub_descriptor *desc;
906    hprt0_data_t hprt0 = {.d32 = 0};
907
908    uint32_t port_status;
909
910    switch (_typeReq)
911    {
912        case ClearHubFeature:
913            IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
914                     "ClearHubFeature 0x%x\n", _wValue);
915            switch (_wValue)
916            {
917                case C_HUB_LOCAL_POWER:
918                case C_HUB_OVER_CURRENT:
919                    /* Nothing required here */
920                    break;
921                default:
922                    retval = -EINVAL;
923                    IFX_ERROR ("IFXUSB HCD - "
924                           "ClearHubFeature request %xh unknown\n", _wValue);
925            }
926            break;
927        case ClearPortFeature:
928            if (!_wIndex || _wIndex > 1)
929                goto error;
930
931            switch (_wValue)
932            {
933                case USB_PORT_FEAT_ENABLE:
934                    IFX_DEBUGPL (DBG_ANY, "IFXUSB HCD HUB CONTROL - "
935                             "ClearPortFeature USB_PORT_FEAT_ENABLE\n");
936                    hprt0.d32 = ifxusb_read_hprt0 (core_if);
937                    hprt0.b.prtena = 1;
938                    ifxusb_wreg(core_if->hprt0, hprt0.d32);
939                    break;
940                case USB_PORT_FEAT_SUSPEND:
941                    IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
942                             "ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
943                    hprt0.d32 = ifxusb_read_hprt0 (core_if);
944                    hprt0.b.prtres = 1;
945                    ifxusb_wreg(core_if->hprt0, hprt0.d32);
946                    /* Clear Resume bit */
947                    mdelay (100);
948                    hprt0.b.prtres = 0;
949                    ifxusb_wreg(core_if->hprt0, hprt0.d32);
950                    break;
951                case USB_PORT_FEAT_POWER:
952                    IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
953                             "ClearPortFeature USB_PORT_FEAT_POWER\n");
954                    #ifdef __IS_DUAL__
955                        ifxusb_vbus_off(core_if);
956                    #else
957                        ifxusb_vbus_off(core_if);
958                    #endif
959                    hprt0.d32 = ifxusb_read_hprt0 (core_if);
960                    hprt0.b.prtpwr = 0;
961                    ifxusb_wreg(core_if->hprt0, hprt0.d32);
962                    break;
963                case USB_PORT_FEAT_INDICATOR:
964                    IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
965                             "ClearPortFeature USB_PORT_FEAT_INDICATOR\n");
966                    /* Port inidicator not supported */
967                    break;
968                case USB_PORT_FEAT_C_CONNECTION:
969                    /* Clears drivers internal connect status change
970                     * flag */
971                    IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
972                             "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n");
973                    ifxhcd->flags.b.port_connect_status_change = 0;
974                    break;
975                case USB_PORT_FEAT_C_RESET:
976                    /* Clears the driver's internal Port Reset Change
977                     * flag */
978                    IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
979                             "ClearPortFeature USB_PORT_FEAT_C_RESET\n");
980                    ifxhcd->flags.b.port_reset_change = 0;
981                    break;
982                case USB_PORT_FEAT_C_ENABLE:
983                    /* Clears the driver's internal Port
984                     * Enable/Disable Change flag */
985                    IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
986                             "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n");
987                    ifxhcd->flags.b.port_enable_change = 0;
988                    break;
989                case USB_PORT_FEAT_C_SUSPEND:
990                    /* Clears the driver's internal Port Suspend
991                     * Change flag, which is set when resume signaling on
992                     * the host port is complete */
993                    IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
994                             "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n");
995                    ifxhcd->flags.b.port_suspend_change = 0;
996                    break;
997                case USB_PORT_FEAT_C_OVER_CURRENT:
998                    IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
999                             "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n");
1000                    ifxhcd->flags.b.port_over_current_change = 0;
1001                    break;
1002                default:
1003                    retval = -EINVAL;
1004                    IFX_ERROR ("IFXUSB HCD - "
1005                             "ClearPortFeature request %xh "
1006                             "unknown or unsupported\n", _wValue);
1007            }
1008            break;
1009        case GetHubDescriptor:
1010            IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1011                     "GetHubDescriptor\n");
1012            desc = (struct usb_hub_descriptor *)_buf;
1013            desc->bDescLength = 9;
1014            desc->bDescriptorType = 0x29;
1015            desc->bNbrPorts = 1;
1016            desc->wHubCharacteristics = 0x08;
1017            desc->bPwrOn2PwrGood = 1;
1018            desc->bHubContrCurrent = 0;
1019// desc->bitmap[0] = 0;
1020// desc->bitmap[1] = 0xff;
1021            break;
1022        case GetHubStatus:
1023            IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1024                     "GetHubStatus\n");
1025            memset (_buf, 0, 4);
1026            break;
1027        case GetPortStatus:
1028            IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1029                     "GetPortStatus\n");
1030            if (!_wIndex || _wIndex > 1)
1031                goto error;
1032
1033# ifdef CONFIG_AVM_POWERMETER
1034            {
1035                /* first port only, but 2 Hosts */
1036                static unsigned char ucOldPower1 = 255;
1037                static unsigned char ucOldPower2 = 255;
1038
1039                unsigned char ucNewPower = 0;
1040                struct usb_device *childdev = _syshcd->self.root_hub->children[0];
1041
1042                if (childdev != NULL) {
1043                    ucNewPower = (childdev->actconfig != NULL)
1044                                    ? childdev->actconfig->desc.bMaxPower
1045                                    : 50;/* default: 50 means 100 mA*/
1046                }
1047                if (_syshcd->self.busnum == 1) {
1048                    if (ucOldPower1 != ucNewPower) {
1049                        ucOldPower1 = ucNewPower;
1050                        printk (KERN_INFO "IFXHCD#1: AVM Powermeter changed to %u mA\n", ucNewPower*2);
1051                        PowerManagmentRessourceInfo(powerdevice_usb_host, ucNewPower*2);
1052                    }
1053                } else {
1054                    if (ucOldPower2 != ucNewPower) {
1055                        ucOldPower2 = ucNewPower;
1056                        printk (KERN_INFO "IFXHCD#2: AVM Powermeter changed to %u mA\n", ucNewPower*2);
1057                        PowerManagmentRessourceInfo(powerdevice_usb_host2, ucNewPower*2);
1058                    }
1059                }
1060            }
1061# endif /*--- #ifdef CONFIG_AVM_POWERMETER ---*/
1062
1063            port_status = 0;
1064            if (ifxhcd->flags.b.port_connect_status_change)
1065                port_status |= (1 << USB_PORT_FEAT_C_CONNECTION);
1066            if (ifxhcd->flags.b.port_enable_change)
1067                port_status |= (1 << USB_PORT_FEAT_C_ENABLE);
1068            if (ifxhcd->flags.b.port_suspend_change)
1069                port_status |= (1 << USB_PORT_FEAT_C_SUSPEND);
1070            if (ifxhcd->flags.b.port_reset_change)
1071                port_status |= (1 << USB_PORT_FEAT_C_RESET);
1072            if (ifxhcd->flags.b.port_over_current_change)
1073            {
1074                IFX_ERROR("Device Not Supported\n");
1075                port_status |= (1 << USB_PORT_FEAT_C_OVER_CURRENT);
1076            }
1077            if (!ifxhcd->flags.b.port_connect_status)
1078            {
1079                /*
1080                 * The port is disconnected, which means the core is
1081                 * either in device mode or it soon will be. Just
1082                 * return 0's for the remainder of the port status
1083                 * since the port register can't be read if the core
1084                 * is in device mode.
1085                 */
1086                *((u32 *) _buf) = cpu_to_le32(port_status);
1087                break;
1088            }
1089
1090            hprt0.d32 = ifxusb_rreg(core_if->hprt0);
1091            IFX_DEBUGPL(DBG_HCDV, " HPRT0: 0x%08x\n", hprt0.d32);
1092            if (hprt0.b.prtconnsts)
1093                port_status |= (1 << USB_PORT_FEAT_CONNECTION);
1094            if (hprt0.b.prtena)
1095                port_status |= (1 << USB_PORT_FEAT_ENABLE);
1096            if (hprt0.b.prtsusp)
1097                port_status |= (1 << USB_PORT_FEAT_SUSPEND);
1098            if (hprt0.b.prtovrcurract)
1099                port_status |= (1 << USB_PORT_FEAT_OVER_CURRENT);
1100            if (hprt0.b.prtrst)
1101                port_status |= (1 << USB_PORT_FEAT_RESET);
1102            if (hprt0.b.prtpwr)
1103                port_status |= (1 << USB_PORT_FEAT_POWER);
1104/* if (hprt0.b.prtspd == IFXUSB_HPRT0_PRTSPD_HIGH_SPEED)
1105                port_status |= (1 << USB_PORT_FEAT_HIGHSPEED);
1106            else if (hprt0.b.prtspd == IFXUSB_HPRT0_PRTSPD_LOW_SPEED)
1107                port_status |= (1 << USB_PORT_FEAT_LOWSPEED);*/
1108            if (hprt0.b.prttstctl)
1109                port_status |= (1 << USB_PORT_FEAT_TEST);
1110            /* USB_PORT_FEAT_INDICATOR unsupported always 0 */
1111            *((u32 *) _buf) = cpu_to_le32(port_status);
1112            break;
1113        case SetHubFeature:
1114            IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1115                     "SetHubFeature\n");
1116            /* No HUB features supported */
1117            break;
1118        case SetPortFeature:
1119            if (_wValue != USB_PORT_FEAT_TEST && (!_wIndex || _wIndex > 1))
1120                goto error;
1121            /*
1122             * The port is disconnected, which means the core is
1123             * either in device mode or it soon will be. Just
1124             * return without doing anything since the port
1125             * register can't be written if the core is in device
1126             * mode.
1127             */
1128            if (!ifxhcd->flags.b.port_connect_status)
1129                break;
1130            switch (_wValue)
1131            {
1132                case USB_PORT_FEAT_SUSPEND:
1133                    IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1134                             "SetPortFeature - USB_PORT_FEAT_SUSPEND\n");
1135                    hprt0.d32 = ifxusb_read_hprt0 (core_if);
1136                    hprt0.b.prtsusp = 1;
1137                    ifxusb_wreg(core_if->hprt0, hprt0.d32);
1138                    //IFX_PRINT( "SUSPEND: HPRT0=%0x\n", hprt0.d32);
1139                    /* Suspend the Phy Clock */
1140                    {
1141                        pcgcctl_data_t pcgcctl = {.d32=0};
1142                        pcgcctl.b.stoppclk = 1;
1143                        ifxusb_wreg(core_if->pcgcctl, pcgcctl.d32);
1144                    }
1145                    break;
1146                case USB_PORT_FEAT_POWER:
1147                    IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1148                         "SetPortFeature - USB_PORT_FEAT_POWER\n");
1149                    ifxusb_vbus_on (core_if);
1150                    hprt0.d32 = ifxusb_read_hprt0 (core_if);
1151                    hprt0.b.prtpwr = 1;
1152                    ifxusb_wreg(core_if->hprt0, hprt0.d32);
1153                    break;
1154                case USB_PORT_FEAT_RESET:
1155                    IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1156                             "SetPortFeature - USB_PORT_FEAT_RESET\n");
1157                    hprt0.d32 = ifxusb_read_hprt0 (core_if);
1158                    hprt0.b.prtrst = 1;
1159                    ifxusb_wreg(core_if->hprt0, hprt0.d32);
1160                    /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */
1161                    MDELAY (60);
1162                    hprt0.b.prtrst = 0;
1163                    ifxusb_wreg(core_if->hprt0, hprt0.d32);
1164                    break;
1165            #ifdef __WITH_HS_ELECT_TST__
1166                case USB_PORT_FEAT_TEST:
1167                    {
1168                        uint32_t t;
1169                        gint_data_t gintmsk;
1170                        t = (_wIndex >> 8); /* MSB wIndex USB */
1171                        IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1172                                 "SetPortFeature - USB_PORT_FEAT_TEST %d\n", t);
1173                        warn("USB_PORT_FEAT_TEST %d\n", t);
1174                        if (t < 6)
1175                        {
1176                            hprt0.d32 = ifxusb_read_hprt0 (core_if);
1177                            hprt0.b.prttstctl = t;
1178                            ifxusb_wreg(core_if->hprt0, hprt0.d32);
1179                        }
1180                        else if (t == 6) /* HS_HOST_PORT_SUSPEND_RESUME */
1181                        {
1182                            /* Save current interrupt mask */
1183                            gintmsk.d32 = ifxusb_rreg(&core_if->core_global_regs->gintmsk);
1184
1185                            /* Disable all interrupts while we muck with
1186                             * the hardware directly
1187                             */
1188                            ifxusb_wreg(&core_if->core_global_regs->gintmsk, 0);
1189
1190                            /* 15 second delay per the test spec */
1191                            mdelay(15000);
1192
1193                            /* Drive suspend on the root port */
1194                            hprt0.d32 = ifxusb_read_hprt0 (core_if);
1195                            hprt0.b.prtsusp = 1;
1196                            hprt0.b.prtres = 0;
1197                            ifxusb_wreg(core_if->hprt0, hprt0.d32);
1198
1199                            /* 15 second delay per the test spec */
1200                            mdelay(15000);
1201
1202                            /* Drive resume on the root port */
1203                            hprt0.d32 = ifxusb_read_hprt0 (core_if);
1204                            hprt0.b.prtsusp = 0;
1205                            hprt0.b.prtres = 1;
1206                            ifxusb_wreg(core_if->hprt0, hprt0.d32);
1207                            mdelay(100);
1208
1209                            /* Clear the resume bit */
1210                            hprt0.b.prtres = 0;
1211                            ifxusb_wreg(core_if->hprt0, hprt0.d32);
1212
1213                            /* Restore interrupts */
1214                            ifxusb_wreg(&core_if->core_global_regs->gintmsk, gintmsk.d32);
1215                        }
1216                        else if (t == 7) /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */
1217                        {
1218                            /* Save current interrupt mask */
1219                            gintmsk.d32 = ifxusb_rreg(&core_if->core_global_regs->gintmsk);
1220
1221                            /* Disable all interrupts while we muck with
1222                             * the hardware directly
1223                             */
1224                            ifxusb_wreg(&core_if->core_global_regs->gintmsk, 0);
1225
1226                            /* 15 second delay per the test spec */
1227                            mdelay(15000);
1228
1229                            /* Send the Setup packet */
1230                            do_setup(core_if);
1231
1232                            /* 15 second delay so nothing else happens for awhile */
1233                            mdelay(15000);
1234
1235                            /* Restore interrupts */
1236                            ifxusb_wreg(&core_if->core_global_regs->gintmsk, gintmsk.d32);
1237                        }
1238
1239                        else if (t == 8) /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */
1240                        {
1241                            /* Save current interrupt mask */
1242                            gintmsk.d32 = ifxusb_rreg(&core_if->core_global_regs->gintmsk);
1243
1244                            /* Disable all interrupts while we muck with
1245                             * the hardware directly
1246                             */
1247                            ifxusb_wreg(&core_if->core_global_regs->gintmsk, 0);
1248
1249                            /* Send the Setup packet */
1250                            do_setup(core_if);
1251
1252                            /* 15 second delay so nothing else happens for awhile */
1253                            mdelay(15000);
1254
1255                            /* Send the In and Ack packets */
1256                            do_in_ack(core_if);
1257
1258                            /* 15 second delay so nothing else happens for awhile */
1259                            mdelay(15000);
1260
1261                            /* Restore interrupts */
1262                            ifxusb_wreg(&core_if->core_global_regs->gintmsk, gintmsk.d32);
1263                        }
1264                    }
1265                    break;
1266            #endif //__WITH_HS_ELECT_TST__
1267                case USB_PORT_FEAT_INDICATOR:
1268                    IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1269                             "SetPortFeature - USB_PORT_FEAT_INDICATOR\n");
1270                    /* Not supported */
1271                    break;
1272                default:
1273                    retval = -EINVAL;
1274                    IFX_ERROR ("IFXUSB HCD - "
1275                           "SetPortFeature request %xh "
1276                           "unknown or unsupported\n", _wValue);
1277            }
1278            break;
1279        default:
1280        error:
1281            retval = -EINVAL;
1282            IFX_WARN ("IFXUSB HCD - "
1283                      "Unknown hub control request type or invalid typeReq: %xh wIndex: %xh wValue: %xh\n",
1284                      _typeReq, _wIndex, _wValue);
1285    }
1286    return retval;
1287}
1288
1289
1290/*!
1291 \brief Assigns transactions from a URBD to a free host channel and initializes the
1292 host channel to perform the transactions. The host channel is removed from
1293 the free list.
1294 \param _ifxhcd The HCD state structure.
1295 \param _epqh Transactions from the first URBD for this EPQH are selected and assigned to a free host channel.
1296 */
1297static int assign_and_init_hc(ifxhcd_hcd_t *_ifxhcd, ifxhcd_epqh_t *_epqh)
1298{
1299    ifxhcd_hc_t *ifxhc;
1300    ifxhcd_urbd_t *urbd;
1301    struct urb *urb;
1302
1303    IFX_DEBUGPL(DBG_HCDV, "%s(%p,%p)\n", __func__, _ifxhcd, _epqh);
1304
1305    if(list_empty(&_epqh->urbd_list))
1306        return 0;
1307
1308    ifxhc = list_entry(_ifxhcd->free_hc_list.next, ifxhcd_hc_t, hc_list_entry);
1309    /* Remove the host channel from the free list. */
1310    list_del_init(&ifxhc->hc_list_entry);
1311
1312    urbd = list_entry(_epqh->urbd_list.next, ifxhcd_urbd_t, urbd_list_entry);
1313    urb = urbd->urb;
1314
1315    _epqh->hc = ifxhc;
1316    _epqh->urbd = urbd;
1317    ifxhc->epqh = _epqh;
1318
1319    urbd->is_active=1;
1320
1321    /*
1322     * Use usb_pipedevice to determine device address. This address is
1323     * 0 before the SET_ADDRESS command and the correct address afterward.
1324     */
1325    ifxhc->dev_addr = usb_pipedevice(urb->pipe);
1326    ifxhc->ep_num = usb_pipeendpoint(urb->pipe);
1327
1328    ifxhc->xfer_started = 0;
1329
1330    if (urb->dev->speed == USB_SPEED_LOW) ifxhc->speed = IFXUSB_EP_SPEED_LOW;
1331    else if (urb->dev->speed == USB_SPEED_FULL) ifxhc->speed = IFXUSB_EP_SPEED_FULL;
1332    else ifxhc->speed = IFXUSB_EP_SPEED_HIGH;
1333
1334    ifxhc->mps = _epqh->mps;
1335    ifxhc->halt_status = HC_XFER_NO_HALT_STATUS;
1336
1337    ifxhc->ep_type = _epqh->ep_type;
1338
1339    if(_epqh->ep_type==IFXUSB_EP_TYPE_CTRL)
1340    {
1341        ifxhc->control_phase=IFXHCD_CONTROL_SETUP;
1342        ifxhc->is_in = 0;
1343        ifxhc->data_pid_start = IFXUSB_HC_PID_SETUP;
1344        ifxhc->xfer_buff = urbd->setup_buff;
1345        ifxhc->xfer_len = 8;
1346        ifxhc->xfer_count = 0;
1347        ifxhc->short_rw =(urb->transfer_flags & URB_ZERO_PACKET)?1:0;
1348    }
1349    else
1350    {
1351        ifxhc->is_in = urbd->is_in;
1352        ifxhc->xfer_buff = urbd->xfer_buff;
1353        ifxhc->xfer_len = urbd->xfer_len;
1354        ifxhc->xfer_count = 0;
1355        /* == AVM/WK 20100710 Fix - Use toggle of usbcore ==*/
1356        //ifxhc->data_pid_start = _epqh->data_toggle;
1357        ifxhc->data_pid_start = usb_gettoggle (urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout (urb->pipe))
1358                                ? IFXUSB_HC_PID_DATA1
1359                                : IFXUSB_HC_PID_DATA0;
1360        if(ifxhc->is_in)
1361            ifxhc->short_rw =0;
1362        else
1363            ifxhc->short_rw =(urb->transfer_flags & URB_ZERO_PACKET)?1:0;
1364
1365        #ifdef __EN_ISOC__
1366            if(_epqh->ep_type==IFXUSB_EP_TYPE_ISOC)
1367            {
1368                struct usb_iso_packet_descriptor *frame_desc;
1369                frame_desc = &urb->iso_frame_desc[urbd->isoc_frame_index];
1370                ifxhc->xfer_buff += frame_desc->offset + urbd->isoc_split_offset;
1371                ifxhc->xfer_len = frame_desc->length - urbd->isoc_split_offset;
1372                if (ifxhc->isoc_xact_pos == IFXUSB_HCSPLIT_XACTPOS_ALL)
1373                {
1374                    if (ifxhc->xfer_len <= 188)
1375                        ifxhc->isoc_xact_pos = IFXUSB_HCSPLIT_XACTPOS_ALL;
1376                    else
1377                        ifxhc->isoc_xact_pos = IFXUSB_HCSPLIT_XACTPOS_BEGIN;
1378                }
1379            }
1380        #endif
1381    }
1382
1383    ifxhc->do_ping=0;
1384    if (_ifxhcd->core_if.snpsid < 0x4f54271a && ifxhc->speed == IFXUSB_EP_SPEED_HIGH)
1385        ifxhc->do_ping=1;
1386
1387
1388    /* Set the split attributes */
1389    ifxhc->split = 0;
1390    if (_epqh->need_split) {
1391        ifxhc->split = 1;
1392        ifxhc->hub_addr = urb->dev->tt->hub->devnum;
1393        ifxhc->port_addr = urb->dev->ttport;
1394    }
1395
1396    //ifxhc->uint16_t pkt_count_limit
1397
1398    {
1399        hcint_data_t hc_intr_mask;
1400        uint8_t hc_num = ifxhc->hc_num;
1401        ifxusb_hc_regs_t *hc_regs = _ifxhcd->core_if.hc_regs[hc_num];
1402
1403        /* Clear old interrupt conditions for this host channel. */
1404        hc_intr_mask.d32 = 0xFFFFFFFF;
1405        hc_intr_mask.b.reserved = 0;
1406        ifxusb_wreg(&hc_regs->hcint, hc_intr_mask.d32);
1407
1408        /* Enable channel interrupts required for this transfer. */
1409        hc_intr_mask.d32 = 0;
1410        hc_intr_mask.b.chhltd = 1;
1411        hc_intr_mask.b.ahberr = 1;
1412
1413        ifxusb_wreg(&hc_regs->hcintmsk, hc_intr_mask.d32);
1414
1415        /* Enable the top level host channel interrupt. */
1416        {
1417            uint32_t intr_enable;
1418            intr_enable = (1 << hc_num);
1419            ifxusb_mreg(&_ifxhcd->core_if.host_global_regs->haintmsk, 0, intr_enable);
1420        }
1421
1422        /* Make sure host channel interrupts are enabled. */
1423        {
1424            gint_data_t gintmsk ={.d32 = 0};
1425            gintmsk.b.hcintr = 1;
1426            ifxusb_mreg(&_ifxhcd->core_if.core_global_regs->gintmsk, 0, gintmsk.d32);
1427        }
1428
1429        /*
1430         * Program the HCCHARn register with the endpoint characteristics for
1431         * the current transfer.
1432         */
1433        {
1434            hcchar_data_t hcchar;
1435
1436            hcchar.d32 = 0;
1437            hcchar.b.devaddr = ifxhc->dev_addr;
1438            hcchar.b.epnum = ifxhc->ep_num;
1439            hcchar.b.lspddev = (ifxhc->speed == IFXUSB_EP_SPEED_LOW);
1440            hcchar.b.eptype = ifxhc->ep_type;
1441            hcchar.b.mps = ifxhc->mps;
1442            ifxusb_wreg(&hc_regs->hcchar, hcchar.d32);
1443
1444            IFX_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, ifxhc->hc_num);
1445            IFX_DEBUGPL(DBG_HCDV, " Dev Addr: %d\n" , hcchar.b.devaddr);
1446            IFX_DEBUGPL(DBG_HCDV, " Ep Num: %d\n" , hcchar.b.epnum);
1447            IFX_DEBUGPL(DBG_HCDV, " Is Low Speed: %d\n", hcchar.b.lspddev);
1448            IFX_DEBUGPL(DBG_HCDV, " Ep Type: %d\n" , hcchar.b.eptype);
1449            IFX_DEBUGPL(DBG_HCDV, " Max Pkt: %d\n" , hcchar.b.mps);
1450            IFX_DEBUGPL(DBG_HCDV, " Multi Cnt: %d\n" , hcchar.b.multicnt);
1451        }
1452        /* Program the HCSPLIT register for SPLITs */
1453        {
1454            hcsplt_data_t hcsplt;
1455
1456            hcsplt.d32 = 0;
1457            if (ifxhc->split)
1458            {
1459                IFX_DEBUGPL(DBG_HCDV, "Programming HC %d with split --> %s\n", ifxhc->hc_num,
1460                       (ifxhc->split==2) ? "CSPLIT" : "SSPLIT");
1461                hcsplt.b.spltena = 1;
1462                hcsplt.b.compsplt = (ifxhc->split==2);
1463                #ifdef __EN_ISOC__
1464                    if(_epqh->ep_type==IFXUSB_EP_TYPE_ISOC)
1465                        hcsplt.b.xactpos = ifxhc->isoc_xact_pos;
1466                    else
1467                #endif
1468                    hcsplt.b.xactpos = IFXUSB_HCSPLIT_XACTPOS_ALL;
1469                hcsplt.b.hubaddr = ifxhc->hub_addr;
1470                hcsplt.b.prtaddr = ifxhc->port_addr;
1471                IFX_DEBUGPL(DBG_HCDV, " comp split %d\n" , hcsplt.b.compsplt);
1472                IFX_DEBUGPL(DBG_HCDV, " xact pos %d\n" , hcsplt.b.xactpos);
1473                IFX_DEBUGPL(DBG_HCDV, " hub addr %d\n" , hcsplt.b.hubaddr);
1474                IFX_DEBUGPL(DBG_HCDV, " port addr %d\n" , hcsplt.b.prtaddr);
1475                IFX_DEBUGPL(DBG_HCDV, " is_in %d\n" , ifxhc->is_in);
1476                IFX_DEBUGPL(DBG_HCDV, " Max Pkt: %d\n" , ifxhc->mps);
1477                IFX_DEBUGPL(DBG_HCDV, " xferlen: %d\n" , ifxhc->xfer_len);
1478            }
1479            ifxusb_wreg(&hc_regs->hcsplt, hcsplt.d32);
1480        }
1481    }
1482
1483    ifxhc->nak_retry_r=ifxhc->nak_retry=0;
1484    ifxhc->nak_countdown_r=ifxhc->nak_countdown=0;
1485
1486    if (ifxhc->split)
1487    {
1488        if(ifxhc->is_in)
1489        {
1490        }
1491        else
1492        {
1493        }
1494    }
1495    else if(_epqh->ep_type==IFXUSB_EP_TYPE_CTRL)
1496    {
1497        if(ifxhc->is_in)
1498        {
1499        }
1500        else
1501        {
1502        }
1503    }
1504    else if(_epqh->ep_type==IFXUSB_EP_TYPE_BULK)
1505    {
1506        if(ifxhc->is_in)
1507        {
1508// ifxhc->nak_retry_r=ifxhc->nak_retry=nak_retry_max;
1509// ifxhc->nak_countdown_r=ifxhc->nak_countdown=nak_countdown_max;
1510        }
1511        else
1512        {
1513        }
1514    }
1515    else if(_epqh->ep_type==IFXUSB_EP_TYPE_INTR)
1516    {
1517        if(ifxhc->is_in)
1518        {
1519        }
1520        else
1521        {
1522        }
1523    }
1524    else if(_epqh->ep_type==IFXUSB_EP_TYPE_ISOC)
1525    {
1526        if(ifxhc->is_in)
1527        {
1528        }
1529        else
1530        {
1531        }
1532    }
1533
1534    return 1;
1535}
1536
1537/*!
1538 \brief This function selects transactions from the HCD transfer schedule and
1539  assigns them to available host channels. It is called from HCD interrupt
1540  handler functions.
1541 */
1542static void select_eps_sub(ifxhcd_hcd_t *_ifxhcd)
1543{
1544    struct list_head *epqh_ptr;
1545    struct list_head *urbd_ptr;
1546    ifxhcd_epqh_t *epqh;
1547    ifxhcd_urbd_t *urbd;
1548    int ret_val=0;
1549
1550    /*== AVM/BC 20101111 Function called with Lock ==*/
1551
1552// #ifdef __DEBUG__
1553// IFX_DEBUGPL(DBG_HCD, " ifxhcd_select_ep\n");
1554// #endif
1555
1556    /* Process entries in the periodic ready list. */
1557    #ifdef __EN_ISOC__
1558        epqh_ptr = _ifxhcd->epqh_isoc_ready.next;
1559        while (epqh_ptr != &_ifxhcd->epqh_isoc_ready && !list_empty(&_ifxhcd->free_hc_list))
1560        {
1561            epqh = list_entry(epqh_ptr, ifxhcd_epqh_t, epqh_list_entry);
1562            epqh_ptr = epqh_ptr->next;
1563            if(epqh->period_do)
1564            {
1565                if(assign_and_init_hc(_ifxhcd, epqh))
1566                {
1567                    IFX_DEBUGPL(DBG_HCD, " select_eps ISOC\n");
1568                    list_move_tail(&epqh->epqh_list_entry, &_ifxhcd->epqh_isoc_active);
1569                    epqh->is_active=1;
1570                    ret_val=1;
1571                    epqh->period_do=0;
1572                }
1573            }
1574        }
1575    #endif
1576
1577    epqh_ptr = _ifxhcd->epqh_intr_ready.next;
1578    while (epqh_ptr != &_ifxhcd->epqh_intr_ready && !list_empty(&_ifxhcd->free_hc_list))
1579    {
1580        epqh = list_entry(epqh_ptr, ifxhcd_epqh_t, epqh_list_entry);
1581        epqh_ptr = epqh_ptr->next;
1582        if(epqh->period_do)
1583        {
1584            if(assign_and_init_hc(_ifxhcd, epqh))
1585            {
1586                IFX_DEBUGPL(DBG_HCD, " select_eps INTR\n");
1587                list_move_tail(&epqh->epqh_list_entry, &_ifxhcd->epqh_intr_active);
1588                epqh->is_active=1;
1589                ret_val=1;
1590                epqh->period_do=0;
1591            }
1592        }
1593    }
1594
1595    epqh_ptr = _ifxhcd->epqh_np_ready.next;
1596    while (epqh_ptr != &_ifxhcd->epqh_np_ready && !list_empty(&_ifxhcd->free_hc_list)) // may need to preserve at lease one for period
1597    {
1598        epqh = list_entry(epqh_ptr, ifxhcd_epqh_t, epqh_list_entry);
1599        epqh_ptr = epqh_ptr->next;
1600        if(assign_and_init_hc(_ifxhcd, epqh))
1601        {
1602            IFX_DEBUGPL(DBG_HCD, " select_eps CTRL/BULK\n");
1603            list_move_tail(&epqh->epqh_list_entry, &_ifxhcd->epqh_np_active);
1604            epqh->is_active=1;
1605            ret_val=1;
1606        }
1607    }
1608    if(ret_val)
1609        /*== AVM/BC 20101111 Function called with Lock ==*/
1610        process_channels_sub(_ifxhcd);
1611
1612    /* AVM/BC 20101111 Urbds completion loop */
1613    while (!list_empty(&_ifxhcd->urbd_complete_list))
1614    {
1615        urbd_ptr = _ifxhcd->urbd_complete_list.next;
1616        list_del_init(urbd_ptr);
1617
1618        urbd = list_entry(urbd_ptr, ifxhcd_urbd_t, urbd_list_entry);
1619
1620        ifxhcd_complete_urb(_ifxhcd, urbd, urbd->status);
1621
1622    }
1623
1624}
1625
1626static void select_eps_func(unsigned long data)
1627{
1628    unsigned long flags;
1629
1630    ifxhcd_hcd_t *ifxhcd;
1631    ifxhcd=((ifxhcd_hcd_t *)data);
1632
1633    /* AVM/BC 20101111 select_eps_in_use flag removed */
1634
1635    SPIN_LOCK_IRQSAVE(&ifxhcd->lock, flags);
1636
1637    /*if(ifxhcd->select_eps_in_use){
1638        SPIN_UNLOCK_IRQRESTORE(&ifxhcd->lock, flags);
1639        return;
1640    }
1641    ifxhcd->select_eps_in_use=1;
1642    */
1643
1644    select_eps_sub(ifxhcd);
1645
1646    //ifxhcd->select_eps_in_use=0;
1647
1648    SPIN_UNLOCK_IRQRESTORE(&ifxhcd->lock, flags);
1649}
1650
1651void select_eps(ifxhcd_hcd_t *_ifxhcd)
1652{
1653    if(in_irq())
1654    {
1655        if(!_ifxhcd->select_eps.func)
1656        {
1657            _ifxhcd->select_eps.next = NULL;
1658            _ifxhcd->select_eps.state = 0;
1659            atomic_set( &_ifxhcd->select_eps.count, 0);
1660            _ifxhcd->select_eps.func = select_eps_func;
1661            _ifxhcd->select_eps.data = (unsigned long)_ifxhcd;
1662        }
1663        tasklet_schedule(&_ifxhcd->select_eps);
1664    }
1665    else
1666    {
1667        unsigned long flags;
1668
1669        /* AVM/BC 20101111 select_eps_in_use flag removed */
1670
1671        SPIN_LOCK_IRQSAVE(&_ifxhcd->lock, flags);
1672
1673        /*if(_ifxhcd->select_eps_in_use){
1674            printk ("select_eps non_irq: busy\n");
1675            SPIN_UNLOCK_IRQRESTORE(&_ifxhcd->lock, flags);
1676            return;
1677        }
1678        _ifxhcd->select_eps_in_use=1;
1679        */
1680
1681        select_eps_sub(_ifxhcd);
1682
1683        //_ifxhcd->select_eps_in_use=0;
1684
1685        SPIN_UNLOCK_IRQRESTORE(&_ifxhcd->lock, flags);
1686    }
1687}
1688
1689/*!
1690 \brief
1691 */
1692static void process_unaligned( ifxhcd_epqh_t *_epqh)
1693{
1694    #if defined(__UNALIGNED_BUFFER_ADJ__)
1695        if(!_epqh->aligned_checked)
1696        {
1697            uint32_t xfer_len;
1698            xfer_len=_epqh->urbd->xfer_len;
1699            if(_epqh->urbd->is_in && xfer_len<_epqh->mps)
1700                xfer_len = _epqh->mps;
1701            _epqh->using_aligned_buf=0;
1702
1703            if(xfer_len > 0 && ((unsigned long)_epqh->urbd->xfer_buff) & 3)
1704            {
1705                if( _epqh->aligned_buf
1706                   && _epqh->aligned_buf_len > 0
1707                   && _epqh->aligned_buf_len < xfer_len
1708                  )
1709                {
1710                    ifxusb_free_buf(_epqh->aligned_buf);
1711                    _epqh->aligned_buf=NULL;
1712                    _epqh->aligned_buf_len=0;
1713                }
1714                if(! _epqh->aligned_buf || ! _epqh->aligned_buf_len)
1715                {
1716                    _epqh->aligned_buf = ifxusb_alloc_buf(xfer_len, _epqh->urbd->is_in);
1717                    if(_epqh->aligned_buf)
1718                        _epqh->aligned_buf_len = xfer_len;
1719                }
1720                if(_epqh->aligned_buf)
1721                {
1722                    if(!_epqh->urbd->is_in)
1723                        memcpy(_epqh->aligned_buf, _epqh->urbd->xfer_buff, xfer_len);
1724                    _epqh->using_aligned_buf=1;
1725                    _epqh->hc->xfer_buff = _epqh->aligned_buf;
1726                }
1727                else
1728                    IFX_WARN("%s():%d\n",__func__,__LINE__);
1729            }
1730            if(_epqh->ep_type==IFXUSB_EP_TYPE_CTRL)
1731            {
1732                _epqh->using_aligned_setup=0;
1733                if(((unsigned long)_epqh->urbd->setup_buff) & 3)
1734                {
1735                    if(! _epqh->aligned_setup)
1736                        _epqh->aligned_setup = ifxusb_alloc_buf(8,0);
1737                    if(_epqh->aligned_setup)
1738                    {
1739                        memcpy(_epqh->aligned_setup, _epqh->urbd->setup_buff, 8);
1740                        _epqh->using_aligned_setup=1;
1741                    }
1742                    else
1743                        IFX_WARN("%s():%d\n",__func__,__LINE__);
1744                    _epqh->hc->xfer_buff = _epqh->aligned_setup;
1745                }
1746            }
1747        }
1748    #elif defined(__UNALIGNED_BUFFER_CHK__)
1749        if(!_epqh->aligned_checked)
1750        {
1751            if(_epqh->urbd->is_in)
1752            {
1753                if(_epqh->urbd->xfer_len==0)
1754                    IFX_WARN("%s():%d IN xfer while length is zero \n",__func__,__LINE__);
1755                else{
1756                    if(_epqh->urbd->xfer_len < _epqh->mps)
1757                        IFX_WARN("%s():%d IN xfer while length < mps \n",__func__,__LINE__);
1758
1759                    if(((unsigned long)_epqh->urbd->xfer_buff) & 3)
1760                        IFX_WARN("%s():%d IN xfer Buffer UNALIGNED\n",__func__,__LINE__);
1761                }
1762            }
1763            else
1764            {
1765                if(_epqh->urbd->xfer_len > 0 && (((unsigned long)_epqh->urbd->xfer_buff) & 3) )
1766                    IFX_WARN("%s():%d OUT xfer Buffer UNALIGNED\n",__func__,__LINE__);
1767            }
1768
1769            if(_epqh->ep_type==IFXUSB_EP_TYPE_CTRL)
1770            {
1771                if(((unsigned long)_epqh->urbd->setup_buff) & 3)
1772                    IFX_WARN("%s():%d SETUP xfer Buffer UNALIGNED\n",__func__,__LINE__);
1773            }
1774        }
1775    #endif
1776    _epqh->aligned_checked=1;
1777}
1778
1779
1780/*!
1781 \brief
1782 */
1783void process_channels_sub(ifxhcd_hcd_t *_ifxhcd)
1784{
1785    ifxhcd_epqh_t *epqh;
1786    struct list_head *epqh_item;
1787    struct ifxhcd_hc *hc;
1788
1789    #ifdef __EN_ISOC__
1790        if (!list_empty(&_ifxhcd->epqh_isoc_active))
1791        {
1792            for (epqh_item = _ifxhcd->epqh_isoc_active.next;
1793                 epqh_item != &_ifxhcd->epqh_isoc_active;
1794                 )
1795            {
1796                epqh = list_entry(epqh_item, ifxhcd_epqh_t, epqh_list_entry);
1797                epqh_item = epqh_item->next;
1798                hc=epqh->hc;
1799                if(hc && !hc->xfer_started && epqh->period_do)
1800                {
1801                    if(hc->split==0
1802                        || hc->split==1
1803                       )
1804                    {
1805                        //epqh->ping_state = 0;
1806                        process_unaligned(epqh);
1807                        hc->wait_for_sof=epqh->wait_for_sof;
1808                        epqh->wait_for_sof=0;
1809                        ifxhcd_hc_start(&_ifxhcd->core_if, hc);
1810                        epqh->period_do=0;
1811                        {
1812                            gint_data_t gintsts = {.d32 = 0};
1813                            gintsts.b.sofintr = 1;
1814                            ifxusb_mreg(&_ifxhcd->core_if.core_global_regs->gintmsk,0, gintsts.d32);
1815                        }
1816                    }
1817                }
1818            }
1819        }
1820    #endif
1821
1822    if (!list_empty(&_ifxhcd->epqh_intr_active))
1823    {
1824        for (epqh_item = _ifxhcd->epqh_intr_active.next;
1825             epqh_item != &_ifxhcd->epqh_intr_active;
1826             )
1827        {
1828            epqh = list_entry(epqh_item, ifxhcd_epqh_t, epqh_list_entry);
1829            epqh_item = epqh_item->next;
1830            hc=epqh->hc;
1831            if(hc && !hc->xfer_started && epqh->period_do)
1832            {
1833                if(hc->split==0
1834                    || hc->split==1
1835                   )
1836                {
1837                    //epqh->ping_state = 0;
1838                    process_unaligned(epqh);
1839                    hc->wait_for_sof=epqh->wait_for_sof;
1840                    epqh->wait_for_sof=0;
1841                    ifxhcd_hc_start(&_ifxhcd->core_if, hc);
1842                    epqh->period_do=0;
1843#ifdef __USE_TIMER_4_SOF__
1844                    /* AVM/WK change: let hc_start decide, if irq is needed */
1845#else
1846                    {
1847                        gint_data_t gintsts = {.d32 = 0};
1848                        gintsts.b.sofintr = 1;
1849                        ifxusb_mreg(&_ifxhcd->core_if.core_global_regs->gintmsk,0, gintsts.d32);
1850                    }
1851#endif
1852                }
1853            }
1854
1855        }
1856    }
1857
1858    if (!list_empty(&_ifxhcd->epqh_np_active))
1859    {
1860        for (epqh_item = _ifxhcd->epqh_np_active.next;
1861             epqh_item != &_ifxhcd->epqh_np_active;
1862             )
1863        {
1864            epqh = list_entry(epqh_item, ifxhcd_epqh_t, epqh_list_entry);
1865            epqh_item = epqh_item->next;
1866            hc=epqh->hc;
1867            if(hc)
1868            {
1869                if(!hc->xfer_started)
1870                {
1871                    if(hc->split==0
1872                        || hc->split==1
1873                      //|| hc->split_counter == 0
1874                       )
1875                    {
1876                        //epqh->ping_state = 0;
1877                        process_unaligned(epqh);
1878                        hc->wait_for_sof=epqh->wait_for_sof;
1879                        epqh->wait_for_sof=0;
1880                        ifxhcd_hc_start(&_ifxhcd->core_if, hc);
1881                    }
1882                }
1883            }
1884        }
1885    }
1886}
1887
1888void process_channels(ifxhcd_hcd_t *_ifxhcd)
1889{
1890    unsigned long flags;
1891
1892    /* AVM/WK Fix: use spin_lock instead busy flag
1893    **/
1894    SPIN_LOCK_IRQSAVE(&_ifxhcd->lock, flags);
1895
1896    //if(_ifxhcd->process_channels_in_use)
1897    // return;
1898    //_ifxhcd->process_channels_in_use=1;
1899
1900    process_channels_sub(_ifxhcd);
1901    //_ifxhcd->process_channels_in_use=0;
1902    SPIN_UNLOCK_IRQRESTORE(&_ifxhcd->lock, flags);
1903}
1904
1905
1906#ifdef __HC_XFER_TIMEOUT__
1907    static void hc_xfer_timeout(unsigned long _ptr)
1908    {
1909        hc_xfer_info_t *xfer_info = (hc_xfer_info_t *)_ptr;
1910        int hc_num = xfer_info->hc->hc_num;
1911        IFX_WARN("%s: timeout on channel %d\n", __func__, hc_num);
1912        IFX_WARN(" start_hcchar_val 0x%08x\n", xfer_info->hc->start_hcchar_val);
1913    }
1914#endif
1915
1916void ifxhcd_hc_dumb_rx(ifxusb_core_if_t *_core_if, ifxhcd_hc_t *_ifxhc,uint8_t *dump_buf)
1917{
1918    ifxusb_hc_regs_t *hc_regs = _core_if->hc_regs[_ifxhc->hc_num];
1919    hctsiz_data_t hctsiz= { .d32=0 };
1920    hcchar_data_t hcchar;
1921
1922
1923    _ifxhc->xfer_len = _ifxhc->mps;
1924    hctsiz.b.xfersize = _ifxhc->mps;
1925    hctsiz.b.pktcnt = 0;
1926    hctsiz.b.pid = _ifxhc->data_pid_start;
1927    ifxusb_wreg(&hc_regs->hctsiz, hctsiz.d32);
1928
1929    ifxusb_wreg(&hc_regs->hcdma, (uint32_t)(CPHYSADDR( ((uint32_t)(dump_buf)))));
1930
1931    {
1932        hcint_data_t hcint= { .d32=0 };
1933// hcint.b.nak =1;
1934// hcint.b.nyet=1;
1935// hcint.b.ack =1;
1936        hcint.d32 =0xFFFFFFFF;
1937        ifxusb_wreg(&hc_regs->hcint, hcint.d32);
1938    }
1939
1940    /* Set host channel enable after all other setup is complete. */
1941    hcchar.b.chen = 1;
1942    hcchar.b.chdis = 0;
1943    hcchar.b.epdir = 1;
1944    IFX_DEBUGPL(DBG_HCDV, " HCCHART: 0x%08x\n", hcchar.d32);
1945    ifxusb_wreg(&hc_regs->hcchar, hcchar.d32);
1946}
1947
1948/*!
1949   \brief This function trigger a data transfer for a host channel and
1950  starts the transfer.
1951
1952  For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ
1953  register along with a packet count of 1 and the channel is enabled. This
1954  causes a single PING transaction to occur. Other fields in HCTSIZ are
1955  simply set to 0 since no data transfer occurs in this case.
1956
1957  For a PING transfer in DMA mode, the HCTSIZ register is initialized with
1958  all the information required to perform the subsequent data transfer. In
1959  addition, the Do Ping bit is set in the HCTSIZ register. In this case, the
1960  controller performs the entire PING protocol, then starts the data
1961  transfer.
1962  \param _core_if Pointer of core_if structure
1963  \param _ifxhc Information needed to initialize the host channel. The xfer_len
1964  value may be reduced to accommodate the max widths of the XferSize and
1965  PktCnt fields in the HCTSIZn register. The multi_count value may be changed
1966  to reflect the final xfer_len value.
1967 */
1968void ifxhcd_hc_start(ifxusb_core_if_t *_core_if, ifxhcd_hc_t *_ifxhc)
1969{
1970    hctsiz_data_t hctsiz= { .d32=0 };
1971    hcchar_data_t hcchar;
1972    uint32_t max_hc_xfer_size = _core_if->params.max_transfer_size;
1973    uint16_t max_hc_pkt_count = _core_if->params.max_packet_count;
1974    ifxusb_hc_regs_t *hc_regs = _core_if->hc_regs[_ifxhc->hc_num];
1975    hfnum_data_t hfnum;
1976
1977    hctsiz.b.dopng = 0;
1978// if(_ifxhc->do_ping && !_ifxhc->is_in) hctsiz.b.dopng = 1;
1979
1980    _ifxhc->nak_countdown=_ifxhc->nak_countdown_r;
1981
1982    /* AVM/BC 20101111 Workaround: Always PING if HI-Speed Out and xfer_len > 0 */
1983    if(/*_ifxhc->do_ping &&*/
1984        (!_ifxhc->is_in) &&
1985        (_ifxhc->speed == IFXUSB_EP_SPEED_HIGH) &&
1986        ((_ifxhc->ep_type == IFXUSB_EP_TYPE_BULK) || ((_ifxhc->ep_type == IFXUSB_EP_TYPE_CTRL) && (_ifxhc->control_phase != IFXHCD_CONTROL_SETUP))) &&
1987        _ifxhc->xfer_len
1988        )
1989        hctsiz.b.dopng = 1;
1990
1991    _ifxhc->xfer_started = 1;
1992
1993    if(_ifxhc->epqh->pkt_count_limit > 0 && _ifxhc->epqh->pkt_count_limit < max_hc_pkt_count )
1994    {
1995        max_hc_pkt_count=_ifxhc->epqh->pkt_count_limit;
1996        if(max_hc_pkt_count * _ifxhc->mps < max_hc_xfer_size)
1997            max_hc_xfer_size = max_hc_pkt_count * _ifxhc->mps;
1998    }
1999    if (_ifxhc->split > 0)
2000    {
2001        {
2002            gint_data_t gintsts = {.d32 = 0};
2003            gintsts.b.sofintr = 1;
2004            ifxusb_mreg(&_core_if->core_global_regs->gintmsk,0, gintsts.d32);
2005        }
2006
2007        _ifxhc->start_pkt_count = 1;
2008        if(!_ifxhc->is_in && _ifxhc->split>1) // OUT CSPLIT
2009            _ifxhc->xfer_len = 0;
2010        if (_ifxhc->xfer_len > _ifxhc->mps)
2011            _ifxhc->xfer_len = _ifxhc->mps;
2012        if (_ifxhc->xfer_len > 188)
2013            _ifxhc->xfer_len = 188;
2014    }
2015    else if(_ifxhc->is_in)
2016    {
2017        _ifxhc->short_rw = 0;
2018        if (_ifxhc->xfer_len > 0)
2019        {
2020            if (_ifxhc->xfer_len > max_hc_xfer_size)
2021                _ifxhc->xfer_len = max_hc_xfer_size - _ifxhc->mps + 1;
2022            _ifxhc->start_pkt_count = (_ifxhc->xfer_len + _ifxhc->mps - 1) / _ifxhc->mps;
2023            if (_ifxhc->start_pkt_count > max_hc_pkt_count)
2024                _ifxhc->start_pkt_count = max_hc_pkt_count;
2025        }
2026        else /* Need 1 packet for transfer length of 0. */
2027            _ifxhc->start_pkt_count = 1;
2028        _ifxhc->xfer_len = _ifxhc->start_pkt_count * _ifxhc->mps;
2029    }
2030    else //non-split out
2031    {
2032        if (_ifxhc->xfer_len == 0)
2033        {
2034            /*== AVM/BC WK 20110421 ZERO PACKET Workaround: Is not an error ==*/
2035            //if(_ifxhc->short_rw==0)
2036            // printk(KERN_INFO "%s() line %d: ZLP write without short_rw set!\n",__func__,__LINE__);
2037            _ifxhc->start_pkt_count = 1;
2038        }
2039        else
2040        {
2041            if (_ifxhc->xfer_len > max_hc_xfer_size)
2042            {
2043                _ifxhc->start_pkt_count = (max_hc_xfer_size / _ifxhc->mps);
2044                _ifxhc->xfer_len = _ifxhc->start_pkt_count * _ifxhc->mps;
2045            }
2046            else
2047            {
2048                _ifxhc->start_pkt_count = (_ifxhc->xfer_len+_ifxhc->mps-1) / _ifxhc->mps;
2049// if(_ifxhc->start_pkt_count * _ifxhc->mps == _ifxhc->xfer_len )
2050// _ifxhc->start_pkt_count += _ifxhc->short_rw;
2051                /*== AVM/BC WK 20110421 ZERO PACKET Workaround / check if short_rw is needed ==*/
2052                if(_ifxhc->start_pkt_count * _ifxhc->mps != _ifxhc->xfer_len )
2053                    _ifxhc->short_rw = 0;
2054            }
2055        }
2056    }
2057
2058    #ifdef __EN_ISOC__
2059        if (_ifxhc->ep_type == IFXUSB_EP_TYPE_ISOC)
2060        {
2061            /* Set up the initial PID for the transfer. */
2062            #if 1
2063                _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA0;
2064            #else
2065                if (_ifxhc->speed == IFXUSB_EP_SPEED_HIGH)
2066                {
2067                    if (_ifxhc->is_in)
2068                    {
2069                        if (_ifxhc->multi_count == 1)
2070                            _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA0;
2071                        else if (_ifxhc->multi_count == 2)
2072                            _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA1;
2073                        else
2074                            _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA2;
2075                    }
2076                    else
2077                    {
2078                        if (_ifxhc->multi_count == 1)
2079                            _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA0;
2080                        else
2081                            _ifxhc->data_pid_start = IFXUSB_HC_PID_MDATA;
2082                    }
2083                }
2084                else
2085                    _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA0;
2086            #endif
2087        }
2088    #endif
2089
2090    hctsiz.b.xfersize = _ifxhc->xfer_len;
2091    hctsiz.b.pktcnt = _ifxhc->start_pkt_count;
2092    hctsiz.b.pid = _ifxhc->data_pid_start;
2093
2094    ifxusb_wreg(&hc_regs->hctsiz, hctsiz.d32);
2095
2096
2097    IFX_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, _ifxhc->hc_num);
2098    IFX_DEBUGPL(DBG_HCDV, " Xfer Size: %d\n", hctsiz.b.xfersize);
2099    IFX_DEBUGPL(DBG_HCDV, " Num Pkts: %d\n" , hctsiz.b.pktcnt);
2100    IFX_DEBUGPL(DBG_HCDV, " Start PID: %d\n", hctsiz.b.pid);
2101    IFX_DEBUGPL(DBG_HCDV, " DMA: 0x%08x\n", (uint32_t)(CPHYSADDR( ((uint32_t)(_ifxhc->xfer_buff))+ _ifxhc->xfer_count )));
2102    ifxusb_wreg(&hc_regs->hcdma, (uint32_t)(CPHYSADDR( ((uint32_t)(_ifxhc->xfer_buff))+ _ifxhc->xfer_count )));
2103
2104    /* Start the split */
2105    if (_ifxhc->split>0)
2106    {
2107        hcsplt_data_t hcsplt;
2108        hcsplt.d32 = ifxusb_rreg (&hc_regs->hcsplt);
2109        hcsplt.b.spltena = 1;
2110        if (_ifxhc->split>1)
2111            hcsplt.b.compsplt = 1;
2112        else
2113            hcsplt.b.compsplt = 0;
2114
2115        #ifdef __EN_ISOC__
2116            if (_ifxhc->ep_type == IFXUSB_EP_TYPE_ISOC)
2117                hcsplt.b.xactpos = _ifxhc->isoc_xact_pos;
2118            else
2119        #endif
2120        hcsplt.b.xactpos = IFXUSB_HCSPLIT_XACTPOS_ALL;// if not ISO
2121        ifxusb_wreg(&hc_regs->hcsplt, hcsplt.d32);
2122        IFX_DEBUGPL(DBG_HCDV, " SPLIT: XACT_POS:0x%08x\n", hcsplt.d32);
2123    }
2124
2125    hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
2126// hcchar.b.multicnt = _ifxhc->multi_count;
2127    hcchar.b.multicnt = 1;
2128
2129    #ifdef __DEBUG__
2130        _ifxhc->start_hcchar_val = hcchar.d32;
2131        if (hcchar.b.chdis)
2132            IFX_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n",
2133                 __func__, _ifxhc->hc_num, hcchar.d32);
2134    #endif
2135
2136    /* Set host channel enable after all other setup is complete. */
2137    hcchar.b.chen = 1;
2138    hcchar.b.chdis = 0;
2139    hcchar.b.epdir = _ifxhc->is_in;
2140    _ifxhc->hcchar=hcchar.d32;
2141
2142    IFX_DEBUGPL(DBG_HCDV, " HCCHART: 0x%08x\n", _ifxhc->hcchar);
2143
2144    /* == 20110901 AVM/WK Fix: Clear IRQ flags in any case ==*/
2145    {
2146        hcint_data_t hcint= { .d32=0 };
2147        hcint.d32 =0xFFFFFFFF;
2148        ifxusb_wreg(&hc_regs->hcint, hcint.d32);
2149    }
2150
2151    if(_ifxhc->wait_for_sof==0)
2152    {
2153        hcint_data_t hcint;
2154
2155        hcint.d32=ifxusb_rreg(&hc_regs->hcintmsk);
2156
2157        hcint.b.nak =0;
2158        hcint.b.ack =0;
2159        /* == 20110901 AVM/WK Fix: We don't need NOT YET IRQ ==*/
2160        hcint.b.nyet=0;
2161        if(_ifxhc->nak_countdown_r)
2162            hcint.b.nak =1;
2163        ifxusb_wreg(&hc_regs->hcintmsk, hcint.d32);
2164
2165        /* AVM WK / BC 20100827
2166         * MOVED. Oddframe updated inmediatly before write HCChar Register.
2167         */
2168        if (_ifxhc->ep_type == IFXUSB_EP_TYPE_INTR || _ifxhc->ep_type == IFXUSB_EP_TYPE_ISOC)
2169        {
2170            hfnum.d32 = ifxusb_rreg(&_core_if->host_global_regs->hfnum);
2171            /* 1 if _next_ frame is odd, 0 if it's even */
2172            hcchar.b.oddfrm = (hfnum.b.frnum & 0x1) ? 0 : 1;
2173            _ifxhc->hcchar=hcchar.d32;
2174        }
2175
2176        ifxusb_wreg(&hc_regs->hcchar, _ifxhc->hcchar);
2177#ifdef __USE_TIMER_4_SOF__
2178    } else {
2179        //activate SOF IRQ
2180        gint_data_t gintsts = {.d32 = 0};
2181        gintsts.b.sofintr = 1;
2182        ifxusb_mreg(&_core_if->core_global_regs->gintmsk,0, gintsts.d32);
2183#endif
2184    }
2185
2186    #ifdef __HC_XFER_TIMEOUT__
2187        /* Start a timer for this transfer. */
2188        init_timer(&_ifxhc->hc_xfer_timer);
2189        _ifxhc->hc_xfer_timer.function = hc_xfer_timeout;
2190        _ifxhc->hc_xfer_timer.core_if = _core_if;
2191        _ifxhc->hc_xfer_timer.hc = _ifxhc;
2192        _ifxhc->hc_xfer_timer.data = (unsigned long)(&_ifxhc->hc_xfer_info);
2193        _ifxhc->hc_xfer_timer.expires = jiffies + (HZ*10);
2194        add_timer(&_ifxhc->hc_xfer_timer);
2195    #endif
2196}
2197
2198/*!
2199   \brief Attempts to halt a host channel. This function should only be called
2200  to abort a transfer in DMA mode. Under normal circumstances in DMA mode, the
2201  controller halts the channel when the transfer is complete or a condition
2202  occurs that requires application intervention.
2203
2204  In DMA mode, always sets the Channel Enable and Channel Disable bits of the
2205  HCCHARn register. The controller ensures there is space in the request
2206  queue before submitting the halt request.
2207
2208  Some time may elapse before the core flushes any posted requests for this
2209  host channel and halts. The Channel Halted interrupt handler completes the
2210  deactivation of the host channel.
2211 */
2212void ifxhcd_hc_halt(ifxusb_core_if_t *_core_if,
2213                    ifxhcd_hc_t *_ifxhc,
2214                    ifxhcd_halt_status_e _halt_status)
2215{
2216    hcchar_data_t hcchar;
2217    ifxusb_hc_regs_t *hc_regs;
2218
2219    hc_regs = _core_if->hc_regs[_ifxhc->hc_num];
2220
2221    WARN_ON(_halt_status == HC_XFER_NO_HALT_STATUS);
2222
2223    if (_halt_status == HC_XFER_URB_DEQUEUE ||
2224        _halt_status == HC_XFER_AHB_ERR)
2225    {
2226        /*
2227         * Disable all channel interrupts except Ch Halted. The URBD
2228         * and EPQH state associated with this transfer has been cleared
2229         * (in the case of URB_DEQUEUE), so the channel needs to be
2230         * shut down carefully to prevent crashes.
2231         */
2232        hcint_data_t hcintmsk;
2233        hcintmsk.d32 = 0;
2234        hcintmsk.b.chhltd = 1;
2235        ifxusb_wreg(&hc_regs->hcintmsk, hcintmsk.d32);
2236
2237        /*
2238         * Make sure no other interrupts besides halt are currently
2239         * pending. Handling another interrupt could cause a crash due
2240         * to the URBD and EPQH state.
2241         */
2242        ifxusb_wreg(&hc_regs->hcint, ~hcintmsk.d32);
2243
2244        /*
2245         * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR
2246         * even if the channel was already halted for some other
2247         * reason.
2248         */
2249        _ifxhc->halt_status = _halt_status;
2250
2251        hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
2252        if (hcchar.b.chen == 0)
2253        {
2254            /*
2255             * The channel is either already halted or it hasn't
2256             * started yet. In DMA mode, the transfer may halt if
2257             * it finishes normally or a condition occurs that
2258             * requires driver intervention. Don't want to halt
2259             * the channel again. In either Slave or DMA mode,
2260             * it's possible that the transfer has been assigned
2261             * to a channel, but not started yet when an URB is
2262             * dequeued. Don't want to halt a channel that hasn't
2263             * started yet.
2264             */
2265            return;
2266        }
2267    }
2268
2269    if (_ifxhc->halting)
2270    {
2271        /*
2272         * A halt has already been issued for this channel. This might
2273         * happen when a transfer is aborted by a higher level in
2274         * the stack.
2275         */
2276        #ifdef __DEBUG__
2277            IFX_PRINT("*** %s: Channel %d, _hc->halting already set ***\n",
2278                  __func__, _ifxhc->hc_num);
2279        #endif
2280        //ifxusb_dump_global_registers(_core_if); */
2281        //ifxusb_dump_host_registers(_core_if); */
2282        return;
2283    }
2284    hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
2285    /* == AVM/WK 20100709 halt channel only if enabled ==*/
2286    if (hcchar.b.chen) {
2287        _ifxhc->halting = 1;
2288        hcchar.b.chdis = 1;
2289
2290        ifxusb_wreg(&hc_regs->hcchar, hcchar.d32);
2291        _ifxhc->halt_status = _halt_status;
2292    }
2293
2294    IFX_DEBUGPL(DBG_HCDV, "%s: Channel %d\n" , __func__, _ifxhc->hc_num);
2295    IFX_DEBUGPL(DBG_HCDV, " hcchar: 0x%08x\n" , hcchar.d32);
2296    IFX_DEBUGPL(DBG_HCDV, " halting: %d\n" , _ifxhc->halting);
2297    IFX_DEBUGPL(DBG_HCDV, " halt_status: %d\n" , _ifxhc->halt_status);
2298
2299    return;
2300}
2301
2302/*!
2303   \brief Clears a host channel.
2304 */
2305void ifxhcd_hc_cleanup(ifxusb_core_if_t *_core_if, ifxhcd_hc_t *_ifxhc)
2306{
2307    ifxusb_hc_regs_t *hc_regs;
2308
2309    _ifxhc->xfer_started = 0;
2310    /*
2311     * Clear channel interrupt enables and any unhandled channel interrupt
2312     * conditions.
2313     */
2314    hc_regs = _core_if->hc_regs[_ifxhc->hc_num];
2315    ifxusb_wreg(&hc_regs->hcintmsk, 0);
2316    ifxusb_wreg(&hc_regs->hcint, 0xFFFFFFFF);
2317
2318    #ifdef __HC_XFER_TIMEOUT__
2319        del_timer(&_ifxhc->hc_xfer_timer);
2320    #endif
2321    #ifdef __DEBUG__
2322        {
2323            hcchar_data_t hcchar;
2324            hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
2325            if (hcchar.b.chdis)
2326                IFX_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n", __func__, _ifxhc->hc_num, hcchar.d32);
2327        }
2328    #endif
2329}
2330
2331
2332
2333
2334
2335
2336
2337
2338#ifdef __DEBUG__
2339    static void dump_urb_info(struct urb *_urb, char* _fn_name)
2340    {
2341        IFX_PRINT("%s, urb %p\n" , _fn_name, _urb);
2342        IFX_PRINT(" Device address: %d\n", usb_pipedevice(_urb->pipe));
2343        IFX_PRINT(" Endpoint: %d, %s\n" , usb_pipeendpoint(_urb->pipe),
2344                                            (usb_pipein(_urb->pipe) ? "IN" : "OUT"));
2345        IFX_PRINT(" Endpoint type: %s\n",
2346            ({ char *pipetype;
2347                switch (usb_pipetype(_urb->pipe)) {
2348                    case PIPE_CONTROL: pipetype = "CONTROL"; break;
2349                    case PIPE_BULK: pipetype = "BULK"; break;
2350                    case PIPE_INTERRUPT: pipetype = "INTERRUPT"; break;
2351                    case PIPE_ISOCHRONOUS: pipetype = "ISOCHRONOUS"; break;
2352                    default: pipetype = "UNKNOWN"; break;
2353                };
2354                pipetype;
2355            }));
2356        IFX_PRINT(" Speed: %s\n",
2357            ({ char *speed;
2358                switch (_urb->dev->speed) {
2359                    case USB_SPEED_HIGH: speed = "HIGH"; break;
2360                    case USB_SPEED_FULL: speed = "FULL"; break;
2361                    case USB_SPEED_LOW: speed = "LOW"; break;
2362                    default: speed = "UNKNOWN"; break;
2363                };
2364                speed;
2365            }));
2366        IFX_PRINT(" Max packet size: %d\n",
2367              usb_maxpacket(_urb->dev, _urb->pipe, usb_pipeout(_urb->pipe)));
2368        IFX_PRINT(" Data buffer length: %d\n", _urb->transfer_buffer_length);
2369        IFX_PRINT(" Transfer buffer: %p, Transfer DMA: %p\n",
2370              _urb->transfer_buffer, (void *)_urb->transfer_dma);
2371        IFX_PRINT(" Setup buffer: %p, Setup DMA: %p\n",
2372              _urb->setup_packet, (void *)_urb->setup_dma);
2373        IFX_PRINT(" Interval: %d\n", _urb->interval);
2374        if (usb_pipetype(_urb->pipe) == PIPE_ISOCHRONOUS)
2375        {
2376            int i;
2377            for (i = 0; i < _urb->number_of_packets; i++)
2378            {
2379                IFX_PRINT(" ISO Desc %d:\n", i);
2380                IFX_PRINT(" offset: %d, length %d\n",
2381                    _urb->iso_frame_desc[i].offset,
2382                    _urb->iso_frame_desc[i].length);
2383            }
2384        }
2385    }
2386
2387    static void dump_channel_info(ifxhcd_hcd_t *_ifxhcd, ifxhcd_epqh_t *_epqh)
2388    {
2389        if (_epqh->hc != NULL)
2390        {
2391            ifxhcd_hc_t *hc = _epqh->hc;
2392            struct list_head *item;
2393            ifxhcd_epqh_t *epqh_item;
2394
2395            ifxusb_hc_regs_t *hc_regs;
2396
2397            hcchar_data_t hcchar;
2398            hcsplt_data_t hcsplt;
2399            hctsiz_data_t hctsiz;
2400            uint32_t hcdma;
2401
2402            hc_regs = _ifxhcd->core_if.hc_regs[hc->hc_num];
2403            hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
2404            hcsplt.d32 = ifxusb_rreg(&hc_regs->hcsplt);
2405            hctsiz.d32 = ifxusb_rreg(&hc_regs->hctsiz);
2406            hcdma = ifxusb_rreg(&hc_regs->hcdma);
2407
2408            IFX_PRINT(" Assigned to channel %d:\n" , hc->hc_num);
2409            IFX_PRINT(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, hcsplt.d32);
2410            IFX_PRINT(" hctsiz 0x%08x, hcdma 0x%08x\n" , hctsiz.d32, hcdma);
2411            IFX_PRINT(" dev_addr: %d, ep_num: %d, is_in: %d\n",
2412               hc->dev_addr, hc->ep_num, hc->is_in);
2413            IFX_PRINT(" ep_type: %d\n" , hc->ep_type);
2414            IFX_PRINT(" max_packet_size: %d\n", hc->mps);
2415            IFX_PRINT(" data_pid_start: %d\n" , hc->data_pid_start);
2416            IFX_PRINT(" xfer_started: %d\n" , hc->xfer_started);
2417            IFX_PRINT(" halt_status: %d\n" , hc->halt_status);
2418            IFX_PRINT(" xfer_buff: %p\n" , hc->xfer_buff);
2419            IFX_PRINT(" xfer_len: %d\n" , hc->xfer_len);
2420            IFX_PRINT(" epqh: %p\n" , hc->epqh);
2421            IFX_PRINT(" NP Active:\n");
2422            list_for_each(item, &_ifxhcd->epqh_np_active)
2423            {
2424                epqh_item = list_entry(item, ifxhcd_epqh_t, epqh_list_entry);
2425                IFX_PRINT(" %p\n", epqh_item);
2426            }
2427            IFX_PRINT(" NP Ready:\n");
2428            list_for_each(item, &_ifxhcd->epqh_np_ready)
2429            {
2430                epqh_item = list_entry(item, ifxhcd_epqh_t, epqh_list_entry);
2431                IFX_PRINT(" %p\n", epqh_item);
2432            }
2433            IFX_PRINT(" INTR Active:\n");
2434            list_for_each(item, &_ifxhcd->epqh_intr_active)
2435            {
2436                epqh_item = list_entry(item, ifxhcd_epqh_t, epqh_list_entry);
2437                IFX_PRINT(" %p\n", epqh_item);
2438            }
2439            IFX_PRINT(" INTR Ready:\n");
2440            list_for_each(item, &_ifxhcd->epqh_intr_ready)
2441            {
2442                epqh_item = list_entry(item, ifxhcd_epqh_t, epqh_list_entry);
2443                IFX_PRINT(" %p\n", epqh_item);
2444            }
2445            #ifdef __EN_ISOC__
2446                IFX_PRINT(" ISOC Active:\n");
2447                list_for_each(item, &_ifxhcd->epqh_isoc_active)
2448                {
2449                    epqh_item = list_entry(item, ifxhcd_epqh_t, epqh_list_entry);
2450                    IFX_PRINT(" %p\n", epqh_item);
2451                }
2452                IFX_PRINT(" ISOC Ready:\n");
2453                list_for_each(item, &_ifxhcd->epqh_isoc_ready)
2454                {
2455                    epqh_item = list_entry(item, ifxhcd_epqh_t, epqh_list_entry);
2456                    IFX_PRINT(" %p\n", epqh_item);
2457                }
2458            #endif
2459            IFX_PRINT(" Standby:\n");
2460            list_for_each(item, &_ifxhcd->epqh_stdby)
2461            {
2462                epqh_item = list_entry(item, ifxhcd_epqh_t, epqh_list_entry);
2463                IFX_PRINT(" %p\n", epqh_item);
2464            }
2465        }
2466    }
2467#endif //__DEBUG__
2468
2469
2470/*!
2471   \brief This function writes a packet into the Tx FIFO associated with the Host
2472  Channel. For a channel associated with a non-periodic EP, the non-periodic
2473  Tx FIFO is written. For a channel associated with a periodic EP, the
2474  periodic Tx FIFO is written. This function should only be called in Slave
2475  mode.
2476
2477  Upon return the xfer_buff and xfer_count fields in _hc are incremented by
2478  then number of bytes written to the Tx FIFO.
2479 */
2480
2481#ifdef __ENABLE_DUMP__
2482    void ifxhcd_dump_state(ifxhcd_hcd_t *_ifxhcd)
2483    {
2484        int num_channels;
2485        int i;
2486        num_channels = _ifxhcd->core_if.params.host_channels;
2487        IFX_PRINT("\n");
2488        IFX_PRINT("************************************************************\n");
2489        IFX_PRINT("HCD State:\n");
2490        IFX_PRINT(" Num channels: %d\n", num_channels);
2491        for (i = 0; i < num_channels; i++) {
2492            ifxhcd_hc_t *hc = &_ifxhcd->ifxhc[i];
2493            IFX_PRINT(" Channel %d:\n", hc->hc_num);
2494            IFX_PRINT(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
2495                  hc->dev_addr, hc->ep_num, hc->is_in);
2496            IFX_PRINT(" speed: %d\n" , hc->speed);
2497            IFX_PRINT(" ep_type: %d\n" , hc->ep_type);
2498            IFX_PRINT(" mps: %d\n", hc->mps);
2499            IFX_PRINT(" data_pid_start: %d\n" , hc->data_pid_start);
2500            IFX_PRINT(" xfer_started: %d\n" , hc->xfer_started);
2501            IFX_PRINT(" xfer_buff: %p\n" , hc->xfer_buff);
2502            IFX_PRINT(" xfer_len: %d\n" , hc->xfer_len);
2503            IFX_PRINT(" xfer_count: %d\n" , hc->xfer_count);
2504            IFX_PRINT(" halting: %d\n" , hc->halting);
2505            IFX_PRINT(" halt_status: %d\n" , hc->halt_status);
2506            IFX_PRINT(" split: %d\n" , hc->split);
2507            IFX_PRINT(" hub_addr: %d\n" , hc->hub_addr);
2508            IFX_PRINT(" port_addr: %d\n" , hc->port_addr);
2509            #ifdef __EN_ISOC__
2510                IFX_PRINT(" isoc_xact_pos: %d\n" , hc->isoc_xact_pos);
2511            #endif
2512            IFX_PRINT(" epqh: %p\n" , hc->epqh);
2513            IFX_PRINT(" short_rw: %d\n" , hc->short_rw);
2514            IFX_PRINT(" do_ping: %d\n" , hc->do_ping);
2515            IFX_PRINT(" control_phase: %d\n" , hc->control_phase);
2516            IFX_PRINT(" pkt_count_limit: %d\n", hc->epqh->pkt_count_limit);
2517            IFX_PRINT(" start_pkt_count: %d\n" , hc->start_pkt_count);
2518        }
2519        IFX_PRINT("************************************************************\n");
2520        IFX_PRINT("\n");
2521    }
2522#endif //__ENABLE_DUMP__
2523
2524

Archive Download this file



interactive