?? sa1100.c
字號:
/** * udc_endpoint_halted - is endpoint halted * @ep: * * Return non-zero if endpoint is halted */int udc_endpoint_halted (unsigned int ep){ switch (ep) { case 0: return (udc (UDCCS0) & UDCCS0_FST) != 0; case 1: return (udc (UDCCS1) & UDCCS1_FST) != 0; case 2: return (udc (UDCCS2) & UDCCS2_FST) != 0; } 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){ usb_address = address;#if 0 int ok; // address can be setup, udc will wait until ack received dbg_udc(1, "%02d", address); IOIOIO(UDCAR, usb_address, *(UDCAR) = address , (udc(UDCAR) != address), ok); if (*(UDCAR) != address) { dbg_udc(0, "AA %02d %02d ok: %d", udc(UDCAR), address, ok); udelay(20); IOIOIO(UDCAR, usb_address, *(UDCAR) = address , (udc(UDCAR) != address), ok); if (*(UDCAR) != address) { dbg_udc(0, "BB %02d %02d ok: %d", udc(UDCAR), address, ok); udelay(40); IOIOIO(UDCAR, usb_address, *(UDCAR) = address , (udc(UDCAR) != address), ok); } } dbg_udc(0, "CC %02d %02d ok: %d", udc(UDCAR), address, ok);#endif}#ifdef CONFIG_SA1100_BITSYstatic int crc32 (char *s, int length){ /* indices */ int pByte; int pBit; const unsigned long poly = 0xedb88320; unsigned long crc_value = 0xffffffff; for (pByte = 0; pByte < length; pByte++) { unsigned char c = *(s++); for (pBit = 0; pBit < 8; pBit++) { crc_value = (crc_value >> 1) ^ (((crc_value ^ c) & 0x01) ? poly : 0); c >>= 1; } } return crc_value;}#endif/** * udc_serial_init - set a serial number if available */int __init udc_serial_init (struct usb_bus_instance *bus){#if defined(SHOW_CPU_STEPPING) char *stepping; u32 id = getCPUID (&stepping); dbg_init (0, "CPU ID #%08x stepping %s",id,stepping);#else dbg_init (2, "serial number");#endif#ifdef CONFIG_SA1100_BITSY if (machine_is_bitsy ()) { char serial_number[22]; int i; int j; memset (&serial_number, 0, sizeof (serial_number)); for (i = 0, j = 0; i < 20; i++, j++) { char buf[4]; h3600_eeprom_read (5 + i, buf, 2); serial_number[j] = buf[1]; } serial_number[j] = '\0'; bus->serial_number = crc32 (serial_number, 22); if (bus->serial_number_str = kmalloc (strlen (serial_number) + 1, GFP_KERNEL)) { strcpy (bus->serial_number_str, serial_number); } //dbg_udc(0, "serial: %s %08x", bus->serial_number_str, bus->serial_number); return 0; }#endif#ifdef CONFIG_SA1100_CALYPSO if (machine_is_calypso ()) { __u32 eerom_serial; int i; if ((i = CalypsoIicGet (IIC_ADDRESS_SERIAL0, (unsigned char *) &eerom_serial, sizeof (eerom_serial)))) { bus->serial_number = eerom_serial; } if (bus->serial_number_str = kmalloc (9, GFP_KERNEL)) { sprintf (bus->serial_number_str, "%08X", eerom_serial & 0xffffffff); } //dbg_udc(0, "serial: %s %08x", bus->serial_number_str, bus->serial_number); return 0; }#endif 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 * @logical_endpoint: * * Return physical endpoint number to use for this logical endpoint or zero if not valid. */int udc_check_ep (int logical_endpoint, int packetsize){ if (packetsize > 64) { return 0; } switch (logical_endpoint) { case 1: return 1; case 0x82: return 2; default: return 0; }}/** * 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){ dbg_udc (1, "[%d]:", ep); if (ep < UDC_MAX_ENDPOINTS) { ep_endpoints[ep] = endpoint; dbg_udc (1, "[%d] ep_endpoint %p endpoint: %p", ep, ep_endpoints[ep], endpoint); if (endpoint) { switch (ep) { case 0: // Control ep0_enable (device, endpoint); break; case 1: // OUT dbg_udc (1, "[%d]: CHECKING rcv_urb: %p", ep, endpoint->rcv_urb); // XXX XXX if (!endpoint->rcv_urb) { usbd_fill_rcv (device, endpoint, 5); endpoint->rcv_urb = first_urb_detached (&endpoint->rdy); dbg_udc (1, "[%d]: SETTING rcv_urb: %p", ep, endpoint->rcv_urb); } ep1_enable (device, endpoint, usbd_rcv_dma); break; case 2: // IN ep2_enable (device, endpoint, usbd_tx_dma); break; } } }}/** * udc_disable_ep - disable endpoint * @ep: * * Disable specified endpoint */void udc_disable_ep (unsigned int ep){ dbg_udc (1, "[%d]:", ep); if (ep < UDC_MAX_ENDPOINTS) { struct usb_endpoint_instance *endpoint; if ((endpoint = ep_endpoints[ep])) { ep_endpoints[ep] = NULL; usbd_flush_ep (endpoint); } switch (ep) { case 0: ep0_disable (); break; case 1: ep1_disable (); break; case 2: ep2_disable (); break; } }}/* ********************************************************************************************* *//** * udc_incradle - is the USB cable connected * * Return non-zeron if cable is connected. */int udc_connected (){ int rc = 1;#ifdef CONFIG_SA1100_USBCABLE_GPIO#ifdef CONFIG_SA1100_USBCABLE_ACTIVE_HIGH rc = (GPLR & GPIO_GPIO (23)) != 0; dbg_udc (1, "udc_connected: ACTIVE_HIGH: %d", rc);#else rc = (GPLR & GPIO_GPIO (23)) == 0; dbg_udc (1, "udc_connected: ACTIVE_LOW: %d", rc);#endif#else#warning UDC_CONNECTED not implemented#endif return rc;}/** * udc_connect - enable pullup resistor * * Turn on the USB connection by enabling the pullup resistor. */void udc_connect (void){#if defined(CONFIG_SA1100_COLLIE) // XXX change to 5500 #warning COLLIE CONNECT if (ucb1200_test_io(TC35143_GPIO_VERSION0) != 0 || ucb1200_test_io(TC35143_GPIO_VERSION1) != 0) { SCP_REG_GPCR |= SCP_GPCR_PA19; /* direction : out mode */ SCP_REG_GPWR |= SCP_GPCR_PA19; /* set Hi */ dbg_udc(1, "udc_connect: %d GPCR: %x GPWR: %x GPRR: %x", SCP_GPCR_PA19, SCP_REG_GPCR, SCP_REG_GPWR, SCP_REG_GPRR); }#elif defined(CONFIG_SA1100_CONNECT_GPIO) GAFR |= GPIO_GPIO (CONFIG_SA1100_CONNECT_GPIO); GPDR |= GPIO_GPIO (CONFIG_SA1100_CONNECT_GPIO); #ifdef CONFIG_SA1100_CONNECT_ACTIVE_HIGH GPSR = GPIO_GPIO (CONFIG_SA1100_CONNECT_GPIO); dbg_udc (1, "udc_connect: %d ACTIVE_HIGH %x %x %x", CONFIG_SA1100_CONNECT_GPIO, GPIO_GPIO (CONFIG_SA1100_CONNECT_GPIO), GPDR, GPLR); #else GPCR = GPIO_GPIO (CONFIG_SA1100_CONNECT_GPIO); dbg_udc (1, "udc_connect: %d ACTIVE_LOW %x %x %x", CONFIG_SA1100_CONNECT_GPIO, GPIO_GPIO (CONFIG_SA1100_CONNECT_GPIO), GPDR, GPLR); #endif#else /* defined(CONFIG_SA1100_CONNECT_GPIO) */#warning UDC_CONNECT not implemented#endif}/** * udc_disconnect - disable pullup resistor * * Turn off the USB connection by disabling the pullup resistor. */void udc_disconnect (void){#if defined(CONFIG_SA1100_COLLIE) // XXX change to 5500 if (ucb1200_test_io(TC35143_GPIO_VERSION0) != 0 || ucb1200_test_io(TC35143_GPIO_VERSION1) != 0) { SCP_REG_GPWR &= ~SCP_GPCR_PA19; /* set Hi */ SCP_REG_GPCR &= ~SCP_GPCR_PA19; /* direction : out mode */ dbg_udc(1, "udc_disconnect: %d GPCR: %x GPWR: %x GPRR: %x", SCP_GPCR_PA19, SCP_REG_GPCR, SCP_REG_GPWR, SCP_REG_GPRR); }#elif defined(CONFIG_SA1100_CONNECT_GPIO)#ifdef CONFIG_SA1100_CONNECT_ACTIVE_HIGH GPCR = GPIO_GPIO (CONFIG_SA1100_CONNECT_GPIO); dbg_udc (1, "udc_disconnect: %d ACTIVE_HIGH", CONFIG_SA1100_CONNECT_GPIO);#else GPSR = GPIO_GPIO (CONFIG_SA1100_CONNECT_GPIO); dbg_udc (1, "udc_disconnect: %d ACTIVE_LOW", CONFIG_SA1100_CONNECT_GPIO);#endif GPDR &= ~GPIO_GPIO (CONFIG_SA1100_CONNECT_GPIO);#endif}/* ********************************************************************************************* */static __inline__ void set_interrupts (int flags){ int ok; //dbg_udc(1, "udc_set_interrupts: %02x", flags); // set interrupt mask SET_AND_TEST ((*(UDCCR) = flags), (udc (UDCCR) != flags), ok); if (!ok) { dbg_intr (0, "failed to set UDCCR %02x to %02x", *(UDCCR), flags); }}/** * udc_enable_interrupts - enable interrupts * * Switch on UDC interrupts. * */void udc_all_interrupts (struct usb_device_instance *device){ set_interrupts (0); dbg_udc (1, "%02x", *(UDCCR)); // setup tick#ifdef USE_ADD_DEL_TIMER_FOR_USBADDR_CHECK if (!usb_addr_check_initialized) { init_timer (&sa1100_usb_dev_addr_check); usb_addr_check_initialized = 1; sa1100_usb_dev_addr_check.function = sa1100_tick; sa1100_usb_dev_addr_check.data = 1; sa1100_usb_dev_addr_check.expires = jiffies + CHECK_INTERVAL; add_timer (&sa1100_usb_dev_addr_check); }#else // XXX sa1100_tq.sync = 0; sa1100_tq.routine = sa1100_tick; sa1100_tq.data = &udc_saw_sof; queue_task (&sa1100_tq, &tq_timer);#endif}/** * udc_suspended_interrupts - enable suspended interrupts * * Switch on only UDC resume interrupt. * */void udc_suspended_interrupts (struct usb_device_instance *device){ set_interrupts (UDCCR_SRM); dbg_udc (1, "%02x", *(UDCCR));}/** * udc_disable_interrupts - disable interrupts. * * switch off interrupts */void udc_disable_interrupts (struct usb_device_instance *device){ set_interrupts (UDCCR_SRM | UDCCR_EIM | UDCCR_RIM | UDCCR_TIM | UDCCR_SRM | UDCCR_REM); dbg_udc (1, "%02x", *(UDCCR));}/* ********************************************************************************************* *//** * udc_ep0_packetsize - return ep0 packetsize */int udc_ep0_packetsize (void){ return EP0_PACKETSIZE;}/** * udc_enable - enable the UDC * * Switch on the UDC */void udc_enable (struct usb_device_instance *device){ int ok; dbg_udc (1, "************************* udc_enable:"); //dbg_udc(0, ""); //dbg_udc(0, "udc_enable: device: %p", device); // save the device structure pointer udc_device = device; // enable UDC for (ok = 0; (*(UDCCR) & UDCCR_UDA) && ok < 100000; ok++); if (ok > 10000) { dbg_udc (0, "Waiting too long to go inactive: UDCCR: %02x", *(UDCCR)); } // set UDD SET_AND_TEST ((*(UDCCR) |= UDCCR_UDD), (!udc (UDCCR) & UDCCR_UDD), ok); if (!ok) { dbg_udc (0, "Waiting too long to disable: UDCCR: %02x", *(UDCCR)); } // reset UDD SET_AND_TEST ((*(UDCCR) &= ~UDCCR_UDD), (udc (UDCCR) & UDCCR_UDD), ok); if (!ok) { dbg_udc (0, "can't enable udc, FAILED: %02x", *(UDCCR)); }}/** * udc_disable - disable the UDC * * Switch off the UDC */void udc_disable (void){ int ok; dbg_udc (1, "************************* udc_disable:"); // tell tick task to stop#ifdef USE_ADD_DEL_TIMER_FOR_USBADDR_CHECK del_timer (&sa1100_usb_dev_addr_check); sa1100_usb_dev_addr_check.data = 0; usb_addr_check_initialized = 0;#else sa1100_tq.data = NULL; while (sa1100_tq.sync) { //printk(KERN_DEBUG"waiting for sa1100_tq to stop\n"); schedule_timeout (10 * HZ); }#endif // disable UDC for (ok = 0; (*(UDCCR) & UDCCR_UDA) && ok < 100000; ok++); if (ok > 10000) { dbg_udc (0, "Waiting too long to go inactive: UDCCR: %02x", *(UDCCR)); } // set UDD SET_AND_TEST ((*(UDCCR) |= UDCCR_UDD), (!udc (UDCCR) & UDCCR_UDD), ok); if (!ok) { dbg_udc (0, "Waiting too long to disable: UDCCR: %02x", *(UDCCR)); } dbg_udc (7, "CCR: %02x", *(UDCCR)); // reset device pointer udc_device = NULL;}/** * udc_startup - allow udc code to do any additional startup */void udc_startup_events (struct usb_device_instance *device){ usbd_device_event (device, DEVICE_INIT, 0); usbd_device_event (device, DEVICE_CREATE, 0); usbd_device_event (device, DEVICE_HUB_CONFIGURED, 0); usbd_device_event (device, DEVICE_RESET, 0); // XXX should be done from device event}/* ********************************************************************************************* *//** * udc_name - return name of USB Device Controller */char *udc_name (void){ return UDC_NAME;}/** * udc_request_udc_irq - request UDC interrupt * * Return non-zero if not successful. */int udc_request_udc_irq (){ // request IRQ and two dma channels // XXX GPDR &= ~GPIO_GPIO(23); // XXX set_GPIO_IRQ_edge(GPIO_GPIO(CONFIG_SA1100_USBCABLE_GPIO), GPIO_BOTH_EDGES); dbg_init (2, "requesting udc irq: %d %d", 13, IRQ_Ser0UDC); return request_irq (IRQ_Ser0UDC, int_hndlr_device, SA_INTERRUPT | SA_SAMPLE_RANDOM, "SA1100 USBD Bus Interface", NULL);}/** * udc_request_cable_irq - request Cable interrupt * * Return non-zero if not successful. */int udc_request_cable_irq (){#ifdef CONFIG_SA1100_USBCABLE_GPIO dbg_init (2, "requesting cable irq: %d %d", CONFIG_SA1100_USBCABLE_GPIO, SA1100_GPIO_TO_IRQ (CONFIG_SA1100_USBCABLE_GPIO)); GPDR &= ~GPIO_GPIO (23); set_GPIO_IRQ_edge (GPIO_GPIO (CONFIG_SA1100_USBCABLE_GPIO), GPIO_BOTH_EDGES); return request_irq (SA1100_GPIO_TO_IRQ (CONFIG_SA1100_USBCABLE_GPIO), int_hndlr_cable, SA_INTERRUPT | SA_SAMPLE_RANDOM, "SA1100 Monitor", NULL);#else return 0;#endif}/** * udc_request_udc_io - request UDC io region * * Return non-zero if not successful. */int udc_request_io (){ //sa1100_bi_init_dma (); usbd_rcv_dma = usbd_tx_dma = -1; if (sa1100_request_dma (&usbd_rcv_dma, "SA1100 USBD OUT - rcv dma", DMA_Ser0UDCRd)) { dbg_init (2, "channel %d taken", usbd_rcv_dma); return -EINVAL; } if (sa1100_request_dma (&usbd_tx_dma, "SA1100 USBD IN - tx dma", DMA_Ser0UDCWr)) { dbg_init (2, "channel %d taken", usbd_tx_dma); sa1100_free_dma (usbd_rcv_dma); return -EINVAL; } return 0;}/** * udc_release_udc_irq - release UDC irq */void udc_release_udc_irq (){ free_irq (IRQ_Ser0UDC, NULL);}/** * udc_release_cable_irq - release Cable irq */void udc_release_cable_irq (){#ifdef CONFIG_SA1100_USBCABLE_GPIO dbg_init (2, "freeing cable irq: %d", CONFIG_SA1100_USBCABLE_GPIO);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -