📄 uboot-s3c2410_udc.patch
字号:
+ }+ if ((ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && urb) {+ /* Read pending data from fifo */+ u32 fifo_count = fifo_count_out();+ int is_last = 0;+ u32 i, urb_avail = urb->buffer_length - urb->actual_length;+ u8 *cp = urb->buffer + urb->actual_length;++ if (fifo_count < endpoint->rcv_packetSize)+ is_last = 1;++ debug("fifo_count=%u is_last=%, urb_avail=%u)\n",+ fifo_count, is_last, urb_avail);++ if (fifo_count < urb_avail)+ urb_avail = fifo_count;++ for (i = 0; i < urb_avail; i++)+ *cp++ = inb(ep_fifo_reg[ep]);++ if (is_last)+ outl(ep_csr1 & ~S3C2410_UDC_OCSR1_PKTRDY,+ S3C2410_UDC_OUT_CSR1_REG);++ usbd_rcv_complete(endpoint, urb_avail, 0);+ }+ }++ urb = endpoint->rcv_urb;+}++/*+-------------------------------------------------------------------------------+*/++/* this is just an empty wrapper for usbtty who assumes polling operation */+void udc_irq(void)+{+}++/* Handle general USB interrupts and dispatch according to type.+ * This function implements TRM Figure 14-13.+ */+void s3c2410_udc_irq(void)+{+ struct usb_endpoint_instance *ep0 = udc_device->bus->endpoint_array;+ u_int32_t save_idx = inl(S3C2410_UDC_INDEX_REG);++ /* read interrupt sources */+ u_int32_t usb_status = inl(S3C2410_UDC_USB_INT_REG);+ u_int32_t usbd_status = inl(S3C2410_UDC_EP_INT_REG);++ //debug("< IRQ usbs=0x%02x, usbds=0x%02x start >", usb_status, usbd_status);++ /* clear interrupts */+ outl(usb_status, S3C2410_UDC_USB_INT_REG);++ if (usb_status & S3C2410_UDC_USBINT_RESET) {+ //serial_putc('R');+ debug("RESET pwr=0x%x\n", inl(S3C2410_UDC_PWR_REG));+ udc_setup_ep(udc_device, 0, ep0);+ outl(S3C2410_UDC_EP0_CSR_SSE|S3C2410_UDC_EP0_CSR_SOPKTRDY, S3C2410_UDC_EP0_CSR_REG);+ ep0->state = EP0_IDLE;+ usbd_device_event_irq (udc_device, DEVICE_RESET, 0);+ }++ if (usb_status & S3C2410_UDC_USBINT_RESUME) {+ debug("RESUME\n");+ usbd_device_event_irq(udc_device, DEVICE_BUS_ACTIVITY, 0);+ }++ if (usb_status & S3C2410_UDC_USBINT_SUSPEND) {+ debug("SUSPEND\n");+ usbd_device_event_irq(udc_device, DEVICE_BUS_INACTIVE, 0);+ }++ /* Endpoint Interrupts */+ if (usbd_status) {+ int i;++ if (usbd_status & S3C2410_UDC_INT_EP0) {+ outl(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_REG);+ s3c2410_udc_ep0();+ }++ for (i = 1; i < 5; i++) {+ u_int32_t tmp = 1 << i;++ if (usbd_status & tmp) {+ /* FIXME: Handle EP X */+ outl(tmp, S3C2410_UDC_EP_INT_REG);+ s3c2410_udc_epn(i);+ }+ }+ }+ S3C2410_UDC_SETIX(save_idx);+}++/*+-------------------------------------------------------------------------------+*/+++/*+ * Start of public functions.+ */++/* Called to start packet transmission. */+void udc_endpoint_write (struct usb_endpoint_instance *endpoint)+{+ unsigned short epnum =+ endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK;++ debug("Entering for ep %x ", epnum);++ if (endpoint->tx_urb) {+ u32 ep_csr1;+ debug_urb_buffer("We have an URB, transmitting", endpoint);++ s3c2410_write_noniso_tx_fifo(endpoint);++ S3C2410_UDC_SETIX(epnum);++ ep_csr1 = inl(S3C2410_UDC_IN_CSR1_REG);+ outl(ep_csr1|S3C2410_UDC_ICSR1_PKTRDY, S3C2410_UDC_IN_CSR1_REG);+ } else+ debug("\n");+}++/* Start to initialize h/w stuff */+int udc_init (void)+{+ S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();+ S3C24X0_INTERRUPT * irq = S3C24X0_GetBase_INTERRUPT();++ udc_device = NULL;++ /* Set and check clock control.+ * We might ought to be using the clock control API to do+ * this instead of fiddling with the clock registers directly+ * here.+ */+ clk_power->CLKCON |= (1 << 7);++ /* Print banner with device revision */+ printf("USB: S3C2410 USB Deviced\n");++ /*+ * At this point, device is ready for configuration...+ */+ outl(0x00, S3C2410_UDC_EP_INT_EN_REG);+ outl(0x00, S3C2410_UDC_USB_INT_EN_REG);++ irq->INTMSK &= ~BIT_USBD;++ return 0;+}++/*+ * udc_setup_ep - setup endpoint+ *+ * Associate a physical endpoint with endpoint_instance+ */+int udc_setup_ep (struct usb_device_instance *device,+ unsigned int ep, struct usb_endpoint_instance *endpoint)+{+ int ep_addr = endpoint->endpoint_address;+ int packet_size;+ int attributes;+ u_int32_t maxp;++ S3C2410_UDC_SETIX(ep);++ if (ep) {+ if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {+ /* IN endpoint */+ outl(S3C2410_UDC_ICSR1_FFLUSH|S3C2410_UDC_ICSR1_CLRDT,+ S3C2410_UDC_IN_CSR1_REG);+ outl(S3C2410_UDC_ICSR2_MODEIN, S3C2410_UDC_IN_CSR2_REG);+ packet_size = endpoint->tx_packetSize;+ attributes = endpoint->tx_attributes;+ } else {+ /* OUT endpoint */+ outl(S3C2410_UDC_ICSR1_CLRDT, S3C2410_UDC_IN_CSR1_REG);+ outl(0, S3C2410_UDC_IN_CSR2_REG);+ outl(S3C2410_UDC_OCSR1_FFLUSH|S3C2410_UDC_OCSR1_CLRDT,+ S3C2410_UDC_OUT_CSR1_REG);+ outl(0, S3C2410_UDC_OUT_CSR2_REG);+ packet_size = endpoint->rcv_packetSize;+ attributes = endpoint->rcv_attributes;+ }+ } else+ packet_size = endpoint->tx_packetSize;++ switch (packet_size) {+ case 8:+ maxp = S3C2410_UDC_MAXP_8;+ break;+ case 16:+ maxp = S3C2410_UDC_MAXP_16;+ break;+ case 32:+ maxp = S3C2410_UDC_MAXP_32;+ break;+ case 64:+ maxp = S3C2410_UDC_MAXP_64;+ break;+ default:+ debug("invalid packet size %u\n", packet_size);+ return -1;+ }++ debug("setting up endpoint %u addr %x packet_size %u maxp %u\n", ep,+ endpoint->endpoint_address, packet_size, maxp);++ /* Set maximum packet size */+ writel(maxp, S3C2410_UDC_MAXP_REG);++ return 0;+}++/* ************************************************************************** */++/**+ * udc_connected - is the USB cable connected+ *+ * Return non-zero if cable is connected.+ */+#if 0+int udc_connected (void)+{+ return ((inw (UDC_DEVSTAT) & UDC_ATT) == UDC_ATT);+}+#endif++/* Turn on the USB connection by enabling the pullup resistor */+void udc_connect (void)+{+ debug("connect, enable Pullup\n");+ S3C24X0_INTERRUPT * irq = S3C24X0_GetBase_INTERRUPT();++ udc_ctrl(UDC_CTRL_PULLUP_ENABLE, 0);+ udelay(10000);+ udc_ctrl(UDC_CTRL_PULLUP_ENABLE, 1);++ irq->INTMSK &= ~BIT_USBD;+}++/* Turn off the USB connection by disabling the pullup resistor */+void udc_disconnect (void)+{+ debug("disconnect, disable Pullup\n");+ S3C24X0_INTERRUPT * irq = S3C24X0_GetBase_INTERRUPT();++ udc_ctrl(UDC_CTRL_PULLUP_ENABLE, 0);++ /* Disable interrupt (we don't want to get interrupts while the kernel+ * is relocating itself */+ irq->INTMSK |= BIT_USBD;+}++/* Switch on the UDC */+void udc_enable (struct usb_device_instance *device)+{+ debug("enable device %p, status %d\n", device, device->status);++ /* Save the device structure pointer */+ udc_device = device;++ /* Setup ep0 urb */+ if (!ep0_urb)+ ep0_urb = usbd_alloc_urb(udc_device,+ udc_device->bus->endpoint_array);+ else+ serial_printf("udc_enable: ep0_urb already allocated %p\n",+ ep0_urb);++ s3c2410_configure_device(device);+}++/* Switch off the UDC */+void udc_disable (void)+{+ debug("disable UDC\n");++ s3c2410_deconfigure_device();++ /* Free ep0 URB */+ if (ep0_urb) {+ /*usbd_dealloc_urb(ep0_urb); */+ ep0_urb = NULL;+ }++ /* Reset device pointer.+ * We ought to do this here to balance the initialization of udc_device+ * in udc_enable, but some of our other exported functions get called+ * by the bus interface driver after udc_disable, so we have to hang on+ * to the device pointer to avoid a null pointer dereference. */+ /* udc_device = NULL; */+}++/**+ * udc_startup - allow udc code to do any additional startup+ */+void udc_startup_events (struct usb_device_instance *device)+{+ /* The DEVICE_INIT event puts the USB device in the state STATE_INIT. */+ usbd_device_event_irq (device, DEVICE_INIT, 0);++ /* The DEVICE_CREATE event puts the USB device in the state+ * STATE_ATTACHED.+ */+ usbd_device_event_irq (device, DEVICE_CREATE, 0);++ /* Some USB controller driver implementations signal+ * DEVICE_HUB_CONFIGURED and DEVICE_RESET events here.+ * DEVICE_HUB_CONFIGURED causes a transition to the state STATE_POWERED,+ * and DEVICE_RESET causes a transition to the state STATE_DEFAULT.+ * The OMAP USB client controller has the capability to detect when the+ * USB cable is connected to a powered USB bus via the ATT bit in the+ * DEVSTAT register, so we will defer the DEVICE_HUB_CONFIGURED and+ * DEVICE_RESET events until later.+ */++ /* The GTA01 can detect usb device attachment, but we just assume being+ * attached for now (go to STATE_POWERED) */+ usbd_device_event_irq (device, DEVICE_HUB_CONFIGURED, 0);++ udc_enable (device);+}++void udc_set_nak(int epid)+{+ /* FIXME: implement this */+}++void udc_unset_nak(int epid)+{+ /* FIXME: implement this */+}++#endif /* CONFIG_S3C2410 && CONFIG_USB_DEVICE */Index: u-boot/drivers/usb/usbdcore_ep0.c===================================================================--- u-boot.orig/drivers/usb/usbdcore_ep0.c+++ u-boot/drivers/usb/usbdcore_ep0.c@@ -193,9 +193,13 @@ if (!urb || !urb->buffer || !urb->buffer_length || (urb->buffer_length < 255)) { dbg_ep0 (2, "invalid urb %p", urb);+ serial_printf("invalid urb %p", urb); return -1L; } + /* re-initialize the ep0 buffer pointer */+ urb->buffer = (u8 *) urb->buffer_data;+ /* setup tx urb */ urb->actual_length = 0; cp = (char*)urb->buffer;@@ -211,15 +215,8 @@ usbd_device_device_descriptor (device, port))) { return -1; }- /* copy descriptor for this device */- copy_config (urb, device_descriptor,- sizeof (struct usb_device_descriptor),- max);-- /* correct the correct control endpoint 0 max packet size into the descriptor */- device_descriptor =- (struct usb_device_descriptor *) urb->buffer;-+ urb->buffer = device_descriptor;+ urb->actual_length = MIN(sizeof(*device_descriptor), max); } dbg_ep0(3, "copied device configuration, actual_length: 0x%x", urb->actual_length); break;@@ -252,11 +249,9 @@ index); return -1; }- dbg_ep0(0, "attempt to copy %d bytes to urb\n",cpu_to_le16(configuration_descriptor->wTotalLength));- copy_config (urb, configuration_descriptor,-- cpu_to_le16(configuration_descriptor->wTotalLength),- max);+ urb->buffer = configuration_descriptor;+ urb->actual_length =+ MIN(le16_to_cpu(configuration_descriptor->wTotalLength), max); } break;@@ -389,6 +384,7 @@ dbg_ep0 (0, "entering ep0_recv_setup()"); if (!urb || !urb->device) { dbg_ep0 (3, "invalid URB %p", urb);+ serial_printf("invalid URB %p", urb); return -1; } @@ -417,6 +413,7 @@ } dbg_ep0 (1, "non standard request: %x", request->bmRequestType & USB_REQ_TYPE_MASK);+ serial_printf("non standard request: %x", request->bmRequestType & USB_REQ_TYPE_MASK); return -1; /* Stall here */ } @@ -465,6 +462,8 @@ dbg_ep0 (1, "request %s not allowed in UNKNOWN state: %s", USBD_DEVICE_REQUESTS (request->bRequest), usbd_device_states[device->device_state]);+ serial_printf("request %s not allowed in UNKNOWN state: %s", USBD_DEVICE_REQUESTS (request->bRequest), usbd_device_states[device->device_state]);+ break; return -1; } @@ -563,6 +562,7 @@ /*dbg_ep0(2, "address: %d %d %d", */ /* request->wValue, le16_to_cpu(request->wValue), device->address); */ + //udc_set_address(device->address); return 0; case USB_REQ_SET_DESCRIPTOR: /* XXX should we support this? */Index: u-boot/include/configs/neo1973_gta01.h===================================================================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -