[lantiq] move files/ -> files-3.3/
[openwrt.git] / target / linux / lantiq / files-3.3 / 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  */
43 void 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  */
67 void 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  */
105 uint32_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  */
118 void 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  */
141 void 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  */
176 void 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