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