diff options
Diffstat (limited to 'board/samus')
-rw-r--r-- | board/samus/battery.c | 301 | ||||
-rw-r--r-- | board/samus/board.c | 490 | ||||
-rw-r--r-- | board/samus/board.h | 227 | ||||
-rw-r--r-- | board/samus/build.mk | 16 | ||||
-rw-r--r-- | board/samus/ec.tasklist | 22 | ||||
-rw-r--r-- | board/samus/extpower.c | 441 | ||||
-rw-r--r-- | board/samus/gpio.inc | 122 | ||||
-rw-r--r-- | board/samus/panel.c | 195 | ||||
-rw-r--r-- | board/samus/power_sequence.c | 560 |
9 files changed, 0 insertions, 2374 deletions
diff --git a/board/samus/battery.c b/board/samus/battery.c deleted file mode 100644 index bc73cbc1c3..0000000000 --- a/board/samus/battery.c +++ /dev/null @@ -1,301 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Battery pack vendor provided charging profile - */ - -#include "battery_smart.h" -#include "charge_state.h" -#include "console.h" -#include "ec_commands.h" -#include "extpower.h" -#include "i2c.h" -#include "util.h" - -static const struct battery_info info = { - /* - * Design voltage - * max = 8.4V - * normal = 7.4V - * min = 6.0V - */ - .voltage_max = 8700, - .voltage_normal = 7400, - .voltage_min = 6000, - - /* Pre-charge current: I <= 0.01C */ - .precharge_current = 64, /* mA */ - - /* - * Operational temperature range - * 0 <= T_charge <= 50 deg C - * -20 <= T_discharge <= 60 deg C - */ - .start_charging_min_c = 0, - .start_charging_max_c = 50, - .charging_min_c = 0, - .charging_max_c = 50, - .discharging_min_c = -20, - .discharging_max_c = 60, -}; - -const struct battery_info *battery_get_info(void) -{ - return &info; -} - -#ifdef CONFIG_CHARGER_PROFILE_OVERRIDE - -static int fast_charging_allowed = 1; - -/* - * This can override the smart battery's charging profile. To make a change, - * modify one or more of requested_voltage, requested_current, or state. - * Leave everything else unchanged. - * - * Return the next poll period in usec, or zero to use the default (which is - * state dependent). - */ -int charger_profile_override(struct charge_state_data *curr) -{ - /* temp in 0.1 deg C */ - int temp_c; - const struct charger_info *info; - - /* keep track of last temperature range for hysteresis */ - static enum { - TEMP_LOW, - TEMP_NORMAL, - TEMP_HIGH - } temp_range = TEMP_NORMAL, prev_temp_range = TEMP_NORMAL; - - /* charging voltage to use at high temp */ - static int high_temp_charging_voltage; - - /* custom profile phase at normal temp */ - static int normal_temp_phase; - - /* battery voltage and current and previous voltage and current */ - int batt_voltage, batt_current; - static int prev_batt_voltage, prev_batt_current; - - /* - * Determine temperature range: - * Low: Battery is <15C - * Normal: Battery is 15-45C - * High: Battery is >45C - * - * Add 0.2 degrees of hysteresis. - * If temp reading was bad use last range. - */ - if (!(curr->batt.flags & BATT_FLAG_BAD_TEMPERATURE)) { - temp_c = curr->batt.temperature - 2731; - if (temp_c < 149) - temp_range = TEMP_LOW; - else if (temp_c > 151 && temp_c < 449) - temp_range = TEMP_NORMAL; - else if (temp_c > 451) - temp_range = TEMP_HIGH; - } - - /* - * Treat voltage and current as a pair, if either is bad fall back to - * previous reading. - */ - if (curr->batt.flags & - (BATT_FLAG_BAD_VOLTAGE | BATT_FLAG_BAD_CURRENT)) { - batt_voltage = prev_batt_voltage; - batt_current = prev_batt_current; - } else { - batt_voltage = prev_batt_voltage = curr->batt.voltage; - batt_current = prev_batt_current = curr->batt.current; - } - - /* - * If we are not charging or we aren't using fast charging profiles, - * then do not override desired current and voltage and reset some - * fast charging profile static variables. - */ - if (curr->state != ST_CHARGE || !fast_charging_allowed) { - prev_temp_range = TEMP_NORMAL; - normal_temp_phase = 0; - return 0; - } - - /* - * Okay, impose our custom will: - * Normal temp: - * Phase 0: CC at 9515mA @ 8.3V - * CV at 8.3V until current drops to 4759mA - * Phase 1: CC at 4759mA @ 8.7V - * CV at 8.7V - * - * Low temp: - * CC at 2854mA @ 8.7V - * CV at 8.7V - * - * High temp: - * If battery voltage < 8.3V then: - * CC at 6660mA @ 8.3V - * CV at 8.3V (when battery is hot we don't go to fully charged) - * else: - * CV at just above battery voltage which will essentially - * terminate the charge and allow battery to cool. - * Note that if we ever request a voltage below the present battery - * voltage, then we will stop the BQ switching, which will power off - * the INA and we won't be able to charge again until AC is - * disconnected. see crbug.com/p/35491. - */ - switch (temp_range) { - case TEMP_LOW: - curr->requested_current = 2854; - curr->requested_voltage = 8700; - break; - case TEMP_NORMAL: - if (normal_temp_phase == 0) { - curr->requested_current = 9515; - curr->requested_voltage = 8300; - if (batt_current <= 4759 && batt_voltage >= 8200) - normal_temp_phase = 1; - } - if (normal_temp_phase == 1) { - curr->requested_current = 4759; - curr->requested_voltage = 8700; - } - break; - case TEMP_HIGH: - /* - * First time TEMP_HIGH is used, get the closest voltage - * just above the battery voltage. If it is above 8.3V, we - * will use that as the target, otherwise we will use 8.3V. - */ - if (prev_temp_range != TEMP_HIGH) { - info = charger_get_info(); - high_temp_charging_voltage = MAX(8300, - charger_closest_voltage(batt_voltage + - info->voltage_step)); - } - curr->requested_current = 6660; - curr->requested_voltage = high_temp_charging_voltage; - break; - } - prev_temp_range = temp_range; - - return 0; -} - -/* Customs options controllable by host command. */ -#define PARAM_FASTCHARGE (CS_PARAM_CUSTOM_PROFILE_MIN + 0) - -enum ec_status charger_profile_override_get_param(uint32_t param, - uint32_t *value) -{ - if (param == PARAM_FASTCHARGE) { - *value = fast_charging_allowed; - return EC_RES_SUCCESS; - } - return EC_RES_INVALID_PARAM; -} - -enum ec_status charger_profile_override_set_param(uint32_t param, - uint32_t value) -{ - if (param == PARAM_FASTCHARGE) { - fast_charging_allowed = value; - return EC_RES_SUCCESS; - } - return EC_RES_INVALID_PARAM; -} - -#ifdef CONFIG_CMD_FASTCHARGE -static int command_fastcharge(int argc, char **argv) -{ - if (argc > 1 && !parse_bool(argv[1], &fast_charging_allowed)) - return EC_ERROR_PARAM1; - - ccprintf("fastcharge %s\n", fast_charging_allowed ? "on" : "off"); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(fastcharge, command_fastcharge, - "[on|off]", - "Get or set fast charging profile"); -#endif /* CONFIG_CMD_FASTCHARGE */ - -#endif /* CONFIG_CHARGER_PROFILE_OVERRIDE */ - -#ifdef CONFIG_BATTERY_REVIVE_DISCONNECT -/* - * Check if battery is in disconnect state, a state entered by pulling - * BATT_DISCONN_N low, and clear that state if we have external power plugged - * and no battery faults are detected. Disconnect state resembles battery - * shutdown mode, but extra steps must be taken to get the battery out of this - * mode. - */ -enum battery_disconnect_state battery_get_disconnect_state(void) -{ - uint8_t data[6]; - int rv; - /* - * Take note if we find that the battery isn't in disconnect state, - * and always return NOT_DISCONNECTED without probing the battery. - * This assumes the battery will not go to disconnect state during - * runtime. - */ - static int not_disconnected; - - if (not_disconnected) - return BATTERY_NOT_DISCONNECTED; - - if (extpower_is_present()) { - /* Check if battery charging + discharging is disabled. */ - rv = sb_read_mfgacc(PARAM_OPERATION_STATUS, - SB_ALT_MANUFACTURER_ACCESS, data, sizeof(data)); - if (rv) - return BATTERY_DISCONNECT_ERROR; - if (~data[3] & (BATTERY_DISCHARGING_DISABLED | - BATTERY_CHARGING_DISABLED)) { - not_disconnected = 1; - return BATTERY_NOT_DISCONNECTED; - } - - /* - * Battery is neither charging nor discharging. Verify that - * we didn't enter this state due to a safety fault. - */ - rv = sb_read_mfgacc(PARAM_SAFETY_STATUS, - SB_ALT_MANUFACTURER_ACCESS, data, sizeof(data)); - if (rv || data[2] || data[3] || data[4] || data[5]) - return BATTERY_DISCONNECT_ERROR; - else - /* No safety fault -- clear disconnect state. */ - return BATTERY_DISCONNECTED; - } - not_disconnected = 1; - return BATTERY_NOT_DISCONNECTED; -} -#endif /* CONFIG_BATTERY_REVIVE_DISCONNECT */ - -#define PARAM_CUT_OFF_LOW 0x10 -#define PARAM_CUT_OFF_HIGH 0x00 - -int board_cut_off_battery(void) -{ - int rv; - uint8_t buf[3]; - - buf[0] = SB_MANUFACTURER_ACCESS & 0xff; - buf[1] = PARAM_CUT_OFF_LOW; - buf[2] = PARAM_CUT_OFF_HIGH; - - i2c_lock(I2C_PORT_BATTERY, 1); - rv = i2c_xfer_unlocked(I2C_PORT_BATTERY, BATTERY_ADDR_FLAGS, - buf, 3, NULL, 0, I2C_XFER_SINGLE); - rv |= i2c_xfer_unlocked(I2C_PORT_BATTERY, BATTERY_ADDR_FLAGS, - buf, 3, NULL, 0, I2C_XFER_SINGLE); - i2c_lock(I2C_PORT_BATTERY, 0); - - return rv; -} - diff --git a/board/samus/board.c b/board/samus/board.c deleted file mode 100644 index d7c4811d49..0000000000 --- a/board/samus/board.c +++ /dev/null @@ -1,490 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -/* EC for Samus board configuration */ - -#include "als.h" -#include "adc.h" -#include "adc_chip.h" -#include "backlight.h" -#include "battery.h" -#include "capsense.h" -#include "charger.h" -#include "charge_state.h" -#include "common.h" -#include "console.h" -#include "driver/accel_kionix.h" -#include "driver/accel_kxcj9.h" -#include "driver/accelgyro_lsm6ds0.h" -#include "driver/als_isl29035.h" -#include "driver/temp_sensor/tmp006.h" -#include "extpower.h" -#include "fan.h" -#include "gesture.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "i2c.h" -#include "keyboard_scan.h" -#include "keyboard_8042.h" -#include "keyboard_8042_sharedlib.h" -#include "lid_switch.h" -#include "lightbar.h" -#include "motion_sense.h" -#include "motion_lid.h" -#include "peci.h" -#include "power.h" -#include "power_button.h" -#include "pwm.h" -#include "pwm_chip.h" -#include "registers.h" -#include "switch.h" -#include "system.h" -#include "task.h" -#include "temp_sensor.h" -#include "temp_sensor_chip.h" -#include "timer.h" -#include "thermal.h" -#include "uart.h" -#include "util.h" - -static void pd_mcu_interrupt(enum gpio_signal signal) -{ - /* Exchange status with PD MCU. */ - host_command_pd_send_status(PD_CHARGE_NO_CHANGE); -} - -#include "gpio_list.h" - -/* power signal list. Must match order of enum power_signal. */ -const struct power_signal_info power_signal_list[] = { - {GPIO_PP1050_PGOOD, POWER_SIGNAL_ACTIVE_HIGH, "PGOOD_PP1050"}, - {GPIO_PP1200_PGOOD, POWER_SIGNAL_ACTIVE_HIGH, "PGOOD_PP1200"}, - {GPIO_PP1800_PGOOD, POWER_SIGNAL_ACTIVE_HIGH, "PGOOD_PP1800"}, - {GPIO_VCORE_PGOOD, POWER_SIGNAL_ACTIVE_HIGH, "PGOOD_VCORE"}, - {GPIO_PCH_SLP_S0_L, POWER_SIGNAL_ACTIVE_HIGH, "SLP_S0_DEASSERTED"}, - {GPIO_PCH_SLP_S3_L, POWER_SIGNAL_ACTIVE_HIGH, "SLP_S3_DEASSERTED"}, - {GPIO_PCH_SLP_S5_L, POWER_SIGNAL_ACTIVE_HIGH, "SLP_S5_DEASSERTED"}, - {GPIO_PCH_SLP_SUS_L, POWER_SIGNAL_ACTIVE_HIGH, "SLP_SUS_DEASSERTED"}, - {GPIO_PCH_SUSWARN_L, POWER_SIGNAL_ACTIVE_HIGH, "SUSWARN_DEASSERTED"}, -}; -BUILD_ASSERT(ARRAY_SIZE(power_signal_list) == POWER_SIGNAL_COUNT); - -/* ADC channels. Must be in the exactly same order as in enum adc_channel. */ -const struct adc_t adc_channels[] = { - /* - * EC internal temperature is calculated by - * 273 + (295 - 450 * ADC_VALUE / ADC_READ_MAX) / 2 - * = -225 * ADC_VALUE / ADC_READ_MAX + 420.5 - */ - {"ECTemp", LM4_ADC_SEQ0, -225, ADC_READ_MAX, 420, - LM4_AIN_NONE, 0x0e /* TS0 | IE0 | END0 */, 0, 0}, - /* - * TODO(crosbug.com/p/23827): We don't know what to expect here, but - * it's an analog input that's pulled high. We're using it as a battery - * presence indicator for now. We'll return just 0 - ADC_READ_MAX for - * now. - */ - {"BatteryTemp", LM4_ADC_SEQ2, 1, 1, 0, - LM4_AIN(10), 0x06 /* IE0 | END0 */, LM4_GPIO_B, BIT(4)}, -}; -BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); - -/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ -const struct pwm_t pwm_channels[] = { - {4, 0}, -}; -BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); - -/* Physical fans. These are logically separate from pwm_channels. */ -const struct fan_conf fan_conf_0 = { - .flags = FAN_USE_RPM_MODE, - .ch = 2, /* Use MFT id to control fan */ - .pgood_gpio = -1, - .enable_gpio = -1, -}; - -const struct fan_conf fan_conf_1 = { - .flags = FAN_USE_RPM_MODE, - .ch = 3, /* Use MFT id to control fan */ - .pgood_gpio = -1, - .enable_gpio = -1, -}; - -const struct fan_rpm fan_rpm_0 = { - .rpm_min = 1000, - .rpm_start = 1000, - .rpm_max = 6350, -}; - -const struct fan_t fans[] = { - { .conf = &fan_conf_0, .rpm = &fan_rpm_0, }, - { .conf = &fan_conf_1, .rpm = &fan_rpm_0, }, -}; -BUILD_ASSERT(ARRAY_SIZE(fans) == CONFIG_FANS); - -/* I2C ports */ -const struct i2c_port_t i2c_ports[] = { - {"batt_chg", 0, 100, GPIO_I2C0_SCL, GPIO_I2C0_SDA}, - {"lightbar", 1, 400, GPIO_I2C1_SCL, GPIO_I2C1_SDA}, - {"thermal", 5, 100, GPIO_I2C5_SCL, GPIO_I2C5_SDA}, -}; -const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); - -#define TEMP_U40_REG_ADDR_FLAGS (0x40 | I2C_FLAG_BIG_ENDIAN) -#define TEMP_U41_REG_ADDR_FLAGS (0x44 | I2C_FLAG_BIG_ENDIAN) -#define TEMP_U42_REG_ADDR_FLAGS (0x41 | I2C_FLAG_BIG_ENDIAN) -#define TEMP_U43_REG_ADDR_FLAGS (0x45 | I2C_FLAG_BIG_ENDIAN) -#define TEMP_U115_REG_ADDR_FLAGS (0x42 | I2C_FLAG_BIG_ENDIAN) -#define TEMP_U116_REG_ADDR_FLAGS (0x43 | I2C_FLAG_BIG_ENDIAN) - -#define TEMP_U40_ADDR_FLAGS TMP006_ADDR(I2C_PORT_THERMAL,\ - TEMP_U40_REG_ADDR_FLAGS) -#define TEMP_U41_ADDR_FLAGS TMP006_ADDR(I2C_PORT_THERMAL,\ - TEMP_U41_REG_ADDR_FLAGS) -#define TEMP_U42_ADDR_FLAGS TMP006_ADDR(I2C_PORT_THERMAL,\ - TEMP_U42_REG_ADDR_FLAGS) -#define TEMP_U43_ADDR_FLAGS TMP006_ADDR(I2C_PORT_THERMAL,\ - TEMP_U43_REG_ADDR_FLAGS) -#define TEMP_U115_ADDR_FLAGS TMP006_ADDR(I2C_PORT_THERMAL,\ - TEMP_U115_REG_ADDR_FLAGS) -#define TEMP_U116_ADDR_FLAGS TMP006_ADDR(I2C_PORT_THERMAL,\ - TEMP_U116_REG_ADDR_FLAGS) - -const struct tmp006_t tmp006_sensors[TMP006_COUNT] = { - {"Charger", TEMP_U40_ADDR_FLAGS}, - {"CPU", TEMP_U41_ADDR_FLAGS}, - {"Left C", TEMP_U42_ADDR_FLAGS}, - {"Right C", TEMP_U43_ADDR_FLAGS}, - {"Right D", TEMP_U115_ADDR_FLAGS}, - {"Left D", TEMP_U116_ADDR_FLAGS}, -}; -BUILD_ASSERT(ARRAY_SIZE(tmp006_sensors) == TMP006_COUNT); - -/* Temperature sensors data; must be in same order as enum temp_sensor_id. */ -const struct temp_sensor_t temp_sensors[] = { - {"PECI", TEMP_SENSOR_TYPE_CPU, peci_temp_sensor_get_val, 0, 2}, - {"ECInternal", TEMP_SENSOR_TYPE_BOARD, chip_temp_sensor_get_val, 0, 4}, - {"I2C-Charger-Die", TEMP_SENSOR_TYPE_BOARD, tmp006_get_val, 0, 7}, - {"I2C-Charger-Object", TEMP_SENSOR_TYPE_CASE, tmp006_get_val, 1, 7}, - {"I2C-CPU-Die", TEMP_SENSOR_TYPE_BOARD, tmp006_get_val, 2, 7}, - {"I2C-CPU-Object", TEMP_SENSOR_TYPE_CASE, tmp006_get_val, 3, 7}, - {"I2C-Left C-Die", TEMP_SENSOR_TYPE_BOARD, tmp006_get_val, 4, 7}, - {"I2C-Left C-Object", TEMP_SENSOR_TYPE_CASE, tmp006_get_val, 5, 7}, - {"I2C-Right C-Die", TEMP_SENSOR_TYPE_BOARD, tmp006_get_val, 6, 7}, - {"I2C-Right C-Object", TEMP_SENSOR_TYPE_CASE, tmp006_get_val, 7, 7}, - {"I2C-Right D-Die", TEMP_SENSOR_TYPE_BOARD, tmp006_get_val, 8, 7}, - {"I2C-Right D-Object", TEMP_SENSOR_TYPE_CASE, tmp006_get_val, 9, 7}, - {"I2C-Left D-Die", TEMP_SENSOR_TYPE_BOARD, tmp006_get_val, 10, 7}, - {"I2C-Left D-Object", TEMP_SENSOR_TYPE_CASE, tmp006_get_val, 11, 7}, - {"Battery", TEMP_SENSOR_TYPE_BATTERY, charge_get_battery_temp, 0, 4}, -}; -BUILD_ASSERT(ARRAY_SIZE(temp_sensors) == TEMP_SENSOR_COUNT); - -/* ALS instances. Must be in same order as enum als_id. */ -struct als_t als[] = { - {"ISL", isl29035_init, isl29035_read_lux, 5}, -}; -BUILD_ASSERT(ARRAY_SIZE(als) == ALS_COUNT); - - -/* Thermal limits for each temp sensor. All temps are in degrees K. Must be in - * same order as enum temp_sensor_id. To always ignore any temp, use 0. - */ -struct ec_thermal_config thermal_params[] = { - /* {Twarn, Thigh, Thalt}, fan_off, fan_max */ - {{C_TO_K(95), C_TO_K(101), C_TO_K(104)}, - {0, 0, 0}, C_TO_K(55), C_TO_K(90)}, /* PECI */ - {{0, 0, 0}, {0, 0, 0}, 0, 0}, /* EC */ - {{0, 0, 0}, {0, 0, 0}, C_TO_K(41), C_TO_K(55)}, /* Charger die */ - {{0, 0, 0}, {0, 0, 0}, 0, 0}, - {{0, 0, 0}, {0, 0, 0}, C_TO_K(35), C_TO_K(49)}, /* CPU die */ - {{0, 0, 0}, {0, 0, 0}, 0, 0}, - {{0, 0, 0}, {0, 0, 0}, 0, 0}, /* Left C die */ - {{0, 0, 0}, {0, 0, 0}, 0, 0}, - {{0, 0, 0}, {0, 0, 0}, 0, 0}, /* Right C die */ - {{0, 0, 0}, {0, 0, 0}, 0, 0}, - {{0, 0, 0}, {0, 0, 0}, 0, 0}, /* Right D die */ - {{0, 0, 0}, {0, 0, 0}, 0, 0}, - {{0, 0, 0}, {0, 0, 0}, C_TO_K(43), C_TO_K(54)}, /* Left D die */ - {{0, 0, 0}, {0, 0, 0}, 0, 0}, - {{0, 0, 0}, {0, 0, 0}, 0, 0}, /* Battery */ -}; -BUILD_ASSERT(ARRAY_SIZE(thermal_params) == TEMP_SENSOR_COUNT); - -struct keyboard_scan_config keyscan_config = { - .output_settle_us = 40, - .debounce_down_us = 6 * MSEC, - .debounce_up_us = 30 * MSEC, - .scan_period_us = 1500, - .min_post_scan_delay_us = 1000, - .poll_timeout_us = SECOND, - .actual_key_mask = { - 0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, - 0xa4, 0xff, 0xf6, 0x55, 0xfa, 0xc8 /* full set */ - }, -}; - -/* Initialize board. */ -static void board_init(void) -{ - gpio_enable_interrupt(GPIO_PD_MCU_INT); -} -DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); - -#ifdef CONFIG_BATTERY_PRESENT_CUSTOM -/** - * Physical check of battery presence. - */ -enum battery_present battery_is_present(void) -{ - /* - * This pin has a pullup, so if it's not completely pegged there's - * something attached. Probably a battery. - */ - int analog_val = adc_read_channel(ADC_CH_BAT_TEMP); - return analog_val < (9 * ADC_READ_MAX / 10) ? BP_YES : BP_NO; -} -#endif - -static int discharging_on_ac; - -/** - * Discharge battery when on AC power for factory test. - */ -int board_discharge_on_ac(int enable) -{ - int rv = charger_discharge_on_ac(enable); - - if (rv == EC_SUCCESS) - discharging_on_ac = enable; - - return rv; -} - -/** - * Check if we are discharging while connected to AC - */ -int board_is_discharging_on_ac(void) -{ - return discharging_on_ac; -} - -/** - * Reset PD MCU - */ -void board_reset_pd_mcu(void) -{ - gpio_set_level(GPIO_USB_MCU_RST, 1); - usleep(100); - gpio_set_level(GPIO_USB_MCU_RST, 0); -} - -void sensor_board_proc_double_tap(void) -{ - lightbar_sequence(LIGHTBAR_TAP); -} - -const int usb_port_enable[CONFIG_USB_PORT_POWER_SMART_PORT_COUNT] = { - GPIO_USB1_ENABLE, - GPIO_USB2_ENABLE, -}; - -/* Base Sensor mutex */ -static struct mutex g_base_mutex; - -/* Lid Sensor mutex */ -static struct mutex g_lid_mutex; - -/* kxcj9 local/private data */ -struct kionix_accel_data g_kxcj9_data; - -/* lsm6ds0 local sensor data (per-sensor) */ -struct lsm6ds0_data g_saved_data[2]; - -/* Four Motion sensors */ -/* Matrix to rotate accelrator into standard reference frame */ -const mat33_fp_t base_standard_ref = { - {FLOAT_TO_FP(-1), 0, 0}, - { 0, FLOAT_TO_FP(-1), 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; - -const mat33_fp_t lid_standard_ref = { - { 0, FLOAT_TO_FP(1), 0}, - {FLOAT_TO_FP(-1), 0, 0}, - { 0, 0, FLOAT_TO_FP(-1)} -}; - -struct motion_sensor_t motion_sensors[] = { - /* - * Note: lsm6ds0: supports accelerometer and gyro sensor - * Requirement: accelerometer sensor must init before gyro sensor - * DO NOT change the order of the following table. - */ - {.name = "Base", - .active_mask = SENSOR_ACTIVE_S0_S3_S5, - .chip = MOTIONSENSE_CHIP_LSM6DS0, - .type = MOTIONSENSE_TYPE_ACCEL, - .location = MOTIONSENSE_LOC_BASE, - .drv = &lsm6ds0_drv, - .mutex = &g_base_mutex, - .drv_data = &g_saved_data[0], - .port = I2C_PORT_ACCEL, - .i2c_spi_addr_flags = LSM6DS0_ADDR1_FLAGS, - .rot_standard_ref = &base_standard_ref, - .default_range = 2, /* g, enough for laptop. */ - .min_frequency = LSM6DS0_ACCEL_MIN_FREQ, - .max_frequency = LSM6DS0_ACCEL_MAX_FREQ, - .config = { - /* EC use accel for angle detection */ - [SENSOR_CONFIG_EC_S0] = { - .odr = 119000 | ROUND_UP_FLAG, - .ec_rate = 100 * MSEC, - }, - /* Used for double tap */ - [SENSOR_CONFIG_EC_S3] = { - .odr = TAP_ODR_LSM6DS0 | ROUND_UP_FLAG, - .ec_rate = CONFIG_GESTURE_SAMPLING_INTERVAL_MS * MSEC, - }, - [SENSOR_CONFIG_EC_S5] = { - .odr = TAP_ODR_LSM6DS0 | ROUND_UP_FLAG, - .ec_rate = CONFIG_GESTURE_SAMPLING_INTERVAL_MS * MSEC, - }, - }, - }, - - {.name = "Lid", - .active_mask = SENSOR_ACTIVE_S0, - .chip = MOTIONSENSE_CHIP_KXCJ9, - .type = MOTIONSENSE_TYPE_ACCEL, - .location = MOTIONSENSE_LOC_LID, - .drv = &kionix_accel_drv, - .mutex = &g_lid_mutex, - .drv_data = &g_kxcj9_data, - .port = I2C_PORT_ACCEL, - .i2c_spi_addr_flags = KXCJ9_ADDR0_FLAGS, - .rot_standard_ref = &lid_standard_ref, - .default_range = 2, /* g, enough for laptop. */ - .min_frequency = KXCJ9_ACCEL_MIN_FREQ, - .max_frequency = KXCJ9_ACCEL_MAX_FREQ, - .config = { - /* EC use accel for angle detection */ - [SENSOR_CONFIG_EC_S0] = { - .odr = 100000 | ROUND_UP_FLAG, - .ec_rate = 100 * MSEC, - }, - }, - }, - - {.name = "Base Gyro", - .active_mask = SENSOR_ACTIVE_S0_S3_S5, - .chip = MOTIONSENSE_CHIP_LSM6DS0, - .type = MOTIONSENSE_TYPE_GYRO, - .location = MOTIONSENSE_LOC_BASE, - .drv = &lsm6ds0_drv, - .mutex = &g_base_mutex, - .drv_data = &g_saved_data[1], - .port = I2C_PORT_ACCEL, - .i2c_spi_addr_flags = LSM6DS0_ADDR1_FLAGS, - .rot_standard_ref = NULL, - .default_range = 2000, /* g, enough for laptop. */ - .min_frequency = LSM6DS0_GYRO_MIN_FREQ, - .max_frequency = LSM6DS0_GYRO_MAX_FREQ, - }, - -}; -const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); - -#ifdef CONFIG_LOW_POWER_IDLE -void jtag_interrupt(enum gpio_signal signal) -{ - /* - * This interrupt is the first sign someone is trying to use - * the JTAG. Disable slow speed sleep so that the JTAG action - * can take place. - */ - disable_sleep(SLEEP_MASK_JTAG); - - /* - * Once we get this interrupt, disable it from occurring again - * to avoid repeated interrupts when debugging via JTAG. - */ - gpio_disable_interrupt(GPIO_JTAG_TCK); -} -#endif /* CONFIG_LOW_POWER_IDLE */ - - -enum ec_error_list keyboard_scancode_callback(uint16_t *make_code, - int8_t pressed) -{ - const uint16_t k = *make_code; - static uint8_t s; - static const uint16_t a[] = { - SCANCODE_UP, SCANCODE_UP, SCANCODE_DOWN, SCANCODE_DOWN, - SCANCODE_LEFT, SCANCODE_RIGHT, SCANCODE_LEFT, SCANCODE_RIGHT, - SCANCODE_B, SCANCODE_A}; - - if (!pressed) - return EC_SUCCESS; - - /* Lightbar demo mode: keyboard can fake the battery state */ - switch (k) { - case SCANCODE_UP: - demo_battery_level(1); - break; - case SCANCODE_DOWN: - demo_battery_level(-1); - break; - case SCANCODE_LEFT: - demo_is_charging(0); - break; - case SCANCODE_RIGHT: - demo_is_charging(1); - break; - case SCANCODE_F6: /* dim */ - demo_brightness(-1); - break; - case SCANCODE_F7: /* bright */ - demo_brightness(1); - break; - case SCANCODE_T: - demo_tap(); - break; - } - - if (k == a[s]) - s++; - else if (k != a[0]) - s = 0; - else if (s != 2) - s = 1; - - if (s == ARRAY_SIZE(a)) { - s = 0; - lightbar_sequence(LIGHTBAR_KONAMI); - } - return EC_SUCCESS; -} - -/* - * Use to define going in to hibernate early if low on battery. - * HIBERNATE_BATT_PCT specifies the low battery threshold - * for going into hibernate early, and HIBERNATE_BATT_SEC defines - * the minimum amount of time to stay in G3 before checking for low - * battery hibernate. - */ -#define HIBERNATE_BATT_PCT 10 -#define HIBERNATE_BATT_SEC (3600 * 24) - -__override enum critical_shutdown board_system_is_idle( - uint64_t last_shutdown_time, uint64_t *target, uint64_t now) -{ - if (charge_get_percent() <= HIBERNATE_BATT_PCT) { - uint64_t t = last_shutdown_time + HIBERNATE_BATT_SEC * SEC_UL; - *target = MIN(*target, t); - } - return now > *target ? - CRITICAL_SHUTDOWN_HIBERNATE : CRITICAL_SHUTDOWN_IGNORE; -} diff --git a/board/samus/board.h b/board/samus/board.h deleted file mode 100644 index 1e3154c2e3..0000000000 --- a/board/samus/board.h +++ /dev/null @@ -1,227 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Configuration for Samus mainboard */ - -#ifndef __CROS_EC_BOARD_H -#define __CROS_EC_BOARD_H - -/* Debug features */ -#define CONFIG_CONSOLE_CMDHELP -#define CONFIG_TASK_PROFILING - -#undef HEY_USE_BUILTIN_CLKRUN - -/* Optional features */ -#define CONFIG_ACCELGYRO_LSM6DS0 -#define CONFIG_ACCEL_KXCJ9 -#define CONFIG_ACCEL_STD_REF_FRAME_OLD -#define CONFIG_ALS_ISL29035 -#define CONFIG_BOARD_VERSION_GPIO -#define CONFIG_CMD_ACCELS -#define CONFIG_CMD_ACCEL_INFO -#undef CONFIG_BATTERY_CRITICAL_SHUTDOWN_TIMEOUT -#define CONFIG_BATTERY_CRITICAL_SHUTDOWN_TIMEOUT 60 -#define CONFIG_BATTERY_CUT_OFF -#define CONFIG_POWER_COMMON -#define CONFIG_POWER_SHUTDOWN_PAUSE_IN_S5 -#define CONFIG_CHIPSET_CAN_THROTTLE -#define CONFIG_I2C -#define CONFIG_I2C_MASTER -#define CONFIG_KEYBOARD_BOARD_CONFIG -#define CONFIG_KEYBOARD_PROTOCOL_8042 -#define CONFIG_KEYBOARD_COL2_INVERTED -#define CONFIG_KEYBOARD_SCANCODE_CALLBACK -#define CONFIG_LID_ANGLE -#define CONFIG_LIGHTBAR_POWER_RAILS -#define CONFIG_LOW_POWER_IDLE -#define CONFIG_POWER_BUTTON -#define CONFIG_POWER_BUTTON_X86 -/* Note: not CONFIG_BACKLIGHT_LID. It's handled specially for Samus. */ -#define CONFIG_BACKLIGHT_REQ_GPIO GPIO_PCH_BL_EN -/* TODO(crosbug.com/p/29467): remove this workaround when possible. */ -#define CONFIG_BATTERY_REQUESTS_NIL_WHEN_DEAD -#define CONFIG_CHARGER_PROFILE_OVERRIDE -#define CONFIG_BATTERY_SMART -#define CONFIG_BATTERY_REVIVE_DISCONNECT -#define CONFIG_CHARGER -#define CONFIG_CHARGER_BQ24773 -#define CONFIG_CHARGER_ILIM_PIN_DISABLED -#define CONFIG_CHARGER_SENSE_RESISTOR 5 -#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 -#define CONFIG_CHARGER_INPUT_CURRENT 320 -#define CONFIG_CHARGER_DISCHARGE_ON_AC -#define CONFIG_CHARGER_DISCHARGE_ON_AC_CUSTOM -#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 1 -#define CONFIG_FANS 2 -#define CONFIG_FAN_UPDATE_PERIOD 10 -#define CONFIG_FPU -#define CONFIG_GESTURE_DETECTION -#define CONFIG_GESTURE_SW_DETECTION -#define CONFIG_GESTURE_SAMPLING_INTERVAL_MS 5 -#undef CONFIG_HIBERNATE_DELAY_SEC -#define CONFIG_HIBERNATE_DELAY_SEC (3600 * 24 * 7) -#define CONFIG_HOSTCMD_PD -#define CONFIG_HOSTCMD_PD_CHG_CTRL -#define CONFIG_HOSTCMD_PD_PANIC -#define CONFIG_PECI_TJMAX 105 -#define CONFIG_PWM -#define CONFIG_PWM_KBLIGHT -#define CONFIG_TEMP_SENSOR -#define CONFIG_TEMP_SENSOR_TMP006 -#define CONFIG_TEMP_SENSOR_POWER_GPIO GPIO_PP3300_DSW_GATED_EN -#define CONFIG_THROTTLE_AP -#define CONFIG_UART_HOST 2 -#define CONFIG_USB_PORT_POWER_SMART -#define CONFIG_USB_PORT_POWER_SMART_DEFAULT_MODE USB_CHARGE_MODE_CDP -#define CONFIG_USB_PORT_POWER_SMART_INVERTED -#define GPIO_USB1_ILIM_SEL GPIO_USB1_ILIM_SEL_L -#define GPIO_USB2_ILIM_SEL GPIO_USB2_ILIM_SEL_L -#define CONFIG_VBOOT_HASH -#define CONFIG_WIRELESS -#define CONFIG_WIRELESS_SUSPEND \ - (EC_WIRELESS_SWITCH_WLAN | EC_WIRELESS_SWITCH_WLAN_POWER) -/* Do we want EC_WIRELESS_SWITCH_WWAN as well? */ - -#ifndef __ASSEMBLER__ - -/* I2C ports */ -#define I2C_PORT_BACKLIGHT 0 -#define I2C_PORT_BATTERY 0 -#define I2C_PORT_CHARGER 0 -#define I2C_PORT_PD_MCU 0 -#define I2C_PORT_ALS 1 -#define I2C_PORT_ACCEL 1 -#define I2C_PORT_LIGHTBAR 1 -#define I2C_PORT_THERMAL 5 - -/* 13x8 keyboard scanner uses an entire GPIO bank for row inputs */ -#define KB_SCAN_ROW_IRQ LM4_IRQ_GPIOK -#define KB_SCAN_ROW_GPIO LM4_GPIO_K - -/* Host connects to keyboard controller module via LPC */ -#define HOST_KB_BUS_LPC - -/* USB ports managed by the EC */ -#define USB_PORT_COUNT 2 - -#include "gpio_signal.h" - -/* x86 signal definitions */ -enum x86_signal { - X86_PGOOD_PP1050 = 0, - X86_PGOOD_PP1200, - X86_PGOOD_PP1800, - X86_PGOOD_VCORE, - - X86_SLP_S0_DEASSERTED, - X86_SLP_S3_DEASSERTED, - X86_SLP_S5_DEASSERTED, - X86_SLP_SUS_DEASSERTED, - X86_SUSWARN_DEASSERTED, - - /* Number of X86 signals */ - POWER_SIGNAL_COUNT -}; - -enum adc_channel { - /* EC internal die temperature in degrees K. */ - ADC_CH_EC_TEMP = 0, - /* BAT_TEMP */ - ADC_CH_BAT_TEMP, - - ADC_CH_COUNT -}; - -enum pwm_channel { - PWM_CH_KBLIGHT, - - /* Number of PWM channels */ - PWM_CH_COUNT -}; - -enum temp_sensor_id { - /* CPU die temperature via PECI */ - TEMP_SENSOR_CPU_PECI, - /* EC internal temperature sensor */ - TEMP_SENSOR_EC_INTERNAL, - /* TMP006 U40, die/object temperature near battery charger */ - TEMP_SENSOR_I2C_U40_DIE, - TEMP_SENSOR_I2C_U40_OBJECT, - /* TMP006 U41, die/object temperature near CPU */ - TEMP_SENSOR_I2C_U41_DIE, - TEMP_SENSOR_I2C_U41_OBJECT, - /* TMP006 U42, die/object temperature left side of C-case */ - TEMP_SENSOR_I2C_U42_DIE, - TEMP_SENSOR_I2C_U42_OBJECT, - /* TMP006 U43, die/object temperature right side of C-case */ - TEMP_SENSOR_I2C_U43_DIE, - TEMP_SENSOR_I2C_U43_OBJECT, - /* TMP006 U115, die/object temperature right side of D-case */ - TEMP_SENSOR_I2C_U115_DIE, - TEMP_SENSOR_I2C_U115_OBJECT, - /* TMP006 U116, die/object temperature left side of D-case */ - TEMP_SENSOR_I2C_U116_DIE, - TEMP_SENSOR_I2C_U116_OBJECT, - - /* Battery temperature sensor */ - TEMP_SENSOR_BATTERY, - - TEMP_SENSOR_COUNT -}; - -enum sensor_id { - BASE_ACCEL, - LID_ACCEL, - BASE_GYRO, - SENSOR_COUNT, -}; - -/* The number of TMP006 sensor chips on the board. */ -#define TMP006_COUNT 6 - -/* Light sensors attached to the EC. */ -enum als_id { - ALS_ISL29035 = 0, - - ALS_COUNT, -}; - -/* Wireless signals */ -#define WIRELESS_GPIO_WLAN GPIO_WLAN_OFF_L -#define WIRELESS_GPIO_WLAN_POWER GPIO_PP3300_WLAN_EN - -/* Discharge battery when on AC power for factory test. */ -int board_is_discharging_on_ac(void); - -/* Reset PD MCU */ -void board_reset_pd_mcu(void); - -/* Backboost detected interrupt */ -void bkboost_det_interrupt(enum gpio_signal signal); - -/* Interrupt handler for JTAG clock */ -void jtag_interrupt(enum gpio_signal signal); - -/* Bit masks for turning on PP5000 rail in G3 */ -#define PP5000_IN_G3_AC BIT(0) -#define PP5000_IN_G3_LIGHTBAR BIT(1) - -/* Enable/disable PP5000 rail mask in G3 */ -void set_pp5000_in_g3(int mask, int enable); - -/* Define for sensor tasks */ -#define CONFIG_GESTURE_SENSOR_DOUBLE_TAP 0 -#define CONFIG_GESTURE_TAP_OUTER_WINDOW_T 200 -#define CONFIG_GESTURE_TAP_INNER_WINDOW_T 30 -#define CONFIG_GESTURE_TAP_MIN_INTERSTICE_T 120 -#define CONFIG_GESTURE_TAP_MAX_INTERSTICE_T 500 - -#define CONFIG_LID_ANGLE_SENSOR_BASE BASE_ACCEL -#define CONFIG_LID_ANGLE_SENSOR_LID LID_ACCEL - -#endif /* !__ASSEMBLER__ */ - -#endif /* __CROS_EC_BOARD_H */ diff --git a/board/samus/build.mk b/board/samus/build.mk deleted file mode 100644 index 183605fc62..0000000000 --- a/board/samus/build.mk +++ /dev/null @@ -1,16 +0,0 @@ -# -*- makefile -*- -# Copyright 2013 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Board specific files build -# - -# the IC is TI Stellaris LM4 -CHIP:=lm4 - -# Samus has board-specific chipset code, and the tests don't -# compile with it. Disable them for now. -test-list-y= - -board-y=battery.o board.o power_sequence.o panel.o extpower.o diff --git a/board/samus/ec.tasklist b/board/samus/ec.tasklist deleted file mode 100644 index 345892a64b..0000000000 --- a/board/samus/ec.tasklist +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/** - * See CONFIG_TASK_LIST in config.h for details. - */ -#define CONFIG_TASK_LIST \ - TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(ALS, als_task, NULL, TASK_STACK_SIZE) \ - TASK_NOTEST(LIGHTBAR, lightbar_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(CHARGER, charger_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(EXTPOWER, extpower_task, NULL, TASK_STACK_SIZE) \ - TASK_NOTEST(MOTIONSENSE, motion_sense_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ - TASK_NOTEST(PDCMD, pd_command_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(HOSTCMD, host_command_task, NULL, TASK_STACK_SIZE) \ - TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) diff --git a/board/samus/extpower.c b/board/samus/extpower.c deleted file mode 100644 index 22cd13b44d..0000000000 --- a/board/samus/extpower.c +++ /dev/null @@ -1,441 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* - * Pure GPIO-based external power detection, buffered to PCH. - * Drive high in S5-S0 when AC_PRESENT is high, otherwise drive low. - */ - -#include "bq24773.h" -#include "charge_state.h" -#include "charger.h" -#include "chipset.h" -#include "common.h" -#include "console.h" -#include "extpower.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "i2c.h" -#include "system.h" -#include "task.h" -#include "util.h" - -/* Console output macros */ -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) - -/* Max number of attempts to enable/disable NVDC charger */ -#define CHARGER_MODE_ATTEMPTS 3 - -/* Backboost has been detected */ -static int bkboost_detected; - -/* Charging is disabled */ -static int charge_is_disabled; - -/* Extpower task has been initialized */ -static int extpower_task_initialized; - -/* - * Charge circuit occasionally gets wedged and doesn't charge. - * This variable keeps track of the state of the circuit. - */ -static enum { - CHARGE_CIRCUIT_OK, - CHARGE_CIRCUIT_WEDGED, -} charge_circuit_state = CHARGE_CIRCUIT_OK; - -int extpower_is_present(void) -{ - return gpio_get_level(GPIO_AC_PRESENT); -} - -static void extpower_buffer_to_pch(void) -{ - if (chipset_in_state(CHIPSET_STATE_HARD_OFF)) { - /* Drive low in G3 state */ - gpio_set_level(GPIO_PCH_ACOK, 0); - } else { - /* Buffer from extpower in S5+ (where 3.3DSW enabled) */ - gpio_set_level(GPIO_PCH_ACOK, extpower_is_present()); - } -} -DECLARE_HOOK(HOOK_CHIPSET_PRE_INIT, extpower_buffer_to_pch, HOOK_PRIO_DEFAULT); - -static void extpower_shutdown(void) -{ - /* Drive ACOK buffer to PCH low when shutting down */ - gpio_set_level(GPIO_PCH_ACOK, 0); -} -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, extpower_shutdown, HOOK_PRIO_DEFAULT); - -void extpower_interrupt(enum gpio_signal signal) -{ - /* Trigger notification of external power change */ - extpower_buffer_to_pch(); - - /* Wake extpower task only if task has been initialized */ - if (extpower_task_initialized) - task_wake(TASK_ID_EXTPOWER); -} - -static void extpower_init(void) -{ - extpower_buffer_to_pch(); - - /* Enable interrupts, now that we've initialized */ - gpio_enable_interrupt(GPIO_AC_PRESENT); -} -DECLARE_HOOK(HOOK_INIT, extpower_init, HOOK_PRIO_DEFAULT); - -/* - * Save power in S3/S5/G3 by disabling charging when the battery is - * full. Restore charging when battery is not full anymore. This saves - * power because our input AC path is inefficient. - */ - -static void check_charging_cutoff(void) -{ - /* If battery is full disable charging */ - if (charge_get_percent() == 100) { - charge_is_disabled = 1; - host_command_pd_send_status(PD_CHARGE_NONE); - } -} -DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, check_charging_cutoff, HOOK_PRIO_DEFAULT); - -static void cancel_charging_cutoff(void) -{ - /* If charging is disabled, enable it */ - if (charge_is_disabled) { - charge_is_disabled = 0; - host_command_pd_send_status(PD_CHARGE_5V); - } -} -DECLARE_HOOK(HOOK_CHIPSET_RESUME, cancel_charging_cutoff, HOOK_PRIO_DEFAULT); - -static void batt_soc_change(void) -{ - /* If in S0, leave charging alone */ - if (chipset_in_state(CHIPSET_STATE_ON)) { - host_command_pd_send_status(PD_CHARGE_NO_CHANGE); - return; - } - - /* Check to disable or enable charging based on batt state of charge */ - if (!charge_is_disabled && charge_get_percent() == 100) { - host_command_pd_send_status(PD_CHARGE_NONE); - charge_is_disabled = 1; - } else if (charge_is_disabled && charge_get_percent() < 100) { - charge_is_disabled = 0; - host_command_pd_send_status(PD_CHARGE_5V); - } else { - /* Leave charging alone, but update battery SOC */ - host_command_pd_send_status(PD_CHARGE_NO_CHANGE); - } -} -DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, batt_soc_change, HOOK_PRIO_DEFAULT); - -/** - * Enable/disable NVDC charger to control AC to system and battery. - */ -static void charger_disable(int disable) -{ - int i, rv; - - for (i = 0; i < CHARGER_MODE_ATTEMPTS; i++) { - rv = charger_discharge_on_ac(disable); - if (rv == EC_SUCCESS) - return; - } - - CPRINTS("Setting learn mode %d failed!", disable); -} - -static void allow_max_request(void) -{ - int prochot_status; - if (charge_circuit_state == CHARGE_CIRCUIT_WEDGED) { - /* Read PROCHOT status register to clear it */ - i2c_read8(I2C_PORT_CHARGER, BQ24773_ADDR_FLAGS, - BQ24773_PROCHOT_STATUS, &prochot_status); - charge_circuit_state = CHARGE_CIRCUIT_OK; - } - host_command_pd_send_status(PD_CHARGE_MAX); -} -DECLARE_DEFERRED(allow_max_request); - -static void allow_min_charging(void) -{ - if (!charge_is_disabled && charge_circuit_state == CHARGE_CIRCUIT_OK) - host_command_pd_send_status(PD_CHARGE_5V); -} -DECLARE_DEFERRED(allow_min_charging); - -static void extpower_board_hacks(int extpower, int extpower_prev) -{ - /* Cancel deferred attempt to enable max charge request */ - hook_call_deferred(&allow_max_request_data, -1); - - /* - * When AC is detected, delay briefly before allowing PD - * to negotiate up to the max voltage to give charge circuit - * time to settle down. When AC goes away, disable charging - * for a brief time, allowing charge state machine time to - * see AC has gone away, and then set PD to only allow - * 5V charging for the next time AC is connected. - * - * Use NVDC charger learn mode (charger_disable()) when AC - * is not present to avoid backboosting when AC is plugged in. - * - * When in G3, PP5000 needs to be enabled to accurately sense - * CC voltage when AC is attached. When AC is disconnceted - * it needs to be off to save power. - */ - if (extpower && !extpower_prev) { - /* AC connected */ - charger_disable(0); - hook_call_deferred(&allow_max_request_data, 500*MSEC); - set_pp5000_in_g3(PP5000_IN_G3_AC, 1); - } else if (extpower && extpower_prev) { - /* - * Glitch on AC_PRESENT, attempt to recover from - * backboost - */ - host_command_pd_send_status(PD_CHARGE_NONE); - } else { - /* AC disconnected */ - if (!charge_is_disabled && - charge_circuit_state == CHARGE_CIRCUIT_OK) - host_command_pd_send_status(PD_CHARGE_NONE); - - charger_disable(1); - - hook_call_deferred(&allow_min_charging_data, 100*MSEC); - set_pp5000_in_g3(PP5000_IN_G3_AC, 0); - } - extpower_prev = extpower; -} - -/* Return boostin_voltage or negative if error */ -static int get_boostin_voltage(void) -{ - /* Static structs to save stack space */ - static struct ec_response_usb_pd_power_info pd_power_ret; - static struct ec_params_usb_pd_power_info pd_power_args; - int ret; - int err; - - /* Boost-in voltage is maximum of voltage now on each port */ - pd_power_args.port = 0; - err = pd_host_command(EC_CMD_USB_PD_POWER_INFO, 0, - &pd_power_args, - sizeof(struct ec_params_usb_pd_power_info), - &pd_power_ret, - sizeof(struct ec_response_usb_pd_power_info)); - if (err < 0) - return err; - ret = pd_power_ret.meas.voltage_now; - - pd_power_args.port = 1; - err = pd_host_command(EC_CMD_USB_PD_POWER_INFO, 0, - &pd_power_args, - sizeof(struct ec_params_usb_pd_power_info), - &pd_power_ret, - sizeof(struct ec_response_usb_pd_power_info)); - if (err < 0) - return err; - - /* Get max of two measuremente */ - if (pd_power_ret.meas.voltage_now > ret) - ret = pd_power_ret.meas.voltage_now; - - return ret; -} - -/* - * Send command to PD to write a custom persistent log entry indicating that - * charging was wedged. Returns pd_host_command success status. - */ -static int log_charge_wedged(void) -{ - static struct ec_params_pd_write_log_entry log_args; - - log_args.type = PD_EVENT_MCU_BOARD_CUSTOM; - log_args.port = 0; - - return pd_host_command(EC_CMD_PD_WRITE_LOG_ENTRY, 0, - &log_args, - sizeof(struct ec_params_pd_write_log_entry), - NULL, 0); -} - -/* Time interval between checking if charge circuit is wedged */ -#define CHARGE_WEDGE_CHECK_INTERVAL (2*SECOND) - -/* - * Number of iterations through check_charge_wedged() with charging stalled - * before attempting unwedge. - */ -#define CHARGE_STALLED_COUNT 5 -/* - * Number of iterations through check_charge_wedged() with charging stalled - * after we already just tried unwedging the circuit, before we try again. - */ -#define CHARGE_STALLED_REPEATEDLY_COUNT 60 - -/* - * Minimum number of iterations through check_charge_wedged() between - * unwedge attempts. - */ -#define MIN_COUNTS_BETWEEN_UNWEDGES 3 - -static void check_charge_wedged(void) -{ - int rv, prochot_status, batt_discharging_on_ac, boostin_voltage = 0; - static int counts_since_wedged; - static int charge_stalled_count = CHARGE_STALLED_COUNT; - uint8_t *batt_flags = host_get_memmap(EC_MEMMAP_BATT_FLAG); - - if (charge_circuit_state == CHARGE_CIRCUIT_OK) { - /* Check PROCHOT warning */ - rv = i2c_read8(I2C_PORT_CHARGER, BQ24773_ADDR_FLAGS, - BQ24773_PROCHOT_STATUS, &prochot_status); - if (rv) - prochot_status = 0; - - batt_discharging_on_ac = - (*batt_flags & EC_BATT_FLAG_AC_PRESENT) && - (*batt_flags & EC_BATT_FLAG_DISCHARGING); - - /* - * If PROCHOT is set or we are discharging on AC, then we - * need to know boostin_voltage. - */ - if (prochot_status || batt_discharging_on_ac) - boostin_voltage = get_boostin_voltage(); - - /* - * If AC is present, and battery is discharging, and - * boostin voltage is above 5V, then we might be wedged. - */ - if (batt_discharging_on_ac) { - if (boostin_voltage > 6000) - charge_stalled_count--; - else if (boostin_voltage >= 0) - charge_stalled_count = CHARGE_STALLED_COUNT; - /* If boostin_voltage < 0, don't change stalled count */ - } else { - charge_stalled_count = CHARGE_STALLED_COUNT; - } - - /* - * If we were recently wedged, then give ourselves a free pass - * here. This gives an opportunity for reading the PROCHOT - * status to clear it if the error has gone away. - */ - if (counts_since_wedged < MIN_COUNTS_BETWEEN_UNWEDGES) - counts_since_wedged++; - - /* - * If PROCHOT is asserted AND boost_in voltage is above 5V, - * then charge circuit is wedged. If charging has been stalled - * long enough, then also consider the circuit wedged. - * - * To unwedge the charge circuit turn on learn mode and notify - * PD to disable charging on all ports. - * Note: learn mode is critical here because when in this state - * backboosting causes >20V on boostin even after PD disables - * CHARGE_EN lines. - */ - if ((prochot_status && boostin_voltage > 6000 && - counts_since_wedged >= MIN_COUNTS_BETWEEN_UNWEDGES) || - charge_stalled_count <= 0) { - counts_since_wedged = 0; - host_command_pd_send_status(PD_CHARGE_NONE); - charger_disable(1); - charge_circuit_state = CHARGE_CIRCUIT_WEDGED; - log_charge_wedged(); - CPRINTS("Charge wedged! PROCHOT %02x, Stalled: %d", - prochot_status, charge_stalled_count); - - /* - * If this doesn't clear the problem, then start - * the stall counter higher so that we don't retry - * unwedging for a while. Note, if we do start charging - * properly, then stall counter will be set to - * default, so that we will trigger faster the first - * time it stalls out. - */ - charge_stalled_count = CHARGE_STALLED_REPEATEDLY_COUNT; - } - } else { - /* - * Charge circuit is wedged and we already disabled charging, - * Now start to recover from wedged state by allowing 5V. - */ - host_command_pd_send_status(PD_CHARGE_5V); - } -} - -/** - * Task to handle external power change - */ -void extpower_task(void) -{ - int extpower = extpower_is_present(); - int extpower_prev = 0; - - extpower_board_hacks(extpower, extpower_prev); - extpower_prev = extpower; - extpower_task_initialized = 1; - - /* Enable backboost detection interrupt */ - gpio_enable_interrupt(GPIO_BKBOOST_DET); - - while (1) { - if (task_wait_event(CHARGE_WEDGE_CHECK_INTERVAL) == - TASK_EVENT_TIMER) { - /* - * If we are NOT purposely discharging on AC, then - * periodically check if charge circuit is wedged. - */ - if (!board_is_discharging_on_ac()) - check_charge_wedged(); - } else { - /* Must have received power change interrupt */ - extpower = extpower_is_present(); - - /* Various board hacks to run on extpower change */ - extpower_board_hacks(extpower, extpower_prev); - extpower_prev = extpower; - - hook_notify(HOOK_AC_CHANGE); - - /* Forward notification to host */ - if (extpower) - host_set_single_event( - EC_HOST_EVENT_AC_CONNECTED); - else - host_set_single_event( - EC_HOST_EVENT_AC_DISCONNECTED); - } - } -} - -void bkboost_det_interrupt(enum gpio_signal signal) -{ - /* Backboost has been detected, save it, and disable interrupt */ - bkboost_detected = 1; - gpio_disable_interrupt(GPIO_BKBOOST_DET); -} - -static int command_backboost_det(int argc, char **argv) -{ - ccprintf("Backboost detected: %d\n", bkboost_detected); - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(bkboost, command_backboost_det, NULL, - "Read backboost detection"); diff --git a/board/samus/gpio.inc b/board/samus/gpio.inc deleted file mode 100644 index 1b49c58bd0..0000000000 --- a/board/samus/gpio.inc +++ /dev/null @@ -1,122 +0,0 @@ -/* -*- mode:c -*- - * - * Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Declare symbolic names for all the GPIOs that we care about. - * Note: Those with interrupt handlers must be declared first. */ - -GPIO_INT(POWER_BUTTON_L, PIN(A, 2), GPIO_INT_BOTH_DSLEEP, power_button_interrupt) /* Power button */ -GPIO_INT(LID_OPEN, PIN(A, 3), GPIO_INT_BOTH_DSLEEP, lid_interrupt) /* Lid switch */ -GPIO_INT(AC_PRESENT, PIN(H, 3), GPIO_INT_BOTH_DSLEEP, extpower_interrupt) /* AC power present */ -GPIO_INT(PCH_SLP_S0_L, PIN(G, 6), GPIO_INT_BOTH, power_signal_interrupt) /* SLP_S0# signal from PCH */ -GPIO_INT(PCH_SLP_S3_L, PIN(G, 7), GPIO_INT_BOTH_DSLEEP, power_signal_interrupt) /* SLP_S3# signal from PCH */ -GPIO_INT(PCH_SLP_S5_L, PIN(H, 1), GPIO_INT_BOTH_DSLEEP, power_signal_interrupt) /* SLP_S5# signal from PCH */ -GPIO_INT(PCH_SLP_SUS_L, PIN(G, 3), GPIO_INT_BOTH, power_signal_interrupt) /* SLP_SUS# signal from PCH */ -GPIO_INT(PCH_SUSWARN_L, PIN(G, 2), GPIO_INT_BOTH, power_signal_interrupt) /* SUSWARN# signal from PCH */ -GPIO_INT(PP1050_PGOOD, PIN(H, 4), GPIO_INT_BOTH, power_signal_interrupt) /* Power good on 1.05V */ -GPIO_INT(PP1200_PGOOD, PIN(H, 6), GPIO_INT_BOTH, power_signal_interrupt) /* Power good on 1.2V (DRAM) */ -GPIO_INT(PP1800_PGOOD, PIN(L, 7), GPIO_INT_BOTH, power_signal_interrupt) /* Power good on 1.8V (DRAM) */ -GPIO_INT(VCORE_PGOOD, PIN(C, 6), GPIO_INT_BOTH, power_signal_interrupt) /* Power good on core VR */ -GPIO_INT(WP_L, PIN(A, 4), GPIO_INT_BOTH, switch_interrupt) /* Write protect input */ -GPIO_INT(PCH_BL_EN, PIN(M, 3), GPIO_INT_RISING, backlight_interrupt) /* PCH backlight input */ -GPIO_INT(JTAG_TCK, PIN(C, 0), GPIO_DEFAULT, jtag_interrupt) /* JTAG clock input */ -GPIO_INT(UART0_RX, PIN(A, 0), GPIO_PULL_UP | GPIO_INT_BOTH_DSLEEP, uart_deepsleep_interrupt) /* UART0 RX input */ -GPIO_INT(BKBOOST_DET, PIN(B, 5), GPIO_INT_RISING, bkboost_det_interrupt) /* Backboost detect */ - -/* Interrupt signal from PD MCU, external pull-down */ -GPIO_INT(PD_MCU_INT, PIN(J, 5), GPIO_INT_RISING | GPIO_INT_DSLEEP, pd_mcu_interrupt) - -/* - * Combined accelerometer input. This will become an interrupt, once we have - * support for it. - */ -GPIO(ACCEL_INT, PIN(F, 7), GPIO_INPUT) - -/* - * Ambient Light Sensor input. This could become an interrupt once supported. - */ -GPIO(ALS_INT_L, PIN(N, 0), GPIO_INPUT) - -/* Other inputs */ -GPIO(BOARD_VERSION1, PIN(Q, 7), GPIO_INPUT) /* Board version stuffing resistor 1 */ -GPIO(BOARD_VERSION2, PIN(Q, 6), GPIO_INPUT) /* Board version stuffing resistor 2 */ -GPIO(BOARD_VERSION3, PIN(Q, 5), GPIO_INPUT) /* Board version stuffing resistor 3 */ -GPIO(USB1_OC_L, PIN(E, 7), GPIO_INPUT) /* USB port overcurrent warning */ -GPIO(USB1_STATUS_L, PIN(E, 6), GPIO_INPUT) /* USB charger port 1 status output */ -GPIO(USB2_OC_L, PIN(E, 0), GPIO_INPUT) /* USB port overcurrent warning */ -GPIO(USB2_STATUS_L, PIN(D, 7), GPIO_INPUT) /* USB charger port 2 status output */ -GPIO(PD_IN_RW, PIN(A, 5), GPIO_INPUT) /* PD is in RW */ -GPIO(PCH_HDA_SDO_L, PIN(G, 1), GPIO_INPUT) /* HDA_SDO signal to PCH to disable ME */ - -/* Outputs; all unasserted by default except for reset signals */ -GPIO(CPU_PROCHOT, PIN(B, 1), GPIO_OUT_LOW) /* Force CPU to think it's overheated */ -GPIO(PP1200_EN, PIN(H, 5), GPIO_OUT_LOW) /* Enable 1.20V supply */ -GPIO(PP3300_DSW_EN, PIN(F, 6), GPIO_OUT_LOW) /* Enable 3.3V DSW rail */ -GPIO(PP3300_DSW_GATED_EN, PIN(J, 3), GPIO_OUT_LOW) /* Enable 3.3V Gated DSW and core VDD */ -GPIO(PP3300_LTE_EN, PIN(D, 2), GPIO_OUT_LOW) /* Enable LTE radio */ -GPIO(PP3300_WLAN_EN, PIN(J, 0), GPIO_OUT_LOW) /* Enable WiFi power */ -GPIO(PP1050_EN, PIN(C, 7), GPIO_OUT_LOW) /* Enable 1.05V regulator */ -GPIO(PP5000_USB_EN, PIN(C, 5), GPIO_OUT_LOW) /* Enable USB power */ -GPIO(PP5000_EN, PIN(H, 7), GPIO_OUT_LOW) /* Enable 5V supply */ -GPIO(PP1800_EN, PIN(L, 6), GPIO_OUT_LOW) /* Enable 1.8V supply */ -GPIO(SYS_PWROK, PIN(H, 2), GPIO_OUT_LOW) /* EC thinks everything is up and ready */ -GPIO(WLAN_OFF_L, PIN(J, 4), GPIO_OUT_LOW) /* Disable WiFi radio */ -GPIO(USB_MCU_RST, PIN(B, 0), GPIO_OUT_LOW) /* USB PD MCU reset */ -GPIO(ENABLE_BACKLIGHT, PIN(M, 7), GPIO_OUT_LOW) /* Enable backlight power */ -GPIO(ENABLE_TOUCHPAD, PIN(N, 1), GPIO_OUT_LOW) /* Enable touchpad power */ -GPIO(ENTERING_RW, PIN(D, 3), GPIO_OUT_LOW) /* Indicate when EC is entering RW code */ -GPIO(LIGHTBAR_RESET_L, PIN(J, 2), GPIO_ODR_LOW) /* Reset lightbar controllers */ -GPIO(PCH_DPWROK, PIN(G, 0), GPIO_OUT_LOW) /* Indicate when VccDSW is good */ -GPIO(PCH_RSMRST_L, PIN(C, 4), GPIO_OUT_LOW) /* Reset PCH resume power plane logic */ -GPIO(PCH_RTCRST_L, PIN(J, 1), GPIO_ODR_HIGH) /* Reset PCH RTC well */ -GPIO(PCH_WAKE_L, PIN(F, 0), GPIO_ODR_HIGH) /* Wake signal from EC to PCH */ -GPIO(PCH_NMI_L, PIN(F, 2), GPIO_ODR_HIGH) /* Non-maskable interrupt pin to PCH */ -GPIO(PCH_PWRBTN_L, PIN(H, 0), GPIO_ODR_HIGH) /* Power button output to PCH */ -GPIO(PCH_PWROK, PIN(F, 5), GPIO_OUT_LOW) /* PWROK / APWROK signals to PCH */ -GPIO(PCH_RCIN_L, PIN(F, 3), GPIO_ODR_HIGH) /* RCIN# line to PCH (for 8042 emulation) */ -GPIO(PCH_SYS_RST_L, PIN(F, 1), GPIO_ODR_HIGH) /* Reset PCH resume power plane logic */ -GPIO(PCH_SMI_L, PIN(F, 4), GPIO_ODR_HIGH) /* System management interrupt to PCH */ -GPIO(TOUCHSCREEN_RESET_L, PIN(N, 7), GPIO_ODR_LOW) /* Reset touch screen */ -GPIO(PCH_ACOK, PIN(M, 6), GPIO_OUT_LOW) /* AC present signal buffered to PCH */ -#ifndef HEY_USE_BUILTIN_CLKRUN -GPIO(LPC_CLKRUN_L, PIN(M, 2), GPIO_ODR_HIGH) /* Dunno. Probably important, though. */ -#endif -GPIO(USB1_CTL1, PIN(E, 1), GPIO_OUT_LOW) /* USB charger port 1 CTL1 output */ -GPIO(USB1_CTL2, PIN(E, 2), GPIO_OUT_HIGH) /* USB charger port 1 CTL2 output */ -GPIO(USB1_CTL3, PIN(E, 3), GPIO_OUT_LOW) /* USB charger port 1 CTL3 output */ -GPIO(USB1_ENABLE, PIN(E, 4), GPIO_OUT_HIGH) /* USB charger port 1 enable */ -GPIO(USB1_ILIM_SEL_L, PIN(E, 5), GPIO_OUT_HIGH) /* USB charger port 1 ILIM_SEL output */ -GPIO(USB2_CTL1, PIN(D, 0), GPIO_OUT_LOW) /* USB charger port 2 CTL1 output */ -GPIO(USB2_CTL2, PIN(D, 1), GPIO_OUT_HIGH) /* USB charger port 2 CTL2 output */ -GPIO(USB2_CTL3, PIN(D, 4), GPIO_OUT_LOW) /* USB charger port 2 CTL3 output */ -GPIO(USB2_ENABLE, PIN(D, 5), GPIO_OUT_HIGH) /* USB charger port 2 enable */ -GPIO(USB2_ILIM_SEL_L, PIN(D, 6), GPIO_OUT_HIGH) /* USB charger port 2 ILIM_SEL output */ - -GPIO(I2C0_SCL, PIN(B, 2), GPIO_ODR_HIGH) /* I2C port 0 SCL */ -GPIO(I2C0_SDA, PIN(B, 3), GPIO_ODR_HIGH) /* I2C port 0 SDA */ -GPIO(I2C1_SCL, PIN(A, 6), GPIO_ODR_HIGH) /* I2C port 1 SCL */ -GPIO(I2C1_SDA, PIN(A, 7), GPIO_ODR_HIGH) /* I2C port 1 SDA */ -GPIO(I2C5_SCL, PIN(B, 6), GPIO_ODR_HIGH) /* I2C port 5 SCL */ -GPIO(I2C5_SDA, PIN(B, 7), GPIO_ODR_HIGH) /* I2C port 5 SDA */ - -ALTERNATE(PIN_MASK(A, 0x03), 1, MODULE_UART, 0) /* UART0 */ -ALTERNATE(PIN_MASK(A, 0x40), 3, MODULE_I2C, 0) /* I2C1 SCL */ -ALTERNATE(PIN_MASK(A, 0x80), 3, MODULE_I2C, GPIO_OPEN_DRAIN) /* I2C1 SDA */ -ALTERNATE(PIN_MASK(B, 0x04), 3, MODULE_I2C, 0) /* I2C0 SCL */ -ALTERNATE(PIN_MASK(B, 0x08), 3, MODULE_I2C, GPIO_OPEN_DRAIN) /* I2C0 SDA */ -ALTERNATE(PIN_MASK(B, 0x40), 3, MODULE_I2C, 0) /* I2C5 SCL */ -ALTERNATE(PIN_MASK(B, 0x80), 3, MODULE_I2C, GPIO_OPEN_DRAIN) /* I2C5 SDA */ -ALTERNATE(PIN_MASK(G, 0x30), 1, MODULE_UART, 0) /* UART2 */ -ALTERNATE(PIN_MASK(J, 0x40), 1, MODULE_PECI, 0) /* PECI Tx */ -ALTERNATE(PIN_MASK(J, 0x80), 0, MODULE_PECI, GPIO_ANALOG) /* PECI Rx */ -ALTERNATE(PIN_MASK(L, 0x3f), 15, MODULE_LPC, 0) /* LPC */ -ALTERNATE(PIN_MASK(M, 0x33), 15, MODULE_LPC, 0) /* LPC */ -#ifdef HEY_USE_BUILTIN_CLKRUN -ALTERNATE(PIN_MASK(M, 0x04), 15, MODULE_LPC, GPIO_OPEN_DRAIN) /* LPC */ -#endif - -ALTERNATE(PIN_MASK(N, 0x3c), 1, MODULE_PWM, 0) /* FAN0PWM 2&3 */ -ALTERNATE(PIN_MASK(N, 0x40), 1, MODULE_PWM, 0) /* FAN0PWM4 */ diff --git a/board/samus/panel.c b/board/samus/panel.c deleted file mode 100644 index b3fe6060aa..0000000000 --- a/board/samus/panel.c +++ /dev/null @@ -1,195 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "chipset.h" -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "i2c.h" -#include "lid_switch.h" -#include "timer.h" - -#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) - -#define I2C_ADDR_BACKLIGHT_FLAGS (0x2C | I2C_FLAG_BIG_ENDIAN) -#define I2C_RETRIES 3 -#define I2C_RETRY_DELAY (5*MSEC) - -#define LP8555_REG_COMMAND 0x00 -#define LP8555_REG_COMMAND_ON 0x01 -#define LP8555_REG_CONFIG 0x10 -#define LP8555_REG_CONFIG_MODE_MASK 0x03 -#define LP8555_REG_CONFIG_MODE_PWM 0x00 -#define LP8555_REG_CURRENT 0x11 -#define LP8555_REG_CURRENT_MAXCURR_5MA 0x00 -#define LP8555_REG_CURRENT_MAXCURR_10MA 0x01 -#define LP8555_REG_CURRENT_MAXCURR_15MA 0x02 -#define LP8555_REG_CURRENT_MAXCURR_20MA 0x03 -#define LP8555_REG_CURRENT_MAXCURR_23MA 0x04 -#define LP8555_REG_CURRENT_MAXCURR_25MA 0x05 -#define LP8555_REG_CURRENT_MAXCURR_30MA 0x06 -#define LP8555_REG_CURRENT_MAXCURR_50MA 0x07 -#define LP8555_REG_STEP 0x15 -#define LP8555_REG_STEP_STEP_0MS (0 << 0) -#define LP8555_REG_STEP_STEP_8MS BIT(0) -#define LP8555_REG_STEP_STEP_16MS (2 << 0) -#define LP8555_REG_STEP_STEP_24MS (3 << 0) -#define LP8555_REG_STEP_STEP_28MS (4 << 0) -#define LP8555_REG_STEP_STEP_32MS (5 << 0) -#define LP8555_REG_STEP_STEP_100MS (6 << 0) -#define LP8555_REG_STEP_STEP_200MS (7 << 0) -#define LP8555_REG_STEP_PWM_IN_HYST_NONE (0 << 3) -#define LP8555_REG_STEP_PWM_IN_HYST_1LSB BIT(3) -#define LP8555_REG_STEP_PWM_IN_HYST_2LSB (2 << 3) -#define LP8555_REG_STEP_PWM_IN_HYST_4LSB (3 << 3) -#define LP8555_REG_STEP_PWM_IN_HYST_8LSB (4 << 3) -#define LP8555_REG_STEP_PWM_IN_HYST_16LSB (5 << 3) -#define LP8555_REG_STEP_PWM_IN_HYST_32LSB (6 << 3) -#define LP8555_REG_STEP_PWM_IN_HYST_64LSB (7 << 3) -#define LP8555_REG_STEP_SMOOTH_NONE (0 << 6) -#define LP8555_REG_STEP_SMOOTH_LIGHT BIT(6) -#define LP8555_REG_STEP_SMOOTH_MEDIUM (2 << 6) -#define LP8555_REG_STEP_SMOOTH_HEAVY (3 << 6) - -/* Read from lp8555 with automatic i2c retries */ -static int lp8555_read_with_retry(int reg, int *data) -{ - int i, rv; - - for (i = 0; i < I2C_RETRIES; i++) { - rv = i2c_read8(I2C_PORT_BACKLIGHT, - I2C_ADDR_BACKLIGHT_FLAGS, - reg, data); - if (rv == EC_SUCCESS) - return EC_SUCCESS; - usleep(I2C_RETRY_DELAY); - } - - CPRINTS("Backlight read fail: reg 0x%02x", reg); - return rv; -} - -/* Write to lp8555 with automatic i2c retries */ -static int lp8555_write_with_retry(int reg, int data) -{ - int i, rv; - - for (i = 0; i < I2C_RETRIES; i++) { - rv = i2c_write8(I2C_PORT_BACKLIGHT, - I2C_ADDR_BACKLIGHT_FLAGS, - reg, data); - if (rv == EC_SUCCESS) - return EC_SUCCESS; - usleep(I2C_RETRY_DELAY); - } - - CPRINTS("Backlight write fail: reg 0x%02x data %d", reg, data); - return rv; -} - -/** - * Setup backlight controller and turn it on. - */ -static void lp8555_enable_pwm_mode(void) -{ - int reg; - int rv; - - /* - * If not in S0, then PCH backlight enable will not be on, and if - * lid is closed EC backlight enable will not be on. Since these - * two signals are AND'ed together, no point in trying to talk to - * the lp8555 if either one of them is not true. - */ - if (!chipset_in_state(CHIPSET_STATE_ON) || !lid_is_open()) - return; - - /* Enable PWM mode. */ - rv = lp8555_read_with_retry(LP8555_REG_CONFIG, ®); - if (rv != EC_SUCCESS) - return; - reg &= ~LP8555_REG_CONFIG_MODE_MASK; - reg |= LP8555_REG_CONFIG_MODE_PWM; - rv = lp8555_write_with_retry(LP8555_REG_CONFIG, reg); - if (rv != EC_SUCCESS) - return; - - /* Set max LED current to 23mA. */ - rv = lp8555_write_with_retry(LP8555_REG_CURRENT, - LP8555_REG_CURRENT_MAXCURR_23MA); - if (rv != EC_SUCCESS) - return; - - /* Set the rate of brightness change. */ - rv = lp8555_write_with_retry(LP8555_REG_STEP, - LP8555_REG_STEP_STEP_200MS | - LP8555_REG_STEP_PWM_IN_HYST_8LSB | - LP8555_REG_STEP_SMOOTH_HEAVY); - if (rv != EC_SUCCESS) - return; - - /* Power on. */ - rv = lp8555_read_with_retry(LP8555_REG_COMMAND, ®); - if (rv != EC_SUCCESS) - return; - reg |= LP8555_REG_COMMAND_ON; - rv = lp8555_write_with_retry(LP8555_REG_COMMAND, reg); -} -DECLARE_DEFERRED(lp8555_enable_pwm_mode); - -/** - * Host command to toggle backlight. - */ -static enum ec_status -switch_command_enable_backlight(struct host_cmd_handler_args *args) -{ - const struct ec_params_switch_enable_backlight *p = args->params; - - gpio_set_level(GPIO_ENABLE_BACKLIGHT, p->enabled); - - if (p->enabled) - lp8555_enable_pwm_mode(); - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_SWITCH_ENABLE_BKLIGHT, - switch_command_enable_backlight, - EC_VER_MASK(0)); - -void backlight_interrupt(enum gpio_signal signal) -{ - /* - * PCH indicates it is turning on backlight so we should - * attempt to put the backlight controller into PWM mode. - */ - hook_call_deferred(&lp8555_enable_pwm_mode_data, 0); -} - -/** - * Update backlight state. - */ -static void update_backlight(void) -{ - /* - * Enable backlight if lid is open; this is AND'd with the request from - * the AP in hardware. - */ - gpio_set_level(GPIO_ENABLE_BACKLIGHT, lid_is_open()); - if (lid_is_open()) - hook_call_deferred(&lp8555_enable_pwm_mode_data, 0); -} -DECLARE_HOOK(HOOK_LID_CHANGE, update_backlight, HOOK_PRIO_DEFAULT); - -/** - * Initialize backlight module. - */ -static void backlight_init(void) -{ - gpio_enable_interrupt(GPIO_PCH_BL_EN); - gpio_set_level(GPIO_ENABLE_BACKLIGHT, lid_is_open()); -} -DECLARE_HOOK(HOOK_INIT, backlight_init, HOOK_PRIO_DEFAULT); diff --git a/board/samus/power_sequence.c b/board/samus/power_sequence.c deleted file mode 100644 index 20109fe803..0000000000 --- a/board/samus/power_sequence.c +++ /dev/null @@ -1,560 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* X86 chipset power control module for Chrome EC */ - -#include "battery.h" -#include "charge_state.h" -#include "chipset.h" -#include "common.h" -#include "console.h" -#include "extpower.h" -#include "i2c.h" -#include "lb_common.h" -#include "gpio.h" -#include "hooks.h" -#include "lid_switch.h" -#include "power.h" -#include "registers.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "util.h" -#include "wireless.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_CHIPSET, outstr) -#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ## args) - -/* Input state flags */ -#define IN_PGOOD_PP1050 POWER_SIGNAL_MASK(X86_PGOOD_PP1050) -#define IN_PGOOD_PP1200 POWER_SIGNAL_MASK(X86_PGOOD_PP1200) -#define IN_PGOOD_PP1800 POWER_SIGNAL_MASK(X86_PGOOD_PP1800) -#define IN_PGOOD_VCORE POWER_SIGNAL_MASK(X86_PGOOD_VCORE) - -#define IN_PCH_SLP_S0_DEASSERTED POWER_SIGNAL_MASK(X86_SLP_S0_DEASSERTED) -#define IN_PCH_SLP_S3_DEASSERTED POWER_SIGNAL_MASK(X86_SLP_S3_DEASSERTED) -#define IN_PCH_SLP_S5_DEASSERTED POWER_SIGNAL_MASK(X86_SLP_S5_DEASSERTED) -#define IN_PCH_SLP_SUS_DEASSERTED POWER_SIGNAL_MASK(X86_SLP_SUS_DEASSERTED) - - -/* All non-core power rails */ -#define IN_PGOOD_ALL_NONCORE (IN_PGOOD_PP1050) -/* All core power rails */ -#define IN_PGOOD_ALL_CORE (IN_PGOOD_VCORE) -/* Rails required for S3 */ -#define IN_PGOOD_S3 (IN_PGOOD_PP1200) -/* Rails required for S0 */ -#define IN_PGOOD_S0 (IN_PGOOD_ALL_NONCORE) -/* Rails used to detect if PP5000 is up. 1.8V PGOOD is not - * a reliable signal to use here with an internal pullup. */ -#define IN_PGOOD_PP5000 (IN_PGOOD_PP1050 | IN_PGOOD_PP1200) - - -/* All PM_SLP signals from PCH deasserted */ -#define IN_ALL_PM_SLP_DEASSERTED (IN_PCH_SLP_S3_DEASSERTED | \ - IN_PCH_SLP_S5_DEASSERTED | \ - IN_PCH_SLP_SUS_DEASSERTED) - -/* All inputs in the right state for S0 */ -#define IN_ALL_S0 (IN_PGOOD_ALL_NONCORE | IN_PGOOD_ALL_CORE | \ - IN_ALL_PM_SLP_DEASSERTED) - -static int throttle_cpu; /* Throttle CPU? */ -static uint32_t pp5000_in_g3; /* Turn PP5000 on in G3? */ - -void chipset_force_shutdown(enum chipset_shutdown_reason reason) -{ - CPRINTS("%s(%d)", __func__, reason); - report_ap_reset(reason); - - /* - * Force off. This condition will reset once the state machine - * transitions to G3. - */ - gpio_set_level(GPIO_PCH_DPWROK, 0); - gpio_set_level(GPIO_PCH_RSMRST_L, 0); -} - -static void chipset_force_g3(void) -{ - CPRINTS("Forcing G3"); - - gpio_disable_interrupt(GPIO_VCORE_PGOOD); - 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); - /* Disable PP5000 if allowed */ - if (!pp5000_in_g3) - gpio_set_level(GPIO_PP5000_EN, 0); - gpio_set_level(GPIO_PCH_RSMRST_L, 0); - gpio_set_level(GPIO_PCH_DPWROK, 0); - gpio_set_level(GPIO_PP3300_DSW_EN, 0); - wireless_set_state(WIRELESS_OFF); -} - -static void chipset_reset_rtc(void) -{ - /* - * Assert RTCRST# to the PCH long enough for it to latch the - * assertion and reset the internal RTC backed state. - */ - CPRINTS("Asserting RTCRST# to PCH"); - gpio_set_level(GPIO_PCH_RTCRST_L, 0); - udelay(100); - gpio_set_level(GPIO_PCH_RTCRST_L, 1); - udelay(10 * MSEC); -} - -void chipset_reset(enum chipset_reset_reason reason) -{ - CPRINTS("%s(%d)", __func__, reason); - report_ap_reset(reason); - - /* - * Send a RCIN# pulse to the PCH. This just causes it to - * assert INIT# to the CPU without dropping power or asserting - * PLTRST# to reset the rest of the system. - */ - - /* - * Pulse must be at least 16 PCI clocks long = 500 ns. - */ - gpio_set_level(GPIO_PCH_RCIN_L, 0); - udelay(10); - gpio_set_level(GPIO_PCH_RCIN_L, 1); -} - -void chipset_throttle_cpu(int throttle) -{ - if (chipset_in_state(CHIPSET_STATE_ON)) - gpio_set_level(GPIO_CPU_PROCHOT, throttle); -} - -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; -} - -enum power_state power_handle_state(enum power_state state) -{ - struct batt_params batt; - - switch (state) { - case POWER_G3: - break; - - case POWER_S5: - - while ((power_get_signals() & IN_PCH_SLP_S5_DEASSERTED) == 0) { - if (task_wait_event(SECOND*4) == TASK_EVENT_TIMER) { - CPRINTS("timeout waiting for S5 exit"); - /* Put system in G3 and assert RTCRST# */ - chipset_force_g3(); - chipset_reset_rtc(); - /* Try to power back up after RTC reset */ - return POWER_G3S5; - } - } - return POWER_S5S3; /* Power up to next state */ - break; - - case POWER_S3: - /* Check for state transitions */ - if (!power_has_signals(IN_PGOOD_S3)) { - /* Required rail went away */ - chipset_force_shutdown(CHIPSET_SHUTDOWN_POWERFAIL); - return POWER_S3S5; - } else if (gpio_get_level(GPIO_PCH_SLP_S3_L) == 1) { - /* Power up to next state */ - return POWER_S3S0; - } else if (gpio_get_level(GPIO_PCH_SLP_S5_L) == 0) { - /* Power down to next state */ - return POWER_S3S5; - } - break; - - case POWER_S0: - if (!power_has_signals(IN_PGOOD_S0)) { - /* Required rail went away */ - chipset_force_shutdown(CHIPSET_SHUTDOWN_POWERFAIL); - return POWER_S0S3; - } else if (gpio_get_level(GPIO_PCH_SLP_S3_L) == 0) { - /* Power down to next state */ - return POWER_S0S3; - } - break; - - case POWER_G3S5: - /* Return to G3 if battery level is too low */ - if (charge_want_shutdown() || - charge_prevent_power_on(0)) { - CPRINTS("power-up inhibited"); - chipset_force_g3(); - return POWER_G3; - } - - /* Enable 3.3V DSW */ - gpio_set_level(GPIO_PP3300_DSW_EN, 1); - - /* - * Wait 10ms after +3VALW good, since that powers VccDSW and - * VccSUS. - */ - msleep(10); - - /* Enable PP5000 (5V) rail as 1.05V and 1.2V rails need 5V - * rail to regulate properly. */ - gpio_set_level(GPIO_PP5000_EN, 1); - - /* Wait for PP1050/PP1200 PGOOD to go LOW to - * indicate that PP5000 is stable */ - while ((power_get_signals() & IN_PGOOD_PP5000) != 0) { - if (task_wait_event(SECOND) == TASK_EVENT_TIMER) { - CPRINTS("timeout waiting for PP5000"); - chipset_force_g3(); - return POWER_G3; - } - } - - /* - * TODO(crosbug.com/p/31583): Temporary hack to allow booting - * without battery. If battery is not present here, then delay - * to give time for PD MCU to negotiate to 20V. - */ - battery_get_params(&batt); - if (batt.is_present != BP_YES && !system_is_locked()) { - CPRINTS("Attempting boot w/o battery, adding delay"); - msleep(500); - } - - /* Assert DPWROK */ - gpio_set_level(GPIO_PCH_DPWROK, 1); - - /* - * Wait for SLP_SUS before enabling 1.05V rail. - */ - if (power_wait_signals(IN_PCH_SLP_SUS_DEASSERTED)) { - CPRINTS("timeout waiting for SLP_SUS deassert"); - chipset_force_g3(); - return POWER_G3; - } - - /* Enable PP1050 rail. */ - gpio_set_level(GPIO_PP1050_EN, 1); - - /* Wait for 1.05V to come up and CPU to notice */ - if (power_wait_signals(IN_PGOOD_PP1050)) { - CPRINTS("timeout waiting for PP1050"); - chipset_force_g3(); - return POWER_G3; - } - - /* Add 10ms delay between SUSP_VR and RSMRST */ - msleep(10); - - /* Deassert RSMRST# */ - gpio_set_level(GPIO_PCH_RSMRST_L, 1); - - /* Wait 5ms for SUSCLK to stabilize */ - msleep(5); - - /* Call hook to indicate out of G3 state */ - hook_notify(HOOK_CHIPSET_PRE_INIT); - return POWER_S5; - - case POWER_S5S3: - /* Turn on power to RAM */ - gpio_set_level(GPIO_PP1800_EN, 1); - gpio_set_level(GPIO_PP1200_EN, 1); - if (power_wait_signals(IN_PGOOD_S3)) { - gpio_set_level(GPIO_PP1800_EN, 0); - gpio_set_level(GPIO_PP1200_EN, 0); - chipset_force_shutdown(CHIPSET_SHUTDOWN_WAIT); - return POWER_S5; - } - - /* - * Take lightbar out of reset, now that +5VALW is - * available and we won't leak +3VALW through the reset - * line. - */ - i2c_lock(I2C_PORT_LIGHTBAR, 1); - gpio_set_level(GPIO_LIGHTBAR_RESET_L, 1); - msleep(1); - lb_init(0); - msleep(100); - i2c_lock(I2C_PORT_LIGHTBAR, 0); - - /* - * Enable touchpad power so it can wake the system from - * suspend. - */ - gpio_set_level(GPIO_ENABLE_TOUCHPAD, 1); - - /* Turn on USB power rail. */ - gpio_set_level(GPIO_PP5000_USB_EN, 1); - - /* Call hooks now that rails are up */ - hook_notify(HOOK_CHIPSET_STARTUP); - return POWER_S3; - - case POWER_S3S0: - /* Turn on 3.3V DSW gated rail for core regulator */ - gpio_set_level(GPIO_PP3300_DSW_GATED_EN, 1); - - /* Wait 20ms before allowing VCCST_PGOOD to rise. */ - msleep(20); - - /* Enable wireless. */ - wireless_set_state(WIRELESS_ON); - - /* Make sure the touchscreen is on, too. */ - gpio_set_level(GPIO_TOUCHSCREEN_RESET_L, 1); - - /* Wait for non-core power rails good */ - if (power_wait_signals(IN_PGOOD_S0)) { - gpio_set_level(GPIO_TOUCHSCREEN_RESET_L, 0); - wireless_set_state(WIRELESS_OFF); - gpio_set_level(GPIO_PP3300_DSW_GATED_EN, 1); - chipset_force_shutdown(CHIPSET_SHUTDOWN_WAIT); - return POWER_S3; - } - - /* Call hooks now that rails are up */ - hook_notify(HOOK_CHIPSET_RESUME); - - /* - * Disable idle task deep sleep. This means that the low - * power idle task will not go into deep sleep while in S0. - */ - disable_sleep(SLEEP_MASK_AP_RUN); - - /* - * Throttle CPU if necessary. This should only be asserted - * when +VCCP is powered (it is by now). - */ - gpio_set_level(GPIO_CPU_PROCHOT, throttle_cpu); - - /* - * VCORE_PGOOD signal buffer is powered by PP1050_VCCST which - * is gated by SLP_S3 assertion. Now the signal is valid and - * can be enabled as an interrupt source. - */ - gpio_enable_interrupt(GPIO_VCORE_PGOOD); - - /* Set PCH_PWROK */ - gpio_set_level(GPIO_PCH_PWROK, 1); - - /* Wait for VCORE_PGOOD before enabling SYS_PWROK */ - if (power_wait_signals(IN_PGOOD_VCORE)) { - gpio_disable_interrupt(GPIO_VCORE_PGOOD); - hook_notify(HOOK_CHIPSET_SUSPEND); - enable_sleep(SLEEP_MASK_AP_RUN); - gpio_set_level(GPIO_PCH_PWROK, 0); - gpio_set_level(GPIO_CPU_PROCHOT, 0); - gpio_set_level(GPIO_TOUCHSCREEN_RESET_L, 0); - gpio_set_level(GPIO_PP3300_DSW_GATED_EN, 1); - wireless_set_state(WIRELESS_OFF); - chipset_force_shutdown(CHIPSET_SHUTDOWN_WAIT); - return POWER_S3; - } - - /* - * Wait a bit for all voltages to be good. PCIe devices need - * 99ms, but mini-PCIe devices only need 1ms. Intel recommends - * at least 5ms between ALL_SYS_PWRGD and SYS_PWROK. - */ - msleep(5); - - /* Set SYS_PWROK */ - gpio_set_level(GPIO_SYS_PWROK, 1); - return POWER_S0; - - case POWER_S0S3: - /* Call hooks before we remove power rails */ - hook_notify(HOOK_CHIPSET_SUSPEND); - - /* Clear PCH_PWROK */ - gpio_set_level(GPIO_SYS_PWROK, 0); - gpio_set_level(GPIO_PCH_PWROK, 0); - - /* Wait 40ns */ - udelay(1); - - /* Suspend wireless */ - wireless_set_state(WIRELESS_SUSPEND); - - /* - * Enable idle task deep sleep. Allow the low power idle task - * to go into deep sleep in S3 or lower. - */ - enable_sleep(SLEEP_MASK_AP_RUN); - - /* Put touchscreen in reset */ - gpio_set_level(GPIO_TOUCHSCREEN_RESET_L, 0); - - /* - * Deassert prochot since CPU is off and we're about to drop - * +VCCP. - */ - gpio_set_level(GPIO_CPU_PROCHOT, 0); - - /* Turn off DSW gated */ - gpio_set_level(GPIO_PP3300_DSW_GATED_EN, 0); - - /* - * VCORE_PGOOD signal buffer is powered by PP1050_VCCST which - * is gated by SLP_S3 assertion. The signal is no longer - * valid and should be disabled as an interrupt source. - */ - gpio_disable_interrupt(GPIO_VCORE_PGOOD); - return POWER_S3; - - case POWER_S3S5: - /* Call hooks before we remove power rails */ - hook_notify(HOOK_CHIPSET_SHUTDOWN); - - /* Disable wireless */ - wireless_set_state(WIRELESS_OFF); - - /* Disable peripheral power */ - gpio_set_level(GPIO_ENABLE_TOUCHPAD, 0); - gpio_set_level(GPIO_PP5000_USB_EN, 0); - - /* Turn off power to RAM */ - gpio_set_level(GPIO_PP1800_EN, 0); - gpio_set_level(GPIO_PP1200_EN, 0); - - /* - * Put touchscreen and lightbar in reset, so we won't - * leak +3VALW through the reset line to chips powered - * by +5VALW. - * - * (Note that we're no longer powering down +5VALW due - * to crosbug.com/p/16600, but to minimize side effects - * of that change we'll still reset these components in - * S5.) - */ - gpio_set_level(GPIO_TOUCHSCREEN_RESET_L, 0); - gpio_set_level(GPIO_LIGHTBAR_RESET_L, 0); - - return power_get_pause_in_s5() ? POWER_S5 : POWER_S5G3; - - case POWER_S5G3: - /* Deassert DPWROK */ - gpio_set_level(GPIO_PCH_DPWROK, 0); - - /* Assert RSMRST# */ - gpio_set_level(GPIO_PCH_RSMRST_L, 0); - - /* Turn off power rails enabled in S5 */ - gpio_set_level(GPIO_PP1050_EN, 0); - - /* Check if we can disable PP5000 */ - if (!pp5000_in_g3) - gpio_set_level(GPIO_PP5000_EN, 0); - - /* Disable 3.3V DSW */ - gpio_set_level(GPIO_PP3300_DSW_EN, 0); - return POWER_G3; - } - - return state; -} - -/** - * Set PP5000 rail in G3. The mask represents the reason for - * turning on/off the PP5000 rail in G3, and enable either - * enables or disables that mask. If any bit is enabled, then - * the PP5000 rail will remain on. If all bits are cleared, - * the rail will turn off. - * - * @param mask Mask to modify - * @param enable Enable flag - */ -void set_pp5000_in_g3(int mask, int enable) -{ - if (enable) - atomic_or(&pp5000_in_g3, mask); - else - atomic_clear(&pp5000_in_g3, mask); - - /* if we are in G3 now, then set the rail accordingly */ - if (chipset_in_state(CHIPSET_STATE_HARD_OFF)) - gpio_set_level(GPIO_PP5000_EN, !!pp5000_in_g3); -} - -#ifdef CONFIG_LIGHTBAR_POWER_RAILS -/* Returns true if a change was made, NOT the new state */ -int lb_power(int enabled) -{ - int ret = 0; - int pp5000_en = gpio_get_level(GPIO_PP5000_EN); - - set_pp5000_in_g3(PP5000_IN_G3_LIGHTBAR, enabled); - - /* If the AP is on, we don't change the rails. */ - if (!chipset_in_state(CHIPSET_STATE_ANY_OFF)) - return ret; - - /* Check if PP5000 rail changed */ - if (gpio_get_level(GPIO_PP5000_EN) != pp5000_en) - ret = 1; - - /* - * When turning on, we have to wait for the rails to come up - * fully before we the lightbar ICs will respond. There's not - * a reliable PGOOD signal for that (I tried), so we just - * have to wait. These delays seem to work. - * - * Note, we should delay even if the PP5000 rail was already - * enabled because we can't be sure it's been enabled long - * enough for lightbar IC to respond. - * - * Also, the lightbar do not expect other i2c traffic while - * being power up. Put a lock on the i2c bus. - * see chrome-os-partner:45223. - */ - if (enabled) { - i2c_lock(I2C_PORT_LIGHTBAR, 1); - msleep(10); - } - - if (enabled != gpio_get_level(GPIO_LIGHTBAR_RESET_L)) { - ret = 1; - gpio_set_level(GPIO_LIGHTBAR_RESET_L, enabled); - msleep(1); - } - if (enabled) { - lb_init(0); - msleep(100); - i2c_lock(I2C_PORT_LIGHTBAR, 0); - } - - return ret; -} -#endif |