1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * BCM1250CPCI USB Driver File: sl11h.c
6 * USB Include definitions
9 * Parts of code extracted from Scanlogic USB demo driver
11 *********************************************************************
13 * Copyright 2000,2001,2002,2003
14 * Broadcom Corporation. All rights reserved.
16 * This software is furnished under license and may be used and
17 * copied only in accordance with the following terms and
18 * conditions. Subject to these conditions, you may download,
19 * copy, install, use, modify and distribute modified or unmodified
20 * copies of this software in source and/or binary form. No title
21 * or ownership is transferred hereby.
23 * 1) Any source code used, modified or distributed must reproduce
24 * and retain this copyright notice and list of conditions
25 * as they appear in the source file.
27 * 2) No right is granted to use any trade name, trademark, or
28 * logo of Broadcom Corporation. The "Broadcom Corporation"
29 * name may not be used to endorse or promote products derived
30 * from this software without the prior written permission of
31 * Broadcom Corporation.
33 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
34 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
35 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
36 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
37 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
38 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
39 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
40 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
41 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
42 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
43 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
44 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
45 * THE POSSIBILITY OF SUCH DAMAGE.
46 ********************************************************************* */
52 #include "lib_types.h"
53 #include "lib_printf.h"
54 #include "lib_string.h"
55 #include "cfe_timer.h"
57 #include "sb1250_regs.h"
58 #include "sb1250_smbus.h"
59 #include "bcm1250cpci.h"
62 #define SBWRITEUSB(csr,val) *((volatile unsigned char *) PHYS_TO_K1(csr)) = (val)
63 #define SBREADUSB(csr) (*((volatile unsigned char *) PHYS_TO_K1(csr)))
66 unsigned short crc5(unsigned short f
);
67 unsigned int usbXfer(unsigned char pid
, unsigned short crc
, unsigned int len
, unsigned char *buf
);
68 short ep0Xfer(PSetupPKG setup
, unsigned char *pData
);
69 short VendorCmd(unsigned char bReq
,unsigned char bCmd
,unsigned short wValue
,unsigned short wIndex
,unsigned short wLen
,unsigned char* pData
);
70 short GetDesc(unsigned short wValue
, unsigned int cDesc
, void * desc
);
71 short SetAddress(unsigned short addr
);
72 short uDataRead(unsigned int cData
,void * pData
);
73 short uDataWrite(unsigned int cData
,void * pData
);
74 short uCloseUsbDev(void);
75 int speed_detect(void);
78 /*--------------------------------------------------------------------------
80 * Input: address = address of SL11 register or memory
81 * Input: port = usb port
83 *--------------------------------------------------------------------------
85 unsigned char SL11Read(unsigned char address
)
88 printf("Invalid register access, register %x\n");
91 // printf("Address = %08X\n",PHYS_TO_K1(USBCTL_PHYS));
92 SBWRITEUSB(USBCTL_PHYS
,address
);
93 // printf("Address = %08X\n",PHYS_TO_K1(USBCTL_PHYS + A0_OFFSET));
94 return(SBREADUSB(USBCTL_PHYS
+ A0_OFFSET
));
97 /*--------------------------------------------------------------------------
99 * Input: address = address of SL11 register or memory, d = data
100 * Input: port = usb port
101 * Input: data = data to output
102 *--------------------------------------------------------------------------
104 void SL11Write(unsigned char address
, unsigned char data
)
106 if (address
> 0xff) {
107 printf("Invalid register access, register %x\n");
109 SBWRITEUSB(USBCTL_PHYS
,address
);
110 SBWRITEUSB(USBCTL_PHYS
+ A0_OFFSET
,data
);
113 /*--------------------------------------------------------------------------
114 * Buffer Read from SL11
115 * Input: address = address of SL11 register or memory
116 * byte_count = byte count
117 * buffer = char buffer
119 *--------------------------------------------------------------------------
121 void SL11BufRead(short address
,unsigned char *buffer
, short byte_count
)
123 if (byte_count
<= 0) return;
124 SBWRITEUSB(USBCTL_PHYS
,address
);
125 while (byte_count
--) *buffer
++ = SBREADUSB(USBCTL_PHYS
+ A0_OFFSET
);
128 /*--------------------------------------------------------------------------
129 * Buffer Write to SL11
130 * Input: address = address of SL11 register or memory
131 * byte_count = byte count
132 * buffer = char buffer
133 *--------------------------------------------------------------------------
135 void SL11BufWrite(short address
, unsigned char *buffer
, short byte_count
)
137 if(byte_count
<= 0) return;
138 SBWRITEUSB(USBCTL_PHYS
,address
);
139 while (byte_count
--) SBWRITEUSB(USBCTL_PHYS
+ A0_OFFSET
,*buffer
++);
143 //--------------------------------------------------------------------------
144 // Delayms mili second
145 //--------------------------------------------------------------------------
146 //void Delayms(unsigned int tt)
148 // unsigned int time;
149 // time=GetTickCount();
150 // while(GetTickCount() < time+tt);
153 /****************************************************************************
154 * Full-speed and slow-speed detect
155 ****************************************************************************/
156 int speed_detect(void)
162 SL11Write(IntEna
, 0x63); // USBA/B, Insert/Remove,USBRest/Resume.
163 SL11Write(cSOFcnt
, 0xae); // Set SOF high counter, no change D+/D-
164 // SL11Write(CtrlReg, 0x48); // Setup Normal Operation
165 SL11Write(CtrlReg
, 0x08); // Setup Normal Operation
166 SL11Write(CtrlReg
, (unsigned char)i
); // Disable USB transfer operation and SOF
167 SL11Write(cSOFcnt
, 0xae); // Set SOF high counter, no change D+/D-
168 // SL11Write(CtrlReg, 0x48); // Clear SL811H mode and setup normal operation
169 SL11Write(CtrlReg
, 0x08); // Clear SL811H mode and setup normal operation
170 cfe_sleep(1); // Sleep 10 ms
171 SL11Write(CtrlReg
, 0); // Disable USB transfer operation and SOF
172 cfe_sleep(1); // Sleep 10 ms (original file 1ms)
173 SL11Write(IntStatus
,0xff);
174 i
= SL11Read(IntStatus
); // Read Interrupt Status
177 printf("Device is Removed\n");
181 if ((i
& 0x80) == 0) { // Checking full or slow speed
182 printf("Slow Speed is detected %x\n", i
);
183 SL11Write(cSOFcnt
,0xee); // Set up Master and Slow Speed direct and SOF cnt high=0x2e
184 SL11Write(cDATASet
,0xe0); // SOF Counter Low = 0xe0; 1ms interval
185 SL11Write(CtrlReg
,0x21); // Setup 6MHz and EOP enable
188 printf("Full Speed is detected %x\n", i
);
189 SL11Write(cSOFcnt
,0xae); // Set up Master and Slow Speed direct and SOF cnt high=0x2e
190 SL11Write(cDATASet
,0xe0); // SOF Counter Low = 0xe0; 1ms interval
191 SL11Write(CtrlReg
,0x05); // Setup 48MHz and SOF enable
193 SL11Write(EP0Status
, 0x50);
194 SL11Write(EP0Counter
, 0);
195 SL11Write(EP0Control
, 0x01); // start generate SOF or EOP
196 cfe_sleep(3); // Sleep 30 ms
197 // Delayms(25); // Hub required approx. 24.1mS
203 /*-------------------------------------------------------------------------
206 * Output: return 0 = no error
207 *-------------------------------------------------------------------------
209 int SL11HMemTest(void)
214 /* Write Data to buffer */
215 for (i
=EP0Buf
; i
<sMemSize
; i
++)
216 SL11Write((unsigned char)i
,(unsigned char)i
);
218 /* Verify Data in buffer using byte checks */
219 for (i
=EP0Buf
; i
<sMemSize
; i
++) {
220 if ((unsigned char)i
!= SL11Read((unsigned char)i
))
222 SL11Write ((unsigned char)i
,(unsigned char)~i
);
223 if ((unsigned char)~i
!= SL11Read((unsigned char)i
))
227 /* Write data to buffer using auto increment mode */
228 SBWRITEUSB(USBCTL_PHYS
,EP0Buf
);
229 for (i
=EP0Buf
; i
<sMemSize
; i
++)
230 SBWRITEUSB(USBCTL_PHYS
+ A0_OFFSET
,i
);
232 /* Verify data in buffer using auto increment mode */
233 SBWRITEUSB(USBCTL_PHYS
,EP0Buf
);
234 for (i
=EP0Buf
; i
<sMemSize
; i
++) {
235 if ((unsigned char)i
!= SBREADUSB(USBCTL_PHYS
+ A0_OFFSET
))
236 //(unsigned char)*(unsigned char *)(PHYS_TO_K1(USBCTL_PHYS + A0_OFFSET)))
240 /* Clear memory in buffer using auto increment mode */
241 SBWRITEUSB(USBCTL_PHYS
,EP0Buf
);
242 for (i
=EP0Buf
; i
<sMemSize
; i
++)
243 SBWRITEUSB(USBCTL_PHYS
+ A0_OFFSET
,0);
247 /*-------------------------------------------------------------------------
251 *-------------------------------------------------------------------------
257 tmp
= SL11Read(CtrlReg
);
258 SL11Write(CtrlReg
, tmp
| 0x08);
259 cfe_sleep(CFE_HZ
/ 4); // Delay 250 ms
260 SL11Write(CtrlReg
, tmp
| 0x18);
261 cfe_sleep(CFE_HZ
/ 6); // Delay 166 ms
262 SL11Write(CtrlReg
, tmp
| 0x08);
263 cfe_sleep(CFE_HZ
/ 10); // Delay 100ms
265 // SL11Write(CtrlReg, tmp & 0xBF);
268 // SL11Write(CtrlReg, 8); /* Setup USB Reset */
269 // cfe_sleep(CFE_HZ / 10); /* Delay 100ms */
270 // SL11Write(CtrlReg, 0); /* Enable USB */
271 // cfe_sleep(CFE_HZ / 10); /* Delay 100ms */
272 // SL11Write(0x0d, 0xff);
277 // tmp = SL11Read(CtrlReg);
278 // SL11Write(CtrlReg, (BYTE)(tmp | 8)); // Setup USB Reset
280 // SL11Write(CtrlReg, tmp); // enable USB
285 /****************************************************************************
286 * SL811H mode Hardware SOF/EOP generation
287 ****************************************************************************/
289 //--------------------------------------------------------------------------
290 // Sending EOP packet
291 // -- (Not used in SL811H)
292 //--------------------------------------------------------------------------
294 /*--------------------------------------------------------------------------
296 *--------------------------------------------------------------------------
298 unsigned short crc5(unsigned short f
)
299 { unsigned short i
,seed
=0x1f,t
=f
,flag
;
307 return((f
&0x7ff)|((seed
&0x1f)<<11));
310 /*--------------------------------------------------------------------------
312 *--------------------------------------------------------------------------
315 unsigned short EP0CRC
=0; /* Endpoint 0: addr + (ep0<<7) */
316 unsigned short ReadCRC
=0; /* current Read Endpoint: addr + (epx<<7) */
317 unsigned short WriteCRC
=0; /* current Write Endpoint: addr + (epx<<7) */
318 unsigned char hUsbNum
=0; /* Device address & number of USB */
319 unsigned char ep0Len
=0;
321 /*--------------------------------------------------------------------------
323 * return 0 on Success
324 * Status bit for register EP0Status
325 * if (result&0x40) Device return NAKs, forever
326 * if (result&0x02) Device Error Bit
327 * if (result&0x04) Device Time out
328 * if (result&0x80) Device return STALL
329 *--------------------------------------------------------------------------
331 unsigned int usbXfer(unsigned char pid
, unsigned short crc
, unsigned int len
, unsigned char *buf
)
334 short result
=0, retry
=0, bLen
, rLen
;
335 unsigned char Cmd
=DATA0_RD
, sMem
=0x40;
337 SL11Write(0x40,pid
); /* PID */
338 SL11BufWrite(0x41,(unsigned char*)&crc
,2); /* 2 bytes CRC */
339 if (len
>=(unsigned int)ep0Len
) {
340 /* setup ping pong buffer */
341 printf("Setting up ping pong\n");
342 SL11Write(0x90,pid
); /* PID */
343 SL11BufWrite(0x91,(unsigned char*)&crc
,2); /* 2 bytes CRC */
350 printf("Not PID IN\n");
351 SL11BufWrite(0x43,buf
,rLen
); /* DATA to SL11 Memory */
354 SL11Write(EP0XferLen
,(unsigned char)(0x03+rLen
));
355 SL11Write(EP0Address
,sMem
);
356 printf("Setting up transfer\n");
359 SL11Write(0x0d,0xff); /* Clear Interrupts */
360 SL11Write(EP0Status
,0);
361 SL11Write(EP0Control
,Cmd
); /* Enable ARM */
364 bLen
= ((unsigned int)(len
- rLen
) >= (unsigned int)ep0Len
) ? (unsigned char)ep0Len
: (unsigned char)(len
- rLen
);
365 sMem
= (Cmd
& 0x40) ? 0x40 : 0x90; /* next ping pong buffer */
366 if ((pid
!= PID_IN
) && !retry
) /* Write ahead for ping pong buffer */
367 SL11BufWrite((unsigned char)(sMem
+ 3),buf
+ rLen
,bLen
);
369 printf("Setting up timer\n");
370 TIMER_SET(time
,TIMEOUT
);
371 while(!(SL11Read(0x0d) & 1)) { /* check interrupt bit */
372 if(TIMER_EXPIRED(time
)) {
373 printf("TimeOut, Abort\n");
380 printf("Fell out of timer\n");
381 // time=GetTickCount();
382 // while(!(SL11Read(0x0d) & 1)) /* check interrupt bit */
383 // if(GetTickCount() > time+TIMEOUT) {
384 // printf("TimeOut, Abort\n");
388 result
=SL11Read(EP0Status
);
389 if (result
& 1) { /* ACK bit */
391 Cmd
^= 0x40; /* toggle DATA0/DATA1 */
392 // rLen = (unsigned char)(SL11Read(EP0XferLen)-SL11Read(EP0Counter)-3);
393 len
-= rLen
; /* rLen = actual read/write */
395 SL11Write(EP0XferLen
,(unsigned char)(0x03 + bLen
));
396 SL11Write(EP0Address
,sMem
); /* data addr */
397 SL11Write(0x0d,0xff); // SL11Write(EP0Counter,0x00);
398 SL11Write(EP0Control
,Cmd
); /* Enable ARM */
401 SL11BufRead((short)((Cmd
& 0x40) ? 0x43 : 0x93),buf
,rLen
);
403 if (result
& 0x20) // payload should be check
406 if (len
) goto XferLoop
;
407 else break; // on SUCCESS
409 if (result
& 0x80) break; // STALL
410 } while (retry
-- < MAX_RETRY
);
412 if (result
& 4) USBReset();
413 printf("PID=%x Result = %x len=%d\n",pid
, result
,len
);
414 if (result
& 1) return len
;
418 /***********************************************************************
420 * Description : Endpoint 0 cmd block
421 * Parameters : hUsbDev
422 * bReq Read/Write Control
423 * bCmd Command Opcode
424 * wValue User 1st Parameter
425 * wIndex User 2nd Parameter
426 * wLen Length for pData
427 * pData User's data buffer pointer
428 * Return : TRUE means successful, else FAIL
429 **********************************************************************/
430 short ep0Xfer(PSetupPKG setup
, unsigned char *pData
)
432 unsigned short pid
=PID_IN
, wLen
= setup
->wLength
;
434 if (usbXfer(PID_SETUP
,EP0CRC
,8,(unsigned char*)setup
)==-1) return FALSE
;
435 printf("Survived First\n");
437 if (setup
->bmRequest
&0x80) {
439 wLen
= (unsigned short)usbXfer(PID_IN
,EP0CRC
,wLen
,pData
);
441 wLen
=(unsigned short)usbXfer(PID_OUT
,EP0CRC
,wLen
,pData
);
444 usbXfer((unsigned char)pid
,EP0CRC
,0,NULL
);
445 // return (wLen >= 0);
450 short VendorCmd(unsigned char bReq
,unsigned char bCmd
,unsigned short wValue
,unsigned short wIndex
,unsigned short wLen
,unsigned char* pData
)
453 setup
.bmRequest
= bReq
;
454 setup
.bRequest
= bCmd
;
455 setup
.wValue
= wValue
;
456 setup
.wIndex
= wIndex
;
457 setup
.wLength
= wLen
;
458 return (ep0Xfer(&setup
, pData
));
461 /*--------------------------------------------------------------------------
464 *--------------------------------------------------------------------------
466 short GetDesc(unsigned short wValue
, unsigned int cDesc
, void * desc
)
468 return VendorCmd(0x80, 6, wValue
, 0, (unsigned short)cDesc
, desc
);
471 short SetAddress(unsigned short addr
)
473 return VendorCmd(0x00, 5, addr
, 0, 0, NULL
);
476 /***************************************************************************/
477 short uDataRead(unsigned int cData
,void * pData
)
479 return usbXfer(PID_IN
,ReadCRC
,cData
,(unsigned char*)pData
)==0;
482 /***************************************************************************/
483 short uDataWrite(unsigned int cData
,void * pData
)
485 return usbXfer(PID_OUT
,WriteCRC
,cData
,(unsigned char*)pData
)==0;
488 /***************************************************************************/
489 #define TMPSIZE 64 /* should use small buffer for SL11R */
490 static unsigned char tmp
[TMPSIZE
]; /* temp buffer */
491 short uFindUsbDev(unsigned short UsbProd
)
501 EP0CRC
= crc5(0); /* address = 0, endpoint = 0 */
503 printf("Device 0: .. ");
505 pDev
= (pDevDesc
) & tmp
[0];
506 printf("Getting Descriptor\n");
507 if (!GetDesc(DEVICE
<< 8,0x40,tmp
)) return FALSE
;
508 printf("Setting Address\n");
509 if (!SetAddress(hUsbAddr
)) return FALSE
;
511 printf("len=%02x ep0Len=%d\n",pDev
->bLength
,pDev
->bMaxPacketSize0
);
512 ep0Len
= (pDev
->bMaxPacketSize0
&0xff)?pDev
->bMaxPacketSize0
:8;
514 printf("Device 2: ..");
515 EP0CRC
= crc5((unsigned short)(hUsbAddr
+ (0 << 7))); /* new Endpoint 0 CRC */
517 if (!GetDesc(DEVICE
<< 8,0x20,tmp
)) return FALSE
;
518 printf("Vendor: %04x Product: %04x\n",pDev
->idVendor
,pDev
->idProduct
);
520 if (!GetDesc(CONFIGURATION
<< 8,64,tmp
)) return FALSE
;
521 pConf
= (pConfDesc
) & tmp
[0];
522 printf("Len=%d, type: %02x\n", pConf
->wLength
, pConf
->bType
);
523 if (!GetDesc(CONFIGURATION
<< 8,TMPSIZE
,tmp
)) return FALSE
;
525 pIntf
= (pIntfDesc
) & tmp
[tmp
[0]]; /* point to Interface Desc */
526 pEP
= (pEPDesc
)&tmp
[tmp
[0]+pIntf
->bLength
]; /* point to EP Desc */
527 printf("Number of Endpoint = %d\n",pIntf
->bEndPoints
);
530 if (pIntf
->bEndPoints
) hUsbNum
= 1;
533 for (i
=1; i
<= pIntf
->bEndPoints
; i
++) {
534 printf("EndPoint Addr %02x Attr %02x wLength=%04x\n",pEP
->bEPAdd
, pEP
->bAttr
, pEP
->wPayLoad
);
535 if (pEP
->bAttr
== 1) {
536 printf("Iso Endpoint doesnot supported\n");
539 if (pEP
->wPayLoad
!= 0x40) {
540 printf("Endpoint Payload requires = 0x40\n");
543 if (pEP
->bEPAdd
&0x80)
544 ReadCRC
= crc5((unsigned short)(hUsbAddr
+ (i
<< 7))); /* Read Endpoint CRC */
546 WriteCRC
=crc5((unsigned short)(hUsbAddr
+ (i
<< 7))); /* Write Endpoint CRC */
547 (unsigned char*)pEP
+= pEP
->bLength
;
555 short uCloseUsbDev(void)
561 /*--------------------------------------------------------------------------
563 *--------------------------------------------------------------------------
568 #define IMSIZE 256*1024
569 unsigned char ibuf[IMSIZE];
574 for (data=0; data<IMSIZE; data++)
579 printf("SL11H Memory test fail or SL11H Device not Install\n");
583 printf("SL11H Memory test PASS\n");
587 printf("Hit any key to contine\n");
593 if (uFindUsbDev(0x4ce))
594 printf("FindUsbDev: SUCCESS\n");
596 printf("FindUsbDev: FAIL\n");
604 uVendorCmdRead(0x48, 0xc00, 0xc00, 64, tmp);
605 printf("Return data %04x\n",*(unsigned short*)&tmp[0]);
609 printf("Get data => "); scanf("%x",&data);
610 printf("data enter = %x\n",data);
611 uVendorCmdWrite(0x47, 0xc00, (unsigned short)data, 0, NULL);
615 printf("Get Read data size => "); scanf("%x",&data);
616 if (data>IMSIZE) data = IMSIZE;
617 printf("data enter = %x\n",data);
618 uVendorCmdWrite(0x4a,(unsigned short)(data>>16), (unsigned short)data, 0, NULL);
619 printf("Status = %x\n",uDataRead(data, ibuf));
620 for (data=0; data<12; data++)
621 printf("%02x ",ibuf[data]); printf("\n");
625 printf("Get Write data size => "); scanf("%x",&data);
626 if (data>IMSIZE) data = IMSIZE;
627 printf("data enter = %x\n",data);
628 uVendorCmdWrite(0x4b,(unsigned short)(data>>16), (unsigned short)data, 0, NULL);
629 printf("Status = %x\n",uDataWrite(data, ibuf));