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

1/*****************************************************************************
2 ** FILE NAME : ifxusb_cif_d.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 : The Core Interface provides basic services for accessing and
9 ** managing the IFX USB hardware. These services are used by the
10 ** Peripheral Controller Driver only.
11 *****************************************************************************/
12
13/*!
14 \file ifxusb_cif_d.c
15 \ingroup IFXUSB_DRIVER_V3
16 \brief This file contains the interface to the IFX USB Core.
17*/
18
19#include <linux/version.h>
20#include "ifxusb_version.h"
21
22
23#include <asm/byteorder.h>
24#include <asm/unaligned.h>
25
26#ifdef __DEBUG__
27    #include <linux/jiffies.h>
28#endif
29
30#include "ifxusb_plat.h"
31#include "ifxusb_regs.h"
32#include "ifxusb_cif.h"
33
34#include "ifxpcd.h"
35
36
37
38/*!
39 \brief Initializes the DevSpd field of the DCFG register depending on the PHY type
40 and the enumeration speed of the device.
41 \param _core_if Pointer of core_if structure
42 */
43void ifxusb_dev_init_spd(ifxusb_core_if_t *_core_if)
44{
45    uint32_t val;
46    dcfg_data_t dcfg;
47
48    IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ );
49    if (_core_if->params.speed == IFXUSB_PARAM_SPEED_FULL)
50        /* High speed PHY running at full speed */
51        val = 0x1;
52    else
53        /* High speed PHY running at high speed and full speed*/
54        val = 0x0;
55
56    IFX_DEBUGPL(DBG_CIL, "Initializing DCFG.DevSpd to 0x%1x\n", val);
57    dcfg.d32 = ifxusb_rreg(&_core_if->dev_global_regs->dcfg);
58    dcfg.b.devspd = val;
59    ifxusb_wreg(&_core_if->dev_global_regs->dcfg, dcfg.d32);
60}
61
62
63/*!
64 \brief This function enables the Device mode interrupts.
65 \param _core_if Pointer of core_if structure
66 */
67void ifxusb_dev_enable_interrupts(ifxusb_core_if_t *_core_if)
68{
69    gint_data_t intr_mask ={ .d32 = 0};
70    ifxusb_core_global_regs_t *global_regs = _core_if->core_global_regs;
71
72    IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ );
73    IFX_DEBUGPL(DBG_CIL, "%s()\n", __func__);
74
75    /* Clear any pending OTG Interrupts */
76    ifxusb_wreg( &global_regs->gotgint, 0xFFFFFFFF);
77
78    /* Clear any pending interrupts */
79    ifxusb_wreg( &global_regs->gintsts, 0xFFFFFFFF);
80
81    /* Enable the interrupts in the GINTMSK.*/
82    intr_mask.b.modemismatch = 1;
83    intr_mask.b.conidstschng = 1;
84    intr_mask.b.wkupintr = 1;
85    intr_mask.b.disconnect = 1;
86    intr_mask.b.usbsuspend = 1;
87
88    intr_mask.b.usbreset = 1;
89    intr_mask.b.enumdone = 1;
90    intr_mask.b.inepintr = 1;
91    intr_mask.b.outepintr = 1;
92    intr_mask.b.erlysuspend = 1;
93    #ifndef __DED_FIFO__
94// intr_mask.b.epmismatch = 1;
95    #endif
96
97    ifxusb_mreg( &global_regs->gintmsk, intr_mask.d32, intr_mask.d32);
98    IFX_DEBUGPL(DBG_CIL, "%s() gintmsk=%0x\n", __func__, ifxusb_rreg( &global_regs->gintmsk));
99}
100
101/*!
102 \brief Gets the current USB frame number. This is the frame number from the last SOF packet.
103 \param _core_if Pointer of core_if structure
104 */
105uint32_t ifxusb_dev_get_frame_number(ifxusb_core_if_t *_core_if)
106{
107    dsts_data_t dsts;
108    IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ );
109    dsts.d32 = ifxusb_rreg(&_core_if->dev_global_regs->dsts);
110    /* read current frame/microfreme number from DSTS register */
111    return dsts.b.soffn;
112}
113
114
115/*!
116 \brief Set the EP STALL.
117 */
118void ifxusb_dev_ep_set_stall(ifxusb_core_if_t *_core_if, uint8_t _epno, uint8_t _is_in)
119{
120    depctl_data_t depctl;
121    volatile uint32_t *depctl_addr;
122
123    IFX_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, _epno, (_is_in?"IN":"OUT"));
124
125    depctl_addr = (_is_in)? (&(_core_if->in_ep_regs [_epno]->diepctl)):
126                            (&(_core_if->out_ep_regs[_epno]->doepctl));
127    depctl.d32 = ifxusb_rreg(depctl_addr);
128    depctl.b.stall = 1;
129
130    if (_is_in && depctl.b.epena)
131        depctl.b.epdis = 1;
132
133    ifxusb_wreg(depctl_addr, depctl.d32);
134    IFX_DEBUGPL(DBG_PCD,"DEPCTL=%0x\n",ifxusb_rreg(depctl_addr));
135    return;
136}
137
138/*!
139\brief Clear the EP STALL.
140 */
141void ifxusb_dev_ep_clear_stall(ifxusb_core_if_t *_core_if, uint8_t _epno, uint8_t _ep_type, uint8_t _is_in)
142{
143    depctl_data_t depctl;
144    volatile uint32_t *depctl_addr;
145
146    IFX_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, _epno, (_is_in?"IN":"OUT"));
147
148    depctl_addr = (_is_in)? (&(_core_if->in_ep_regs [_epno]->diepctl)):
149                            (&(_core_if->out_ep_regs[_epno]->doepctl));
150
151    depctl.d32 = ifxusb_rreg(depctl_addr);
152    /* clear the stall bits */
153    depctl.b.stall = 0;
154
155    /*
156     * USB Spec 9.4.5: For endpoints using data toggle, regardless
157     * of whether an endpoint has the Halt feature set, a
158     * ClearFeature(ENDPOINT_HALT) request always results in the
159     * data toggle being reinitialized to DATA0.
160     */
161    if (_ep_type == IFXUSB_EP_TYPE_INTR || _ep_type == IFXUSB_EP_TYPE_BULK)
162        depctl.b.setd0pid = 1; /* DATA0 */
163
164    ifxusb_wreg(depctl_addr, depctl.d32);
165    IFX_DEBUGPL(DBG_PCD,"DEPCTL=%0x\n",ifxusb_rreg(depctl_addr));
166    return;
167}
168
169/*!
170   \brief This function initializes the IFXUSB controller registers for Device mode.
171 This function flushes the Tx and Rx FIFOs and it flushes any entries in the
172 request queues.
173   \param _core_if Pointer of core_if structure
174   \param _params parameters to be set
175 */
176void ifxusb_dev_core_init(ifxusb_core_if_t *_core_if, ifxusb_params_t *_params)
177{
178    ifxusb_core_global_regs_t *global_regs = _core_if->core_global_regs;
179
180    gusbcfg_data_t usbcfg ={.d32 = 0};
181    gahbcfg_data_t ahbcfg ={.d32 = 0};
182    dcfg_data_t dcfg ={.d32 = 0};
183    grstctl_t resetctl ={.d32 = 0};
184    gotgctl_data_t gotgctl ={.d32 = 0};
185
186    uint32_t dir;
187    int i;
188
189    IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ );
190    IFX_DEBUGPL(DBG_CILV, "%s(%p)\n",__func__,_core_if);
191
192    /* Copy Params */
193    _core_if->params.dma_burst_size = _params->dma_burst_size;
194    _core_if->params.speed = _params->speed;
195    if(_params->max_transfer_size < 2048 || _params->max_transfer_size > ((1 << (_core_if->hwcfg3.b.xfer_size_cntr_width + 11)) - 1) )
196        _core_if->params.max_transfer_size = ((1 << (_core_if->hwcfg3.b.xfer_size_cntr_width + 11)) - 1);
197    else
198        _core_if->params.max_transfer_size = _params->max_transfer_size;
199
200    if(_params->max_packet_count < 16 || _params->max_packet_count > ((1 << (_core_if->hwcfg3.b.packet_size_cntr_width + 4)) - 1) )
201        _core_if->params.max_packet_count= ((1 << (_core_if->hwcfg3.b.packet_size_cntr_width + 4)) - 1);
202    else
203        _core_if->params.max_packet_count= _params->max_packet_count;
204    _core_if->params.phy_utmi_width = _params->phy_utmi_width;
205    _core_if->params.turn_around_time_hs = _params->turn_around_time_hs;
206    _core_if->params.turn_around_time_fs = _params->turn_around_time_fs;
207    _core_if->params.timeout_cal_hs = _params->timeout_cal_hs;
208    _core_if->params.timeout_cal_fs = _params->timeout_cal_fs;
209
210    #ifdef __DED_FIFO__
211        _core_if->params.thr_ctl = _params->thr_ctl;
212        _core_if->params.tx_thr_length = _params->tx_thr_length;
213        _core_if->params.rx_thr_length = _params->rx_thr_length;
214    #endif
215
216    /* Reset the Controller */
217    do
218    {
219        while(ifxusb_core_soft_reset( _core_if ))
220            ifxusb_hard_reset(_core_if);
221    } while (ifxusb_is_host_mode(_core_if));
222
223    usbcfg.d32 = ifxusb_rreg(&global_regs->gusbcfg);
224    #if 0
225    #if defined(__DED_FIFO__)
226        usbcfg.b.ForceDevMode = 1;
227        usbcfg.b.ForceHstMode = 0;
228    #endif
229    #endif
230    usbcfg.b.term_sel_dl_pulse = 0;
231    ifxusb_wreg (&global_regs->gusbcfg, usbcfg.d32);
232
233    /* This programming sequence needs to happen in FS mode before any other
234     * programming occurs */
235    /* High speed PHY. */
236    if (!_core_if->phy_init_done)
237    {
238        _core_if->phy_init_done = 1;
239        /* HS PHY parameters. These parameters are preserved
240         * during soft reset so only program the first time. Do
241         * a soft reset immediately after setting phyif. */
242        usbcfg.b.ulpi_utmi_sel = 0; //UTMI+
243        usbcfg.b.phyif = ( _core_if->params.phy_utmi_width == 16)?1:0;
244        ifxusb_wreg( &global_regs->gusbcfg, usbcfg.d32);
245        /* Reset after setting the PHY parameters */
246        ifxusb_core_soft_reset( _core_if );
247    }
248
249    /* Program the GAHBCFG Register.*/
250    switch (_core_if->params.dma_burst_size)
251    {
252        case 0 :
253            ahbcfg.b.hburstlen = IFXUSB_GAHBCFG_INT_DMA_BURST_SINGLE;
254            break;
255        case 1 :
256            ahbcfg.b.hburstlen = IFXUSB_GAHBCFG_INT_DMA_BURST_INCR;
257            break;
258        case 4 :
259            ahbcfg.b.hburstlen = IFXUSB_GAHBCFG_INT_DMA_BURST_INCR4;
260            break;
261        case 8 :
262            ahbcfg.b.hburstlen = IFXUSB_GAHBCFG_INT_DMA_BURST_INCR8;
263            break;
264        case 16:
265            ahbcfg.b.hburstlen = IFXUSB_GAHBCFG_INT_DMA_BURST_INCR16;
266            break;
267    }
268    ahbcfg.b.dmaenable = 1;
269    ifxusb_wreg(&global_regs->gahbcfg, ahbcfg.d32);
270
271    /* Program the GUSBCFG register. */
272    usbcfg.d32 = ifxusb_rreg( &global_regs->gusbcfg );
273    usbcfg.b.hnpcap = 0;
274    usbcfg.b.srpcap = 0;
275    ifxusb_wreg( &global_regs->gusbcfg, usbcfg.d32);
276
277    /* Restart the Phy Clock */
278    ifxusb_wreg(_core_if->pcgcctl, 0);
279
280    /* Device configuration register */
281    ifxusb_dev_init_spd(_core_if);
282    dcfg.d32 = ifxusb_rreg( &_core_if->dev_global_regs->dcfg);
283    dcfg.b.perfrint = IFXUSB_DCFG_FRAME_INTERVAL_80;
284    #if defined(__DED_FIFO__)
285        #if defined(__DESC_DMA__)
286            dcfg.b.descdma = 1;
287        #else
288            dcfg.b.descdma = 0;
289        #endif
290    #endif
291
292    ifxusb_wreg( &_core_if->dev_global_regs->dcfg, dcfg.d32 );
293
294    /* Configure data FIFO sizes */
295    _core_if->params.data_fifo_size = _core_if->hwcfg3.b.dfifo_depth;
296    _core_if->params.rx_fifo_size = ifxusb_rreg(&global_regs->grxfsiz);
297    IFX_DEBUGPL(DBG_CIL, "Initial: FIFO Size=0x%06X\n" , _core_if->params.data_fifo_size);
298    IFX_DEBUGPL(DBG_CIL, " Rx FIFO Size=0x%06X\n", _core_if->params.rx_fifo_size);
299
300    _core_if->params.tx_fifo_size[0]= ifxusb_rreg(&global_regs->gnptxfsiz) >> 16;
301
302    #ifdef __DED_FIFO__
303        for (i=1; i <= _core_if->hwcfg4.b.num_in_eps; i++)
304            _core_if->params.tx_fifo_size[i] =
305                ifxusb_rreg(&global_regs->dptxfsiz_dieptxf[i-1]) >> 16;
306    #else
307        for (i=0; i < _core_if->hwcfg4.b.num_dev_perio_in_ep; i++)
308            _core_if->params.tx_fifo_size[i+1] =
309                ifxusb_rreg(&global_regs->dptxfsiz_dieptxf[i]) >> 16;
310    #endif
311
312    #ifdef __DEBUG__
313        #ifdef __DED_FIFO__
314            for (i=0; i <= _core_if->hwcfg4.b.num_in_eps; i++)
315                IFX_DEBUGPL(DBG_CIL, " Tx[%02d] FIFO Size=0x%06X\n",i, _core_if->params.tx_fifo_size[i]);
316        #else
317            IFX_DEBUGPL(DBG_CIL, " NPTx FIFO Size=0x%06X\n", _core_if->params.tx_fifo_size[0]);
318            for (i=0; i < _core_if->hwcfg4.b.num_dev_perio_in_ep; i++)
319                IFX_DEBUGPL(DBG_CIL, " PTx[%02d] FIFO Size=0x%06X\n",i, _core_if->params.tx_fifo_size[i+1]);
320        #endif
321    #endif
322
323    {
324        fifosize_data_t txfifosize;
325        if(_params->data_fifo_size >=0 && _params->data_fifo_size < _core_if->params.data_fifo_size)
326            _core_if->params.data_fifo_size = _params->data_fifo_size;
327
328
329        if(_params->rx_fifo_size >=0 && _params->rx_fifo_size < _core_if->params.rx_fifo_size)
330            _core_if->params.rx_fifo_size = _params->rx_fifo_size;
331        if(_core_if->params.data_fifo_size < _core_if->params.rx_fifo_size)
332            _core_if->params.rx_fifo_size = _core_if->params.data_fifo_size;
333        ifxusb_wreg( &global_regs->grxfsiz, _core_if->params.rx_fifo_size);
334
335        for (i=0; i < MAX_EPS_CHANNELS; i++)
336            if(_params->tx_fifo_size[i] >=0 && _params->tx_fifo_size[i] < _core_if->params.tx_fifo_size[i])
337                _core_if->params.tx_fifo_size[i] = _params->tx_fifo_size[i];
338
339        txfifosize.b.startaddr = _core_if->params.rx_fifo_size;
340        #ifdef __DED_FIFO__
341            if(txfifosize.b.startaddr + _core_if->params.tx_fifo_size[0] > _core_if->params.data_fifo_size)
342                _core_if->params.tx_fifo_size[0]= _core_if->params.data_fifo_size - txfifosize.b.startaddr;
343            txfifosize.b.depth=_core_if->params.tx_fifo_size[0];
344            ifxusb_wreg( &global_regs->gnptxfsiz, txfifosize.d32);
345            txfifosize.b.startaddr += _core_if->params.tx_fifo_size[0];
346            for (i=1; i <= _core_if->hwcfg4.b.num_in_eps; i++)
347            {
348                if(txfifosize.b.startaddr + _core_if->params.tx_fifo_size[i] > _core_if->params.data_fifo_size)
349                    _core_if->params.tx_fifo_size[i]= _core_if->params.data_fifo_size - txfifosize.b.startaddr;
350                txfifosize.b.depth=_core_if->params.tx_fifo_size[i];
351                ifxusb_wreg( &global_regs->dptxfsiz_dieptxf[i-1], txfifosize.d32);
352                txfifosize.b.startaddr += _core_if->params.tx_fifo_size[i];
353            }
354        #else
355            if(txfifosize.b.startaddr + _core_if->params.tx_fifo_size[0] > _core_if->params.data_fifo_size)
356                _core_if->params.tx_fifo_size[0]= _core_if->params.data_fifo_size - txfifosize.b.startaddr;
357            txfifosize.b.depth=_core_if->params.tx_fifo_size[0];
358            ifxusb_wreg( &global_regs->gnptxfsiz, txfifosize.d32);
359            txfifosize.b.startaddr += _core_if->params.tx_fifo_size[0];
360            for (i=0; i < _core_if->hwcfg4.b.num_dev_perio_in_ep; i++)
361            {
362                if(txfifosize.b.startaddr + _core_if->params.tx_fifo_size[i+1] > _core_if->params.data_fifo_size)
363                    _core_if->params.tx_fifo_size[i+1]= _core_if->params.data_fifo_size - txfifosize.b.startaddr;
364                //txfifosize.b.depth=_core_if->params.tx_fifo_size[i+1];
365                ifxusb_wreg( &global_regs->dptxfsiz_dieptxf[i], txfifosize.d32);
366                txfifosize.b.startaddr += _core_if->params.tx_fifo_size[i+1];
367            }
368        #endif
369    }
370
371    #ifdef __DEBUG__
372    {
373        fifosize_data_t fifosize;
374        IFX_DEBUGPL(DBG_CIL, "Result : FIFO Size=0x%06X\n" , _core_if->params.data_fifo_size);
375
376        IFX_DEBUGPL(DBG_CIL, " Rx FIFO =0x%06X Sz=0x%06X\n", 0,ifxusb_rreg(&global_regs->grxfsiz));
377        #ifdef __DED_FIFO__
378            fifosize.d32=ifxusb_rreg(&global_regs->gnptxfsiz);
379            IFX_DEBUGPL(DBG_CIL, " Tx[00] FIFO =0x%06X Sz=0x%06X\n", fifosize.b.startaddr,fifosize.b.depth);
380            for (i=1; i <= _core_if->hwcfg4.b.num_in_eps; i++)
381            {
382                fifosize.d32=ifxusb_rreg(&global_regs->dptxfsiz_dieptxf[i-1]);
383                IFX_DEBUGPL(DBG_CIL, " Tx[%02d] FIFO 0x%06X Sz=0x%06X\n",i, fifosize.b.startaddr,fifosize.b.depth);
384            }
385        #else
386            fifosize.d32=ifxusb_rreg(&global_regs->gnptxfsiz);
387            IFX_DEBUGPL(DBG_CIL, " NPTx FIFO =0x%06X Sz=0x%06X\n", fifosize.b.startaddr,fifosize.b.depth);
388            for (i=0; i < _core_if->hwcfg4.b.num_dev_perio_in_ep; i++)
389            {
390                fifosize.d32=ifxusb_rreg(&global_regs->dptxfsiz_dieptxf[i]);
391                IFX_DEBUGPL(DBG_CIL, " PTx[%02d] FIFO 0x%06X Sz=0x%06X\n",i, fifosize.b.startaddr,fifosize.b.depth);
392            }
393        #endif
394    }
395    #endif
396
397    /* Clear Host Set HNP Enable in the OTG Control Register */
398    gotgctl.b.hstsethnpen = 1;
399    ifxusb_mreg( &global_regs->gotgctl, gotgctl.d32, 0);
400
401    /* Flush the FIFOs */
402    ifxusb_flush_tx_fifo(_core_if, 0x10); /* all Tx FIFOs */
403    ifxusb_flush_rx_fifo(_core_if);
404
405    /* Flush the Learning Queue. */
406    resetctl.b.intknqflsh = 1;
407    ifxusb_wreg( &global_regs->grstctl, resetctl.d32);
408
409    /* Clear all pending Device Interrupts */
410    ifxusb_wreg( &_core_if->dev_global_regs->diepmsk , 0 );
411    ifxusb_wreg( &_core_if->dev_global_regs->doepmsk , 0 );
412    ifxusb_wreg( &_core_if->dev_global_regs->daint , 0xFFFFFFFF );
413    ifxusb_wreg( &_core_if->dev_global_regs->daintmsk, 0 );
414
415    dir=_core_if->hwcfg1.d32;
416    for (i=0; i <= _core_if->hwcfg2.b.num_dev_ep ; i++,dir>>=2)
417    {
418        depctl_data_t depctl;
419        if((dir&0x03)==0 || (dir&0x03) ==1)
420        {
421            depctl.d32 = ifxusb_rreg(&_core_if->in_ep_regs[i]->diepctl);
422            if (depctl.b.epena)
423            {
424                depctl.d32 = 0;
425                depctl.b.epdis = 1;
426                depctl.b.snak = 1;
427            }
428            else
429                depctl.d32 = 0;
430            ifxusb_wreg( &_core_if->in_ep_regs[i]->diepctl, depctl.d32);
431            #ifndef __DESC_DMA__
432                ifxusb_wreg( &_core_if->in_ep_regs[i]->dieptsiz, 0);
433            #endif
434            ifxusb_wreg( &_core_if->in_ep_regs[i]->diepdma, 0);
435            ifxusb_wreg( &_core_if->in_ep_regs[i]->diepint, 0xFF);
436        }
437
438        if((dir&0x03)==0 || (dir&0x03) ==2)
439        {
440            depctl.d32 = ifxusb_rreg(&_core_if->out_ep_regs[i]->doepctl);
441            if (depctl.b.epena)
442            {
443                depctl.d32 = 0;
444                depctl.b.epdis = 1;
445                depctl.b.snak = 1;
446            }
447            else
448                depctl.d32 = 0;
449            ifxusb_wreg( &_core_if->out_ep_regs[i]->doepctl, depctl.d32);
450            #ifndef __DESC_DMA__
451                ifxusb_wreg( &_core_if->out_ep_regs[i]->doeptsiz, 0);
452            #endif
453            ifxusb_wreg( &_core_if->out_ep_regs[i]->doepdma, 0);
454            ifxusb_wreg( &_core_if->out_ep_regs[i]->doepint, 0xFF);
455        }
456    }
457}
458
459

Archive Download this file



interactive