diff options
author | Randall Spangler <rspangler@chromium.org> | 2013-10-16 13:23:10 -0700 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2013-10-23 20:07:25 +0000 |
commit | 8cf03ac0563294fbdeca2dc133d06f0b51c9a546 (patch) | |
tree | 6b07c493e7567a3221d8592b4337d2787d6bc531 /common | |
parent | 2464d08e4d310a3f63208f22df4502c5250c4b58 (diff) | |
download | chrome-ec-8cf03ac0563294fbdeca2dc133d06f0b51c9a546.tar.gz |
Move source files to driver/ and power/ subdirs
The common/ subdir was getting cluttered. Move drivers for external
components to a new driver/ tree, and move what used to be called
chipset_*.c to a new power/ directory.
This does not move/rename header files or CONFIG options. That will
be done in subsequent steps, since moving and modifying .c files in
the same CL is harder to review.
BUG=chrome-os-partner:18343
BRANCH=none
TEST=build all boards; pass unit tests
Change-Id: I67a3003dc8564783a320335cf0e9620a21982d5e
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/173601
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Tested-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-by: Vic Yang <victoryang@chromium.org>
Diffstat (limited to 'common')
-rw-r--r-- | common/battery.c (renamed from common/battery_common.c) | 0 | ||||
-rw-r--r-- | common/battery_bq20z453.c | 37 | ||||
-rw-r--r-- | common/battery_bq27541.c | 219 | ||||
-rw-r--r-- | common/battery_link.c | 131 | ||||
-rw-r--r-- | common/battery_smart.c | 356 | ||||
-rw-r--r-- | common/build.mk | 41 | ||||
-rw-r--r-- | common/charger.c (renamed from common/charger_common.c) | 0 | ||||
-rw-r--r-- | common/charger_bq24192.c | 273 | ||||
-rw-r--r-- | common/charger_bq24707a.c | 167 | ||||
-rw-r--r-- | common/charger_bq24715.c | 192 | ||||
-rw-r--r-- | common/charger_bq24725.c | 166 | ||||
-rw-r--r-- | common/charger_bq24738.c | 188 | ||||
-rw-r--r-- | common/chipset_baytrail.c | 362 | ||||
-rw-r--r-- | common/chipset_gaia.c | 770 | ||||
-rw-r--r-- | common/chipset_haswell.c | 406 | ||||
-rw-r--r-- | common/chipset_ivybridge.c | 344 | ||||
-rw-r--r-- | common/chipset_tegra.c | 601 | ||||
-rw-r--r-- | common/chipset_x86_common.c | 422 | ||||
-rw-r--r-- | common/flash.c (renamed from common/flash_common.c) | 0 | ||||
-rw-r--r-- | common/gpio.c (renamed from common/gpio_common.c) | 0 | ||||
-rw-r--r-- | common/i2c.c (renamed from common/i2c_common.c) | 0 | ||||
-rw-r--r-- | common/led_driver_ds2413.c | 166 | ||||
-rw-r--r-- | common/led_driver_lp5562.c | 161 | ||||
-rw-r--r-- | common/pwm.c (renamed from common/pwm_common.c) | 0 | ||||
-rw-r--r-- | common/regulator_ir357x.c | 247 | ||||
-rw-r--r-- | common/system.c (renamed from common/system_common.c) | 0 | ||||
-rw-r--r-- | common/temp_sensor_g781.c | 210 | ||||
-rw-r--r-- | common/temp_sensor_tmp006.c | 444 | ||||
-rw-r--r-- | common/usb_switch_tsu6721.c | 252 |
29 files changed, 14 insertions, 6141 deletions
diff --git a/common/battery_common.c b/common/battery.c index 25c4bcf1f9..25c4bcf1f9 100644 --- a/common/battery_common.c +++ b/common/battery.c diff --git a/common/battery_bq20z453.c b/common/battery_bq20z453.c deleted file mode 100644 index cda3a7cbdb..0000000000 --- a/common/battery_bq20z453.c +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright (c) 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. - * - * Smart battery driver for BQ20Z453. - */ - -#include "battery_smart.h" -#include "host_command.h" - -#define PARAM_CUT_OFF 0x0010 - -int battery_command_cut_off(struct host_cmd_handler_args *args) -{ - /* - * TODO: Since this is a host command, the i2c bus is claimed by host. - * Thus, we would send back the response in advanced so that - * the host can release the bus and then EC can send command to - * battery. - * - * Refactoring this via task is a way. However, it is wasteful. - * Need a light-weight solution. - */ - args->result = EC_RES_SUCCESS; - host_send_response(args); - - /* This function would try to claim i2c and then send to battery. */ - sb_write(SB_MANUFACTURER_ACCESS, PARAM_CUT_OFF); - - return EC_RES_SUCCESS; - /* - * Not sure if there is a side-effect since this could send result - * back to host TWICE. - */ -} -DECLARE_HOST_COMMAND(EC_CMD_BATTERY_CUT_OFF, battery_command_cut_off, - EC_VER_MASK(0)); diff --git a/common/battery_bq27541.c b/common/battery_bq27541.c deleted file mode 100644 index 3dce19ea54..0000000000 --- a/common/battery_bq27541.c +++ /dev/null @@ -1,219 +0,0 @@ -/* Copyright (c) 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. - * - * Battery driver for BQ27541. - */ - -#include "battery.h" -#include "console.h" -#include "i2c.h" -#include "util.h" - -#define BQ27541_ADDR 0xaa -#define BQ27541_TYPE_ID 0x0541 - -#define REG_CTRL 0x00 -#define REG_AT_RATE 0x02 -#define REG_AT_RATE_TIME_TO_EMPTY 0x04 -#define REG_TEMPERATURE 0x06 -#define REG_VOLTAGE 0x08 -#define REG_FLAGS 0x0a -#define REG_NOMINAL_CAPACITY 0x0c -#define REG_FULL_AVAILABLE_CAPACITY 0x0e -#define REG_REMAINING_CAPACITY 0x10 -#define REG_FULL_CHARGE_CAPACITY 0x12 -#define REG_AVERAGE_CURRENT 0x14 -#define REG_TIME_TO_EMPTY 0x16 -#define REG_TIME_TO_FULL 0x18 -#define REG_STANDBY_CURRENT 0x1a -#define REG_STANDBY_TIME_TO_EMPTY 0x1c -#define REG_MAX_LOAD_CURRENT 0x1e -#define REG_MAX_LOAD_TIME_TO_EMPTY 0x20 -#define REG_AVAILABLE_ENERGY 0x22 -#define REG_AVERAGE_POEWR 0x24 -#define REG_TT_EAT_CONSTANT_POWER 0x26 -#define REG_CYCLE_COUNT 0x2a -#define REG_STATE_OF_CHARGE 0x2c -#define REG_DESIGN_CAPACITY 0x3c -#define REG_DEVICE_NAME_LENGTH 0x62 -#define MAX_DEVICE_NAME_LENGTH 7 -#define REG_DEVICE_NAME 0x63 - -static int bq27541_read(int offset, int *data) -{ - return i2c_read16(I2C_PORT_HOST, BQ27541_ADDR, offset, data); -} - -static int bq27541_read8(int offset, int *data) -{ - return i2c_read8(I2C_PORT_HOST, BQ27541_ADDR, offset, data); -} - -static int bq27541_write(int offset, int data) -{ - return i2c_write16(I2C_PORT_HOST, BQ27541_ADDR, offset, data); -} - -int bq27541_probe(void) -{ - int rv; - int dev_type; - - rv = bq27541_write(REG_CTRL, 0x1); - rv |= bq27541_read(REG_CTRL, &dev_type); - - if (rv) - return rv; - return (dev_type == BQ27541_TYPE_ID) ? EC_SUCCESS : EC_ERROR_UNKNOWN; -} - -int battery_device_name(char *device_name, int buf_size) -{ - int rv, i, val; - int len = MIN(7, buf_size - 1); - - rv = bq27541_read8(REG_DEVICE_NAME_LENGTH, &val); - if (rv) - return rv; - len = MIN(len, val); - - for (i = 0; i < len; ++i) { - rv |= bq27541_read8(REG_DEVICE_NAME + i, &val); - device_name[i] = val; - } - device_name[i] = '\0'; - - return rv; -} - -int battery_temperature(int *deci_kelvin) -{ - return bq27541_read(REG_TEMPERATURE, deci_kelvin); -} - -int battery_voltage(int *voltage) -{ - return bq27541_read(REG_VOLTAGE, voltage); -} - -int battery_state_of_charge(int *percent) -{ - return bq27541_read(REG_STATE_OF_CHARGE, percent); -} - -int battery_state_of_charge_abs(int *percent) -{ - return battery_state_of_charge(percent); -} - -int battery_remaining_capacity(int *capacity) -{ - return bq27541_read(REG_REMAINING_CAPACITY, capacity); -} - -int battery_full_charge_capacity(int *capacity) -{ - return bq27541_read(REG_FULL_CHARGE_CAPACITY, capacity); -} - -int battery_time_to_empty(int *minutes) -{ - return bq27541_read(REG_TIME_TO_EMPTY, minutes); -} - -int battery_time_to_full(int *minutes) -{ - return bq27541_read(REG_TIME_TO_FULL, minutes); -} - -int battery_cycle_count(int *count) -{ - return bq27541_read(REG_CYCLE_COUNT, count); -} - -int battery_design_capacity(int *capacity) -{ - return bq27541_read(REG_DESIGN_CAPACITY, capacity); -} - -int battery_average_current(int *current) -{ - int rv = bq27541_read(REG_AVERAGE_CURRENT, current); - *current = (int)((int16_t)*current); - return rv; -} - -int battery_current(int *current) -{ - return battery_average_current(current); -} - -int battery_time_at_rate(int rate, int *minutes) -{ - int rv; - - rv = bq27541_write(REG_AT_RATE, rate); - if (rv) - return rv; - return bq27541_read(REG_AT_RATE_TIME_TO_EMPTY, minutes); -} - -int battery_manufacturer_name(char *dest, int size) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_device_chemistry(char *dest, int size) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_serial_number(int *serial) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_desired_voltage(int *voltage) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_design_voltage(int *voltage) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_charging_allowed(int *allowed) -{ - int rv, val; - - rv = bq27541_read(REG_FLAGS, &val); - if (rv) - return rv; - *allowed = (val & 0x100); - return EC_SUCCESS; -} - -int battery_desired_current(int *current) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_get_mode(int *mode) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_is_in_10mw_mode(int *val) -{ - /* Always using mAh unit */ - *val = 0; - return EC_SUCCESS; -} - -int battery_set_10mw_mode(int enabled) -{ - /* Not supported by this battery chip */ - return EC_ERROR_INVAL; -} diff --git a/common/battery_link.c b/common/battery_link.c deleted file mode 100644 index a7877529a8..0000000000 --- a/common/battery_link.c +++ /dev/null @@ -1,131 +0,0 @@ -/* Copyright (c) 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.h" - -/* - * Design capacity - * Battery capacity = 8200 mAh - * 1C = 8200 mA - */ -#define DESIGN_CAPACITY 8200 - -enum { - TEMP_RANGE_10, - TEMP_RANGE_23, - TEMP_RANGE_35, - TEMP_RANGE_45, - TEMP_RANGE_50, - TEMP_RANGE_MAX -}; - -enum { - VOLT_RANGE_7200, - VOLT_RANGE_8000, - VOLT_RANGE_8400, - VOLT_RANGE_MAX -}; - -/* - * Vendor provided charging method - * temp : < 7.2V, 7.2V ~ 8.0V, 8.0V ~ 8.4V - * - 0 ~ 10 : 0.8A 1.6A 0.8A - * - 10 ~ 23 : 1.6A 4.0A 1.6A - * - 23 ~ 35 : 4.0A 4.0A 4.0A - * - 35 ~ 45 : 1.6A 4.0A 1.6A - * - 45 ~ 50 : 0.8A 1.6A 0.8A - */ -static const int const current_limit[TEMP_RANGE_MAX][VOLT_RANGE_MAX] = { - { 800, 1600, 800}, - {1600, 4000, 1600}, - {4000, 4000, 4000}, - {1600, 4000, 1600}, - { 800, 1600, 800}, -}; - -const struct battery_temperature_ranges bat_temp_ranges = { - /* - * 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, -}; - -static const struct battery_info info = { - /* - * Design voltage - * max = 8.4V - * normal = 7.4V - * min = 6.0V - */ - .voltage_max = 8400, - .voltage_normal = 7400, - .voltage_min = 6000, - - /* Pre-charge current: I <= 0.01C */ - .precharge_current = 64, /* mA */ -}; - -static inline void limit_value(int *val, int limit) -{ - if (*val > limit) - *val = limit; -} - -const struct battery_info *battery_get_info(void) -{ - return &info; -} - -void battery_vendor_params(struct batt_params *batt) -{ - int *desired_current = &batt->desired_current; - int temp_range, volt_range; - int bat_temp_c = DECI_KELVIN_TO_CELSIUS(batt->temperature); - - /* Limit charging voltage */ - if (batt->desired_voltage > info.voltage_max) - batt->desired_voltage = info.voltage_max; - - /* Don't charge if outside of allowable temperature range */ - if (bat_temp_c >= bat_temp_ranges.charging_max_c || - bat_temp_c < bat_temp_ranges.charging_min_c) { - batt->desired_voltage = 0; - batt->desired_current = 0; - return; - } - - if (bat_temp_c <= 10) - temp_range = TEMP_RANGE_10; - else if (bat_temp_c <= 23) - temp_range = TEMP_RANGE_23; - else if (bat_temp_c <= 35) - temp_range = TEMP_RANGE_35; - else if (bat_temp_c <= 45) - temp_range = TEMP_RANGE_45; - else - temp_range = TEMP_RANGE_50; - - if (batt->voltage < 7200) - volt_range = VOLT_RANGE_7200; - else if (batt->voltage < 8000) - volt_range = VOLT_RANGE_8000; - else - volt_range = VOLT_RANGE_8400; - - limit_value(desired_current, current_limit[temp_range][volt_range]); - - /* If battery wants current, give it at least the precharge current */ - if (*desired_current > 0 && *desired_current < info.precharge_current) - *desired_current = info.precharge_current; -} diff --git a/common/battery_smart.c b/common/battery_smart.c deleted file mode 100644 index 29af6286ad..0000000000 --- a/common/battery_smart.c +++ /dev/null @@ -1,356 +0,0 @@ -/* Copyright (c) 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. - * - * Smart battery driver. - */ - -#include "battery.h" -#include "battery_smart.h" -#include "host_command.h" -#include "i2c.h" -#include "timer.h" - -test_mockable int sbc_read(int cmd, int *param) -{ - return i2c_read16(I2C_PORT_CHARGER, CHARGER_ADDR, cmd, param); -} - -test_mockable int sbc_write(int cmd, int param) -{ - return i2c_write16(I2C_PORT_CHARGER, CHARGER_ADDR, cmd, param); -} - -int sb_read(int cmd, int *param) -{ - return i2c_read16(I2C_PORT_BATTERY, BATTERY_ADDR, cmd, param); -} - -int sb_write(int cmd, int param) -{ - return i2c_write16(I2C_PORT_BATTERY, BATTERY_ADDR, cmd, param); -} - -int battery_get_mode(int *mode) -{ - return sb_read(SB_BATTERY_MODE, mode); -} - -int battery_set_mode(int mode) -{ - return sb_write(SB_BATTERY_MODE, mode); -} - -int battery_is_in_10mw_mode(int *ret) -{ - int val; - int rv = battery_get_mode(&val); - if (rv) - return rv; - *ret = val & MODE_CAPACITY; - return EC_SUCCESS; -} - -int battery_set_10mw_mode(int enabled) -{ - int val, rv; - rv = battery_get_mode(&val); - if (rv) - return rv; - if (enabled) - val |= MODE_CAPACITY; - else - val &= ~MODE_CAPACITY; - return battery_set_mode(val); -} - -int battery_temperature(int *deci_kelvin) -{ - return sb_read(SB_TEMPERATURE, deci_kelvin); -} - -int battery_voltage(int *voltage) -{ - return sb_read(SB_VOLTAGE, voltage); -} - -int battery_state_of_charge(int *percent) -{ - return sb_read(SB_RELATIVE_STATE_OF_CHARGE, percent); -} - -int battery_state_of_charge_abs(int *percent) -{ - return sb_read(SB_ABSOLUTE_STATE_OF_CHARGE, percent); -} - -int battery_remaining_capacity(int *capacity) -{ - return sb_read(SB_REMAINING_CAPACITY, capacity); -} - -int battery_full_charge_capacity(int *capacity) -{ - return sb_read(SB_FULL_CHARGE_CAPACITY, capacity); -} - -int battery_time_to_empty(int *minutes) -{ - return sb_read(SB_AVERAGE_TIME_TO_EMPTY, minutes); -} - -int battery_run_time_to_empty(int *minutes) -{ - return sb_read(SB_RUN_TIME_TO_EMPTY, minutes); -} - -int battery_time_to_full(int *minutes) -{ - return sb_read(SB_AVERAGE_TIME_TO_FULL, minutes); -} - -int battery_desired_current(int *current) -{ - return sb_read(SB_CHARGING_CURRENT, current); -} - -int battery_desired_voltage(int *voltage) -{ - return sb_read(SB_CHARGING_VOLTAGE, voltage); -} - -int battery_charging_allowed(int *allowed) -{ - int v, c, rv; - - /* - * TODO(rspangler): This re-reads the battery current and voltage, - * which is silly because charge_state.c just read them. - */ - rv = battery_desired_voltage(&v) | battery_desired_current(&c); - if (rv) - return rv; - *allowed = (v != 0) && (c != 0); - return EC_SUCCESS; -} - -/* Read battery status */ -int battery_status(int *status) -{ - return sb_read(SB_BATTERY_STATUS, status); -} - -/* Battery charge cycle count */ -int battery_cycle_count(int *count) -{ - return sb_read(SB_CYCLE_COUNT, count); -} - -/* Designed battery capacity - * unit: mAh or 10mW depends on battery mode - */ -int battery_design_capacity(int *capacity) -{ - return sb_read(SB_DESIGN_CAPACITY, capacity); -} - -/* Designed battery output voltage - * unit: mV - */ -int battery_design_voltage(int *voltage) -{ - return sb_read(SB_DESIGN_VOLTAGE, voltage); -} - -/* Read serial number */ -int battery_serial_number(int *serial) -{ - return sb_read(SB_SERIAL_NUMBER, serial); -} - -/* Read battery discharging current - * unit: mA - * negative value: charging - */ -int battery_current(int *current) -{ - int rv, d; - - rv = sb_read(SB_CURRENT, &d); - if (rv) - return rv; - - *current = (int16_t)d; - return EC_SUCCESS; -} - - -int battery_average_current(int *current) -{ - int rv, d; - - rv = sb_read(SB_AVERAGE_CURRENT, &d); - if (rv) - return rv; - - *current = (int16_t)d; - return EC_SUCCESS; -} - -test_mockable int battery_time_at_rate(int rate, int *minutes) -{ - int rv; - int ok, time; - int loop, cmd, output_sign; - - if (rate == 0) { - *minutes = 0; - return EC_ERROR_INVAL; - } - - rv = sb_write(SB_AT_RATE, rate); - if (rv) - return rv; - loop = 5; - while (loop--) { - rv = sb_read(SB_AT_RATE_OK, &ok); - if (rv) - return rv; - if (ok) { - if (rate > 0) { - cmd = SB_AT_RATE_TIME_TO_FULL; - output_sign = -1; - } else { - cmd = SB_AT_RATE_TIME_TO_EMPTY; - output_sign = 1; - } - rv = sb_read(cmd, &time); - if (rv) - return rv; - - *minutes = (time == 0xffff) ? 0 : output_sign * time; - return EC_SUCCESS; - } else { - /* wait 10ms for AT_RATE_OK */ - msleep(10); - } - } - return EC_ERROR_TIMEOUT; -} - -test_mockable int battery_manufacture_date(int *year, int *month, int *day) -{ - int rv; - int ymd; - - rv = sb_read(SB_SPECIFICATION_INFO, &ymd); - if (rv) - return rv; - - /* battery date format: - * ymd = day + month * 32 + (year - 1980) * 256 - */ - *year = (ymd >> 8) + 1980; - *month = (ymd & 0xff) / 32; - *day = (ymd & 0xff) % 32; - - return EC_SUCCESS; -} - -/* Read manufacturer name */ -test_mockable int battery_manufacturer_name(char *dest, int size) -{ - return i2c_read_string(I2C_PORT_BATTERY, BATTERY_ADDR, - SB_MANUFACTURER_NAME, dest, size); -} - -/* Read device name */ -test_mockable int battery_device_name(char *dest, int size) -{ - return i2c_read_string(I2C_PORT_BATTERY, BATTERY_ADDR, - SB_DEVICE_NAME, dest, size); -} - -/* Read battery type/chemistry */ -test_mockable int battery_device_chemistry(char *dest, int size) -{ - return i2c_read_string(I2C_PORT_BATTERY, BATTERY_ADDR, - SB_DEVICE_CHEMISTRY, dest, size); -} - -/*****************************************************************************/ -/* Smart battery pass-through - */ -#ifdef CONFIG_I2C_PASSTHROUGH -static int host_command_sb_read_word(struct host_cmd_handler_args *args) -{ - int rv; - int val; - const struct ec_params_sb_rd *p = args->params; - struct ec_response_sb_rd_word *r = args->response; - - if (p->reg > 0x1c) - return EC_RES_INVALID_PARAM; - rv = i2c_read16(I2C_PORT_BATTERY, BATTERY_ADDR, p->reg, &val); - if (rv) - return EC_RES_ERROR; - - r->value = val; - args->response_size = sizeof(struct ec_response_sb_rd_word); - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_SB_READ_WORD, - host_command_sb_read_word, - EC_VER_MASK(0)); - -static int host_command_sb_write_word(struct host_cmd_handler_args *args) -{ - int rv; - const struct ec_params_sb_wr_word *p = args->params; - - if (p->reg > 0x1c) - return EC_RES_INVALID_PARAM; - rv = i2c_write16(I2C_PORT_BATTERY, BATTERY_ADDR, p->reg, p->value); - if (rv) - return EC_RES_ERROR; - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_SB_WRITE_WORD, - host_command_sb_write_word, - EC_VER_MASK(0)); - -static int host_command_sb_read_block(struct host_cmd_handler_args *args) -{ - int rv; - const struct ec_params_sb_rd *p = args->params; - struct ec_response_sb_rd_block *r = args->response; - - if ((p->reg != SB_MANUFACTURER_NAME) && - (p->reg != SB_DEVICE_NAME) && - (p->reg != SB_DEVICE_CHEMISTRY) && - (p->reg != SB_MANUFACTURER_DATA)) - return EC_RES_INVALID_PARAM; - rv = i2c_read_string(I2C_PORT_BATTERY, BATTERY_ADDR, p->reg, - r->data, 32); - if (rv) - return EC_RES_ERROR; - - args->response_size = sizeof(struct ec_response_sb_rd_block); - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_SB_READ_BLOCK, - host_command_sb_read_block, - EC_VER_MASK(0)); - -static int host_command_sb_write_block(struct host_cmd_handler_args *args) -{ - /* Not implemented */ - return EC_RES_INVALID_COMMAND; -} -DECLARE_HOST_COMMAND(EC_CMD_SB_WRITE_BLOCK, - host_command_sb_write_block, - EC_VER_MASK(0)); -#endif diff --git a/common/build.mk b/common/build.mk index 02d841e9ee..bd1bccdc82 100644 --- a/common/build.mk +++ b/common/build.mk @@ -7,28 +7,20 @@ # common-y=main.o util.o console_output.o uart_buffering.o -common-y+=memory_commands.o shared_mem.o system_common.o hooks.o -common-y+=gpio_common.o version.o printf.o queue.o +common-y+=memory_commands.o shared_mem.o system.o hooks.o +common-y+=gpio.o version.o printf.o queue.o common-y+=throttle_ap.o common-$(CONFIG_BACKLIGHT_LID)+=backlight_lid.o -common-$(CONFIG_BATTERY_BQ20Z453)+=battery_bq20z453.o -common-$(CONFIG_BATTERY_BQ27541)+=battery_common.o battery_bq27541.o -common-$(CONFIG_BATTERY_LINK)+=battery_link.o -common-$(CONFIG_BATTERY_SMART)+=battery_common.o battery_smart.o -common-$(CONFIG_CHARGER)+=charge_state.o charger_common.o -common-$(CONFIG_CHARGER_BQ24192)+=charger_bq24192.o -common-$(CONFIG_CHARGER_BQ24715)+=charger_bq24715.o -common-$(CONFIG_CHARGER_BQ24725)+=charger_bq24725.o -common-$(CONFIG_CHARGER_BQ24707A)+=charger_bq24707a.o -common-$(CONFIG_CHARGER_BQ24738)+=charger_bq24738.o +# TODO(rspangler): Why do these include battery_common but the other batteries +# don't? Perhaps should use CONFIG_CMD_BATTERY instead, since all that's in +# battery.c is the battery console command? +common-$(CONFIG_BATTERY_BQ27541)+=battery.o +common-$(CONFIG_BATTERY_SMART)+=battery.o +common-$(CONFIG_CHARGER)+=charge_state.o charger.o +# TODO(rspangler): This is really the charge state machine for ARM, not the +# charger driver for the tps65090. Rename. common-$(CONFIG_CHARGER_TPS65090)+=pmu_tps65090_charger.o -common-$(CONFIG_CHIPSET_BAYTRAIL)+=chipset_baytrail.o -common-$(CONFIG_CHIPSET_GAIA)+=chipset_gaia.o -common-$(CONFIG_CHIPSET_TEGRA)+=chipset_tegra.o -common-$(CONFIG_CHIPSET_HASWELL)+=chipset_haswell.o -common-$(CONFIG_CHIPSET_IVYBRIDGE)+=chipset_ivybridge.o -common-$(CONFIG_CHIPSET_X86)+=chipset_x86_common.o common-$(CONFIG_PMU_POWERINFO)+=pmu_tps65090_powerinfo.o common-$(CONFIG_PMU_TPS65090)+=pmu_tps65090.o common-$(CONFIG_EOPTION)+=eoption.o @@ -37,33 +29,28 @@ common-$(CONFIG_EXTPOWER_GPIO)+=extpower_gpio.o common-$(CONFIG_EXTPOWER_KIRBY)+=extpower_kirby.o common-$(CONFIG_EXTPOWER_SNOW)+=extpower_snow.o common-$(CONFIG_EXTPOWER_SPRING)+=extpower_spring.o +# TODO(rspangler): Rename to CONFIG_PWM_FAN. common-$(CONFIG_FAN)+=pwm_fan.o -common-$(CONFIG_FLASH)+=flash_common.o +common-$(CONFIG_FLASH)+=flash.o common-$(CONFIG_FMAP)+=fmap.o -common-$(CONFIG_I2C)+=i2c_common.o +common-$(CONFIG_I2C)+=i2c.o common-$(CONFIG_I2C_ARBITRATION)+=i2c_arbitration.o common-$(CONFIG_KEYBOARD_PROTOCOL_8042)+=keyboard_8042.o common-$(CONFIG_KEYBOARD_PROTOCOL_MKBP)+=keyboard_mkbp.o common-$(CONFIG_KEYBOARD_TEST)+=keyboard_test.o common-$(CONFIG_LED_COMMON)+=led_common.o -common-$(CONFIG_LED_DRIVER_DS2413)+=led_driver_ds2413.o -common-$(CONFIG_LED_DRIVER_LP5562)+=led_driver_lp5562.o common-$(CONFIG_LID_SWITCH)+=lid_switch.o common-$(CONFIG_LPC)+=port80.o common-$(CONFIG_ONEWIRE)+=onewire.o common-$(CONFIG_POWER_BUTTON)+=power_button.o common-$(CONFIG_POWER_BUTTON_X86)+=power_button_x86.o common-$(CONFIG_PSTORE)+=pstore_commands.o -common-$(CONFIG_PWM)+=pwm_common.o +common-$(CONFIG_PWM)+=pwm.o common-$(CONFIG_PWM_KBLIGHT)+=pwm_kblight.o -common-$(CONFIG_REGULATOR_IR357X)+=regulator_ir357x.o common-$(CONFIG_SWITCH)+=switch.o common-$(CONFIG_TEMP_SENSOR)+=temp_sensor.o thermal.o -common-$(CONFIG_TEMP_SENSOR_G781)+=temp_sensor_g781.o -common-$(CONFIG_TEMP_SENSOR_TMP006)+=temp_sensor_tmp006.o common-$(CONFIG_USB_PORT_POWER_DUMB)+=usb_port_power_dumb.o common-$(CONFIG_USB_PORT_POWER_SMART)+=usb_port_power_smart.o -common-$(CONFIG_USB_SWITCH_TSU6721)+=usb_switch_tsu6721.o common-$(CONFIG_WIRELESS)+=wireless.o common-$(HAS_TASK_CHIPSET)+=chipset.o common-$(HAS_TASK_CONSOLE)+=console.o diff --git a/common/charger_common.c b/common/charger.c index 15bdf8f73c..15bdf8f73c 100644 --- a/common/charger_common.c +++ b/common/charger.c diff --git a/common/charger_bq24192.c b/common/charger_bq24192.c deleted file mode 100644 index 72f778d367..0000000000 --- a/common/charger_bq24192.c +++ /dev/null @@ -1,273 +0,0 @@ -/* Copyright (c) 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. - * - * TI bq24192 battery charger driver. - */ - -#include "charger.h" -#include "charger_bq24192.h" -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "i2c.h" -#include "printf.h" -#include "util.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_CHARGER, outstr) -#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args) - -/* Charger information */ -static const struct charger_info bq24192_charger_info = { - .name = "bq24192", - .voltage_max = 4400, - .voltage_min = 3504, - .voltage_step = 16, - .current_max = 4544, - .current_min = 512, - .current_step = 64, - .input_current_max = 3000, - .input_current_min = 100, - .input_current_step = -1, -}; - -static const int input_current_steps[] = { - 100, 150, 500, 900, 1200, 1500, 2000, 3000}; - -int bq24192_read(int reg, int *value) -{ - return i2c_read8(I2C_PORT_HOST, BQ24192_ADDR, reg, value); -} - -int bq24192_write(int reg, int value) -{ - return i2c_write8(I2C_PORT_HOST, BQ24192_ADDR, reg, value); -} - -static int bq24192_watchdog_reset(void) -{ - int rv, val; - - rv = bq24192_read(BQ24192_REG_POWER_ON_CFG, &val); - if (rv) - return rv; - val |= (1 << 6); - return bq24192_write(BQ24192_REG_POWER_ON_CFG, val) || - bq24192_write(BQ24192_REG_POWER_ON_CFG, val); -} - -static int bq24192_set_terminate_current(int current) -{ - int reg_val, rv; - int val = (current - 128) / 128; - - rv = bq24192_read(BQ24192_REG_PRE_CHG_CURRENT, ®_val); - if (rv) - return rv; - reg_val = (reg_val & ~0xf) | (val & 0xf); - return bq24192_write(BQ24192_REG_PRE_CHG_CURRENT, reg_val); -} - -int charger_enable_otg_power(int enabled) -{ - int val, rv; - - gpio_set_level(GPIO_BCHGR_OTG, enabled); - rv = bq24192_read(BQ24192_REG_POWER_ON_CFG, &val); - if (rv) - return rv; - val = (val & ~0x30) | (enabled ? 0x20 : 0x10); - return bq24192_write(BQ24192_REG_POWER_ON_CFG, val); -} - -int charger_set_input_current(int input_current) -{ - int i, value, rv; - - for (i = 1; i < ARRAY_SIZE(input_current_steps); ++i) - if (input_current_steps[i] > input_current) { - --i; - break; - } - if (i == ARRAY_SIZE(input_current_steps)) - --i; - - rv = bq24192_read(BQ24192_REG_INPUT_CTRL, &value); - if (rv) - return rv; - value = value & ~(0x7); - value |= (i & 0x7); - return bq24192_write(BQ24192_REG_INPUT_CTRL, value); -} - -int charger_get_input_current(int *input_current) -{ - int rv, value; - - rv = bq24192_read(BQ24192_REG_INPUT_CTRL, &value); - if (rv) - return rv; - *input_current = input_current_steps[value & 0x7]; - return EC_SUCCESS; -} - -int charger_manufacturer_id(int *id) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int charger_device_id(int *id) -{ - return bq24192_read(BQ24192_REG_ID, id); -} - -int charger_get_option(int *option) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int charger_set_option(int option) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -const struct charger_info *charger_get_info(void) -{ - return &bq24192_charger_info; -} - -int charger_get_status(int *status) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int charger_set_mode(int mode) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int charger_get_current(int *current) -{ - int rv, val; - const struct charger_info * const info = charger_get_info(); - - rv = bq24192_read(BQ24192_REG_CHG_CURRENT, &val); - if (rv) - return rv; - val = (val >> 2) & 0x3f; - *current = val * info->current_step + info->current_min; - return EC_SUCCESS; -} - -int charger_set_current(int current) -{ - int rv, val; - const struct charger_info * const info = charger_get_info(); - - current = charger_closest_current(current); - rv = bq24192_read(BQ24192_REG_CHG_CURRENT, &val); - if (rv) - return rv; - val = val & 0x3; - val |= ((current - info->current_min) / info->current_step) << 2; - return bq24192_write(BQ24192_REG_CHG_CURRENT, val); -} - -int charger_get_voltage(int *voltage) -{ - int rv, val; - const struct charger_info * const info = charger_get_info(); - - rv = bq24192_read(BQ24192_REG_CHG_VOLTAGE, &val); - if (rv) - return rv; - val = (val >> 2) & 0x3f; - *voltage = val * info->voltage_step + info->voltage_min; - return EC_SUCCESS; -} - -int charger_set_voltage(int voltage) -{ - int rv, val; - const struct charger_info * const info = charger_get_info(); - - rv = bq24192_read(BQ24192_REG_CHG_VOLTAGE, &val); - if (rv) - return rv; - val = val & 0x3; - val |= ((voltage - info->voltage_min) / info->voltage_step) << 2; - return bq24192_write(BQ24192_REG_CHG_VOLTAGE, val); -} - -/* Charging power state initialization */ -int charger_post_init(void) -{ - /* Input current controlled by extpower module. Do nothing here. */ - return EC_SUCCESS; -} - - -/*****************************************************************************/ -/* Hooks */ - -static void bq24192_init(void) -{ - int val, rv; - - if (charger_device_id(&val) || val != BQ24192_DEVICE_ID) { - CPRINTF("[%T BQ24192 incorrent ID: 0x%02x]\n", val); - return; - } - - /* - * Disable I2C watchdog timer. - * TODO(victoryang): Re-enable watchdog timer and kick it periodically - * in charger task. - */ - rv = bq24192_read(BQ24192_REG_CHG_TERM_TMR, &val); - if (rv) - return; - val &= ~0x30; - rv = bq24192_write(BQ24192_REG_CHG_TERM_TMR, val); - if (rv) - return; - - if (bq24192_set_terminate_current(128)) - return; - - if (bq24192_watchdog_reset()) - return; - - CPRINTF("[%T BQ24192 initialized]\n"); -} -DECLARE_HOOK(HOOK_INIT, bq24192_init, HOOK_PRIO_LAST); - -/*****************************************************************************/ -/* Console commands */ - -static int command_bq24192(int argc, char **argv) -{ - int i; - int value; - int rv; - - ccprintf("REG:"); - for (i = 0; i <= 0xa; ++i) - ccprintf(" %02x", i); - ccprintf("\n"); - - ccprintf("VAL:"); - for (i = 0; i <= 0xa; ++i) { - rv = bq24192_read(i, &value); - if (rv) - return rv; - ccprintf(" %02x", value); - } - ccprintf("\n"); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(bq24192, command_bq24192, - NULL, NULL, NULL); diff --git a/common/charger_bq24707a.c b/common/charger_bq24707a.c deleted file mode 100644 index 43bd32eb91..0000000000 --- a/common/charger_bq24707a.c +++ /dev/null @@ -1,167 +0,0 @@ -/* Copyright (c) 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. - * - * TI bq24707A battery charger driver. - */ - -#include "battery_smart.h" -#include "charger.h" -#include "charger_bq24707a.h" -#include "console.h" -#include "common.h" -#include "util.h" - -/* Sense resistor configurations and macros */ -#define DEFAULT_SENSE_RESISTOR 10 -#define R_SNS CONFIG_CHARGER_SENSE_RESISTOR -#define R_AC CONFIG_CHARGER_SENSE_RESISTOR_AC -#define REG_TO_CURRENT(REG, RS) ((REG) * DEFAULT_SENSE_RESISTOR / (RS)) -#define CURRENT_TO_REG(CUR, RS) ((CUR) * (RS) / DEFAULT_SENSE_RESISTOR) - -/* - * charge voltage bitmask: 0111 1111 1111 0000 - * charge current bitmask: 0001 1111 1100 0000 - * input current bitmask : 0001 1111 1000 0000 - */ -static const struct charger_info bq24707a_charger_info = { - .name = "bq24707A", - .voltage_max = 19200, - .voltage_min = 1024, - .voltage_step = 16, - .current_max = REG_TO_CURRENT(0x1fc0, R_SNS), - .current_min = REG_TO_CURRENT(0x40, R_SNS), - .current_step = REG_TO_CURRENT(0x40, R_SNS), - .input_current_max = REG_TO_CURRENT(0x1F80, R_AC), - .input_current_min = REG_TO_CURRENT(0x80, R_AC), - .input_current_step = REG_TO_CURRENT(0x80, R_AC), -}; - -/* bq24707a specific interfaces */ - -int charger_set_input_current(int input_current) -{ - return sbc_write(BQ24707_INPUT_CURRENT, - CURRENT_TO_REG(input_current, R_AC)); -} - -int charger_get_input_current(int *input_current) -{ - int rv; - int reg; - - rv = sbc_read(BQ24707_INPUT_CURRENT, ®); - if (rv) - return rv; - - *input_current = REG_TO_CURRENT(reg, R_AC); - - return EC_SUCCESS; -} - -int charger_manufacturer_id(int *id) -{ - return sbc_read(BQ24707_MANUFACTURE_ID, id); -} - -int charger_device_id(int *id) -{ - return sbc_read(BQ24707_DEVICE_ID, id); -} - -int charger_get_option(int *option) -{ - return sbc_read(BQ24707_CHARGE_OPTION, option); -} - -int charger_set_option(int option) -{ - return sbc_write(BQ24707_CHARGE_OPTION, option); -} - -/* Charger interfaces */ - -const struct charger_info *charger_get_info(void) -{ - return &bq24707a_charger_info; -} - -int charger_get_status(int *status) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - /* Default status */ - *status = CHARGER_LEVEL_2; - - if (option & OPTION_CHARGE_INHIBIT) - *status |= CHARGER_CHARGE_INHIBITED; - - return EC_SUCCESS; -} - -int charger_set_mode(int mode) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - if (mode & CHARGE_FLAG_INHIBIT_CHARGE) - option |= OPTION_CHARGE_INHIBIT; - else - option &= ~OPTION_CHARGE_INHIBIT; - return charger_set_option(option); -} - -int charger_get_current(int *current) -{ - int rv; - int reg; - - rv = sbc_read(SB_CHARGING_CURRENT, ®); - if (rv) - return rv; - - *current = REG_TO_CURRENT(reg, R_SNS); - return EC_SUCCESS; -} - -int charger_set_current(int current) -{ - current = charger_closest_current(current); - - return sbc_write(SB_CHARGING_CURRENT, CURRENT_TO_REG(current, R_SNS)); -} - -int charger_get_voltage(int *voltage) -{ - return sbc_read(SB_CHARGING_VOLTAGE, voltage); -} - -int charger_set_voltage(int voltage) -{ - return sbc_write(SB_CHARGING_VOLTAGE, voltage); -} - -/* Charging power state initialization */ -int charger_post_init(void) -{ - /* - * Note: bq24725 power on reset state is: - * watch dog timer = 175 sec - * input current limit = ~1/2 maximum setting - * charging voltage = 0 mV - * charging current = 0 mA - * IOUT = 20x adapter current sense - */ - - /* Set charger input current limit */ - return charger_set_input_current(CONFIG_CHARGER_INPUT_CURRENT); -} diff --git a/common/charger_bq24715.c b/common/charger_bq24715.c deleted file mode 100644 index d90b35b021..0000000000 --- a/common/charger_bq24715.c +++ /dev/null @@ -1,192 +0,0 @@ -/* Copyright (c) 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. - * - * TI bq24715 battery charger driver. - */ - -#include "battery_smart.h" -#include "charger.h" -#include "charger_bq24715.h" -#include "console.h" -#include "common.h" -#include "util.h" - -/* Sense resistor configurations and macros */ -#define DEFAULT_SENSE_RESISTOR 10 -#define R_SNS CONFIG_CHARGER_SENSE_RESISTOR -#define R_AC CONFIG_CHARGER_SENSE_RESISTOR_AC -#define REG_TO_CURRENT(REG, RS) ((REG) * DEFAULT_SENSE_RESISTOR / (RS)) -#define CURRENT_TO_REG(CUR, RS) ((CUR) * (RS) / DEFAULT_SENSE_RESISTOR) - -/* Note: it is assumed that the sense resistors are 10mOhm. */ - -static const struct charger_info bq24725_charger_info = { - .name = "bq24715", - .voltage_max = CHARGE_V_MAX, - .voltage_min = CHARGE_V_MIN, - .voltage_step = CHARGE_V_STEP, - .current_max = REG_TO_CURRENT(CHARGE_I_MAX, R_SNS), - .current_min = REG_TO_CURRENT(CHARGE_I_MIN, R_SNS), - .current_step = REG_TO_CURRENT(CHARGE_I_STEP, R_SNS), - .input_current_max = REG_TO_CURRENT(INPUT_I_MAX, R_AC), - .input_current_min = REG_TO_CURRENT(INPUT_I_MIN, R_AC), - .input_current_step = REG_TO_CURRENT(INPUT_I_STEP, R_AC), -}; - -int charger_set_input_current(int input_current) -{ - return sbc_write(BQ24715_INPUT_CURRENT, - CURRENT_TO_REG(input_current, R_AC)); -} - -int charger_get_input_current(int *input_current) -{ - int rv; - int reg; - - rv = sbc_read(BQ24715_INPUT_CURRENT, ®); - if (rv) - return rv; - - *input_current = REG_TO_CURRENT(reg, R_AC); - - return EC_SUCCESS; -} - -int charger_manufacturer_id(int *id) -{ - return sbc_read(BQ24715_MANUFACTURER_ID, id); -} - -int charger_device_id(int *id) -{ - return sbc_read(BQ24715_DEVICE_ID, id); -} - -int charger_get_option(int *option) -{ - return sbc_read(BQ24715_CHARGE_OPTION, option); -} - -int charger_set_option(int option) -{ - return sbc_write(BQ24715_CHARGE_OPTION, option); -} - -/* Charger interfaces */ - -const struct charger_info *charger_get_info(void) -{ - return &bq24725_charger_info; -} - -int charger_get_status(int *status) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - /* Default status */ - *status = CHARGER_LEVEL_2; - - if ((option & OPT_CHARGE_INHIBIT_MASK) == OPT_CHARGE_DISABLE) - *status |= CHARGER_CHARGE_INHIBITED; - - return EC_SUCCESS; -} - -int charger_set_mode(int mode) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - option &= ~OPT_CHARGE_INHIBIT_MASK; - if (mode & CHARGE_FLAG_INHIBIT_CHARGE) - option |= OPT_CHARGE_DISABLE; - else - option |= OPT_CHARGE_ENABLE; - return charger_set_option(option); -} - -int charger_get_current(int *current) -{ - int rv; - int reg; - - rv = sbc_read(SB_CHARGING_CURRENT, ®); - if (rv) - return rv; - - *current = REG_TO_CURRENT(reg, R_SNS); - return EC_SUCCESS; -} - -int charger_set_current(int current) -{ - current = charger_closest_current(current); - - return sbc_write(SB_CHARGING_CURRENT, CURRENT_TO_REG(current, R_SNS)); -} - -/* The voltage setting needs to be cached to work with the current - * charging infrastructure and state machine. The reason is that - * the state machine expects to be able to set a 0V charging voltage. - * The bq24715 does not allow this in the hardware register. Therefore - * 0V is handled specially to appease the state machine. */ -static int cached_voltage; - -int charger_get_voltage(int *voltage) -{ - int ret; - - if (cached_voltage == 0) { - *voltage = cached_voltage; - return EC_SUCCESS; - } - - ret = sbc_read(SB_CHARGING_VOLTAGE, &cached_voltage); - - if (ret == EC_SUCCESS) - *voltage = cached_voltage; - - return ret; -} - -int charger_set_voltage(int voltage) -{ - cached_voltage = voltage; - return sbc_write(SB_CHARGING_VOLTAGE, voltage); -} - -/* Charging power state initialization */ -int charger_post_init(void) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - /* Don't be noisy */ - option |= OPT_AUDIO_FREQ_40KHZ_LIMIT; - - /* Always monitor adapter current (40X multiplier). */ - option |= OPT_FIX_IOUT_ALWAYS; - option &= ~OPT_IOUT_MASK; - - rv = charger_set_option(option); - if (rv) - return rv; - - rv = charger_set_input_current(CONFIG_CHARGER_INPUT_CURRENT); - return rv; -} diff --git a/common/charger_bq24725.c b/common/charger_bq24725.c deleted file mode 100644 index 3e418c7216..0000000000 --- a/common/charger_bq24725.c +++ /dev/null @@ -1,166 +0,0 @@ -/* Copyright (c) 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. - * - * TI bq24725 battery charger driver. - */ - -#include "battery_smart.h" -#include "charger.h" -#include "charger_bq24725.h" -#include "console.h" -#include "common.h" -#include "util.h" - -/* Sense resistor configurations and macros */ -#define DEFAULT_SENSE_RESISTOR 10 -#define R_SNS CONFIG_CHARGER_SENSE_RESISTOR -#define R_AC CONFIG_CHARGER_SENSE_RESISTOR_AC -#define REG_TO_CURRENT(REG, RS) ((REG) * DEFAULT_SENSE_RESISTOR / (RS)) -#define CURRENT_TO_REG(CUR, RS) ((CUR) * (RS) / DEFAULT_SENSE_RESISTOR) - -/* Charger infomation - * charge voltage bitmask: 0111 1111 1111 0000 - * charge current bitmask: 0001 1111 1000 0000 - * input current bitmask : 0000 0000 1000 0000 - */ -static const struct charger_info bq24725_charger_info = { - .name = "bq24725", - .voltage_max = 19200, - .voltage_min = 1024, - .voltage_step = 16, - .current_max = REG_TO_CURRENT(8128, R_SNS), - .current_min = REG_TO_CURRENT(128, R_SNS), - .current_step = REG_TO_CURRENT(128, R_SNS), - .input_current_max = REG_TO_CURRENT(8064, R_AC), - .input_current_min = REG_TO_CURRENT(128, R_AC), - .input_current_step = REG_TO_CURRENT(128, R_AC), -}; - -/* bq24725 specific interfaces */ - -int charger_set_input_current(int input_current) -{ - return sbc_write(BQ24725_INPUT_CURRENT, - CURRENT_TO_REG(input_current, R_AC)); -} - -int charger_get_input_current(int *input_current) -{ - int rv; - int reg; - - rv = sbc_read(BQ24725_INPUT_CURRENT, ®); - if (rv) - return rv; - - *input_current = REG_TO_CURRENT(reg, R_AC); - - return EC_SUCCESS; -} - -int charger_manufacturer_id(int *id) -{ - return sbc_read(BQ24725_MANUFACTURE_ID, id); -} - -int charger_device_id(int *id) -{ - return sbc_read(BQ24725_DEVICE_ID, id); -} - -int charger_get_option(int *option) -{ - return sbc_read(BQ24725_CHARGE_OPTION, option); -} - -int charger_set_option(int option) -{ - return sbc_write(BQ24725_CHARGE_OPTION, option); -} - -/* Charger interfaces */ - -const struct charger_info *charger_get_info(void) -{ - return &bq24725_charger_info; -} - -int charger_get_status(int *status) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - /* Default status */ - *status = CHARGER_LEVEL_2; - - if (option & OPTION_CHARGE_INHIBIT) - *status |= CHARGER_CHARGE_INHIBITED; - - return EC_SUCCESS; -} - -int charger_set_mode(int mode) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - if (mode & CHARGE_FLAG_INHIBIT_CHARGE) - option |= OPTION_CHARGE_INHIBIT; - else - option &= ~OPTION_CHARGE_INHIBIT; - return charger_set_option(option); -} - -int charger_get_current(int *current) -{ - int rv; - int reg; - - rv = sbc_read(SB_CHARGING_CURRENT, ®); - if (rv) - return rv; - - *current = REG_TO_CURRENT(reg, R_SNS); - return EC_SUCCESS; -} - -int charger_set_current(int current) -{ - current = charger_closest_current(current); - - return sbc_write(SB_CHARGING_CURRENT, CURRENT_TO_REG(current, R_SNS)); -} - -int charger_get_voltage(int *voltage) -{ - return sbc_read(SB_CHARGING_VOLTAGE, voltage); -} - -int charger_set_voltage(int voltage) -{ - return sbc_write(SB_CHARGING_VOLTAGE, voltage); -} - -/* Charging power state initialization */ -int charger_post_init(void) -{ - /* - * Note: bq24725 power on reset state is: - * watch dog timer = 175 sec - * input current limit = ~1/2 maximum setting - * charging voltage = 0 mV - * charging current = 0 mA - */ - - /* Set charger input current limit */ - return charger_set_input_current(CONFIG_CHARGER_INPUT_CURRENT); -} diff --git a/common/charger_bq24738.c b/common/charger_bq24738.c deleted file mode 100644 index 057e71c12f..0000000000 --- a/common/charger_bq24738.c +++ /dev/null @@ -1,188 +0,0 @@ -/* Copyright (c) 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. - * - * TI bq24738 battery charger driver. - */ - -#include "battery_smart.h" -#include "charger.h" -#include "charger_bq24738.h" -#include "console.h" -#include "common.h" -#include "util.h" - -/* Sense resistor configurations and macros */ -#define DEFAULT_SENSE_RESISTOR 10 -#define R_SNS CONFIG_CHARGER_SENSE_RESISTOR -#define R_AC CONFIG_CHARGER_SENSE_RESISTOR_AC -#define REG_TO_CURRENT(REG, RS) ((REG) * DEFAULT_SENSE_RESISTOR / (RS)) -#define CURRENT_TO_REG(CUR, RS) ((CUR) * (RS) / DEFAULT_SENSE_RESISTOR) - -/* Charger infomation - * charge voltage bitmask: 0111 1111 1111 0000 - * charge current bitmask: 0001 1111 1100 0000 - * input current bitmask : 0000 0000 1000 0000 - */ -static const struct charger_info bq24738_charger_info = { - .name = "bq24738", - .voltage_max = 19200, - .voltage_min = 1024, - .voltage_step = 16, - .current_max = REG_TO_CURRENT(8128, R_SNS), - .current_min = REG_TO_CURRENT(128, R_SNS), - .current_step = REG_TO_CURRENT(64, R_SNS), - .input_current_max = REG_TO_CURRENT(8064, R_AC), - .input_current_min = REG_TO_CURRENT(128, R_AC), - .input_current_step = REG_TO_CURRENT(128, R_AC), -}; - -/* bq24738 specific interfaces */ - -int charger_set_input_current(int input_current) -{ - return sbc_write(BQ24738_INPUT_CURRENT, - CURRENT_TO_REG(input_current, R_AC)); -} - -int charger_get_input_current(int *input_current) -{ - int rv; - int reg; - - rv = sbc_read(BQ24738_INPUT_CURRENT, ®); - if (rv) - return rv; - - *input_current = REG_TO_CURRENT(reg, R_AC); - - return EC_SUCCESS; -} - -int charger_manufacturer_id(int *id) -{ - return sbc_read(BQ24738_MANUFACTURE_ID, id); -} - -int charger_device_id(int *id) -{ - return sbc_read(BQ24738_DEVICE_ID, id); -} - -int charger_get_option(int *option) -{ - return sbc_read(BQ24738_CHARGE_OPTION, option); -} - -int charger_set_option(int option) -{ - return sbc_write(BQ24738_CHARGE_OPTION, option); -} - -/* Charger interfaces */ - -const struct charger_info *charger_get_info(void) -{ - return &bq24738_charger_info; -} - -int charger_get_status(int *status) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - /* Default status */ - *status = CHARGER_LEVEL_2; - - if (option & OPTION_CHARGE_INHIBIT) - *status |= CHARGER_CHARGE_INHIBITED; - - return EC_SUCCESS; -} - -int charger_set_mode(int mode) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - if (mode & CHARGE_FLAG_INHIBIT_CHARGE) - option |= OPTION_CHARGE_INHIBIT; - else - option &= ~OPTION_CHARGE_INHIBIT; - return charger_set_option(option); -} - -int charger_get_current(int *current) -{ - int rv; - int reg; - - rv = sbc_read(SB_CHARGING_CURRENT, ®); - if (rv) - return rv; - - *current = REG_TO_CURRENT(reg, R_SNS); - return EC_SUCCESS; -} - -int charger_set_current(int current) -{ - current = charger_closest_current(current); - - return sbc_write(SB_CHARGING_CURRENT, CURRENT_TO_REG(current, R_SNS)); -} - -int charger_get_voltage(int *voltage) -{ - return sbc_read(SB_CHARGING_VOLTAGE, voltage); -} - -int charger_set_voltage(int voltage) -{ - return sbc_write(SB_CHARGING_VOLTAGE, voltage); -} - -/* Charging power state initialization */ -int charger_post_init(void) -{ - int rv; - int val; - - /* Disable IFAULT_HI. See crosbug.com/p/19868 */ - rv = charger_get_option(&val); - if (rv) - return rv; - val &= ~OPTION_IFAULT_HI_ENABLE; - rv = charger_set_option(val); - if (rv) - return rv; - - /* Set charger input current limit */ - rv = charger_set_input_current(CONFIG_CHARGER_INPUT_CURRENT); - return rv; -} - -int charger_discharge_on_ac(int enable) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - if (enable) - rv = charger_set_option(option | OPTION_LEARN_ENABLE); - else - rv = charger_set_option(option & ~OPTION_LEARN_ENABLE); - - return rv; -} diff --git a/common/chipset_baytrail.c b/common/chipset_baytrail.c deleted file mode 100644 index 7de5aaac01..0000000000 --- a/common/chipset_baytrail.c +++ /dev/null @@ -1,362 +0,0 @@ -/* Copyright (c) 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 "chipset.h" -#include "chipset_x86_common.h" -#include "common.h" -#include "console.h" -#include "ec_commands.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "lid_switch.h" -#include "system.h" -#include "timer.h" -#include "util.h" -#include "wireless.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_CHIPSET, outstr) -#define CPRINTF(format, args...) cprintf(CC_CHIPSET, format, ## args) - -/* Input state flags */ -#define IN_PGOOD_PP5000 X86_SIGNAL_MASK(X86_PGOOD_PP5000) -#define IN_PGOOD_PP1050 X86_SIGNAL_MASK(X86_PGOOD_PP1050) -#define IN_PGOOD_S5 X86_SIGNAL_MASK(X86_PGOOD_S5) -#define IN_PGOOD_VCORE X86_SIGNAL_MASK(X86_PGOOD_VCORE) -#define IN_PCH_SLP_S3n_DEASSERTED X86_SIGNAL_MASK(X86_PCH_SLP_S3n_DEASSERTED) -#define IN_PCH_SLP_S4n_DEASSERTED X86_SIGNAL_MASK(X86_PCH_SLP_S4n_DEASSERTED) - -/* All always-on supplies */ -#define IN_PGOOD_ALWAYS_ON (IN_PGOOD_S5) -/* All non-core power rails */ -#define IN_PGOOD_ALL_NONCORE (IN_PGOOD_PP5000) -/* All core power rails */ -#define IN_PGOOD_ALL_CORE (IN_PGOOD_VCORE) -/* Rails required for S3 */ -#define IN_PGOOD_S3 (IN_PGOOD_ALWAYS_ON) -/* Rails required for S0 */ -#define IN_PGOOD_S0 (IN_PGOOD_ALWAYS_ON | IN_PGOOD_ALL_NONCORE) - -/* All PM_SLP signals from PCH deasserted */ -#define IN_ALL_PM_SLP_DEASSERTED (IN_PCH_SLP_S3n_DEASSERTED | \ - IN_PCH_SLP_S4n_DEASSERTED) -/* All inputs in the right state for S0 */ -#define IN_ALL_S0 (IN_PGOOD_ALWAYS_ON | IN_PGOOD_ALL_NONCORE | \ - IN_PGOOD_ALL_CORE | IN_ALL_PM_SLP_DEASSERTED) - -static int throttle_cpu; /* Throttle CPU? */ -static int pause_in_s5; /* Pause in S5 when shutting down? */ - -void chipset_force_shutdown(void) -{ - CPRINTF("[%T %s()]\n", __func__); - - /* - * Force x86 off. This condition will reset once the state machine - * transitions to G3. - */ - /* TODO(rspangler): verify this works */ - gpio_set_level(GPIO_PCH_SYS_PWROK, 0); - gpio_set_level(GPIO_PCH_RSMRST_L, 0); -} - -void chipset_reset(int cold_reset) -{ - CPRINTF("[%T %s(%d)]\n", __func__, cold_reset); - if (cold_reset) { - /* - * Drop and restore PWROK. This causes the PCH to reboot, - * regardless of its after-G3 setting. This type of reboot - * causes the PCH to assert PLTRST#, SLP_S3#, and SLP_S5#, so - * we actually drop power to the rest of the system (hence, a - * "cold" reboot). - */ - - /* Ignore if PWROK is already low */ - if (gpio_get_level(GPIO_PCH_SYS_PWROK) == 0) - return; - - /* PWROK must deassert for at least 3 RTC clocks = 91 us */ - gpio_set_level(GPIO_PCH_SYS_PWROK, 0); - udelay(100); - gpio_set_level(GPIO_PCH_SYS_PWROK, 1); - - } else { - /* - * Send a reset 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 x86_state x86_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 ((x86_get_signals() & IN_ALL_S0) == IN_ALL_S0) { - CPRINTF("[%T x86 already in S0]\n"); - return X86_S0; - } else { - /* Force all signals to their G3 states */ - CPRINTF("[%T x86 forcing G3]\n"); - gpio_set_level(GPIO_PCH_CORE_PWROK, 0); - gpio_set_level(GPIO_VCORE_EN, 0); - gpio_set_level(GPIO_SUSP_VR_EN, 0); - gpio_set_level(GPIO_PP1350_EN, 0); - gpio_set_level(GPIO_PP3300_DX_EN, 0); - gpio_set_level(GPIO_PP5000_EN, 0); - gpio_set_level(GPIO_PCH_RSMRST_L, 0); - gpio_set_level(GPIO_PCH_SYS_PWROK, 0); - wireless_enable(0); - } - } - - return X86_G3; -} - -enum x86_state x86_handle_state(enum x86_state state) -{ - switch (state) { - case X86_G3: - break; - - case X86_S5: - if (gpio_get_level(GPIO_PCH_SLP_S4_L) == 1) - return X86_S5S3; /* Power up to next state */ - break; - - case X86_S3: - /* - * If lid is closed; hold touchscreen in reset to cut power - * usage. If lid is open, take touchscreen out of reset so it - * can wake the processor. Chipset task is awakened on lid - * switch transitions. - */ - gpio_set_level(GPIO_TOUCHSCREEN_RESET_L, lid_is_open()); - - /* Check for state transitions */ - if (!x86_has_signals(IN_PGOOD_S3)) { - /* Required rail went away */ - chipset_force_shutdown(); - return X86_S3S5; - } else if (gpio_get_level(GPIO_PCH_SLP_S3_L) == 1) { - /* Power up to next state */ - return X86_S3S0; - } else if (gpio_get_level(GPIO_PCH_SLP_S4_L) == 0) { - /* Power down to next state */ - return X86_S3S5; - } - break; - - case X86_S0: - if (!x86_has_signals(IN_PGOOD_S0)) { - /* Required rail went away */ - chipset_force_shutdown(); - return X86_S0S3; - } else if (gpio_get_level(GPIO_PCH_SLP_S3_L) == 0) { - /* Power down to next state */ - return X86_S0S3; - } - break; - - case X86_G3S5: - /* TODO(rspangler): temporary hack on Rev.1 boards */ - gpio_set_level(GPIO_PP5000_EN, 1); - - /* - * Wait 10ms after +3VALW good, since that powers VccDSW and - * VccSUS. - */ - msleep(10); - - gpio_set_level(GPIO_SUSP_VR_EN, 1); - if (x86_wait_signals(IN_PGOOD_S5)) { - chipset_force_shutdown(); - return X86_G3; - } - - /* Deassert RSMRST# */ - gpio_set_level(GPIO_PCH_RSMRST_L, 1); - - /* Wait 10ms for SUSCLK to stabilize */ - msleep(10); - return X86_S5; - - case X86_S5S3: - /* Wait for the always-on rails to be good */ - if (x86_wait_signals(IN_PGOOD_ALWAYS_ON)) { - chipset_force_shutdown(); - return X86_S5G3; - } - - /* Turn on power to RAM */ - gpio_set_level(GPIO_PP1350_EN, 1); - if (x86_wait_signals(IN_PGOOD_S3)) { - chipset_force_shutdown(); - return X86_S5G3; - } - - /* - * Enable touchpad power so it can wake the system from - * suspend. - */ - gpio_set_level(GPIO_ENABLE_TOUCHPAD, 1); - - /* Call hooks now that rails are up */ - hook_notify(HOOK_CHIPSET_STARTUP); - return X86_S3; - - case X86_S3S0: - /* Turn on power rails */ - gpio_set_level(GPIO_PP5000_EN, 1); - gpio_set_level(GPIO_PP3300_DX_EN, 1); - - /* Enable wireless */ - wireless_enable(EC_WIRELESS_SWITCH_ALL); - - /* - * Make sure touchscreen is out if reset (even if the lid is - * still closed); it may have been turned off if the lid was - * closed in S3. - */ - gpio_set_level(GPIO_TOUCHSCREEN_RESET_L, 1); - - /* Wait for non-core power rails good */ - if (x86_wait_signals(IN_PGOOD_S0)) { - chipset_force_shutdown(); - wireless_enable(0); - gpio_set_level(GPIO_PP3300_DX_EN, 0); - /* TODO(rspangler) turn off PP5000 after Rev.1 */ - gpio_set_level(GPIO_TOUCHSCREEN_RESET_L, 0); - return X86_S3; - } - - /* - * Enable +CPU_CORE. The CPU itself will request the supplies - * when it's ready. - */ - gpio_set_level(GPIO_VCORE_EN, 1); - - /* Call hooks now that rails are up */ - hook_notify(HOOK_CHIPSET_RESUME); - - /* Wait 100ms after all voltages good */ - msleep(100); - - /* - * 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); - - /* Set SYS and CORE PWROK */ - gpio_set_level(GPIO_PCH_SYS_PWROK, 1); - gpio_set_level(GPIO_PCH_CORE_PWROK, 1); - return X86_S0; - - case X86_S0S3: - /* Call hooks before we remove power rails */ - hook_notify(HOOK_CHIPSET_SUSPEND); - - /* Clear SYS and CORE PWROK */ - gpio_set_level(GPIO_PCH_SYS_PWROK, 0); - gpio_set_level(GPIO_PCH_CORE_PWROK, 0); - - /* Wait 40ns */ - udelay(1); - - /* Disable +CPU_CORE */ - gpio_set_level(GPIO_VCORE_EN, 0); - - /* Disable wireless */ - wireless_enable(0); - - /* - * Deassert prochot since CPU is off and we're about to drop - * +VCCP. - */ - gpio_set_level(GPIO_CPU_PROCHOT, 0); - - /* Turn off power rails */ - gpio_set_level(GPIO_PP3300_DX_EN, 0); - /* TODO(rspangler: turn off PP5000 after rev.1 */ - return X86_S3; - - case X86_S3S5: - /* Call hooks before we remove power rails */ - hook_notify(HOOK_CHIPSET_SHUTDOWN); - - /* Disable touchpad power */ - gpio_set_level(GPIO_ENABLE_TOUCHPAD, 0); - - /* Turn off power to RAM */ - gpio_set_level(GPIO_PP1350_EN, 0); - - /* Start shutting down */ - return pause_in_s5 ? X86_S5 : X86_S5G3; - - case X86_S5G3: - /* Assert RSMRST# */ - gpio_set_level(GPIO_PCH_RSMRST_L, 0); - gpio_set_level(GPIO_SUSP_VR_EN, 0); - - /* TODO(rspangler): temporary hack on rev.1 boards */ - gpio_set_level(GPIO_PP5000_EN, 0); - - return X86_G3; - } - - return state; -} - -static int host_command_gsv(struct host_cmd_handler_args *args) -{ - const struct ec_params_get_set_value *p = args->params; - struct ec_response_get_set_value *r = args->response; - - if (p->flags & EC_GSV_SET) - pause_in_s5 = p->value; - - r->value = pause_in_s5; - - args->response_size = sizeof(*r); - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_GSV_PAUSE_IN_S5, - host_command_gsv, - EC_VER_MASK(0)); - -static int console_command_gsv(int argc, char **argv) -{ - if (argc > 1 && !parse_bool(argv[1], &pause_in_s5)) - return EC_ERROR_INVAL; - - ccprintf("pause_in_s5 = %s\n", pause_in_s5 ? "on" : "off"); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(pause_in_s5, console_command_gsv, - "[on|off]", - "Should the AP pause in S5 during shutdown?", - NULL); - diff --git a/common/chipset_gaia.c b/common/chipset_gaia.c deleted file mode 100644 index fd5d5fb7a6..0000000000 --- a/common/chipset_gaia.c +++ /dev/null @@ -1,770 +0,0 @@ -/* Copyright (c) 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. - */ - -/* - * GAIA SoC power sequencing module for Chrome EC - * - * This implements the following features: - * - * - Cold reset powers off the AP - * - * When powered off: - * - Press pwron turns on the AP - * - Hold pwron turns on the AP, and then 16s later turns it off and leaves - * it off until pwron is released and pressed again - * - * When powered on: - * - The PMIC PWRON signal is released <= 1 second after the power button is - * released (we expect that U-Boot as asserted XPSHOLD by then) - * - Holding pwron for 8s powers off the AP - * - Pressing and releasing pwron within that 8s is ignored - * - If XPSHOLD is dropped by the AP, then we power the AP off - */ - -#include "clock.h" -#include "chipset.h" /* This module implements chipset functions too */ -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "lid_switch.h" -#include "keyboard_scan.h" -#include "power_led.h" -#include "pmu_tpschrome.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_CHIPSET, outstr) -#define CPRINTF(format, args...) cprintf(CC_CHIPSET, format, ## args) - -/* Time necessary for the 5V and 3.3V regulator outputs to stabilize */ -#if defined(BOARD_pit) || defined(BOARD_puppy) -#define DELAY_5V_SETUP (2 * MSEC) -#define DELAY_3V_SETUP (2 * MSEC) -#else -#define DELAY_5V_SETUP MSEC -#endif - -/* Delay between PMIC_PWRON and enabling 3.3V */ -#ifdef BOARD_kirby -#define DELAY_PRE_3V_ENABLE 16620 -#endif - -/* Delay between 1.35v and 3.3v rails startup */ -#define DELAY_RAIL_STAGGERING 100 /* 100us */ - -/* Long power key press to force shutdown */ -#define DELAY_FORCE_SHUTDOWN (8 * SECOND) - -/* Time necessary for pulling down XPSHOLD to shutdown PMIC power */ -#define DELAY_XPSHOLD_PULL (2 * MSEC) - -/* - * If the power key is pressed to turn on, then held for this long, we - * power off. - * - * The idea here is that behavior for 8s for AP shutdown is unchanged - * but power-on is modified to allow enough time U-Boot to be updated - * via USB (which takes about 10sec). - * - * So after power button is pressed: - - * Normal case: User releases power button and chipset_task() goes - * into the inner loop, waiting for next event to occur (power button - * press or XPSHOLD == 0). - * - * U-Boot updating: User presses and holds power button. If EC does not - * see XPSHOLD, it waits up to 16sec for an event. If no event occurs - * within 16sec, EC powers off AP. - */ -#define DELAY_SHUTDOWN_ON_POWER_HOLD (8 * SECOND) -#define DELAY_SHUTDOWN_ON_USB_BOOT (16 * SECOND) - -/* Maximum delay after power button press before we deassert GPIO_PMIC_PWRON */ -#define DELAY_RELEASE_PWRON SECOND /* 1s */ - -/* debounce time to prevent accidental power-on after keyboard power off */ -#define KB_PWR_ON_DEBOUNCE 250 /* 250us */ - -/* debounce time to prevent accidental power event after lid open/close */ -#define LID_SWITCH_DEBOUNCE 250 /* 250us */ - -/* PMIC fails to set the LDO2 output */ -#define PMIC_TIMEOUT (100 * MSEC) /* 100ms */ - -/* Default timeout for input transition */ -#define FAIL_TIMEOUT (500 * MSEC) /* 500ms */ - - -/* Application processor power state */ -static int ap_on; -static int ap_suspended; - -/* simulated event state */ -static int force_signal = -1; -static int force_value; - -/* 1 if the power button was pressed last time we checked */ -static char power_button_was_pressed; - -/* 1 if lid-open event has been detected */ -static char lid_opened; - -/* time where we will power off, if power button still held down */ -static timestamp_t power_off_deadline; - -/* force AP power on (used for recovery keypress) */ -static int auto_power_on; - -enum power_request_t { - POWER_REQ_NONE, - POWER_REQ_OFF, - POWER_REQ_ON, - - POWER_REQ_COUNT, -}; - -static enum power_request_t power_request; - -/** - * Wait for GPIO "signal" to reach level "value". - * Returns EC_ERROR_TIMEOUT if timeout before reaching the desired state. - * - * @param signal Signal to watch - * @param value Value to watch for - * @param timeout Timeout in microseconds from now, or -1 to wait forever - * @return 0 if signal did change to required value, EC_ERROR_TIMEOUT if we - * timed out first. - */ -static int wait_in_signal(enum gpio_signal signal, int value, int timeout) -{ - timestamp_t deadline; - timestamp_t now = get_time(); - - deadline.val = now.val + timeout; - - while (((force_signal != signal) || (force_value != value)) && - gpio_get_level(signal) != value) { - now = get_time(); - if (timeout < 0) { - task_wait_event(-1); - } else if (timestamp_expired(deadline, &now) || - (task_wait_event(deadline.val - now.val) == - TASK_EVENT_TIMER)) { - CPRINTF("[%T power timeout waiting for GPIO %d/%s]\n", - signal, gpio_get_name(signal)); - return EC_ERROR_TIMEOUT; - } - } - - return EC_SUCCESS; -} - -/** - * Set the PMIC PWROK signal. - * - * @param asserted Assert (=1) or deassert (=0) the signal. This is the - * logical level of the pin, not the physical level. - */ -static void set_pmic_pwrok(int asserted) -{ -#if defined(BOARD_pit) || defined(BOARD_kirby) - /* Signal is active-high */ - gpio_set_level(GPIO_PMIC_PWRON, asserted); -#else - /* Signal is active-low */ - gpio_set_level(GPIO_PMIC_PWRON_L, asserted ? 0 : 1); -#endif -} - - -/** - * Check for some event triggering the shutdown. - * - * It can be either a long power button press or a shutdown triggered from the - * AP and detected by reading XPSHOLD. - * - * @return 1 if a shutdown should happen, 0 if not - */ -static int check_for_power_off_event(void) -{ - timestamp_t now; - int pressed = 0; - - /* Check for power button press */ - if (gpio_get_level(GPIO_KB_PWR_ON_L) == 0) { - udelay(KB_PWR_ON_DEBOUNCE); - if (gpio_get_level(GPIO_KB_PWR_ON_L) == 0) - pressed = 1; - } - -#ifdef HAS_TASK_KEYSCAN - /* Dis/Enable keyboard scanning when the power button state changes */ - if (!pressed || pressed != power_button_was_pressed) - keyboard_scan_enable(!pressed); -#endif - - - now = get_time(); - if (pressed) { - set_pmic_pwrok(1); - - if (!power_button_was_pressed) { - power_off_deadline.val = now.val + DELAY_FORCE_SHUTDOWN; - CPRINTF("[%T power waiting for long press %u]\n", - power_off_deadline.le.lo); - } else if (timestamp_expired(power_off_deadline, &now)) { - power_off_deadline.val = 0; - CPRINTF("[%T power off after long press now=%u, %u]\n", - now.le.lo, power_off_deadline.le.lo); - return 2; - } - } else if (power_button_was_pressed) { - CPRINTF("[%T power off cancel]\n"); - set_pmic_pwrok(0); - } - - power_button_was_pressed = pressed; - - /* XPSHOLD released by AP : shutdown immediately */ - if (gpio_get_level(GPIO_SOC1V8_XPSHOLD) == 0) - return 3; - - if (power_request == POWER_REQ_OFF) { - power_request = POWER_REQ_NONE; - return 4; - } - - return 0; -} - -/** - * Deferred handling for suspend events - * - * The suspend event needs to be able to call the suspend and resume hooks. - * This cannot be done from interrupt level, since the handlers from those - * hooks may need to use mutexes or other functionality not present at - * interrupt level. Use a deferred function instead. - * - * Deferred functions are called from the hook task and not the chipset task, - * so that's a slight deviation from the spec in hooks.h, but a minor one. - */ -static void gaia_suspend_deferred(void) -{ - int new_ap_suspended; - - if (!ap_on) /* power on/off : not a real suspend / resume */ - return; - - /* - * Note: For Snow, suspend state can only be reliably - * determined when the AP is on (crosbug.com/p/13200). - */ - new_ap_suspended = !gpio_get_level(GPIO_SUSPEND_L); - - /* We never want to call two suspend or two resumes in a row */ - if (ap_suspended == new_ap_suspended) - return; - - ap_suspended = new_ap_suspended; - - if (ap_suspended) { - if (lid_is_open()) - powerled_set_state(POWERLED_STATE_SUSPEND); - else - powerled_set_state(POWERLED_STATE_OFF); - /* Call hooks here since we don't know it prior to AP suspend */ - hook_notify(HOOK_CHIPSET_SUSPEND); - } else { - powerled_set_state(POWERLED_STATE_ON); - hook_notify(HOOK_CHIPSET_RESUME); - } - -} -DECLARE_DEFERRED(gaia_suspend_deferred); - -void power_interrupt(enum gpio_signal signal) -{ - if (signal == GPIO_SUSPEND_L) { - /* Handle suspend events in the hook task */ - hook_call_deferred(gaia_suspend_deferred, 0); - } else { - /* All other events are handled in the chipset task */ - task_wake(TASK_ID_CHIPSET); - } -} - -static void gaia_lid_event(void) -{ - /* Power task only cares about lid-open events */ - if (!lid_is_open()) - return; - - lid_opened = 1; - task_wake(TASK_ID_CHIPSET); -} -DECLARE_HOOK(HOOK_LID_CHANGE, gaia_lid_event, HOOK_PRIO_DEFAULT); - -static int gaia_power_init(void) -{ - /* Enable interrupts for our GPIOs */ - gpio_enable_interrupt(GPIO_KB_PWR_ON_L); - gpio_enable_interrupt(GPIO_SOC1V8_XPSHOLD); - gpio_enable_interrupt(GPIO_SUSPEND_L); -#ifndef BOARD_kirby - gpio_enable_interrupt(GPIO_PP1800_LDO2); -#endif - - /* Leave power off only if requested by reset flags */ - if (!(system_get_reset_flags() & RESET_FLAG_AP_OFF)) { - CPRINTF("[%T auto_power_on is set due to reset_flag 0x%x]\n", - system_get_reset_flags()); - auto_power_on = 1; - } - -#ifdef BOARD_pit - /* - * Force the AP into reset unless we're doing a sysjump. Otherwise a - * suspended AP may still be in a strange state from the last reboot, - * and will hold XPSHOLD for a long time if it's in a low power state. - * See crosbug.com/p/22233. - */ - if (!(system_get_reset_flags() & RESET_FLAG_SYSJUMP)) { - CPRINTF("[%T not sysjump; forcing AP reset]\n"); - gpio_set_level(GPIO_AP_RESET_L, 0); - udelay(1000); - gpio_set_level(GPIO_AP_RESET_L, 1); - } -#endif - - return EC_SUCCESS; -} - - -/*****************************************************************************/ -/* Chipset interface */ - -int chipset_in_state(int state_mask) -{ - /* If AP is off, match any off state for now */ - if ((state_mask & CHIPSET_STATE_ANY_OFF) && !ap_on) - return 1; - - /* If AP is on, match on state */ - if ((state_mask & CHIPSET_STATE_ON) && ap_on && !ap_suspended) - return 1; - - /* if AP is suspended, match on state */ - if ((state_mask & CHIPSET_STATE_SUSPEND) && ap_on && ap_suspended) - return 1; - - /* In any other case, we don't have a match */ - return 0; -} - -void chipset_exit_hard_off(void) -{ - /* TODO: implement, if/when we take the AP down to a hard-off state */ -} - -void chipset_reset(int is_cold) -{ - /* TODO: implement cold reset. For now, all resets are warm resets. */ - CPRINTF("[%T EC triggered warm reboot]\n"); - - /* - * This is a hack to do an AP warm reboot while still preserving RAM - * contents. This is useful for looking at kernel log message contents - * from previous boot in cases where the AP/OS is hard hung. - */ -#ifdef CONFIG_CHIPSET_HAS_PP5000 - gpio_set_level(GPIO_EN_PP5000, 0); -#endif - gpio_set_level(GPIO_EN_PP3300, 0); - - power_request = POWER_REQ_ON; - task_wake(TASK_ID_CHIPSET); -} - -void chipset_force_shutdown(void) -{ -#ifdef BOARD_kirby - gpio_set_flags(GPIO_SOC1V8_XPSHOLD, GPIO_ODR_LOW); - udelay(DELAY_XPSHOLD_PULL); - gpio_set_flags(GPIO_SOC1V8_XPSHOLD, GPIO_INT_RISING | GPIO_INPUT); -#endif - - /* Turn off all rails */ - gpio_set_level(GPIO_EN_PP3300, 0); -#ifdef CONFIG_CHIPSET_HAS_PP1350 - /* - * Turn off PP1350 unless we're immediately waking back up. This - * works with the hack in chipset_reset() to preserve the contents of - * RAM across a reset. - */ - if (power_request != POWER_REQ_ON) - gpio_set_level(GPIO_EN_PP1350, 0); -#endif - set_pmic_pwrok(0); -#ifdef CONFIG_CHIPSET_HAS_PP5000 - gpio_set_level(GPIO_EN_PP5000, 0); -#endif - -#ifdef BOARD_pit - /* - * Force the AP into reset. Otherwise it will hold XPSHOLD for a long - * time if it's in a low power state. See crosbug.com/p/22233. - */ - gpio_set_level(GPIO_AP_RESET_L, 0); - udelay(1000); - gpio_set_level(GPIO_AP_RESET_L, 1); -#endif -} - -/*****************************************************************************/ - -/** - * Check if there has been a power-on event - * - * This checks all power-on event signals and returns non-zero if any have been - * triggered (with debounce taken into account). - * - * @return non-zero if there has been a power-on event, 0 if not. - */ -static int check_for_power_on_event(void) -{ - /* the system is already ON */ - /* TODO: this isn't the right check for pit */ - if (gpio_get_level(GPIO_EN_PP3300)) { - CPRINTF("[%T system is on, thus clear auto_power_on]\n"); - auto_power_on = 0; /* no need to arrange another power on */ - return 1; - } - - /* power on requested at EC startup for recovery */ - if (auto_power_on) { - auto_power_on = 0; - return 2; - } - - /* Check lid open */ - if (lid_opened) { - lid_opened = 0; - return 3; - } - - /* check for power button press */ - if (gpio_get_level(GPIO_KB_PWR_ON_L) == 0) { - udelay(KB_PWR_ON_DEBOUNCE); - if (gpio_get_level(GPIO_KB_PWR_ON_L) == 0) - return 4; - } - - if (power_request == POWER_REQ_ON) { - power_request = POWER_REQ_NONE; - return 5; - } - - return 0; -} - -/** - * Power on the AP - * - * @return 0 if ok, -1 on error (PP1800_LDO2 failed to come on) - */ -static int power_on(void) -{ -#ifdef CONFIG_CHIPSET_HAS_PP5000 - /* Enable 5v power rail */ - gpio_set_level(GPIO_EN_PP5000, 1); - /* Wait for it to stabilize */ - usleep(DELAY_5V_SETUP); -#endif - -#if defined(BOARD_pit) || defined(BOARD_puppy) - /* - * 3.3V rail must come up right after 5V, because it sources power to - * various buck supplies. - */ - gpio_set_level(GPIO_EN_PP3300, 1); - usleep(DELAY_3V_SETUP); -#endif - if (gpio_get_level(GPIO_SOC1V8_XPSHOLD) == 0) { - /* Initialize non-AP components */ - hook_notify(HOOK_CHIPSET_PRE_INIT); - - /* - * Initiate PMIC power-on sequence only if cold booting AP to - * avoid accidental reset (crosbug.com/p/12650). - */ - set_pmic_pwrok(1); - } - -#ifdef BOARD_kirby - /* - * There is no input signal for PMIC ready for 3.3V power. We can only - * for a pre-defined amount of time. - */ - udelay(DELAY_PRE_3V_ENABLE); -#else - /* wait for all PMIC regulators to be ready */ - wait_in_signal(GPIO_PP1800_LDO2, 1, PMIC_TIMEOUT); - - /* - * If PP1800_LDO2 did not come up (e.g. PMIC_TIMEOUT was reached), - * turn off 5V rail (and 3.3V, if turned on above) and start over. - */ - if (gpio_get_level(GPIO_PP1800_LDO2) == 0) { - gpio_set_level(GPIO_EN_PP5000, 0); - gpio_set_level(GPIO_EN_PP3300, 0); - usleep(DELAY_5V_SETUP); - CPRINTF("[%T power error: PMIC failed to enable]\n"); - return -1; - } - - /* Enable DDR 1.35v power rail */ - gpio_set_level(GPIO_EN_PP1350, 1); - /* Wait to avoid large inrush current */ - usleep(DELAY_RAIL_STAGGERING); -#endif - - /* Enable 3.3v power rail, if it's not already on */ - gpio_set_level(GPIO_EN_PP3300, 1); - - ap_on = 1; - disable_sleep(SLEEP_MASK_AP_RUN); - powerled_set_state(POWERLED_STATE_ON); - - /* Call hooks now that AP is running */ - hook_notify(HOOK_CHIPSET_STARTUP); - - CPRINTF("[%T AP running ...]\n"); - return 0; -} - -/** - * Wait for the power button to be released - * - * @return 0 if ok, -1 if power button failed to release - */ -static int wait_for_power_button_release(unsigned int timeout_us) -{ - /* wait for Power button release */ - wait_in_signal(GPIO_KB_PWR_ON_L, 1, timeout_us); - - udelay(KB_PWR_ON_DEBOUNCE); - if (gpio_get_level(GPIO_KB_PWR_ON_L) == 0) { - CPRINTF("[%T power button not released in time]\n"); - return -1; - } - CPRINTF("[%T power button released]\n"); - return 0; -} - -/** - * Wait for the XPSHOLD signal from the AP to be asserted within timeout_us - * and if asserted clear the PMIC_PWRON signal - * - * @return 0 if ok, -1 if power button failed to release - */ -static int react_to_xpshold(unsigned int timeout_us) -{ - /* wait for Power button release */ - wait_in_signal(GPIO_SOC1V8_XPSHOLD, 1, timeout_us); - - if (gpio_get_level(GPIO_SOC1V8_XPSHOLD) == 0) { - CPRINTF("[%T XPSHOLD not seen in time]\n"); - return -1; - } - CPRINTF("[%T XPSHOLD seen]\n"); - set_pmic_pwrok(0); - return 0; -} - -/** - * Power off the AP - */ -static void power_off(void) -{ - /* Call hooks before we drop power rails */ - hook_notify(HOOK_CHIPSET_SHUTDOWN); - /* switch off all rails */ - chipset_force_shutdown(); - ap_on = 0; - ap_suspended = 0; - lid_opened = 0; - enable_sleep(SLEEP_MASK_AP_RUN); - powerled_set_state(POWERLED_STATE_OFF); -#ifdef CONFIG_PMU_TPS65090 - pmu_shutdown(); -#endif - CPRINTF("[%T power shutdown complete]\n"); -} - - -/* - * Calculates the delay in microseconds to the next time we have to check - * for a power event, - * - *@return delay to next check, or -1 if no future check is needed - */ -static int next_pwr_event(void) -{ - if (!power_off_deadline.val) - return -1; - - return power_off_deadline.val - get_time().val; -} - - -/*****************************************************************************/ - -static int wait_for_power_on(void) -{ - int value; - while (1) { - value = check_for_power_on_event(); - if (!value) { - task_wait_event(-1); - continue; - } - -#ifdef HAS_TASK_CHARGER - /* - * If the system is already on (value == 1), the kernel - * would handle low power condition and we should not - * shutdown the system from EC. - */ - if (value != 1 && charge_keep_power_off()) { - CPRINTF("[%T power on ignored due to low battery]\n"); - continue; - } -#endif - - CPRINTF("[%T power on %d]\n", value); - return value; - } -} - -void chipset_task(void) -{ - int value; - - gaia_power_init(); - ap_on = 0; - - while (1) { - /* Wait until we need to power on, then power on */ - wait_for_power_on(); - - if (!power_on()) { - int continue_power = 0; - - if (!react_to_xpshold(DELAY_RELEASE_PWRON)) { - /* AP looks good */ - if (!wait_for_power_button_release( - DELAY_SHUTDOWN_ON_POWER_HOLD)) - continue_power = 1; - } else { - /* AP is possibly in bad shape */ - /* allow USB boot in 16 secs */ - if (!wait_for_power_button_release( - DELAY_SHUTDOWN_ON_USB_BOOT)) - continue_power = 1; - } - if (continue_power) { - power_button_was_pressed = 0; - while (!(value = check_for_power_off_event())) - task_wait_event(next_pwr_event()); - CPRINTF("[%T power ending loop %d]\n", value); - } - } - power_off(); - wait_for_power_button_release(-1); - } -} - -/*****************************************************************************/ -/* Console debug command */ - -static int command_force_power(int argc, char **argv) -{ - /* simulate power button pressed */ - force_signal = GPIO_KB_PWR_ON_L; - force_value = 1; - /* Wake up the task */ - task_wake(TASK_ID_CHIPSET); - /* Wait 100 ms */ - msleep(100); - /* Release power button */ - force_signal = -1; - force_value = 0; - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(forcepower, command_force_power, - NULL, - "Force power on", - NULL); - -static const char *power_req_name[POWER_REQ_COUNT] = { - "none", - "off", - "on", -}; - -/* Power states that we can report */ -enum power_state_t { - PSTATE_UNKNOWN, - PSTATE_OFF, - PSTATE_SUSPEND, - PSTATE_ON, - - PSTATE_COUNT, -}; - -static const char * const state_name[] = { - "unknown", - "off", - "suspend", - "on", -}; - -static int command_power(int argc, char **argv) -{ - int v; - - if (argc < 2) { - enum power_state_t state; - - state = PSTATE_UNKNOWN; - if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) - state = PSTATE_OFF; - if (chipset_in_state(CHIPSET_STATE_SUSPEND)) - state = PSTATE_SUSPEND; - if (chipset_in_state(CHIPSET_STATE_ON)) - state = PSTATE_ON; - ccprintf("%s\n", state_name[state]); - - return EC_SUCCESS; - } - - if (!parse_bool(argv[1], &v)) - return EC_ERROR_PARAM1; - - power_request = v ? POWER_REQ_ON : POWER_REQ_OFF; - ccprintf("Requesting power %s\n", power_req_name[power_request]); - task_wake(TASK_ID_CHIPSET); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(power, command_power, - "on/off", - "Turn AP power on/off", - NULL); diff --git a/common/chipset_haswell.c b/common/chipset_haswell.c deleted file mode 100644 index 95823ae418..0000000000 --- a/common/chipset_haswell.c +++ /dev/null @@ -1,406 +0,0 @@ -/* Copyright (c) 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 "chipset.h" -#include "chipset_x86_common.h" -#include "common.h" -#include "console.h" -#include "ec_commands.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "lid_switch.h" -#include "system.h" -#include "timer.h" -#include "util.h" -#include "wireless.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_CHIPSET, outstr) -#define CPRINTF(format, args...) cprintf(CC_CHIPSET, format, ## args) - -/* Input state flags */ -#define IN_PGOOD_PP5000 X86_SIGNAL_MASK(X86_PGOOD_PP5000) -#define IN_PGOOD_PP1350 X86_SIGNAL_MASK(X86_PGOOD_PP1350) -#define IN_PGOOD_PP1050 X86_SIGNAL_MASK(X86_PGOOD_PP1050) -#define IN_PGOOD_VCORE X86_SIGNAL_MASK(X86_PGOOD_VCORE) -#define IN_PCH_SLP_S0n_DEASSERTED X86_SIGNAL_MASK(X86_PCH_SLP_S0n_DEASSERTED) -#define IN_PCH_SLP_S3n_DEASSERTED X86_SIGNAL_MASK(X86_PCH_SLP_S3n_DEASSERTED) -#define IN_PCH_SLP_S5n_DEASSERTED X86_SIGNAL_MASK(X86_PCH_SLP_S5n_DEASSERTED) -#define IN_PCH_SLP_SUSn_DEASSERTED X86_SIGNAL_MASK(X86_PCH_SLP_SUSn_DEASSERTED) - -/* All always-on supplies */ -#define IN_PGOOD_ALWAYS_ON (IN_PGOOD_PP5000) -/* All non-core power rails */ -#define IN_PGOOD_ALL_NONCORE (IN_PGOOD_PP1350 | 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_ALWAYS_ON | IN_PGOOD_PP1350) -/* Rails required for S0 */ -#define IN_PGOOD_S0 (IN_PGOOD_ALWAYS_ON | IN_PGOOD_ALL_NONCORE) - -/* All PM_SLP signals from PCH deasserted */ -#define IN_ALL_PM_SLP_DEASSERTED (IN_PCH_SLP_S3n_DEASSERTED | \ - IN_PCH_SLP_S5n_DEASSERTED) -/* All inputs in the right state for S0 */ -#define IN_ALL_S0 (IN_PGOOD_ALWAYS_ON | IN_PGOOD_ALL_NONCORE | \ - IN_PGOOD_ALL_CORE | IN_ALL_PM_SLP_DEASSERTED) - -static int throttle_cpu; /* Throttle CPU? */ -static int pause_in_s5; /* Pause in S5 when shutting down? */ - -void chipset_force_shutdown(void) -{ - CPRINTF("[%T %s()]\n", __func__); - - /* - * Force x86 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); -} - -void chipset_reset(int cold_reset) -{ - CPRINTF("[%T %s(%d)]\n", __func__, cold_reset); - if (cold_reset) { - /* - * Drop and restore PWROK. This causes the PCH to reboot, - * regardless of its after-G3 setting. This type of reboot - * causes the PCH to assert PLTRST#, SLP_S3#, and SLP_S5#, so - * we actually drop power to the rest of the system (hence, a - * "cold" reboot). - */ - - /* Ignore if PWROK is already low */ - if (gpio_get_level(GPIO_PCH_PWROK) == 0) - return; - - /* PWROK must deassert for at least 3 RTC clocks = 91 us */ - gpio_set_level(GPIO_PCH_PWROK, 0); - udelay(100); - gpio_set_level(GPIO_PCH_PWROK, 1); - - } else { - /* - * 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. - */ - - /* - * The gpio pin used by the EC (PL6) does not behave in the - * correct manner when configured as open drain. In order to - * mimic open drain, the pin is initially configured as an - * input. When it is needed to drive low, the flags are - * updated which changes the pin to an output and drives the - * pin low. Note that this logic will work fine even on boards - * where RCIN# has been moved to a different pin, so there's no - * need to #ifdef this behavior. See crosbug.com/p/20173. - */ - gpio_set_flags(GPIO_PCH_RCIN_L, GPIO_OUT_LOW); - udelay(10); - gpio_set_flags(GPIO_PCH_RCIN_L, GPIO_INPUT); - } -} - -void chipset_throttle_cpu(int throttle) -{ - if (chipset_in_state(CHIPSET_STATE_ON)) - gpio_set_level(GPIO_CPU_PROCHOT, throttle); -} - -enum x86_state x86_chipset_init(void) -{ - /* Enable interrupts for our GPIOs */ - gpio_enable_interrupt(GPIO_PCH_EDP_VDD_EN); - - /* - * 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 ((x86_get_signals() & IN_ALL_S0) == IN_ALL_S0) { - CPRINTF("[%T x86 already in S0]\n"); - return X86_S0; - } else { - /* Force all signals to their G3 states */ - CPRINTF("[%T x86 forcing G3]\n"); - gpio_set_level(GPIO_PCH_PWROK, 0); - gpio_set_level(GPIO_VCORE_EN, 0); - gpio_set_level(GPIO_SUSP_VR_EN, 0); - gpio_set_level(GPIO_PP1350_EN, 0); - gpio_set_level(GPIO_EC_EDP_VDD_EN, 0); - gpio_set_level(GPIO_PP3300_DX_EN, 0); - gpio_set_level(GPIO_PP5000_EN, 0); - gpio_set_level(GPIO_PCH_RSMRST_L, 0); - gpio_set_level(GPIO_PCH_DPWROK, 0); - wireless_enable(0); - } - } - - return X86_G3; -} - -enum x86_state x86_handle_state(enum x86_state state) -{ - switch (state) { - case X86_G3: - break; - - case X86_S5: - if (gpio_get_level(GPIO_PCH_SLP_S5_L) == 1) - return X86_S5S3; /* Power up to next state */ - break; - - case X86_S3: - /* - * If lid is closed; hold touchscreen in reset to cut power - * usage. If lid is open, take touchscreen out of reset so it - * can wake the processor. Chipset task is awakened on lid - * switch transitions. - */ - gpio_set_level(GPIO_TOUCHSCREEN_RESET_L, lid_is_open()); - - /* Check for state transitions */ - if (!x86_has_signals(IN_PGOOD_S3)) { - /* Required rail went away */ - chipset_force_shutdown(); - return X86_S3S5; - } else if (gpio_get_level(GPIO_PCH_SLP_S3_L) == 1) { - /* Power up to next state */ - return X86_S3S0; - } else if (gpio_get_level(GPIO_PCH_SLP_S5_L) == 0) { - /* Power down to next state */ - return X86_S3S5; - } - break; - - case X86_S0: - if (!x86_has_signals(IN_PGOOD_S0)) { - /* Required rail went away */ - chipset_force_shutdown(); - return X86_S0S3; - } else if (gpio_get_level(GPIO_PCH_SLP_S3_L) == 0) { - /* Power down to next state */ - return X86_S0S3; - } - break; - - case X86_G3S5: - /* - * Wait 10ms after +3VALW good, since that powers VccDSW and - * VccSUS. - */ - msleep(10); - - /* Assert DPWROK */ - gpio_set_level(GPIO_PCH_DPWROK, 1); - if (x86_wait_signals(IN_PCH_SLP_SUSn_DEASSERTED)) { - chipset_force_shutdown(); - return X86_G3; - } - - gpio_set_level(GPIO_SUSP_VR_EN, 1); - if (x86_wait_signals(IN_PGOOD_PP1050)) { - chipset_force_shutdown(); - return X86_G3; - } - - /* Deassert RSMRST# */ - gpio_set_level(GPIO_PCH_RSMRST_L, 1); - - /* Wait 5ms for SUSCLK to stabilize */ - msleep(5); - return X86_S5; - - case X86_S5S3: - /* Enable PP5000 (5V) rail. */ - gpio_set_level(GPIO_PP5000_EN, 1); - if (x86_wait_signals(IN_PGOOD_PP5000)) { - chipset_force_shutdown(); - return X86_G3; - } - - /* Wait for the always-on rails to be good */ - if (x86_wait_signals(IN_PGOOD_ALWAYS_ON)) { - chipset_force_shutdown(); - return X86_S5G3; - } - - /* Turn on power to RAM */ - gpio_set_level(GPIO_PP1350_EN, 1); - if (x86_wait_signals(IN_PGOOD_S3)) { - chipset_force_shutdown(); - return X86_S5G3; - } - - /* - * Enable touchpad power so it can wake the system from - * suspend. - */ - gpio_set_level(GPIO_ENABLE_TOUCHPAD, 1); - - /* Call hooks now that rails are up */ - hook_notify(HOOK_CHIPSET_STARTUP); - return X86_S3; - - case X86_S3S0: - /* Turn on power rails */ - gpio_set_level(GPIO_PP3300_DX_EN, 1); - - /* Enable wireless */ - wireless_enable(EC_WIRELESS_SWITCH_ALL); - - /* - * Make sure touchscreen is out if reset (even if the lid is - * still closed); it may have been turned off if the lid was - * closed in S3. - */ - gpio_set_level(GPIO_TOUCHSCREEN_RESET_L, 1); - - /* Wait for non-core power rails good */ - if (x86_wait_signals(IN_PGOOD_S0)) { - chipset_force_shutdown(); - wireless_enable(0); - gpio_set_level(GPIO_EC_EDP_VDD_EN, 0); - gpio_set_level(GPIO_PP3300_DX_EN, 0); - gpio_set_level(GPIO_TOUCHSCREEN_RESET_L, 0); - return X86_S3; - } - - /* - * Enable +CPU_CORE. The CPU itself will request the supplies - * when it's ready. - */ - gpio_set_level(GPIO_VCORE_EN, 1); - - /* 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); - - /* Wait 99ms after all voltages good */ - msleep(99); - - /* - * 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); - - /* Set PCH_PWROK */ - gpio_set_level(GPIO_PCH_PWROK, 1); - gpio_set_level(GPIO_SYS_PWROK, 1); - return X86_S0; - - case X86_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); - - /* Disable +CPU_CORE */ - gpio_set_level(GPIO_VCORE_EN, 0); - - /* Disable wireless */ - wireless_enable(0); - - /* - * 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); - - /* - * Deassert prochot since CPU is off and we're about to drop - * +VCCP. - */ - gpio_set_level(GPIO_CPU_PROCHOT, 0); - - /* Turn off power rails */ - gpio_set_level(GPIO_EC_EDP_VDD_EN, 0); - gpio_set_level(GPIO_PP3300_DX_EN, 0); - return X86_S3; - - case X86_S3S5: - /* Call hooks before we remove power rails */ - hook_notify(HOOK_CHIPSET_SHUTDOWN); - - /* Disable touchpad power */ - gpio_set_level(GPIO_ENABLE_TOUCHPAD, 0); - - /* Turn off power to RAM */ - gpio_set_level(GPIO_PP1350_EN, 0); - - /* Disable PP5000 (5V) rail. */ - gpio_set_level(GPIO_PP5000_EN, 0); - - /* Start shutting down */ - return pause_in_s5 ? X86_S5 : X86_S5G3; - - case X86_S5G3: - /* Deassert DPWROK, assert RSMRST# */ - gpio_set_level(GPIO_PCH_DPWROK, 0); - gpio_set_level(GPIO_PCH_RSMRST_L, 0); - gpio_set_level(GPIO_SUSP_VR_EN, 0); - return X86_G3; - } - - return state; -} - -void power_interrupt(enum gpio_signal signal) -{ - /* Pass through eDP VDD enable from PCH */ - gpio_set_level(GPIO_EC_EDP_VDD_EN, gpio_get_level(GPIO_PCH_EDP_VDD_EN)); -} - -static int host_command_gsv(struct host_cmd_handler_args *args) -{ - const struct ec_params_get_set_value *p = args->params; - struct ec_response_get_set_value *r = args->response; - - if (p->flags & EC_GSV_SET) - pause_in_s5 = p->value; - - r->value = pause_in_s5; - - args->response_size = sizeof(*r); - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_GSV_PAUSE_IN_S5, - host_command_gsv, - EC_VER_MASK(0)); - -static int console_command_gsv(int argc, char **argv) -{ - if (argc > 1 && !parse_bool(argv[1], &pause_in_s5)) - return EC_ERROR_INVAL; - - ccprintf("pause_in_s5 = %s\n", pause_in_s5 ? "on" : "off"); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(pause_in_s5, console_command_gsv, - "[on|off]", - "Should the AP pause in S5 during shutdown?", - NULL); - diff --git a/common/chipset_ivybridge.c b/common/chipset_ivybridge.c deleted file mode 100644 index 7a8dfd12aa..0000000000 --- a/common/chipset_ivybridge.c +++ /dev/null @@ -1,344 +0,0 @@ -/* Copyright (c) 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 "chipset.h" -#include "chipset_x86_common.h" -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "lid_switch.h" -#include "system.h" -#include "timer.h" -#include "util.h" -#include "wireless.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_CHIPSET, outstr) -#define CPRINTF(format, args...) cprintf(CC_CHIPSET, format, ## args) - -/* Input state flags */ -#define IN_PGOOD_5VALW X86_SIGNAL_MASK(X86_PGOOD_5VALW) -#define IN_PGOOD_1_5V_DDR X86_SIGNAL_MASK(X86_PGOOD_1_5V_DDR) -#define IN_PGOOD_1_5V_PCH X86_SIGNAL_MASK(X86_PGOOD_1_5V_PCH) -#define IN_PGOOD_1_8VS X86_SIGNAL_MASK(X86_PGOOD_1_8VS) -#define IN_PGOOD_VCCP X86_SIGNAL_MASK(X86_PGOOD_VCCP) -#define IN_PGOOD_VCCSA X86_SIGNAL_MASK(X86_PGOOD_VCCSA) -#define IN_PGOOD_CPU_CORE X86_SIGNAL_MASK(X86_PGOOD_CPU_CORE) -#define IN_PGOOD_VGFX_CORE X86_SIGNAL_MASK(X86_PGOOD_VGFX_CORE) -#define IN_PCH_SLP_S3n_DEASSERTED X86_SIGNAL_MASK(X86_PCH_SLP_S3n_DEASSERTED) -#define IN_PCH_SLP_S4n_DEASSERTED X86_SIGNAL_MASK(X86_PCH_SLP_S4n_DEASSERTED) -#define IN_PCH_SLP_S5n_DEASSERTED X86_SIGNAL_MASK(X86_PCH_SLP_S5n_DEASSERTED) -#define IN_PCH_SLP_An_DEASSERTED X86_SIGNAL_MASK(X86_PCH_SLP_An_DEASSERTED) -#define IN_PCH_SLP_SUSn_DEASSERTED X86_SIGNAL_MASK(X86_PCH_SLP_SUSn_DEASSERTED) -#define IN_PCH_SLP_MEn_DEASSERTED X86_SIGNAL_MASK(X86_PCH_SLP_MEn_DEASSERTED) - -/* All always-on supplies */ -#define IN_PGOOD_ALWAYS_ON (IN_PGOOD_5VALW) -/* All non-core power rails */ -#define IN_PGOOD_ALL_NONCORE (IN_PGOOD_1_5V_DDR | IN_PGOOD_1_5V_PCH | \ - IN_PGOOD_1_8VS | IN_PGOOD_VCCP | IN_PGOOD_VCCSA) -/* All core power rails */ -#define IN_PGOOD_ALL_CORE (IN_PGOOD_CPU_CORE | IN_PGOOD_VGFX_CORE) -/* Rails required for S3 */ -#define IN_PGOOD_S3 (IN_PGOOD_ALWAYS_ON | IN_PGOOD_1_5V_DDR) -/* Rails required for S0 */ -#define IN_PGOOD_S0 (IN_PGOOD_ALWAYS_ON | IN_PGOOD_ALL_NONCORE) - -/* All PM_SLP signals from PCH deasserted */ -#define IN_ALL_PM_SLP_DEASSERTED (IN_PCH_SLP_S3n_DEASSERTED | \ - IN_PCH_SLP_S4n_DEASSERTED | \ - IN_PCH_SLP_S5n_DEASSERTED | \ - IN_PCH_SLP_An_DEASSERTED) -/* All inputs in the right state for S0 */ -#define IN_ALL_S0 (IN_PGOOD_ALWAYS_ON | IN_PGOOD_ALL_NONCORE | \ - IN_PGOOD_CPU_CORE | IN_ALL_PM_SLP_DEASSERTED) - -static int throttle_cpu; /* Throttle CPU? */ - -void chipset_force_shutdown(void) -{ - CPRINTF("[%T chipset force shutdown]\n"); - - /* - * Force x86 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); -} - -void chipset_reset(int cold_reset) -{ - if (cold_reset) { - /* - * Drop and restore PWROK. This causes the PCH to reboot, - * regardless of its after-G3 setting. This type of reboot - * causes the PCH to assert PLTRST#, SLP_S3#, and SLP_S5#, so - * we actually drop power to the rest of the system (hence, a - * "cold" reboot). - */ - - /* Ignore if PWROK is already low */ - if (gpio_get_level(GPIO_PCH_PWROK) == 0) - return; - - /* PWROK must deassert for at least 3 RTC clocks = 91 us */ - gpio_set_level(GPIO_PCH_PWROK, 0); - udelay(100); - gpio_set_level(GPIO_PCH_PWROK, 1); - - } else { - /* - * 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) -{ - throttle_cpu = throttle; - - /* Immediately set throttling if CPU is on */ - if (chipset_in_state(CHIPSET_STATE_ON)) - gpio_set_level(GPIO_CPU_PROCHOT, throttle); -} - -enum x86_state x86_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 ((x86_get_signals() & IN_ALL_S0) == IN_ALL_S0) { - CPRINTF("[%T x86 already in S0]\n"); - return X86_S0; - } else { - /* Force all signals to their G3 states */ - CPRINTF("[%T x86 forcing G3]\n"); - gpio_set_level(GPIO_PCH_PWROK, 0); - gpio_set_level(GPIO_ENABLE_VCORE, 0); - gpio_set_level(GPIO_ENABLE_VS, 0); - gpio_set_level(GPIO_ENABLE_TOUCHPAD, 0); - gpio_set_level(GPIO_TOUCHSCREEN_RESET_L, 0); - gpio_set_level(GPIO_ENABLE_1_5V_DDR, 0); - gpio_set_level(GPIO_PCH_RSMRST_L, 0); - gpio_set_level(GPIO_PCH_DPWROK, 0); - } - } - - return X86_G3; -} - -enum x86_state x86_handle_state(enum x86_state state) -{ - switch (state) { - case X86_G3: - break; - - case X86_S5: - if (gpio_get_level(GPIO_PCH_SLP_S5_L) == 1) { - /* Power up to next state */ - return X86_S5S3; - } - break; - - case X86_S3: - /* - * If lid is closed; hold touchscreen in reset to cut power - * usage. If lid is open, take touchscreen out of reset so it - * can wake the processor. - */ - gpio_set_level(GPIO_TOUCHSCREEN_RESET_L, lid_is_open()); - - /* Check for state transitions */ - if (!x86_has_signals(IN_PGOOD_S3)) { - /* Required rail went away */ - chipset_force_shutdown(); - return X86_S3S5; - } else if (gpio_get_level(GPIO_PCH_SLP_S3_L) == 1) { - /* Power up to next state */ - return X86_S3S0; - } else if (gpio_get_level(GPIO_PCH_SLP_S5_L) == 0) { - /* Power down to next state */ - return X86_S3S5; - } - break; - - case X86_S0: - if (!x86_has_signals(IN_PGOOD_S0)) { - /* Required rail went away */ - chipset_force_shutdown(); - return X86_S0S3; - } else if (gpio_get_level(GPIO_PCH_SLP_S3_L) == 0) { - /* Power down to next state */ - return X86_S0S3; - } - break; - - case X86_G3S5: - /* - * Wait 10ms after +3VALW good, since that powers VccDSW and - * VccSUS. - */ - msleep(10); - - /* Assert DPWROK, deassert RSMRST# */ - gpio_set_level(GPIO_PCH_DPWROK, 1); - gpio_set_level(GPIO_PCH_RSMRST_L, 1); - - /* Wait 5ms for SUSCLK to stabilize */ - msleep(5); - return X86_S5; - - case X86_S5S3: - /* Wait for the always-on rails to be good */ - if (x86_wait_signals(IN_PGOOD_ALWAYS_ON)) { - chipset_force_shutdown(); - return X86_S5; - } - - /* - * Take lightbar out of reset, now that +5VALW is available and - * we won't leak +3VALW through the reset line. - */ - gpio_set_level(GPIO_LIGHTBAR_RESET_L, 1); - - /* Turn on power to RAM */ - gpio_set_level(GPIO_ENABLE_1_5V_DDR, 1); - if (x86_wait_signals(IN_PGOOD_S3)) { - chipset_force_shutdown(); - return X86_S5; - } - - /* - * Enable touchpad power so it can wake the system from - * suspend. - */ - gpio_set_level(GPIO_ENABLE_TOUCHPAD, 1); - - /* Call hooks now that rails are up */ - hook_notify(HOOK_CHIPSET_STARTUP); - return X86_S3; - - case X86_S3S0: - /* Turn on power rails */ - gpio_set_level(GPIO_ENABLE_VS, 1); - - /* Enable wireless */ - wireless_enable(EC_WIRELESS_SWITCH_ALL); - - /* - * Make sure touchscreen is out if reset (even if the lid is - * still closed); it may have been turned off if the lid was - * closed in S3. - */ - gpio_set_level(GPIO_TOUCHSCREEN_RESET_L, 1); - - /* Wait for non-core power rails good */ - if (x86_wait_signals(IN_PGOOD_S0)) { - chipset_force_shutdown(); - gpio_set_level(GPIO_TOUCHSCREEN_RESET_L, 0); - wireless_enable(0); - gpio_set_level(GPIO_ENABLE_VS, 0); - return X86_S3; - } - - /* - * Enable +CPU_CORE and +VGFX_CORE regulator. The CPU itself - * will request the supplies when it's ready. - */ - gpio_set_level(GPIO_ENABLE_VCORE, 1); - - /* Call hooks now that rails are up */ - hook_notify(HOOK_CHIPSET_RESUME); - - /* Wait 99ms after all voltages good */ - msleep(99); - - /* - * 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); - - /* Set PCH_PWROK */ - gpio_set_level(GPIO_PCH_PWROK, 1); - return X86_S0; - - case X86_S0S3: - /* Call hooks before we remove power rails */ - hook_notify(HOOK_CHIPSET_SUSPEND); - - /* Clear PCH_PWROK */ - gpio_set_level(GPIO_PCH_PWROK, 0); - - /* Wait 40ns */ - udelay(1); - - /* Disable +CPU_CORE and +VGFX_CORE */ - gpio_set_level(GPIO_ENABLE_VCORE, 0); - - /* Disable wireless */ - wireless_enable(0); - - /* - * Deassert prochot since CPU is off and we're about to drop - * +VCCP. - */ - gpio_set_level(GPIO_CPU_PROCHOT, 0); - - /* Turn off power rails */ - gpio_set_level(GPIO_ENABLE_VS, 0); - return X86_S3; - - case X86_S3S5: - /* Call hooks before we remove power rails */ - hook_notify(HOOK_CHIPSET_SHUTDOWN); - - /* Disable touchpad power */ - gpio_set_level(GPIO_ENABLE_TOUCHPAD, 0); - - /* Turn off power to RAM */ - gpio_set_level(GPIO_ENABLE_1_5V_DDR, 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 X86_S5; - - case X86_S5G3: - /* Deassert DPWROK, assert RSMRST# */ - gpio_set_level(GPIO_PCH_DPWROK, 0); - gpio_set_level(GPIO_PCH_RSMRST_L, 0); - return X86_G3; - } - - return state; -} - -void power_interrupt(enum gpio_signal signal) -{ - /* Route SUSWARN# back to SUSACK# */ - gpio_set_level(GPIO_PCH_SUSACK_L, gpio_get_level(GPIO_PCH_SUSWARN_L)); -} diff --git a/common/chipset_tegra.c b/common/chipset_tegra.c deleted file mode 100644 index 3484a266ae..0000000000 --- a/common/chipset_tegra.c +++ /dev/null @@ -1,601 +0,0 @@ -/* Copyright (c) 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. - */ - -/* - * TEGRA SoC power sequencing module for Chrome EC - * - * This implements the following features: - * - * - Cold reset powers on the AP - * - * When powered off: - * - Press pwron turns on the AP - * - Hold pwron turns on the AP, and then 9s later turns it off and leaves - * it off until pwron is released and pressed again - * - * When powered on: - * - The PMIC PWRON signal is released <= 1 second after the power button is - * released - * - Holding pwron for 9s powers off the AP - * - Pressing and releasing pwron within that 9s is ignored - * - If XPSHOLD is dropped by the AP, then we power the AP off - */ - -#include "clock.h" -#include "chipset.h" /* This module implements chipset functions too */ -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "lid_switch.h" -#include "keyboard_scan.h" -#include "power_led.h" -#include "pmu_tpschrome.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_CHIPSET, outstr) -#define CPRINTF(format, args...) cprintf(CC_CHIPSET, format, ## args) - -/* Long power key press to force shutdown */ -#define DELAY_FORCE_SHUTDOWN (9 * SECOND) - -/* - * If the power key is pressed to turn on, then held for this long, we - * power off. - * - * Normal case: User releases power button and chipset_task() goes - * into the inner loop, waiting for next event to occur (power button - * press or XPSHOLD == 0). - */ -#define DELAY_SHUTDOWN_ON_POWER_HOLD (9 * SECOND) - -/* Maximum delay after power button press before we deassert GPIO_PMIC_PWRON */ -#define DELAY_RELEASE_PWRON SECOND /* 1s */ - -/* debounce time to prevent accidental power-on after keyboard power off */ -#define KB_PWR_ON_DEBOUNCE 250 /* 250us */ - -/* - * nyan's GPIO_SOC1V8_XPSHOLD will go low for ~20ms after initial high. - * XPSHOLD_DEBOUNCE is used to wait this long, then check the signal again. - */ -#define XPSHOLD_DEBOUNCE (30 * 1000) /* 30 ms */ - -/* Application processor power state */ -static int ap_on; -static int ap_suspended; - -/* simulated event state */ -static int force_signal = -1; -static int force_value; - -/* 1 if the power button was pressed last time we checked */ -static char power_button_was_pressed; - -/* 1 if lid-open event has been detected */ -static char lid_opened; - -/* time where we will power off, if power button still held down */ -static timestamp_t power_off_deadline; - -/* force AP power on (used for recovery keypress) */ -static int auto_power_on; - -enum power_request_t { - POWER_REQ_NONE, - POWER_REQ_OFF, - POWER_REQ_ON, - - POWER_REQ_COUNT, -}; - -static enum power_request_t power_request; - -/** - * Wait for GPIO "signal" to reach level "value". - * Returns EC_ERROR_TIMEOUT if timeout before reaching the desired state. - * - * @param signal Signal to watch - * @param value Value to watch for - * @param timeout Timeout in microseconds from now, or -1 to wait forever - * @return 0 if signal did change to required value, EC_ERROR_TIMEOUT if we - * timed out first. - */ -static int wait_in_signal(enum gpio_signal signal, int value, int timeout) -{ - timestamp_t deadline; - timestamp_t now = get_time(); - - deadline.val = now.val + timeout; - - while (((force_signal != signal) || (force_value != value)) && - gpio_get_level(signal) != value) { - now = get_time(); - if (timeout < 0) { - task_wait_event(-1); - } else if (timestamp_expired(deadline, &now) || - (task_wait_event(deadline.val - now.val) == - TASK_EVENT_TIMER)) { - CPRINTF("[%T power timeout waiting for GPIO %d/%s]\n", - signal, gpio_get_name(signal)); - return EC_ERROR_TIMEOUT; - } - } - - return EC_SUCCESS; -} - -/** - * Set the PMIC PWROK signal. - * - * @param asserted Assert (=1) or deassert (=0) the signal. This is the - * logical level of the pin, not the physical level. - */ -static void set_pmic_pwrok(int asserted) -{ - /* Signal is active-low */ - gpio_set_level(GPIO_PMIC_PWRON_L, asserted ? 0 : 1); -} - -/** - * Check for some event triggering the shutdown. - * - * It can be either a long power button press or a shutdown triggered from the - * AP and detected by reading XPSHOLD. - * - * @return non-zero if a shutdown should happen, 0 if not - */ -static int check_for_power_off_event(void) -{ - timestamp_t now; - int pressed = 0; - - /* - * Check for power button press. - * - * If power_request is POWER_REQ_OFF, simulate the requst as power - * button is pressed. This will casue GPIO_PMIC_PWRON_L to be driven - * low (by set_pmic_pwrok(1)) until PMIC automatically turns off power. - * (PMIC turns off power if GPIO_PMIC_PWRON_L is low for >=9 seconds.) - */ - if (gpio_get_level(GPIO_KB_PWR_ON_L) == 0) { - udelay(KB_PWR_ON_DEBOUNCE); - if (gpio_get_level(GPIO_KB_PWR_ON_L) == 0) - pressed = 1; - } else if (power_request == POWER_REQ_OFF) { - pressed = 1; - power_request = POWER_REQ_NONE; - } - -#ifdef HAS_TASK_KEYSCAN - /* Dis/Enable keyboard scanning when the power button state changes */ - if (!pressed || pressed != power_button_was_pressed) - keyboard_scan_enable(!pressed); -#endif - - now = get_time(); - if (pressed) { - set_pmic_pwrok(1); - - if (!power_button_was_pressed) { - power_off_deadline.val = now.val + DELAY_FORCE_SHUTDOWN; - CPRINTF("[%T power waiting for long press %u]\n", - power_off_deadline.le.lo); - } else if (timestamp_expired(power_off_deadline, &now)) { - power_off_deadline.val = 0; - CPRINTF("[%T power off after long press now=%u, %u]\n", - now.le.lo, power_off_deadline.le.lo); - return 2; - } - } else if (power_button_was_pressed) { - CPRINTF("[%T power off cancel]\n"); - set_pmic_pwrok(0); - } - - power_button_was_pressed = pressed; - - /* XPSHOLD released by AP : shutdown immediately */ - if (gpio_get_level(GPIO_SOC1V8_XPSHOLD) == 0) - return 3; - - return 0; -} - -/** - * Deferred handling for suspend events - * - * The suspend event needs to be able to call the suspend and resume hooks. - * This cannot be done from interrupt level, since the handlers from those - * hooks may need to use mutexes or other functionality not present at - * interrupt level. Use a deferred function instead. - * - * Deferred functions are called from the hook task and not the chipset task, - * so that's a slight deviation from the spec in hooks.h, but a minor one. - */ -static void tegra_suspend_deferred(void) -{ - int new_ap_suspended; - - if (!ap_on) /* power on/off : not a real suspend / resume */ - return; - - new_ap_suspended = !gpio_get_level(GPIO_SUSPEND_L); - - /* We never want to call two suspend or two resumes in a row */ - if (ap_suspended == new_ap_suspended) - return; - - ap_suspended = new_ap_suspended; - - if (ap_suspended) { - if (lid_is_open()) - powerled_set_state(POWERLED_STATE_SUSPEND); - else - powerled_set_state(POWERLED_STATE_OFF); - /* Call hooks here since we don't know it prior to AP suspend */ - hook_notify(HOOK_CHIPSET_SUSPEND); - } else { - powerled_set_state(POWERLED_STATE_ON); - hook_notify(HOOK_CHIPSET_RESUME); - } -} -DECLARE_DEFERRED(tegra_suspend_deferred); - -void power_interrupt(enum gpio_signal signal) -{ - if (signal == GPIO_SUSPEND_L) { - /* Handle suspend events in the hook task */ - hook_call_deferred(tegra_suspend_deferred, 0); - } else { - /* All other events are handled in the chipset task */ - task_wake(TASK_ID_CHIPSET); - } -} - -static void tegra_lid_event(void) -{ - /* Power task only cares about lid-open events */ - if (!lid_is_open()) - return; - - lid_opened = 1; - task_wake(TASK_ID_CHIPSET); -} -DECLARE_HOOK(HOOK_LID_CHANGE, tegra_lid_event, HOOK_PRIO_DEFAULT); - -static int tegra_power_init(void) -{ - /* Enable interrupts for our GPIOs */ - gpio_enable_interrupt(GPIO_KB_PWR_ON_L); - gpio_enable_interrupt(GPIO_SOC1V8_XPSHOLD); - gpio_enable_interrupt(GPIO_SUSPEND_L); - - /* Leave power off only if requested by reset flags */ - if (!(system_get_reset_flags() & RESET_FLAG_AP_OFF)) { - CPRINTF("[%T auto_power_on is set due to reset_flag 0x%x]\n", - system_get_reset_flags()); - auto_power_on = 1; - } - - return EC_SUCCESS; -} - -/*****************************************************************************/ -/* Chipset interface */ - -int chipset_in_state(int state_mask) -{ - /* If AP is off, match any off state for now */ - if ((state_mask & CHIPSET_STATE_ANY_OFF) && !ap_on) - return 1; - - /* If AP is on, match on state */ - if ((state_mask & CHIPSET_STATE_ON) && ap_on && !ap_suspended) - return 1; - - /* if AP is suspended, match on state */ - if ((state_mask & CHIPSET_STATE_SUSPEND) && ap_on && ap_suspended) - return 1; - - /* In any other case, we don't have a match */ - return 0; -} - -void chipset_exit_hard_off(void) -{ - /* TODO: implement, if/when we take the AP down to a hard-off state */ -} - -void chipset_reset(int is_cold) -{ - /* TODO: implement cold reset. For now, all resets are warm resets. */ - CPRINTF("[%T EC triggered warm reboot]\n"); - - /* - * This is a hack to do an AP warm reboot while still preserving RAM - * contents. This is useful for looking at kernel log message contents - * from previous boot in cases where the AP/OS is hard hung. - */ - power_request = POWER_REQ_ON; - task_wake(TASK_ID_CHIPSET); -} - -void chipset_force_shutdown(void) -{ - set_pmic_pwrok(0); -} - -/*****************************************************************************/ - -/** - * Check if there has been a power-on event - * - * This checks all power-on event signals and returns non-zero if any have been - * triggered (with debounce taken into account). - * - * @return non-zero if there has been a power-on event, 0 if not. - */ -static int check_for_power_on_event(void) -{ - /* check if system is already ON */ - if (gpio_get_level(GPIO_SOC1V8_XPSHOLD)) { - CPRINTF("[%T system is on, thus clear auto_power_on]\n"); - auto_power_on = 0; /* no need to arrange another power on */ - return 1; - } - - /* power on requested at EC startup for recovery */ - if (auto_power_on) { - auto_power_on = 0; - return 2; - } - - /* Check lid open */ - if (lid_opened) { - lid_opened = 0; - return 3; - } - - /* check for power button press */ - if (gpio_get_level(GPIO_KB_PWR_ON_L) == 0) { - udelay(KB_PWR_ON_DEBOUNCE); - if (gpio_get_level(GPIO_KB_PWR_ON_L) == 0) - return 4; - } - - if (power_request == POWER_REQ_ON) { - power_request = POWER_REQ_NONE; - return 5; - } - - return 0; -} - -/** - * Power on the AP - * - * @return 0 if ok, -1 on error (PP1800_LDO2 failed to come on) - */ -static int power_on(void) -{ - gpio_set_level(GPIO_AP_RESET_L, 1); - set_pmic_pwrok(1); - - if (gpio_get_level(GPIO_SOC1V8_XPSHOLD) == 0) - /* Initialize non-AP components */ - hook_notify(HOOK_CHIPSET_PRE_INIT); - - ap_on = 1; - disable_sleep(SLEEP_MASK_AP_RUN); - powerled_set_state(POWERLED_STATE_ON); - - /* Call hooks now that AP is running */ - hook_notify(HOOK_CHIPSET_STARTUP); - - CPRINTF("[%T AP running ...]\n"); - return 0; -} - -/** - * Wait for the power button to be released - * - * @return 0 if ok, -1 if power button failed to release - */ -static int wait_for_power_button_release(unsigned int timeout_us) -{ - /* wait for Power button release */ - wait_in_signal(GPIO_KB_PWR_ON_L, 1, timeout_us); - - udelay(KB_PWR_ON_DEBOUNCE); - if (gpio_get_level(GPIO_KB_PWR_ON_L) == 0) { - CPRINTF("[%T power button not released in time]\n"); - return -1; - } - CPRINTF("[%T power button released]\n"); - return 0; -} - -/** - * Wait for the XPSHOLD signal from the AP to be asserted within timeout_us - * and if asserted clear the PMIC_PWRON signal - * - * @return 0 if ok, -1 if power button failed to release - */ -static int react_to_xpshold(unsigned int timeout_us) -{ - /* wait for Power button release */ - wait_in_signal(GPIO_SOC1V8_XPSHOLD, 1, timeout_us); - -#ifdef BOARD_nyan - /* - * nyan's GPIO_SOC1V8_XPSHOLD will go low for about 20ms after initial - * high. Wait XPSHOLD_DEBOUNCE time, then check the signal again. - */ - udelay(XPSHOLD_DEBOUNCE); -#endif - - if (gpio_get_level(GPIO_SOC1V8_XPSHOLD) == 0) { - CPRINTF("[%T XPSHOLD not seen in time]\n"); - return -1; - } - - CPRINTF("[%T XPSHOLD seen]\n"); - return 0; -} - -/** - * Power off the AP - */ -static void power_off(void) -{ - /* Call hooks before we drop power rails */ - hook_notify(HOOK_CHIPSET_SHUTDOWN); - /* switch off all rails */ - chipset_force_shutdown(); - ap_on = 0; - ap_suspended = 0; - lid_opened = 0; - enable_sleep(SLEEP_MASK_AP_RUN); - powerled_set_state(POWERLED_STATE_OFF); - CPRINTF("[%T power shutdown complete]\n"); -} - -/* - * Calculates the delay in microseconds to the next time we have to check - * for a power event, - * - *@return delay to next check, or -1 if no future check is needed - */ -static int next_pwr_event(void) -{ - if (!power_off_deadline.val) - return -1; - - return power_off_deadline.val - get_time().val; -} - -/*****************************************************************************/ -static int wait_for_power_on(void) -{ - int value; - while (1) { - value = check_for_power_on_event(); - if (!value) { - task_wait_event(-1); - continue; - } - -#ifdef HAS_TASK_CHARGER - /* - * If the system is already on (value == 1), the kernel - * would handle low power condition and we should not - * shutdown the system from EC. - */ - if (value != 1 && charge_keep_power_off()) { - CPRINTF("[%T power on ignored due to low battery]\n"); - continue; - } -#endif - - CPRINTF("[%T power on %d]\n", value); - return value; - } -} - -void chipset_task(void) -{ - int value; - - tegra_power_init(); - ap_on = 0; - - while (1) { - /* Wait until we need to power on, then power on */ - wait_for_power_on(); - - if (!power_on()) { - int continue_power = 0; - - if (!react_to_xpshold(DELAY_RELEASE_PWRON)) { - /* AP looks good */ - if (!wait_for_power_button_release( - DELAY_SHUTDOWN_ON_POWER_HOLD)) - continue_power = 1; - } - set_pmic_pwrok(0); - if (continue_power) { - power_button_was_pressed = 0; - while (!(value = check_for_power_off_event())) - task_wait_event(next_pwr_event()); - CPRINTF("[%T power ending loop %d]\n", value); - } - } - power_off(); - wait_for_power_button_release(-1); - } -} - -/*****************************************************************************/ -/* Console debug command */ - -static const char *power_req_name[POWER_REQ_COUNT] = { - "none", - "off", - "on", -}; - -/* Power states that we can report */ -enum power_state_t { - PSTATE_UNKNOWN, - PSTATE_OFF, - PSTATE_SUSPEND, - PSTATE_ON, - - PSTATE_COUNT, -}; - -static const char * const state_name[] = { - "unknown", - "off", - "suspend", - "on", -}; - -static int command_power(int argc, char **argv) -{ - int v; - - if (argc < 2) { - enum power_state_t state; - - state = PSTATE_UNKNOWN; - if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) - state = PSTATE_OFF; - if (chipset_in_state(CHIPSET_STATE_SUSPEND)) - state = PSTATE_SUSPEND; - if (chipset_in_state(CHIPSET_STATE_ON)) - state = PSTATE_ON; - ccprintf("%s\n", state_name[state]); - - return EC_SUCCESS; - } - - if (!parse_bool(argv[1], &v)) - return EC_ERROR_PARAM1; - - power_request = v ? POWER_REQ_ON : POWER_REQ_OFF; - ccprintf("Requesting power %s\n", power_req_name[power_request]); - task_wake(TASK_ID_CHIPSET); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(power, command_power, - "on/off", - "Turn AP power on/off", - NULL); diff --git a/common/chipset_x86_common.c b/common/chipset_x86_common.c deleted file mode 100644 index add033906e..0000000000 --- a/common/chipset_x86_common.c +++ /dev/null @@ -1,422 +0,0 @@ -/* Copyright (c) 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. - */ - -/* Common functionality across x86 chipsets */ - -#include "chipset.h" -#include "chipset_x86_common.h" -#include "common.h" -#include "console.h" -#include "extpower.h" -#include "gpio.h" -#include "hooks.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_CHIPSET, outstr) -#define CPRINTF(format, args...) cprintf(CC_CHIPSET, format, ## args) - -/* - * Default timeout in us; if we've been waiting this long for an input - * transition, just jump to the next state. - */ -#define DEFAULT_TIMEOUT SECOND - -/* Timeout for dropping back from S5 to G3 */ -#define S5_INACTIVITY_TIMEOUT (10 * SECOND) - -static const char * const state_names[] = { - "G3", - "S5", - "S3", - "S0", - "G3->S5", - "S5->S3", - "S3->S0", - "S0->S3", - "S3->S5", - "S5->G3", -}; - -static uint32_t in_signals; /* Current input signal states (IN_PGOOD_*) */ -static uint32_t in_want; /* Input signal state we're waiting for */ -static uint32_t in_debug; /* Signal values which print debug output */ - -static enum x86_state state = X86_G3; /* Current state */ -static int want_g3_exit; /* Should we exit the G3 state? */ -static uint64_t last_shutdown_time; /* When did we enter G3? */ - -/* Delay before hibernating, in seconds */ -static uint32_t hibernate_delay = 3600; - -/** - * Update input signals mask - */ -static void x86_update_signals(void) -{ - uint32_t inew = 0; - const struct x86_signal_info *s = x86_signal_list; - int i; - - for (i = 0; i < X86_SIGNAL_COUNT; i++, s++) { - if (gpio_get_level(s->gpio) == s->level) - inew |= 1 << i; - } - - if ((in_signals & in_debug) != (inew & in_debug)) - CPRINTF("[%T x86 in 0x%04x]\n", inew); - - in_signals = inew; -} - -uint32_t x86_get_signals(void) -{ - return in_signals; -} - -int x86_has_signals(uint32_t want) -{ - if ((in_signals & want) == want) - return 1; - - CPRINTF("[%T x86 power lost input; wanted 0x%04x, got 0x%04x]\n", - want, in_signals & want); - - return 0; -} - -int x86_wait_signals(uint32_t want) -{ - in_want = want; - if (!want) - return EC_SUCCESS; - - while ((in_signals & in_want) != in_want) { - if (task_wait_event(DEFAULT_TIMEOUT) == TASK_EVENT_TIMER) { - x86_update_signals(); - CPRINTF("[%T x86 power timeout on input; " - "wanted 0x%04x, got 0x%04x]\n", - in_want, in_signals & in_want); - return EC_ERROR_TIMEOUT; - } - /* - * TODO: should really shrink the remaining timeout if we woke - * up but didn't have all the signals we wanted. Also need to - * handle aborts if we're no longer in the same state we were - * when we started waiting. - */ - } - return EC_SUCCESS; -} - -/** - * Set the low-level x86 chipset state. - * - * @param new_state New chipset state. - */ -void x86_set_state(enum x86_state new_state) -{ - /* Record the time we go into G3 */ - if (new_state == X86_G3) - last_shutdown_time = get_time().val; - - state = new_state; -} - -/** - * Common handler for x86 steady states - * - * @param state Current x86 state - * @return Updated x86 state - */ -static enum x86_state x86_common_state(enum x86_state state) -{ - switch (state) { - case X86_G3: - if (want_g3_exit) { - want_g3_exit = 0; - return X86_G3S5; - } - - in_want = 0; - if (extpower_is_present()) - task_wait_event(-1); - else { - uint64_t target_time = last_shutdown_time + - hibernate_delay * 1000000ull; - uint64_t time_now = get_time().val; - if (time_now > target_time) { - /* - * Time's up. Hibernate until wake pin - * asserted. - */ - CPRINTF("[%T x86 hibernating]\n"); - system_hibernate(0, 0); - } else { - uint64_t wait = target_time - time_now; - if (wait > TASK_MAX_WAIT_US) - wait = TASK_MAX_WAIT_US; - - /* Wait for a message */ - task_wait_event(wait); - } - } - break; - - case X86_S5: - /* Wait for inactivity timeout */ - x86_wait_signals(0); - if (task_wait_event(S5_INACTIVITY_TIMEOUT) == - TASK_EVENT_TIMER) { - /* Drop to G3; wake not requested yet */ - want_g3_exit = 0; - return X86_S5G3; - } - break; - - case X86_S3: - /* Wait for a message */ - x86_wait_signals(0); - task_wait_event(-1); - break; - - case X86_S0: - /* Wait for a message */ - x86_wait_signals(0); - task_wait_event(-1); - break; - - default: - /* No common functionality for transition states */ - break; - } - - return state; -} - -/*****************************************************************************/ -/* Chipset interface */ - -int chipset_in_state(int state_mask) -{ - int need_mask = 0; - - /* - * TODO: what to do about state transitions? If the caller wants - * HARD_OFF|SOFT_OFF and we're in G3S5, we could still return - * non-zero. - */ - switch (state) { - case X86_G3: - need_mask = CHIPSET_STATE_HARD_OFF; - break; - case X86_G3S5: - case X86_S5G3: - /* - * In between hard and soft off states. Match only if caller - * will accept both. - */ - need_mask = CHIPSET_STATE_HARD_OFF | CHIPSET_STATE_SOFT_OFF; - break; - case X86_S5: - need_mask = CHIPSET_STATE_SOFT_OFF; - break; - case X86_S5S3: - case X86_S3S5: - need_mask = CHIPSET_STATE_SOFT_OFF | CHIPSET_STATE_SUSPEND; - break; - case X86_S3: - need_mask = CHIPSET_STATE_SUSPEND; - break; - case X86_S3S0: - case X86_S0S3: - need_mask = CHIPSET_STATE_SUSPEND | CHIPSET_STATE_ON; - break; - case X86_S0: - need_mask = CHIPSET_STATE_ON; - break; - } - - /* Return non-zero if all needed bits are present */ - return (state_mask & need_mask) == need_mask; -} - -void chipset_exit_hard_off(void) -{ - /* If not in the hard-off state nor headed there, nothing to do */ - if (state != X86_G3 && state != X86_S5G3) - return; - - /* Set a flag to leave G3, then wake the task */ - want_g3_exit = 1; - - if (task_start_called()) - task_wake(TASK_ID_CHIPSET); -} - -/*****************************************************************************/ -/* Task function */ - -void chipset_task(void) -{ - enum x86_state new_state; - - while (1) { - CPRINTF("[%T x86 power state %d = %s, in 0x%04x]\n", - state, state_names[state], in_signals); - - /* Always let the specific chipset handle the state first */ - new_state = x86_handle_state(state); - - /* - * If the state hasn't changed, run common steady-state - * handler. - */ - if (new_state == state) - new_state = x86_common_state(state); - - /* Handle state changes */ - if (new_state != state) - x86_set_state(new_state); - } -} - -/*****************************************************************************/ -/* Hooks */ - -static void x86_common_init(void) -{ - const struct x86_signal_info *s = x86_signal_list; - int i; - - /* Update input state */ - x86_update_signals(); - - /* Call chipset-specific init to set initial state */ - x86_set_state(x86_chipset_init()); - - /* Enable interrupts for input signals */ - for (i = 0; i < X86_SIGNAL_COUNT; i++, s++) - gpio_enable_interrupt(s->gpio); -} -DECLARE_HOOK(HOOK_INIT, x86_common_init, HOOK_PRIO_INIT_CHIPSET); - -static void x86_lid_change(void) -{ - /* Wake up the task to update power state */ - task_wake(TASK_ID_CHIPSET); -} -DECLARE_HOOK(HOOK_LID_CHANGE, x86_lid_change, HOOK_PRIO_DEFAULT); - -static void x86_ac_change(void) -{ - if (extpower_is_present()) { - CPRINTF("[%T x86 AC on]\n"); - } else { - CPRINTF("[%T x86 AC off]\n"); - - if (state == X86_G3) { - last_shutdown_time = get_time().val; - task_wake(TASK_ID_CHIPSET); - } - } -} -DECLARE_HOOK(HOOK_AC_CHANGE, x86_ac_change, HOOK_PRIO_DEFAULT); - -/*****************************************************************************/ -/* Interrupts */ - -void x86_interrupt(enum gpio_signal signal) -{ - /* Shadow signals and compare with our desired signal state. */ - x86_update_signals(); - - /* Wake up the task */ - task_wake(TASK_ID_CHIPSET); -} - -/*****************************************************************************/ -/* Console commands */ - -static int command_powerinfo(int argc, char **argv) -{ - /* - * Print x86 power state in same format as state machine. This is - * used by FAFT tests, so must match exactly. - */ - ccprintf("[%T x86 power state %d = %s, in 0x%04x]\n", - state, state_names[state], in_signals); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(powerinfo, command_powerinfo, - NULL, - "Show current x86 power state", - NULL); - -static int command_x86indebug(int argc, char **argv) -{ - const struct x86_signal_info *s = x86_signal_list; - int i; - char *e; - - /* If one arg, set the mask */ - if (argc == 2) { - int m = strtoi(argv[1], &e, 0); - if (*e) - return EC_ERROR_PARAM1; - - in_debug = m; - } - - /* Print the mask */ - ccprintf("x86 in: 0x%04x\n", in_signals); - ccprintf("debug mask: 0x%04x\n", in_debug); - - /* Print the decode */ - - ccprintf("bit meanings:\n"); - for (i = 0; i < X86_SIGNAL_COUNT; i++, s++) { - int mask = 1 << i; - ccprintf(" 0x%04x %d %s\n", - mask, in_signals & mask ? 1 : 0, s->name); - } - - return EC_SUCCESS; -}; -DECLARE_CONSOLE_COMMAND(x86indebug, command_x86indebug, - "[mask]", - "Get/set x86 input debug mask", - NULL); - -static int command_hibernation_delay(int argc, char **argv) -{ - char *e; - uint32_t time_g3 = ((uint32_t)(get_time().val - last_shutdown_time)) - / SECOND; - - if (argc >= 2) { - uint32_t s = strtoi(argv[1], &e, 0); - if (*e) - return EC_ERROR_PARAM1; - - hibernate_delay = s; - } - - /* Print the current setting */ - ccprintf("Hibernation delay: %d s\n", hibernate_delay); - if (state == X86_G3 && !extpower_is_present()) { - ccprintf("Time G3: %d s\n", time_g3); - ccprintf("Time left: %d s\n", hibernate_delay - time_g3); - } - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(hibdelay, command_hibernation_delay, - "[sec]", - "Set the delay before going into hibernation", - NULL); diff --git a/common/flash_common.c b/common/flash.c index c2773f6dd0..c2773f6dd0 100644 --- a/common/flash_common.c +++ b/common/flash.c diff --git a/common/gpio_common.c b/common/gpio.c index e310814847..e310814847 100644 --- a/common/gpio_common.c +++ b/common/gpio.c diff --git a/common/i2c_common.c b/common/i2c.c index ed3a888872..ed3a888872 100644 --- a/common/i2c_common.c +++ b/common/i2c.c diff --git a/common/led_driver_ds2413.c b/common/led_driver_ds2413.c deleted file mode 100644 index 9babd75992..0000000000 --- a/common/led_driver_ds2413.c +++ /dev/null @@ -1,166 +0,0 @@ -/* Copyright (c) 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. - */ - -/* Power LED control for Chrome EC */ - -#include "charge_state.h" -#include "console.h" -#include "hooks.h" -#include "onewire.h" -#include "timer.h" -#include "util.h" - -#define ONEWIRE_RETRIES 10 - -enum led_color { - LED_OFF = 0, - LED_RED, - LED_YELLOW, - LED_GREEN, - LED_COLOR_COUNT /* Number of colors, not a color itself */ -}; - -static const uint8_t led_masks[LED_COLOR_COUNT] = {0xff, 0xfe, 0xfc, 0xfd}; -static const char * const color_names[LED_COLOR_COUNT] = { - "off", "red", "yellow", "green"}; - -/** - * Set the onewire LED GPIO controller outputs - * - * @param mask Mask of outputs to enable - * - * @return EC_SUCCESS, or non-zero if error. - */ -static int led_set_mask(int mask) -{ - int rv; - - /* Reset the 1-wire bus */ - rv = onewire_reset(); - if (rv) - return rv; - - /* Skip ROM, since only one device */ - onewire_write(0xcc); - - /* Write and turn on the LEDs */ - onewire_write(0x5a); - onewire_write(mask); - onewire_write(~mask); /* Repeat inverted */ - - rv = onewire_read(); /* Confirmation byte */ - if (rv != 0xaa) - return EC_ERROR_UNKNOWN; - - /* The next byte is a read-back of the chip status. Since we're only - * using lines as outputs, we can ignore it. */ - return EC_SUCCESS; -} - -static int led_set(enum led_color color) -{ - int rv = EC_SUCCESS; - int i; - - /* - * 1-wire communication can fail for timing reasons in the current - * system. We have a limited timing window to send/receive bits, but - * we can't disable interrupts for the rest of the system to guarantee - * we hit that window. Instead, simply retry the low-level command a - * few times. - */ - for (i = 0; i < ONEWIRE_RETRIES; i++) { - rv = led_set_mask(led_masks[color]); - if (rv == EC_SUCCESS) - break; - - /* - * Sleep for a bit between tries. This gives the 1-wire GPIO - * chip time to recover from the failed attempt, and allows - * lower-priority tasks a chance to run. - */ - usleep(100); - } - - return rv; -} - -/*****************************************************************************/ -/* Hooks */ - -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; -} -DECLARE_HOOK(HOOK_SECOND, onewire_led_tick, HOOK_PRIO_DEFAULT); - -/*****************************************************************************/ -/* Console commands */ - -static int command_powerled(int argc, char **argv) -{ - int i; - - /* Pick a color, any color... */ - for (i = 0; i < LED_COLOR_COUNT; i++) { - if (!strcasecmp(argv[1], color_names[i])) - return led_set(i); - } - return EC_ERROR_PARAM1; -} -DECLARE_CONSOLE_COMMAND(powerled, command_powerled, - "<off | red | yellow | green>", - "Set power LED color", - NULL); diff --git a/common/led_driver_lp5562.c b/common/led_driver_lp5562.c deleted file mode 100644 index fd92fae26f..0000000000 --- a/common/led_driver_lp5562.c +++ /dev/null @@ -1,161 +0,0 @@ -/* Copyright (c) 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. - * - * TI LP5562 driver. - */ - -#include "console.h" -#include "i2c.h" -#include "lp5562.h" -#include "timer.h" -#include "uart.h" -#include "util.h" - -/* 8-bit I2C address */ -#define LP5562_I2C_ADDR (0x30 << 1) - -inline int lp5562_write(uint8_t reg, uint8_t val) -{ - return i2c_write8(I2C_PORT_HOST, LP5562_I2C_ADDR, reg, val); -} - -inline int lp5562_read(uint8_t reg, int *val) -{ - return i2c_read8(I2C_PORT_HOST, LP5562_I2C_ADDR, reg, val); -} - -int lp5562_set_color(uint32_t rgb) -{ - int ret = 0; - - ret |= lp5562_write(LP5562_REG_B_PWM, rgb & 0xff); - ret |= lp5562_write(LP5562_REG_G_PWM, (rgb >> 8) & 0xff); - ret |= lp5562_write(LP5562_REG_R_PWM, (rgb >> 16) & 0xff); - - return ret; -} - -int lp5562_set_engine(uint8_t r, uint8_t g, uint8_t b) -{ - return lp5562_write(LP5562_REG_LED_MAP, (r << 4) | (g << 2) | b); -} - -int lp5562_engine_load(int engine, const uint8_t *program, int size) -{ - int prog_addr = LP5562_REG_ENG_PROG(engine); - int i, ret, val; - int shift = 6 - engine * 2; - - ret = lp5562_read(LP5562_REG_OP_MODE, &val); - if (ret) - return ret; - val &= ~(0x3 << shift); - val |= 0x1 << shift; - ret = lp5562_write(LP5562_REG_OP_MODE, val); - if (ret) - return ret; - - for (i = 0; i < size; ++i) { - ret = lp5562_write(prog_addr + i, program[i]); - if (ret) - return ret; - } - - val &= ~(0x3 << shift); - val |= 0x2 << shift; - ret = lp5562_write(LP5562_REG_OP_MODE, val); - - return ret; -} - -int lp5562_engine_control(int eng1, int eng2, int eng3) -{ - int ret, val; - - ret = lp5562_read(LP5562_REG_ENABLE, &val); - if (ret) - return ret; - val &= 0xc0; - val |= (eng1 << 4) | (eng2 << 2) | eng3; - return lp5562_write(LP5562_REG_ENABLE, val); -} - -int lp5562_get_engine_state(int engine) -{ - int val; - - if (lp5562_read(LP5562_REG_ENABLE, &val)) - return 0xee; - return (val >> (6 - engine * 2)) & 0x3; -} - -int lp5562_poweron(void) -{ - int ret = 0; - - ret |= lp5562_write(LP5562_REG_ENABLE, 0x40); - udelay(500); /* start-up delay */ - - ret |= lp5562_write(LP5562_REG_CONFIG, 0x1); - ret |= lp5562_write(LP5562_REG_LED_MAP, 0x0); - - return ret; -} - -int lp5562_poweroff(void) -{ - return lp5562_write(LP5562_REG_ENABLE, 0x0); -} - -int lp5562_get_pc(int engine) -{ - int ret; - if (lp5562_read(LP5562_REG_ENG1_PC + engine - 1, &ret)) - return 0xee; - return ret; -} - -int lp5562_set_pc(int engine, int val) -{ - return lp5562_write(LP5562_REG_ENG1_PC + engine - 1, val); -} - -/*****************************************************************************/ -/* Console commands */ - -static int command_lp5562(int argc, char **argv) -{ - if (argc == 4) { - char *e; - uint8_t red, green, blue; - - red = strtoi(argv[1], &e, 0); - if (e && *e) - return EC_ERROR_PARAM1; - green = strtoi(argv[2], &e, 0); - if (e && *e) - return EC_ERROR_PARAM2; - blue = strtoi(argv[3], &e, 0); - if (e && *e) - return EC_ERROR_PARAM3; - - return lp5562_set_color((red << 16) | (green << 8) | blue); - } else if (argc == 2) { - int v; - - if (!parse_bool(argv[1], &v)) - return EC_ERROR_PARAM1; - - if (v) - return lp5562_poweron(); - else - return lp5562_poweroff(); - } - - return EC_ERROR_INVAL; -} -DECLARE_CONSOLE_COMMAND(lp5562, command_lp5562, - "on | off | <red> <green> <blue>", - "Set the color of the LED", - NULL); diff --git a/common/pwm_common.c b/common/pwm.c index 3a3073d142..3a3073d142 100644 --- a/common/pwm_common.c +++ b/common/pwm.c diff --git a/common/regulator_ir357x.c b/common/regulator_ir357x.c deleted file mode 100644 index c6966b7e31..0000000000 --- a/common/regulator_ir357x.c +++ /dev/null @@ -1,247 +0,0 @@ -/* Copyright (c) 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. - * - * IR357x driver. - */ - -#include "common.h" -#include "console.h" -#include "hooks.h" -#include "i2c.h" -#include "timer.h" -#include "uart.h" -#include "util.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_CHIPSET, outstr) -#define CPRINTF(format, args...) cprintf(CC_CHIPSET, format, ## args) - -/* 8-bit I2C address */ -#define IR357x_I2C_ADDR (0x8 << 1) - -struct ir_setting { - uint8_t reg; - uint8_t value; -}; - -static struct ir_setting ir3570_settings[] = { - {0x10, 0x22}, {0x11, 0x22}, {0x12, 0x88}, {0x13, 0x10}, - {0x14, 0x0d}, {0x15, 0x21}, {0x16, 0x21}, {0x17, 0x00}, - {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00}, - {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00}, - {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x60}, {0x23, 0x60}, - {0x24, 0x74}, {0x25, 0x4e}, {0x26, 0xff}, {0x27, 0x80}, - {0x28, 0x00}, {0x29, 0x20}, {0x2a, 0x15}, {0x2b, 0x26}, - {0x2c, 0xb6}, {0x2d, 0x21}, {0x2e, 0x11}, {0x2f, 0x20}, - {0x30, 0xab}, {0x31, 0x14}, {0x32, 0x90}, {0x33, 0x4d}, - {0x34, 0x75}, {0x35, 0x64}, {0x36, 0x64}, {0x37, 0x09}, - {0x38, 0xc4}, {0x39, 0x20}, {0x3a, 0x80}, {0x3b, 0x00}, - {0x3c, 0x00}, {0x3d, 0xaa}, {0x3e, 0x00}, {0x3f, 0x05}, - {0x40, 0x50}, {0x41, 0x40}, {0x42, 0x00}, {0x43, 0x00}, - {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00}, - {0x48, 0x1c}, {0x49, 0x0c}, {0x4a, 0x0f}, {0x4b, 0x40}, - {0x4c, 0x80}, {0x4d, 0x40}, {0x4e, 0x80}, - {0x51, 0x00}, {0x52, 0x45}, {0x53, 0x59}, - {0x54, 0x23}, {0x55, 0xae}, {0x56, 0x68}, {0x57, 0x24}, - {0x58, 0x62}, {0x59, 0x42}, {0x5a, 0x34}, {0x5b, 0x00}, - {0x5c, 0x30}, {0x5d, 0x05}, {0x5e, 0x02}, {0x5f, 0x35}, - {0x60, 0x30}, {0x61, 0x00}, {0x62, 0xd8}, {0x63, 0x00}, - {0x64, 0x52}, {0x65, 0x28}, {0x66, 0x14}, {0x67, 0x87}, - {0x68, 0x80}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00}, - {0x6c, 0x00}, {0x6d, 0xff}, {0x6e, 0x06}, {0x6f, 0xff}, - {0x70, 0xff}, {0x71, 0x20}, {0x72, 0x00}, {0x73, 0x01}, - {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00}, - {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00}, - {0x7c, 0x15}, {0x7d, 0x15}, {0x7e, 0x00}, {0x7f, 0x00}, - {0x80, 0x00}, {0x81, 0x00}, {0x82, 0x00}, {0x83, 0x00}, - {0x84, 0x00}, {0x85, 0x00}, {0x86, 0x00}, {0x87, 0x00}, - {0x88, 0x88}, {0x89, 0x88}, {0x8a, 0x01}, {0x8b, 0x42}, - {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0x1f}, - {0, 0} -}; - -static struct ir_setting ir3571_settings[] = { - {0x18, 0x22}, {0x19, 0x22}, {0x1a, 0x08}, {0x1b, 0x10}, - {0x1c, 0x06}, {0x1d, 0x21}, {0x1e, 0x21}, {0x1f, 0x83}, - {0x20, 0x83}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00}, - {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x34}, - {0x28, 0x34}, {0x29, 0x74}, {0x2a, 0x4e}, {0x2b, 0xff}, - {0x2c, 0x00}, {0x2d, 0x1d}, {0x2e, 0x14}, {0x2f, 0x1f}, - {0x30, 0x88}, {0x31, 0x9a}, {0x32, 0x1e}, {0x33, 0x19}, - {0x34, 0xe9}, {0x35, 0x40}, {0x36, 0x90}, {0x37, 0x6d}, - {0x38, 0x75}, {0x39, 0xa0}, {0x3a, 0x84}, {0x3b, 0x08}, - {0x3c, 0xc5}, {0x3d, 0xa0}, {0x3e, 0x80}, {0x3f, 0xaa}, - {0x40, 0x50}, {0x41, 0x4b}, {0x42, 0x02}, {0x43, 0x04}, - {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x78}, - {0x48, 0x56}, {0x49, 0x18}, {0x4a, 0x88}, {0x4b, 0x00}, - {0x4c, 0x80}, {0x4d, 0x60}, {0x4e, 0x60}, {0x4f, 0xff}, - {0x50, 0xff}, {0x51, 0x00}, {0x52, 0x9b}, {0x53, 0xaa}, - {0x54, 0xd8}, {0x55, 0x56}, {0x56, 0x31}, {0x57, 0x1a}, - {0x58, 0x12}, {0x59, 0x63}, {0x5a, 0x00}, {0x5b, 0x09}, - {0x5c, 0x02}, {0x5d, 0x00}, {0x5e, 0xea}, {0x5f, 0x00}, - {0x60, 0xb0}, {0x61, 0x1e}, {0x62, 0x00}, {0x63, 0x56}, - {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00}, - {0x68, 0x28}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00}, - {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00}, - {0x70, 0x80}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00}, - {0x74, 0x00}, {0x75, 0xbf}, {0x76, 0x06}, {0x77, 0xff}, - {0x78, 0xff}, {0x79, 0x04}, {0x7a, 0x00}, {0x7b, 0x1d}, - {0x7c, 0xa0}, {0x7d, 0x10}, {0x7e, 0x00}, {0x7f, 0x8a}, - {0x80, 0x1b}, {0x81, 0x11}, {0x82, 0x00}, {0x83, 0x00}, - {0x84, 0x00}, {0x85, 0x00}, {0x86, 0x00}, {0x87, 0x00}, - {0x88, 0x00}, {0x89, 0x00}, {0x8a, 0x00}, {0x8b, 0x00}, - {0x8c, 0x00}, {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0x00}, - {0, 0} -}; - -static uint8_t ir357x_read(uint8_t reg) -{ - int res; - int val; - - res = i2c_read8(I2C_PORT_REGULATOR, IR357x_I2C_ADDR, reg, &val); - if (res) - return 0xee; - - return val; -} - -static void ir357x_write(uint8_t reg, uint8_t val) -{ - int res; - - res = i2c_write8(I2C_PORT_REGULATOR, IR357x_I2C_ADDR, reg, val); - if (res) - CPRINTF("[%T IR I2C write failed]\n"); -} - -static int ir357x_get_version(void) -{ - /* IR3571 on Link EVT */ - if ((ir357x_read(0xfc) == 'I') && (ir357x_read(0xfd) == 'R') && - ((ir357x_read(0x0a) & 0xe) == 0)) - return 3571; - - /* IR3570A on Link Proto 0/1 and Link DVT */ - if ((ir357x_read(0x92) == 'C') && (ir357x_read(0xcd) == 0x24)) - return 3570; - - /* Unknown and unsupported chip */ - return -1; -} - -struct ir_setting *ir357x_get_settings(void) -{ - int version = ir357x_get_version(); - - if (version == 3570) - return ir3570_settings; - else if (version == 3571) - return ir3571_settings; - else - return NULL; -} - -static void ir357x_prog(void) -{ - struct ir_setting *settings = ir357x_get_settings(); - - if (settings) { - for (; settings->reg; settings++) - ir357x_write(settings->reg, settings->value); - } else { - CPRINTF("[%T IR%d chip unsupported. Skip writing settings!\n", - ir357x_get_version()); - return; - } - - CPRINTF("[%T IR%d registers UPDATED]\n", ir357x_get_version()); -} - -static void ir357x_dump(void) -{ - int i; - - for (i = 0; i < 256; i++) { - if (!(i & 0xf)) { - ccprintf("\n%02x: ", i); - cflush(); - } - ccprintf("%02x ", ir357x_read(i)); - } - ccprintf("\n"); -} - -static int ir357x_check(void) -{ - uint8_t val; - int diff = 0; - struct ir_setting *settings = ir357x_get_settings(); - - if (!settings) { - ccprintf("no setting for chip IR%d !\n", ir357x_get_version()); - return 1; - } - - for (; settings->reg; settings++) { - val = ir357x_read(settings->reg); - if (val != settings->value) { - ccprintf("DIFF reg 0x%02x %02x->%02x\n", - settings->reg, settings->value, val); - cflush(); - diff++; - } - } - return !!diff; -} - -static int command_ir357x(int argc, char **argv) -{ - int reg, val; - char *rem; - - if (1 == argc) { /* dump all registers */ - ir357x_dump(); - return EC_SUCCESS; - } else if (2 == argc) { - if (!strcasecmp(argv[1], "check")) { - ir357x_check(); - } else { /* read one register */ - reg = strtoi(argv[1], &rem, 16); - if (*rem) { - ccprintf("Invalid register: %s\n", argv[1]); - return EC_ERROR_INVAL; - } - ccprintf("reg 0x%02x = 0x%02x\n", reg, - ir357x_read(reg)); - } - return EC_SUCCESS; - } else if (3 == argc) { /* write one register */ - reg = strtoi(argv[1], &rem, 16); - if (*rem) { - ccprintf("Invalid register: %s\n", argv[1]); - return EC_ERROR_INVAL; - } - val = strtoi(argv[2], &rem, 16); - if (*rem) { - ccprintf("Invalid value: %s\n", argv[2]); - return EC_ERROR_INVAL; - } - ir357x_write(reg, val); - return EC_SUCCESS; - } - - return EC_ERROR_INVAL; -} -DECLARE_CONSOLE_COMMAND(ir357x, command_ir357x, - "[check|write]", - "IR357x core regulator control", - NULL); - -static void ir357x_hot_settings(void) -{ - /* dynamically apply settings to workaround issue */ - ir357x_prog(); -} -DECLARE_HOOK(HOOK_CHIPSET_RESUME, ir357x_hot_settings, HOOK_PRIO_DEFAULT); diff --git a/common/system_common.c b/common/system.c index 4af045a641..4af045a641 100644 --- a/common/system_common.c +++ b/common/system.c diff --git a/common/temp_sensor_g781.c b/common/temp_sensor_g781.c deleted file mode 100644 index 389b12629e..0000000000 --- a/common/temp_sensor_g781.c +++ /dev/null @@ -1,210 +0,0 @@ -/* Copyright (c) 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. - */ - -/* G781 temperature sensor module for Chrome EC */ - -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "i2c.h" -#include "hooks.h" -#include "temp_sensor_g781.h" -#include "util.h" - -static int g781_temp_val_local; -static int g781_temp_val_remote; - -/** - * Determine whether the sensor is powered. - * - * @return non-zero the g781 sensor is powered. - */ -static int g781_has_power(void) -{ -#ifdef CONFIG_TEMP_SENSOR_POWER_GPIO - return gpio_get_level(CONFIG_TEMP_SENSOR_POWER_GPIO); -#else - return 1; -#endif -} - -static int g781_read8(const int offset, int *data_ptr) -{ - return i2c_read8(I2C_PORT_THERMAL, G781_I2C_ADDR, offset, data_ptr); -} - -static int g781_write8(const int offset, int data) -{ - return i2c_write8(I2C_PORT_THERMAL, G781_I2C_ADDR, offset, data); -} - -static int g781_get_temp(const int offset, int *temp_ptr) -{ - int rv; - int temp_raw = 0; - - rv = g781_read8(offset, &temp_raw); - if (rv < 0) - return rv; - - *temp_ptr = (int)(int8_t)temp_raw; - return EC_SUCCESS; -} - -static int g781_set_temp(const int offset, int temp) -{ - if (temp < -127 || temp > 127) - return EC_ERROR_INVAL; - - return g781_write8(offset, (uint8_t)temp); -} - -int g781_get_val(int idx, int *temp_ptr) -{ - if (!g781_has_power()) - return EC_ERROR_NOT_POWERED; - - switch (idx) { - case G781_IDX_INTERNAL: - *temp_ptr = g781_temp_val_local; - break; - case G781_IDX_EXTERNAL: - *temp_ptr = g781_temp_val_remote; - break; - default: - return EC_ERROR_UNKNOWN; - } - - return EC_SUCCESS; -} - -static void g781_temp_sensor_poll(void) -{ - if (!g781_has_power()) - return; - - g781_get_temp(G781_TEMP_LOCAL, &g781_temp_val_local); - g781_temp_val_local = C_TO_K(g781_temp_val_local); - - g781_get_temp(G781_TEMP_REMOTE, &g781_temp_val_remote); - g781_temp_val_remote = C_TO_K(g781_temp_val_remote); -} -DECLARE_HOOK(HOOK_SECOND, g781_temp_sensor_poll, HOOK_PRIO_TEMP_SENSOR); - -static int g781_show_status(void) -{ - int value; - int rv; - - - rv = g781_get_temp(G781_TEMP_LOCAL, &value); - if (rv < 0) - return rv; - ccprintf("Local Temp: %3dC\n", value); - - rv = g781_get_temp(G781_LOCAL_TEMP_THERM_LIMIT, &value); - if (rv < 0) - return rv; - ccprintf(" Therm Trip: %3dC\n", value); - - rv = g781_get_temp(G781_LOCAL_TEMP_HIGH_LIMIT_R, &value); - if (rv < 0) - return rv; - ccprintf(" High Alarm: %3dC\n", value); - - rv = g781_get_temp(G781_LOCAL_TEMP_LOW_LIMIT_R, &value); - if (rv < 0) - return rv; - ccprintf(" Low Alarm: %3dC\n", value); - - rv = g781_get_temp(G781_TEMP_REMOTE, &value); - if (rv < 0) - return rv; - ccprintf("Remote Temp: %3dC\n", value); - - rv = g781_get_temp(G781_REMOTE_TEMP_THERM_LIMIT, &value); - if (rv < 0) - return rv; - ccprintf(" Therm Trip: %3dC\n", value); - - rv = g781_get_temp(G781_REMOTE_TEMP_HIGH_LIMIT_R, &value); - if (rv < 0) - return rv; - ccprintf(" High Alarm: %3dC\n", value); - - rv = g781_get_temp(G781_REMOTE_TEMP_LOW_LIMIT_R, &value); - if (rv < 0) - return rv; - ccprintf(" Low Alarm: %3dC\n", value); - - rv = g781_read8(G781_STATUS, &value); - if (rv < 0) - return rv; - ccprintf("\nSTATUS: %08b\n", value); - - rv = g781_read8(G781_CONFIGURATION_R, &value); - if (rv < 0) - return rv; - ccprintf("CONFIG: %08b\n", value); - - return EC_SUCCESS; -} - -static int command_g781(int argc, char **argv) -{ - char *command; - char *e; - int data; - int offset; - int rv; - - if (!g781_has_power()) { - ccprintf("ERROR: Temp sensor not powered.\n"); - return EC_ERROR_NOT_POWERED; - } - - /* If no args just print status */ - if (argc == 1) - return g781_show_status(); - - if (argc < 3) - return EC_ERROR_PARAM_COUNT; - - command = argv[1]; - offset = strtoi(argv[2], &e, 0); - if (*e || offset < 0 || offset > 255) - return EC_ERROR_PARAM2; - - if (!strcasecmp(command, "getbyte")) { - rv = g781_read8(offset, &data); - if (rv < 0) - return rv; - ccprintf("Byte at offset 0x%02x is %08b\n", offset, data); - return rv; - } - - /* Remaining commands are of the form "g781 set-command offset data" */ - if (argc != 4) - return EC_ERROR_PARAM_COUNT; - - data = strtoi(argv[3], &e, 0); - if (*e) - return EC_ERROR_PARAM3; - - if (!strcasecmp(command, "settemp")) { - ccprintf("Setting 0x%02x to %dC\n", offset, data); - rv = g781_set_temp(offset, data); - } else if (!strcasecmp(command, "setbyte")) { - ccprintf("Setting 0x%02x to 0x%02x\n", offset, data); - rv = g781_write8(offset, data); - } else - return EC_ERROR_PARAM1; - - return rv; -} -DECLARE_CONSOLE_COMMAND(g781, command_g781, - "[settemp|setbyte <offset> <value>] or [getbyte <offset>]. " - "Temps in Celsius.", - "Print g781 temp sensor status or set parameters.", NULL); diff --git a/common/temp_sensor_tmp006.c b/common/temp_sensor_tmp006.c deleted file mode 100644 index 19d66d87aa..0000000000 --- a/common/temp_sensor_tmp006.c +++ /dev/null @@ -1,444 +0,0 @@ -/* Copyright (c) 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. - */ - -/* TMP006 temperature sensor module for Chrome EC */ - -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "i2c.h" -#include "math.h" -#include "task.h" -#include "temp_sensor.h" -#include "tmp006.h" -#include "util.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_THERMAL, outstr) -#define CPRINTF(format, args...) cprintf(CC_THERMAL, format, ## args) - -/* Constants for calculating target object temperatures */ -static const float A1 = 1.75e-3f; -static const float A2 = -1.678e-5f; -static const float B0 = -2.94e-5f; -static const float B1 = -5.7e-7f; -static const float B2 = 4.63e-9f; -static const float C2 = 13.4f; - -/* Defined in board_temp_sensor.c. */ -extern const struct tmp006_t tmp006_sensors[TMP006_COUNT]; - -/* Flags for tdata->fail */ -#define FAIL_INIT (1 << 0) /* Just initialized */ -#define FAIL_POWER (1 << 1) /* Sensor not powered */ -#define FAIL_I2C (1 << 2) /* I2C communication error */ -#define FAIL_NOT_READY (1 << 3) /* Data not ready */ - -struct tmp006_data_t { - int v; /* Object voltage */ - int t[4]; /* Circular buffer of last four die temperatures */ - int tidx; /* Index of the current value in t[] */ - int fail; /* Fail flags; non-zero if last read failed */ - float s0; /* Sensitivity factor */ - float b0, b1, b2; /* Coefficients for self-heating correction */ -}; - -static struct tmp006_data_t tmp006_data[TMP006_COUNT]; - -/** - * Check if sensor has power - * - * @param idx Sensor index - * - * @return non-zero if sensor has power. - */ -static int tmp006_has_power(int idx) -{ -#ifdef CONFIG_TEMP_SENSOR_POWER_GPIO - return gpio_get_level(CONFIG_TEMP_SENSOR_POWER_GPIO); -#else - return 1; -#endif -} - -static int tmp006_read_die_temp(const struct tmp006_data_t *tdata, - int *temp_ptr) -{ - if (tdata->fail) - return EC_ERROR_UNKNOWN; - - /* Return previous die temperature */ - *temp_ptr = tdata->t[(tdata->tidx - 1) & 0x3] / 100; - return EC_SUCCESS; -} - -/** - * Calculate the remote object temperature. - * - * @param Tdie_i Die temperature in 1/100 K. - * @param Vobj_i Voltage read from register 0. In nV. - * @param tdata TMP006 data for this sensor. - * - * @return Object temperature in 1/100 K. - */ -static int tmp006_calculate_object_temp(int Tdie_i, int Vobj_i, - const struct tmp006_data_t *tdata) -{ - float Tdie, Vobj; - float Tx, S, Vos, Vx, fv, Tobj, T4; - int Tobj_i; - - Tdie = (float)Tdie_i * 1e-2f; - Vobj = (float)Vobj_i * 1e-9f; - - /* Calculate according to TMP006 users guide. */ - Tx = Tdie - 298.15f; - /* S is the sensitivity */ - S = tdata->s0 * (1.0f + A1 * Tx + A2 * Tx * Tx); - /* Vos is the offset voltage */ - Vos = tdata->b0 + tdata->b1 * Tx + tdata->b2 * Tx * Tx; - Vx = Vobj - Vos; - /* fv is Seebeck coefficient f(Vobj) */ - fv = Vx + C2 * Vx * Vx; - - T4 = Tdie * Tdie * Tdie * Tdie + fv / S; - Tobj = sqrtf(sqrtf(T4)); - Tobj_i = (int32_t)(Tobj * 100.0f); - - return Tobj_i; -} - -/** - * Apply TMP006 temporal correction. - * - * @param T1-T4 Four die temperature readings separated by 1s in 1/100K. - * @param Vobj Voltage read from register 0, in nV. - * - * @return Corrected object voltage in 1/100K. - */ -static int tmp006_correct_object_voltage(int T1, int T2, int T3, int T4, - int Vobj) -{ - int Tslope = 3 * T1 + T2 - T3 - 3 * T4; - return Vobj + 296 * Tslope; -} - -static int tmp006_read_object_temp(const struct tmp006_data_t *tdata, - int *temp_ptr) -{ - int pidx = (tdata->tidx - 1) & 0x3; - int t = tdata->t[pidx]; - int v = tdata->v; - - if (tdata->fail) - return EC_ERROR_UNKNOWN; - - if (!tdata->s0) - return EC_ERROR_NOT_CALIBRATED; - - v = tmp006_correct_object_voltage( - t, - tdata->t[(pidx + 3) & 3], - tdata->t[(pidx + 2) & 3], - tdata->t[(pidx + 1) & 3], - v); - - *temp_ptr = tmp006_calculate_object_temp(t, v, tdata) / 100; - - return EC_SUCCESS; -} - -static int tmp006_poll_sensor(int sensor_id) -{ - struct tmp006_data_t *tdata = tmp006_data + sensor_id; - int traw, t; - int vraw, v; - int rv; - int addr = tmp006_sensors[sensor_id].addr; - int idx; - - if (!tmp006_has_power(sensor_id)) { - tdata->fail |= FAIL_POWER; - return EC_ERROR_UNKNOWN; - } - - /* - * If sensor has just initialized and/or has lost power, wait for - * data ready; otherwise, we read garbage data. - */ - if (tdata->fail && (FAIL_POWER | FAIL_INIT)) { - rv = i2c_read16(TMP006_PORT(addr), TMP006_REG(addr), 0x02, &v); - if (rv) { - tdata->fail |= FAIL_I2C; - return EC_ERROR_UNKNOWN; - } else if (!(v & 0x80)) { - tdata->fail |= FAIL_NOT_READY; - return EC_ERROR_UNKNOWN; - } - } - - rv = i2c_read16(TMP006_PORT(addr), TMP006_REG(addr), 0x01, &traw); - if (rv) { - tdata->fail |= FAIL_I2C; - return EC_ERROR_UNKNOWN; - } - - /* Convert temperature from raw to 1/100 K */ - t = ((int)(int16_t)traw * 100) / 128 + 27300; - - rv = i2c_read16(TMP006_PORT(addr), TMP006_REG(addr), 0x00, &vraw); - if (rv) { - tdata->fail |= FAIL_I2C; - return EC_ERROR_UNKNOWN; - } - - /* Convert voltage from raw to nV */ - v = ((int)(int16_t)vraw * 15625) / 100; - - /* - * If last read failed, set the entire temperature history to the - * current temperature. This keeps us from making inaccurate temporal - * corrections based on stale data. - */ - if (tdata->fail) { - for (idx = 0; idx < 4; idx++) - tdata->t[idx] = t; - } else { - idx = tdata->tidx; - tdata->t[idx] = t; - tdata->tidx = (idx + 1) & 3; - } - - tdata->v = v; - tdata->fail = 0; - - return EC_SUCCESS; -} - -int tmp006_get_val(int idx, int *temp_ptr) -{ - /* - * Note: idx is a thermal sensor index, where the top N-1 bits are the - * TMP006 index and the bottom bit is (0=die, 1=remote). - */ - int tidx = idx >> 1; - const struct tmp006_data_t *tdata = tmp006_data + tidx; - - if (tdata->fail & FAIL_POWER) { - /* - * Sensor isn't powered, or hasn't successfully provided data - * since being powered. Keep reporting not-powered until - * we get good data (which will clear FAIL_POWER) or there is - * an I2C error. - */ - return (tdata->fail & FAIL_I2C) ? EC_ERROR_UNKNOWN : - EC_ERROR_NOT_POWERED; - } - - /* Check the low bit to determine which temperature to read. */ - if ((idx & 0x1) == 0) - return tmp006_read_die_temp(tdata, temp_ptr); - else - return tmp006_read_object_temp(tdata, temp_ptr); -} - -/*****************************************************************************/ -/* Hooks */ - -static void tmp006_poll(void) -{ - int i; - - for (i = 0; i < TMP006_COUNT; ++i) - tmp006_poll_sensor(i); -} -DECLARE_HOOK(HOOK_SECOND, tmp006_poll, HOOK_PRIO_TEMP_SENSOR); - -static void tmp006_init(void) -{ - int i; - - for (i = 0; i < TMP006_COUNT; ++i) { - struct tmp006_data_t *tdata = tmp006_data + i; - - /* Report error until we actually read the sensor */ - tdata->fail = FAIL_INIT; - - /* Use defaults for Bn params */ - tdata->b0 = B0; - tdata->b1 = B1; - tdata->b2 = B2; - } -} -DECLARE_HOOK(HOOK_INIT, tmp006_init, HOOK_PRIO_DEFAULT); - -/*****************************************************************************/ -/* Host commands */ - -int tmp006_get_calibration(struct host_cmd_handler_args *args) -{ - const struct ec_params_tmp006_get_calibration *p = args->params; - struct ec_response_tmp006_get_calibration *r = args->response; - const struct tmp006_data_t *tdata; - - if (p->index >= TMP006_COUNT) - return EC_RES_INVALID_PARAM; - - tdata = tmp006_data + p->index; - - r->s0 = tdata->s0; - r->b0 = tdata->b0; - r->b1 = tdata->b1; - r->b2 = tdata->b2; - - args->response_size = sizeof(*r); - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_TMP006_GET_CALIBRATION, - tmp006_get_calibration, - EC_VER_MASK(0)); - -int tmp006_set_calibration(struct host_cmd_handler_args *args) -{ - const struct ec_params_tmp006_set_calibration *p = args->params; - struct tmp006_data_t *tdata; - - if (p->index >= TMP006_COUNT) - return EC_RES_INVALID_PARAM; - - tdata = tmp006_data + p->index; - - tdata->s0 = p->s0; - tdata->b0 = p->b0; - tdata->b1 = p->b1; - tdata->b2 = p->b2; - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_TMP006_SET_CALIBRATION, - tmp006_set_calibration, - EC_VER_MASK(0)); - -/*****************************************************************************/ -/* Console commands */ - -/** - * Print temperature info for a sensor; used by console command. - */ -static int tmp006_print(int idx) -{ - int vraw, v; - int traw, t; - int rv; - int d; - int addr = tmp006_sensors[idx].addr; - - - ccprintf("Debug data from %s:\n", tmp006_sensors[idx].name); - - if (!tmp006_has_power(idx)) { - ccputs("Sensor powered off.\n"); - return EC_ERROR_UNKNOWN; - } - - rv = i2c_read16(TMP006_PORT(addr), TMP006_REG(addr), 0xfe, &d); - if (rv) - return rv; - ccprintf(" Manufacturer ID: 0x%04x\n", d); - - rv = i2c_read16(TMP006_PORT(addr), TMP006_REG(addr), 0xff, &d); - ccprintf(" Device ID: 0x%04x\n", d); - - rv = i2c_read16(TMP006_PORT(addr), TMP006_REG(addr), 0x02, &d); - ccprintf(" Config: 0x%04x\n", d); - - rv = i2c_read16(TMP006_PORT(addr), TMP006_REG(addr), 0x00, &vraw); - v = ((int)(int16_t)vraw * 15625) / 100; - ccprintf(" Voltage: 0x%04x = %d nV\n", vraw, v); - - rv = i2c_read16(TMP006_PORT(addr), TMP006_REG(addr), 0x01, &traw); - t = ((int)(int16_t)traw * 100) / 128; - ccprintf(" Temperature: 0x%04x = %d.%02d C\n", - traw, t / 100, t > 0 ? t % 100 : 100 - (t % 100)); - - return EC_SUCCESS; -} - -static int command_sensor_info(int argc, char **argv) -{ - int i; - int rv, rv1; - - rv1 = EC_SUCCESS; - for (i = 0; i < TMP006_COUNT; i++) { - rv = tmp006_print(i); - if (rv != EC_SUCCESS) - rv1 = rv; - cflush(); - } - - return rv1; -} -DECLARE_CONSOLE_COMMAND(tmp006, command_sensor_info, - NULL, - "Print TMP006 sensors", - NULL); - -static int command_t6cal(int argc, char **argv) -{ - struct tmp006_data_t *tdata; - char *e; - int v; - int i; - - if (argc < 2) { - ccprintf("# Name S0 b0" - " b1 b2\n"); - for (i = 0; i < TMP006_COUNT; i++) { - tdata = tmp006_data + i; - ccprintf("%d %-11s" - "%7de-17 %7de-8 %7de-10 %7de-12\n", - i, tmp006_sensors[i].name, - (int)(tdata->s0 * 1e17f), - (int)(tdata->b0 * 1e8f), - (int)(tdata->b1 * 1e10f), - (int)(tdata->b2 * 1e12f)); - } - - return EC_SUCCESS; - } - - if (argc != 4) - return EC_ERROR_PARAM_COUNT; - - i = strtoi(argv[1], &e, 0); - if (*e || i < 0 || i >= TMP006_COUNT) - return EC_ERROR_PARAM1; - tdata = tmp006_data + i; - - v = strtoi(argv[3], &e, 0); - if (*e) - return EC_ERROR_PARAM3; - - if (!strcasecmp(argv[2], "s0")) - tdata->s0 = (float)v * 1e-17f; - else if (!strcasecmp(argv[2], "b0")) - tdata->b0 = (float)v * 1e-8f; - else if (!strcasecmp(argv[2], "b1")) - tdata->b1 = (float)v * 1e-10f; - else if (!strcasecmp(argv[2], "b2")) - tdata->b2 = (float)v * 1e-12f; - else - return EC_ERROR_PARAM2; - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(t6cal, command_t6cal, - "[<index> <coeff_name> <radix>]", - "Set/print TMP006 calibration", - NULL); diff --git a/common/usb_switch_tsu6721.c b/common/usb_switch_tsu6721.c deleted file mode 100644 index 1eaa74de55..0000000000 --- a/common/usb_switch_tsu6721.c +++ /dev/null @@ -1,252 +0,0 @@ -/* Copyright (c) 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. - * - * TI TSU6721 USB port switch driver. - */ - -#include "console.h" -#include "ec_commands.h" -#include "hooks.h" -#include "host_command.h" -#include "i2c.h" -#include "system.h" -#include "timer.h" -#include "tsu6721.h" -#include "uart.h" -#include "util.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_USBCHARGE, outstr) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) - -/* 8-bit I2C address */ -#define TSU6721_I2C_ADDR (0x25 << 1) - -/* Delay values */ -#define TSU6721_SW_RESET_DELAY 15 - -/* Number of retries when reset fails */ -#define TSU6721_SW_RESET_RETRY 3 - -static int saved_interrupts; - -uint8_t tsu6721_read(uint8_t reg) -{ - int res; - int val; - - res = i2c_read8(I2C_PORT_HOST, TSU6721_I2C_ADDR, reg, &val); - if (res) - return 0xee; - - return val; -} - -int tsu6721_write(uint8_t reg, uint8_t val) -{ - int res; - - res = i2c_write8(I2C_PORT_HOST, TSU6721_I2C_ADDR, reg, val); - if (res) - CPRINTF("[%T TSU6721 I2C write failed]\n"); - return res; -} - -int tsu6721_enable_interrupts(void) -{ - int ctrl = tsu6721_read(TSU6721_REG_CONTROL); - return tsu6721_write(TSU6721_REG_CONTROL, ctrl & 0x1e); -} - -int tsu6721_disable_interrupts(void) -{ - int ctrl = tsu6721_read(TSU6721_REG_CONTROL); - int rv; - - rv = tsu6721_write(TSU6721_REG_CONTROL, ctrl | 0x1); - tsu6721_get_interrupts(); - return rv; -} - -int tsu6721_set_interrupt_mask(uint16_t mask) -{ - return tsu6721_write(TSU6721_REG_INT_MASK1, (~mask) & 0xff) | - tsu6721_write(TSU6721_REG_INT_MASK2, ((~mask) >> 8) & 0xff); -} - -int tsu6721_get_interrupts(void) -{ - int ret = tsu6721_peek_interrupts(); - saved_interrupts = 0; - return ret; -} - -int tsu6721_peek_interrupts(void) -{ - saved_interrupts |= (tsu6721_read(TSU6721_REG_INT2) << 8) | - (tsu6721_read(TSU6721_REG_INT1)); - return saved_interrupts; -} - -int tsu6721_get_device_type(void) -{ - return (tsu6721_read(TSU6721_REG_DEV_TYPE3) << 16) | - (tsu6721_read(TSU6721_REG_DEV_TYPE2) << 8) | - (tsu6721_read(TSU6721_REG_DEV_TYPE1)); -} - -void tsu6721_reset(void) -{ - int i; - - for (i = 0; i < TSU6721_SW_RESET_RETRY; ++i) { - if (i != 0) { - CPRINTF("[%T TSU6721 init failed. Retrying.]\n"); - msleep(500); - } - if (tsu6721_write(TSU6721_REG_RESET, 0x1)) - continue; - /* TSU6721 reset takes ~10ms. Let's wait for 15ms to be safe. */ - msleep(TSU6721_SW_RESET_DELAY); - if (tsu6721_init() == EC_SUCCESS) - break; - } -} - -int tsu6721_mux(enum tsu6721_mux sel) -{ - uint8_t id = tsu6721_read(TSU6721_REG_ADC); - uint8_t vbus1 = tsu6721_read(TSU6721_REG_DEV_TYPE1) & 0x74; - uint8_t vbus3 = tsu6721_read(TSU6721_REG_DEV_TYPE3) & 0x74; - uint8_t ctrl = tsu6721_read(TSU6721_REG_CONTROL); - - /* - * silicon limitation: the chip stays in low power mode and cannot - * activate manual mode if it is not detecting either a VBUS or - * something known on the ID pin - */ - if (sel != TSU6721_MUX_AUTO && (id == 0x1f) && !vbus1 && !vbus3) { - CPRINTF("TSU6721 cannot use manual mode: no VBUS or ID\n"); - return EC_ERROR_INVAL; - } - - if (sel == TSU6721_MUX_AUTO) { - tsu6721_write(TSU6721_REG_CONTROL, ctrl | TSU6721_CTRL_AUTO); - } else { - tsu6721_write(TSU6721_REG_MANUAL1, sel); - tsu6721_write(TSU6721_REG_CONTROL, ctrl & ~TSU6721_CTRL_AUTO); - } - - return EC_SUCCESS; -} - -int tsu6721_init(void) -{ - uint8_t settings; - uint8_t dev_id = tsu6721_read(TSU6721_REG_DEV_ID); - int res = 0; - - if ((dev_id != 0x0a) && (dev_id != 0x12)) { - CPRINTF("TSU6721 invalid device ID 0x%02x\n", dev_id); - return EC_ERROR_UNKNOWN; - } - - /* set USB charger detection timeout to 600ms */ - settings = tsu6721_read(TSU6721_REG_TIMER); - if (settings == 0xee) - return EC_ERROR_UNKNOWN; - settings = (settings & ~0x38); - res |= tsu6721_write(TSU6721_REG_TIMER, settings); - - res |= tsu6721_set_interrupt_mask(TSU6721_INT_ATTACH | - TSU6721_INT_DETACH | - TSU6721_INT_ADC_CHANGE | - TSU6721_INT_VBUS); - res |= tsu6721_enable_interrupts(); - - return res ? EC_ERROR_UNKNOWN : EC_SUCCESS; -} -/* - * TODO(vpalatin): using the I2C early in the HOOK_INIT - * currently triggers all sort of badness, I need to debug - * this before re-activatin this initialization. - */ -#if 0 -DECLARE_HOOK(HOOK_INIT, tsu6721_init, HOOK_PRIO_DEFAULT); -#endif - -static void tsu6721_dump(void) -{ - int i; - uint8_t id = tsu6721_read(TSU6721_REG_ADC); - uint8_t ctrl = tsu6721_read(TSU6721_REG_CONTROL); - - if (ctrl & TSU6721_CTRL_AUTO) - ccprintf("Auto: %02x %02x %02x\n", - tsu6721_read(TSU6721_REG_DEV_TYPE1), - tsu6721_read(TSU6721_REG_DEV_TYPE2), - tsu6721_read(TSU6721_REG_DEV_TYPE3)); - else - ccprintf("Manual: %02x %02x\n", - tsu6721_read(TSU6721_REG_MANUAL1), - tsu6721_read(TSU6721_REG_MANUAL2)); - ccprintf("ID: 0x%02x\n", id); - for (i = 1; i < 0x24; i++) - ccprintf("%02x ", tsu6721_read(i)); - ccprintf("\n"); -} - -/*****************************************************************************/ -/* Console commands */ - -static int command_usbmux(int argc, char **argv) -{ - if (1 == argc) { /* dump all registers */ - tsu6721_dump(); - return EC_SUCCESS; - } else if (2 == argc) { - if (!strcasecmp(argv[1], "usb")) { - tsu6721_mux(TSU6721_MUX_USB); - } else if (!strcasecmp(argv[1], "uart1")) { - tsu6721_mux(TSU6721_MUX_UART); - } else if (!strcasecmp(argv[1], "uart2")) { - tsu6721_mux(TSU6721_MUX_AUDIO); - } else if (!strcasecmp(argv[1], "auto")) { - tsu6721_mux(TSU6721_MUX_AUTO); - } else { /* read one register */ - ccprintf("Invalid mux value: %s\n", argv[1]); - return EC_ERROR_INVAL; - } - return EC_SUCCESS; - } - - return EC_ERROR_INVAL; -} -DECLARE_CONSOLE_COMMAND(usbmux, command_usbmux, - "[usb|uart1|uart2|auto]", - "TSU6721 USB mux control", - NULL); - -/*****************************************************************************/ -/* Host commands */ - -static int usb_command_mux(struct host_cmd_handler_args *args) -{ - const struct ec_params_usb_mux *p = args->params; - - if (system_is_locked()) - return EC_RES_ACCESS_DENIED; - - /* Safety check */ - if (p->mux != TSU6721_MUX_AUTO && - p->mux != TSU6721_MUX_USB && - p->mux != TSU6721_MUX_UART && - p->mux != TSU6721_MUX_AUDIO) - return EC_RES_ERROR; - - if (tsu6721_mux(p->mux)) - return EC_RES_ERROR; - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_USB_MUX, usb_command_mux, EC_VER_MASK(0)); |