📄 dm320.c.svn-base
字号:
{ int iInterruptFlags,i; int iInterrupt; int iCount; unsigned char ucCSR0; struct dm320 *dev = the_controller; unsigned long flags; spin_lock_irqsave (&dev->lock, flags); iInterruptFlags = dm320_read_intr_regs( ); do { iInterrupt = dm320_get_intr_by_priority( iInterruptFlags ); switch( iInterrupt ) { case USB_RESET: printk("Event: RESET Interrupt\n" ); paddr_status = 0 ;#if 0 if( ) { }#endif break; case USB_SESSREQ: break; case USB_VBUSERR: printk("INT VBUSERR\n" ); break; case USB_CONNECTED: printk( "INT CONNECT\n" ); break; case USB_RESUME: printk( "INT RESUME\n" ); break; case USB_CONTROL: writeb( USB_EP0_SELECT, USB_INDEX ); ucCSR0 = readb( USB_PER_CSR0 ); dm320_info( "ucCSR0 : 0x%02X\n", ucCSR0 ); if( ucCSR0 == 0x00 ) // response complete interrupt { char chNewAddr; if(paddr_status == 0 ) { if( ( chNewAddr = dm320_get_peripheral_addr(dev) ) > 0 ) { dm320_set_addr_reg( chNewAddr & 0xFF ); paddr_status = 1; } break; } } if( ( ucCSR0 & USB_CSR0_RXPKTRDY ) != 0 ) { dm320_info("dm320:%s: USB_CSR0_RXPKTRDY set\n", __FUNCTION__); iCount = readb( USB_COUNT0 ); // number of received bytes dm320_control_service(dev); } else if( ( ucCSR0 & USB_CSR0_SENTST ) != 0 ) { dm320_info( KERN_INFO "INT TXFIFO0 stall.[%04x].\n", ucCSR0 ); writeb( 0, USB_PER_CSR0 ); } else if( ( ucCSR0 & USB_CSR0_SETEND ) != 0 ) { dm320_info( KERN_INFO "INT TXFIFO0 setend from HOST[%04x].\n", ucCSR0 ); *(unsigned char *)USB_PER_CSR0 = USB_CSR0_CLRSETEND; } else if( ( ucCSR0 & USB_CSR0_TXPKTRDY ) != 0 ) { dm320_info( KERN_INFO "INT TXPKTRDY\n" ); // Nothing to do now... } else { // ----- FIXME ----- // Now ignore these unknown interrupts... dm320_set_CSR0_reg( USB_CSR0_CLRRXRDY | USB_CSR0_DATAEND ); // Vishal: added this$#$ //printk( KERN_INFO "Attention: Unknown USB Core Interrupt encountered!\n" ); } break; case USB_RXFIFO: // printk("%s: USB_RXFIFO interrupt\n", __FUNCTION__); dm320_rx_service(dev); break; case USB_TXFIFO: //if(dm320_tx_service(dev)) //printk ("USB_TXFIFO\n"); dm320_tx_service(dev); break; case USB_SOF: do_pending_transfers(); // printk("%s: SOF \n", __FUNCTION__); break; case USB_DISCONNECTED: printk("dm320: DISCONNECT Intr.\n" ); dm320_disconnect_service( ); break; case USB_SUSPEND: printk("dm320: SUSPEND Intr.\n" ); dm320_suspend_service( ); break; default: //printk("UNKNOWN USB core interrupt!\n" ); break; } iInterruptFlags = iInterruptFlags & ~iInterrupt; } while( iInterruptFlags != USB_NO_INTERRUPT ); spin_unlock_irqrestore(&dev->lock, flags); return IRQ_HANDLED;}static int dm320_connection_status( void ){ unsigned short usGIO; mdelay(50); usGIO = inw( IO_GIO_BITSET0 ); if( ( usGIO & ( 1 << GIO_USB_ATTACH ) ) == 0 ) // check if USB device was connected or disconnected { if(the_controller->last_event == HOST_DISCONNECT) return -1; else { the_controller->last_event = HOST_DISCONNECT; return 0; // 0 : DISCONNECTED } } else /* Connect Event */ { if(the_controller->last_event == HOST_CONNECT) return -1; else { the_controller->last_event = HOST_CONNECT; return 1; // 0 : DISCONNECTED } } return -1;}static irqreturn_t handle_attach_irqs (int irq, void *_dev, struct pt_regs * r){ u8 tmp, mask; struct dm320 *dev = _dev; int i, connect;// spin_lock (&dev->lock); connect=dm320_connection_status();#if 0 if(connect == HOST_CONNECT ) printk("%s: Device Connected\n", __FUNCTION__); else if (connect == HOST_DISCONNECT) printk("%s: Device DisConnected\n", __FUNCTION__);#endif if(connect < 0 ) { printk("%s: Debounce detected\n", __FUNCTION__); return 0; } if (connect == HOST_DISCONNECT) { stop_activity(dev, dev->driver); /* Vishal : Stop activity...haha!!*/ printk("%s: Disconnect the USB device\n", __FUNCTION__); dev->gadget.speed = USB_SPEED_UNKNOWN; outw( inw( IO_CLK_LPCTL1 ) | 0x0010, IO_CLK_LPCTL1 ); printk("Disconnect: USB device\n");// spin_unlock (&dev->lock); if((readb(USB_PER_TXCSR1) & USB_TXCSR1_FIFOEMP) ) { writeb(USB_TXCSR1_FLFIFO , USB_PER_TXCSR1); mdelay(5); } return IRQ_HANDLED; } if(the_controller) { printk("dm320.c: Controller exists. Initializing\n"); usb_reset (the_controller); outw(inw(IO_INTC_FISEL0) & 0x7F, IO_INTC_FISEL0); outw(inw(IO_INTC_EINT0) | 0x80, IO_INTC_EINT0); dm320_reconnect_init(dev); //usb_reinit (the_controller); //writeb( USB_DEVCTL_SESSREQ, USB_DEVCTL ); // For 'B' device initiate session request protocol }// spin_unlock (&dev->lock); printk("dm320 : Connect event handled\n"); return IRQ_HANDLED;}static void gadget_release (struct device *_dev){ struct dm320 *dev = dev_get_drvdata (_dev); printk("%s: released\n", __FUNCTION__); kfree (dev);}static int dm320_remove (struct dm320 *dev){ /* clean up resources allocated during probe() */ dev = the_controller; printk("%s: Disconnect the USB device\n", __FUNCTION__); dev->gadget.speed = USB_SPEED_UNKNOWN; outw( inw( IO_CLK_LPCTL1 ) | 0x0010, IO_CLK_LPCTL1 ); printk("Disconnect: USB device\n"); if (dev->attach_irq) free_irq( IRQ_USB_ATTACH, handle_attach_irqs ); if (dev->core_irq) free_irq( IRQ_USB_CORE, handle_core_irqs ); gio_disable_irq( GIO_USB_ATTACH ); unrequest_gio( GIO_USB_ATTACH ); unrequest_gio( GIO_DP_PULLUP ); stop_activity (dev, dev->driver); /* Vishal : Stop activity...!!*/ device_unregister (&dev->gadget.dev); if (dev->driver) { /* should have been done already by driver model core */ printk("WARNING: remove, driver '%s' is still registered\n", dev->driver->driver.name); usb_gadget_unregister_driver (dev->driver); } kfree(the_controller); the_controller = NULL; return 0;}static void dm320_reset_ep(unsigned int index) /* */{ writeb(index,USB_INDEX ); writeb( USB_CSR0_CLRSETEND | USB_CSR0_CLRRXRDY, USB_PER_CSR0 ); writeb( USB_CSR2_FLFIFO, USB_CSR2 ); // flush FIFO writeb( USB_CSR2_FLFIFO, USB_CSR2 ); // flush FIFO for double buffer}static void dm320_setup_ep_regs(struct dm320 *dev) /* Setup Conrol Endpoint, EP1 and EP2 */{ int i; int nBufPos; writeb( USB_EP0_SELECT, USB_INDEX ); // select EP0 writeb( USB_CSR0_CLRSETEND | USB_CSR0_CLRRXRDY, USB_PER_CSR0 ); writeb( USB_CSR2_FLFIFO, USB_CSR2 ); // flush FIFO writeb( USB_CSR2_FLFIFO, USB_CSR2 ); // flush FIFO for double buffer writeb( nBufPos & 0xFF, USB_TXFIFO1 ); // TX ADDL = 0x00 writeb( nBufPos & 0xFF, USB_RXFIFO1 ); // RX ADDL = 0x00 writeb( USB_TXFIFO2_SZ_64, USB_TXFIFO2 ); // TX fixed 64 bytes, single buffer, ADDH = 0 writeb( USB_TXFIFO2_SZ_64, USB_RXFIFO2 ); // RX fixed 64 bytes, single buffer, ADDH = 0 writeb( EP0_FIFO_SIZE / 8 , USB_TXMAXP ); // max TX packet size = 8 * 8 = 64 bytes writeb( EP0_FIFO_SIZE / 8 , USB_RXMAXP ); // max RX packet size = 8 * 8 = 64 bytes nBufPos = EP0_FIFO_SIZE; // move to next buffer position /* Setup bulk-in, bulk-out, iso-in, iso-out, and intr endpoints * These endpoints will be configured using the stEndpointInfo[] array if you need to add a new end poing to change the confiuration for an existing endpoint, you will need to change that array */ for( i = 0; i < NUM_OF_ENDPOINTS ; i++ ) { writeb( stEndpointInfo[i].fAddr & 0x0F, USB_INDEX ); if( stEndpointInfo[i].nSize ) { char fLowAddr = ( nBufPos / 8 ) & 0xFF; char fHighAddr = ( nBufPos >= 2048 ) ? 1 : 0; char fPacketSize = 0x00; char fIsDualBuf = ( stEndpointInfo[i].fBufMode == EP_BUF_SINGLE ) ? 0x00 : 0x10; switch( stEndpointInfo[i].nSize ) { case 16: fPacketSize = USB_TXFIFO2_SZ_16; break; case 32: fPacketSize = USB_TXFIFO2_SZ_32; break; case 64: fPacketSize = USB_TXFIFO2_SZ_64; break; case 128: fPacketSize = USB_TXFIFO2_SZ_128; break; case 256: fPacketSize = USB_TXFIFO2_SZ_256; break; case 512: fPacketSize = USB_TXFIFO2_SZ_512; break; case 1024: fPacketSize = USB_TXFIFO2_SZ_1024; break; } // DM320 USB registers : OUT direction // USB specification : IN direction that mean device-to-host if( stEndpointInfo[i].fAddr & 0x80 ) { writeb( USB_TXCSR1_CLRDATTOG | USB_TXCSR1_FLFIFO | USB_TXCSR1_UNDERRUN, USB_PER_TXCSR1 ); writeb( USB_TXCSR1_FLFIFO, USB_PER_TXCSR1 ); // clear FIFO for double buffer writeb( USB_TXCSR2_FRDATTOG | USB_TXCSR2_MODE_TX, USB_TXCSR2 ); // no DMA sending writeb( fLowAddr, USB_TXFIFO1 ); writeb( fHighAddr | fPacketSize | fIsDualBuf, USB_TXFIFO2 ); writeb( stEndpointInfo[i].nSize / 8, USB_TXMAXP ); } // DM320 USB registers : IN direction // USB specification : OUT direction that mean host-to-device else { // clear Data toggle, FIFO, OVERRUN of RXCSR1 writeb( USB_RXCSR1_CLRDATTOG | USB_RXCSR1_FLFIFO, USB_PER_RXCSR1 ); writeb( USB_RXCSR1_FLFIFO, USB_PER_RXCSR1 ); // clear FIFO for double buffer writeb( 0x00, USB_PER_RXCSR2); // no DMA receiving// writeb( USB_RXCSR2_AUTOCLR, USB_PER_RXCSR2 ); // AUTOCLR for DMA receiving writeb( fLowAddr, USB_RXFIFO1 ); writeb( fHighAddr | fPacketSize | fIsDualBuf, USB_RXFIFO2 ); Vishal: writeb( stEndpointInfo[i].nSize / 8, USB_RXMAXP ); } nBufPos += stEndpointInfo[i].nSize; } else writeb( 0x00, USB_RXMAXP ); }}static void dm320_init_per_mode(){ outw( inw( IO_CLK_MOD2 ) | 0x0060, IO_CLK_MOD2 ); // 0x0040 : USB clock enable // 0x0020 : GIO clock enable outw( inw( IO_CLK_LPCTL1 ) & 0xFFEF, IO_CLK_LPCTL1 ); // USB Power down mode off // 0x0010 : Set USB power down mode. writel( 0x00000000, AHB_USBCTL ); // USB controller in peripheral mode. ( 0x00000008 : host mode ) writeb( USB_DEVCTL_SESSREQ, USB_DEVCTL ); /* ATTENTION : vishal :for bug fix only!! **ATTENTION** */ // Setup USB core registers writeb( 0x00, USB_FADDR ); // reset peripheral address register writeb( 0x00, USB_POWER ); // reset power control register}static void dm320_clear_intrs(){ outw( ( 1 << IRQ_USB_DMA ), IO_INTC_IRQ0 ); // clear USB core interrupt flag outw( ( 1 << IRQ_USB_CORE ), IO_INTC_IRQ0 ); // clear USB DMA interrupt flag readb( USB_INTRTX1 ); // clear TX interrupt flags readb( USB_INTRRX1 ); // clear RX interrupt flags readb( USB_INTRUSB ); // clear control interrupt flags readb( USBDMA_INTR );}static void dm320_enable_intrs(){ writeb( ( BULK_OUT_EP << 1 ) | USB_EP0, USB_INTRTX1E ); // enable endpoint transmmit interrupt ( including EP0 RX/TX ) writeb( ( BULK_IN_EP << 1 ), USB_INTRRX1E ); // enable endpoint receving interrupt writeb( USB_RESET | USB_RESUME | USB_SUSPEND | USB_SESSREQ | USB_SOF , USB_INTRUSBE ); // Peripheral mode & 'B' type( slave ) }static void dm320_reconnect_init(struct dm320 *dev){ dev->gadget.speed = USB_SPEED_UNKNOWN; printk("device speed is UNKNOWN\n"); paddr_status = 0 ; dev->peripheral_addr = 0;}static void dm320_usb_hw_init(struct dm320 *dev ){ dm320_init_per_mode(); dm320_clear_intrs(); dm320_enable_intrs(); dm320_setup_ep_regs(dev); dev->peripheral_addr = 0; dm320_set_addr_reg(0); writeb( USB_EP0_SELECT, USB_INDEX ); // set default endpoint as EP0}static void usb_reset (struct dm320 *dev){ printk("dm320 : %s\n", __FUNCTION__);; dev->gadget.speed = USB_SPEED_UNKNOWN; dm320_usb_hw_init(dev ); printk("device speed is UNKNOWN\n"); INIT_LIST_HEAD (&dev->gadget.ep_list); list_add_tail (&dev->ep [1].ep.ep_list, &dev->gadget.ep_list); list_add_tail (&dev->ep [2].ep.ep_list, &dev->gadget.ep_list); list_add_tail (&dev->ep [3].ep.ep_list, &dev->gadget.ep_list);}static int dm320_init_gio(){ outw( inw( IO_CLK_DIV4 ) | ( ( ( 4 ) - 1 ) << 8 ) | ( ( 1 ) - 1 ), IO_CLK_DIV4 ); if(request_gio( GIO_DP_PULLUP )!=0 ) // D+ pullup control GIO { printk(" dm320 : GIO for D+ Pullup already taken\n"); return -EBUSY; } gio_set_dir( GIO_DP_PULLUP, 0 ); // output direction gio_set_bitset( GIO_DP_PULLUP ); // set D+ pullup if(request_gio( GIO_USB_ATTACH )!=0) { printk(" dm320 : USB Attach Interrupt handler GIO Interrupt already taken\n"); return -EBUSY; } gio_enable_irq( GIO_USB_ATTACH, GIO_ANY_EDGE ); outw(inw(IO_GIO_CHAT0) | (1 << GIO_USB_ATTACH),IO_GIO_CHAT0); return 0;}static int dm320_register_irqs(){ if( request_irq( IRQ_USB_ATTACH, handle_attach_irqs, SA_INTERRUPT, "usb_external", handle_attach_irqs )!= 0 ) { printk("dm320 USB: Attach IRQ could not be registered \n"); return -EBUSY; } // Register USB core control interrupt handler if(request_irq( IRQ_USB_CORE, handle_core_irqs, SA_INTERRUPT, "usb_core", handle_core_irqs )!=0 ) { printk("dm320 USB: Core IRQ could not be registered\n"); return -EBUSY; } return 0;}static int dm320_probe (void){ int retval; if (the_controller!= NULL) { /* Check if the driver for the DM320 device mode is already running */ printk(" dm320: driver already running.\n"); return -EBUSY; /* return busy status and exit driver...am i addicted to commenting code? */ } the_controller = kmalloc (sizeof(struct dm320), SLAB_KERNEL); if (the_controller == NULL) { printk("dm320: cannot allocate memory for USB function driver!\n"); retval = -ENOMEM; goto done; } memset (the_controller, 0, sizeof(struct dm320)); spin_lock_init (&the_controller->lock); the_controller->gadget.ops = &dm320_ops; the_controller->gadget.is_dualspeed = 0; /* The DM320 is a full speed controlelr only!! */ strcpy (the_controller->gadget.dev.bus_id, "DM320 Gadget"); the_controller->gadget.dev.release = gadget_release; the_controller->gadget.name = driver_name; the_controller->enabled = 1; the_controller->chiprev = inw( IO_BUSC_REVR ); printk("dm320: %s :Board revision : %d.%d\n",__FUNCTION__, the_controller->chiprev >> 4, the_controller->chiprev & 0xF ); outw( inw( IO_CLK_MOD2 ) | 0x0060, IO_CLK_MOD2 ); // Enable USB clock & GIO clock if(dm320_init_gio() != 0 ) goto done; if(dm320_register_irqs() != 0 ) goto done; the_controller->attach_irq = IRQ_USB_ATTACH; the_controller->core_irq = IRQ_USB_CORE; usb_reset (the_controller); usb_reinit (the_controller); if( (dm320_connection_status( ) ) > 0 ) {#if 0 usb_reset (the_controller); outw(inw(IO_INTC_FISEL0) & 0x7F, IO_INTC_FISEL0); outw(inw(IO_INTC_EINT0) | 0x80, IO_INTC_EINT0); dm320_reconnect_init(the_controller);#endif } writeb( USB_DEVCTL_SESSREQ, USB_DEVCTL ); // For 'B' device initiate session request protocol INFO (the_controller, "%s\n", driver_desc); INFO (the_controller, "core irq %d, attach irq %d, dma irq %d\n", the_controller->core_irq, the_controller->attach_irq, the_controller->dma_irq); INFO (the_controller, "version: %s\n", DRIVER_VERSION); device_register (&the_controller->gadget.dev); return 0;done: if (the_controller) dm320_remove (the_controller); }static int __init init (void){ return dm320_probe ();}static void __exit cleanup (void){ dm320_remove (the_controller); }module_init (init);module_exit (cleanup);MODULE_DESCRIPTION (DRIVER_DESC);MODULE_AUTHOR ("Ingenient Technologies");MODULE_LICENSE ("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -