Root/package/platform/lantiq/ltq-hcd/src/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 : 3.2
6 ** DATE : 1/Jan/2011
7 ** AUTHOR : Chen, Howard
8 ** DESCRIPTION : This file contains the structures, constants, and
9 ** interfaces for the Host Contoller Driver (HCD).
10 **
11 ** The Host Controller Driver (HCD) is responsible for
12 ** translating requests from the USB Driver into the
13 ** appropriate actions on the IFXUSB controller.
14 ** It isolates the USBD from the specifics of the
15 ** controller by providing an API to the USBD.
16 ** FUNCTIONS :
17 ** COMPILER : gcc
18 ** REFERENCE : Synopsys DWC-OTG Driver 2.7
19 ** COPYRIGHT : Copyright (c) 2010
20 ** LANTIQ DEUTSCHLAND GMBH,
21 ** Am Campeon 3, 85579 Neubiberg, Germany
22 **
23 ** This program is free software; you can redistribute it and/or modify
24 ** it under the terms of the GNU General Public License as published by
25 ** the Free Software Foundation; either version 2 of the License, or
26 ** (at your option) any later version.
27 **
28 ** Version Control Section **
29 ** $Author$
30 ** $Date$
31 ** $Revisions$
32 ** $Log$ Revision history
33 *****************************************************************************/
34
35/*
36 * This file contains code fragments from Synopsys HS OTG Linux Software Driver.
37 * For this code the following notice is applicable:
38 *
39 * ==========================================================================
40 *
41 * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
42 * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
43 * otherwise expressly agreed to in writing between Synopsys and you.
44 *
45 * The Software IS NOT an item of Licensed Software or Licensed Product under
46 * any End User Software License Agreement or Agreement for Licensed Product
47 * with Synopsys or any supplement thereto. You are permitted to use and
48 * redistribute this Software in source and binary forms, with or without
49 * modification, provided that redistributions of source code must retain this
50 * notice. You may not view, use, disclose, copy or distribute this file or
51 * any information contained herein except pursuant to this license grant from
52 * Synopsys. If you do not agree with this notice, including the disclaimer
53 * below, then you are not authorized to use the Software.
54 *
55 * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
56 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
57 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
58 * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
59 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
60 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
61 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
62 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
63 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
64 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
65 * DAMAGE.
66 * ========================================================================== */
67
68/*!
69  \file ifxhcd.c
70  \ingroup IFXUSB_DRIVER_V3
71  \brief This file contains the implementation of the HCD. In Linux,
72   the HCD implements the hc_driver API.
73*/
74
75#include <linux/version.h>
76#include "ifxusb_version.h"
77
78#include <linux/kernel.h>
79#include <linux/module.h>
80#include <linux/moduleparam.h>
81#include <linux/init.h>
82
83#include <linux/device.h>
84
85#include <linux/errno.h>
86#include <linux/list.h>
87#include <linux/interrupt.h>
88#include <linux/string.h>
89
90#include <linux/dma-mapping.h>
91
92
93#include "ifxusb_plat.h"
94#include "ifxusb_regs.h"
95#include "ifxusb_cif.h"
96#include "ifxhcd.h"
97
98#include <asm/irq.h>
99
100#ifdef __DEBUG__
101    static void dump_urb_info(struct urb *_urb, char* _fn_name);
102#if 0
103    static void dump_channel_info(ifxhcd_hcd_t *_ifxhcd,
104                                  ifxhcd_epqh_t *_epqh);
105#endif
106#endif
107
108static void ifxhcd_complete_urb_sub(ifxhcd_urbd_t *_urbd)
109{
110    ifxhcd_hcd_t *ifxhcd;
111    struct urb *urb=NULL;
112
113    if (!list_empty(&_urbd->ql))
114    {
115        list_del_init(&_urbd->ql);
116        _urbd->epqh->urbd_count--;
117    }
118    else
119        IFX_ERROR("%s: urb(%p) not connect to any epqh\n",
120                  __func__,_urbd);
121
122    ifxhcd=_urbd->epqh->ifxhcd;
123    urb =_urbd->urb;
124    if(!urb)
125        IFX_ERROR("%s: invalid urb\n",__func__);
126    else if(urb->hcpriv)
127    {
128        if(urb->hcpriv != _urbd)
129            IFX_ERROR("%s: invalid"
130                      " urb(%p)->hcpriv(%p) != _urbd(%p)\n",
131                      __func__,
132                      urb,
133                      urb->hcpriv,
134                      _urbd);
135        #if defined(__UNALIGNED_BUF_ADJ__)
136            if(_urbd->is_in &&
137// _urbd->using_aligned_buf &&
138               _urbd->aligned_buf)
139                memcpy(_urbd->xfer_buff,
140                       _urbd->aligned_buf,
141                       _urbd->xfer_len);
142            if(_urbd->aligned_buf)
143                ifxusb_free_buf_h(_urbd->aligned_buf);
144        #endif
145        urb->hcpriv = NULL;
146        #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
147            urb->status=_urbd->status;
148            usb_hcd_giveback_urb(ifxhcd_to_syshcd(ifxhcd), urb);
149        #else
150            usb_hcd_giveback_urb(ifxhcd_to_syshcd(ifxhcd), urb,
151                                 _urbd->status);
152        #endif
153    }
154    kfree(_urbd);
155}
156
157#ifdef __STRICT_ORDER__
158    static void ifxhcd_complete_urb_func(unsigned long data)
159    {
160        unsigned long flags;
161        ifxhcd_urbd_t *urbd;
162        ifxhcd_epqh_t *epqh;
163        struct list_head *item;
164
165        int count=10;
166
167        epqh=((ifxhcd_epqh_t *)data);
168
169        while (!list_empty(&epqh->release_list) && count)
170        {
171            item = epqh->release_list.next;
172            urbd = list_entry(item, ifxhcd_urbd_t, ql);
173            if (!urbd)
174                IFX_ERROR("%s: invalid urbd\n",__func__);
175            else if (!urbd->epqh)
176                IFX_ERROR("%s: invalid epqd\n",__func__);
177            else
178            {
179                ifxhcd_epqh_t *epqh2;
180                epqh2=urbd->epqh;
181                local_irq_save(flags);
182                LOCK_URBD_LIST(epqh2);
183                ifxhcd_complete_urb_sub(urbd);
184                UNLOCK_URBD_LIST(epqh2);
185                local_irq_restore (flags);
186            }
187            count--;
188        }
189        if(!list_empty(&epqh->release_list))
190            tasklet_schedule(&epqh->complete_urb_sub);
191    }
192
193    /*!
194     \brief Sets the final status of an URB and returns it to the device
195      driver. Any required cleanup of the URB is performed.
196     */
197    void ifxhcd_complete_urb(ifxhcd_hcd_t *_ifxhcd,
198                             ifxhcd_urbd_t *_urbd,
199                             int _status)
200    {
201        unsigned long flags;
202
203        if(!_urbd)
204        {
205            IFX_ERROR("%s: invalid urbd\n",__func__);
206            return;
207        }
208        if (!_urbd->epqh)
209        {
210            IFX_ERROR("%s: invalid epqh\n",__func__);
211            return;
212        }
213
214        local_irq_save(flags);
215        LOCK_URBD_LIST(_urbd->epqh);
216        #ifdef __DEBUG__
217            if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB))
218            {
219                IFX_PRINT("%s: ehqh %p _urbd %p, urb %p,"
220                          " device %d, ep %d %s/%s, status=%d\n",
221                      __func__,_urbd->epqh,
222                      _urbd,_urbd->urb,
223                      (_urbd->urb)?usb_pipedevice(_urbd->urb->pipe):-1,
224                      (_urbd->urb)?usb_pipeendpoint(_urbd->urb->pipe):-1,
225                      (_urbd->urb)?(usb_pipein(_urbd->urb->pipe) ? "IN" : "OUT"):"--",
226                      (_urbd->is_in) ? "IN" : "OUT",
227                       _status);
228                if ((_urbd->urb)&& _urbd->epqh->ep_type == IFXUSB_EP_TYPE_ISOC)
229                {
230                    int i;
231                    for (i = 0; i < _urbd->urb->number_of_packets; i++)
232                        IFX_PRINT(" ISO Desc %d status: %d\n", i, _urbd->urb->iso_frame_desc[i].status);
233                }
234            }
235        #endif
236        _urbd->status = _status;
237
238        if(_urbd->phase!=URBD_FINISHING)
239        {
240            if(_urbd->phase!=URBD_DEQUEUEING && _urbd->phase!=URBD_COMPLETING)
241                printk(KERN_INFO "Warning: %s() Strange URBD PHASE %d\n",__func__,_urbd->phase);
242            if(_urbd->urb)
243            {
244                if( _urbd->status == 0
245                   && _urbd->phase==URBD_COMPLETING
246                   && in_irq())
247                {
248                    list_move_tail(&_urbd->ql,&_urbd->epqh->release_list);
249                    if(!_urbd->epqh->complete_urb_sub.func)
250                    {
251                        _urbd->epqh->complete_urb_sub.next = NULL;
252                        _urbd->epqh->complete_urb_sub.state = 0;
253                        atomic_set( &_urbd->epqh->complete_urb_sub.count, 0);
254                        _urbd->epqh->complete_urb_sub.func = ifxhcd_complete_urb_func;
255                        _urbd->epqh->complete_urb_sub.data = (unsigned long)_urbd->epqh;
256                    }
257                    tasklet_schedule(&_urbd->epqh->complete_urb_sub);
258                }
259                else
260                {
261                    _urbd->phase=URBD_FINISHING;
262                    ifxhcd_complete_urb_sub(_urbd);
263                }
264                UNLOCK_URBD_LIST(_urbd->epqh);
265            }
266            else
267            {
268                UNLOCK_URBD_LIST(_urbd->epqh);
269                kfree(_urbd);
270            }
271        }
272        else
273        {
274            printk(KERN_INFO "Warning: %s() Double Completing \n",__func__);
275            UNLOCK_URBD_LIST(_urbd->epqh);
276        }
277        
278        local_irq_restore (flags);
279    }
280#else
281    static void ifxhcd_complete_urb_func(unsigned long data)
282    {
283        unsigned long flags;
284        ifxhcd_urbd_t *urbd;
285
286        urbd=((ifxhcd_urbd_t *)data);
287
288    // local_irq_save(flags);
289        if (!urbd)
290            IFX_ERROR("%s: invalid urbd\n",__func__);
291        else if (!urbd->epqh)
292            IFX_ERROR("%s: invalid epqd\n",__func__);
293        else
294        {
295            local_irq_save(flags);
296            LOCK_URBD_LIST(urbd->epqh);
297            ifxhcd_complete_urb_sub(urbd);
298            UNLOCK_URBD_LIST(urbd->epqh);
299            local_irq_restore (flags);
300        }
301    // local_irq_restore (flags);
302    }
303
304
305    /*!
306     \brief Sets the final status of an URB and returns it to the device driver. Any
307      required cleanup of the URB is performed.
308     */
309    void ifxhcd_complete_urb(ifxhcd_hcd_t *_ifxhcd, ifxhcd_urbd_t *_urbd, int _status)
310    {
311        unsigned long flags;
312
313        if(!_urbd)
314        {
315            IFX_ERROR("%s: invalid urbd\n",__func__);
316            return;
317        }
318        if (!_urbd->epqh)
319        {
320            IFX_ERROR("%s: invalid epqh\n",__func__);
321            return;
322        }
323
324        local_irq_save(flags);
325        LOCK_URBD_LIST(_urbd->epqh);
326        #ifdef __DEBUG__
327            if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB))
328            {
329                IFX_PRINT("%s: ehqh %p _urbd %p, urb %p, device %d, ep %d %s/%s, status=%d\n",
330                      __func__,_urbd->epqh, _urbd,_urbd->urb,
331                      (_urbd->urb)?usb_pipedevice(_urbd->urb->pipe):-1,
332                      (_urbd->urb)?usb_pipeendpoint(_urbd->urb->pipe):-1,
333                      (_urbd->urb)?(usb_pipein(_urbd->urb->pipe) ? "IN" : "OUT"):"--",
334                      (_urbd->is_in) ? "IN" : "OUT",
335                       _status);
336                if ((_urbd->urb)&& _urbd->epqh->ep_type == IFXUSB_EP_TYPE_ISOC)
337                {
338                    int i;
339                    for (i = 0; i < _urbd->urb->number_of_packets; i++)
340                        IFX_PRINT(" ISO Desc %d status: %d\n", i, _urbd->urb->iso_frame_desc[i].status);
341                }
342            }
343        #endif
344        _urbd->status = _status;
345
346        if(_urbd->phase!=URBD_FINISHING)
347        {
348            if(_urbd->phase!=URBD_DEQUEUEING && _urbd->phase!=URBD_COMPLETING)
349                printk(KERN_INFO "Warning: %s() Strange URBD PHASE %d\n",__func__,_urbd->phase);
350            if(_urbd->urb)
351            {
352                if( _urbd->status == 0
353                   && _urbd->phase==URBD_COMPLETING
354                   && in_irq())
355                {
356                    if(_urbd->complete_urb_sub.func)
357                        printk(KERN_INFO "Warning: %s() URBD Tasklet is on already\n",__func__);
358                    _urbd->phase=URBD_FINISHING;
359                    _urbd->complete_urb_sub.next = NULL;
360                    _urbd->complete_urb_sub.state = 0;
361                    atomic_set( &_urbd->complete_urb_sub.count, 0);
362                    _urbd->complete_urb_sub.func = ifxhcd_complete_urb_func;
363                    _urbd->complete_urb_sub.data = (unsigned long)_urbd;
364                    tasklet_schedule(&_urbd->complete_urb_sub);
365                }
366                else
367                {
368                    _urbd->phase=URBD_FINISHING;
369                    ifxhcd_complete_urb_sub(_urbd);
370                }
371            }
372            else
373                kfree(_urbd);
374        }
375        else
376            printk(KERN_INFO "Warning: %s() Double Completing \n",__func__);
377        UNLOCK_URBD_LIST(_urbd->epqh);
378        local_irq_restore (flags);
379    }
380#endif
381
382/*!
383 \brief Processes all the URBs in a single EPQHs. Completes them with
384        status and frees the URBD.
385 */
386static
387void kill_all_urbs_in_epqh(ifxhcd_hcd_t *_ifxhcd, ifxhcd_epqh_t *_epqh, int _status)
388{
389    struct list_head *item;
390    struct list_head *next;
391    ifxhcd_urbd_t *urbd;
392
393    if(!_epqh)
394        return;
395
396    IFX_DEBUGPL(DBG_HCDV, "%s %p\n",__func__,_epqh);
397    LOCK_URBD_LIST(_epqh);
398    list_for_each(item, &_epqh->urbd_list)
399    {
400        urbd = list_entry(item, ifxhcd_urbd_t, ql);
401        if( urbd->phase==URBD_IDLE
402           || urbd->phase==URBD_ACTIVE
403// || urbd->phase==URBD_STARTING
404          )
405            urbd->phase=URBD_DEQUEUEING;
406    }
407    list_for_each_safe(item, next, &_epqh->urbd_list)
408    {
409        urbd = list_entry(item, ifxhcd_urbd_t, ql);
410        if(urbd->phase==URBD_DEQUEUEING)
411        {
412            urbd->urb->status = _status;
413            urbd->phase = URBD_FINISHING;
414            ifxhcd_complete_urb_sub(urbd);
415        }
416        else if( urbd->phase==URBD_STARTED
417                || urbd->phase==URBD_STARTING
418// || urbd->phase==URBD_ACTIVE
419               )
420        {
421            if(ifxhcd_hc_halt(&_ifxhcd->core_if, _epqh->hc, HC_XFER_URB_DEQUEUE))
422            {
423                urbd->urb->status = _status;
424                urbd->phase=URBD_FINISHING;
425                ifxhcd_complete_urb_sub(urbd);
426            }
427        }
428        else
429            IFX_ERROR("%s: invalid urb phase:%d \n",__func__,urbd->phase);
430    }
431    UNLOCK_URBD_LIST(_epqh);
432    IFX_DEBUGPL(DBG_HCDV, "%s %p finish\n",__func__,_epqh);
433}
434
435
436/*!
437 \brief Free all EPS in one Processes all the URBs in a single list of EPQHs. Completes them with
438        -ETIMEDOUT and frees the URBD.
439 */
440static
441void epqh_list_free_1(ifxhcd_hcd_t *_ifxhcd, struct list_head *_epqh_list)
442{
443    ifxhcd_epqh_t *epqh;
444    struct list_head *item;
445    if (!_ifxhcd)
446        return;
447    if (!_epqh_list)
448        return;
449
450    IFX_DEBUGPL(DBG_HCDV, "%s %p\n",__func__,_epqh_list);
451
452    item = _epqh_list->next;
453    while(item != _epqh_list && item != item->next)
454    {
455        epqh = list_entry(item, ifxhcd_epqh_t, ql);
456        epqh->phase=EPQH_DISABLING;
457        item = item->next;
458        kill_all_urbs_in_epqh(_ifxhcd, epqh, -ETIMEDOUT);
459        #ifdef __STRICT_ORDER__
460        if(list_empty(&epqh->urbd_list) && list_empty(&epqh->release_list))
461        #else
462        if(list_empty(&epqh->urbd_list))
463        #endif
464            ifxhcd_epqh_free(epqh);
465    }
466    IFX_DEBUGPL(DBG_HCDV, "%s %p finish\n",__func__,_epqh_list);
467    /* Ensure there are no URBDs or URBs left. */
468}
469
470static
471void epqh_list_free_2(ifxhcd_hcd_t *_ifxhcd, struct list_head *_epqh_list)
472{
473    ifxhcd_epqh_t *epqh;
474    struct list_head *item;
475    struct list_head *next;
476    if (!_ifxhcd)
477        return;
478    if (!_epqh_list)
479        return;
480
481    IFX_DEBUGPL(DBG_HCDV, "%s %p\n",__func__,_epqh_list);
482    list_for_each_safe(item, next, _epqh_list)
483    {
484        epqh = list_entry(item, ifxhcd_epqh_t, ql);
485        if(item == item->next)
486        {
487            ifxhcd_epqh_free(epqh);
488        }
489        else
490        {
491            uint32_t count=0x80000;
492            #ifdef __STRICT_ORDER__
493            for(;(!list_empty(&epqh->urbd_list) || !list_empty(&epqh->release_list))&& count> 0; count--) udelay(1);
494            #else
495            for(;!list_empty(&epqh->urbd_list) && count> 0; count--) udelay(1);
496            #endif
497            if(!count)
498                IFX_ERROR("%s: unable to clear urbd in epqh \n",__func__);
499            ifxhcd_epqh_free(epqh);
500        }
501    }
502    IFX_DEBUGPL(DBG_HCDV, "%s %p finish\n",__func__,_epqh_list);
503    /* Ensure there are no URBDs or URBs left. */
504}
505
506static
507void epqh_list_free_all_sub(unsigned long data)
508{
509    ifxhcd_hcd_t *ifxhcd;
510
511    ifxhcd=(ifxhcd_hcd_t *)data;
512    epqh_list_free_1(ifxhcd, &ifxhcd->epqh_list_np );
513    epqh_list_free_1(ifxhcd, &ifxhcd->epqh_list_intr);
514    #ifdef __EN_ISOC__
515        epqh_list_free_1(ifxhcd, &ifxhcd->epqh_list_isoc);
516    #endif
517
518    epqh_list_free_2(ifxhcd, &ifxhcd->epqh_list_np );
519    epqh_list_free_2(ifxhcd, &ifxhcd->epqh_list_intr);
520    #ifdef __EN_ISOC__
521        epqh_list_free_2(ifxhcd, &ifxhcd->epqh_list_isoc);
522    #endif
523}
524
525static
526void epqh_list_free_all(ifxhcd_hcd_t *_ifxhcd)
527{
528    _ifxhcd->tasklet_free_epqh_list.next = NULL;
529    _ifxhcd->tasklet_free_epqh_list.state = 0;
530    atomic_set( &_ifxhcd->tasklet_free_epqh_list.count, 0);
531    _ifxhcd->tasklet_free_epqh_list.func=epqh_list_free_all_sub;
532    _ifxhcd->tasklet_free_epqh_list.data = (unsigned long)_ifxhcd;
533    tasklet_schedule(&_ifxhcd->tasklet_free_epqh_list);
534}
535
536
537/*!
538   \brief This function is called to handle the disconnection of host port.
539 */
540int32_t ifxhcd_disconnect(ifxhcd_hcd_t *_ifxhcd)
541{
542    IFX_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, _ifxhcd);
543
544    _ifxhcd->disconnecting=1;
545    /* Set status flags for the hub driver. */
546    _ifxhcd->flags.b.port_connect_status_change = 1;
547    _ifxhcd->flags.b.port_connect_status = 0;
548
549    /*
550     * Shutdown any transfers in process by clearing the Tx FIFO Empty
551     * interrupt mask and status bits and disabling subsequent host
552     * channel interrupts.
553     */
554     {
555        gint_data_t intr = { .d32 = 0 };
556        intr.b.nptxfempty = 1;
557        intr.b.ptxfempty = 1;
558        intr.b.hcintr = 1;
559        ifxusb_mreg (&_ifxhcd->core_if.core_global_regs->gintmsk, intr.d32, 0);
560        ifxusb_mreg (&_ifxhcd->core_if.core_global_regs->gintsts, intr.d32, 0);
561    }
562
563    /* Respond with an error status to all URBs in the schedule. */
564    epqh_list_free_all(_ifxhcd);
565
566    /* Clean up any host channels that were in use. */
567    {
568        int num_channels;
569        ifxhcd_hc_t *channel;
570        ifxusb_hc_regs_t *hc_regs;
571        hcchar_data_t hcchar;
572        int i;
573
574        num_channels = _ifxhcd->core_if.params.host_channels;
575
576        for (i = 0; i < num_channels; i++)
577        {
578            channel = &_ifxhcd->ifxhc[i];
579            hc_regs = _ifxhcd->core_if.hc_regs[i];
580            hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
581            if (hcchar.b.chen)
582                printk(KERN_INFO "Warning: %s() HC still enabled\n",__func__);
583            ifxhcd_hc_cleanup(&_ifxhcd->core_if, channel);
584        }
585    }
586    IFX_DEBUGPL(DBG_HCDV, "%s(%p) finish\n", __func__, _ifxhcd);
587    return 1;
588}
589
590
591/*!
592   \brief Frees secondary storage associated with the ifxhcd_hcd structure contained
593          in the struct usb_hcd field.
594 */
595static void ifxhcd_freeextra(struct usb_hcd *_syshcd)
596{
597    ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd(_syshcd);
598
599    IFX_DEBUGPL(DBG_HCD, "IFXUSB HCD FREE\n");
600
601    /* Free memory for EPQH/URBD lists */
602    epqh_list_free_all(ifxhcd);
603
604    /* Free memory for the host channels. */
605    ifxusb_free_buf_h(ifxhcd->status_buf);
606    return;
607}
608
609/*!
610   \brief Initializes the HCD. This function allocates memory for and initializes the
611  static parts of the usb_hcd and ifxhcd_hcd structures. It also registers the
612  USB bus with the core and calls the hc_driver->start() function. It returns
613  a negative error on failure.
614 */
615int ifxhcd_init(ifxhcd_hcd_t *_ifxhcd)
616{
617    int retval = 0;
618    struct usb_hcd *syshcd = NULL;
619
620    IFX_DEBUGPL(DBG_HCD, "IFX USB HCD INIT\n");
621
622    INIT_EPQH_LIST_ALL(_ifxhcd);
623    INIT_EPQH_LIST(_ifxhcd);
624
625    init_timer(&_ifxhcd->autoprobe_timer);
626    init_timer(&_ifxhcd->host_probe_timer);
627    _ifxhcd->probe_sec = 5;
628    _ifxhcd->autoprobe_sec = 30;
629
630    _ifxhcd->hc_driver.description = _ifxhcd->core_if.core_name;
631    _ifxhcd->hc_driver.product_desc = "IFX USB Controller";
632    //_ifxhcd->hc_driver.hcd_priv_size = sizeof(ifxhcd_hcd_t);
633    _ifxhcd->hc_driver.hcd_priv_size = sizeof(unsigned long);
634    _ifxhcd->hc_driver.irq = ifxhcd_irq;
635    _ifxhcd->hc_driver.flags = HCD_MEMORY | HCD_USB2;
636    _ifxhcd->hc_driver.start = ifxhcd_start;
637    _ifxhcd->hc_driver.stop = ifxhcd_stop;
638    //_ifxhcd->hc_driver.reset =
639    //_ifxhcd->hc_driver.suspend =
640    //_ifxhcd->hc_driver.resume =
641    _ifxhcd->hc_driver.urb_enqueue = ifxhcd_urb_enqueue;
642    _ifxhcd->hc_driver.urb_dequeue = ifxhcd_urb_dequeue;
643    _ifxhcd->hc_driver.endpoint_disable = ifxhcd_endpoint_disable;
644    _ifxhcd->hc_driver.get_frame_number = ifxhcd_get_frame_number;
645    _ifxhcd->hc_driver.hub_status_data = ifxhcd_hub_status_data;
646    _ifxhcd->hc_driver.hub_control = ifxhcd_hub_control;
647    //_ifxhcd->hc_driver.hub_suspend =
648    //_ifxhcd->hc_driver.hub_resume =
649    _ifxhcd->pkt_remaining_reload_hs=PKT_REMAINING_RELOAD_HS;
650    _ifxhcd->pkt_remaining_reload_fs=PKT_REMAINING_RELOAD_FS;
651    _ifxhcd->pkt_remaining_reload_ls=PKT_REMAINING_RELOAD_LS;
652    _ifxhcd->pkt_count_limit_bo =8;
653    _ifxhcd->pkt_count_limit_bi =8;
654
655    /* Allocate memory for and initialize the base HCD and */
656    //syshcd = usb_create_hcd(&_ifxhcd->hc_driver, _ifxhcd->dev, _ifxhcd->dev->bus_id);
657    syshcd = usb_create_hcd(&_ifxhcd->hc_driver, _ifxhcd->dev, _ifxhcd->core_if.core_name);
658
659    if (syshcd == NULL)
660    {
661        retval = -ENOMEM;
662        goto error1;
663    }
664
665    syshcd->rsrc_start = (unsigned long)_ifxhcd->core_if.core_global_regs;
666    syshcd->regs = (void *)_ifxhcd->core_if.core_global_regs;
667    syshcd->self.otg_port = 0;
668
669    //*((unsigned long *)(&(syshcd->hcd_priv)))=(unsigned long)_ifxhcd;
670    //*((unsigned long *)(&(syshcd->hcd_priv[0])))=(unsigned long)_ifxhcd;
671    syshcd->hcd_priv[0]=(unsigned long)_ifxhcd;
672    _ifxhcd->syshcd=syshcd;
673    INIT_LIST_HEAD(&_ifxhcd->epqh_list_all );
674    INIT_LIST_HEAD(&_ifxhcd->epqh_list_np );
675    INIT_LIST_HEAD(&_ifxhcd->epqh_list_intr );
676    #ifdef __EN_ISOC__
677        INIT_LIST_HEAD(&_ifxhcd->epqh_list_isoc);
678    #endif
679
680    /*
681     * Create a host channel descriptor for each host channel implemented
682     * in the controller. Initialize the channel descriptor array.
683     */
684    {
685        int num_channels = _ifxhcd->core_if.params.host_channels;
686        int i;
687        for (i = 0; i < num_channels; i++)
688        {
689            _ifxhcd->ifxhc[i].hc_num = i;
690            IFX_DEBUGPL(DBG_HCDV, "HCD Added channel #%d\n", i);
691        }
692    }
693
694    /* Set device flags indicating whether the HCD supports DMA. */
695    if(_ifxhcd->dev->dma_mask)
696        *(_ifxhcd->dev->dma_mask) = ~0;
697    _ifxhcd->dev->coherent_dma_mask = ~0;
698
699    /*
700     * Finish generic HCD initialization and start the HCD. This function
701     * allocates the DMA buffer pool, registers the USB bus, requests the
702     * IRQ line, and calls ifxusb_hcd_start method.
703     */
704    retval = usb_add_hcd(syshcd, _ifxhcd->core_if.irq, 0
705                                               |IRQF_DISABLED
706                                               |IRQF_SHARED
707                               );
708    if (retval < 0)
709        goto error2;
710
711    /*
712     * Allocate space for storing data on status transactions. Normally no
713     * data is sent, but this space acts as a bit bucket. This must be
714     * done after usb_add_hcd since that function allocates the DMA buffer
715     * pool.
716     */
717    _ifxhcd->status_buf = ifxusb_alloc_buf_h(IFXHCD_STATUS_BUF_SIZE, 1);
718
719    if (_ifxhcd->status_buf)
720    {
721        IFX_DEBUGPL(DBG_HCD, "IFX USB HCD Initialized, bus=%s, usbbus=%d\n", _ifxhcd->core_if.core_name, syshcd->self.busnum);
722        return 0;
723    }
724    IFX_ERROR("%s: status_buf allocation failed\n", __func__);
725
726    /* Error conditions */
727    usb_remove_hcd(syshcd);
728error2:
729    ifxhcd_freeextra(syshcd);
730    usb_put_hcd(syshcd);
731error1:
732    return retval;
733}
734
735/*!
736   \brief Removes the HCD.
737  Frees memory and resources associated with the HCD and deregisters the bus.
738 */
739void ifxhcd_remove(ifxhcd_hcd_t *_ifxhcd)
740{
741    struct usb_hcd *syshcd = ifxhcd_to_syshcd(_ifxhcd);
742
743    IFX_DEBUGPL(DBG_HCD, "IFX USB HCD REMOVE\n");
744
745    /* Turn off all interrupts */
746    ifxusb_wreg (&_ifxhcd->core_if.core_global_regs->gintmsk, 0);
747    ifxusb_mreg (&_ifxhcd->core_if.core_global_regs->gahbcfg, 1, 0);
748
749    usb_remove_hcd(syshcd);
750    ifxhcd_freeextra(syshcd);
751    usb_put_hcd(syshcd);
752
753    return;
754}
755
756
757/* =========================================================================
758 * Linux HC Driver Functions
759 * ========================================================================= */
760
761/*!
762   \brief Initializes the IFXUSB controller and its root hub and prepares it for host
763 mode operation. Activates the root port. Returns 0 on success and a negative
764 error code on failure.
765 Called by USB stack.
766 */
767int ifxhcd_start(struct usb_hcd *_syshcd)
768{
769    ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd (_syshcd);
770    ifxusb_core_if_t *core_if = &ifxhcd->core_if;
771    struct usb_bus *bus;
772
773    IFX_DEBUGPL(DBG_HCD, "IFX USB HCD START\n");
774
775    bus = hcd_to_bus(_syshcd);
776
777    /* Initialize the bus state. */
778    _syshcd->state = HC_STATE_RUNNING;
779
780    /* Initialize and connect root hub if one is not already attached */
781    if (bus->root_hub)
782    {
783        IFX_DEBUGPL(DBG_HCD, "IFX USB HCD Has Root Hub\n");
784        /* Inform the HUB driver to resume. */
785        usb_hcd_resume_root_hub(_syshcd);
786    }
787
788    ifxhcd->flags.d32 = 0;
789
790    /* Put all channels in the free channel list and clean up channel states.*/
791    {
792        int num_channels = ifxhcd->core_if.params.host_channels;
793        int i;
794        for (i = 0; i < num_channels; i++)
795        {
796            ifxhcd_hc_t *channel;
797            channel = &ifxhcd->ifxhc[i];
798            ifxhcd_hc_cleanup(&ifxhcd->core_if, channel);
799        }
800    }
801    /* Initialize the USB core for host mode operation. */
802
803    ifxusb_host_enable_interrupts(core_if);
804    ifxusb_enable_global_interrupts_h(core_if);
805    ifxusb_phy_power_on_h (core_if);
806
807    ifxusb_vbus_init(core_if);
808
809    /* Turn on the vbus power. */
810    {
811        hprt0_data_t hprt0;
812        hprt0.d32 = ifxusb_read_hprt0(core_if);
813
814        IFX_PRINT("Init: Power Port (%d)\n", hprt0.b.prtpwr);
815        if (hprt0.b.prtpwr == 0 )
816        {
817            hprt0.b.prtpwr = 1;
818            ifxusb_wreg(core_if->hprt0, hprt0.d32);
819            ifxusb_vbus_on(core_if);
820        }
821    }
822    return 0;
823}
824
825/*!
826   \brief Halts the IFXUSB host mode operations in a clean manner. USB transfers are
827 stopped.
828 */
829    #if defined(__IS_AR10__)
830void ifxusb_oc_int_free(int port);
831    #else
832void ifxusb_oc_int_free(void);
833    #endif
834 
835void ifxhcd_stop(struct usb_hcd *_syshcd)
836{
837    ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd(_syshcd);
838    hprt0_data_t hprt0 = { .d32=0 };
839
840    IFX_DEBUGPL(DBG_HCD, "IFX USB HCD STOP\n");
841
842    /* Turn off all interrupts. */
843    ifxusb_disable_global_interrupts_h(&ifxhcd->core_if );
844    ifxusb_host_disable_interrupts(&ifxhcd->core_if );
845
846    /*
847     * The root hub should be disconnected before this function is called.
848     * The disconnect will clear the URBD lists (via ..._hcd_urb_dequeue)
849     * and the EPQH lists (via ..._hcd_endpoint_disable).
850     */
851
852    /* Turn off the vbus power */
853    IFX_PRINT("PortPower off\n");
854
855    ifxusb_vbus_off(&ifxhcd->core_if );
856    
857    
858    #if defined(__IS_AR10__)
859        ifxusb_oc_int_free(ifxhcd->core_if.core_no);
860    #else
861        ifxusb_oc_int_free();
862    #endif
863    
864
865    ifxusb_vbus_free(&ifxhcd->core_if );
866    hprt0.b.prtpwr = 0;
867    ifxusb_wreg(ifxhcd->core_if.hprt0, hprt0.d32);
868    return;
869}
870
871/*!
872   \brief Returns the current frame number
873 */
874int ifxhcd_get_frame_number(struct usb_hcd *_syshcd)
875{
876    ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd(_syshcd);
877    hfnum_data_t hfnum;
878
879    hfnum.d32 = ifxusb_rreg(&ifxhcd->core_if.host_global_regs->hfnum);
880
881    return hfnum.b.frnum;
882}
883
884/*!
885   \brief Starts processing a USB transfer request specified by a USB Request Block
886  (URB). mem_flags indicates the type of memory allocation to use while
887  processing this URB.
888 */
889int ifxhcd_urb_enqueue( struct usb_hcd *_syshcd,
890#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
891                        struct usb_host_endpoint *_sysep,
892#endif
893                        struct urb *_urb,
894                        gfp_t _mem_flags)
895{
896    ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd (_syshcd);
897    ifxhcd_epqh_t *epqh = NULL;
898
899    #ifdef __DEBUG__
900        if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB))
901            dump_urb_info(_urb, "ifxusb_hcd_urb_enqueue");
902    #endif //__DEBUG__
903
904    if (!ifxhcd->flags.b.port_connect_status) /* No longer connected. */
905        return -ENODEV;
906
907    #if !defined(__EN_ISOC__)
908        if(usb_pipetype(_urb->pipe) == PIPE_ISOCHRONOUS)
909        {
910            IFX_ERROR("ISOC transfer not supported!!!\n");
911            return -ENODEV;
912        }
913    #endif
914
915    if(_urb->hcpriv)
916    {
917        IFX_WARN("%s() Previous urb->hcpriv exist %p\n",__func__,_urb->hcpriv);
918    #if 1
919        return -ENOSPC;
920    #endif
921    }
922
923    epqh=ifxhcd_urbd_create (ifxhcd,_urb);
924    if (!epqh)
925    {
926        IFX_ERROR("IFXUSB HCD URB Enqueue failed creating URBD\n");
927        return -ENOSPC;
928    }
929    if(epqh->phase==EPQH_DISABLING )
930    {
931        IFX_ERROR("Enqueue to a DISABLING EP!!!\n");
932        return -ENODEV;
933    }
934
935    #ifdef __DYN_SOF_INTR__
936        ifxhcd->dyn_sof_count = DYN_SOF_COUNT_DEF;
937    #endif
938    //enable_sof(ifxhcd);
939    {
940        gint_data_t gintsts;
941        gintsts.d32=0;
942        gintsts.b.sofintr = 1;
943        ifxusb_mreg(&ifxhcd->core_if.core_global_regs->gintmsk, 0,gintsts.d32);
944    }
945
946    if(epqh->phase==EPQH_IDLE || epqh->phase==EPQH_STDBY )
947    {
948        epqh->phase=EPQH_READY;
949        #ifdef __EPQD_DESTROY_TIMEOUT__
950            del_timer(&epqh->destroy_timer);
951        #endif
952    }
953    select_eps(ifxhcd);
954    return 0;
955}
956
957/*!
958   \brief Aborts/cancels a USB transfer request. Always returns 0 to indicate
959  success.
960 */
961#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
962int ifxhcd_urb_dequeue(struct usb_hcd *_syshcd, struct urb *_urb)
963#else
964int ifxhcd_urb_dequeue(struct usb_hcd *_syshcd, struct urb *_urb, int status)
965#endif
966{
967    ifxhcd_hcd_t *ifxhcd;
968    struct usb_host_endpoint *sysep;
969    ifxhcd_urbd_t *urbd;
970    ifxhcd_epqh_t *epqh;
971
972    IFX_DEBUGPL(DBG_HCD, "IFXUSB HCD URB Dequeue\n");
973    #if !defined(__EN_ISOC__)
974        if(usb_pipetype(_urb->pipe) == PIPE_ISOCHRONOUS)
975            return 0;
976    #endif
977
978    ifxhcd = syshcd_to_ifxhcd(_syshcd);
979
980    urbd = (ifxhcd_urbd_t *) _urb->hcpriv;
981    if(!urbd)
982    {
983        #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
984            _urb->status=-ETIMEDOUT;
985            usb_hcd_giveback_urb(_syshcd, _urb);
986        #else
987// usb_hcd_giveback_urb(_syshcd, _urb,-ETIMEDOUT);
988            usb_hcd_giveback_urb(_syshcd, _urb,status);
989        #endif
990        return 0;
991    }
992
993    sysep = ifxhcd_urb_to_endpoint(_urb);
994    if(sysep)
995    {
996        LOCK_EPQH_LIST_ALL(ifxhcd);
997        epqh = sysep_to_epqh(ifxhcd,sysep);
998        UNLOCK_EPQH_LIST_ALL(ifxhcd);
999        if(epqh!=urbd->epqh)
1000            IFX_ERROR("%s inconsistant epqh %p %p\n",__func__,epqh,urbd->epqh);
1001    }
1002    else
1003        epqh = (ifxhcd_epqh_t *) urbd->epqh;
1004    if(!ifxhcd->flags.b.port_connect_status || !epqh)
1005    {
1006        urbd->phase=URBD_DEQUEUEING;
1007        ifxhcd_complete_urb(ifxhcd, urbd, -ENODEV);
1008    }
1009    else
1010    {
1011        LOCK_URBD_LIST(epqh);
1012        if( urbd->phase==URBD_IDLE
1013           || urbd->phase==URBD_ACTIVE
1014// || urbd->phase==URBD_STARTING
1015           )
1016        {
1017            urbd->phase=URBD_DEQUEUEING;
1018            #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
1019                ifxhcd_complete_urb(ifxhcd, urbd, -ETIMEDOUT);
1020            #else
1021                ifxhcd_complete_urb(ifxhcd, urbd, status);
1022            #endif
1023        }
1024        else if( urbd->phase==URBD_STARTED
1025                || urbd->phase==URBD_STARTING
1026// || urbd->phase==URBD_ACTIVE
1027               )
1028        {
1029            if(ifxhcd_hc_halt(&ifxhcd->core_if, epqh->hc, HC_XFER_URB_DEQUEUE))
1030            {
1031                urbd->phase=URBD_DEQUEUEING;
1032                #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
1033                    ifxhcd_complete_urb(ifxhcd, urbd, -ETIMEDOUT);
1034                #else
1035                    ifxhcd_complete_urb(ifxhcd, urbd, status);
1036                #endif
1037                ifxhcd_epqh_idle(epqh);
1038            }
1039        }
1040        UNLOCK_URBD_LIST(epqh);
1041    }
1042    return 0;
1043}
1044
1045
1046/*!
1047   \brief Frees resources in the IFXUSB controller related to a given endpoint. Also
1048  clears state in the HCD related to the endpoint. Any URBs for the endpoint
1049  must already be dequeued.
1050 */
1051void ifxhcd_endpoint_disable( struct usb_hcd *_syshcd,
1052                              struct usb_host_endpoint *_sysep)
1053{
1054    ifxhcd_hcd_t *ifxhcd;
1055    ifxhcd_epqh_t *epqh;
1056
1057    IFX_DEBUGPL(DBG_HCD, "IFXUSB HCD EP DISABLE: _bEndpointAddress=0x%02x, "
1058        "endpoint=%d\n", _sysep->desc.bEndpointAddress,
1059            ifxhcd_ep_addr_to_endpoint(_sysep->desc.bEndpointAddress));
1060
1061    ifxhcd = syshcd_to_ifxhcd(_syshcd);
1062
1063    LOCK_EPQH_LIST_ALL(ifxhcd);
1064    epqh = sysep_to_epqh(ifxhcd,_sysep);
1065    UNLOCK_EPQH_LIST_ALL(ifxhcd);
1066
1067    if (!epqh)
1068    {
1069        return;
1070    }
1071    else
1072    {
1073        if (epqh->sysep!=_sysep)
1074        {
1075            IFX_ERROR("%s inconsistant sysep %p %p %p\n",__func__,epqh,epqh->sysep,_sysep);
1076            return;
1077        }
1078
1079        epqh->phase=EPQH_DISABLING;
1080        kill_all_urbs_in_epqh(ifxhcd, epqh, -ETIMEDOUT);
1081        {
1082            uint32_t count=0x80000;
1083            for(;!list_empty(&epqh->urbd_list) && count> 0; count--) udelay(1);
1084            if(!count)
1085                IFX_ERROR("%s: unable to clear urbd in epqh \n",__func__);
1086        }
1087        ifxhcd_epqh_free(epqh);
1088    }
1089    IFX_DEBUGPL(DBG_HCD, "IFXUSB HCD EP DISABLE: done\n");
1090}
1091
1092
1093/*!
1094  \brief Handles host mode interrupts for the IFXUSB controller. Returns IRQ_NONE if
1095 there was no interrupt to handle. Returns IRQ_HANDLED if there was a valid
1096 interrupt.
1097
1098 This function is called by the USB core when an interrupt occurs
1099 */
1100irqreturn_t ifxhcd_irq(struct usb_hcd *_syshcd)
1101{
1102    ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd (_syshcd);
1103    int32_t retval=0;
1104
1105    //mask_and_ack_ifx_irq (ifxhcd->core_if.irq);
1106    retval = ifxhcd_handle_intr(ifxhcd);
1107    return IRQ_RETVAL(retval);
1108}
1109
1110
1111
1112/*!
1113 \brief Creates Status Change bitmap for the root hub and root port. The bitmap is
1114  returned in buf. Bit 0 is the status change indicator for the root hub. Bit 1
1115  is the status change indicator for the single root port. Returns 1 if either
1116  change indicator is 1, otherwise returns 0.
1117 */
1118int ifxhcd_hub_status_data(struct usb_hcd *_syshcd, char *_buf)
1119{
1120    ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd (_syshcd);
1121
1122    _buf[0] = 0;
1123    _buf[0] |= (ifxhcd->flags.b.port_connect_status_change ||
1124                ifxhcd->flags.b.port_reset_change ||
1125                ifxhcd->flags.b.port_enable_change ||
1126                ifxhcd->flags.b.port_suspend_change ||
1127                ifxhcd->flags.b.port_over_current_change) << 1;
1128
1129    #ifdef __DEBUG__
1130        if (_buf[0])
1131        {
1132            IFX_DEBUGPL(DBG_HCD, "IFXUSB HCD HUB STATUS DATA:"
1133                    " Root port status changed\n");
1134            IFX_DEBUGPL(DBG_HCDV, " port_connect_status_change: %d\n",
1135                    ifxhcd->flags.b.port_connect_status_change);
1136            IFX_DEBUGPL(DBG_HCDV, " port_reset_change: %d\n",
1137                    ifxhcd->flags.b.port_reset_change);
1138            IFX_DEBUGPL(DBG_HCDV, " port_enable_change: %d\n",
1139                    ifxhcd->flags.b.port_enable_change);
1140            IFX_DEBUGPL(DBG_HCDV, " port_suspend_change: %d\n",
1141                    ifxhcd->flags.b.port_suspend_change);
1142            IFX_DEBUGPL(DBG_HCDV, " port_over_current_change: %d\n",
1143                    ifxhcd->flags.b.port_over_current_change);
1144            {
1145                hprt0_data_t hprt0;
1146                hprt0.d32 = ifxusb_rreg(ifxhcd->core_if.hprt0);
1147                IFX_DEBUGPL(DBG_HCDV, " port reg :%08X\n",hprt0.d32);
1148                IFX_DEBUGPL(DBG_HCDV, " port reg :connect: %d/%d\n",hprt0.b.prtconnsts,hprt0.b.prtconndet);
1149                IFX_DEBUGPL(DBG_HCDV, " port reg :enable: %d/%d\n",hprt0.b.prtena,hprt0.b.prtenchng);
1150                IFX_DEBUGPL(DBG_HCDV, " port reg :OC: %d/%d\n",hprt0.b.prtovrcurract,hprt0.b.prtovrcurrchng);
1151                IFX_DEBUGPL(DBG_HCDV, " port reg :rsume/suspend/reset: %d/%d/%d\n",hprt0.b.prtres,hprt0.b.prtsusp,hprt0.b.prtrst);
1152                IFX_DEBUGPL(DBG_HCDV, " port reg :port power: %d/\n",hprt0.b.prtpwr);
1153                IFX_DEBUGPL(DBG_HCDV, " port reg :speed: %d/\n",hprt0.b.prtspd);
1154            }
1155        }
1156    #endif //__DEBUG__
1157    return (_buf[0] != 0);
1158}
1159
1160#ifdef __WITH_HS_ELECT_TST__
1161    extern void do_setup(ifxusb_core_if_t *_core_if) ;
1162    extern void do_in_ack(ifxusb_core_if_t *_core_if);
1163#endif //__WITH_HS_ELECT_TST__
1164
1165/*!
1166 \brief Handles hub class-specific requests.
1167 */
1168int ifxhcd_hub_control( struct usb_hcd *_syshcd,
1169                        u16 _typeReq,
1170                        u16 _wValue,
1171                        u16 _wIndex,
1172                        char *_buf,
1173                        u16 _wLength)
1174{
1175    int retval = 0;
1176    ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd (_syshcd);
1177    ifxusb_core_if_t *core_if = &ifxhcd->core_if;
1178    struct usb_hub_descriptor *desc;
1179    hprt0_data_t hprt0 = {.d32 = 0};
1180
1181    uint32_t port_status;
1182
1183    switch (_typeReq)
1184    {
1185        case ClearHubFeature:
1186            IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1187                     "ClearHubFeature 0x%x\n", _wValue);
1188            switch (_wValue)
1189            {
1190                case C_HUB_LOCAL_POWER:
1191                case C_HUB_OVER_CURRENT:
1192                    /* Nothing required here */
1193                    break;
1194                default:
1195                    retval = -EINVAL;
1196                    IFX_ERROR ("IFXUSB HCD - "
1197                           "ClearHubFeature request %xh unknown\n", _wValue);
1198            }
1199            break;
1200        case ClearPortFeature:
1201            if (!_wIndex || _wIndex > 1)
1202                goto error;
1203
1204            switch (_wValue)
1205            {
1206                case USB_PORT_FEAT_ENABLE:
1207                    IFX_DEBUGPL (DBG_ANY, "IFXUSB HCD HUB CONTROL - "
1208                             "ClearPortFeature USB_PORT_FEAT_ENABLE\n");
1209                    hprt0.d32 = ifxusb_read_hprt0 (core_if);
1210                    hprt0.b.prtena = 1;
1211                    ifxusb_wreg(core_if->hprt0, hprt0.d32);
1212                    break;
1213                case USB_PORT_FEAT_SUSPEND:
1214                    IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1215                             "ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
1216                    hprt0.d32 = ifxusb_read_hprt0 (core_if);
1217                    hprt0.b.prtres = 1;
1218                    ifxusb_wreg(core_if->hprt0, hprt0.d32);
1219                    /* Clear Resume bit */
1220                    mdelay (100);
1221                    hprt0.b.prtres = 0;
1222                    ifxusb_wreg(core_if->hprt0, hprt0.d32);
1223                    break;
1224                case USB_PORT_FEAT_POWER:
1225                    IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1226                             "ClearPortFeature USB_PORT_FEAT_POWER\n");
1227                    #ifdef __IS_DUAL__
1228                        ifxusb_vbus_off(core_if);
1229                    #else
1230                        ifxusb_vbus_off(core_if);
1231                    #endif
1232                    hprt0.d32 = ifxusb_read_hprt0 (core_if);
1233                    hprt0.b.prtpwr = 0;
1234                    ifxusb_wreg(core_if->hprt0, hprt0.d32);
1235                    break;
1236                case USB_PORT_FEAT_INDICATOR:
1237                    IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1238                             "ClearPortFeature USB_PORT_FEAT_INDICATOR\n");
1239                    /* Port inidicator not supported */
1240                    break;
1241                case USB_PORT_FEAT_C_CONNECTION:
1242                    /* Clears drivers internal connect status change
1243                     * flag */
1244                    IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1245                             "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n");
1246                    ifxhcd->flags.b.port_connect_status_change = 0;
1247                    break;
1248                case USB_PORT_FEAT_C_RESET:
1249                    /* Clears the driver's internal Port Reset Change
1250                     * flag */
1251                    IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1252                             "ClearPortFeature USB_PORT_FEAT_C_RESET\n");
1253                    ifxhcd->flags.b.port_reset_change = 0;
1254                    break;
1255                case USB_PORT_FEAT_C_ENABLE:
1256                    /* Clears the driver's internal Port
1257                     * Enable/Disable Change flag */
1258                    IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1259                             "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n");
1260                    ifxhcd->flags.b.port_enable_change = 0;
1261                    break;
1262                case USB_PORT_FEAT_C_SUSPEND:
1263                    /* Clears the driver's internal Port Suspend
1264                     * Change flag, which is set when resume signaling on
1265                     * the host port is complete */
1266                    IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1267                             "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n");
1268                    ifxhcd->flags.b.port_suspend_change = 0;
1269                    break;
1270                case USB_PORT_FEAT_C_OVER_CURRENT:
1271                    IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1272                             "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n");
1273                    ifxhcd->flags.b.port_over_current_change = 0;
1274                    break;
1275                default:
1276                    retval = -EINVAL;
1277                    IFX_ERROR ("IFXUSB HCD - "
1278                             "ClearPortFeature request %xh "
1279                             "unknown or unsupported\n", _wValue);
1280            }
1281            break;
1282        case GetHubDescriptor:
1283            IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1284                     "GetHubDescriptor\n");
1285            desc = (struct usb_hub_descriptor *)_buf;
1286            desc->bDescLength = 9;
1287            desc->bDescriptorType = 0x29;
1288            desc->bNbrPorts = 1;
1289            desc->wHubCharacteristics = 0x08;
1290            desc->bPwrOn2PwrGood = 1;
1291            desc->bHubContrCurrent = 0;
1292
1293            desc->u.hs.DeviceRemovable[0] = 0;
1294                desc->u.hs.DeviceRemovable[1] = 1;
1295            /*desc->bitmap[0] = 0;
1296            desc->bitmap[1] = 0xff;*/
1297            break;
1298        case GetHubStatus:
1299            IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1300                     "GetHubStatus\n");
1301            memset (_buf, 0, 4);
1302            break;
1303        case GetPortStatus:
1304            IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1305                     "GetPortStatus\n");
1306            if (!_wIndex || _wIndex > 1)
1307                goto error;
1308            port_status = 0;
1309            if (ifxhcd->flags.b.port_connect_status_change)
1310                port_status |= (1 << USB_PORT_FEAT_C_CONNECTION);
1311            if (ifxhcd->flags.b.port_enable_change)
1312                port_status |= (1 << USB_PORT_FEAT_C_ENABLE);
1313            if (ifxhcd->flags.b.port_suspend_change)
1314                port_status |= (1 << USB_PORT_FEAT_C_SUSPEND);
1315            if (ifxhcd->flags.b.port_reset_change)
1316                port_status |= (1 << USB_PORT_FEAT_C_RESET);
1317            if (ifxhcd->flags.b.port_over_current_change)
1318            {
1319                IFX_ERROR("Device Not Supported\n");
1320                port_status |= (1 << USB_PORT_FEAT_C_OVER_CURRENT);
1321            }
1322            if (!ifxhcd->flags.b.port_connect_status)
1323            {
1324                /*
1325                 * The port is disconnected, which means the core is
1326                 * either in device mode or it soon will be. Just
1327                 * return 0's for the remainder of the port status
1328                 * since the port register can't be read if the core
1329                 * is in device mode.
1330                 */
1331                *((u32 *) _buf) = cpu_to_le32(port_status);
1332                break;
1333            }
1334
1335            hprt0.d32 = ifxusb_rreg(core_if->hprt0);
1336            IFX_DEBUGPL(DBG_HCDV, " HPRT0: 0x%08x\n", hprt0.d32);
1337            if (hprt0.b.prtconnsts)
1338                port_status |= (1 << USB_PORT_FEAT_CONNECTION);
1339            if (hprt0.b.prtena)
1340            {
1341                ifxhcd->disconnecting=0;
1342                port_status |= (1 << USB_PORT_FEAT_ENABLE);
1343            }
1344            if (hprt0.b.prtsusp)
1345                port_status |= (1 << USB_PORT_FEAT_SUSPEND);
1346            if (hprt0.b.prtovrcurract)
1347                port_status |= (1 << USB_PORT_FEAT_OVER_CURRENT);
1348            if (hprt0.b.prtrst)
1349                port_status |= (1 << USB_PORT_FEAT_RESET);
1350            if (hprt0.b.prtpwr)
1351                port_status |= (1 << USB_PORT_FEAT_POWER);
1352            if (hprt0.b.prtspd == IFXUSB_HPRT0_PRTSPD_HIGH_SPEED)
1353                port_status |= USB_PORT_STAT_HIGH_SPEED;
1354            else if (hprt0.b.prtspd == IFXUSB_HPRT0_PRTSPD_LOW_SPEED)
1355                port_status |= USB_PORT_STAT_LOW_SPEED;
1356            if (hprt0.b.prttstctl)
1357                port_status |= (1 << USB_PORT_FEAT_TEST);
1358            /* USB_PORT_FEAT_INDICATOR unsupported always 0 */
1359            *((u32 *) _buf) = cpu_to_le32(port_status);
1360            break;
1361        case SetHubFeature:
1362            IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1363                     "SetHubFeature\n");
1364            /* No HUB features supported */
1365            break;
1366        case SetPortFeature:
1367            if (_wValue != USB_PORT_FEAT_TEST && (!_wIndex || _wIndex > 1))
1368                goto error;
1369            /*
1370             * The port is disconnected, which means the core is
1371             * either in device mode or it soon will be. Just
1372             * return without doing anything since the port
1373             * register can't be written if the core is in device
1374             * mode.
1375             */
1376            if (!ifxhcd->flags.b.port_connect_status)
1377                break;
1378            switch (_wValue)
1379            {
1380                case USB_PORT_FEAT_SUSPEND:
1381                    IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1382                             "SetPortFeature - USB_PORT_FEAT_SUSPEND\n");
1383                    hprt0.d32 = ifxusb_read_hprt0 (core_if);
1384                    hprt0.b.prtsusp = 1;
1385                    ifxusb_wreg(core_if->hprt0, hprt0.d32);
1386                    //IFX_PRINT( "SUSPEND: HPRT0=%0x\n", hprt0.d32);
1387                    /* Suspend the Phy Clock */
1388                    {
1389                        pcgcctl_data_t pcgcctl = {.d32=0};
1390                        pcgcctl.b.stoppclk = 1;
1391                        ifxusb_wreg(core_if->pcgcctl, pcgcctl.d32);
1392                    }
1393                    break;
1394                case USB_PORT_FEAT_POWER:
1395                    IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1396                         "SetPortFeature - USB_PORT_FEAT_POWER\n");
1397                    ifxusb_vbus_on (core_if);
1398                    hprt0.d32 = ifxusb_read_hprt0 (core_if);
1399                    hprt0.b.prtpwr = 1;
1400                    ifxusb_wreg(core_if->hprt0, hprt0.d32);
1401                    break;
1402                case USB_PORT_FEAT_RESET:
1403                    IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1404                             "SetPortFeature - USB_PORT_FEAT_RESET\n");
1405                    hprt0.d32 = ifxusb_read_hprt0 (core_if);
1406                    hprt0.b.prtrst = 1;
1407                    ifxusb_wreg(core_if->hprt0, hprt0.d32);
1408                    /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */
1409                    MDELAY (60);
1410                    hprt0.b.prtrst = 0;
1411                    ifxusb_wreg(core_if->hprt0, hprt0.d32);
1412                    break;
1413            #ifdef __WITH_HS_ELECT_TST__
1414                case USB_PORT_FEAT_TEST:
1415                    {
1416                        uint32_t t;
1417                        gint_data_t gintmsk;
1418                        t = (_wIndex >> 8); /* MSB wIndex USB */
1419                        IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1420                                 "SetPortFeature - USB_PORT_FEAT_TEST %d\n", t);
1421                        warn("USB_PORT_FEAT_TEST %d\n", t);
1422                        if (t < 6)
1423                        {
1424                            hprt0.d32 = ifxusb_read_hprt0 (core_if);
1425                            hprt0.b.prttstctl = t;
1426                            ifxusb_wreg(core_if->hprt0, hprt0.d32);
1427                        }
1428                        else if (t == 6) /* HS_HOST_PORT_SUSPEND_RESUME */
1429                        {
1430                            /* Save current interrupt mask */
1431                            gintmsk.d32 = ifxusb_rreg(&core_if->core_global_regs->gintmsk);
1432
1433                            /* Disable all interrupts while we muck with
1434                             * the hardware directly
1435                             */
1436                            ifxusb_wreg(&core_if->core_global_regs->gintmsk, 0);
1437
1438                            /* 15 second delay per the test spec */
1439                            mdelay(15000);
1440
1441                            /* Drive suspend on the root port */
1442                            hprt0.d32 = ifxusb_read_hprt0 (core_if);
1443                            hprt0.b.prtsusp = 1;
1444                            hprt0.b.prtres = 0;
1445                            ifxusb_wreg(core_if->hprt0, hprt0.d32);
1446
1447                            /* 15 second delay per the test spec */
1448                            mdelay(15000);
1449
1450                            /* Drive resume on the root port */
1451                            hprt0.d32 = ifxusb_read_hprt0 (core_if);
1452                            hprt0.b.prtsusp = 0;
1453                            hprt0.b.prtres = 1;
1454                            ifxusb_wreg(core_if->hprt0, hprt0.d32);
1455                            mdelay(100);
1456
1457                            /* Clear the resume bit */
1458                            hprt0.b.prtres = 0;
1459                            ifxusb_wreg(core_if->hprt0, hprt0.d32);
1460
1461                            /* Restore interrupts */
1462                            ifxusb_wreg(&core_if->core_global_regs->gintmsk, gintmsk.d32);
1463                        }
1464                        else if (t == 7) /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */
1465                        {
1466                            /* Save current interrupt mask */
1467                            gintmsk.d32 = ifxusb_rreg(&core_if->core_global_regs->gintmsk);
1468
1469                            /* Disable all interrupts while we muck with
1470                             * the hardware directly
1471                             */
1472                            ifxusb_wreg(&core_if->core_global_regs->gintmsk, 0);
1473
1474                            /* 15 second delay per the test spec */
1475                            mdelay(15000);
1476
1477                            /* Send the Setup packet */
1478                            do_setup(core_if);
1479
1480                            /* 15 second delay so nothing else happens for awhile */
1481                            mdelay(15000);
1482
1483                            /* Restore interrupts */
1484                            ifxusb_wreg(&core_if->core_global_regs->gintmsk, gintmsk.d32);
1485                        }
1486
1487                        else if (t == 8) /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */
1488                        {
1489                            /* Save current interrupt mask */
1490                            gintmsk.d32 = ifxusb_rreg(&core_if->core_global_regs->gintmsk);
1491
1492                            /* Disable all interrupts while we muck with
1493                             * the hardware directly
1494                             */
1495                            ifxusb_wreg(&core_if->core_global_regs->gintmsk, 0);
1496
1497                            /* Send the Setup packet */
1498                            do_setup(core_if);
1499
1500                            /* 15 second delay so nothing else happens for awhile */
1501                            mdelay(15000);
1502
1503                            /* Send the In and Ack packets */
1504                            do_in_ack(core_if);
1505
1506                            /* 15 second delay so nothing else happens for awhile */
1507                            mdelay(15000);
1508
1509                            /* Restore interrupts */
1510                            ifxusb_wreg(&core_if->core_global_regs->gintmsk, gintmsk.d32);
1511                        }
1512                    }
1513                    break;
1514            #endif //__WITH_HS_ELECT_TST__
1515                case USB_PORT_FEAT_INDICATOR:
1516                    IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
1517                             "SetPortFeature - USB_PORT_FEAT_INDICATOR\n");
1518                    /* Not supported */
1519                    break;
1520                default:
1521                    retval = -EINVAL;
1522                    IFX_ERROR ("IFXUSB HCD - "
1523                           "SetPortFeature request %xh "
1524                           "unknown or unsupported\n", _wValue);
1525            }
1526            break;
1527        default:
1528        error:
1529            retval = -EINVAL;
1530            IFX_WARN ("IFXUSB HCD - "
1531                      "Unknown hub control request type or invalid typeReq: %xh wIndex: %xh wValue: %xh\n",
1532                      _typeReq, _wIndex, _wValue);
1533    }
1534    return retval;
1535}
1536
1537
1538
1539
1540/*!
1541   \brief This function trigger a data transfer for a host channel and
1542  starts the transfer.
1543
1544  For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ
1545  register along with a packet count of 1 and the channel is enabled. This
1546  causes a single PING transaction to occur. Other fields in HCTSIZ are
1547  simply set to 0 since no data transfer occurs in this case.
1548
1549  For a PING transfer in DMA mode, the HCTSIZ register is initialized with
1550  all the information required to perform the subsequent data transfer. In
1551  addition, the Do Ping bit is set in the HCTSIZ register. In this case, the
1552  controller performs the entire PING protocol, then starts the data
1553  transfer.
1554  \param _core_if Pointer of core_if structure
1555  \param _ifxhc Information needed to initialize the host channel. The xfer_len
1556  value may be reduced to accommodate the max widths of the XferSize and
1557  PktCnt fields in the HCTSIZn register. The multi_count value may be changed
1558  to reflect the final xfer_len value.
1559 */
1560void ifxhcd_hc_start(ifxhcd_hcd_t *_ifxhcd, ifxhcd_hc_t *_ifxhc)
1561{
1562    ifxusb_core_if_t *core_if = &_ifxhcd->core_if;
1563    uint32_t max_hc_xfer_size = core_if->params.max_transfer_size;
1564    uint16_t max_hc_pkt_count = core_if->params.max_packet_count;
1565    ifxusb_hc_regs_t *hc_regs = core_if->hc_regs[_ifxhc->hc_num];
1566    hfnum_data_t hfnum;
1567
1568    hprt0_data_t hprt0;
1569
1570    if(_ifxhc->epqh->urbd->phase==URBD_DEQUEUEING)
1571        return;
1572
1573    hprt0.d32 = ifxusb_read_hprt0(core_if);
1574
1575    if(_ifxhcd->pkt_remaining==0)
1576        return;
1577
1578#if 0
1579    if(_ifxhc->phase!=HC_WAITING)
1580        printk(KERN_INFO "%s() line %d: _ifxhc->phase!=HC_WAITING :%d\n",__func__,__LINE__,_ifxhc->phase);
1581    if(_ifxhc->epqh->urbd->phase==URBD_IDLE ) printk(KERN_INFO "%s() line %d: _ifxhc->epqh->urbd->phase==URBD_IDLE\n",__func__,__LINE__);
1582// if(_ifxhc->epqh->urbd->phase==URBD_ACTIVE ) printk(KERN_INFO "%s() line %d: _ifxhc->epqh->urbd->phase==URBD_ACTIVE\n",__func__,__LINE__);
1583    if(_ifxhc->epqh->urbd->phase==URBD_STARTING ) printk(KERN_INFO "%s() line %d: _ifxhc->epqh->urbd->phase==URBD_STARTING\n",__func__,__LINE__);
1584    if(_ifxhc->epqh->urbd->phase==URBD_STARTED ) printk(KERN_INFO "%s() line %d: _ifxhc->epqh->urbd->phase==URBD_STARTED\n",__func__,__LINE__);
1585    if(_ifxhc->epqh->urbd->phase==URBD_COMPLETING) printk(KERN_INFO "%s() line %d: _ifxhc->epqh->urbd->phase==URBD_COMPLETING\n",__func__,__LINE__);
1586    if(_ifxhc->epqh->urbd->phase==URBD_DEQUEUEING) printk(KERN_INFO "%s() line %d: _ifxhc->epqh->urbd->phase==URBD_DEQUEUEING\n",__func__,__LINE__);
1587    if(_ifxhc->epqh->urbd->phase==URBD_FINISHING ) printk(KERN_INFO "%s() line %d: _ifxhc->epqh->urbd->phase==URBD_FINISHING\n",__func__,__LINE__);
1588#endif
1589
1590    if (hprt0.b.prtspd == IFXUSB_HPRT0_PRTSPD_HIGH_SPEED)
1591    {
1592        if (_ifxhc->split)
1593        {
1594            if(max_hc_pkt_count > _ifxhcd->pkt_remaining)
1595                max_hc_pkt_count = _ifxhcd->pkt_remaining;
1596        }
1597        else if(_ifxhc->ep_type == IFXUSB_EP_TYPE_BULK)
1598        {
1599            if( _ifxhc->is_in && _ifxhcd->pkt_count_limit_bi && max_hc_pkt_count > _ifxhcd->pkt_count_limit_bi)
1600                max_hc_pkt_count = _ifxhcd->pkt_count_limit_bi;
1601            if(!_ifxhc->is_in && _ifxhcd->pkt_count_limit_bo && max_hc_pkt_count > _ifxhcd->pkt_count_limit_bo)
1602                max_hc_pkt_count = _ifxhcd->pkt_count_limit_bo;
1603            if(max_hc_pkt_count*8 > _ifxhcd->pkt_remaining)
1604                max_hc_pkt_count = _ifxhcd->pkt_remaining/8;
1605        }
1606        else
1607        {
1608            if(max_hc_pkt_count > _ifxhcd->pkt_remaining)
1609                max_hc_pkt_count = _ifxhcd->pkt_remaining;
1610        }
1611    }
1612    else if (hprt0.b.prtspd == IFXUSB_HPRT0_PRTSPD_LOW_SPEED)
1613    {
1614        if(max_hc_pkt_count > _ifxhcd->pkt_remaining)
1615            max_hc_pkt_count = _ifxhcd->pkt_remaining;
1616    }
1617    else
1618    {
1619        if(max_hc_pkt_count > _ifxhcd->pkt_remaining)
1620            max_hc_pkt_count = _ifxhcd->pkt_remaining;
1621    }
1622
1623    if(max_hc_pkt_count==0)
1624        return;
1625
1626    if(max_hc_pkt_count * _ifxhc->mps < max_hc_xfer_size)
1627        max_hc_xfer_size = max_hc_pkt_count * _ifxhc->mps;
1628
1629    _ifxhc->epqh->urbd->phase=URBD_STARTING;
1630
1631    if(_ifxhc->is_in || _ifxhc->speed != IFXUSB_EP_SPEED_HIGH || _ifxhc->xfer_len==0)
1632        _ifxhc->epqh->do_ping=0;
1633    if(_ifxhc->ep_type == IFXUSB_EP_TYPE_INTR || _ifxhc->ep_type == IFXUSB_EP_TYPE_ISOC)
1634        _ifxhc->epqh->do_ping=0;
1635    if(_ifxhc->ep_type == IFXUSB_EP_TYPE_CTRL && _ifxhc->control_phase != IFXHCD_CONTROL_DATA )
1636        _ifxhc->epqh->do_ping=0;
1637
1638    if (_ifxhc->split > 0)
1639    {
1640        _ifxhc->start_pkt_count = 1;
1641        if(!_ifxhc->is_in && _ifxhc->split>1) // OUT CSPLIT
1642            _ifxhc->xfer_len = 0;
1643        if (_ifxhc->xfer_len > _ifxhc->mps)
1644            _ifxhc->xfer_len = _ifxhc->mps;
1645        if (_ifxhc->xfer_len > 188)
1646            _ifxhc->xfer_len = 188;
1647    }
1648    else if(_ifxhc->is_in)
1649    {
1650        _ifxhc->short_rw = 0;
1651        if (_ifxhc->xfer_len > 0)
1652        {
1653            if (_ifxhc->xfer_len > max_hc_xfer_size)
1654                _ifxhc->xfer_len = max_hc_xfer_size - _ifxhc->mps + 1;
1655            _ifxhc->start_pkt_count = (_ifxhc->xfer_len + _ifxhc->mps - 1) / _ifxhc->mps;
1656            if (_ifxhc->start_pkt_count > max_hc_pkt_count)
1657                _ifxhc->start_pkt_count = max_hc_pkt_count;
1658        }
1659        else /* Need 1 packet for transfer length of 0. */
1660            _ifxhc->start_pkt_count = 1;
1661        _ifxhc->xfer_len = _ifxhc->start_pkt_count * _ifxhc->mps;
1662    }
1663    else //non-split out
1664    {
1665        if (_ifxhc->xfer_len == 0)
1666        {
1667            if(_ifxhc->short_rw==0)
1668                printk(KERN_INFO "Info: %s() line %d: ZLP write without short_rw set! xfer_count:%d/%d \n",__func__,__LINE__,
1669                    _ifxhc->xfer_count,
1670                    _ifxhc->epqh->urbd->xfer_len);
1671            _ifxhc->start_pkt_count = 1;
1672        }
1673        else
1674        {
1675            if (_ifxhc->xfer_len > max_hc_xfer_size)
1676            {
1677                _ifxhc->start_pkt_count = (max_hc_xfer_size / _ifxhc->mps);
1678                _ifxhc->xfer_len = _ifxhc->start_pkt_count * _ifxhc->mps;
1679            }
1680            else
1681            {
1682                _ifxhc->start_pkt_count = (_ifxhc->xfer_len+_ifxhc->mps-1) / _ifxhc->mps;
1683// if(_ifxhc->start_pkt_count * _ifxhc->mps == _ifxhc->xfer_len )
1684// _ifxhc->start_pkt_count += _ifxhc->short_rw;
1685            }
1686        }
1687    }
1688
1689    if (hprt0.b.prtspd == IFXUSB_HPRT0_PRTSPD_HIGH_SPEED)
1690    {
1691        if (_ifxhc->split)
1692        {
1693            if( _ifxhcd->pkt_remaining > _ifxhc->start_pkt_count)
1694                _ifxhcd->pkt_remaining -= _ifxhc->start_pkt_count;
1695            else
1696                _ifxhcd->pkt_remaining = 0;
1697        }
1698        else if(_ifxhc->ep_type == IFXUSB_EP_TYPE_BULK)
1699        {
1700            if( _ifxhcd->pkt_remaining*8 > _ifxhc->start_pkt_count)
1701                _ifxhcd->pkt_remaining -= (_ifxhc->start_pkt_count*8);
1702            else
1703                _ifxhcd->pkt_remaining = 0;
1704        }
1705        else
1706        {
1707            if( _ifxhcd->pkt_remaining > _ifxhc->start_pkt_count)
1708                _ifxhcd->pkt_remaining -= _ifxhc->start_pkt_count;
1709            else
1710                _ifxhcd->pkt_remaining = 0;
1711        }
1712    }
1713    else if (hprt0.b.prtspd == IFXUSB_HPRT0_PRTSPD_LOW_SPEED)
1714    {
1715        if( _ifxhcd->pkt_remaining > _ifxhc->start_pkt_count)
1716            _ifxhcd->pkt_remaining -= _ifxhc->start_pkt_count;
1717        else
1718            _ifxhcd->pkt_remaining = 0;
1719    }
1720    else
1721    {
1722        if( _ifxhcd->pkt_remaining > _ifxhc->start_pkt_count)
1723            _ifxhcd->pkt_remaining -= _ifxhc->start_pkt_count;
1724        else
1725            _ifxhcd->pkt_remaining = 0;
1726    }
1727
1728    #ifdef __EN_ISOC__
1729        if (_ifxhc->ep_type == IFXUSB_EP_TYPE_ISOC)
1730        {
1731            /* Set up the initial PID for the transfer. */
1732            #if 1
1733                _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA0;
1734            #else
1735                if (_ifxhc->speed == IFXUSB_EP_SPEED_HIGH)
1736                {
1737                    if (_ifxhc->is_in)
1738                    {
1739                        if (_ifxhc->multi_count == 1)
1740                            _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA0;
1741                        else if (_ifxhc->multi_count == 2)
1742                            _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA1;
1743                        else
1744                            _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA2;
1745                    }
1746                    else
1747                    {
1748                        if (_ifxhc->multi_count == 1)
1749                            _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA0;
1750                        else
1751                            _ifxhc->data_pid_start = IFXUSB_HC_PID_MDATA;
1752                    }
1753                }
1754                else
1755                    _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA0;
1756            #endif
1757        }
1758    #endif
1759
1760    IFX_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, _ifxhc->hc_num);
1761    {
1762        hctsiz_data_t hctsiz= { .d32=0 };
1763
1764        hctsiz.b.dopng = _ifxhc->epqh->do_ping;
1765        _ifxhc->epqh->do_ping=0;
1766
1767        if(_ifxhc->is_in || _ifxhc->speed != IFXUSB_EP_SPEED_HIGH || _ifxhc->xfer_len==0)
1768            hctsiz.b.dopng = 0;
1769        if(_ifxhc->ep_type == IFXUSB_EP_TYPE_INTR || _ifxhc->ep_type == IFXUSB_EP_TYPE_ISOC)
1770            hctsiz.b.dopng = 0;
1771        if(_ifxhc->ep_type == IFXUSB_EP_TYPE_CTRL && _ifxhc->control_phase != IFXHCD_CONTROL_DATA )
1772            hctsiz.b.dopng = 0;
1773
1774        hctsiz.b.xfersize = _ifxhc->xfer_len;
1775        hctsiz.b.pktcnt = _ifxhc->start_pkt_count;
1776        hctsiz.b.pid = _ifxhc->data_pid_start;
1777        ifxusb_wreg(&hc_regs->hctsiz, hctsiz.d32);
1778
1779        IFX_DEBUGPL(DBG_HCDV, " Xfer Size: %d\n", hctsiz.b.xfersize);
1780        IFX_DEBUGPL(DBG_HCDV, " Num Pkts: %d\n" , hctsiz.b.pktcnt);
1781        IFX_DEBUGPL(DBG_HCDV, " Start PID: %d\n", hctsiz.b.pid);
1782    }
1783    IFX_DEBUGPL(DBG_HCDV, " DMA: 0x%08x\n", (uint32_t)(CPHYSADDR( ((uint32_t)(_ifxhc->xfer_buff))+ _ifxhc->xfer_count )));
1784    ifxusb_wreg(&hc_regs->hcdma, (uint32_t)(CPHYSADDR( ((uint32_t)(_ifxhc->xfer_buff))+ _ifxhc->xfer_count )));
1785
1786    /* Start the split */
1787    if (_ifxhc->split>0)
1788    {
1789        hcsplt_data_t hcsplt;
1790        hcsplt.d32 = ifxusb_rreg (&hc_regs->hcsplt);
1791        hcsplt.b.spltena = 1;
1792        if (_ifxhc->split>1)
1793            hcsplt.b.compsplt = 1;
1794        else
1795            hcsplt.b.compsplt = 0;
1796
1797        #if defined(__EN_ISOC__) && defined(__EN_ISOC_SPLIT__)
1798            if (_ifxhc->ep_type == IFXUSB_EP_TYPE_ISOC)
1799                hcsplt.b.xactpos = _ifxhc->isoc_xact_pos;
1800            else
1801        #endif
1802        hcsplt.b.xactpos = IFXUSB_HCSPLIT_XACTPOS_ALL;// if not ISO
1803        ifxusb_wreg(&hc_regs->hcsplt, hcsplt.d32);
1804        IFX_DEBUGPL(DBG_HCDV, " SPLIT: XACT_POS:0x%08x\n", hcsplt.d32);
1805    }
1806
1807    {
1808        hcchar_data_t hcchar;
1809        hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
1810// hcchar.b.multicnt = _ifxhc->multi_count;
1811        hcchar.b.multicnt = 1;
1812
1813        if (_ifxhc->ep_type == IFXUSB_EP_TYPE_INTR || _ifxhc->ep_type == IFXUSB_EP_TYPE_ISOC)
1814        {
1815            hfnum.d32 = ifxusb_rreg(&core_if->host_global_regs->hfnum);
1816            /* 1 if _next_ frame is odd, 0 if it's even */
1817            hcchar.b.oddfrm = (hfnum.b.frnum & 0x1) ? 0 : 1;
1818        }
1819
1820        #ifdef __DEBUG__
1821            _ifxhc->start_hcchar_val = hcchar.d32;
1822            if (hcchar.b.chdis)
1823                IFX_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n",
1824                     __func__, _ifxhc->hc_num, hcchar.d32);
1825        #endif
1826
1827        /* Set host channel enable after all other setup is complete. */
1828        hcchar.b.chen = 1;
1829        hcchar.b.chdis = 0;
1830        hcchar.b.epdir = _ifxhc->is_in;
1831        _ifxhc->hcchar=hcchar.d32;
1832    }
1833
1834    IFX_DEBUGPL(DBG_HCDV, " HCCHART: 0x%08x\n", _ifxhc->hcchar);
1835
1836    _ifxhc->phase=HC_STARTING;
1837}
1838
1839/*!
1840   \brief Attempts to halt a host channel. This function should only be called
1841  to abort a transfer in DMA mode. Under normal circumstances in DMA mode, the
1842  controller halts the channel when the transfer is complete or a condition
1843  occurs that requires application intervention.
1844
1845  In DMA mode, always sets the Channel Enable and Channel Disable bits of the
1846  HCCHARn register. The controller ensures there is space in the request
1847  queue before submitting the halt request.
1848
1849  Some time may elapse before the core flushes any posted requests for this
1850  host channel and halts. The Channel Halted interrupt handler completes the
1851  deactivation of the host channel.
1852 */
1853int ifxhcd_hc_halt(ifxusb_core_if_t *_core_if,
1854                    ifxhcd_hc_t *_ifxhc,
1855                    ifxhcd_halt_status_e _halt_status)
1856{
1857    hcchar_data_t hcchar;
1858    ifxusb_hc_regs_t *hc_regs;
1859    hc_regs = _core_if->hc_regs[_ifxhc->hc_num];
1860
1861    WARN_ON(_halt_status == HC_XFER_NO_HALT_STATUS);
1862
1863    {
1864        hprt0_data_t hprt0;
1865        hprt0.d32 = ifxusb_rreg(_core_if->hprt0);
1866        if(hprt0.b.prtena == 0)
1867            return -1;
1868    }
1869
1870    if (_halt_status == HC_XFER_URB_DEQUEUE ||
1871        _halt_status == HC_XFER_AHB_ERR)
1872    {
1873        /*
1874         * Disable all channel interrupts except Ch Halted. The URBD
1875         * and EPQH state associated with this transfer has been cleared
1876         * (in the case of URB_DEQUEUE), so the channel needs to be
1877         * shut down carefully to prevent crashes.
1878         */
1879        hcint_data_t hcintmsk;
1880        hcintmsk.d32 = 0;
1881        hcintmsk.b.chhltd = 1;
1882        ifxusb_wreg(&hc_regs->hcintmsk, hcintmsk.d32);
1883
1884        /*
1885         * Make sure no other interrupts besides halt are currently
1886         * pending. Handling another interrupt could cause a crash due
1887         * to the URBD and EPQH state.
1888         */
1889        ifxusb_wreg(&hc_regs->hcint, ~hcintmsk.d32);
1890
1891        /*
1892         * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR
1893         * even if the channel was already halted for some other
1894         * reason.
1895         */
1896        _ifxhc->halt_status = _halt_status;
1897    }
1898
1899    hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
1900    if (hcchar.b.chen == 0)
1901    {
1902        /*
1903         * The channel is either already halted or it hasn't
1904         * started yet. In DMA mode, the transfer may halt if
1905         * it finishes normally or a condition occurs that
1906         * requires driver intervention. Don't want to halt
1907         * the channel again. In either Slave or DMA mode,
1908         * it's possible that the transfer has been assigned
1909         * to a channel, but not started yet when an URB is
1910         * dequeued. Don't want to halt a channel that hasn't
1911         * started yet.
1912         */
1913        _ifxhc->phase=HC_IDLE;
1914        return -1;
1915    }
1916
1917    if (_ifxhc->phase==HC_STOPPING)
1918    {
1919        /*
1920         * A halt has already been issued for this channel. This might
1921         * happen when a transfer is aborted by a higher level in
1922         * the stack.
1923         */
1924        #ifdef __DEBUG__
1925            IFX_PRINT("*** %s: Channel %d, double halt a channel***\n",
1926                  __func__, _ifxhc->hc_num);
1927        #endif
1928        return 0;
1929    }
1930    hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
1931    hcchar.b.chen = 1;
1932    hcchar.b.chdis = 1;
1933
1934    ifxusb_wreg(&hc_regs->hcchar, hcchar.d32);
1935
1936    _ifxhc->halt_status = _halt_status;
1937    _ifxhc->phase=HC_STOPPING;
1938
1939    IFX_DEBUGPL(DBG_HCDV, "%s: Channel %d\n" , __func__, _ifxhc->hc_num);
1940    IFX_DEBUGPL(DBG_HCDV, " hcchar: 0x%08x\n" , hcchar.d32);
1941    IFX_DEBUGPL(DBG_HCDV, " halt_status: %d\n" , _ifxhc->halt_status);
1942
1943    return 0;
1944}
1945
1946/*!
1947   \brief Clears a host channel.
1948 */
1949void ifxhcd_hc_cleanup(ifxusb_core_if_t *_core_if, ifxhcd_hc_t *_ifxhc)
1950{
1951    ifxusb_hc_regs_t *hc_regs;
1952
1953    _ifxhc->phase=HC_IDLE;
1954    _ifxhc->epqh=0;
1955
1956    /*
1957     * Clear channel interrupt enables and any unhandled channel interrupt
1958     * conditions.
1959     */
1960    hc_regs = _core_if->hc_regs[_ifxhc->hc_num];
1961    ifxusb_wreg(&hc_regs->hcintmsk, 0);
1962    ifxusb_wreg(&hc_regs->hcint, 0xFFFFFFFF);
1963
1964    #ifdef __DEBUG__
1965        {
1966            hcchar_data_t hcchar;
1967            hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
1968            if (hcchar.b.chdis)
1969                IFX_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n", __func__, _ifxhc->hc_num, hcchar.d32);
1970        }
1971    #endif
1972}
1973
1974
1975
1976
1977
1978#ifdef __DEBUG__
1979    static void dump_urb_info(struct urb *_urb, char* _fn_name)
1980    {
1981        IFX_PRINT("%s, urb %p\n" , _fn_name, _urb);
1982        IFX_PRINT(" Device address: %d\n", usb_pipedevice(_urb->pipe));
1983        IFX_PRINT(" Endpoint: %d, %s\n" , usb_pipeendpoint(_urb->pipe),
1984                                            (usb_pipein(_urb->pipe) ? "IN" : "OUT"));
1985        IFX_PRINT(" Endpoint type: %s\n",
1986            ({ char *pipetype;
1987                switch (usb_pipetype(_urb->pipe)) {
1988                    case PIPE_CONTROL: pipetype = "CONTROL"; break;
1989                    case PIPE_BULK: pipetype = "BULK"; break;
1990                    case PIPE_INTERRUPT: pipetype = "INTERRUPT"; break;
1991                    case PIPE_ISOCHRONOUS: pipetype = "ISOCHRONOUS"; break;
1992                    default: pipetype = "UNKNOWN"; break;
1993                };
1994                pipetype;
1995            }));
1996        IFX_PRINT(" Speed: %s\n",
1997            ({ char *speed;
1998                switch (_urb->dev->speed) {
1999                    case USB_SPEED_HIGH: speed = "HIGH"; break;
2000                    case USB_SPEED_FULL: speed = "FULL"; break;
2001                    case USB_SPEED_LOW: speed = "LOW"; break;
2002                    default: speed = "UNKNOWN"; break;
2003                };
2004                speed;
2005            }));
2006        IFX_PRINT(" Max packet size: %d\n",
2007              usb_maxpacket(_urb->dev, _urb->pipe, usb_pipeout(_urb->pipe)));
2008        IFX_PRINT(" Data buffer length: %d\n", _urb->transfer_buffer_length);
2009        IFX_PRINT(" Transfer buffer: %p, Transfer DMA: %p\n",
2010              _urb->transfer_buffer, (void *)_urb->transfer_dma);
2011        IFX_PRINT(" Setup buffer: %p, Setup DMA: %p\n",
2012              _urb->setup_packet, (void *)_urb->setup_dma);
2013        IFX_PRINT(" Interval: %d\n", _urb->interval);
2014        if (usb_pipetype(_urb->pipe) == PIPE_ISOCHRONOUS)
2015        {
2016            int i;
2017            for (i = 0; i < _urb->number_of_packets; i++)
2018            {
2019                IFX_PRINT(" ISO Desc %d:\n", i);
2020                IFX_PRINT(" offset: %d, length %d\n",
2021                    _urb->iso_frame_desc[i].offset,
2022                    _urb->iso_frame_desc[i].length);
2023            }
2024        }
2025    }
2026
2027#if 0
2028    static void dump_channel_info(ifxhcd_hcd_t *_ifxhcd, ifxhcd_epqh_t *_epqh)
2029    {
2030        if (_epqh->hc != NULL)
2031        {
2032            ifxhcd_hc_t *hc = _epqh->hc;
2033            struct list_head *item;
2034            ifxhcd_epqh_t *epqh_item;
2035
2036            ifxusb_hc_regs_t *hc_regs;
2037
2038            hcchar_data_t hcchar;
2039            hcsplt_data_t hcsplt;
2040            hctsiz_data_t hctsiz;
2041            uint32_t hcdma;
2042
2043            hc_regs = _ifxhcd->core_if.hc_regs[hc->hc_num];
2044            hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
2045            hcsplt.d32 = ifxusb_rreg(&hc_regs->hcsplt);
2046            hctsiz.d32 = ifxusb_rreg(&hc_regs->hctsiz);
2047            hcdma = ifxusb_rreg(&hc_regs->hcdma);
2048
2049            IFX_PRINT(" Assigned to channel %d:\n" , hc->hc_num);
2050            IFX_PRINT(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, hcsplt.d32);
2051            IFX_PRINT(" hctsiz 0x%08x, hcdma 0x%08x\n" , hctsiz.d32, hcdma);
2052            IFX_PRINT(" dev_addr: %d, ep_num: %d, is_in: %d\n",
2053               hc->dev_addr, hc->ep_num, hc->is_in);
2054            IFX_PRINT(" ep_type: %d\n" , hc->ep_type);
2055            IFX_PRINT(" max_packet_size: %d\n", hc->mps);
2056            IFX_PRINT(" data_pid_start: %d\n" , hc->data_pid_start);
2057            IFX_PRINT(" halt_status: %d\n" , hc->halt_status);
2058            IFX_PRINT(" xfer_buff: %p\n" , hc->xfer_buff);
2059            IFX_PRINT(" xfer_len: %d\n" , hc->xfer_len);
2060            IFX_PRINT(" epqh: %p\n" , hc->epqh);
2061            IFX_PRINT(" NP :\n");
2062            list_for_each(item, &_ifxhcd->epqh_list_np)
2063            {
2064                epqh_item = list_entry(item, ifxhcd_epqh_t, ql);
2065                IFX_PRINT(" %p\n", epqh_item);
2066            }
2067            IFX_PRINT(" INTR :\n");
2068            list_for_each(item, &_ifxhcd->epqh_list_intr)
2069            {
2070                epqh_item = list_entry(item, ifxhcd_epqh_t, ql);
2071                IFX_PRINT(" %p\n", epqh_item);
2072            }
2073            #ifdef __EN_ISOC__
2074                IFX_PRINT(" ISOC:\n");
2075                list_for_each(item, &_ifxhcd->epqh_list_isoc)
2076                {
2077                    epqh_item = list_entry(item, ifxhcd_epqh_t, ql);
2078                    IFX_PRINT(" %p\n", epqh_item);
2079                }
2080            #endif
2081        }
2082    }
2083#endif
2084#endif //__DEBUG__
2085
2086
2087/*!
2088   \brief This function writes a packet into the Tx FIFO associated with the Host
2089  Channel. For a channel associated with a non-periodic EP, the non-periodic
2090  Tx FIFO is written. For a channel associated with a periodic EP, the
2091  periodic Tx FIFO is written. This function should only be called in Slave
2092  mode.
2093
2094  Upon return the xfer_buff and xfer_count fields in _hc are incremented by
2095  then number of bytes written to the Tx FIFO.
2096 */
2097
2098#ifdef __ENABLE_DUMP__
2099    void ifxhcd_dump_state(ifxhcd_hcd_t *_ifxhcd)
2100    {
2101        int num_channels;
2102        int i;
2103        num_channels = _ifxhcd->core_if.params.host_channels;
2104        IFX_PRINT("\n");
2105        IFX_PRINT("************************************************************\n");
2106        IFX_PRINT("HCD State:\n");
2107        IFX_PRINT(" Num channels: %d\n", num_channels);
2108        for (i = 0; i < num_channels; i++) {
2109            ifxhcd_hc_t *hc = &_ifxhcd->ifxhc[i];
2110            IFX_PRINT(" Channel %d:\n", hc->hc_num);
2111            IFX_PRINT(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
2112                  hc->dev_addr, hc->ep_num, hc->is_in);
2113            IFX_PRINT(" speed: %d\n" , hc->speed);
2114            IFX_PRINT(" ep_type: %d\n" , hc->ep_type);
2115            IFX_PRINT(" mps: %d\n", hc->mps);
2116            IFX_PRINT(" data_pid_start: %d\n" , hc->data_pid_start);
2117            IFX_PRINT(" xfer_buff: %p\n" , hc->xfer_buff);
2118            IFX_PRINT(" xfer_len: %d\n" , hc->xfer_len);
2119            IFX_PRINT(" xfer_count: %d\n" , hc->xfer_count);
2120            IFX_PRINT(" halt_status: %d\n" , hc->halt_status);
2121            IFX_PRINT(" split: %d\n" , hc->split);
2122            IFX_PRINT(" hub_addr: %d\n" , hc->hub_addr);
2123            IFX_PRINT(" port_addr: %d\n" , hc->port_addr);
2124            #if defined(__EN_ISOC__) && defined(__EN_ISOC_SPLIT__)
2125                IFX_PRINT(" isoc_xact_pos: %d\n" , hc->isoc_xact_pos);
2126            #endif
2127
2128            IFX_PRINT(" epqh: %p\n" , hc->epqh);
2129            IFX_PRINT(" short_rw: %d\n" , hc->short_rw);
2130            IFX_PRINT(" control_phase: %d\n" , hc->control_phase);
2131            if(hc->epqh)
2132            {
2133                IFX_PRINT(" do_ping: %d\n" , hc->epqh->do_ping);
2134            }
2135            IFX_PRINT(" start_pkt_count: %d\n" , hc->start_pkt_count);
2136        }
2137        IFX_PRINT("************************************************************\n");
2138        IFX_PRINT("\n");
2139    }
2140#endif //__ENABLE_DUMP__
2141
2142

Archive Download this file



interactive