/* Initialize board. */ static void board_init(void) { /* Enable PD MCU interrupt */ gpio_enable_interrupt(GPIO_PD_MCU_INT); /* Enable VBUS interrupt */ gpio_enable_interrupt(GPIO_USB_C0_VBUS_WAKE_L); gpio_enable_interrupt(GPIO_USB_C1_VBUS_WAKE_L); /* Enable pericom BC1.2 interrupts */ gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L); gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L); /* Provide AC status to the PCH */ gpio_set_level(GPIO_PCH_ACOK, extpower_is_present()); /* Proto board workarounds */ if (system_get_board_version() == 0) { /* Disable interrupt for SLP_S0 */ gpio_set_flags(GPIO_PCH_SLP_S0_L, GPIO_INPUT | GPIO_PULL_DOWN); /* Add internal pullup on PLATFORM_EC_PROCHOT */ gpio_set_flags(GPIO_PLATFORM_EC_PROCHOT, GPIO_INPUT | GPIO_PULL_UP); } }
int board_get_version(void) { static int version = BOARD_VERSION_UNKNOWN; int mv, i; if (version != BOARD_VERSION_UNKNOWN) return version; /* FIXME(dhendrix): enable ADC */ gpio_set_flags(GPIO_EC_BRD_ID_EN_ODL, GPIO_ODR_HIGH); gpio_set_level(GPIO_EC_BRD_ID_EN_ODL, 0); /* Wait to allow cap charge */ msleep(1); mv = adc_read_channel(ADC_BOARD_ID); /* FIXME(dhendrix): disable ADC */ gpio_set_level(GPIO_EC_BRD_ID_EN_ODL, 1); gpio_set_flags(GPIO_EC_BRD_ID_EN_ODL, GPIO_INPUT); if (mv == ADC_READ_ERROR) { version = BOARD_VERSION_UNKNOWN; return version; } for (i = 0; i < BOARD_VERSION_COUNT; i++) { if (mv < reef_board_versions[i].thresh_mv) { version = reef_board_versions[i].version; break; } } CPRINTS("Board version: %d\n", version); return version; }
static int cmd_btn_press(int argc, char **argv) { enum gpio_signal gpio; char *e; int v; if (argc < 2) return EC_ERROR_PARAM_COUNT; if (!strcasecmp(argv[1], "volup")) gpio = GPIO_BTN_VOLU_L; else if (!strcasecmp(argv[1], "voldown")) gpio = GPIO_BTN_VOLD_L; else return EC_ERROR_PARAM1; if (argc < 3) { /* Just reading */ ccprintf("Button %s pressed = %d\n", argv[1], !gpio_get_level(gpio)); return EC_SUCCESS; } v = strtoi(argv[2], &e, 0); if (*e) return EC_ERROR_PARAM2; if (v) gpio_set_flags(gpio, GPIO_OUT_LOW); else gpio_set_flags(gpio, GPIO_INPUT | GPIO_PULL_UP); return EC_SUCCESS; }
/** * Power off the AP */ static void power_off(void) { unsigned int power_off_timeout = 100; /* ms */ /* Call hooks before we drop power rails */ hook_notify(HOOK_CHIPSET_SHUTDOWN); /* switch off all rails */ chipset_turn_off_power_rails(); /* Change SUSPEND_L and EC_INT pin to high-Z to reduce power draw. */ gpio_set_flags(GPIO_SUSPEND_L, GPIO_INPUT); gpio_set_flags(GPIO_EC_INT_L, GPIO_INPUT); /* Wait till we actually turn off to not mess up the state machine. */ while (power_get_signals() & IN_POWER_GOOD) { msleep(1); power_off_timeout--; ASSERT(power_off_timeout); } lid_opened = 0; enable_sleep(SLEEP_MASK_AP_RUN); powerled_set_state(POWERLED_STATE_OFF); CPRINTS("power shutdown complete"); }
/** * Enable and disable SPI for case closed debugging. This forces the AP into * reset while SPI is enabled, thus preventing contention on the SPI interface. */ void usb_spi_board_enable(struct usb_spi_config const *config) { /* Place AP into reset */ gpio_set_level(GPIO_PMIC_WARM_RESET_L, 0); /* Configure SPI GPIOs */ gpio_config_module(MODULE_SPI_FLASH, 1); gpio_set_flags(SPI_FLASH_DEVICE->gpio_cs, GPIO_OUT_HIGH); /* Set all four SPI pins to high speed */ /* pins B10/B14/B15 and B9 */ STM32_GPIO_OSPEEDR(GPIO_B) |= 0xf03c0000; /* Enable clocks to SPI2 module */ STM32_RCC_APB1ENR |= STM32_RCC_PB1_SPI2; /* Reset SPI2 */ STM32_RCC_APB1RSTR |= STM32_RCC_PB1_SPI2; STM32_RCC_APB1RSTR &= ~STM32_RCC_PB1_SPI2; /* Enable SPI LDO to power the flash chip */ gpio_set_level(GPIO_VDDSPI_EN, 1); spi_enable(CONFIG_SPI_FLASH_PORT, 1); }
void board_hibernate_late(void) { int i; const uint32_t hibernate_pins[][2] = { /* Turn off LEDs in hibernate */ {GPIO_BAT_LED_BLUE, GPIO_INPUT | GPIO_PULL_UP}, {GPIO_BAT_LED_AMBER, GPIO_INPUT | GPIO_PULL_UP}, {GPIO_LID_OPEN, GPIO_INT_RISING | GPIO_PULL_DOWN}, /* * BD99956 handles charge input automatically. We'll disable * charge output in hibernate. Charger will assert ACOK_OD * when VBUS or VCC are plugged in. */ {GPIO_USB_C0_5V_EN, GPIO_INPUT | GPIO_PULL_DOWN}, {GPIO_USB_C1_5V_EN, GPIO_INPUT | GPIO_PULL_DOWN}, }; /* Change GPIOs' state in hibernate for better power consumption */ for (i = 0; i < ARRAY_SIZE(hibernate_pins); ++i) gpio_set_flags(hibernate_pins[i][0], hibernate_pins[i][1]); gpio_config_module(MODULE_KEYBOARD_SCAN, 0); /* * Calling gpio_config_module sets disabled alternate function pins to * GPIO_INPUT. But to prevent keypresses causing leakage currents * while hibernating we want to enable GPIO_PULL_UP as well. */ gpio_set_flags_by_mask(0x2, 0x03, GPIO_INPUT | GPIO_PULL_UP); gpio_set_flags_by_mask(0x1, 0xFF, GPIO_INPUT | GPIO_PULL_UP); gpio_set_flags_by_mask(0x0, 0xE0, GPIO_INPUT | GPIO_PULL_UP); }
enum cts_rc read_low_test(void) { gpio_set_flags(GPIO_OUTPUT_TEST, GPIO_ODR_LOW); gpio_set_level(GPIO_OUTPUT_TEST, 0); msleep(READ_WAIT_TIME_MS*2); return CTS_RC_SUCCESS; }
/** * Power off the AP */ static void power_off(void) { /* Call hooks before we drop power rails */ hook_notify(HOOK_CHIPSET_SHUTDOWN); /* switch off all rails */ chipset_turn_off_power_rails(); /* Change SUSPEND_L and EC_INT pin to high-Z to reduce power draw. */ gpio_set_flags(GPIO_SUSPEND_L, GPIO_INPUT); gpio_set_flags(GPIO_EC_INT, GPIO_INPUT); lid_opened = 0; enable_sleep(SLEEP_MASK_AP_RUN); powerled_set_state(POWERLED_STATE_OFF); CPRINTS("power shutdown complete"); }
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 */ }
static int command_gpio_set(int argc, char **argv) { #ifdef CONFIG_CMD_GPIO_EXTENDED int gpio; int flags = 0; int af = -1; char *e; if (argc < 3) return EC_ERROR_PARAM_COUNT; gpio = find_signal_by_name(argv[1]); if (gpio == GPIO_COUNT) return EC_ERROR_PARAM1; if (strcasecmp(argv[2], "IN") == 0) flags = GPIO_INPUT; else if (strcasecmp(argv[2], "1") == 0) flags = GPIO_OUT_HIGH; else if (strcasecmp(argv[2], "0") == 0) flags = GPIO_OUT_LOW; else if (strcasecmp(argv[2], "A") == 0) flags = GPIO_ANALOG; else if (strcasecmp(argv[2], "ALT") == 0) { if (argc >= 4) { af = strtoi(argv[3], &e, 0); if (*e || af < 0 || af > 5) return EC_ERROR_PARAM2; } flags = GPIO_ALTERNATE; } else return EC_ERROR_PARAM2; /* Update alt function if requested. */ if (af >= 0) { const struct gpio_info *g = gpio_list + gpio; gpio_set_alternate_function(g->port, g->mask, af); } /* Update GPIO flags. */ gpio_set_flags(gpio, flags); #else char *e; int v; if (argc < 3) return EC_ERROR_PARAM_COUNT; v = strtoi(argv[2], &e, 0); if (*e) return EC_ERROR_PARAM2; if (set(argv[1], v) != EC_SUCCESS) return EC_ERROR_PARAM1; #endif return EC_SUCCESS; }
static enum cts_rc timer_calibration_test(void) { gpio_set_flags(GPIO_OUTPUT_TEST, GPIO_ODR_HIGH); sync(); usleep(SECOND); gpio_set_level(GPIO_OUTPUT_TEST, 0); return CTS_RC_SUCCESS; }
static void spi_chipset_shutdown(void) { enabled = 0; state = SPI_STATE_DISABLED; /* Disable pullup and interrupts on NSS */ gpio_set_flags(GPIO_SPI1_NSS, GPIO_INPUT); /* Set SPI pins to inputs so we don't leak power when AP is off */ gpio_config_module(MODULE_SPI, 0); }
enum cts_rc set_low_test(void) { int level; gpio_set_flags(GPIO_INPUT_TEST, GPIO_INPUT | GPIO_PULL_UP); msleep(READ_WAIT_TIME_MS); level = gpio_get_level(GPIO_INPUT_TEST); if (!level) return CTS_RC_SUCCESS; else return CTS_RC_FAILURE; }
/** * Set SPI enabled. * * @spi_port port to act on. Only one port supported, one gpio. * @param enable enabled flag * @return success */ int spi_enable(int port, int enable) { int i; enum gpio_signal gpio; if (enable) { /* Enabling spi module for gpio configuration */ gpio_config_module(MODULE_SPI, 1); /* GPIO No SPI Select */ CLEAR_BIT(NPCX_DEVALT(0), NPCX_DEVALT0_GPIO_NO_SPIP); for (i = 0; i < spi_devices_used; i++) { if (spi_devices[i].port != port) continue; gpio = spi_devices[i].gpio_cs; /* Make sure CS# is a GPIO output mode. */ gpio_set_flags(gpio, GPIO_OUTPUT); /* Make sure CS# is deselected */ gpio_set_level(gpio, 1); } /* Enabling spi module */ SET_BIT(NPCX_SPI_CTL1, NPCX_SPI_CTL1_SPIEN); } else { /* Disabling spi module */ CLEAR_BIT(NPCX_SPI_CTL1, NPCX_SPI_CTL1_SPIEN); for (i = 0; i < spi_devices_used; i++) { if (spi_devices[i].port != port) continue; gpio = spi_devices[i].gpio_cs; /* Make sure CS# is deselected */ gpio_set_level(gpio, 1); gpio_set_flags(gpio, GPIO_ODR_HIGH); } /* Disabling spi module for gpio configuration */ gpio_config_module(MODULE_SPI, 0); /* GPIO No SPI Select */ SET_BIT(NPCX_DEVALT(0), NPCX_DEVALT0_GPIO_NO_SPIP); } return EC_SUCCESS; }
int board_get_version(void) { static int ver; if (!ver) { /* * read the board EC ID on the tristate strappings * using ternary encoding: 0 = 0, 1 = 1, Hi-Z = 2 */ uint8_t id0 = 0, id1 = 0; gpio_set_flags(GPIO_BOARD_ID0, GPIO_PULL_DOWN | GPIO_INPUT); gpio_set_flags(GPIO_BOARD_ID1, GPIO_PULL_DOWN | GPIO_INPUT); usleep(100); id0 = gpio_get_level(GPIO_BOARD_ID0); id1 = gpio_get_level(GPIO_BOARD_ID1); gpio_set_flags(GPIO_BOARD_ID0, GPIO_PULL_UP | GPIO_INPUT); gpio_set_flags(GPIO_BOARD_ID1, GPIO_PULL_UP | GPIO_INPUT); usleep(100); id0 = gpio_get_level(GPIO_BOARD_ID0) && !id0 ? 2 : id0; id1 = gpio_get_level(GPIO_BOARD_ID1) && !id1 ? 2 : id1; gpio_set_flags(GPIO_BOARD_ID0, GPIO_INPUT); gpio_set_flags(GPIO_BOARD_ID1, GPIO_INPUT); ver = id1 * 3 + id0; CPRINTS("Board ID = %d", ver); } return ver; }
/** * Flush an SPI transaction and receive data from slave. * * @param spi_device device to talk to * @param txdata transfer data * @param txlen transfer length * @param rxdata receive data * @param rxlen receive length * @return success * @notes set master transaction mode in npcx chip */ int spi_transaction(const struct spi_device_t *spi_device, const uint8_t *txdata, int txlen, uint8_t *rxdata, int rxlen) { int i = 0; enum gpio_signal gpio = spi_device->gpio_cs; /* Make sure CS# is a GPIO output mode. */ gpio_set_flags(gpio, GPIO_OUTPUT); /* Make sure CS# is deselected */ gpio_set_level(gpio, 1); /* Cleaning junk data in the buffer */ clear_databuf(); /* Assert CS# to start transaction */ gpio_set_level(gpio, 0); CPRINTS("NPCX_SPI_DATA=%x", NPCX_SPI_DATA); CPRINTS("NPCX_SPI_CTL1=%x", NPCX_SPI_CTL1); CPRINTS("NPCX_SPI_STAT=%x", NPCX_SPI_STAT); /* Writing the data */ for (i = 0; i < txlen; ++i) { /* Making sure we can write */ while (IS_BIT_SET(NPCX_SPI_STAT, NPCX_SPI_STAT_BSY)) ; /* Write the data */ NPCX_SPI_DATA = txdata[i]; CPRINTS("txdata[i]=%x", txdata[i]); /* Waiting till reading is finished */ while (!IS_BIT_SET(NPCX_SPI_STAT, NPCX_SPI_STAT_RBF)) ; /* Reading the (dummy) data */ clear_databuf(); } CPRINTS("write end"); /* Reading the data */ for (i = 0; i < rxlen; ++i) { /* Making sure we can write */ while (IS_BIT_SET(NPCX_SPI_STAT, NPCX_SPI_STAT_BSY)) ; /* Write the (dummy) data */ NPCX_SPI_DATA = 0; /* Wait till reading is finished */ while (!IS_BIT_SET(NPCX_SPI_STAT, NPCX_SPI_STAT_RBF)) ; /* Reading the data */ rxdata[i] = (uint8_t)NPCX_SPI_DATA; CPRINTS("rxdata[i]=%x", rxdata[i]); } /* Deassert CS# (high) to end transaction */ gpio_set_level(gpio, 1); return EC_SUCCESS; }
static void spi_chipset_startup(void) { /* Enable pullup and interrupts on NSS */ gpio_set_flags(GPIO_SPI1_NSS, GPIO_INT_BOTH | GPIO_PULL_UP); /* Set SPI pins to alternate function */ gpio_config_module(MODULE_SPI, 1); /* Set up for next transaction */ setup_for_transaction(); enabled = 1; }
/* * This is for NOT having enough hibernate (more precisely, the stand-by mode) * wake-up source pin. STM32L100 supports 3 wake-up source pins: * * WKUP1 (PA0) -- used for ACOK_PMU * WKUP2 (PC13) -- used for LID_OPEN * WKUP3 (PE6) -- cannot be used due to IC package. * * However, we need the power button as a wake-up source as well and there is * no available pin for us (we don't want to move the ACOK_PMU pin). * * Fortunately, the STM32L is low-power enough so that we don't need the * super-low-power mode. So, we fake this hibernate mode and accept the * following wake-up source. * * RTC alarm (faked as well). * Power button * Lid open * AC detected * * The original issue is here: crosbug.com/p/25435. */ void __enter_hibernate(uint32_t seconds, uint32_t microseconds) { int i; fake_hibernate = 1; #ifdef CONFIG_POWER_COMMON /* * A quick hack to stop annoying messages from charger task. * * When the battery is under 3%, the power task would call * power_off() to shutdown AP. However, the power_off() would * notify the HOOK_CHIPSET_SHUTDOWN, where the last hook is * charge_shutdown() and it hibernates the power task (infinite * loop -- not real CPU hibernate mode). Unfortunately, the * charger task is still running. It keeps generating annoying * log message. * * Thus, the hack is to set the power state machine (before we * enter infinite loop) so that the charger task thinks the AP * is off and stops generating messages. */ power_set_state(POWER_G3); #endif /* * Change keyboard outputs to high-Z to reduce power draw. * We don't need corresponding code to change them back, * because fake hibernate is always exited with a reboot. * * A little hacky to do this here. */ for (i = GPIO_KB_OUT00; i < GPIO_KB_OUT00 + KEYBOARD_COLS; i++) gpio_set_flags(i, GPIO_INPUT); ccprints("fake hibernate. waits for power button/lid/RTC/AC"); cflush(); if (seconds || microseconds) { if (seconds) sleep(seconds); if (microseconds) usleep(microseconds); } else { while (1) task_wait_event(-1); } ccprints("fake RTC alarm fires. resets EC"); cflush(); system_reset(SYSTEM_RESET_HARD); }
static void board_vbus_update_source_current(int port) { enum gpio_signal gpio = port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN; int flags = (vbus_rp[port] == TYPEC_RP_1A5 && vbus_en[port]) ? (GPIO_INPUT | GPIO_PULL_UP) : (GPIO_OUTPUT | GPIO_PULL_UP); /* * Driving USB_Cx_5V_EN high, actually put a 16.5k resistance * (2x 33k in parallel) on the NX5P3290 load switch ILIM pin, * setting a minimum OCP current of 3186 mA. * Putting an internal pull-up on USB_Cx_5V_EN, effectively put a 33k * resistor on ILIM, setting a minimum OCP current of 1505 mA. */ gpio_set_level(gpio, vbus_en[port]); gpio_set_flags(gpio, flags); }
void usb_spi_board_disable(struct usb_spi_config const *config) { spi_enable(CONFIG_SPI_FLASH_PORT, 0); /* Disable SPI LDO */ gpio_set_level(GPIO_VDDSPI_EN, 0); /* Disable clocks to SPI2 module */ STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_SPI2; /* Release SPI GPIOs */ gpio_config_module(MODULE_SPI_FLASH, 0); gpio_set_flags(SPI_FLASH_DEVICE->gpio_cs, GPIO_INPUT); /* Release AP from reset */ gpio_set_level(GPIO_PMIC_WARM_RESET_L, 1); }
void cts_task(void) { enum cts_rc rc; int i; gpio_set_flags(GPIO_OUTPUT_TEST, GPIO_ODR_HIGH); for (i = 0; i < CTS_TEST_ID_COUNT; i++) { gpio_set_level(GPIO_OUTPUT_TEST, 1); gpio_set_level(GPIO_CTS_IRQ2, 1); sync(); rc = tests[i].run(); CPRINTF("\n%s %d\n", tests[i].name, rc); cflush(); } CPRINTS("Interrupt test suite finished"); cflush(); while (1) { watchdog_reload(); sleep(1); } }
void system_hibernate(uint32_t seconds, uint32_t microseconds) { int i; #ifdef CONFIG_HOSTCMD_PD /* Inform the PD MCU that we are going to hibernate. */ host_command_pd_request_hibernate(); /* Wait to ensure exchange with PD before hibernating. */ msleep(100); #endif cflush(); if (board_hibernate) board_hibernate(); /* Disable interrupts */ interrupt_disable(); for (i = 0; i <= 92; ++i) { task_disable_irq(i); task_clear_pending_irq(i); } for (i = 8; i <= 23; ++i) MEC1322_INT_DISABLE(i) = 0xffffffff; MEC1322_INT_BLK_DIS |= 0xffff00; /* Power down ADC VREF */ MEC1322_EC_ADC_VREF_PD |= 1; /* Assert nSIO_RESET */ MEC1322_PCR_PWR_RST_CTL |= 1; /* Disable UART */ MEC1322_UART_ACT &= ~0x1; MEC1322_LPC_ACT &= ~0x1; /* Disable JTAG */ MEC1322_EC_JTAG_EN &= ~1; /* Disable 32KHz clock */ MEC1322_VBAT_CE &= ~0x2; /* Stop watchdog */ MEC1322_WDG_CTL &= ~1; /* Stop timers */ MEC1322_TMR32_CTL(0) &= ~1; MEC1322_TMR32_CTL(1) &= ~1; MEC1322_TMR16_CTL(0) &= ~1; /* Power down ADC */ MEC1322_ADC_CTRL &= ~1; /* Disable blocks */ MEC1322_PCR_CHIP_SLP_EN |= 0x3; MEC1322_PCR_EC_SLP_EN |= MEC1322_PCR_EC_SLP_EN_SLEEP; MEC1322_PCR_HOST_SLP_EN |= MEC1322_PCR_HOST_SLP_EN_SLEEP; MEC1322_PCR_EC_SLP_EN2 |= MEC1322_PCR_EC_SLP_EN2_SLEEP; MEC1322_PCR_SLOW_CLK_CTL &= 0xfffffc00; /* Set sleep state */ MEC1322_PCR_SYS_SLP_CTL = (MEC1322_PCR_SYS_SLP_CTL & ~0x7) | 0x2; CPU_SCB_SYSCTRL |= 0x4; /* Setup GPIOs for hibernate */ if (board_hibernate_late) board_hibernate_late(); #ifdef CONFIG_USB_PD_PORT_COUNT /* * Leave USB-C charging enabled in hibernate, in order to * allow wake-on-plug. 5V enable must be pulled low. */ #if CONFIG_USB_PD_PORT_COUNT > 0 gpio_set_flags(GPIO_USB_C0_5V_EN, GPIO_PULL_DOWN | GPIO_INPUT); gpio_set_level(GPIO_USB_C0_CHARGE_EN_L, 0); #endif #if CONFIG_USB_PD_PORT_COUNT > 1 gpio_set_flags(GPIO_USB_C1_5V_EN, GPIO_PULL_DOWN | GPIO_INPUT); gpio_set_level(GPIO_USB_C1_CHARGE_EN_L, 0); #endif #endif /* CONFIG_USB_PD_PORT_COUNT */ if (hibernate_wake_pins_used > 0) { for (i = 0; i < hibernate_wake_pins_used; ++i) { const enum gpio_signal pin = hibernate_wake_pins[i]; gpio_reset(pin); gpio_enable_interrupt(pin); } interrupt_enable(); task_enable_irq(MEC1322_IRQ_GIRQ8); task_enable_irq(MEC1322_IRQ_GIRQ9); task_enable_irq(MEC1322_IRQ_GIRQ10); task_enable_irq(MEC1322_IRQ_GIRQ11); task_enable_irq(MEC1322_IRQ_GIRQ20); } if (seconds || microseconds) { MEC1322_INT_BLK_EN |= 1 << 17; MEC1322_INT_ENABLE(17) |= 1 << 20; interrupt_enable(); task_enable_irq(MEC1322_IRQ_HTIMER); if (seconds > 2) { ASSERT(seconds <= 0xffff / 8); MEC1322_HTIMER_CONTROL = 1; MEC1322_HTIMER_PRELOAD = (seconds * 8 + microseconds / 125000); } else { MEC1322_HTIMER_CONTROL = 0; MEC1322_HTIMER_PRELOAD = (seconds * 1000000 + microseconds) * 2 / 71; } } asm("wfi"); /* Use 48MHz clock to speed through wake-up */ MEC1322_PCR_PROC_CLK_CTL = 1; /* Reboot */ _system_reset(0, 1); /* We should never get here. */ while (1) ; }
enum power_state power_handle_state(enum power_state state) { int value; static int boot_from_g3; switch (state) { case POWER_G3: boot_from_g3 = check_for_power_on_event(); if (boot_from_g3) return POWER_G3S5; break; case POWER_G3S5: return POWER_S5; case POWER_S5: if (boot_from_g3) { value = boot_from_g3; boot_from_g3 = 0; } else { value = check_for_power_on_event(); } if (value) { CPRINTS("power on %d", value); return POWER_S5S3; } return state; case POWER_S5S3: hook_notify(HOOK_CHIPSET_PRE_INIT); power_on(); disable_sleep(SLEEP_MASK_AP_RUN); powerled_set_state(POWERLED_STATE_ON); if (power_wait_signals(IN_POWER_GOOD) == EC_SUCCESS) { CPRINTS("POWER_GOOD seen"); if (power_button_wait_for_release( DELAY_SHUTDOWN_ON_POWER_HOLD) == EC_SUCCESS) { power_button_was_pressed = 0; set_pmic_pwron(0); /* setup misc gpio for S3/S0 functionality */ gpio_set_flags(GPIO_SUSPEND_L, GPIO_INPUT | GPIO_INT_BOTH | GPIO_PULL_DOWN); gpio_set_flags(GPIO_EC_INT_L, GPIO_OUTPUT | GPIO_OUT_HIGH); /* Call hooks now that AP is running */ hook_notify(HOOK_CHIPSET_STARTUP); return POWER_S3; } else { CPRINTS("long-press button, shutdown"); power_off(); /* * Since the AP may be up already, return S0S3 * state to go through the suspend hook. */ return POWER_S0S3; } } else { CPRINTS("POWER_GOOD not seen in time"); } chipset_turn_off_power_rails(); return POWER_S5; case POWER_S3: if (!(power_get_signals() & IN_POWER_GOOD)) return POWER_S3S5; else if (!(power_get_signals() & IN_SUSPEND)) return POWER_S3S0; return state; case POWER_S3S0: powerled_set_state(POWERLED_STATE_ON); hook_notify(HOOK_CHIPSET_RESUME); return POWER_S0; case POWER_S0: value = check_for_power_off_event(); if (value) { CPRINTS("power off %d", value); power_off(); return POWER_S0S3; } else if (power_get_signals() & IN_SUSPEND) return POWER_S0S3; return state; case POWER_S0S3: if (lid_is_open()) powerled_set_state(POWERLED_STATE_SUSPEND); else powerled_set_state(POWERLED_STATE_OFF); /* Call hooks here since we don't know it prior to AP suspend */ hook_notify(HOOK_CHIPSET_SUSPEND); return POWER_S3; case POWER_S3S5: power_button_wait_for_release(-1); power_button_was_pressed = 0; return POWER_S5; case POWER_S5G3: return POWER_G3; } return state; }
enum cts_rc od_read_high_test(void) { gpio_set_flags(GPIO_INPUT_TEST, GPIO_OUTPUT | GPIO_ODR_LOW); msleep(READ_WAIT_TIME_MS*2); return CTS_RC_SUCCESS; }