void bootloader_main() { SystemInit(); spiflash_reinit(); CGU_Init(); hw_digital_output(LED1); hw_digital_output(LED2); hw_digital_output(CC3K_CONN_LED); hw_digital_output(CC3K_ERR_LED); hw_digital_write(CC3K_CONN_LED, 0); hw_digital_write(CC3K_ERR_LED, 0); init_systick(); __enable_irq(); usb_init(); usb_set_speed(USB_SPEED_FULL); usb_attach(); while(!exit_and_jump) { led_task(); __WFI(); /* conserve power */ } delay_ms(25); usb_detach(); delay_ms(100); if (dfu_target == TARGET_RAM) { jump_to_flash(DFU_DEST_BASE, 0); } }
static void usb_hub_attach(USBPort *port1, USBDevice *dev) { USBHubState *s = port1->opaque; USBHubPort *port = &s->ports[port1->index]; if (dev) { if (port->port.dev) usb_attach(port1, NULL); port->wPortStatus |= PORT_STAT_CONNECTION; port->wPortChange |= PORT_STAT_C_CONNECTION; if (dev->speed == USB_SPEED_LOW) port->wPortStatus |= PORT_STAT_LOW_SPEED; else port->wPortStatus &= ~PORT_STAT_LOW_SPEED; port->port.dev = dev; /* send the attach message */ usb_send_msg(dev, USB_MSG_ATTACH); } else { dev = port->port.dev; if (dev) { port->wPortStatus &= ~PORT_STAT_CONNECTION; port->wPortChange |= PORT_STAT_C_CONNECTION; if (port->wPortStatus & PORT_STAT_ENABLE) { port->wPortStatus &= ~PORT_STAT_ENABLE; port->wPortChange |= PORT_STAT_C_ENABLE; } /* send the detach message */ usb_send_msg(dev, USB_MSG_DETACH); port->port.dev = NULL; } } }
// see usb_hw_layer.h for documentation void usb_task(void) { if (usb_attached()) { if (UCON_USBEN==0) { usb_attach(); } } else { if (UCON_USBEN==1) { usb_detach(); } } if ((usb_state == USB_STATE_ATTACHED)&&(!UCON_SE0)) { UIR=0; UIE=0; //enable_interrupts(INT_USB); //enable_interrupts(GLOBAL); UIE=__USB_UIF_IDLE | __USB_UIF_RESET; //enable IDLE and RESET USB ISR usb_state=USB_STATE_POWERED; } }
void usb_port_reset(USBPort *port) { USBDevice *dev = port->dev; assert(dev != NULL); usb_detach(port); usb_attach(port); usb_device_reset(dev); }
void usb_reset(USBPort *port) { USBDevice *dev = port->dev; assert(dev != NULL); usb_detach(port); usb_attach(port); usb_send_msg(dev, USB_MSG_RESET); }
/* Attach or detach a device on a root hub port. */ static void ohci_attach(USBPort *port1, USBDevice *dev) { OHCIState *s = port1->opaque; OHCIPort *port = &s->rhport[port1->index]; uint32_t old_state = port->ctrl; if (dev) { if (port->port.dev) { usb_attach(port1, NULL); } /* set connect status */ port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC; /* update speed */ if (dev->speed == USB_SPEED_LOW) port->ctrl |= OHCI_PORT_LSDA; else port->ctrl &= ~OHCI_PORT_LSDA; port->port.dev = dev; /* notify of remote-wakeup */ if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) ohci_set_interrupt(s, OHCI_INTR_RD); /* send the attach message */ usb_send_msg(dev, USB_MSG_ATTACH); dprintf("usb-ohci: Attached port %d\n", port1->index); } else { /* set connect status */ if (port->ctrl & OHCI_PORT_CCS) { port->ctrl &= ~OHCI_PORT_CCS; port->ctrl |= OHCI_PORT_CSC; } /* disable port */ if (port->ctrl & OHCI_PORT_PES) { port->ctrl &= ~OHCI_PORT_PES; port->ctrl |= OHCI_PORT_PESC; } dev = port->port.dev; if (dev) { /* send the detach message */ usb_send_msg(dev, USB_MSG_DETACH); } port->port.dev = NULL; dprintf("usb-ohci: Detached port %d\n", port1->index); } if (old_state != port->ctrl) ohci_set_interrupt(s, OHCI_INTR_RHSC); }
/* Reset the controller */ static void ohci_reset(void *opaque) { OHCIState *ohci = opaque; OHCIPort *port; int i; ohci_bus_stop(ohci); ohci->ctl = 0; ohci->old_ctl = 0; ohci->status = 0; ohci->intr_status = 0; ohci->intr = OHCI_INTR_MIE; ohci->hcca = 0; ohci->ctrl_head = ohci->ctrl_cur = 0; ohci->bulk_head = ohci->bulk_cur = 0; ohci->per_cur = 0; ohci->done = 0; ohci->done_count = 7; /* FSMPS is marked TBD in OCHI 1.0, what gives ffs? * I took the value linux sets ... */ ohci->fsmps = 0x2778; ohci->fi = 0x2edf; ohci->fit = 0; ohci->frt = 0; ohci->frame_number = 0; ohci->pstart = 0; ohci->lst = OHCI_LS_THRESH; ohci->rhdesc_a = OHCI_RHA_NPS | ohci->num_ports; ohci->rhdesc_b = 0x0; /* Impl. specific */ ohci->rhstatus = 0; for (i = 0; i < ohci->num_ports; i++) { port = &ohci->rhport[i]; port->ctrl = 0; if (port->port.dev) { usb_attach(&port->port, port->port.dev); } } if (ohci->async_td) { usb_cancel_packet(&ohci->usb_packet); ohci->async_td = 0; } DPRINTF("usb-ohci: Reset %s\n", ohci->name); }
void usb_attach(USBPort *port, USBDevice *dev) { if (dev != NULL) { /* attach */ if (port->dev) { usb_attach(port, NULL); } dev->port = port; port->dev = dev; port->ops->attach(port); usb_send_msg(dev, USB_MSG_ATTACH); } else { /* detach */ dev = port->dev; assert(dev); port->ops->detach(port); usb_send_msg(dev, USB_MSG_DETACH); dev->port = NULL; port->dev = NULL; } }
// see usb_hw_layer.h for documentation void usb_task(void) { #if defined(USB_ISR_POLLING) if (interrupt_active(INT_USB)) { usb_isr(); } #endif if (usb_attached()) { if (UCON_USBEN==0) { debug_usb(debug_putc, "\r\n\nUSB TASK: ATTACH"); usb_attach(); } } else { if (UCON_USBEN==1) { debug_usb(debug_putc, "\r\n\nUSB TASK: DE-ATTACH"); usb_detach(); } } if ((usb_state == USB_STATE_ATTACHED)&&(!UCON_SE0)) { UIR=0; UIE=0; #if !defined(USB_ISR_POLLING) enable_interrupts(INT_USB); enable_interrupts(GLOBAL); #endif UIE=__USB_UIF_IDLE | __USB_UIF_RESET; //enable IDLE and RESET USB ISR usb_state=USB_STATE_POWERED; debug_usb(debug_putc, "\r\n\nUSB TASK: POWERED"); } }
/* inline since branch is chosen at compile time */ static inline void usb_slave_mode(bool on) { #ifdef USE_ROCKBOX_USB int rc; if (on) { trigger_cpu_boost(); #ifdef HAVE_PRIORITY_SCHEDULING thread_set_priority(THREAD_ID_CURRENT, PRIORITY_REALTIME); #endif usb_attach(); } else /* usb_state == USB_INSERTED (only!) */ { #ifndef USB_DETECT_BY_DRV usb_enable(false); #endif #ifdef HAVE_PRIORITY_SCHEDULING thread_set_priority(THREAD_ID_CURRENT, PRIORITY_SYSTEM); #endif /* Entered exclusive mode */ rc = disk_mount_all(); if (rc <= 0) /* no partition */ panicf("mount: %d",rc); cancel_cpu_boost(); } #else /* !USE_ROCKBOX_USB */ if (on) { /* until we have native mass-storage mode, we want to reboot on usb host connect */ try_reboot(); } #endif /* USE_ROCKBOX_USB */ }
// **************************************************************************** void HAL_hardware_init_final(void) { usb_init(); usb_attach(); }
static void usb_thread(void) { int num_acks_to_expect = 0; struct queue_event ev; while(1) { queue_wait(&usb_queue, &ev); switch(ev.id) { #ifdef USB_DRIVER_CLOSE case USB_QUIT: return; #endif #ifdef HAVE_USBSTACK case USB_TRANSFER_COMPLETION: usb_core_handle_transfer_completion( (struct usb_transfer_completion_event_data*)ev.data); break; #endif #ifdef USB_DETECT_BY_DRV /* In this case, these events the handle cable insertion USB * driver determines INSERTED/EXTRACTED state. */ case USB_POWERED: /* Set the state to USB_POWERED for now and enable the driver * to detect a bus reset only. If a bus reset is detected, * USB_INSERTED will be received. */ usb_state = USB_POWERED; usb_enable(true); break; case USB_UNPOWERED: usb_enable(false); /* This part shouldn't be obligatory for anything that can * reliably detect removal of the data lines. USB_EXTRACTED * could be posted on that event while bus power remains * available. */ queue_post(&usb_queue, USB_EXTRACTED, 0); break; #endif /* USB_DETECT_BY_DRV */ case USB_INSERTED: #ifdef HAVE_LCD_BITMAP if(do_screendump_instead_of_usb) { usb_state = USB_SCREENDUMP; screen_dump(); #ifdef HAVE_REMOTE_LCD remote_screen_dump(); #endif break; } #endif #ifdef HAVE_USB_POWER if(usb_power_button()) { /* Only charging is desired */ usb_state = USB_POWERED; #ifdef HAVE_USBSTACK #ifdef USB_ENABLE_STORAGE usb_core_enable_driver(USB_DRIVER_MASS_STORAGE, false); #endif #ifdef USB_ENABLE_HID #ifdef USB_ENABLE_CHARGING_ONLY usb_core_enable_driver(USB_DRIVER_HID, false); #else usb_core_enable_driver(USB_DRIVER_HID, true); #endif /* USB_ENABLE_CHARGING_ONLY */ #endif /* USB_ENABLE_HID */ #ifdef USB_ENABLE_CHARGING_ONLY usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY, true); #endif usb_attach(); #endif break; } #endif /* HAVE_USB_POWER */ #ifdef HAVE_USBSTACK #ifdef HAVE_USB_POWER /* Set the state to USB_POWERED for now. If permission to connect * by threads and storage is granted it will be changed to * USB_CONNECTED. */ usb_state = USB_POWERED; #endif #ifdef USB_ENABLE_STORAGE usb_core_enable_driver(USB_DRIVER_MASS_STORAGE, true); #endif #ifdef USB_ENABLE_HID usb_core_enable_driver(USB_DRIVER_HID, usb_hid); #endif #ifdef USB_ENABLE_CHARGING_ONLY usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY, false); #endif /* Check any drivers enabled at this point for exclusive storage * access requirements. */ exclusive_storage_access = usb_core_any_exclusive_storage(); if(!exclusive_storage_access) { usb_attach(); break; } #endif /* HAVE_USBSTACK */ /* Tell all threads that they have to back off the storage. We subtract one for our own thread. */ num_acks_to_expect = queue_broadcast(SYS_USB_CONNECTED, 0) - 1; DEBUGF("USB inserted. Waiting for ack from %d threads...\n", num_acks_to_expect); break; case SYS_USB_CONNECTED_ACK: if(num_acks_to_expect > 0 && --num_acks_to_expect == 0) { DEBUGF("All threads have acknowledged the connect.\n"); usb_slave_mode(true); usb_state = USB_INSERTED; } else { DEBUGF("usb: got ack, %d to go...\n", num_acks_to_expect); } break; case USB_EXTRACTED: #ifdef HAVE_LCD_BITMAP if(usb_state == USB_SCREENDUMP) { usb_state = USB_EXTRACTED; break; /* Connected for screendump only */ } #endif #ifndef HAVE_USBSTACK /* Stack must undo this if POWERED state was transitional */ #ifdef HAVE_USB_POWER if(usb_state == USB_POWERED) { usb_state = USB_EXTRACTED; break; } #endif #endif /* HAVE_USBSTACK */ if(usb_state == USB_INSERTED) { /* Only disable the USB mode if we really have enabled it some threads might not have acknowledged the insertion */ usb_slave_mode(false); } usb_state = USB_EXTRACTED; #ifdef HAVE_USBSTACK if(!exclusive_storage_access) { #ifndef USB_DETECT_BY_DRV /* Disabled handling USB_UNPOWERED */ usb_enable(false); #endif break; } #endif /* HAVE_USBSTACK */ num_acks_to_expect = usb_release_exclusive_storage(); break; case SYS_USB_DISCONNECTED_ACK: if(num_acks_to_expect > 0 && --num_acks_to_expect == 0) { DEBUGF("All threads have acknowledged. " "We're in business.\n"); } else { DEBUGF("usb: got ack, %d to go...\n", num_acks_to_expect); } break; #ifdef HAVE_HOTSWAP case SYS_HOTSWAP_INSERTED: case SYS_HOTSWAP_EXTRACTED: #ifdef HAVE_USBSTACK usb_core_hotswap_event(1,ev.id == SYS_HOTSWAP_INSERTED); #else /* !HAVE_USBSTACK */ if(usb_state == USB_INSERTED) { #if (CONFIG_STORAGE & STORAGE_MMC) usb_enable(false); usb_mmc_countdown = HZ/2; /* re-enable after 0.5 sec */ #endif /* STORAGE_MMC */ } #endif /* HAVE_USBSTACK */ break; #if (CONFIG_STORAGE & STORAGE_MMC) case USB_REENABLE: if(usb_state == USB_INSERTED) usb_enable(true); /* reenable only if still inserted */ break; #endif /* STORAGE_MMC */ #endif /* HAVE_HOTSWAP */ #ifdef USB_FIREWIRE_HANDLING case USB_REQUEST_REBOOT: #ifdef HAVE_USB_POWER if (usb_reboot_button()) #endif try_reboot(); break; #endif /* USB_FIREWIRE_HANDLING */ #if defined(HAVE_USB_CHARGING_ENABLE) && defined(HAVE_USBSTACK) case USB_CHARGER_UPDATE: usb_charging_maxcurrent_change(usb_charging_maxcurrent()); break; #endif } } }
int main(void) { if (PM->RCAUSE.reg & (PM_RCAUSE_POR | PM_RCAUSE_BOD12 | PM_RCAUSE_BOD33)) { // On powerup, force a clean reset of the MT7620 pin_low(PIN_SOC_RST); pin_out(PIN_SOC_RST); // turn off 3.3V to SoC pin_low(PIN_SOC_PWR); pin_out(PIN_SOC_PWR); // pull 1.8V low pin_low(PIN_18_V); pin_out(PIN_18_V); clock_init_crystal(GCLK_SYSTEM, GCLK_32K); timer_clock_enable(TC_BOOT); // hold everything low boot_delay_ms(50); // power off for 50ms pin_high(PIN_SOC_PWR); boot_delay_ms(2); // 2ms until 1.8 rail comes on pin_high(PIN_18_V); boot_delay_ms(50); // 50ms before soc rst comes on } else { clock_init_crystal(GCLK_SYSTEM, GCLK_32K); } pin_mux(PIN_USB_DM); pin_mux(PIN_USB_DP); usb_init(); usb_attach(); NVIC_SetPriority(USB_IRQn, 0xff); pin_high(PIN_LED); pin_out(PIN_LED); pin_in(PIN_SOC_RST); pin_high(PIN_SOC_PWR); pin_out(PIN_SOC_PWR); pin_low(PORT_A.power); pin_out(PORT_A.power); pin_low(PORT_B.power); pin_out(PORT_B.power); pin_pull_up(PIN_BRIDGE_CS); pin_pull_up(PIN_FLASH_CS); pin_pull_up(PIN_SERIAL_TX); pin_pull_up(PIN_SERIAL_RX); dma_init(); NVIC_EnableIRQ(DMAC_IRQn); NVIC_SetPriority(DMAC_IRQn, 0xff); eic_init(); NVIC_EnableIRQ(EIC_IRQn); NVIC_SetPriority(EIC_IRQn, 0xff); evsys_init(); NVIC_EnableIRQ(EVSYS_IRQn); NVIC_SetPriority(EVSYS_IRQn, 0); adc_init(GCLK_SYSTEM, ADC_REFCTRL_REFSEL_INTVCC1); dac_init(GCLK_32K); bridge_init(); port_init(&port_a, 1, &PORT_A, GCLK_PORT_A, TCC_PORT_A, DMA_PORT_A_TX, DMA_PORT_A_RX); port_init(&port_b, 2, &PORT_B, GCLK_PORT_B, TCC_PORT_B, DMA_PORT_B_TX, DMA_PORT_B_RX); __enable_irq(); SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk; init_systick(); while (1) { __WFI(); } }