📄 pxa.c
字号:
pxa_ep0xmit(endpoint, UDCCS0); // Clear SA and OPR bits UDCCS0 = UDCCS0_SA | UDCCS0_OPR; PXA_REGS(UDCCS0," <-- setup data"); } }}static __inline__ void pxa_ep0(struct usb_endpoint_instance *endpoint, volatile u32 udccs0){ int j = 0; PXA_REGS(udccs0," --> ep0"); if (udccs0 & UDCCS0_SST) { pxa_ep_reset_irs(0); UDCCS0 = UDCCS0_SST; PXA_REGS(udccs0," --> ep0 clear SST"); if (endpoint) { endpoint->state = WAIT_FOR_SETUP; endpoint->tx_urb = NULL; } return; } if (!endpoint) { printk(KERN_INFO"ep0[%d:%d] endpoint Zero is NULL CS0[%02x]\n", udc_interrupts, jifs(), UDCCS0); pxa_ep_reset_irs(0); UDCCS0 = UDCCS0_IPR | UDCCS0_OPR | UDCCS0_SA; PXA_REGS(UDCCS0," ep0 NULL"); return; } if (endpoint->tx_urb) { usbd_tx_complete_irq (endpoint, 0); if (!endpoint->tx_urb) { if (endpoint->state != DATA_STATE_NEED_ZLP) { endpoint->state = WAIT_FOR_OUT_STATUS; } } } if ((endpoint->state != WAIT_FOR_SETUP) && (udccs0 & UDCCS0_SA)) { PXA_REGS(udccs0," --> ep0 early SA"); endpoint->state = WAIT_FOR_SETUP; endpoint->tx_urb = NULL; } switch (endpoint->state) { case DATA_STATE_NEED_ZLP: UDCCS0 = UDCCS0_IPR; endpoint->state = WAIT_FOR_OUT_STATUS; break; case WAIT_FOR_OUT_STATUS: if ((udccs0 & (UDCCS0_OPR | UDCCS0_SA)) == UDCCS0_OPR) { UDCCS0 |= UDCCS0_OPR; } PXA_REGS(UDCCS0," --> ep0 WAIT for STATUS"); endpoint->state = WAIT_FOR_SETUP; case WAIT_FOR_SETUP: do { pxa_ep0setup(endpoint, UDCCS0); if (udccs0 & UDCCS0_SST) { pxa_ep_reset_irs(0); UDCCS0 = UDCCS0_SST | UDCCS0_OPR | UDCCS0_SA; PXA_REGS(udccs0," --> ep0 clear SST"); if (endpoint) { endpoint->state = WAIT_FOR_SETUP; endpoint->tx_urb = NULL; } return; } if (j++ > 2) { u32 udccs0 = UDCCS0; PXA_REGS(udccs0," ep0 wait"); if ((udccs0 & (UDCCS0_OPR | UDCCS0_SA | UDCCS0_RNE)) == (UDCCS0_OPR | UDCCS0_SA)) { UDCCS0 = UDCCS0_OPR | UDCCS0_SA; PXA_REGS(UDCCS0," ep0 force"); } else { UDCCS0 = UDCCS0_OPR | UDCCS0_SA; PXA_REGS(UDCCS0," ep0 force and return"); break; } } } while (UDCCS0 & (UDCCS0_OPR | UDCCS0_RNE)); break; case DATA_STATE_XMIT: pxa_ep0xmit(endpoint, UDCCS0); break;#ifdef CONFIG_USBD_EP0_SUPPORT case DATA_STATE_RECV: pxa_ep0recv(endpoint, UDCCS0); break;#endif } pxa_ep_reset_irs(0); PXA_REGS(UDCCS0," <-- ep0");}/* ********************************************************************************************* *//* Interrupt Handler *//** * int_hndlr - interrupt handler * */static void int_hndlr (int irq, void *dev_id, struct pt_regs *regs){ int usiro; int udccr; int ep; int_oscr = OSCR; udc_interrupts++; // check for common, high priority interrupts first, i.e. per endpoint service requests // XXX if ISO supported it might be necessary to give the ISO endpoints priority while ((usiro = USIR0)) { u32 udccs0 = UDCCS0; PXA_IRO(usiro, "------------------------> Interrupt"); for (ep = 0; usiro; usiro >>= 1, ep++) { if (usiro & 1) { switch (ep_maps[ep].eptype) { case ep_control: pxa_ep0(ep_endpoints[0], udccs0); //PXA_IRO(USIRO, "<-- Interrupt"); break; case ep_bulk_in: case ep_interrupt: pxa_in_n(ep, ep_endpoints[ep]); break; case ep_bulk_out:#ifdef CONFIG_USBD_PXA_DMA_OUT printk (KERN_WARNING "PXA: bulk out with DMA out, ep %d - may be a bug\n", ep);#else pxa_out_n(ep, ep_endpoints[ep]);#endif pxa_ep_reset_irs(ep); break; case ep_iso_in: case ep_iso_out: pxa_ep_reset_irs(ep); break; } } } } // sof interrupt if (UFNHR & UFNHR_SIR) { UFNHR = UFNHR_SIR; } // uncommon interrupts if ((udccr = UDCCR) & (UDCCR_RSTIR | UDCCR_RESIR | UDCCR_SUSIR)) { // UDC Reset if (udccr & UDCCR_RSTIR) { PXA_CCR(udccr, "------------------------> Reset"); //printk(KERN_INFO"int_hndlr[%d:%d] Reset\n", udc_interrupts, jifs()); udc_suspended = 0; usbd_device_event (udc_device, DEVICE_RESET, 0); usbd_device_event (udc_device, DEVICE_ADDRESS_ASSIGNED, 0); UDCCR |= UDCCR_RSTIR; } // UDC Resume if (udccr & UDCCR_RESIR) { PXA_CCR(udccr, "------------------------> Resume"); if (udc_suspended) { udc_suspended = 0; usbd_device_event (udc_device, DEVICE_BUS_ACTIVITY, 0); } UDCCR |= UDCCR_RESIR; } // UDC Suspend if (udccr & UDCCR_SUSIR) { PXA_CCR(udccr, "------------------------> Suspend"); if (!udc_suspended) { udc_suspended = 1; usbd_device_event (udc_device, DEVICE_BUS_INACTIVE, 0); } UDCCR |= UDCCR_SUSIR; } } PXA_CCR(UDCCR, "<-- Interrupt");}/* ********************************************************************************************* *//* ********************************************************************************************* *//* * Start of public functions. *//** * udc_start_in_irq - start transmit * @eendpoint: endpoint instance * * Called by bus interface driver to see if we need to start a data transmission. */void udc_start_in_irq (struct usb_endpoint_instance *endpoint){ if (UDCCSN(endpoint->endpoint_address & 0xf) & UDCCS_BI_TFS) {#ifdef CONFIG_USBD_PXA_DMA_IN if (usb_pxa_dma_in.dma_buf) /* Buffer ok, use DMA */ pxa_start_n_dma (endpoint->endpoint_address & 0xf, endpoint); else /* Buffer is not allocated, switch to polling mode */ pxa_start_n (endpoint->endpoint_address & 0xf, endpoint);#else pxa_start_n (endpoint->endpoint_address & 0xf, endpoint);#endif }}/** * udc_init - initialize * * Return non-zero if we cannot see device. **/int udc_init (void){ udc_disable_interrupts (NULL);#ifdef CONFIG_USBD_PXA_DMA_IN if (!(usb_pxa_dma_in.dma_buf = (unsigned char *)consistent_alloc (GFP_KERNEL, DMA_IN_BUFSIZE, &usb_pxa_dma_in.dma_buf_phys))) { /* Can't allocate DMAable memory... Make a warning and not use DMA */ printk (KERN_WARNING "PXA: can't allocate consistent memory for USB DMA IN\n"); printk (KERN_WARNING "PXA: USB DMA IN is disabled\n"); }#endif#ifdef CONFIG_USBD_PXA_DMA_OUT if (!(usb_pxa_dma_out.dma_buf = (unsigned char *)consistent_alloc (GFP_KERNEL, DMA_OUT_BUFSIZE, &usb_pxa_dma_out.dma_buf_phys))) { /* The same as above */ printk (KERN_WARNING "PXA: can't allocate consistent memory for USB DMA OUT\n"); printk (KERN_WARNING "PXA: USB DMA OUT is disabled\n"); }#endif return 0;}/** * udc_start_in - start transmit * @eendpoint: endpoint instance * * Called by bus interface driver to see if we need to start a data transmission. */void udc_start_in (struct usb_endpoint_instance *endpoint){ if (endpoint) { unsigned long flags; local_irq_save (flags); udc_start_in_irq(endpoint); local_irq_restore (flags); }}/** * udc_stall_ep - stall endpoint * @ep: physical endpoint * * Stall the endpoint. */void udc_stall_ep (unsigned int ep){ if (ep < UDC_MAX_ENDPOINTS) { // stall }}/** * udc_reset_ep - reset endpoint * @ep: physical endpoint * reset the endpoint. * * returns : 0 if ok, -1 otherwise */void udc_reset_ep (unsigned int ep){ if (ep < UDC_MAX_ENDPOINTS) { }}/** * udc_endpoint_halted - is endpoint halted * @ep: * * Return non-zero if endpoint is halted */int udc_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. */void udc_set_address (unsigned char address){}/** * udc_serial_init - set a serial number if available */int __init udc_serial_init (struct usb_bus_instance *bus){ return -EINVAL;}/* ********************************************************************************************* *//** * udc_max_endpoints - max physical endpoints * * Return number of physical endpoints. */int udc_max_endpoints (void){ return UDC_MAX_ENDPOINTS;}/** * udc_check_ep - check logical endpoint * @lep: * * Return physical endpoint number to use for this logical endpoint or zero if not valid. */int udc_check_ep (int logical_endpoint, int packetsize){ // XXX check ep table return ( ((logical_endpoint & 0xf) >= UDC_MAX_ENDPOINTS) || (packetsize > 64)) ? 0 : (logical_endpoint & 0xf);}/** * udc_set_ep - setup endpoint * @ep: * @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){ if (ep < UDC_MAX_ENDPOINTS) { ep_endpoints[ep] = endpoint; // ep0 if (ep == 0) { } // IN else if (endpoint->endpoint_address & 0x80) {#ifdef CONFIG_USBD_PXA_DMA_IN if (ep == IN_ENDPOINT && usb_pxa_dma_in.dmach == -1 && /* No DMA IN if we can't allocate DMAable buffer in udc_init() */ usb_pxa_dma_in.dma_buf) { /* Get DMA irq */ if ((usb_pxa_dma_in.dmach = pxa_request_dma ("USB DMA IN", DMA_PRIO_HIGH, pxa_tx_dma_irq, (void *)&usb_pxa_dma_in)) < 0) { printk (KERN_WARNING "PXA: can't allocate DMA IRQ for USB DMA IN\n"); printk (KERN_WARNING "PXA: USB DMA IN is disabled\n"); consistent_free (usb_pxa_dma_in.dma_buf, DMA_IN_BUFSIZE, usb_pxa_dma_in.dma_buf_phys); usb_pxa_dma_in.dma_buf = NULL; } else DMA_TRACEMSG (KERN_DEBUG "PXA: USB IN DMA channel %d\n", usb_pxa_dma_in.dmach); }#endif /* CONFIG_USBD_PXA_DMA_IN */ } // OUT else if (endpoint->endpoint_address) { usbd_fill_rcv (device, endpoint, 5); endpoint->rcv_urb = first_urb_detached (&endpoint->rdy);#ifdef CONFIG_USBD_PXA_DMA_OUT if (ep == OUT_ENDPOINT && usb_pxa_dma_out.dmach == -1 && /* Again, no DMA OUT if we can't allocate DMAable buffer in udc_init() */ usb_pxa_dma_out.dma_buf) { /* Get DMA irq */ if ((usb_pxa_dma_out.dmach = pxa_request_dma ("USB DMA OUT", DMA_PRIO_HIGH, pxa_rx_dma_irq, (void *)&usb_pxa_dma_out)) < 0) { printk (KERN_WARNING "PXA: can't allocate DMA IRQ for USB DMA OUT\n"); printk (KERN_WARNING "PXA: USB DMA OUT is disabled\n"); consistent_free (usb_pxa_dma_out.dma_buf, DMA_OUT_BUFSIZE, usb_pxa_dma_out.dma_buf_phys); usb_pxa_dma_out.dma_buf = NULL; } else { DMA_TRACEMSG (KERN_DEBUG "PXA: USB OUT DMA channel %d\n", usb_pxa_dma_out.dmach); usb_pxa_dma_out.ep = ep; usb_pxa_dma_out.endpoint = endpoint; usb_pxa_dma_out.size = DMA_OUT_BUFSIZE; pxa_rx_dma_hw_init (); /* Enable DME for BULK OUT endpoint */ UDCCS2 |= UDCCS_BO_DME; DMA_TRACEMSG ("PXA: enable DME\n"); /* Start DMA */ DCSR(usb_pxa_dma_out.dmach) |= DCSR_RUN; DMA_TRACEMSG ("PXA: OUT DMA started [ep %d]\n", ep); } }#endif /* CONFIG_USBD_PXA_DMA_OUT */ } pxa_enable_ep_interrupt(ep_endpoints[ep]->endpoint_address); }}/** * udc_disable_ep - disable endpoint * @ep: * * Disable specified endpoint */void udc_disable_ep (unsigned int ep){ if (ep < UDC_MAX_ENDPOINTS) { struct usb_endpoint_instance *endpoint; if ((endpoint = ep_endpoints[ep])) { ep_endpoints[ep] = NULL; usbd_flush_ep (endpoint); } if (ep == 0) { //printk(KERN_INFO"udc_setup_ep: 0 do nothing\n"); } // IN else if (endpoint && endpoint->endpoint_address & 0x80) {#ifdef CONFIG_USBD_PXA_DMA_IN if (ep == IN_ENDPOINT && usb_pxa_dma_in.dmach != -1) { pxa_free_dma (usb_pxa_dma_in.dmach); usb_pxa_dma_in.dmach = -1; }#endif } // OUT else if (endpoint && endpoint->endpoint_address) {#ifdef CONFIG_USBD_PXA_DMA_OUT if (ep == OUT_ENDPOINT && usb_pxa_dma_out.dmach != -1) { pxa_free_dma (usb_pxa_dma_out.dmach); usb_pxa_dma_out.dmach = -1; }#endif } }}/* ********************************************************************************************* *//** * udc_connected - is the USB cable connected * * Return non-zeron if cable is connected. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -