📄 patch-2.4.4-sl811hs
字号:
+
+/***************************************************************************
+ * Function Name : regTest
+ *
+ * This routine test the Read/Write functionality of SL811HS registers
+ *
+ * 1) Store original register value into a buffer
+ * 2) Write to registers with a RAMP pattern. (10, 11, 12, ..., 255)
+ * 3) Read from register
+ * 4) Compare the written value with the read value and make sure they are
+ * equivalent
+ * 5) Restore the original register value
+ *
+ * Input: hci = data structure for the host controller
+ *
+ *
+ * Return: TRUE = passed; FALSE = failed
+ **************************************************************************/
+
+int regTest(hci_t *hci)
+{
+ int i, data, result = TRUE;
+ char buf[256];
+
+ DBGFUNC ("Enter regTest\n");
+ for (i=0x10; i < 256; i++)
+ {
+ /* save the original buffer */
+ buf[i] = (char) SL811Read(hci, i);
+
+ /* Write the new data to the buffer */
+ SL811Write(hci, i, i);
+ }
+
+ /* compare the written data */
+ for (i=0x10; i < 256; i++)
+ {
+ data = SL811Read(hci, i);
+ if (data != i)
+ {
+ DBGERR ("Pattern test failed!! value = 0x%x, s/b 0x%x\n",
+ data, i);
+ result = FALSE;
+ }
+ }
+
+ /* restore the data */
+ for (i=0x10; i < 256; i++)
+ {
+ SL811Write(hci, i, buf[i]);
+ }
+
+ return (result);
+}
+
+/***************************************************************************
+ * Function Name : regShow
+ *
+ * Display all SL811HS register values
+ *
+ * Input: hci = data structure for the host controller
+ *
+ * Return: none
+ **************************************************************************/
+
+void regShow(hci_t *hci)
+{
+ int i;
+ for (i = 0; i<256; i++)
+ {
+ printk ("offset %d: 0x%x\n", i, SL811Read(hci, i));
+ }
+}
+
+/************************************************************************
+ * Function Name : USBReset
+ *
+ * This function resets SL811HS controller and detects the speed of
+ * the connecting device
+ *
+ * Input: hci = data structure for the host controller
+ *
+ * Return: 0 = no device attached; 1 = USB device attached
+ *
+ ***********************************************************************/
+
+static int USBReset (hci_t *hci)
+{
+ int status ;
+ hcipriv_t *hp = &hci->hp;
+
+ DBGFUNC ("enter USBReset\n");
+
+
+ SL811Write(hci, SL11H_CTLREG2, 0xae);
+
+ // setup master and full speed
+
+ SL811Write(hci, SL11H_CTLREG1, 0x08 ); // reset USB
+ mdelay(20); // 20ms
+ SL811Write(hci, SL11H_CTLREG1, 0); // remove SE0
+
+ for (status=0; status < 100; status++)
+ SL811Write (hci, SL11H_INTSTATREG, 0xff); // clear all interrupt bits
+
+ status = SL811Read (hci, SL11H_INTSTATREG);
+
+ if (status & 0x40) // Check if device is removed
+ {
+ DBG ("USBReset: Device removed\n");
+ SL811Write(hci, SL11H_INTENBLREG, SL11H_INTMASK_XFERDONE
+ | SL11H_INTMASK_SOFINTR|SL11H_INTMASK_INSRMV);
+ hp->RHportStatus->portStatus &= ~(PORT_CONNECT_STAT | PORT_ENABLE_STAT);
+
+ return 0;
+ }
+
+ SL811Write (hci, SL11H_BUFLNTHREG_B, 0 ) ; //zero lenth
+ SL811Write (hci, SL11H_PIDEPREG_B, 0x50 ) ; //send SOF to EP0
+ SL811Write (hci, SL11H_DEVADDRREG_B, 0x01 ) ; //address0
+ SL811Write (hci, SL11H_SOFLOWREG, 0xe0 ) ;
+
+ if (!(status & 0x80 ))
+ {
+ /* slow speed device connect directly to root-hub */
+
+ DBG ("USBReset: low speed Device attached\n");
+ SL811Write (hci, SL11H_CTLREG1, 0x8);
+ mdelay(20);
+ SL811Write (hci, SL11H_SOFTMRREG, 0xee );
+ SL811Write (hci, SL11H_CTLREG1, 0x21 );
+
+ /* start the SOF or EOP */
+
+ SL811Write (hci, SL11H_HOSTCTLREG_B, 0x01 ) ;
+ hp->RHportStatus->portStatus |= (PORT_CONNECT_STAT
+ | PORT_LOW_SPEED_DEV_ATTACH_STAT);
+
+ /* clear all interrupt bits */
+
+ for (status=0; status < 20; status++)
+ SL811Write (hci, SL11H_INTSTATREG, 0xff);
+ }
+ else
+ {
+ /* full speed device connect directly to root hub */
+
+ DBG ("USBReset: full speed Device attached\n");
+ SL811Write (hci, SL11H_CTLREG1, 0x8);
+ mdelay(20);
+ SL811Write (hci, SL11H_SOFTMRREG, 0xae ) ;
+ SL811Write (hci, SL11H_CTLREG1, 0x01 ) ;
+
+ /* start the SOF or EOP */
+
+ SL811Write (hci, SL11H_HOSTCTLREG_B, 0x01 ) ;
+ hp->RHportStatus->portStatus |= (PORT_CONNECT_STAT);
+ hp->RHportStatus->portStatus &= ~PORT_LOW_SPEED_DEV_ATTACH_STAT;
+
+ /* clear all interrupt bits */
+
+ SL811Write (hci, SL11H_INTSTATREG, 0xff);
+
+ }
+
+ /* enable all interrupts */
+
+ SL811Write(hci, SL11H_INTENBLREG, SL11H_INTMASK_XFERDONE
+ | SL11H_INTMASK_SOFINTR|SL11H_INTMASK_INSRMV);
+
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*/
+/* tl functions */
+static inline void hc_mark_last_trans (hci_t * hci)
+{
+ hcipriv_t * hp = &hci->hp;
+ __u8 * ptd = hp->tl;
+
+ dbg ("enter hc_mark_last_trans\n");
+ if (ptd == NULL)
+ {
+ printk ("hc_mark_last_trans: ptd = null\n");
+ return;
+ }
+ if (hp->xferPktLen > 0)
+ *(ptd + hp->tl_last) |= (1 << 3);
+}
+
+static inline void hc_flush_data_cache (hci_t * hci, void * data, int len)
+{}
+
+
+/************************************************************************
+ * Function Name : hc_add_trans
+ *
+ * This function sets up the SL811HS register and transmit the USB packets.
+ *
+ * 1) Determine if enough time within the current frame to send the packet
+ * 2) Load the data into the SL811HS register
+ * 3) Set the appropriate command to the register and trigger the transmit
+ *
+ * Input: hci = data structure for the host controller
+ * len = data length
+ * data = transmitting data
+ * toggle = USB toggle bit, either 0 or 1
+ * maxps = maximum packet size for this endpoint
+ * slow = speed of the device
+ * endpoint = endpoint number
+ * address = USB address of the device
+ * pid = packet ID
+ * format =
+ * urb_state = the current stage of USB transaction
+ *
+ * Return: 0 = no time left to schedule the transfer
+ * 1 = success
+ *
+ ***********************************************************************/
+
+static inline int hc_add_trans (hci_t * hci, int len, void * data,
+ int toggle, int maxps, int slow, int endpoint, int address, int pid, int format, int urb_state)
+{
+ hcipriv_t * hp = &hci->hp;
+ __u16 speed;
+ int ii, jj, kk;
+
+ DBGFUNC ("enter hc_addr_trans: len =0x%x, toggle:0x%x, endpoing:0x%x,"
+ " addr:0x%x, pid:0x%x,format:0x%x\n", len, toggle, endpoint, i
+ address, pid, format);
+
+ if (len > maxps)
+ {
+ len = maxps;
+ }
+
+ speed = hp->RHportStatus->portStatus;
+ if (speed & PORT_LOW_SPEED_DEV_ATTACH_STAT)
+ {
+// ii = (8*7*8 + 6*3) * len + 800;
+ ii = 8*8*len + 1024;
+ }
+ else
+ {
+ if (slow)
+ {
+// ii = (8*7*8 + 6*3) * len + 800;
+ ii = 8*8*len + 2048;
+ }
+ else
+// ii = (8*7 + 6*3)*len + 110;
+ ii = 8*len + 256;
+ }
+
+ ii += 2*10 * len;
+
+
+ jj = SL811Read(hci, SL11H_SOFTMRREG);
+ kk = (jj & 0xFF) * 64 - ii;
+
+ if (kk < 0)
+ {
+ DBGVERBOSE ("hc_add_trans: no bandwidth for schedule, ii = 0x%x,"
+ "jj = 0x%x, len =0x%x, active_trans = 0x%x\n", ii, jj,
+ len, hci->active_trans);
+ return (-1);
+ }
+
+ if (pid != PID_IN)
+ {
+ /* Load data into hc */
+
+ SL811BufWrite(hci, SL11H_DATA_START, (__u8 *) data, len);
+ }
+
+ /* transmit */
+
+ SL11StartXaction(hci, (__u8) address, (__u8) endpoint,
+ (__u8) pid, len, toggle, slow, urb_state);
+
+ return len;
+}
+
+
+/************************************************************************
+ * Function Name : hc_parse_trans
+ *
+ * This function checks the status of the transmitted or received packet
+ * and copy the data from the SL811HS register into a buffer.
+ *
+ * 1) Check the status of the packet
+ * 2) If successful, and IN packet then copy the data from the SL811HS register
+ * into a buffer
+ *
+ * Input: hci = data structure for the host controller
+ * actbytes = pointer to actual number of bytes
+ * data = data buffer
+ * cc = packet status
+ * length = the urb transmit length
+ * pid = packet ID
+ * urb_state = the current stage of USB transaction
+ *
+ * Return: 0
+ ***********************************************************************/
+
+static inline int hc_parse_trans (hci_t * hci, int * actbytes, __u8 * data,
+ int * cc, int * toggle, int length, int pid, int urb_state)
+{
+ __u8 addr;
+ __u8 len;
+
+ DBGFUNC ("enter hc_parse_trans\n");
+
+ /* get packet status; convert ack rcvd to ack-not-rcvd */
+
+ *cc = (int) SL811Read(hci, SL11H_PKTSTATREG);
+
+
+ if (*cc & (SL11H_STATMASK_ERROR | SL11H_STATMASK_TMOUT |
+ SL11H_STATMASK_OVF | SL11H_STATMASK_NAK | SL11H_STATMASK_STALL))
+ {
+ if (*cc & SL11H_STATMASK_OVF)
+ DBGERR ("parse trans: error recv ack, cc = 0x%x, TX_BASE_Len = "
+ "0x%x, TX_count=0x%x\n", *cc,
+ SL811Read(hci, SL11H_BUFLNTHREG),
+ SL811Read(hci, SL11H_XFERCNTREG));
+
+ }
+ else
+ {
+ DBGVERBOSE ("parse trans: recv ack, cc = 0x%x, len = 0x%x, \n",
+ *cc, length);
+
+ /* Successful data */
+
+ if ((pid == PID_IN) && (urb_state != US_CTRL_SETUP))
+ {
+
+ /* Find the base address */
+
+ addr = SL811Read(hci, SL11H_BUFADDRREG);
+
+ /* Find the Transmit Length */
+
+ len = SL811Read(hci, SL11H_BUFLNTHREG);
+
+ /* The actual data length = xmit length reg - xfer count reg */
+
+ *actbytes = len - SL811Read(hci, SL11H_XFERCNTREG);
+
+ if ((data != NULL) && (*actbytes > 0))
+ {
+ SL811BufRead (hci, addr, data, *actbytes);
+
+ }
+ else if ((data == NULL) && (*actbytes <=0))
+ {
+ DBGERR ("hc_parse_trans: data = NULL or actbyte = 0x%x\n",
+ *actbytes);
+ return 0;
+ }
+ }
+ else if (pid == PID_OUT)
+ {
+ *actbytes = length;
+ }
+ else
+ {
+ // printk ("ERR:parse_trans, pid != IN or OUT, pid = 0x%x\n", pid);
+ }
+ *toggle = !*toggle;
+ }
+
+ return 0;
+}
+
+/************************************************************************
+ * Function Name : hc_start_int
+ *
+ * This function enables SL811HS interrupts
+ *
+ * Input: hci = data structure for the host controller
+ *
+ * Return: none
+ ***********************************************************************/
+
+static void hc_start_int (hci_t *hci)
+{
+#ifdef HC_SWITCH_INT
+ int mask = SL11H_INTMASK_XFERDONE | SL11H_INTMASK_SOFINTR |
+ SL11H_INTMASK_INSRMV | SL11H_INTMASK_USBRESET;
+ SL811Write (hci, IntEna, mask);
+#endif
+}
+
+/************************************************************************
+ * Function Name : hc_stop_int
+ *
+ * This function disables SL811HS interrupts
+ *
+ * Input: hci = data structure for the host controller
+ *
+ * Return: none
+ ***********************************************************************/
+
+static void hc_stop_int (hci_t *hci)
+{
+#ifdef HC_SWITCH_INT
+ SL811Write(hci, SL11H_INTSTATREG, 0xff);
+// SL811Write(hci, SL11H_INTENBLREG, SL11H_INTMASK_INSRMV);
+
+#endif
+}
+
+
+/************************************************************************
+ * Function Name : handleInsRmvIntr
+ *
+ * This function handles the insertion or removal of device on SL811HS.
+ * It resets the controller and updates the port status
+ *
+ * Input: hci = data structure for the host controller
+ *
+ * Return: none
+ ***********************************************************************/
+
+void handleInsRmvIntr (hci_t * hci)
+{
+ hcipriv_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -