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
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 *****************************************************************************/
15 \ingroup IFXUSB_DRIVER_V3
16 \brief This file contains the interface to the IFX USB Core.
19 #include <linux/version.h>
20 #include "ifxusb_version.h"
23 #include <asm/byteorder.h>
24 #include <asm/unaligned.h>
27 #include <linux/jiffies.h>
30 #include "ifxusb_plat.h"
31 #include "ifxusb_regs.h"
32 #include "ifxusb_cif.h"
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
43 void ifxusb_dev_init_spd(ifxusb_core_if_t
*_core_if
)
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 */
53 /* High speed PHY running at high speed and full speed*/
56 IFX_DEBUGPL(DBG_CIL
, "Initializing DCFG.DevSpd to 0x%1x\n", val
);
57 dcfg
.d32
= ifxusb_rreg(&_core_if
->dev_global_regs
->dcfg
);
59 ifxusb_wreg(&_core_if
->dev_global_regs
->dcfg
, dcfg
.d32
);
64 \brief This function enables the Device mode interrupts.
65 \param _core_if Pointer of core_if structure
67 void ifxusb_dev_enable_interrupts(ifxusb_core_if_t
*_core_if
)
69 gint_data_t intr_mask
={ .d32
= 0};
70 ifxusb_core_global_regs_t
*global_regs
= _core_if
->core_global_regs
;
72 IFX_DEBUGPL(DBG_ENTRY
, "%s() %d\n", __func__
, __LINE__
);
73 IFX_DEBUGPL(DBG_CIL
, "%s()\n", __func__
);
75 /* Clear any pending OTG Interrupts */
76 ifxusb_wreg( &global_regs
->gotgint
, 0xFFFFFFFF);
78 /* Clear any pending interrupts */
79 ifxusb_wreg( &global_regs
->gintsts
, 0xFFFFFFFF);
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;
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;
94 // intr_mask.b.epmismatch = 1;
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
));
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
105 uint32_t ifxusb_dev_get_frame_number(ifxusb_core_if_t
*_core_if
)
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 */
116 \brief Set the EP STALL.
118 void ifxusb_dev_ep_set_stall(ifxusb_core_if_t
*_core_if
, uint8_t _epno
, uint8_t _is_in
)
120 depctl_data_t depctl
;
121 volatile uint32_t *depctl_addr
;
123 IFX_DEBUGPL(DBG_PCD
, "%s ep%d-%s\n", __func__
, _epno
, (_is_in
?"IN":"OUT"));
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
);
130 if (_is_in
&& depctl
.b
.epena
)
133 ifxusb_wreg(depctl_addr
, depctl
.d32
);
134 IFX_DEBUGPL(DBG_PCD
,"DEPCTL=%0x\n",ifxusb_rreg(depctl_addr
));
139 \brief Clear the EP STALL.
141 void ifxusb_dev_ep_clear_stall(ifxusb_core_if_t
*_core_if
, uint8_t _epno
, uint8_t _ep_type
, uint8_t _is_in
)
143 depctl_data_t depctl
;
144 volatile uint32_t *depctl_addr
;
146 IFX_DEBUGPL(DBG_PCD
, "%s ep%d-%s\n", __func__
, _epno
, (_is_in
?"IN":"OUT"));
148 depctl_addr
= (_is_in
)? (&(_core_if
->in_ep_regs
[_epno
]->diepctl
)):
149 (&(_core_if
->out_ep_regs
[_epno
]->doepctl
));
151 depctl
.d32
= ifxusb_rreg(depctl_addr
);
152 /* clear the stall bits */
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.
161 if (_ep_type
== IFXUSB_EP_TYPE_INTR
|| _ep_type
== IFXUSB_EP_TYPE_BULK
)
162 depctl
.b
.setd0pid
= 1; /* DATA0 */
164 ifxusb_wreg(depctl_addr
, depctl
.d32
);
165 IFX_DEBUGPL(DBG_PCD
,"DEPCTL=%0x\n",ifxusb_rreg(depctl_addr
));
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
173 \param _core_if Pointer of core_if structure
174 \param _params parameters to be set
176 void ifxusb_dev_core_init(ifxusb_core_if_t
*_core_if
, ifxusb_params_t
*_params
)
178 ifxusb_core_global_regs_t
*global_regs
= _core_if
->core_global_regs
;
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};
189 IFX_DEBUGPL(DBG_ENTRY
, "%s() %d\n", __func__
, __LINE__
);
190 IFX_DEBUGPL(DBG_CILV
, "%s(%p)\n",__func__
,_core_if
);
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);
198 _core_if
->params
.max_transfer_size
= _params
->max_transfer_size
;
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);
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
;
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
;
216 /* Reset the Controller */
219 while(ifxusb_core_soft_reset( _core_if
))
220 ifxusb_hard_reset(_core_if
);
221 } while (ifxusb_is_host_mode(_core_if
));
223 usbcfg
.d32
= ifxusb_rreg(&global_regs
->gusbcfg
);
225 #if defined(__DED_FIFO__)
226 usbcfg
.b
.ForceDevMode
= 1;
227 usbcfg
.b
.ForceHstMode
= 0;
230 usbcfg
.b
.term_sel_dl_pulse
= 0;
231 ifxusb_wreg (&global_regs
->gusbcfg
, usbcfg
.d32
);
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
)
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
);
249 /* Program the GAHBCFG Register.*/
250 switch (_core_if
->params
.dma_burst_size
)
253 ahbcfg
.b
.hburstlen
= IFXUSB_GAHBCFG_INT_DMA_BURST_SINGLE
;
256 ahbcfg
.b
.hburstlen
= IFXUSB_GAHBCFG_INT_DMA_BURST_INCR
;
259 ahbcfg
.b
.hburstlen
= IFXUSB_GAHBCFG_INT_DMA_BURST_INCR4
;
262 ahbcfg
.b
.hburstlen
= IFXUSB_GAHBCFG_INT_DMA_BURST_INCR8
;
265 ahbcfg
.b
.hburstlen
= IFXUSB_GAHBCFG_INT_DMA_BURST_INCR16
;
268 ahbcfg
.b
.dmaenable
= 1;
269 ifxusb_wreg(&global_regs
->gahbcfg
, ahbcfg
.d32
);
271 /* Program the GUSBCFG register. */
272 usbcfg
.d32
= ifxusb_rreg( &global_regs
->gusbcfg
);
275 ifxusb_wreg( &global_regs
->gusbcfg
, usbcfg
.d32
);
277 /* Restart the Phy Clock */
278 ifxusb_wreg(_core_if
->pcgcctl
, 0);
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__)
292 ifxusb_wreg( &_core_if
->dev_global_regs
->dcfg
, dcfg
.d32
);
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
);
300 _core_if
->params
.tx_fifo_size
[0]= ifxusb_rreg(&global_regs
->gnptxfsiz
) >> 16;
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;
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;
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
]);
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]);
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
;
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
);
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
];
339 txfifosize
.b
.startaddr
= _core_if
->params
.rx_fifo_size
;
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
++)
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
];
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
++)
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];
373 fifosize_data_t fifosize
;
374 IFX_DEBUGPL(DBG_CIL
, "Result : FIFO Size=0x%06X\n" , _core_if
->params
.data_fifo_size
);
376 IFX_DEBUGPL(DBG_CIL
, " Rx FIFO =0x%06X Sz=0x%06X\n", 0,ifxusb_rreg(&global_regs
->grxfsiz
));
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
++)
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
);
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
++)
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
);
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);
401 /* Flush the FIFOs */
402 ifxusb_flush_tx_fifo(_core_if
, 0x10); /* all Tx FIFOs */
403 ifxusb_flush_rx_fifo(_core_if
);
405 /* Flush the Learning Queue. */
406 resetctl
.b
.intknqflsh
= 1;
407 ifxusb_wreg( &global_regs
->grstctl
, resetctl
.d32
);
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 );
415 dir
=_core_if
->hwcfg1
.d32
;
416 for (i
=0; i
<= _core_if
->hwcfg2
.b
.num_dev_ep
; i
++,dir
>>=2)
418 depctl_data_t depctl
;
419 if((dir
&0x03)==0 || (dir
&0x03) ==1)
421 depctl
.d32
= ifxusb_rreg(&_core_if
->in_ep_regs
[i
]->diepctl
);
430 ifxusb_wreg( &_core_if
->in_ep_regs
[i
]->diepctl
, depctl
.d32
);
432 ifxusb_wreg( &_core_if
->in_ep_regs
[i
]->dieptsiz
, 0);
434 ifxusb_wreg( &_core_if
->in_ep_regs
[i
]->diepdma
, 0);
435 ifxusb_wreg( &_core_if
->in_ep_regs
[i
]->diepint
, 0xFF);
438 if((dir
&0x03)==0 || (dir
&0x03) ==2)
440 depctl
.d32
= ifxusb_rreg(&_core_if
->out_ep_regs
[i
]->doepctl
);
449 ifxusb_wreg( &_core_if
->out_ep_regs
[i
]->doepctl
, depctl
.d32
);
451 ifxusb_wreg( &_core_if
->out_ep_regs
[i
]->doeptsiz
, 0);
453 ifxusb_wreg( &_core_if
->out_ep_regs
[i
]->doepdma
, 0);
454 ifxusb_wreg( &_core_if
->out_ep_regs
[i
]->doepint
, 0xFF);