/** * Jump to what we hope is the init address of an image. * * This function does not return. * * @param init_addr Init address of target image */ static void jump_to_image(uintptr_t init_addr) { void (*resetvec)(void) = (void(*)(void))init_addr; /* * Jumping to any image asserts the signal to the Silego chip that that * EC is not in read-only firmware. (This is not technically true if * jumping from RO -> RO, but that's not a meaningful use case...). * * Pulse the signal long enough to set the latch in the Silego, then * drop it again so we don't leak power through the pulldown in the * Silego. */ gpio_set_level(GPIO_ENTERING_RW, 1); usleep(MSEC); gpio_set_level(GPIO_ENTERING_RW, 0); #ifdef CONFIG_USB_POWER_DELIVERY /* * Notify USB PD module that we are about to sysjump and give it time * to do what it needs. */ pd_prepare_sysjump(); usleep(5*MSEC); #endif /* Flush UART output unless the UART hasn't been initialized yet */ if (uart_init_done()) uart_flush_output(); /* Disable interrupts before jump */ interrupt_disable(); #ifdef CONFIG_DMA /* Disable all DMA channels to avoid memory corruption */ dma_disable_all(); #endif /* CONFIG_DMA */ /* Fill in preserved data between jumps */ jdata->reserved0 = 0; jdata->magic = JUMP_DATA_MAGIC; jdata->version = JUMP_DATA_VERSION; jdata->reset_flags = reset_flags; jdata->jump_tag_total = 0; /* Reset tags */ jdata->struct_size = sizeof(struct jump_data); /* Call other hooks; these may add tags */ hook_notify(HOOK_SYSJUMP); /* Jump to the reset vector */ resetvec(); }
/** * Jump to what we hope is the init address of an image. * * This function does not return. * * @param init_addr Init address of target image */ static void jump_to_image(uintptr_t init_addr) { void (*resetvec)(void) = (void(*)(void))init_addr; /* * Jumping to any image asserts the signal to the Silego chip that that * EC is not in read-only firmware. (This is not technically true if * jumping from RO -> RO, but that's not a meaningful use case...). * * Pulse the signal long enough to set the latch in the Silego, then * drop it again so we don't leak power through the pulldown in the * Silego. */ gpio_set_level(GPIO_ENTERING_RW, 1); usleep(MSEC); gpio_set_level(GPIO_ENTERING_RW, 0); #ifdef CONFIG_USB_POWER_DELIVERY /* * On sysjump, we are most definitely going to drop pings (if any) * and lose all of our PD state. Instead of trying to remember all * the states and deal with on-going transmission, let's send soft * reset here so that the communication starts over without dropping * power. */ pd_soft_reset(); usleep(5*MSEC); #endif /* Flush UART output unless the UART hasn't been initialized yet */ if (uart_init_done()) uart_flush_output(); /* Disable interrupts before jump */ interrupt_disable(); /* Fill in preserved data between jumps */ jdata->reserved0 = 0; jdata->magic = JUMP_DATA_MAGIC; jdata->version = JUMP_DATA_VERSION; jdata->reset_flags = reset_flags; jdata->jump_tag_total = 0; /* Reset tags */ jdata->struct_size = sizeof(struct jump_data); /* Call other hooks; these may add tags */ hook_notify(HOOK_SYSJUMP); /* Jump to the reset vector */ resetvec(); }
/** * Jump to what we hope is the init address of an image. * * This function does not return. * * @param init_addr Init address of target image */ static void jump_to_image(uintptr_t init_addr) { void (*resetvec)(void) = (void(*)(void))init_addr; /* * Jumping to any image asserts the signal to the Silego chip that that * EC is not in read-only firmware. (This is not technically true if * jumping from RO -> RO, but that's not a meaningful use case...). * * Pulse the signal long enough to set the latch in the Silego, then * drop it again so we don't leak power through the pulldown in the * Silego. */ gpio_set_level(GPIO_ENTERING_RW, 1); usleep(MSEC); gpio_set_level(GPIO_ENTERING_RW, 0); /* Flush UART output unless the UART hasn't been initialized yet */ if (uart_init_done()) uart_flush_output(); /* Disable interrupts before jump */ interrupt_disable(); /* Fill in preserved data between jumps */ jdata->reserved0 = 0; jdata->magic = JUMP_DATA_MAGIC; jdata->version = JUMP_DATA_VERSION; jdata->reset_flags = reset_flags; jdata->jump_tag_total = 0; /* Reset tags */ jdata->struct_size = sizeof(struct jump_data); /* Call other hooks; these may add tags */ hook_notify(HOOK_SYSJUMP); /* Jump to the reset vector */ resetvec(); }
void uart_tx_start(void) { if (!uart_init_done()) return; /* If interrupt is already enabled, nothing to do */ if (GR_UART_ICTRL(0) & GC_UART_ICTRL_TX_MASK) return; /* Do not allow deep sleep while transmit in progress */ disable_sleep(SLEEP_MASK_UART); /* * Re-enable the transmit interrupt, then forcibly trigger the * interrupt. This works around a hardware problem with the * UART where the FIFO only triggers the interrupt when its * threshold is _crossed_, not just met. */ /* TODO(crosbug.com/p/33819): Do we need this hack here? Find out. */ REG_WRITE_MLV(GR_UART_ICTRL(0), GC_UART_ICTRL_TX_MASK, GC_UART_ICTRL_TX_LSB, 1); task_trigger_irq(GC_IRQNUM_UART0_TXINT); }