[lantiq] move files/ -> files-3.3/
[openwrt/svn-archive/archive.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