blob: 22fd410b7efac484b2c65d557293a24edaac01a4 [file] [log] [blame]
yuezonghe824eb0c2024-06-27 02:32:26 -07001/* ==========================================================================
2 * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.c $
3 * $Revision: #191 $
4 * $Date: 2012/08/10 $
5 * $Change: 2047372 $
6 *
7 * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
8 * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
9 * otherwise expressly agreed to in writing between Synopsys and you.
10 *
11 * The Software IS NOT an item of Licensed Software or Licensed Product under
12 * any End User Software License Agreement or Agreement for Licensed Product
13 * with Synopsys or any supplement thereto. You are permitted to use and
14 * redistribute this Software in source and binary forms, with or without
15 * modification, provided that redistributions of source code must retain this
16 * notice. You may not view, use, disclose, copy or distribute this file or
17 * any information contained herein except pursuant to this license grant from
18 * Synopsys. If you do not agree with this notice, including the disclaimer
19 * below, then you are not authorized to use the Software.
20 *
21 * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31 * DAMAGE.
32 * ========================================================================== */
33
34/** @file
35 *
36 * The Core Interface Layer provides basic services for accessing and
37 * managing the DWC_otg hardware. These services are used by both the
38 * Host Controller Driver and the Peripheral Controller Driver.
39 *
40 * The CIL manages the memory map for the core so that the HCD and PCD
41 * don't have to do this separately. It also handles basic tasks like
42 * reading/writing the registers and data FIFOs in the controller.
43 * Some of the data access functions provide encapsulation of several
44 * operations required to perform a task, such as writing multiple
45 * registers to start a transfer. Finally, the CIL performs basic
46 * services that are not specific to either the host or device modes
47 * of operation. These services include management of the OTG Host
48 * Negotiation Protocol (HNP) and Session Request Protocol (SRP). A
49 * Diagnostic API is also provided to allow testing of the controller
50 * hardware.
51 *
52 * The Core Interface Layer has the following requirements:
53 * - Provides basic controller operations.
54 * - Minimal use of OS services.
55 * - The OS services used will be abstracted by using inline functions
56 * or macros.
57 *
58 */
59
60#include <common.h>
61
62#include "global.h"
63#include "dwc_otg_regs.h"
64#include "dwc_otg_cil.h"
65#include "dwc_otg_driver.h"
66
67
68
69static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if);
70
71void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask)
72{
73 DWC_WRITE_REG32(reg,(DWC_READ_REG32(reg) & ~clear_mask) | set_mask);
74}
75
76dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * reg_base_addr)
77{
78 dwc_otg_core_if_t *core_if = (&global.core_if_t);
79 dwc_otg_dev_if_t *dev_if = (&global.dev_if_t);
80 uint8_t *pt_core_if = ( uint8_t *)(&global.core_if_t);
81 uint8_t *pt_dev_if = ( uint8_t *)(&global.dev_if_t);
82 uint8_t *reg_base = (uint8_t *) reg_base_addr;
83 int i = 0;
84 for(i= 0;i<sizeof(global.core_if_t);i++)
85 {
86 pt_core_if[i] = 0;
87 }
88 core_if->core_global_regs = (dwc_otg_core_global_regs_t *) reg_base;
89
90 for(i= 0;i<sizeof(global.dev_if_t);i++)
91 {
92 pt_dev_if[i] = 0;
93 }
94
95 dev_if->dev_global_regs = (dwc_otg_device_global_regs_t *) (reg_base +DWC_DEV_GLOBAL_REG_OFFSET);
96
97 for (i = 0; i < MAX_EPS_CHANNELS; i++)
98 {
99 dev_if->in_ep_regs[i] = (dwc_otg_dev_in_ep_regs_t *)
100 (reg_base + DWC_DEV_IN_EP_REG_OFFSET +
101 (i * DWC_EP_REG_OFFSET));
102
103 dev_if->out_ep_regs[i] = (dwc_otg_dev_out_ep_regs_t *)
104 (reg_base + DWC_DEV_OUT_EP_REG_OFFSET +
105 (i * DWC_EP_REG_OFFSET));
106
107 core_if->data_fifo[i] =(uint32_t *) (reg_base + DWC_OTG_DATA_FIFO_OFFSET +(i * DWC_OTG_DATA_FIFO_SIZE));
108 }
109
110 dev_if->speed = 0;
111
112 core_if->dev_if = dev_if;
113
114 core_if->pcgcctl = (uint32_t *) (reg_base + DWC_OTG_PCGCCTL_OFFSET);
115
116 core_if->hwcfg1.d32 =DWC_READ_REG32(&core_if->core_global_regs->ghwcfg1);
117 core_if->hwcfg2.d32 =DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2);
118 core_if->hwcfg3.d32 =DWC_READ_REG32(&core_if->core_global_regs->ghwcfg3);
119 core_if->hwcfg4.d32 =DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4);
120
121 core_if->dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
122
123 dwc_otg_setup_params(core_if);
124
125
126 return core_if;
127}
128
129/**
130 * Initializes the DevSpd field of the DCFG register depending on the PHY type
131 * and the enumeration speed of the device.
132 */
133void init_devspd(dwc_otg_core_if_t * core_if,uint8_t speed)
134{
135 uint32_t val;
136 dcfg_data_t dcfg;
137
138 val = speed;
139 dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
140 dcfg.b.devspd = val;
141 if(global.g_enum == NEED_ENUM)
142 {
143 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
144 }
145}
146
147/**
148 * This function initializes the DWC_otg controller registers and
149 * prepares the core for device mode or host mode operation.
150 *
151 * @param core_if Programming view of the DWC_otg controller
152 *
153 */
154void dwc_otg_core_init(dwc_otg_core_if_t * core_if)
155{
156 dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
157 dwc_otg_dev_if_t *dev_if = core_if->dev_if;
158 gahbcfg_data_t ahbcfg;
159 gotgctl_data_t gotgctl;
160
161 gusbcfg_data_t usbcfg;
162 ahbcfg.d32 = 0;
163 usbcfg.d32 = 0;
164 gotgctl.d32 = 0;
165
166
167 usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
168if(global.g_enum == NEED_ENUM)
169{
170
171#if !USE_ASIC
172 usbcfg.b.ulpi_ext_vbus_drv =(core_if->core_params->phy_ulpi_ext_vbus == DWC_PHY_ULPI_EXTERNAL_VBUS) ? 1 : 0;
173
174 usbcfg.b.term_sel_dl_pulse = (core_if->core_params->ts_dline == 1) ? 1 : 0;
175
176
177 DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
178#endif
179 dwc_otg_core_reset(core_if);
180 }
181
182
183 dev_if->num_in_eps = 2;//calc_num_in_eps(core_if);
184 dev_if->num_out_eps = 2;//calc_num_out_eps(core_if);
185
186 core_if->total_fifo_size = core_if->hwcfg3.b.dfifo_depth;
187 core_if->rx_fifo_size = DWC_READ_REG32(&global_regs->grxfsiz);
188 core_if->nperio_tx_fifo_size = DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16;
189 {
190 /* High speed PHY. */
191 if (!core_if->phy_init_done)
192 {
193 core_if->phy_init_done = 1;
194 /* HS PHY parameters. These parameters are preserved
195 * during soft reset so only program the first time. Do
196 * a soft reset immediately after setting phyif. */
197 #if !USE_ASIC
198 if (core_if->core_params->phy_type == 2)
199 {
200 /* ULPI interface */
201 usbcfg.b.ulpi_utmi_sel = 1;
202 usbcfg.b.phyif = 0;
203 usbcfg.b.ddrsel = core_if->core_params->phy_ulpi_ddr;
204 }
205 #else
206 if (core_if->core_params->phy_type == 1)
207 {
208 /* UTMI+ interface */
209 usbcfg.b.ulpi_utmi_sel = 0;
210 if (core_if->core_params->phy_utmi_width == 16)
211 {
212 usbcfg.b.phyif = 1;
213
214 }
215 else
216 {
217 usbcfg.b.phyif = 0;
218 }
219 }
220 #endif
221 if(global.g_enum == NEED_ENUM)
222 {
223 DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
224 /* Reset after setting the PHY parameters */
225 dwc_otg_core_reset(core_if);
226 }
227 }
228 }
229 if(global.g_enum == NEED_ENUM)
230 {
231#if !USE_ASIC
232 if ((core_if->hwcfg2.b.hs_phy_type == 2) &&(core_if->hwcfg2.b.fs_phy_type == 1) &&(core_if->core_params->ulpi_fs_ls))
233 {
234 usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
235 usbcfg.b.ulpi_fsls = 1;
236 usbcfg.b.ulpi_clk_sus_m = 1;
237 DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
238 }
239 else
240 {
241 usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
242 usbcfg.b.ulpi_fsls = 0;
243 usbcfg.b.ulpi_clk_sus_m = 0;
244 DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
245 }
246#endif
247 }
248
249
250 ahbcfg.b.nptxfemplvl_txfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
251 ahbcfg.b.ptxfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
252
253
254 ahbcfg.b.dmaenable = 0;
255// ÅäÖÃÈ«¿ÕFIFO²úÉúÖжÏ
256 ahbcfg.b.nptxfemplvl_txfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_EMPTY ;
257 if(global.g_enum == NEED_ENUM)
258 {
259
260 DWC_WRITE_REG32(&global_regs->gahbcfg, ahbcfg.d32);
261 }
262
263
264 core_if->en_multiple_tx_fifo = core_if->hwcfg4.b.ded_fifo_en;
265
266 core_if->pti_enh_enable = core_if->core_params->pti_enable != 0;
267 core_if->multiproc_int_enable = dwc_param_mpi_enable_default;//core_if->core_params->mpi_enable;
268 /*
269 * Program the GUSBCFG register.
270 */
271 usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
272 usbcfg.b.hnpcap = 0;
273 usbcfg.b.srpcap = 0;
274
275 if(global.g_enum == NEED_ENUM)
276 {
277 DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
278 }
279 {
280 gotgctl.b.otgver = core_if->core_params->otg_ver;
281 if(global.g_enum == NEED_ENUM)
282 {
283 DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl, 0, gotgctl.d32);
284 }
285 /* Set OTG version supported */
286 core_if->otg_ver = core_if->core_params->otg_ver;
287 }
288 if(global.g_enum == NEED_ENUM)
289 {
290 dwc_otg_core_dev_init(core_if);
291 }
292
293}
294
295/**
296 * This function enables the Device mode interrupts.
297 *
298 * @param core_if Programming view of DWC_otg controller
299 */
300void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * core_if)
301{
302 gintmsk_data_t intr_mask ;
303
304 dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
305 intr_mask.d32 = 0;
306 /* Disable all interrupts. */
307 DWC_WRITE_REG32(&global_regs->gintmsk, 0);
308
309 /* Clear any pending interrupts */
310 DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF);
311
312 /* Enable the common interrupts */
313 intr_mask.b.rxstsqlvl = 1;
314 intr_mask.b.usbsuspend = 1;
315 DWC_WRITE_REG32(&global_regs->gintmsk, intr_mask.d32);
316
317 intr_mask.d32 = 0x1e3400;
318 DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32);
319
320}
321
322/**
323 * This function initializes the DWC_otg controller registers for
324 * device mode.
325 *
326 * @param core_if Programming view of DWC_otg controller
327 *
328 */
329void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if)
330{
331 int i;
332 dwc_otg_dev_if_t *dev_if = core_if->dev_if;
333 dcfg_data_t dcfg;
334 grstctl_t resetctl;
335 dctl_data_t dctl;
336 diepmsk_data_t msk;
337 dcfg.d32 = 0;
338 resetctl.d32 = 0;
339 dctl.d32 = 0;
340 msk.d32 = 0;
341 /* Restart the Phy Clock */
342
343 DWC_WRITE_REG32(core_if->pcgcctl, 0);
344
345
346 /* Device configuration register */
347 init_devspd(core_if,0);//ĬÈÏÅäÖóɸßËÙ
348 dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
349 dcfg.b.descdma = 0;
350 dcfg.b.perfrint = DWC_DCFG_FRAME_INTERVAL_80;
351
352 DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
353
354
355 /* Flush the FIFOs */
356 dwc_otg_flush_tx_fifo(core_if, 0x10); /* all Tx FIFOs */
357 dwc_otg_flush_rx_fifo(core_if);
358
359 /* Flush the Learning Queue. */
360 resetctl.b.intknqflsh = 1;
361 DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
362
363 /* Clear all pending Device Interrupts */
364 /** @todo - if the condition needed to be checked
365 * or in any case all pending interrutps should be cleared?
366 */
367 DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, 0);
368 DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, 0);
369 DWC_WRITE_REG32(&dev_if->dev_global_regs->daint, 0xFFFFFFFF);
370 DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk, 0);
371
372 for (i = 0; i <= dev_if->num_in_eps; i++)
373 {
374 DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl,0);
375
376 DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, 0);
377 DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, 0);
378 DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepint, 0xFF);
379
380 DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl,0);
381
382 DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doeptsiz, 0);
383 DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepdma, 0);
384 DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepint, 0xFF);
385 }
386
387 //ÓÃÓÚhsic
388 if(1==global.g_USB_MODE)
389 {
390 DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, 0x40000000);
391 }
392 dwc_otg_enable_device_interrupts(core_if);
393 msk.b.txfifoundrn = 1;
394 DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk,msk.d32, msk.d32);
395 dctl.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dctl);
396 dctl.b.sftdiscon = 0;
397 DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, dctl.d32);
398
399}
400
401void dwc_otg_core_dev_disconnet(dwc_otg_core_if_t * core_if)
402{
403 dctl_data_t dctl;
404 dwc_otg_dev_if_t *dev_if = core_if->dev_if;
405 dctl.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dctl);
406 dctl.b.sftdiscon = 1;
407 DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, dctl.d32);
408}
409/**
410 * This function reads a setup packet from the Rx FIFO into the destination
411 * buffer. This function is called from the Rx Status Queue Level (RxStsQLvl)
412 * Interrupt routine when a SETUP packet has been received in Slave mode.
413 *
414 * @param core_if Programming view of DWC_otg controller.
415 * @param dest Destination buffer for packet data.
416 */
417void dwc_otg_read_setup_packet(dwc_otg_core_if_t * core_if, uint32_t * dest)
418{
419 dest[0] = DWC_READ_REG32(core_if->data_fifo[0]);
420 dest[1] = DWC_READ_REG32(core_if->data_fifo[0]);
421
422}
423
424/**
425 * This function enables EP0 OUT to receive SETUP packets and configures EP0
426 * IN for transmitting packets. It is normally called when the
427 * "Enumeration Done" interrupt occurs.
428 *
429 * @param core_if Programming view of DWC_otg controller.
430 * @param ep The EP0 data.
431 */
432void dwc_otg_ep0_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
433{
434 dwc_otg_dev_if_t *dev_if = core_if->dev_if;
435 dsts_data_t dsts;
436 depctl_data_t diepctl;
437 dctl_data_t dctl;
438 ep->stp_rollover = 0;
439 dctl.d32 = 0;
440
441 /* Read the Device Status and Endpoint 0 Control registers */
442 dsts.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dsts);
443 diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl);
444
445 /* Set the MPS of the IN EP based on the enumeration speed */
446 switch (dsts.b.enumspd)
447 {
448 case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
449 case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
450 case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:
451 diepctl.b.mps = DWC_DEP0CTL_MPS_64;
452 break;
453 }
454
455 DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);
456 dctl.b.cgnpinnak = 1;
457
458 DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
459
460}
461
462/**
463 * This function activates an EP. The Device EP control register for
464 * the EP is configured as defined in the ep structure. Note: This
465 * function is not used for EP0.
466 *
467 * @param core_if Programming view of DWC_otg controller.
468 * @param ep The EP to activate.
469 */
470void dwc_otg_ep_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
471{
472 dwc_otg_dev_if_t *dev_if = core_if->dev_if;
473 depctl_data_t depctl;
474 volatile uint32_t *addr;
475 daint_data_t daintmsk;
476
477 daintmsk.d32 = 0;
478 /* Read DEPCTLn register */
479 if (ep->is_in == 1)
480 {
481 addr = &dev_if->in_ep_regs[ep->num]->diepctl;
482 daintmsk.ep.in = 1 << ep->num;
483 }
484 else
485 {
486 addr = &dev_if->out_ep_regs[ep->num]->doepctl;
487 daintmsk.ep.out = 1 << ep->num;
488 }
489
490 /* If the EP is already active don't change the EP Control
491 * register. */
492 depctl.d32 = DWC_READ_REG32(addr);
493 if (!depctl.b.usbactep)
494 {
495 depctl.b.mps = ep->maxpacket;
496 depctl.b.eptype = ep->type;
497 depctl.b.txfnum = ep->tx_fifo_num;
498
499
500 depctl.b.setd0pid = 1;
501
502 depctl.b.usbactep = 1;
503
504 DWC_WRITE_REG32(addr, depctl.d32);
505 }
506 {
507
508 DWC_MODIFY_REG32(&dev_if->dev_global_regs->daintmsk,0, daintmsk.d32);
509 }
510
511 ep->stall_clear_flag = 0;
512
513 return;
514}
515/**
516 * This function does the setup for a data transfer for an EP and
517 * starts the transfer. For an IN transfer, the packets will be
518 * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers,
519 * the packets are unloaded from the Rx FIFO in the ISR. the ISR.
520 *
521 * @param core_if Programming view of DWC_otg controller.
522 * @param ep The EP to start the transfer on.
523 */
524
525void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
526{
527 depctl_data_t depctl;
528 deptsiz_data_t deptsiz;
529
530 if (ep->is_in == 1)
531 {
532 dwc_otg_dev_in_ep_regs_t *in_regs = core_if->dev_if->in_ep_regs[ep->num];
533
534 depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl));
535 deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz));
536
537 if (ep->maxpacket > (ep->maxxfer / MAX_PKT_CNT))
538 ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ?\
539 ep->maxxfer : (ep->total_len - ep->xfer_len);
540 else
541 ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len - ep->xfer_len)) ?\
542 MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len);
543
544
545 /* Zero Length Packet? */
546 if ((ep->xfer_len - ep->xfer_count) == 0)
547 {
548 deptsiz.b.xfersize = 0;
549 deptsiz.b.pktcnt = 1;
550 }
551 else
552 {
553 deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count;
554 deptsiz.b.pktcnt = (ep->xfer_len - ep->xfer_count - 1 + ep->maxpacket) / ep->maxpacket;
555 #if 0/*unsigned the max value is 1023*/
556 if (deptsiz.b.pktcnt > MAX_PKT_CNT)
557 {
558 deptsiz.b.pktcnt = MAX_PKT_CNT;
559 deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
560 }
561 #endif
562 }
563
564 if((ep->xfer_len - ep->xfer_count)% ep->maxpacket== 0)
565 {
566 printf("sent_zlp = 1\n");
567 ep->sent_zlp = 1;
568 }
569
570 DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
571
572 if (ep->xfer_len > 0)
573 {
574 uint32_t fifoemptymsk = 0;
575 fifoemptymsk = 1 << ep->num;
576 DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk,0, fifoemptymsk);
577
578 }
579
580 /* EP enable, IN data in FIFO */
581 depctl.b.cnak = 1;
582 depctl.b.epena = 1;
583 DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
584#if SYNC_USB_CTRL
585 REG32(ARM_PORTA)=0x87;
586#endif
587
588 }
589 else
590 {
591 /* OUT endpoint */
592 dwc_otg_dev_out_ep_regs_t *out_regs = core_if->dev_if->out_ep_regs[ep->num];
593
594 depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl));
595 deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz));
596
597
598 if (ep->maxpacket > (ep->maxxfer / MAX_PKT_CNT))
599 ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ? ep->maxxfer : (ep->total_len - ep->xfer_len);
600 else
601 ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len - ep->xfer_len)) ? MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len);
602
603
604 if ((ep->xfer_len - ep->xfer_count) == 0)
605 {
606 deptsiz.b.xfersize = ep->maxpacket;
607 deptsiz.b.pktcnt = 1;
608 }
609 else
610 {
611 deptsiz.b.pktcnt = (ep->xfer_len - ep->xfer_count + (ep->maxpacket - 1)) / ep->maxpacket;
612 #if 0/*unsigned the max value is 1023*/
613 if (deptsiz.b.pktcnt > MAX_PKT_CNT)
614 {
615 deptsiz.b.pktcnt = MAX_PKT_CNT;
616 }
617 #endif
618 ep->xfer_len = deptsiz.b.pktcnt * ep->maxpacket + ep->xfer_count;
619 deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count;
620 }
621
622 {
623
624 DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
625 }
626 /* EP enable */
627 depctl.b.cnak = 1;
628 depctl.b.epena = 1;
629
630 DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);
631#if SYNC_USB_CTRL
632 REG32(ARM_PORTA)=0x76;
633#endif
634
635 }
636}
637
638/**
639 * This function setup a zero length transfer in Buffer DMA and
640 * Slave modes for usb requests with zero field set
641 *
642 * @param core_if Programming view of DWC_otg controller.
643 * @param ep The EP to start the transfer on.
644 *
645 */
646void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
647{
648
649 depctl_data_t depctl;
650 deptsiz_data_t deptsiz;
651
652 /* IN endpoint */
653 if (ep->is_in == 1)
654 {
655 dwc_otg_dev_in_ep_regs_t *in_regs = core_if->dev_if->in_ep_regs[ep->num];
656
657 depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl));
658 deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz));
659
660 deptsiz.b.xfersize = 0;
661 deptsiz.b.pktcnt = 1;
662 {
663 DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
664 {
665 /* Enable the Tx FIFO Empty Interrupt for this EP */
666 if (ep->xfer_len > 0)
667 {
668 uint32_t fifoemptymsk = 0;
669 fifoemptymsk = 1 << ep->num;
670 DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk,0, fifoemptymsk);
671 }
672 }
673 }
674
675 /* EP enable, IN data in FIFO */
676 depctl.b.cnak = 1;
677 depctl.b.epena = 1;
678 DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
679
680 }
681 else
682 {
683 /* OUT endpoint */
684 dwc_otg_dev_out_ep_regs_t *out_regs = core_if->dev_if->out_ep_regs[ep->num];
685
686 depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl));
687 deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz));
688
689 /* Zero Length Packet */
690 deptsiz.b.xfersize = ep->maxpacket;
691 deptsiz.b.pktcnt = 1;
692 {
693 DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
694 }
695
696 /* EP enable */
697 depctl.b.cnak = 1;
698 depctl.b.epena = 1;
699
700 DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);
701
702 }
703}
704
705/**
706 * This function does the setup for a data transfer for EP0 and starts
707 * the transfer. For an IN transfer, the packets will be loaded into
708 * the appropriate Tx FIFO in the ISR. For OUT transfers, the packets are
709 * unloaded from the Rx FIFO in the ISR.
710 *
711 * @param core_if Programming view of DWC_otg controller.
712 * @param ep The EP0 data.
713 */
714void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
715{
716 depctl_data_t depctl;
717 deptsiz0_data_t deptsiz;
718 uint32_t fifoemptymsk;
719
720 ep->total_len = ep->xfer_len;
721
722 /* IN endpoint */
723 if (ep->is_in == 1)
724 {
725 printf("ep0 tx data\n");
726 dwc_otg_dev_in_ep_regs_t *in_regs = core_if->dev_if->in_ep_regs[0];
727 depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
728 if (depctl.b.epena)
729 return;
730
731
732 /* If dedicated FIFO every time flush fifo before enable ep*/
733 dwc_otg_flush_tx_fifo(core_if, ep->tx_fifo_num);
734
735 depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
736 deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);
737
738 /* Zero Length Packet? */
739 if (ep->xfer_len == 0)
740 {
741 deptsiz.b.xfersize = 0;
742 deptsiz.b.pktcnt = 1;
743 }
744 else
745 {
746 /* Program the transfer size and packet count
747 * as follows: xfersize = N * maxpacket +
748 * short_packet pktcnt = N + (short_packet
749 * exist ? 1 : 0)
750 */
751 if (ep->xfer_len > ep->maxpacket)
752 {
753 ep->xfer_len = ep->maxpacket;
754 deptsiz.b.xfersize = ep->maxpacket;
755 }
756 else
757 {
758 deptsiz.b.xfersize = ep->xfer_len;
759 }
760 deptsiz.b.pktcnt = 1;
761
762 }
763
764
765 {
766 DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
767 }
768
769 /* EP enable, IN data in FIFO */
770 depctl.b.cnak = 1;
771 depctl.b.epena = 1;
772 DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
773
774 /**
775 * Enable the Non-Periodic Tx FIFO empty interrupt, the
776 * data will be written into the fifo by the ISR.
777 */
778
779 /* Enable the Tx FIFO Empty Interrupt for this EP */
780 if (ep->xfer_len > 0)
781 {
782 fifoemptymsk = 0;
783 fifoemptymsk |= 1 << ep->num;
784 DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk,0, fifoemptymsk);
785 }
786
787 }
788 else
789 {
790
791 /* OUT endpoint */
792 dwc_otg_dev_out_ep_regs_t *out_regs = core_if->dev_if->out_ep_regs[0];
793
794 depctl.d32 = DWC_READ_REG32(&out_regs->doepctl);
795 deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz);
796
797 /* Program the transfer size and packet count as follows:
798 * xfersize = N * (maxpacket + 4 - (maxpacket % 4))
799 * pktcnt = N */
800 /* Zero Length Packet */
801 deptsiz.b.xfersize = ep->maxpacket;
802 deptsiz.b.pktcnt = 1;
803 deptsiz.b.supcnt = 3;
804 DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
805
806 /* EP enable */
807 depctl.b.cnak = 1;
808 depctl.b.epena = 1;
809 DWC_WRITE_REG32(&(out_regs->doepctl), depctl.d32);
810
811 }
812}
813
814/**
815 * This function continues control IN transfers started by
816 * dwc_otg_ep0_start_transfer, when the transfer does not fit in a
817 * single packet. NOTE: The DIEPCTL0/DOEPCTL0 registers only have one
818 * bit for the packet count.
819 *
820 * @param core_if Programming view of DWC_otg controller.
821 * @param ep The EP0 data.
822 */
823void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
824{
825 depctl_data_t depctl;
826 deptsiz0_data_t deptsiz;
827
828 if (ep->is_in == 1)
829 {
830 dwc_otg_dev_in_ep_regs_t *in_regs = core_if->dev_if->in_ep_regs[0];
831
832 depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
833 deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);
834
835 deptsiz.b.xfersize = (ep->total_len - ep->xfer_count) > ep->maxpacket ? ep->maxpacket : (ep->total_len - ep->xfer_count);
836 deptsiz.b.pktcnt = 1;
837
838 ep->xfer_len += deptsiz.b.xfersize;
839
840 DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
841
842
843 depctl.b.cnak = 1;
844 depctl.b.epena = 1;
845 DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
846
847 /**
848 * Enable the Non-Periodic Tx FIFO empty interrupt, the
849 * data will be written into the fifo by the ISR.
850 */
851
852 /* Enable the Tx FIFO Empty Interrupt for this EP */
853 if (ep->xfer_len > 0)
854 {
855 uint32_t fifoemptymsk = 0;
856 fifoemptymsk |= 1 << ep->num;
857 DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk,0, fifoemptymsk);
858 }
859
860 }
861 else
862 {
863 dwc_otg_dev_out_ep_regs_t *out_regs = core_if->dev_if->out_ep_regs[0];
864
865 depctl.d32 = DWC_READ_REG32(&out_regs->doepctl);
866 deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz);
867
868 deptsiz.b.xfersize = ep->maxpacket;
869 deptsiz.b.pktcnt = 1;
870 DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
871 depctl.b.cnak = 1;
872 depctl.b.epena = 1;
873 DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);
874
875 }
876}
877
878
879/**
880 * This function writes a packet into the Tx FIFO associated with the
881 * EP. For non-periodic EPs the non-periodic Tx FIFO is written. For
882 * periodic EPs the periodic Tx FIFO associated with the EP is written
883 * with all packets for the next micro-frame.
884 *
885 * @param core_if Programming view of DWC_otg controller.
886 * @param ep The EP to write packet for.
887 * @param dma Indicates if DMA is being used.
888 */
889void dwc_otg_ep_write_packet(dwc_otg_core_if_t * core_if, dwc_ep_t * ep,
890 int dma)
891{
892 uint32_t i;
893 uint32_t byte_count;
894 uint32_t dword_count;
895 uint32_t *fifo;
896 uint32_t *data_buff = (uint32_t *) ep->xfer_buff;
897
898 if (ep->xfer_count >= ep->xfer_len)
899 {
900 return;
901 }
902
903 /* Find the byte length of the packet either short packet or MPS */
904 if ((ep->xfer_len - ep->xfer_count) < ep->maxpacket)
905 {
906 byte_count = ep->xfer_len - ep->xfer_count;
907 }
908 else
909 {
910 byte_count = ep->maxpacket;
911 }
912
913 /* Find the DWORD length, padded by extra bytes as neccessary if MPS
914 * is not a multiple of DWORD */
915 dword_count = (byte_count + 3) / 4;
916
917 /**@todo NGS Where are the Periodic Tx FIFO addresses
918 * intialized? What should this be? */
919
920 fifo = core_if->data_fifo[ep->num];
921 for (i = 0; i < dword_count; i++, data_buff++)
922 {
923 DWC_WRITE_REG32(fifo, *data_buff);
924
925 }
926
927
928 ep->xfer_count += byte_count;
929 ep->xfer_buff += byte_count;
930}
931
932/**
933 * Set the EP STALL.
934 *
935 * @param core_if Programming view of DWC_otg controller.
936 * @param ep The EP to set the stall on.
937 */
938void dwc_otg_ep_set_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
939{
940 depctl_data_t depctl;
941 volatile uint32_t *depctl_addr;
942 if (ep->is_in == 1)
943 {
944 depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl);
945 depctl.d32 = DWC_READ_REG32(depctl_addr);
946
947 /* set the disable and stall bits */
948 if (depctl.b.epena)
949 {
950 depctl.b.epdis = 1;
951 }
952 depctl.b.stall = 1;
953 DWC_WRITE_REG32(depctl_addr, depctl.d32);
954 }
955 else
956 {
957 depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl);
958 depctl.d32 = DWC_READ_REG32(depctl_addr);
959
960 depctl.b.stall = 1;
961 DWC_WRITE_REG32(depctl_addr, depctl.d32);
962 }
963
964 return;
965}
966
967/**
968 * Clear the EP STALL.
969 *
970 * @param core_if Programming view of DWC_otg controller.
971 * @param ep The EP to clear stall from.
972 */
973void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
974{
975 depctl_data_t depctl;
976 volatile uint32_t *depctl_addr;
977
978 if (ep->is_in == 1)
979 {
980 depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl);
981 }
982 else
983 {
984 depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl);
985 }
986
987 depctl.d32 = DWC_READ_REG32(depctl_addr);
988
989 /* clear the stall bits */
990 depctl.b.stall = 0;
991
992 /*
993 * USB Spec 9.4.5: For endpoints using data toggle, regardless
994 * of whether an endpoint has the Halt feature set, a
995 * ClearFeature(ENDPOINT_HALT) request always results in the
996 * data toggle being reinitialized to DATA0.
997 */
998 if (ep->type == DWC_OTG_EP_TYPE_INTR ||
999 ep->type == DWC_OTG_EP_TYPE_BULK)
1000 {
1001 depctl.b.setd0pid = 1; /* DATA0 */
1002 }
1003
1004 DWC_WRITE_REG32(depctl_addr, depctl.d32);
1005 return;
1006}
1007
1008/**
1009 * This function reads a packet from the Rx FIFO into the destination
1010 * buffer. To read SETUP data use dwc_otg_read_setup_packet.
1011 *
1012 * @param core_if Programming view of DWC_otg controller.
1013 * @param dest Destination buffer for the packet.
1014 * @param bytes Number of bytes to copy to the destination.
1015 */
1016void dwc_otg_read_packet(dwc_otg_core_if_t * core_if,
1017 uint8_t * dest, uint16_t bytes)
1018{
1019 int i;
1020 int word_count = (bytes + 3) / 4;
1021
1022 volatile uint32_t *fifo = core_if->data_fifo[0];
1023 uint32_t *data_buff = (uint32_t *) dest;
1024
1025
1026 for (i = 0; i < word_count; i++, data_buff++)
1027 {
1028 *data_buff = DWC_READ_REG32(fifo);
1029 }
1030
1031 return;
1032}
1033
1034/**
1035 * Flush a Tx FIFO.
1036 *
1037 * @param core_if Programming view of DWC_otg controller.
1038 * @param num Tx FIFO to flush.
1039 */
1040void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * core_if, const int num)
1041{
1042 dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
1043 volatile grstctl_t greset;
1044 int count = 0;
1045 greset.d32 = 0;
1046
1047 greset.b.txfflsh = 1;
1048 greset.b.txfnum = num;
1049if(global.g_enum == NEED_ENUM)
1050{
1051 DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
1052
1053
1054 do
1055 {
1056 greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
1057 if (++count > 10000)
1058 {
1059 break;
1060 }
1061 usdelay(10);
1062 }
1063 while (greset.b.txfflsh == 1);
1064
1065 /* Wait for 3 PHY Clocks */
1066 usdelay(10);
1067}
1068
1069}
1070
1071/**
1072 * Flush Rx FIFO.
1073 *
1074 * @param core_if Programming view of DWC_otg controller.
1075 */
1076void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * core_if)
1077{
1078 dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
1079 volatile grstctl_t greset;
1080 int count = 0;
1081 greset.d32 = 0;
1082 greset.b.rxfflsh = 1;
1083if(global.g_enum == NEED_ENUM)
1084{
1085 DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
1086
1087 do
1088 {
1089 greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
1090 if (++count > 10000)
1091 {
1092 break;
1093 }
1094 usdelay(10);
1095 }
1096 while (greset.b.rxfflsh == 1);
1097
1098 /* Wait for 3 PHY Clocks */
1099
1100 usdelay(10);
1101}
1102}
1103
1104/**
1105 * Do core a soft reset of the core. Be careful with this because it
1106 * resets all the internal state machines of the core.
1107 */
1108void dwc_otg_core_reset(dwc_otg_core_if_t * core_if)
1109{
1110 dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
1111 volatile grstctl_t greset;
1112 int count = 0;
1113 greset.d32 =0;
1114 /* Wait for AHB master IDLE state. */
1115 do
1116 {
1117 usdelay(10);
1118 greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
1119 if (++count > 100000)
1120 {
1121 return;
1122 }
1123 }
1124 while (greset.b.ahbidle == 0);
1125
1126 /* Core Soft Reset */
1127 count = 0;
1128 greset.b.csftrst = 1;
1129 DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
1130 do
1131 {
1132 greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
1133 if (++count > 10000)
1134 {
1135 break;
1136 }
1137 usdelay(10);
1138 }
1139 while (greset.b.csftrst == 1);
1140/* Wait for 3 PHY Clocks */
1141 usdelay(10);
1142}
1143
1144static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if)
1145{
1146 int i;
1147 core_if->core_params = &global.g_core_params;
1148 core_if->core_params->otg_cap = DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE;
1149 #if !USE_ASIC
1150 core_if->core_params->phy_type = DWC_PHY_TYPE_PARAM_ULPI;
1151 #else
1152 core_if->core_params->phy_type = DWC_PHY_TYPE_PARAM_UTMI;
1153 #endif
1154 core_if->core_params->speed = DWC_SPEED_PARAM_HIGH;//DWC_SPEED_PARAM_FULL
1155 core_if->core_params->phy_ulpi_ddr = dwc_param_phy_ulpi_ddr_default;
1156 core_if->core_params->phy_ulpi_ext_vbus = dwc_param_phy_ulpi_ext_vbus_default;
1157 core_if->core_params->phy_utmi_width = 8;
1158 core_if->core_params->ts_dline = dwc_param_ts_dline_default;
1159 core_if->core_params->ulpi_fs_ls = dwc_param_ulpi_fs_ls_default;
1160 core_if->core_params->en_multiple_tx_fifo = dwc_param_en_multiple_tx_fifo_default;
1161 for (i = 0; i < 15; i++)
1162 {
1163 core_if->core_params->dev_tx_fifo_size[i] = dwc_param_dev_tx_fifo_size_default;
1164 }
1165 core_if->core_params->otg_ver = 1;
1166 return 0;
1167}
1168
1169
1170
1171
1172
1173
1174