📄 usbdcore_omap1510.c
字号:
/* Determine the endpoint number for this interrupt */ epnum = (inw (UDC_EPN_STAT) & 0x0f00) >> 8; UDCDBGA ("RX on ep %x", epnum); /* acknowledge interrupt */ outw (UDC_EPn_RX, UDC_IRQ_SRC); if (epnum) { /* select the endpoint FIFO */ outw (UDC_EP_Sel | epnum, UDC_EP_NUM); omap1510_udc_epn_rx (epnum); /* deselect the endpoint FIFO */ outw (epnum, UDC_EP_NUM); } valid_irq++; } if (irq_src & UDC_EPn_TX) { /* Endpoint N IN transaction */ /* Determine the endpoint number for this interrupt */ epnum = (inw (UDC_EPN_STAT) & 0x000f) | USB_DIR_IN; UDCDBGA ("TX on ep %x", epnum); /* acknowledge interrupt */ outw (UDC_EPn_TX, UDC_IRQ_SRC); if (epnum) { /* select the endpoint FIFO */ outw (UDC_EP_Sel | UDC_EP_Dir | epnum, UDC_EP_NUM); omap1510_udc_epn_tx (epnum); /* deselect the endpoint FIFO */ outw (UDC_EP_Dir | epnum, UDC_EP_NUM); } valid_irq++; } if (!valid_irq) serial_printf (": unknown non-ISO interrupt, IRQ_SRC %.4x\n", irq_src);}/*-------------------------------------------------------------------------------*//* * 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; UDCDBGA ("Starting transmit on ep %x", epnum); if (endpoint->tx_urb) { /* select the endpoint FIFO */ outw (UDC_EP_Sel | UDC_EP_Dir | epnum, UDC_EP_NUM); /* write data to FIFO */ omap1510_write_noniso_tx_fifo (endpoint); /* enable tx FIFO to start transmission */ outw (UDC_Set_FIFO_En, UDC_CTRL); /* deselect the endpoint FIFO */ outw (UDC_EP_Dir | epnum, UDC_EP_NUM); }}/* Start to initialize h/w stuff */int udc_init (void){ u16 udc_rev; uchar value; ulong gpio; int i; /* Let the device settle down before we start */ for (i = 0; i < UDC_INIT_MDELAY; i++) udelay(1000); udc_device = NULL; UDCDBG ("starting"); /* Check peripheral reset. Must be 1 to make sure MPU TIPB peripheral reset is inactive */ UDCREG (ARM_RSTCT2); /* 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. */ outw ((1 << 4) | (1 << 5), CLOCK_CTRL); UDCREG (CLOCK_CTRL); /* Set and check APLL */ outw (0x0008, APLL_CTRL); UDCREG (APLL_CTRL); /* Set and check DPLL */ outw (0x2210, DPLL_CTRL); UDCREG (DPLL_CTRL); /* Set and check SOFT */ outw ((1 << 4) | (1 << 3) | 1, SOFT_REQ); /* Short delay to wait for DPLL */ udelay (1000); /* Print banner with device revision */ udc_rev = inw (UDC_REV) & 0xff; printf ("USB: TI OMAP1510 USB function module rev %d.%d\n", udc_rev >> 4, udc_rev & 0xf);#ifdef CONFIG_OMAP_SX1 i2c_read (0x32, 0x04, 1, &value, 1); value |= 0x04; i2c_write (0x32, 0x04, 1, &value, 1); i2c_read (0x32, 0x03, 1, &value, 1); value |= 0x01; i2c_write (0x32, 0x03, 1, &value, 1); gpio = inl(GPIO_PIN_CONTROL_REG); gpio |= 0x0002; /* A_IRDA_OFF */ gpio |= 0x0800; /* A_SWITCH */ gpio |= 0x8000; /* A_USB_ON */ outl (gpio, GPIO_PIN_CONTROL_REG); gpio = inl(GPIO_DIR_CONTROL_REG); gpio &= ~0x0002; /* A_IRDA_OFF */ gpio &= ~0x0800; /* A_SWITCH */ gpio &= ~0x8000; /* A_USB_ON */ outl (gpio, GPIO_DIR_CONTROL_REG); gpio = inl(GPIO_DATA_OUTPUT_REG); gpio |= 0x0002; /* A_IRDA_OFF */ gpio &= ~0x0800; /* A_SWITCH */ gpio &= ~0x8000; /* A_USB_ON */ outl (gpio, GPIO_DATA_OUTPUT_REG);#endif /* The VBUS_MODE bit selects whether VBUS detection is done via * software (1) or hardware (0). When software detection is * selected, VBUS_CTRL selects whether USB is not connected (0) * or connected (1). */ outl (inl (FUNC_MUX_CTRL_0) | UDC_VBUS_MODE, FUNC_MUX_CTRL_0); outl (inl (FUNC_MUX_CTRL_0) & ~UDC_VBUS_CTRL, FUNC_MUX_CTRL_0); UDCREGL (FUNC_MUX_CTRL_0); /* * At this point, device is ready for configuration... */ UDCDBG ("disable USB interrupts"); outw (0, UDC_IRQ_EN); UDCREG (UDC_IRQ_EN); UDCDBG ("disable USB DMA"); outw (0, UDC_DMA_IRQ_EN); UDCREG (UDC_DMA_IRQ_EN); UDCDBG ("initialize SYSCON1"); outw (UDC_Self_Pwr | UDC_Pullup_En, UDC_SYSCON1); UDCREG (UDC_SYSCON1); return 0;}/* Stall endpoint */static void udc_stall_ep (unsigned int ep_addr){ /*int ep_addr = PHYS_EP_TO_EP_ADDR(ep); */ int ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK; UDCDBGA ("stall ep_addr %d", ep_addr); /* REVISIT? * The OMAP TRM section 14.2.4.2 says we must check that the FIFO * is empty before halting the endpoint. The current implementation * doesn't check that the FIFO is empty. */ if (!ep_num) { outw (UDC_Stall_Cmd, UDC_SYSCON2); } else if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { if (inw (UDC_EP_RX (ep_num)) & UDC_EPn_RX_Valid) { /* we have a valid rx endpoint, so halt it */ outw (UDC_EP_Sel | ep_num, UDC_EP_NUM); outw (UDC_Set_Halt, UDC_CTRL); outw (ep_num, UDC_EP_NUM); } } else { if (inw (UDC_EP_TX (ep_num)) & UDC_EPn_TX_Valid) { /* we have a valid tx endpoint, so halt it */ outw (UDC_EP_Sel | UDC_EP_Dir | ep_num, UDC_EP_NUM); outw (UDC_Set_Halt, UDC_CTRL); outw (ep_num, UDC_EP_NUM); } }}/* Reset endpoint */#if 0static void udc_reset_ep (unsigned int ep_addr){ /*int ep_addr = PHYS_EP_TO_EP_ADDR(ep); */ int ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK; UDCDBGA ("reset ep_addr %d", ep_addr); if (!ep_num) { /* control endpoint 0 can't be reset */ } else if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) { UDCDBGA ("UDC_EP_RX(%d) = 0x%04x", ep_num, inw (UDC_EP_RX (ep_num))); if (inw (UDC_EP_RX (ep_num)) & UDC_EPn_RX_Valid) { /* we have a valid rx endpoint, so reset it */ outw (ep_num | UDC_EP_Sel, UDC_EP_NUM); outw (UDC_Reset_EP, UDC_CTRL); outw (ep_num, UDC_EP_NUM); UDCDBGA ("OUT endpoint %d reset", ep_num); } } else { UDCDBGA ("UDC_EP_TX(%d) = 0x%04x", ep_num, inw (UDC_EP_TX (ep_num))); /* Resetting of tx endpoints seems to be causing the USB function * module to fail, which causes problems when the driver is * uninstalled. We'll skip resetting tx endpoints for now until * we figure out what the problem is. */#if 0 if (inw (UDC_EP_TX (ep_num)) & UDC_EPn_TX_Valid) { /* we have a valid tx endpoint, so reset it */ outw (ep_num | UDC_EP_Dir | UDC_EP_Sel, UDC_EP_NUM); outw (UDC_Reset_EP, UDC_CTRL); outw (ep_num | UDC_EP_Dir, UDC_EP_NUM); UDCDBGA ("IN endpoint %d reset", ep_num); }#endif }}#endif/* ************************************************************************** *//** * udc_check_ep - check logical endpoint * * Return physical endpoint number to use for this logical endpoint or zero if not valid. */#if 0int udc_check_ep (int logical_endpoint, int packetsize){ if ((logical_endpoint == 0x80) || ((logical_endpoint & 0x8f) != logical_endpoint)) { return 0; } switch (packetsize) { case 8: case 16: case 32: case 64: case 128: case 256: case 512: break; default: return 0; } return EP_ADDR_TO_PHYS_EP (logical_endpoint);}#endif/* * udc_setup_ep - setup endpoint * * Associate a physical endpoint with endpoint_instance */void udc_setup_ep (struct usb_device_instance *device, unsigned int ep, struct usb_endpoint_instance *endpoint){ UDCDBGA ("setting up endpoint addr %x", endpoint->endpoint_address); /* This routine gets called by bi_modinit for endpoint 0 and from * bi_config for all of the other endpoints. bi_config gets called * during the DEVICE_CREATE, DEVICE_CONFIGURED, and * DEVICE_SET_INTERFACE events. We need to reconfigure the OMAP packet * RAM after bi_config scans the selected device configuration and * initializes the endpoint structures, but before this routine enables * the OUT endpoint FIFOs. Since bi_config calls this routine in a * loop for endpoints 1 through UDC_MAX_ENDPOINTS, we reconfigure our * packet RAM here when ep==1. * I really hate to do this here, but it seems like the API exported * by the USB bus interface controller driver to the usbd-bi module * isn't quite right so there is no good place to do this. */ if (ep == 1) { omap1510_deconfigure_device (); omap1510_configure_device (device); } if (endpoint && (ep < UDC_MAX_ENDPOINTS)) { int ep_addr = endpoint->endpoint_address; if (!ep_addr) { /* nothing to do for endpoint 0 */ } else if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) { /* nothing to do for IN (tx) endpoints */ } else { /* OUT (rx) endpoint */ if (endpoint->rcv_packetSize) { /*struct urb* urb = &(urb_out_array[ep&0xFF]); */ /*urb->endpoint = endpoint; */ /*urb->device = device; */ /*urb->buffer_length = sizeof(urb->buffer); */ /*endpoint->rcv_urb = urb; */ omap1510_prepare_endpoint_for_rx (ep_addr); } } }}/** * udc_disable_ep - disable endpoint * @ep: * * Disable specified endpoint */#if 0void udc_disable_ep (unsigned int ep_addr){ /*int ep_addr = PHYS_EP_TO_EP_ADDR(ep); */ int ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK; struct usb_endpoint_instance *endpoint = omap1510_find_ep (ep_addr); /*udc_device->bus->endpoint_array + ep; */ UDCDBGA ("disable ep_addr %d", ep_addr); if (!ep_num) { /* nothing to do for endpoint 0 */ ; } else if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) { if (endpoint->tx_packetSize) { /* we have a valid tx endpoint */ /*usbd_flush_tx(endpoint); */ endpoint->tx_urb = NULL; } } else { if (endpoint->rcv_packetSize) { /* we have a valid rx endpoint */ /*usbd_flush_rcv(endpoint); */ endpoint->rcv_urb = NULL; } }}#endif/* ************************************************************************** *//** * udc_connected - is the USB cable connected * * Return non-zero if cable is connected. */#if 0int 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){ UDCDBG ("connect, enable Pullup"); outl (0x00000018, FUNC_MUX_CTRL_D);}/* Turn off the USB connection by disabling the pullup resistor */void udc_disconnect (void){ UDCDBG ("disconnect, disable Pullup"); outl (0x00000000, FUNC_MUX_CTRL_D);}/* ************************************************************************** *//* * udc_disable_interrupts - disable interrupts * switch off interrupts */#if 0void udc_disable_interrupts (struct usb_device_instance *device){ UDCDBG ("disabling all interrupts"); outw (0, UDC_IRQ_EN);}#endif/* ************************************************************************** *//** * udc_ep0_packetsize - return ep0 packetsize */#if 0int udc_ep0_packetsize (void){ return EP0_PACKETSIZE;}#endif/* Switch on the UDC */void udc_enable (struct usb_device_instance *device){ UDCDBGA ("enable device %p, status %d", device, device->status); /* initialize driver state variables */ udc_devstat = 0; /* 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); } UDCDBG ("Check clock status"); UDCREG (STATUS_REQ); /* The VBUS_MODE bit selects whether VBUS detection is done via * software (1) or hardware (0). When software detection is * selected, VBUS_CTRL selects whether USB is not connected (0) * or connected (1). */ outl (inl (FUNC_MUX_CTRL_0) | UDC_VBUS_CTRL | UDC_VBUS_MODE, FUNC_MUX_CTRL_0); UDCREGL (FUNC_MUX_CTRL_0); omap1510_configure_device (device);}/* Switch off the UDC */void udc_disable (void){ UDCDBG ("disable UDC"); omap1510_deconfigure_device (); /* The VBUS_MODE bit selects whether VBUS detection is done via * software (1) or hardware (0). When software detection is * selected, VBUS_CTRL selects whether USB is not connected (0) * or connected (1). */ outl (inl (FUNC_MUX_CTRL_0) | UDC_VBUS_MODE, FUNC_MUX_CTRL_0); outl (inl (FUNC_MUX_CTRL_0) & ~UDC_VBUS_CTRL, FUNC_MUX_CTRL_0); UDCREGL (FUNC_MUX_CTRL_0); /* 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. */ udc_enable (device);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -