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);