📄 omap.c
字号:
*/#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); UDCDBG("IN endpoint %d reset", ep_num); }#endif } local_irq_restore(flags);}/** * udc_endpoint_halted - is endpoint halted * @ep: * * Return non-zero if endpoint is halted */intudc_endpoint_halted(unsigned int ep){ return 0;}/** * udc_set_address - set the USB address for this device * @address: * * Called from control endpoint function after it decodes a set address setup packet. */voidudc_set_address(unsigned char address){ UDCDBG("setting address %x", address); usb_address = address;}#if 1/** * udc_serial_init - set a serial number if available */int __initudc_serial_init(struct usb_bus_instance *bus){ return -EINVAL;}#endif/* ************************************************************************** *//* * udc_max_endpoints - max physical endpoints * * Return number of physical endpoints. */intudc_max_endpoints(void){ return UDC_MAX_ENDPOINTS;}/** * udc_check_ep - check logical endpoint * * Return physical endpoint number to use for this logical endpoint or zero if not valid. */intudc_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);}/* * udc_setup_ep - setup endpoint * * Associate a physical endpoint with endpoint_instance */voidudc_setup_ep(struct usb_device_instance *device, unsigned int ep, struct usb_endpoint_instance *endpoint){ /* 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) { omap_deconfigure_device(); omap_configure_device(device); } UDCDBG("setting up physical endpoint %d", ep); if (endpoint && (ep < UDC_MAX_ENDPOINTS)) { int ep_addr = PHYS_EP_TO_EP_ADDR(ep); if (!ep) { /* 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) { /* Why are we pre-allocating 5 urbs? Because * most of the other existing USB controller * drivers pre-allocate 5 urbs. We must * allocate enough urbs so that we never run * out of urbs in our endpoint->rdy queue * because the function driver hasn't had a * chance to process an urb from the * endpoint->rcv queue and recycle it back to * the rdy queue. */ usbd_fill_rcv(device, endpoint, 5); endpoint->rcv_urb = first_urb_detached(&endpoint->rdy); omap_prepare_endpoint_for_rx(ep); } } }}/** * udc_disable_ep - disable endpoint * @ep: * * Disable specified endpoint */voidudc_disable_ep(unsigned int ep){ int ep_addr = PHYS_EP_TO_EP_ADDR(ep); int ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK; struct usb_endpoint_instance *endpoint = udc_device->bus->endpoint_array + ep; UDCDBG("disable ep %d", ep); 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); } } else { if (endpoint->rcv_packetSize) { /* we have a valid rx endpoint */ usbd_flush_rcv(endpoint); } }}/* ************************************************************************** *//** * udc_connected - is the USB cable connected * * Return non-zero if cable is connected. */intudc_connected(void){ return ((inw(UDC_DEVSTAT) & UDC_ATT) == UDC_ATT);}/* Turn on the USB connection by enabling the pullup resistor */voidudc_connect(void){ UDCDBG("connect, enable Pullup"); outw(inw(UDC_SYSCON1) | UDC_Pullup_En, UDC_SYSCON1); UDCREG(UDC_SYSCON1);#ifdef CONFIG_OMAP_H2 usbd_do_connect = 1; up(&usbd_connect_lock);#endif}/* Turn off the USB connection by disabling the pullup resistor */voidudc_disconnect(void){ UDCDBG("disconnect, disable Pullup"); outw(inw(UDC_SYSCON1) & ~UDC_Pullup_En, UDC_SYSCON1); UDCREG(UDC_SYSCON1);#ifdef CONFIG_OMAP_H2 down(&usbd_i2c_lock); usbd_do_connect = 0; if (usbd_connected) { /*disable pull-up resistor on D+ */ i2c_write(0xC, ISP1301_I2C_OTG_CONTROL_1); i2c_write(~0xC, ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR); usbd_connected = 0; } up(&usbd_i2c_lock);#endif}/* ************************************************************************** *//** * udc_enable_interrupts - enable interrupts * * Switch on UDC interrupts. * */voidudc_all_interrupts(struct usb_device_instance *device){ UDCDBG("enabling all endpoint interrupts"); outw( /* UDC_Sof_IE | */ UDC_EPn_RX_IE | UDC_EPn_TX_IE | UDC_DS_Chg_IE | UDC_EP0_IE, UDC_IRQ_EN);}/** * udc_suspended_interrupts - enable suspended interrupts * * Switch on only UDC resume interrupt. * */voidudc_suspended_interrupts(struct usb_device_instance *device){ UDCDBG("enabling resume interrupt (DS_Chg)"); outw(UDC_DS_Chg_IE, UDC_IRQ_EN);}/* * udc_disable_interrupts - disable interrupts * switch off interrupts */voidudc_disable_interrupts(struct usb_device_instance *device){ UDCDBG("disabling all interrupts"); outw(0, UDC_IRQ_EN);}/* ************************************************************************** *//** * udc_ep0_packetsize - return ep0 packetsize */intudc_ep0_packetsize(void){ return EP0_PACKETSIZE;}/* Switch on the UDC */voidudc_enable(struct usb_device_instance *device){ UDCDBG("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) { if (!(ep0_urb = usbd_alloc_urb(device, device->function_instance_array, 0, 512))) { printk(KERN_ERR "udc_enable: usbd_alloc_urb failed\n"); } } else { printk(KERN_ERR "udc_enable: ep0_urb already allocated\n"); } 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);#ifdef CONFIG_ARCH_OMAP1610 //OTG_CTRL.18 = 1 (BSESSVLD) //1 = host attached (VBUS present) outl((1 << 18), OTG_CTRL);#endif omap_configure_device(device);}/* Switch off the UDC */voidudc_disable(void){ UDCDBG("disable UDC"); omap_deconfigure_device();#ifdef CONFIG_ARCH_OMAP1610 //OTG_CTRL.18 = 0 (BSESSVLD) //1 = host attached (VBUS present) outl(0, OTG_CTRL);#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); /* 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 */voidudc_startup_events(struct usb_device_instance *device){ /* The DEVICE_INIT event puts the USB device in the state STATE_INIT. */ usbd_device_event(device, DEVICE_INIT, 0); /* The DEVICE_CREATE event puts the USB device in the state * STATE_ATTACHED. */ usbd_device_event(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. */}/* ************************************************************************** *//* Return name of this UDC */char *udc_name(void){ return UDC_NAME;}/* Request all UDC interrups */intudc_request_udc_irq(void){ UDCDBG("installing interrupt handlers"); /* Request general USB interrupt */ if (request_irq(UDC_IRQ, omap_udc_irq, SA_INTERRUPT | SA_SAMPLE_RANDOM, UDC_NAME " Bus Interface", NULL)) { printk(KERN_ERR UDC_NAME ": couldn't register USB interrupt handler\n"); goto request_irq_failed; } /* Request non-ISO endpoint-specific interrupt */ if (request_irq(UDC_NONISO_IRQ, omap_udc_noniso_irq, SA_INTERRUPT | SA_SAMPLE_RANDOM, UDC_NAME " non-ISO endpoints", NULL)) { printk(KERN_ERR UDC_NAME ": couldn't register USB non-ISO interrupt handler\n"); goto request_noniso_irq_failed; } /* Request Start-of-Frame interrupt for ISO transactions */ if (request_irq(UDC_SOF_IRQ, omap_udc_sof_irq, SA_INTERRUPT | SA_SAMPLE_RANDOM, UDC_NAME " SOF ISO", NULL)) { printk(KERN_ERR UDC_NAME ": couldn't register USB SOF ISO interrupt handler\n"); goto request_sof_irq_failed; } return 0; request_sof_irq_failed: free_irq(UDC_NONISO_IRQ, NULL); request_noniso_irq_failed: free_irq(UDC_IRQ, NULL); request_irq_failed: return -EINVAL;}/* Release all UDC interrupts */voidudc_release_udc_irq(void){ UDCDBG("release all interrupts"); free_irq(UDC_IRQ, NULL); free_irq(UDC_NONISO_IRQ, NULL); free_irq(UDC_SOF_IRQ, NULL);}/* Request UDC IO region */intudc_request_io(void){#ifdef CONFIG_OMAP_H2 int tmp = (int) request_region(OTG_BASE, OTG_IOSIZE, "OMAP H2 USBD BI"); if (!tmp) { printk(KERN_ERR UDC_NAME ": OTG is already in use\n"); udc_release_io(); return -ENODEV; } initstate_region = 1; tmp = i2c_configure(); if (tmp < 0) { udc_release_io(); return tmp; } /*init thread */ connect_thread_terminating = 0; tmp = kernel_thread(&usbd_connect_thread, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); if (tmp < 0) { printk(KERN_ERR UDC_NAME ": could not start thread\n"); udc_release_io(); return tmp; } initstate_thread = 1; isp1301_configure();#endif return 0;}/* Release UDC IO region */voidudc_release_io(void){#ifdef CONFIG_OMAP_H2 //OTG_CTRL.18 = 0 (BSESSVLD) //1 = host attached (VBUS present) outl(0, OTG_CTRL); if (initstate_thread) { connect_thread_terminating = 1; up(&usbd_connect_lock); wait_for_completion(&connect_thread_exit); } i2c_close(); if (initstate_region) { release_region(OTG_BASE, OTG_IOSIZE); initstate_region = 0; }#endif}/* Request UDC cable interrupt */intudc_request_cable_irq(void){ /* Cable events are handled via the Ds_Chg ISR, so we don't need to * install a separate handler here. */ return 0;}/* Release UDC cable interrupt */voidudc_release_cable_irq(void){}/* Dump all UDC registers */voidudc_regs(void){ UDCDBG("** ALL UDC registers **"); UDCREG(UDC_REV); UDCREG(UDC_EP_NUM); UDCREG(UDC_SYSCON1); UDCREG(UDC_DEVSTAT); UDCREG(UDC_SOF); UDCREG(UDC_IRQ_EN); UDCREG(UDC_DMA_IRQ_EN); UDCREG(UDC_IRQ_SRC); UDCREG(UDC_EPN_STAT); UDCREG(UDC_DMAN_STAT);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -