static void kevin_led_set_power_battery(void) { static int power_ticks; if (chipset_in_state(CHIPSET_STATE_ON)) { set_color(LED_BLUE); return; } /* CHIPSET_STATE_OFF */ switch (charge_get_state()) { case PWR_STATE_DISCHARGE: set_color(LED_OFF); break; case PWR_STATE_CHARGE: set_color(LED_RED); break; case PWR_STATE_ERROR: power_ticks++; set_color(((power_ticks % LED_TOTAL_TICKS) < LED_ON_TICKS) ? LED_RED : LED_GREEN); break; case PWR_STATE_CHARGE_NEAR_FULL: case PWR_STATE_IDLE: /* External power connected in IDLE. */ set_color(LED_GREEN); break; default: set_color(LED_RED); break; } if ((charge_get_state()) != PWR_STATE_ERROR) power_ticks = 0; }
static int wait_charging_state(void) { enum charge_state state; task_wake(TASK_ID_CHARGER); msleep(WAIT_CHARGER_TASK); state = charge_get_state(); ccprintf("[CHARGING TEST] state = %d\n", state); return state; }
static void onewire_led_tick(void) { static enum led_color current_color = LED_COLOR_COUNT; static int tick_count; enum led_color new_color = LED_OFF; uint32_t chflags = charge_get_flags(); tick_count++; if (!(chflags & CHARGE_FLAG_EXTERNAL_POWER)) { /* AC isn't present, so the power LED on the AC plug is off */ current_color = LED_OFF; return; } /* Translate charge state to LED color */ switch (charge_get_state()) { case PWR_STATE_IDLE: if (chflags & CHARGE_FLAG_FORCE_IDLE) new_color = (tick_count & 1) ? LED_GREEN : LED_OFF; else new_color = LED_GREEN; break; case PWR_STATE_CHARGE: new_color = LED_YELLOW; break; case PWR_STATE_CHARGE_NEAR_FULL: new_color = LED_GREEN; break; case PWR_STATE_ERROR: new_color = LED_RED; break; default: /* Other states don't change LED color */ break; } /* * The power adapter on link can partially unplug and lose its LED * state. There's no way to detect this, so just assume it forgets its * state every 10 seconds. */ if (!(tick_count % 10)) current_color = LED_COLOR_COUNT; /* If current color is still correct, leave now */ if (new_color == current_color) return; /* Update LED */ if (!led_set(new_color)) current_color = new_color; }
int charge_keep_power_off(void) { int charge; if (BATTERY_AP_OFF_LEVEL == 0) return 0; if (battery_remaining_capacity(&charge)) return charge_get_state() != PWR_STATE_ERROR; return charge <= BATTERY_AP_OFF_LEVEL; }
static void glados_led_set_battery(void) { static int battery_ticks; uint32_t chflags = charge_get_flags(); battery_ticks++; /* BAT LED behavior: * Same as the chromeos spec * Green/Amber for CHARGE_FLAG_FORCE_IDLE */ switch (charge_get_state()) { case PWR_STATE_CHARGE: glados_led_set_color_battery(LED_AMBER); break; case PWR_STATE_DISCHARGE: /* Less than 3%, blink one second every two second */ if (charge_get_percent() < CRITICAL_LOW_BATTERY_PERCENTAGE) glados_led_set_color_battery( (battery_ticks % LED_TOTAL_2SECS_TICKS < LED_ON_1SEC_TICKS) ? LED_AMBER : LED_OFF); /* Less than 10%, blink one second every four seconds */ else if (charge_get_percent() < LOW_BATTERY_PERCENTAGE) glados_led_set_color_battery( (battery_ticks % LED_TOTAL_4SECS_TICKS < LED_ON_1SEC_TICKS) ? LED_AMBER : LED_OFF); else glados_led_set_color_battery(LED_OFF); break; case PWR_STATE_ERROR: glados_led_set_color_battery( (battery_ticks % LED_TOTAL_2SECS_TICKS < LED_ON_1SEC_TICKS) ? LED_RED : LED_OFF); break; case PWR_STATE_CHARGE_NEAR_FULL: glados_led_set_color_battery(LED_GREEN); break; case PWR_STATE_IDLE: /* External power connected in IDLE */ if (chflags & CHARGE_FLAG_FORCE_IDLE) glados_led_set_color_battery( (battery_ticks % LED_TOTAL_4SECS_TICKS < LED_ON_2SECS_TICKS) ? LED_GREEN : LED_AMBER); else glados_led_set_color_battery(LED_GREEN); break; default: /* Other states don't alter LED behavior */ break; } }
static void big_led_set_battery(void) { static int battery_second; uint32_t chflags = charge_get_flags(); battery_second++; /* BAT LED behavior: * Fully charged / idle: Blue * Force idle (for factory): 2 secs of blue, 2 secs of yellow * Under charging: Orange * Battery low (10%): Orange in breeze mode (1 sec on, 3 sec off) * Battery critical low (less than 3%) or abnormal battery * situation: Orange in blinking mode (1 sec on, 1 sec off) * Using battery or not connected to AC power: OFF */ switch (charge_get_state()) { case PWR_STATE_CHARGE: bat_led_set_color(LED_ORANGE); break; case PWR_STATE_DISCHARGE: if (charge_get_percent() < 3) bat_led_set_color((battery_second & 1) ? LED_OFF : LED_ORANGE); else if (charge_get_percent() < 10) bat_led_set_color((battery_second & 3) ? LED_OFF : LED_ORANGE); else bat_led_set_color(LED_OFF); break; case PWR_STATE_ERROR: bat_led_set_color((battery_second & 1) ? LED_OFF : LED_ORANGE); break; case PWR_STATE_CHARGE_NEAR_FULL: bat_led_set_color(LED_BLUE); break; case PWR_STATE_IDLE: /* External power connected in IDLE. */ if (chflags & CHARGE_FLAG_FORCE_IDLE) bat_led_set_color( (battery_second & 0x2) ? LED_BLUE : LED_ORANGE); else bat_led_set_color(LED_BLUE); break; default: /* Other states don't alter LED behavior */ break; } }
static void std_led_set_battery(void) { static int battery_second; uint32_t chflags = charge_get_flags(); battery_second++; /* BAT LED behavior: * Same as the chromeos spec * Green/Amber for CHARGE_FLAG_FORCE_IDLE */ switch (charge_get_state()) { case PWR_STATE_CHARGE: bat_led_set_color(LED_AMBER); break; case PWR_STATE_DISCHARGE: if (charge_get_percent() < 3) bat_led_set_color((battery_second & 1) ? LED_OFF : LED_AMBER); else if (charge_get_percent() < 10) bat_led_set_color((battery_second & 3) ? LED_OFF : LED_AMBER); else bat_led_set_color(LED_OFF); break; case PWR_STATE_ERROR: bat_led_set_color((battery_second & 1) ? LED_OFF : LED_RED); break; case PWR_STATE_CHARGE_NEAR_FULL: bat_led_set_color(LED_GREEN); break; case PWR_STATE_IDLE: /* External power connected in IDLE. */ if (chflags & CHARGE_FLAG_FORCE_IDLE) bat_led_set_color( (battery_second & 0x2) ? LED_GREEN : LED_AMBER); else bat_led_set_color(LED_GREEN); break; default: /* Other states don't alter LED behavior */ break; } }
/** * Called by hook task every 250 ms */ static void led_tick(void) { static unsigned ticks; int chstate = charge_get_state(); ticks++; /* If we don't control the LED, nothing to do */ if (!led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) return; /* If charging error, blink orange, 25% duty cycle, 4 sec period */ if (chstate == PWR_STATE_ERROR) { set_color((ticks % 16) < 4 ? LED_ORANGE : LED_OFF); return; } /* If charge-force-idle, blink green, 50% duty cycle, 2 sec period */ if (chstate == PWR_STATE_IDLE && (charge_get_flags() & CHARGE_FLAG_FORCE_IDLE)) { set_color((ticks & 0x4) ? LED_GREEN : LED_OFF); return; } /* If the system is charging, solid orange */ if (chstate == PWR_STATE_CHARGE) { set_color(LED_ORANGE); return; } /* If AC connected and fully charged (or close to it), solid green */ if (chstate == PWR_STATE_CHARGE_NEAR_FULL || chstate == PWR_STATE_IDLE) { set_color(LED_GREEN); return; } /* Otherwise, system is off and AC not connected, LED off */ set_color(LED_OFF); }
static void jerry_led_set_battery(void) { static int battery_second; battery_second++; /* BAT LED behavior: * Fully charged / idle: Off * Under charging: Orange * Battery low (10%): Orange in breeze mode (1 sec on, 3 sec off) * Battery critical low (less than 3%) or abnormal battery * situation: Orange in blinking mode (1 sec on, 1 sec off) * Using battery or not connected to AC power: OFF */ switch (charge_get_state()) { case PWR_STATE_CHARGE: bat_led_set(LED_ORANGE, 1); break; case PWR_STATE_CHARGE_NEAR_FULL: bat_led_set(LED_ORANGE, 1); break; case PWR_STATE_DISCHARGE: if (charge_get_percent() < 3) bat_led_set(LED_ORANGE, (battery_second & 1) ? 0 : 1); else if (charge_get_percent() < 10) bat_led_set(LED_ORANGE, (battery_second & 3) ? 0 : 1); else bat_led_set(LED_ORANGE, 0); break; case PWR_STATE_ERROR: bat_led_set(LED_ORANGE, (battery_second & 1) ? 0 : 1); break; case PWR_STATE_IDLE: /* External power connected in IDLE. */ bat_led_set(LED_ORANGE, 0); break; default: /* Other states don't alter LED behavior */ break; } }
static int test_external_funcs(void) { int rv, temp; uint32_t flags; int state; /* Connect the AC */ test_setup(1); flags = charge_get_flags(); TEST_ASSERT(flags & CHARGE_FLAG_EXTERNAL_POWER); TEST_ASSERT(!(flags & CHARGE_FLAG_FORCE_IDLE)); /* Invalid or do-nothing commands first */ UART_INJECT("chg\n"); state = wait_charging_state(); TEST_ASSERT(state == PWR_STATE_CHARGE); flags = charge_get_flags(); TEST_ASSERT(flags & CHARGE_FLAG_EXTERNAL_POWER); TEST_ASSERT(!(flags & CHARGE_FLAG_FORCE_IDLE)); UART_INJECT("chg blahblah\n"); state = wait_charging_state(); TEST_ASSERT(state == PWR_STATE_CHARGE); flags = charge_get_flags(); TEST_ASSERT(flags & CHARGE_FLAG_EXTERNAL_POWER); TEST_ASSERT(!(flags & CHARGE_FLAG_FORCE_IDLE)); UART_INJECT("chg idle\n"); state = wait_charging_state(); TEST_ASSERT(state == PWR_STATE_CHARGE); flags = charge_get_flags(); TEST_ASSERT(flags & CHARGE_FLAG_EXTERNAL_POWER); TEST_ASSERT(!(flags & CHARGE_FLAG_FORCE_IDLE)); UART_INJECT("chg idle blargh\n"); state = wait_charging_state(); TEST_ASSERT(state == PWR_STATE_CHARGE); flags = charge_get_flags(); TEST_ASSERT(flags & CHARGE_FLAG_EXTERNAL_POWER); TEST_ASSERT(!(flags & CHARGE_FLAG_FORCE_IDLE)); /* Now let's force idle on and off */ UART_INJECT("chg idle on\n"); state = wait_charging_state(); TEST_ASSERT(state == PWR_STATE_IDLE); flags = charge_get_flags(); TEST_ASSERT(flags & CHARGE_FLAG_EXTERNAL_POWER); TEST_ASSERT(flags & CHARGE_FLAG_FORCE_IDLE); UART_INJECT("chg idle off\n"); wait_charging_state(); state = wait_charging_state(); TEST_ASSERT(state == PWR_STATE_CHARGE); flags = charge_get_flags(); TEST_ASSERT(flags & CHARGE_FLAG_EXTERNAL_POWER); TEST_ASSERT(!(flags & CHARGE_FLAG_FORCE_IDLE)); /* and the rest */ TEST_ASSERT(charge_get_state() == PWR_STATE_CHARGE); TEST_ASSERT(!charge_want_shutdown()); TEST_ASSERT(charge_get_percent() == 50); temp = 0; rv = charge_temp_sensor_get_val(0, &temp); TEST_ASSERT(rv == EC_SUCCESS); TEST_ASSERT(K_TO_C(temp) == 25); return EC_SUCCESS; }
static void oak_led_set_battery(int board_version) { static int battery_second; battery_second++; switch(board_version) { case OAK_REV3: case OAK_REV4: /* * For Rev3 and Rev4 revision: * BAT LED behavior: * - Fully charged / idle: Green ON * - Charging: Amber ON (BAT_LED_RED && BAT_LED_GREEN) * - Battery discharging capacity<10%, red blink * - Battery error: Red ON */ switch (charge_get_state()) { case PWR_STATE_CHARGE: bat_led_set(BAT_LED_AMBER, 1); break; case PWR_STATE_CHARGE_NEAR_FULL: bat_led_set(BAT_LED_GREEN, 1); bat_led_set(BAT_LED_RED, 0); break; case PWR_STATE_DISCHARGE: bat_led_set(BAT_LED_GREEN, 0); if (charge_get_percent() < 3) bat_led_set(BAT_LED_RED, (battery_second & 1) ? 0 : 1); else if (charge_get_percent() < 10) bat_led_set(BAT_LED_RED, (battery_second & 3) ? 0 : 1); else bat_led_set(BAT_LED_RED, 0); break; case PWR_STATE_ERROR: bat_led_set(BAT_LED_RED, 1); break; case PWR_STATE_IDLE: /* Ext. power connected in IDLE. */ bat_led_set(BAT_LED_GREEN, 1); bat_led_set(BAT_LED_RED, 0); break; default: /* Other states don't alter LED behavior */ break; } break; /* End of case OAK_REV3 & OAK_REV4 */ default: /* * Put power control here since we are using the "battery" LED. * This allows LED autocontrol to be turned off by cmd during factory test. * * PWR LED behavior: * Power on: Green * Suspend: Green in breeze mode ( 1 sec on/ 3 sec off) * Power off: OFF */ if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) bat_led_set(BAT_LED_GREEN, 0); else if (chipset_in_state(CHIPSET_STATE_ON)) bat_led_set(BAT_LED_GREEN, 1); else if (chipset_in_state(CHIPSET_STATE_SUSPEND)) { int cycle_time = 4; /* Oak rev5 with GlaDOS ID has a extremely power * comsuming LED. Increase LED blink cycle time to reduce * S3 power comsuption. */ if (board_version >= OAK_REV5) cycle_time = 10; bat_led_set(BAT_LED_GREEN, (battery_second % cycle_time) ? 0 : 1); } /* BAT LED behavior: * Fully charged / idle: Off * Under charging: Orange * Bat. low (10%): Orange in breeze mode (1s on, 3s off) * Bat. critical low (less than 3%) or abnormal battery * situation: Orange in blinking mode (1s on, 1s off) * Using battery or not connected to AC power: OFF */ switch (charge_get_state()) { case PWR_STATE_CHARGE: bat_led_set(BAT_LED_ORANGE, 1); break; case PWR_STATE_CHARGE_NEAR_FULL: bat_led_set(BAT_LED_ORANGE, 1); break; case PWR_STATE_DISCHARGE: if (charge_get_percent() < 3) bat_led_set(BAT_LED_ORANGE, (battery_second & 1) ? 0 : 1); else if (charge_get_percent() < 10) bat_led_set(BAT_LED_ORANGE, (battery_second & 3) ? 0 : 1); else bat_led_set(BAT_LED_ORANGE, 0); break; case PWR_STATE_ERROR: bat_led_set(BAT_LED_ORANGE, (battery_second & 1) ? 0 : 1); break; case PWR_STATE_IDLE: /* Ext. power connected in IDLE. */ bat_led_set(BAT_LED_ORANGE, 0); break; default: /* Other states don't alter LED behavior */ break; } break; /* End of default */ } }
/** * Power button state machine. * * @param tnow Current time from usec counter */ static void state_machine(uint64_t tnow) { /* Not the time to move onto next state */ if (tnow < tnext_state) return; /* States last forever unless otherwise specified */ tnext_state = 0; switch (pwrbtn_state) { case PWRBTN_STATE_PRESSED: if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) { /* * Chipset is off, so wake the chipset and send it a * long enough pulse to wake up. After that we'll * reflect the true power button state. If we don't * stretch the pulse here, the user may release the * power button before the chipset finishes waking from * hard off state. */ chipset_exit_hard_off(); tnext_state = tnow + PWRBTN_INITIAL_US; pwrbtn_state = PWRBTN_STATE_WAS_OFF; } else { /* Chipset is on, so send the chipset a pulse */ tnext_state = tnow + PWRBTN_DELAY_T0; pwrbtn_state = PWRBTN_STATE_T0; } set_pwrbtn_to_pch(0); break; case PWRBTN_STATE_T0: tnext_state = tnow + PWRBTN_DELAY_T1; pwrbtn_state = PWRBTN_STATE_T1; set_pwrbtn_to_pch(1); break; case PWRBTN_STATE_T1: /* * If the chipset is already off, don't tell it the power * button is down; it'll just cause the chipset to turn on * again. */ if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) CPRINTS("PB chipset already off"); else set_pwrbtn_to_pch(0); pwrbtn_state = PWRBTN_STATE_HELD; break; case PWRBTN_STATE_RELEASED: case PWRBTN_STATE_LID_OPEN: set_pwrbtn_to_pch(1); pwrbtn_state = PWRBTN_STATE_IDLE; break; case PWRBTN_STATE_INIT_ON: /* * Don't do anything until the charger knows the battery level. * Otherwise we could power on the AP only to shut it right * back down due to insufficient battery. */ #ifdef HAS_TASK_CHARGER if (charge_get_state() == PWR_STATE_INIT) break; #endif /* * Power the system on if possible. Gating due to insufficient * battery is handled inside set_pwrbtn_to_pch(). */ chipset_exit_hard_off(); set_pwrbtn_to_pch(0); tnext_state = get_time().val + PWRBTN_INITIAL_US; if (power_button_is_pressed()) { if (system_get_reset_flags() & RESET_FLAG_RESET_PIN) pwrbtn_state = PWRBTN_STATE_BOOT_KB_RESET; else pwrbtn_state = PWRBTN_STATE_WAS_OFF; } else { pwrbtn_state = PWRBTN_STATE_RELEASED; } break; case PWRBTN_STATE_BOOT_KB_RESET: /* Initial forced pulse is done. Ignore the actual power * button until it's released, so that holding down the * recovery combination doesn't cause the chipset to shut back * down. */ set_pwrbtn_to_pch(1); if (power_button_is_pressed()) pwrbtn_state = PWRBTN_STATE_EAT_RELEASE; else pwrbtn_state = PWRBTN_STATE_IDLE; break; case PWRBTN_STATE_WAS_OFF: /* Done stretching initial power button signal, so show the * true power button state to the PCH. */ if (power_button_is_pressed()) { /* User is still holding the power button */ pwrbtn_state = PWRBTN_STATE_HELD; } else { /* Stop stretching the power button press */ power_button_released(tnow); } break; case PWRBTN_STATE_IDLE: case PWRBTN_STATE_HELD: case PWRBTN_STATE_EAT_RELEASE: /* Do nothing */ break; } }
int charge_want_shutdown(void) { return (charge_get_state() == PWR_STATE_DISCHARGE) && charge_get_percent() < BATTERY_LEVEL_SHUTDOWN; }
static void led_set_battery(void) { static int battery_ticks; static int suspend_ticks; static int previous_state_suspend; uint32_t chflags = charge_get_flags(); battery_ticks++; suspend_ticks++; switch (charge_get_state()) { case PWR_STATE_CHARGE: led_set_color_battery(LED_AMBER); break; case PWR_STATE_DISCHARGE: /* Less than 3%, blink one second every two second */ if (!chipset_in_state(CHIPSET_STATE_ANY_OFF) && charge_get_percent() < CRITICAL_LOW_BATTERY_PERCENTAGE) led_set_color_battery( (battery_ticks % LED_TOTAL_2SECS_TICKS < LED_ON_1SEC_TICKS) ? LED_AMBER : LED_OFF); /* Less than 10%, blink one second every four seconds */ else if (!chipset_in_state(CHIPSET_STATE_ANY_OFF) && charge_get_percent() < LOW_BATTERY_PERCENTAGE) led_set_color_battery( (battery_ticks % LED_TOTAL_4SECS_TICKS < LED_ON_1SEC_TICKS) ? LED_AMBER : LED_OFF); else { if (chipset_in_state(CHIPSET_STATE_SUSPEND | CHIPSET_STATE_STANDBY)) { if (!previous_state_suspend) suspend_ticks = 0; /* Blink once every four seconds. */ led_set_color_battery( (suspend_ticks % LED_TOTAL_4SECS_TICKS) < LED_ON_1SEC_TICKS ? LED_AMBER : LED_OFF); previous_state_suspend = 1; return; } if (chipset_in_state(CHIPSET_STATE_ON)) led_set_color_battery(LED_BLUE); else led_set_color_battery(LED_OFF); } break; case PWR_STATE_ERROR: led_set_color_battery( (battery_ticks % LED_TOTAL_2SECS_TICKS < LED_ON_1SEC_TICKS) ? LED_AMBER : LED_OFF); break; case PWR_STATE_CHARGE_NEAR_FULL: led_set_color_battery(LED_BLUE); break; case PWR_STATE_IDLE: /* External power connected in IDLE */ if (chflags & CHARGE_FLAG_FORCE_IDLE) led_set_color_battery( (battery_ticks % LED_TOTAL_4SECS_TICKS < LED_ON_2SECS_TICKS) ? LED_AMBER : LED_BLUE); else led_set_color_battery(LED_BLUE); break; default: /* Other states don't alter LED behavior */ break; } previous_state_suspend = 0; }