]> Git Repo - J-u-boot.git/blobdiff - drivers/usb/musb/musb_udc.c
usb: dwc3: allocate setup_buf with dma_alloc_coherent()
[J-u-boot.git] / drivers / usb / musb / musb_udc.c
index e0b4217dc3f5060c1fe8d2489f452722d804b003..696855ee3a613bcb9cfaa0eb443df5a45bc510a5 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 2009 Wind River Systems, Inc.
  * Tom Rix <[email protected]>
  *         Atin Malaviya ([email protected])
  *
  * -------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
  */
 
-#include <common.h>
-#include <usb/musb_udc.h>
+#include <hang.h>
+#include <serial.h>
+#include <usbdevice.h>
+#include <linux/delay.h>
+#include <usb/udc.h>
 #include "../gadget/ep0.h"
 #include "musb_core.h"
 #if defined(CONFIG_USB_OMAP3)
 #include "omap3.h"
 #elif defined(CONFIG_USB_AM35X)
 #include "am35x.h"
-#elif defined(CONFIG_USB_DAVINCI)
-#include "davinci.h"
 #endif
 
 /* Define MUSB_DEBUG for debugging */
@@ -97,7 +84,7 @@ do {                                                                  \
 /* static implies these initialized to 0 or NULL */
 static int debug_setup;
 static int debug_level;
-static struct musb_epinfo epinfo[MAX_ENDPOINT * 2];
+static struct musb_epinfo epinfo[MAX_ENDPOINT * 2 + 2];
 static enum ep0_state_enum {
        IDLE = 0,
        TX,
@@ -116,6 +103,8 @@ struct usb_endpoint_instance *ep0_endpoint;
 static struct usb_device_instance *udc_device;
 static int enabled;
 
+static u16 pending_intrrx;
+
 #ifdef MUSB_DEBUG
 static void musb_db_regs(void)
 {
@@ -279,7 +268,7 @@ static void musb_peri_ep0_set_address(void)
                                      __PRETTY_FUNCTION__, udc_device->address);
        } else {
                if (debug_level > 0)
-                       serial_printf("ERROR : %s Address missmatch "
+                       serial_printf("ERROR : %s Address mismatch "
                                      "sw %d vs hw %d\n",
                                      __PRETTY_FUNCTION__,
                                      udc_device->address, faddr);
@@ -641,7 +630,7 @@ static void musb_peri_ep0(void)
 static void musb_peri_rx_ep(unsigned int ep)
 {
        u16 peri_rxcount;
-       u8 peri_rxcsr = readw(&musbr->ep[ep].epN.rxcsr);
+       u16 peri_rxcsr = readw(&musbr->ep[ep].epN.rxcsr);
 
        if (!(peri_rxcsr & MUSB_RXCSR_RXPKTRDY)) {
                if (debug_level > 0)
@@ -676,7 +665,10 @@ static void musb_peri_rx_ep(unsigned int ep)
                                /* The common musb fifo reader */
                                read_fifo(ep, length, data);
 
-                               musb_peri_rx_ack(ep);
+                               if (length == peri_rxcount)
+                                       musb_peri_rx_ack(ep);
+                               else
+                                       pending_intrrx |= (1 << ep);
 
                                /*
                                 * urb's actual_length is updated in
@@ -689,18 +681,24 @@ static void musb_peri_rx_ep(unsigned int ep)
                                        serial_printf("ERROR : %s %d no space "
                                                      "in rcv buffer\n",
                                                      __PRETTY_FUNCTION__, ep);
+
+                               pending_intrrx |= (1 << ep);
                        }
                } else {
                        if (debug_level > 0)
                                serial_printf("ERROR : %s %d problem with "
                                              "endpoint\n",
                                              __PRETTY_FUNCTION__, ep);
+
+                       pending_intrrx |= (1 << ep);
                }
 
        } else {
                if (debug_level > 0)
                        serial_printf("ERROR : %s %d with nothing to do\n",
                                      __PRETTY_FUNCTION__, ep);
+
+               musb_peri_rx_ack(ep);
        }
 }
 
@@ -708,9 +706,7 @@ static void musb_peri_rx(u16 intr)
 {
        unsigned int ep;
 
-       /* Check for EP0 */
-       if (0x01 & intr)
-               musb_peri_ep0();
+       /* First bit is reserved and does not indicate interrupt for EP0 */
 
        for (ep = 1; ep < 16; ep++) {
                if ((1 << ep) & intr)
@@ -720,21 +716,16 @@ static void musb_peri_rx(u16 intr)
 
 static void musb_peri_tx(u16 intr)
 {
-       /* Check for EP0 */
+       unsigned int ep;
+
+       /* Check for EP0: first bit indicates interrupt for both RX and TX */
        if (0x01 & intr)
-               musb_peri_ep0_tx();
+               musb_peri_ep0();
 
-       /*
-        * Use this in the future when handling epN tx
-        *
-        * u8 ep;
-        *
-        * for (ep = 1; ep < 16; ep++) {
-        *      if ((1 << ep) & intr) {
-        *              / * handle tx for this endpoint * /
-        *      }
-        * }
-        */
+       for (ep = 1; ep < 16; ep++) {
+               if ((1 << ep) & intr)
+                       udc_endpoint_write(GET_ENDPOINT(udc_device, ep));
+       }
 }
 
 void udc_irq(void)
@@ -756,8 +747,6 @@ void udc_irq(void)
                        musb_peri_resume();
                }
 
-               musb_peri_ep0();
-
                if (MUSB_INTR_RESET & intrusb) {
                        usbd_device_event_irq(udc_device, DEVICE_RESET, 0);
                        musb_peri_reset();
@@ -787,13 +776,16 @@ void udc_irq(void)
                        intrrx = readw(&musbr->intrrx);
                        intrtx = readw(&musbr->intrtx);
 
+                       intrrx |= pending_intrrx;
+                       pending_intrrx = 0;
+
                        if (intrrx)
                                musb_peri_rx(intrrx);
 
                        if (intrtx)
                                musb_peri_tx(intrtx);
                } else {
-                       if (MUSB_INTR_SOF & intrusb) {
+                       if (readw(&musbr->intrtx) & 0x1) {
                                u8 faddr;
                                faddr = readb(&musbr->faddr);
                                /*
@@ -882,20 +874,9 @@ void udc_setup_ep(struct usb_device_instance *device, unsigned int id,
                ep0_endpoint->endpoint_address = 0xff;
                ep0_urb = usbd_alloc_urb(device, endpoint);
        } else if (MAX_ENDPOINT >= id) {
-               int ep_addr;
-
-               /* Check the direction */
-               ep_addr = endpoint->endpoint_address;
-               if (USB_DIR_IN == (ep_addr & USB_ENDPOINT_DIR_MASK)) {
-                       /* IN */
-                       epinfo[(id * 2) + 1].epsize = endpoint->tx_packetSize;
-               } else {
-                       /* OUT */
-                       epinfo[id * 2].epsize = endpoint->rcv_packetSize;
-               }
-
-               musb_configure_ep(&epinfo[0],
-                                 sizeof(epinfo) / sizeof(struct musb_epinfo));
+               epinfo[(id * 2) + 0].epsize = endpoint->rcv_packetSize;
+               epinfo[(id * 2) + 1].epsize = endpoint->tx_packetSize;
+               musb_configure_ep(&epinfo[0], ARRAY_SIZE(epinfo));
        } else {
                if (debug_level > 0)
                        serial_printf("ERROR : %s endpoint request %d "
@@ -957,7 +938,7 @@ int udc_init(void)
        musbr = musb_cfg.regs;
 
        /* Initialize the endpoints */
-       for (ep_loop = 0; ep_loop < MAX_ENDPOINT * 2; ep_loop++) {
+       for (ep_loop = 0; ep_loop <= MAX_ENDPOINT * 2; ep_loop++) {
                epinfo[ep_loop].epnum = (ep_loop / 2) + 1;
                epinfo[ep_loop].epdir = ep_loop % 2; /* OUT, IN */
                epinfo[ep_loop].epsize = 0;
This page took 0.033591 seconds and 4 git commands to generate.