static void board_handle_reboot(void) { int flags; if (system_jumped_to_this_image()) return; if (system_get_board_version() < BOARD_MIN_ID_LOD_EN) return; /* Interrogate current reset flags from previous reboot. */ flags = system_get_reset_flags(); if (!(flags & PMIC_RESET_FLAGS)) return; /* Preserve AP off request. */ if (flags & RESET_FLAG_AP_OFF) chip_save_reset_flags(RESET_FLAG_AP_OFF); ccprintf("Restarting system with PMIC.\n"); /* Flush console */ cflush(); /* Bring down all rails but RTC rail (including EC power). */ gpio_set_flags(GPIO_BATLOW_L_PMIC_LDO_EN, GPIO_OUT_HIGH); while (1) ; /* wait here */ }
/* Called by APL power state machine when transitioning from G3 to S5 */ static void chipset_pre_init(void) { /* * No need to re-init PMIC since settings are sticky across sysjump. * However, be sure to check that PMIC is already enabled. If it is * then there's no need to re-sequence the PMIC. */ if (system_jumped_to_this_image() && gpio_get_level(GPIO_PMIC_EN)) return; /* Enable PP5000 before PP3300 due to NFC: chrome-os-partner:50807 */ gpio_set_level(GPIO_EN_PP5000, 1); while (!gpio_get_level(GPIO_PP5000_PG)) ; /* * To prevent SLP glitches, PMIC_EN (V5A_EN) should be enabled * at the same time as PP3300 (chrome-os-partner:51323). */ /* Enable 3.3V rail */ gpio_set_level(GPIO_EN_PP3300, 1); while (!gpio_get_level(GPIO_PP3300_PG)) ; /* Enable PMIC */ gpio_set_level(GPIO_PMIC_EN, 1); }
static void board_pmic_init(void) { /* No need to re-init PMIC since settings are sticky across sysjump */ if (system_jumped_to_this_image()) return; /* Set CSDECAYEN / VCCIO decays to 0V at assertion of SLP_S0# */ i2c_write8(I2C_PORT_PMIC, I2C_ADDR_BD99992, 0x30, 0x4a); /* * Set V100ACNT / V1.00A Control Register: * Nominal output = 1.0V. */ i2c_write8(I2C_PORT_PMIC, I2C_ADDR_BD99992, 0x37, 0x1a); /* * Set V085ACNT / V0.85A Control Register: * Lower power mode = 0.7V. * Nominal output = 1.0V. */ i2c_write8(I2C_PORT_PMIC, I2C_ADDR_BD99992, 0x38, 0x7a); /* VRMODECTRL - enable low-power mode for VCCIO and V0.85A */ i2c_write8(I2C_PORT_PMIC, I2C_ADDR_BD99992, 0x3b, 0x18); }
enum power_state power_chipset_init(void) { /* * If we're switching between images without rebooting, see if the x86 * is already powered on; if so, leave it there instead of cycling * through G3. */ if (system_jumped_to_this_image()) { if ((power_get_signals() & IN_ALL_S0) == IN_ALL_S0) { /* Disable idle task deep sleep when in S0. */ disable_sleep(SLEEP_MASK_AP_RUN); CPRINTS("already in S0"); return POWER_S0; } else { /* Force all signals to their G3 states */ CPRINTS("forcing G3"); gpio_set_level(GPIO_PCH_PWROK, 0); gpio_set_level(GPIO_SYS_PWROK, 0); gpio_set_level(GPIO_PP1050_EN, 0); gpio_set_level(GPIO_PP1200_EN, 0); gpio_set_level(GPIO_PP1800_EN, 0); gpio_set_level(GPIO_PP3300_DSW_GATED_EN, 0); gpio_set_level(GPIO_PP5000_USB_EN, 0); gpio_set_level(GPIO_PP5000_EN, 0); gpio_set_level(GPIO_PCH_DPWROK, 0); gpio_set_level(GPIO_PP3300_DSW_EN, 0); wireless_set_state(WIRELESS_OFF); } } return POWER_G3; }
/** * Set initial power button state. */ static void set_initial_pwrbtn_state(void) { uint32_t reset_flags = system_get_reset_flags(); if (system_jumped_to_this_image() && chipset_in_state(CHIPSET_STATE_ON)) { /* * Jumped to this image while the chipset was already on, so * simply reflect the actual power button state. */ if (power_button_is_pressed()) { CPRINTS("PB init-jumped-held"); set_pwrbtn_to_pch(0); } else { CPRINTS("PB init-jumped"); } } else if ((reset_flags & RESET_FLAG_AP_OFF) || (keyboard_scan_get_boot_key() == BOOT_KEY_DOWN_ARROW)) { /* * Reset triggered by keyboard-controlled reset, and down-arrow * was held down. Or reset flags request AP off. * * Leave the main processor off. This is a fail-safe * combination for debugging failures booting the main * processor. * * Don't let the PCH see that the power button was pressed. * Otherwise, it might power on. */ CPRINTS("PB init-off"); power_button_pch_release(); } else { /* * All other EC reset conditions power on the main processor so * it can verify the EC. */ #ifdef CONFIG_BRINGUP CPRINTS("PB idle"); pwrbtn_state = PWRBTN_STATE_IDLE; #else CPRINTS("PB init-on"); pwrbtn_state = PWRBTN_STATE_INIT_ON; #endif } }
enum power_state power_chipset_init(void) { /* * If we're switching between images without rebooting, see if the x86 * is already powered on; if so, leave it there instead of cycling * through G3. */ if (system_jumped_to_this_image()) { if ((power_get_signals() & IN_ALL_S0) == IN_ALL_S0) { /* Disable idle task deep sleep when in S0. */ disable_sleep(SLEEP_MASK_AP_RUN); CPRINTS("already in S0"); return POWER_S0; } else { /* Force all signals to their G3 states */ chipset_force_g3(); } } return POWER_G3; }
void board_tcpc_init(void) { int port, reg; /* Only reset TCPC if not sysjump */ if (!system_jumped_to_this_image()) board_reset_pd_mcu(); /* * TODO: Remove when Reef is updated with PS8751 A3. * * Force PS8751 A2 to wake from low power mode. * If PS8751 remains in low power mode after sysjump, * TCPM_INIT will fail due to not able to access PS8751. * * NOTE: PS8751 A3 will wake on any I2C access. */ i2c_read8(NPCX_I2C_PORT0_1, 0x10, 0xA0, ®); /* Enable TCPC0 interrupt */ gpio_enable_interrupt(GPIO_USB_C0_PD_INT_ODL); /* Enable TCPC1 interrupt */ gpio_enable_interrupt(GPIO_USB_C1_PD_INT_ODL); #ifdef CONFIG_USB_PD_TCPC_LOW_POWER /* Enable CABLE_DET interrupt for ANX3429 wake from standby */ gpio_enable_interrupt(GPIO_USB_C0_CABLE_DET); #endif /* * Initialize HPD to low; after sysjump SOC needs to see * HPD pulse to enable video path */ for (port = 0; port < CONFIG_USB_PD_PORT_COUNT; port++) { const struct usb_mux *mux = &usb_muxes[port]; mux->hpd_update(port, 0, 0); } }
static int command_sysinfo(int argc, char **argv) { ccprintf("Reset flags: 0x%08x (", system_get_reset_flags()); system_print_reset_flags(); ccprintf(")\n"); ccprintf("Copy: %s\n", system_get_image_copy_string()); ccprintf("Jumped: %s\n", system_jumped_to_this_image() ? "yes" : "no"); ccputs("Flags: "); if (system_is_locked()) { ccputs(" locked"); if (force_locked) ccputs(" (forced)"); if (disable_jump) ccputs(" jump-disabled"); } else ccputs(" unlocked"); ccputs("\n"); if (reboot_at_shutdown) ccprintf("Reboot at shutdown: %d\n", reboot_at_shutdown); return EC_SUCCESS; }
test_mockable int main(void) { /* * Pre-initialization (pre-verified boot) stage. Initialization at * this level should do as little as possible, because verified boot * may need to jump to another image, which will repeat this * initialization. In particular, modules should NOT enable * interrupts. */ #ifdef CONFIG_BOARD_PRE_INIT board_config_pre_init(); #endif #ifdef CONFIG_MPU mpu_pre_init(); #endif /* Configure the pin multiplexers and GPIOs */ jtag_pre_init(); gpio_pre_init(); #ifdef CONFIG_BOARD_POST_GPIO_INIT board_config_post_gpio_init(); #endif /* * Initialize interrupts, but don't enable any of them. Note that * task scheduling is not enabled until task_start() below. */ task_pre_init(); /* * Initialize the system module. This enables the hibernate clock * source we need to calibrate the internal oscillator. */ system_pre_init(); system_common_pre_init(); #ifdef CONFIG_FLASH /* * Initialize flash and apply write protect if necessary. Requires * the reset flags calculated by system initialization. */ flash_pre_init(); #endif /* Set the CPU clocks / PLLs. System is now running at full speed. */ clock_init(); /* * Initialize timer. Everything after this can be benchmarked. * get_time() and udelay() may now be used. usleep() requires task * scheduling, so cannot be used yet. Note that interrupts declared * via DECLARE_IRQ() call timer routines when profiling is enabled, so * timer init() must be before uart_init(). */ timer_init(); /* Main initialization stage. Modules may enable interrupts here. */ cpu_init(); #ifdef CONFIG_DMA /* Initialize DMA. Must be before UART. */ dma_init(); #endif /* Initialize UART. Console output functions may now be used. */ uart_init(); if (system_jumped_to_this_image()) { CPRINTS("UART initialized after sysjump"); } else { CPUTS("\n\n--- UART initialized after reboot ---\n"); CPUTS("[Reset cause: "); system_print_reset_flags(); CPUTS("]\n"); } CPRINTF("[Image: %s, %s]\n", system_get_image_copy_string(), system_get_build_info()); #ifdef CONFIG_WATCHDOG /* * Intialize watchdog timer. All lengthy operations between now and * task_start() must periodically call watchdog_reload() to avoid * triggering a watchdog reboot. (This pretty much applies only to * verified boot, because all *other* lengthy operations should be done * by tasks.) */ watchdog_init(); #endif /* * Verified boot needs to read the initial keyboard state and EEPROM * contents. EEPROM must be up first, so keyboard_scan can toggle * debugging settings via keys held at boot. */ #ifdef CONFIG_EEPROM eeprom_init(); #endif #ifdef CONFIG_EOPTION eoption_init(); #endif #ifdef HAS_TASK_KEYSCAN keyboard_scan_init(); #endif /* Initialize the hook library. This calls HOOK_INIT hooks. */ hook_init(); /* * Print the init time. Not completely accurate because it can't take * into account the time before timer_init(), but it'll at least catch * the majority of the time. */ CPRINTS("Inits done"); /* Launch task scheduling (never returns) */ return task_start(); }
static void board_pmic_init(void) { int ret; int data; int error_count = 0; /* No need to re-init PMIC since settings are sticky across sysjump */ if (system_jumped_to_this_image()) return; /* Read vendor ID */ while (1) { ret = I2C_PMIC_READ(TPS650830_REG_VENDORID, &data); if (!ret && data == TPS650830_VENDOR_ID) { break; } else if (error_count > 5) goto pmic_error; error_count++; } /* * VCCIOCNT register setting * [6] : CSDECAYEN * otherbits: default */ ret = I2C_PMIC_WRITE(TPS650830_REG_VCCIOCNT, 0x4A); if (ret) goto pmic_error; /* * VRMODECTRL: * [4] : VCCIOLPM clear * otherbits: default */ ret = I2C_PMIC_WRITE(TPS650830_REG_VRMODECTRL, 0x2F); if (ret) goto pmic_error; /* * PGMASK1 : Exclude VCCIO from Power Good Tree * [7] : MVCCIOPG clear * otherbits: default */ ret = I2C_PMIC_WRITE(TPS650830_REG_PGMASK1, 0x80); if (ret) goto pmic_error; /* * PWFAULT_MASK1 Register settings * [7] : 1b V4 Power Fault Masked * [4] : 1b V7 Power Fault Masked * [2] : 1b V9 Power Fault Masked * [0] : 1b V13 Power Fault Masked */ ret = I2C_PMIC_WRITE(TPS650830_REG_PWFAULT_MASK1, 0x95); if (ret) goto pmic_error; /* * Discharge control 4 register configuration * [7:6] : 00b Reserved * [5:4] : 01b V3.3S discharge resistance (V6S), 100 Ohm * [3:2] : 01b V18S discharge resistance (V8S), 100 Ohm * [1:0] : 01b V100S discharge resistance (V11S), 100 Ohm */ ret = I2C_PMIC_WRITE(TPS650830_REG_DISCHCNT4, 0x15); if (ret) goto pmic_error; /* * Discharge control 3 register configuration * [7:6] : 01b V1.8U_2.5U discharge resistance (V9), 100 Ohm * [5:4] : 01b V1.2U discharge resistance (V10), 100 Ohm * [3:2] : 01b V100A discharge resistance (V11), 100 Ohm * [1:0] : 01b V085A discharge resistance (V12), 100 Ohm */ ret = I2C_PMIC_WRITE(TPS650830_REG_DISCHCNT3, 0x55); if (ret) goto pmic_error; /* * Discharge control 2 register configuration * [7:6] : 01b V5ADS3 discharge resistance (V5), 100 Ohm * [5:4] : 01b V33A_DSW discharge resistance (V6), 100 Ohm * [3:2] : 01b V33PCH discharge resistance (V7), 100 Ohm * [1:0] : 01b V18A discharge resistance (V8), 100 Ohm */ ret = I2C_PMIC_WRITE(TPS650830_REG_DISCHCNT2, 0x55); if (ret) goto pmic_error; /* * Discharge control 1 register configuration * [7:2] : 00b Reserved * [1:0] : 01b VCCIO discharge resistance (V4), 100 Ohm */ ret = I2C_PMIC_WRITE(TPS650830_REG_DISCHCNT1, 0x01); if (ret) goto pmic_error; /* * Increase Voltage * [7:0] : 0x2a default * [5:4] : 10b default * [5:4] : 01b 5.1V (0x1a) */ ret = I2C_PMIC_WRITE(TPS650830_REG_V5ADS3CNT, 0x1a); if (ret) goto pmic_error; CPRINTS("PMIC initialization done"); return; pmic_error: CPRINTS("PMIC initialization failed"); }
test_mockable __keep int main(void) { #ifdef CONFIG_REPLACE_LOADER_WITH_BSS_SLOW /* * Now that we have started execution, we no longer need the loader. * Instead, variables placed in the .bss.slow section will use this * space. Therefore, clear out this region now. */ memset((void *)(CONFIG_PROGRAM_MEMORY_BASE + CONFIG_LOADER_MEM_OFF), 0, CONFIG_LOADER_SIZE); #endif /* defined(CONFIG_REPLACE_LOADER_WITH_BSS_SLOW) */ /* * Pre-initialization (pre-verified boot) stage. Initialization at * this level should do as little as possible, because verified boot * may need to jump to another image, which will repeat this * initialization. In particular, modules should NOT enable * interrupts. */ #ifdef CONFIG_BOARD_PRE_INIT board_config_pre_init(); #endif #ifdef CONFIG_MPU mpu_pre_init(); #endif /* Configure the pin multiplexers and GPIOs */ jtag_pre_init(); gpio_pre_init(); #ifdef CONFIG_BOARD_POST_GPIO_INIT board_config_post_gpio_init(); #endif /* * Initialize interrupts, but don't enable any of them. Note that * task scheduling is not enabled until task_start() below. */ task_pre_init(); /* * Initialize the system module. This enables the hibernate clock * source we need to calibrate the internal oscillator. */ system_pre_init(); system_common_pre_init(); #ifdef CONFIG_FLASH /* * Initialize flash and apply write protect if necessary. Requires * the reset flags calculated by system initialization. */ flash_pre_init(); #endif #if defined(CONFIG_CASE_CLOSED_DEBUG) /* * If the device is locked we assert PD_NO_DEBUG, preventing the EC * from interfering with the AP's access to the SPI flash. * The PD_NO_DEBUG signal is latched in hardware, so changing this * GPIO later has no effect. */ gpio_set_level(GPIO_PD_DISABLE_DEBUG, system_is_locked()); #endif /* Set the CPU clocks / PLLs. System is now running at full speed. */ clock_init(); /* * Initialize timer. Everything after this can be benchmarked. * get_time() and udelay() may now be used. usleep() requires task * scheduling, so cannot be used yet. Note that interrupts declared * via DECLARE_IRQ() call timer routines when profiling is enabled, so * timer init() must be before uart_init(). */ timer_init(); /* Main initialization stage. Modules may enable interrupts here. */ cpu_init(); #ifdef CONFIG_DMA /* Initialize DMA. Must be before UART. */ dma_init(); #endif /* Initialize UART. Console output functions may now be used. */ uart_init(); if (system_jumped_to_this_image()) { CPRINTS("UART initialized after sysjump"); } else { CPUTS("\n\n--- UART initialized after reboot ---\n"); CPUTS("[Reset cause: "); system_print_reset_flags(); CPUTS("]\n"); } CPRINTF("[Image: %s, %s]\n", system_get_image_copy_string(), system_get_build_info()); #ifdef CONFIG_BRINGUP ccprintf("\n\nWARNING: BRINGUP BUILD\n\n\n"); #endif #ifdef CONFIG_WATCHDOG /* * Intialize watchdog timer. All lengthy operations between now and * task_start() must periodically call watchdog_reload() to avoid * triggering a watchdog reboot. (This pretty much applies only to * verified boot, because all *other* lengthy operations should be done * by tasks.) */ watchdog_init(); #endif /* * Verified boot needs to read the initial keyboard state and EEPROM * contents. EEPROM must be up first, so keyboard_scan can toggle * debugging settings via keys held at boot. */ #ifdef CONFIG_EEPROM eeprom_init(); #endif #ifdef HAS_TASK_KEYSCAN keyboard_scan_init(); #endif #ifdef CONFIG_RWSIG /* * Check the RW firmware signature * and eventually jump to it if it is good. */ check_rw_signature(); #endif /* * Print the init time. Not completely accurate because it can't take * into account the time before timer_init(), but it'll at least catch * the majority of the time. */ CPRINTS("Inits done"); /* Launch task scheduling (never returns) */ return task_start(); }