diff options
author | Jack Rosenthal <jrosenth@chromium.org> | 2021-11-04 12:11:58 -0600 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-11-05 04:22:34 +0000 |
commit | 252457d4b21f46889eebad61d4c0a65331919cec (patch) | |
tree | 01856c4d31d710b20e85a74c8d7b5836e35c3b98 /driver/charger | |
parent | 08f5a1e6fc2c9467230444ac9b582dcf4d9f0068 (diff) | |
download | chrome-ec-stabilize-14526.89.B-ish.tar.gz |
ish: Trim down the release branchstabilize-wristpin-14469.59.B-ishstabilize-voshyr-14637.B-ishstabilize-quickfix-14695.187.B-ishstabilize-quickfix-14695.124.B-ishstabilize-quickfix-14526.91.B-ishstabilize-14695.85.B-ishstabilize-14695.107.B-ishstabilize-14682.B-ishstabilize-14633.B-ishstabilize-14616.B-ishstabilize-14589.B-ishstabilize-14588.98.B-ishstabilize-14588.14.B-ishstabilize-14588.123.B-ishstabilize-14536.B-ishstabilize-14532.B-ishstabilize-14528.B-ishstabilize-14526.89.B-ishstabilize-14526.84.B-ishstabilize-14526.73.B-ishstabilize-14526.67.B-ishstabilize-14526.57.B-ishstabilize-14498.B-ishstabilize-14496.B-ishstabilize-14477.B-ishstabilize-14469.9.B-ishstabilize-14469.8.B-ishstabilize-14469.58.B-ishstabilize-14469.41.B-ishstabilize-14442.B-ishstabilize-14438.B-ishstabilize-14411.B-ishstabilize-14396.B-ishstabilize-14395.B-ishstabilize-14388.62.B-ishstabilize-14388.61.B-ishstabilize-14388.52.B-ishstabilize-14385.B-ishstabilize-14345.B-ishstabilize-14336.B-ishstabilize-14333.B-ishrelease-R99-14469.B-ishrelease-R98-14388.B-ishrelease-R102-14695.B-ishrelease-R101-14588.B-ishrelease-R100-14526.B-ishfirmware-cherry-14454.B-ishfirmware-brya-14505.B-ishfirmware-brya-14505.71.B-ishfactory-kukui-14374.B-ishfactory-guybrush-14600.B-ishfactory-cherry-14455.B-ishfactory-brya-14517.B-ish
In the interest of making long-term branch maintenance incur as little
technical debt on us as possible, we should not maintain any files on
the branch we are not actually using.
This has the added effect of making it extremely clear when merging CLs
from the main branch when changes have the possibility to affect us.
The follow-on CL adds a convenience script to actually pull updates from
the main branch and generate a CL for the update.
BUG=b:204206272
BRANCH=ish
TEST=make BOARD=arcada_ish && make BOARD=drallion_ish
Signed-off-by: Jack Rosenthal <jrosenth@chromium.org>
Change-Id: I17e4694c38219b5a0823e0a3e55a28d1348f4b18
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3262038
Reviewed-by: Jett Rink <jettrink@chromium.org>
Reviewed-by: Tom Hughes <tomhughes@chromium.org>
Diffstat (limited to 'driver/charger')
-rw-r--r-- | driver/charger/bd9995x.c | 1775 | ||||
-rw-r--r-- | driver/charger/bd9995x.h | 352 | ||||
-rw-r--r-- | driver/charger/bq24715.c | 252 | ||||
-rw-r--r-- | driver/charger/bq24715.h | 132 | ||||
-rw-r--r-- | driver/charger/bq24773.c | 308 | ||||
-rw-r--r-- | driver/charger/bq24773.h | 91 | ||||
-rw-r--r-- | driver/charger/bq25710.c | 752 | ||||
-rw-r--r-- | driver/charger/bq25710.h | 143 | ||||
-rw-r--r-- | driver/charger/isl923x.c | 1471 | ||||
-rw-r--r-- | driver/charger/isl923x.h | 352 | ||||
-rw-r--r-- | driver/charger/isl9241.c | 599 | ||||
-rw-r--r-- | driver/charger/isl9241.h | 140 | ||||
-rw-r--r-- | driver/charger/rt946x.c | 1927 | ||||
-rw-r--r-- | driver/charger/rt946x.h | 853 | ||||
-rw-r--r-- | driver/charger/sm5803.c | 1933 | ||||
-rw-r--r-- | driver/charger/sm5803.h | 432 | ||||
-rw-r--r-- | driver/charger/sy21612.c | 213 | ||||
-rw-r--r-- | driver/charger/sy21612.h | 164 |
18 files changed, 0 insertions, 11889 deletions
diff --git a/driver/charger/bd9995x.c b/driver/charger/bd9995x.c deleted file mode 100644 index 6fd79b8d8f..0000000000 --- a/driver/charger/bd9995x.c +++ /dev/null @@ -1,1775 +0,0 @@ -/* Copyright 2016 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. - * - * ROHM BD9995X battery charger driver. - */ - -#include "battery.h" -#include "battery_smart.h" -#include "bd9995x.h" -#include "charge_manager.h" -#include "charge_state.h" -#include "charger.h" -#include "console.h" -#include "ec_commands.h" -#include "hooks.h" -#include "i2c.h" -#include "task.h" -#include "time.h" -#include "util.h" -#include "usb_charge.h" -#include "usb_pd.h" - -#define OTPROM_LOAD_WAIT_RETRY 3 - -#define BD9995X_CHARGE_PORT_COUNT 2 - -/* - * BC1.2 detection starts 100ms after VBUS/VCC attach and typically - * completes 312ms after VBUS/VCC attach. - */ -#define BC12_DETECT_US (312*MSEC) -#define BD9995X_VSYS_PRECHARGE_OFFSET_MV 200 - -/* Console output macros */ -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) - -#ifdef CONFIG_BD9995X_DELAY_INPUT_PORT_SELECT -/* - * Used in a check to determine if VBUS is within the - * range of some VOLTAGE +/- VBUS_DELTA, where voltage - * is measured in mV. - */ -#define VBUS_DELTA 1000 - -/* VBUS is debounced if it's stable for this length of time */ -#define VBUS_MSEC (100*MSEC) - -/* VBUS debouncing sample interval */ -#define VBUS_CHECK_MSEC (10*MSEC) - -/* Time to wait before VBUS debouncing begins */ -#define STABLE_TIMEOUT (500*MSEC) - -/* Maximum time to wait until VBUS is debounced */ -#define DEBOUNCE_TIMEOUT (500*MSEC) - -enum vstate {START, STABLE, DEBOUNCE}; -static enum vstate vbus_state; - -static int vbus_voltage; -static uint64_t debounce_time; -static uint64_t vbus_timeout; -static int port_update; -static int select_update; -static int select_input_port_update; -#endif - -/* Charger parameters */ -#define CHARGER_NAME BD9995X_CHARGER_NAME -#define CHARGE_V_MAX 19200 -#define CHARGE_V_MIN 3072 -#define CHARGE_V_STEP 16 -#define CHARGE_I_MAX 16320 -#define CHARGE_I_MIN 128 -#define CHARGE_I_OFF 0 -#define CHARGE_I_STEP 64 -#define INPUT_I_MAX 16352 -#define INPUT_I_MIN 512 -#define INPUT_I_STEP 32 - -/* Charger parameters */ -static const struct charger_info bd9995x_charger_info = { - .name = CHARGER_NAME, - .voltage_max = CHARGE_V_MAX, - .voltage_min = CHARGE_V_MIN, - .voltage_step = CHARGE_V_STEP, - .current_max = CHARGE_I_MAX, - .current_min = CHARGE_I_MIN, - .current_step = CHARGE_I_STEP, - .input_current_max = INPUT_I_MAX, - .input_current_min = INPUT_I_MIN, - .input_current_step = INPUT_I_STEP, -}; - -/* Charge command code map */ -static enum bd9995x_command charger_map_cmd = BD9995X_INVALID_COMMAND; - -/* Mutex for active register set control. */ -static struct mutex bd9995x_map_mutex; - -/* Tracks the state of VSYS_PRIORITY */ -static int vsys_priority; -/* Mutex for VIN_CTRL_SET register */ -static struct mutex bd9995x_vin_mutex; - -#ifdef HAS_TASK_USB_CHG -/* USB switch */ -static enum usb_switch usb_switch_state[BD9995X_CHARGE_PORT_COUNT] = { - USB_SWITCH_DISCONNECT, - USB_SWITCH_DISCONNECT, -}; - -static enum ec_error_list bd9995x_set_current(int chgnum, int current); -static enum ec_error_list bd9995x_set_voltage(int chgnum, int voltage); - -/* - * The USB Type-C specification limits the maximum amount of current from BC 1.2 - * suppliers to 1.5A. Technically, proprietary methods are not allowed, but we - * will continue to allow those. - */ -static int bd9995x_get_bc12_ilim(int charge_supplier) -{ - switch (charge_supplier) { - case CHARGE_SUPPLIER_BC12_CDP: - return USB_CHARGER_MAX_CURR_MA; - case CHARGE_SUPPLIER_BC12_DCP: - return USB_CHARGER_MAX_CURR_MA; - case CHARGE_SUPPLIER_BC12_SDP: - return 900; - case CHARGE_SUPPLIER_OTHER: -#ifdef CONFIG_CHARGE_RAMP_SW - return USB_CHARGER_MAX_CURR_MA; -#else - /* - * Setting the higher limit of current may result in an - * anti-collapse hence limiting the current to 1A. - */ - return 1000; -#endif - default: - return 500; - } -} -#endif /* HAS_TASK_USB_CHG */ - -static inline enum ec_error_list ch_raw_read16(int chgnum, int cmd, int *param, - enum bd9995x_command map_cmd) -{ - int rv; - - /* Map the Charge command code to appropriate region */ - mutex_lock(&bd9995x_map_mutex); - if (charger_map_cmd != map_cmd) { - rv = i2c_write16(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - BD9995X_CMD_MAP_SET, map_cmd); - if (rv) { - charger_map_cmd = BD9995X_INVALID_COMMAND; - goto bd9995x_read_cleanup; - } - - charger_map_cmd = map_cmd; - } - - rv = i2c_read16(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - cmd, param); - -bd9995x_read_cleanup: - mutex_unlock(&bd9995x_map_mutex); - - return rv; -} - -static inline enum ec_error_list ch_raw_write16(int chgnum, int cmd, int param, - enum bd9995x_command map_cmd) -{ - int rv; - - /* Map the Charge command code to appropriate region */ - mutex_lock(&bd9995x_map_mutex); - if (charger_map_cmd != map_cmd) { - rv = i2c_write16(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - BD9995X_CMD_MAP_SET, map_cmd); - if (rv) { - charger_map_cmd = BD9995X_INVALID_COMMAND; - goto bd9995x_write_cleanup; - } - - charger_map_cmd = map_cmd; - } - - rv = i2c_write16(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - cmd, param); - -bd9995x_write_cleanup: - mutex_unlock(&bd9995x_map_mutex); - - return rv; -} - -/* BD9995X local interfaces */ - -static int bd9995x_set_vfastchg(int chgnum, int voltage) -{ - - int rv; - - /* Fast Charge Voltage Regulation Settings for fast charging. */ - rv = ch_raw_write16(chgnum, BD9995X_CMD_VFASTCHG_REG_SET1, - voltage & 0x7FF0, BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - -#ifndef CONFIG_CHARGER_BATTERY_TSENSE - /* - * If TSENSE is not connected set all the VFASTCHG_REG_SETx - * to same voltage. - */ - rv = ch_raw_write16(chgnum, BD9995X_CMD_VFASTCHG_REG_SET2, - voltage & 0x7FF0, BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - rv = ch_raw_write16(chgnum, BD9995X_CMD_VFASTCHG_REG_SET3, - voltage & 0x7FF0, BD9995X_EXTENDED_COMMAND); -#endif - - return rv; -} - -static int bd9995x_set_vsysreg(int chgnum, int voltage) -{ - /* VSYS Regulation voltage is in 64mV steps. */ - voltage &= ~0x3F; - - return ch_raw_write16(chgnum, BD9995X_CMD_VSYSREG_SET, voltage, - BD9995X_EXTENDED_COMMAND); -} - -static int bd9995x_is_discharging_on_ac(int chgnum) -{ - int reg; - - if (ch_raw_read16(chgnum, BD9995X_CMD_CHGOP_SET2, ®, - BD9995X_EXTENDED_COMMAND)) - return 0; - - return !!(reg & BD9995X_CMD_CHGOP_SET2_BATT_LEARN); -} - -static int bd9995x_charger_enable(int chgnum, int enable) -{ - int rv, reg; - static int prev_chg_enable = -1; - const struct battery_info *bi = battery_get_info(); - -#ifdef CONFIG_CHARGER_BD9995X_CHGEN - /* - * If the battery is not yet initialized, dont turn-off the BGATE so - * that voltage from the AC is applied to the battery PACK. - */ - if (!enable && !board_battery_initialized()) - return EC_SUCCESS; -#endif - - /* Nothing to change */ - if (enable == prev_chg_enable) - return EC_SUCCESS; - - prev_chg_enable = enable; - - if (enable) { - /* - * BGATE capacitor max : 0.1uF + 20% - * Charge MOSFET threshold max : 2.8V - * BGATE charge pump current min : 3uA - * T = C * V / I so, Tmax = 112ms - */ - msleep(115); - - /* - * Set VSYSREG_SET <= VBAT so that the charger is in Fast-Charge - * state when charging. - */ - rv = bd9995x_set_vsysreg(chgnum, bi->voltage_min); - } else { - /* - * Set VSYSREG_SET > VBAT so that the charger is in Pre-Charge - * state when not charging or discharging. - */ - rv = bd9995x_set_vsysreg(chgnum, bi->voltage_max + - BD9995X_VSYS_PRECHARGE_OFFSET_MV); - - /* - * Allow charger in pre-charge state for 50ms before disabling - * the charger which prevents inrush current while moving from - * fast-charge state to pre-charge state. - */ - msleep(50); - } - if (rv) - return rv; - - rv = ch_raw_read16(chgnum, BD9995X_CMD_CHGOP_SET2, ®, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - if (enable) - reg |= BD9995X_CMD_CHGOP_SET2_CHG_EN; - else - reg &= ~BD9995X_CMD_CHGOP_SET2_CHG_EN; - - return ch_raw_write16(chgnum, BD9995X_CMD_CHGOP_SET2, reg, - BD9995X_EXTENDED_COMMAND); -} - -static int bd9995x_por_reset(int chgnum) -{ - int rv; - int reg; - int i; - - rv = ch_raw_write16(chgnum, BD9995X_CMD_SYSTEM_CTRL_SET, - BD9995X_CMD_SYSTEM_CTRL_SET_OTPLD | - BD9995X_CMD_SYSTEM_CTRL_SET_ALLRST, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - /* Wait until OTPROM loading is finished */ - for (i = 0; i < OTPROM_LOAD_WAIT_RETRY; i++) { - msleep(10); - rv = ch_raw_read16(chgnum, BD9995X_CMD_SYSTEM_STATUS, ®, - BD9995X_EXTENDED_COMMAND); - - if (!rv && (reg & BD9995X_CMD_SYSTEM_STATUS_OTPLD_STATE) && - (reg & BD9995X_CMD_SYSTEM_STATUS_ALLRST_STATE)) - break; - } - - if (rv) - return rv; - if (i == OTPROM_LOAD_WAIT_RETRY) - return EC_ERROR_TIMEOUT; - - return ch_raw_write16(chgnum, BD9995X_CMD_SYSTEM_CTRL_SET, 0, - BD9995X_EXTENDED_COMMAND); -} - -static int bd9995x_reset_to_zero(int chgnum) -{ - int rv; - - rv = bd9995x_set_current(chgnum, 0); - if (rv) - return rv; - - return bd9995x_set_voltage(chgnum, 0); -} - -static int bd9995x_get_charger_op_status(int chgnum, int *status) -{ - return ch_raw_read16(chgnum, BD9995X_CMD_CHGOP_STATUS, status, - BD9995X_EXTENDED_COMMAND); -} - -#ifdef HAS_TASK_USB_CHG -static int bc12_detected_type[CONFIG_USB_PD_PORT_MAX_COUNT]; -/* Mutex for UCD_SET registers, lock before read / mask / write. */ -static struct mutex ucd_set_mutex[BD9995X_CHARGE_PORT_COUNT]; - -static int bd9995x_get_bc12_device_type(int chgnum, int port) -{ - int rv; - int reg; - - rv = ch_raw_read16(chgnum, (port == BD9995X_CHARGE_PORT_VBUS) ? - BD9995X_CMD_VBUS_UCD_STATUS : - BD9995X_CMD_VCC_UCD_STATUS, - ®, BD9995X_EXTENDED_COMMAND); - if (rv) - return CHARGE_SUPPLIER_NONE; - - switch (reg & BD9995X_TYPE_MASK) { - case BD9995X_TYPE_CDP: - return CHARGE_SUPPLIER_BC12_CDP; - case BD9995X_TYPE_DCP: - return CHARGE_SUPPLIER_BC12_DCP; - case BD9995X_TYPE_SDP: - return CHARGE_SUPPLIER_BC12_SDP; - case BD9995X_TYPE_PUP_PORT: - case BD9995X_TYPE_OTHER: - return CHARGE_SUPPLIER_OTHER; - case BD9995X_TYPE_OPEN_PORT: - case BD9995X_TYPE_VBUS_OPEN: - default: - return CHARGE_SUPPLIER_NONE; - } -} - -/* - * Do safe read / mask / write of BD9995X_CMD_*_UCD_SET register. - * The USB charger task owns all bits of this register, except for bit 0 - * (BD9995X_CMD_UCD_SET_USB_SW), which is controlled by - * usb_charger_set_switches(). - */ -static int bd9995x_update_ucd_set_reg(int chgnum, int port, uint16_t mask, - int set) -{ - int rv; - int reg; - int port_reg = (port == BD9995X_CHARGE_PORT_VBUS) ? - BD9995X_CMD_VBUS_UCD_SET : BD9995X_CMD_VCC_UCD_SET; - - mutex_lock(&ucd_set_mutex[port]); - rv = ch_raw_read16(chgnum, port_reg, ®, BD9995X_EXTENDED_COMMAND); - if (!rv) { - if (set) - reg |= mask; - else - reg &= ~mask; - - rv = ch_raw_write16(chgnum, port_reg, reg, - BD9995X_EXTENDED_COMMAND); - } - - mutex_unlock(&ucd_set_mutex[port]); - return rv; -} - -static int bd9995x_bc12_check_type(int chgnum, int port) -{ - int bc12_type; - struct charge_port_info charge; - int vbus_provided = bd9995x_is_vbus_provided(port) && - !usb_charger_port_is_sourcing_vbus(port); - - /* - * If vbus is no longer provided, then no need to continue. Return 0 so - * that a wait event is not scheduled. - */ - if (!vbus_provided) - return 0; - - /* get device type */ - bc12_type = bd9995x_get_bc12_device_type(chgnum, port); - if (bc12_type == CHARGE_SUPPLIER_NONE) - /* - * Device type is not available, return non-zero so new wait - * will be scheduled before putting the task to sleep. - */ - return 1; - - bc12_detected_type[port] = bc12_type; - /* Update charge manager */ - charge.voltage = USB_CHARGER_VOLTAGE_MV; - charge.current = bd9995x_get_bc12_ilim(bc12_type); - charge_manager_update_charge(bc12_type, port, &charge); - - return 0; -} - -static void bd9995x_bc12_detach(int chgnum, int port, int type) -{ - /* Update charge manager */ - charge_manager_update_charge(type, port, NULL); - - /* Disable charging trigger by BC1.2 detection */ - bd9995x_bc12_enable_charging(port, 0); -} - -static int bd9995x_enable_vbus_detect_interrupts(int chgnum, int port, - int enable) -{ - int reg; - int rv; - int port_reg; - int mask_val; - - /* 1st Level Interrupt Setting */ - rv = ch_raw_read16(chgnum, BD9995X_CMD_INT0_SET, ®, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - mask_val = ((port == BD9995X_CHARGE_PORT_VBUS) ? - BD9995X_CMD_INT0_SET_INT1_EN : - BD9995X_CMD_INT0_SET_INT2_EN) | - BD9995X_CMD_INT0_SET_INT0_EN; - if (enable) - reg |= mask_val; - else - reg &= ~mask_val; - - rv = ch_raw_write16(chgnum, BD9995X_CMD_INT0_SET, reg, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - /* 2nd Level Interrupt Setting */ - port_reg = (port == BD9995X_CHARGE_PORT_VBUS) ? - BD9995X_CMD_INT1_SET : BD9995X_CMD_INT2_SET; - rv = ch_raw_read16(chgnum, port_reg, ®, BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - /* Enable threshold interrupts if we need to control discharge */ -#ifdef CONFIG_USB_PD_DISCHARGE - mask_val = BD9995X_CMD_INT_VBUS_DET | BD9995X_CMD_INT_VBUS_TH; -#else - mask_val = BD9995X_CMD_INT_VBUS_DET; -#endif - if (enable) - reg |= mask_val; - else - reg &= ~mask_val; - - return ch_raw_write16(chgnum, port_reg, reg, BD9995X_EXTENDED_COMMAND); -} - -/* Read + clear active interrupt bits for a given port */ -static int bd9995x_get_interrupts(int chgnum, int port) -{ - int rv; - int reg; - int port_reg; - - port_reg = (port == BD9995X_CHARGE_PORT_VBUS) ? - BD9995X_CMD_INT1_STATUS : BD9995X_CMD_INT2_STATUS; - - rv = ch_raw_read16(chgnum, port_reg, ®, BD9995X_EXTENDED_COMMAND); - - if (rv) - return 0; - - /* Clear the interrupt status bits we just read */ - ch_raw_write16(chgnum, port_reg, reg, BD9995X_EXTENDED_COMMAND); - - return reg; -} - -/* - * Set or clear registers necessary to do one-time BC1.2 detection. - * Pass enable = 1 to trigger BC1.2 detection, and enable = 0 once - * BC1.2 detection has completed. - */ -static int bd9995x_bc12_detect(int chgnum, int port, int enable) -{ - return bd9995x_update_ucd_set_reg(chgnum, port, - BD9995X_CMD_UCD_SET_BCSRETRY | - BD9995X_CMD_UCD_SET_USBDETEN | - BD9995X_CMD_UCD_SET_USB_SW_EN, - enable); -} - -static int usb_charger_process(int chgnum, int port) -{ - int vbus_provided = bd9995x_is_vbus_provided(port) && - !usb_charger_port_is_sourcing_vbus(port); - - /* Inform other modules about VBUS level */ - usb_charger_vbus_change(port, vbus_provided); - - /* - * Do BC1.2 detection, if we have VBUS and our port is not known - * to speak PD. - */ - if (vbus_provided && !pd_capable(port)) { - bd9995x_bc12_detect(chgnum, port, 1); - /* - * Need to give the charger time (~312 mSec) before the - * bc12_type is available. The main task loop will schedule a - * task wait event which will then call bd9995x_bc12_get_type. - */ - return 1; - } - - /* Reset BC1.2 regs so we don't do auto-detection. */ - bd9995x_bc12_detect(chgnum, port, 0); - - /* - * VBUS is no longer being provided, if the bc12_type had been - * previously determined, then need to detach. - */ - if (bc12_detected_type[port] != CHARGE_SUPPLIER_NONE) { - /* Charger/sink detached */ - bd9995x_bc12_detach(chgnum, port, bc12_detected_type[port]); - bc12_detected_type[port] = CHARGE_SUPPLIER_NONE; - } - /* No need for the task to schedule a wait event */ - return 0; -} - -#ifdef CONFIG_CHARGE_RAMP_SW -static int bd9995x_ramp_allowed(int supplier) -{ - return supplier == CHARGE_SUPPLIER_BC12_DCP || - supplier == CHARGE_SUPPLIER_BC12_SDP || - supplier == CHARGE_SUPPLIER_BC12_CDP || - supplier == CHARGE_SUPPLIER_OTHER; -} - -static int bd9995x_ramp_max(int supplier, int sup_curr) -{ - return bd9995x_get_bc12_ilim(supplier); -} -#endif /* CONFIG_CHARGE_RAMP_SW */ -#endif /* HAS_TASK_USB_CHG */ - -/* chip specific interfaces */ - -static enum ec_error_list bd9995x_set_input_current_limit(int chgnum, - int input_current) -{ - int rv; - - /* Input current step 32 mA */ - input_current &= ~0x1F; - - if (input_current < bd9995x_charger_info.input_current_min) - input_current = bd9995x_charger_info.input_current_min; - - rv = ch_raw_write16(chgnum, BD9995X_CMD_IBUS_LIM_SET, input_current, - BD9995X_BAT_CHG_COMMAND); - if (rv) - return rv; - - return ch_raw_write16(chgnum, BD9995X_CMD_ICC_LIM_SET, input_current, - BD9995X_BAT_CHG_COMMAND); -} - -static enum ec_error_list bd9995x_get_input_current_limit(int chgnum, - int *input_current) -{ - return ch_raw_read16(chgnum, BD9995X_CMD_CUR_ILIM_VAL, input_current, - BD9995X_EXTENDED_COMMAND); -} - -static enum ec_error_list bd9995x_manufacturer_id(int chgnum, int *id) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -static enum ec_error_list bd9995x_device_id(int chgnum, int *id) -{ - return ch_raw_read16(chgnum, BD9995X_CMD_CHIP_ID, id, - BD9995X_EXTENDED_COMMAND); -} - -static enum ec_error_list bd9995x_get_option(int chgnum, int *option) -{ - int rv; - int reg; - - rv = ch_raw_read16(chgnum, BD9995X_CMD_CHGOP_SET1, option, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - rv = ch_raw_read16(chgnum, BD9995X_CMD_CHGOP_SET2, ®, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - *option |= reg << 16; - - return EC_SUCCESS; -} - -static enum ec_error_list bd9995x_set_option(int chgnum, int option) -{ - int rv; - - rv = ch_raw_write16(chgnum, BD9995X_CMD_CHGOP_SET1, option & 0xFFFF, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - return ch_raw_write16(chgnum, BD9995X_CMD_CHGOP_SET2, - (option >> 16) & 0xFFFF, - BD9995X_EXTENDED_COMMAND); -} - -/* Charger interfaces */ - -static const struct charger_info *bd9995x_get_info(int chgnum) -{ - return &bd9995x_charger_info; -} - -static enum ec_error_list bd9995x_get_status(int chgnum, int *status) -{ - int rv; - int reg; - int ch_status; - - /* charger level */ - *status = CHARGER_LEVEL_2; - - /* charger enable/inhibit */ - rv = ch_raw_read16(chgnum, BD9995X_CMD_CHGOP_SET2, ®, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - if (!(reg & BD9995X_CMD_CHGOP_SET2_CHG_EN)) - *status |= CHARGER_CHARGE_INHIBITED; - - /* charger alarm enable/inhibit */ - rv = ch_raw_read16(chgnum, BD9995X_CMD_PROCHOT_CTRL_SET, ®, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - if (!(reg & (BD9995X_CMD_PROCHOT_CTRL_SET_PROCHOT_EN4 | - BD9995X_CMD_PROCHOT_CTRL_SET_PROCHOT_EN3 | - BD9995X_CMD_PROCHOT_CTRL_SET_PROCHOT_EN2 | - BD9995X_CMD_PROCHOT_CTRL_SET_PROCHOT_EN1 | - BD9995X_CMD_PROCHOT_CTRL_SET_PROCHOT_EN0))) - *status |= CHARGER_ALARM_INHIBITED; - - rv = bd9995x_get_charger_op_status(chgnum, ®); - if (rv) - return rv; - - /* power fail */ - if (!(reg & BD9995X_CMD_CHGOP_STATUS_RBOOST_UV)) - *status |= CHARGER_POWER_FAIL; - - /* Safety signal ranges & battery presence */ - ch_status = (reg & BD9995X_BATTTEMP_MASK) >> 8; - - *status |= CHARGER_BATTERY_PRESENT; - - switch (ch_status) { - case BD9995X_CMD_CHGOP_STATUS_BATTEMP_COLD1: - *status |= CHARGER_RES_COLD; - break; - case BD9995X_CMD_CHGOP_STATUS_BATTEMP_COLD2: - *status |= CHARGER_RES_COLD; - *status |= CHARGER_RES_UR; - break; - case BD9995X_CMD_CHGOP_STATUS_BATTEMP_HOT1: - case BD9995X_CMD_CHGOP_STATUS_BATTEMP_HOT2: - *status |= CHARGER_RES_HOT; - break; - case BD9995X_CMD_CHGOP_STATUS_BATTEMP_HOT3: - *status |= CHARGER_RES_HOT; - *status |= CHARGER_RES_OR; - break; - case BD9995X_CMD_CHGOP_STATUS_BATTEMP_BATOPEN: - *status &= ~CHARGER_BATTERY_PRESENT; - default: - break; - } - - /* source of power */ - if (bd9995x_is_vbus_provided(BD9995X_CHARGE_PORT_BOTH)) - *status |= CHARGER_AC_PRESENT; - - return EC_SUCCESS; -} - -static enum ec_error_list bd9995x_set_mode(int chgnum, int mode) -{ - int rv; - - if (mode & CHARGE_FLAG_POR_RESET) { - rv = bd9995x_por_reset(chgnum); - if (rv) - return rv; - } - - if (mode & CHARGE_FLAG_RESET_TO_ZERO) { - rv = bd9995x_reset_to_zero(chgnum); - if (rv) - return rv; - } - - return EC_SUCCESS; -} - -static enum ec_error_list bd9995x_get_current(int chgnum, int *current) -{ - return ch_raw_read16(chgnum, BD9995X_CMD_CHG_CURRENT, current, - BD9995X_BAT_CHG_COMMAND); -} - -static enum ec_error_list bd9995x_set_current(int chgnum, int current) -{ - int rv; - int chg_enable = 1; - - /* Charge current step 64 mA */ - current &= ~0x3F; - - if (current < BD9995X_NO_BATTERY_CHARGE_I_MIN && - (battery_is_present() != BP_YES || battery_is_cut_off())) - current = BD9995X_NO_BATTERY_CHARGE_I_MIN; - - /* - * Disable charger before setting charge current to 0 or when - * discharging on AC. - * If charging current is set to 0mA during charging, reference of - * the charge current feedback amp (VREF_CHG) is set to 0V. Hence - * the DCDC stops switching (because of the EA offset). - */ - if (!current || bd9995x_is_discharging_on_ac(chgnum)) { - chg_enable = 0; - rv = bd9995x_charger_enable(chgnum, 0); - if (rv) - return rv; - } - - rv = ch_raw_write16(chgnum, BD9995X_CMD_IPRECH_SET, - MIN(current, BD9995X_IPRECH_MAX), - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - rv = ch_raw_write16(chgnum, BD9995X_CMD_CHG_CURRENT, current, - BD9995X_BAT_CHG_COMMAND); - if (rv) - return rv; - - /* - * Enable charger if charge current is non-zero or not discharging - * on AC. - */ - return chg_enable ? bd9995x_charger_enable(chgnum, 1) : EC_SUCCESS; -} - -static enum ec_error_list bd9995x_get_voltage(int chgnum, int *voltage) -{ - if (vsys_priority) { - int batt_volt_measured; - int reg; - int rv; - - /* Get battery voltage as reported by charger */ - batt_volt_measured = bd9995x_get_battery_voltage(); - if (batt_volt_measured > (battery_get_info()->voltage_min + - BD9995X_VSYS_PRECHARGE_OFFSET_MV)) { - /* - * Battery is not deeply discharged. Clear the - * VSYS_PRIORITY bit to ensure that input current limit - * is always active. - */ - mutex_lock(&bd9995x_vin_mutex); - if (!ch_raw_read16(chgnum, BD9995X_CMD_VIN_CTRL_SET, - ®, BD9995X_EXTENDED_COMMAND)) { - reg &= ~BD9995X_CMD_VIN_CTRL_SET_VSYS_PRIORITY; - rv = ch_raw_write16(chgnum, - BD9995X_CMD_VIN_CTRL_SET, - reg, - BD9995X_EXTENDED_COMMAND); - - /* Mirror the state of this bit */ - if (!rv) - vsys_priority = 0; - } - mutex_unlock(&bd9995x_vin_mutex); - } - } - - return ch_raw_read16(chgnum, BD9995X_CMD_CHG_VOLTAGE, voltage, - BD9995X_BAT_CHG_COMMAND); -} - -static enum ec_error_list bd9995x_set_voltage(int chgnum, int voltage) -{ - const int battery_voltage_max = battery_get_info()->voltage_max; - - /* - * Regulate the system voltage to battery max if the battery - * is not present or the battery is discharging on AC. - */ - if (voltage == 0 || - bd9995x_is_discharging_on_ac(chgnum) || - battery_is_present() != BP_YES || - battery_is_cut_off() || - voltage > battery_voltage_max) - voltage = battery_voltage_max; - - /* Charge voltage step 16 mV */ - voltage &= ~0x0F; - - /* Assumes charger's voltage_min < battery's voltage_max */ - if (voltage < bd9995x_charger_info.voltage_min) - voltage = bd9995x_charger_info.voltage_min; - - return bd9995x_set_vfastchg(chgnum, voltage); -} - -static void bd9995x_battery_charging_profile_settings(int chgnum) -{ - const struct battery_info *bi = battery_get_info(); - - /* Input Current Limit Setting */ - bd9995x_set_input_current_limit(chgnum, CONFIG_CHARGER_INPUT_CURRENT); - - /* Charge Termination Current Setting */ - ch_raw_write16(chgnum, BD9995X_CMD_ITERM_SET, 0, - BD9995X_EXTENDED_COMMAND); - - /* Trickle-charge Current Setting */ - ch_raw_write16(chgnum, BD9995X_CMD_ITRICH_SET, - bi->precharge_current & 0x07C0, - BD9995X_EXTENDED_COMMAND); - - bd9995x_set_vfastchg(chgnum, bi->voltage_max); - - /* Set Pre-charge Voltage Threshold for trickle charging. */ - ch_raw_write16(chgnum, BD9995X_CMD_VPRECHG_TH_SET, - (bi->voltage_min - 1000) & 0x7FC0, - BD9995X_EXTENDED_COMMAND); - - /* Re-charge Battery Voltage Setting */ - ch_raw_write16(chgnum, BD9995X_CMD_VRECHG_SET, - bi->voltage_max & 0x7FF0, - BD9995X_EXTENDED_COMMAND); - - /* Set battery OVP to 500 + maximum battery voltage */ - ch_raw_write16(chgnum, BD9995X_CMD_VBATOVP_SET, - (bi->voltage_max + 500) & 0x7ff0, - BD9995X_EXTENDED_COMMAND); - - /* Reverse buck boost voltage Setting */ - ch_raw_write16(chgnum, BD9995X_CMD_VRBOOST_SET, 0, - BD9995X_EXTENDED_COMMAND); - - /* Disable fast/pre-charging watchdog */ - ch_raw_write16(chgnum, BD9995X_CMD_CHGWDT_SET, 0, - BD9995X_EXTENDED_COMMAND); - - /* TODO(crosbug.com/p/55626): Set VSYSVAL_THH/THL appropriately */ -} - -/* - * Note: opting not to use charger driver init here due to the different - * priority (other drivers use HOOK_PRIO_INIT_I2C + 1) - */ -static void bd9995x_init(void) -{ - int reg; - - /* - * Disable charging trigger by BC1.2 on VCC & VBUS and - * automatic limitation of the input current. - */ - if (ch_raw_read16(CHARGER_SOLO, BD9995X_CMD_CHGOP_SET1, ®, - BD9995X_EXTENDED_COMMAND)) - return; - reg |= (BD9995X_CMD_CHGOP_SET1_SDP_CHG_TRIG_EN | - BD9995X_CMD_CHGOP_SET1_SDP_CHG_TRIG | - BD9995X_CMD_CHGOP_SET1_VBUS_BC_DISEN | - BD9995X_CMD_CHGOP_SET1_VCC_BC_DISEN | - BD9995X_CMD_CHGOP_SET1_ILIM_AUTO_DISEN | - BD9995X_CMD_CHGOP_SET1_SDP_500_SEL | - BD9995X_CMD_CHGOP_SET1_DCP_2500_SEL); - ch_raw_write16(CHARGER_SOLO, BD9995X_CMD_CHGOP_SET1, reg, - BD9995X_EXTENDED_COMMAND); - - /* - * OTP setting for this register is 6.08V. Set VSYS to above battery max - * (as is done when charger is disabled) to ensure VSYSREG_SET > VBAT so - * that the charger is in Pre-Charge state and that the input current - * disable setting below will be active. - */ - bd9995x_set_vsysreg(CHARGER_SOLO, battery_get_info()->voltage_max + - BD9995X_VSYS_PRECHARGE_OFFSET_MV); - - /* Enable BC1.2 USB charging and DC/DC converter @ 1200KHz */ - if (ch_raw_read16(CHARGER_SOLO, BD9995X_CMD_CHGOP_SET2, ®, - BD9995X_EXTENDED_COMMAND)) - return; - reg &= ~(BD9995X_CMD_CHGOP_SET2_USB_SUS | - BD9995X_CMD_CHGOP_SET2_DCDC_CLK_SEL); - reg |= BD9995X_CMD_CHGOP_SET2_DCDC_CLK_SEL_1200; -#ifdef CONFIG_CHARGER_BD9995X_CHGEN - reg |= BD9995X_CMD_CHGOP_SET2_CHG_EN; -#endif - ch_raw_write16(CHARGER_SOLO, BD9995X_CMD_CHGOP_SET2, reg, - BD9995X_EXTENDED_COMMAND); - - /* - * We disable IADP (here before setting IBUS_LIM_SET and ICC_LIM_SET) - * to prevent voltage on IADP/RESET pin from affecting SEL_ILIM_VAL. - */ - if (ch_raw_read16(CHARGER_SOLO, BD9995X_CMD_VM_CTRL_SET, ®, - BD9995X_EXTENDED_COMMAND)) - return; - reg &= ~BD9995X_CMD_VM_CTRL_SET_EXTIADPEN; - ch_raw_write16(CHARGER_SOLO, BD9995X_CMD_VM_CTRL_SET, reg, - BD9995X_EXTENDED_COMMAND); - /* - * Disable the input current limit when VBAT is < VSYSREG_SET. This - * needs to be done before calling - * bd9995x_battery_charging_profile_settings() as in that function the - * input current limit is set to CONFIG_CHARGER_INPUT_CURRENT which is - * 512 mA. In deeply discharged battery cases, setting the input current - * limit this low can cause VSYS to collapse, which in turn can cause - * the EC's brownout detector to reset the EC. - */ - if (ch_raw_read16(CHARGER_SOLO, BD9995X_CMD_VIN_CTRL_SET, ®, - BD9995X_EXTENDED_COMMAND)) - return; - reg |= BD9995X_CMD_VIN_CTRL_SET_VSYS_PRIORITY; - ch_raw_write16(CHARGER_SOLO, BD9995X_CMD_VIN_CTRL_SET, reg, - BD9995X_EXTENDED_COMMAND); - /* Mirror the state of this bit */ - vsys_priority = 1; - - /* Define battery charging profile */ - bd9995x_battery_charging_profile_settings(CHARGER_SOLO); - - /* Power save mode when VBUS/VCC is removed. */ -#ifdef CONFIG_BD9995X_POWER_SAVE_MODE - bd9995x_set_power_save_mode(CONFIG_BD9995X_POWER_SAVE_MODE); -#else - bd9995x_set_power_save_mode(BD9995X_PWR_SAVE_OFF); -#endif - -#ifdef CONFIG_USB_PD_DISCHARGE - /* Set VBUS / VCC detection threshold for discharge enable */ - ch_raw_write16(CHARGER_SOLO, BD9995X_CMD_VBUS_TH_SET, - BD9995X_VBUS_DISCHARGE_TH, BD9995X_EXTENDED_COMMAND); - ch_raw_write16(CHARGER_SOLO, BD9995X_CMD_VCC_TH_SET, - BD9995X_VBUS_DISCHARGE_TH, BD9995X_EXTENDED_COMMAND); -#endif - - /* Unlock debug regs */ - ch_raw_write16(CHARGER_SOLO, BD9995X_CMD_PROTECT_SET, 0x3c, - BD9995X_EXTENDED_COMMAND); - - /* Undocumented - reverse current threshold = -50mV */ - ch_raw_write16(CHARGER_SOLO, 0x14, 0x0202, BD9995X_DEBUG_COMMAND); - /* Undocumented - internal gain = 2x */ - ch_raw_write16(CHARGER_SOLO, 0x1a, 0x80, BD9995X_DEBUG_COMMAND); - - /* Re-lock debug regs */ - ch_raw_write16(CHARGER_SOLO, BD9995X_CMD_PROTECT_SET, 0x0, - BD9995X_EXTENDED_COMMAND); -} -DECLARE_HOOK(HOOK_INIT, bd9995x_init, HOOK_PRIO_INIT_EXTPOWER); - -static enum ec_error_list bd9995x_post_init(int chgnum) -{ - return EC_SUCCESS; -} - -static enum ec_error_list bd9995x_discharge_on_ac(int chgnum, int enable) -{ - int rv; - int reg; - - rv = ch_raw_read16(chgnum, BD9995X_CMD_CHGOP_SET2, ®, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - /* - * Suspend USB charging and DC/DC converter so that BATT_LEARN mode - * doesn't auto exit if VBAT < VSYSVAL_THL_SET and also it helps to - * discharge VBUS quickly when charging is not allowed and the AC - * is removed. - */ - if (enable) - reg |= BD9995X_CMD_CHGOP_SET2_BATT_LEARN | - BD9995X_CMD_CHGOP_SET2_USB_SUS; - else - reg &= ~(BD9995X_CMD_CHGOP_SET2_BATT_LEARN | - BD9995X_CMD_CHGOP_SET2_USB_SUS); - - return ch_raw_write16(chgnum, BD9995X_CMD_CHGOP_SET2, reg, - BD9995X_EXTENDED_COMMAND); -} - -static enum ec_error_list bd9995x_get_vbus_voltage(int chgnum, int port, - int *voltage) -{ - uint8_t read_reg; - - read_reg = (port == BD9995X_CHARGE_PORT_VBUS) ? BD9995X_CMD_VBUS_VAL : - BD9995X_CMD_VCC_VAL; - - return ch_raw_read16(chgnum, read_reg, voltage, - BD9995X_EXTENDED_COMMAND); -} - -/*** Non-standard interface functions ***/ - -int bd9995x_is_vbus_provided(enum bd9995x_charge_port port) -{ - int reg; - - if (ch_raw_read16(CHARGER_SOLO, BD9995X_CMD_VBUS_VCC_STATUS, ®, - BD9995X_EXTENDED_COMMAND)) - return 0; - - if (port == BD9995X_CHARGE_PORT_VBUS) - reg &= BD9995X_CMD_VBUS_VCC_STATUS_VBUS_DETECT; - else if (port == BD9995X_CHARGE_PORT_VCC) - reg &= BD9995X_CMD_VBUS_VCC_STATUS_VCC_DETECT; - else if (port == BD9995X_CHARGE_PORT_BOTH) { - /* Check VBUS on either port */ - reg &= (BD9995X_CMD_VBUS_VCC_STATUS_VCC_DETECT | - BD9995X_CMD_VBUS_VCC_STATUS_VBUS_DETECT); - } else - reg = 0; - - return !!reg; -} - -#ifdef CONFIG_BD9995X_DELAY_INPUT_PORT_SELECT -static int bd9995x_select_input_port_private(enum bd9995x_charge_port port, - int select) -#else -int bd9995x_select_input_port(enum bd9995x_charge_port port, int select) -#endif -{ - int rv; - int reg; - - mutex_lock(&bd9995x_vin_mutex); - rv = ch_raw_read16(CHARGER_SOLO, BD9995X_CMD_VIN_CTRL_SET, ®, - BD9995X_EXTENDED_COMMAND); - if (rv) - goto select_input_port_exit; - - if (select) { - if (port == BD9995X_CHARGE_PORT_VBUS) { - reg |= BD9995X_CMD_VIN_CTRL_SET_VBUS_EN; - reg &= ~BD9995X_CMD_VIN_CTRL_SET_VCC_EN; - } else if (port == BD9995X_CHARGE_PORT_VCC) { - reg |= BD9995X_CMD_VIN_CTRL_SET_VCC_EN; - reg &= ~BD9995X_CMD_VIN_CTRL_SET_VBUS_EN; - } else if (port == BD9995X_CHARGE_PORT_BOTH) { - /* Enable both the ports for PG3 */ - reg |= BD9995X_CMD_VIN_CTRL_SET_VBUS_EN | - BD9995X_CMD_VIN_CTRL_SET_VCC_EN; - } else { - /* Invalid charge port */ - panic("Invalid charge port"); - } - } else { - if (port == BD9995X_CHARGE_PORT_VBUS) - reg &= ~BD9995X_CMD_VIN_CTRL_SET_VBUS_EN; - else if (port == BD9995X_CHARGE_PORT_VCC) - reg &= ~BD9995X_CMD_VIN_CTRL_SET_VCC_EN; - else if (port == BD9995X_CHARGE_PORT_BOTH) - reg &= ~(BD9995X_CMD_VIN_CTRL_SET_VBUS_EN | - BD9995X_CMD_VIN_CTRL_SET_VCC_EN); - else - panic("Invalid charge port"); - } - - rv = ch_raw_write16(CHARGER_SOLO, BD9995X_CMD_VIN_CTRL_SET, reg, - BD9995X_EXTENDED_COMMAND); -select_input_port_exit: - mutex_unlock(&bd9995x_vin_mutex); - return rv; -} - -#ifdef CONFIG_BD9995X_DELAY_INPUT_PORT_SELECT -int bd9995x_select_input_port(enum bd9995x_charge_port port, int select) -{ - port_update = port; - select_update = select; - vbus_state = START; - select_input_port_update = 1; - task_wake(TASK_ID_USB_CHG); - - return EC_SUCCESS; -} - -static inline int bd9995x_vbus_test(int value, int limit) -{ - uint32_t hi_value = limit + VBUS_DELTA; - uint32_t lo_value = limit - VBUS_DELTA; - - return ((value > lo_value) && (value < hi_value)); -} - -static int bd9995x_vbus_debounce(int chgnum, enum bd9995x_charge_port port) -{ - int vbus_reg; - int voltage; - - vbus_reg = (port == BD9995X_CHARGE_PORT_VBUS) ? - BD9995X_CMD_VBUS_VAL : BD9995X_CMD_VCC_VAL; - if (ch_raw_read16(chgnum, vbus_reg, &voltage, BD9995X_EXTENDED_COMMAND)) - voltage = 0; - - if (!bd9995x_vbus_test(voltage, vbus_voltage)) { - vbus_voltage = voltage; - debounce_time = get_time().val + VBUS_MSEC; - } else { - if (get_time().val >= debounce_time) - return 1; - } - - return 0; -} -#endif - - -#ifdef CONFIG_CHARGER_BATTERY_TSENSE -int bd9995x_get_battery_temp(int *temp_ptr) -{ - int rv; - - rv = ch_raw_read16(CHARGER_SOLO, BD9995X_CMD_THERM_VAL, temp_ptr, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - /* Degrees C = 200 - THERM_VAL, range is -55C-200C, 1C steps */ - *temp_ptr = 200 - *temp_ptr; - return EC_SUCCESS; -} -#endif - -void bd9995x_set_power_save_mode(int mode) -{ - ch_raw_write16(CHARGER_SOLO, BD9995X_CMD_SMBREG, mode, - BD9995X_EXTENDED_COMMAND); -} - -int bd9995x_get_battery_voltage(void) -{ - int vbat_val, rv; - - rv = ch_raw_read16(CHARGER_SOLO, BD9995X_CMD_VBAT_VAL, &vbat_val, - BD9995X_EXTENDED_COMMAND); - - return rv ? 0 : vbat_val; -} - -#ifdef HAS_TASK_USB_CHG -int bd9995x_bc12_enable_charging(int port, int enable) -{ - int rv; - int reg; - int mask_val; - - /* - * For BC1.2, enable VBUS/VCC_BC_DISEN charging trigger by BC1.2 - * detection and disable SDP_CHG_TRIG, SDP_CHG_TRIG_EN. Vice versa - * for USB-C. - */ - rv = ch_raw_read16(CHARGER_SOLO, BD9995X_CMD_CHGOP_SET1, ®, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - mask_val = (BD9995X_CMD_CHGOP_SET1_SDP_CHG_TRIG_EN | - BD9995X_CMD_CHGOP_SET1_SDP_CHG_TRIG | - ((port == BD9995X_CHARGE_PORT_VBUS) ? - BD9995X_CMD_CHGOP_SET1_VBUS_BC_DISEN : - BD9995X_CMD_CHGOP_SET1_VCC_BC_DISEN)); - - if (enable) - reg &= ~mask_val; - else - reg |= mask_val; - - return ch_raw_write16(CHARGER_SOLO, BD9995X_CMD_CHGOP_SET1, reg, - BD9995X_EXTENDED_COMMAND); -} - -static void bd9995x_set_switches(int port, enum usb_switch setting) -{ - /* If switch is not changing then return */ - if (setting == usb_switch_state[port]) - return; - - if (setting != USB_SWITCH_RESTORE) - usb_switch_state[port] = setting; - - /* ensure we disable power saving when we are using DP/DN */ -#ifdef CONFIG_BD9995X_POWER_SAVE_MODE - bd9995x_set_power_save_mode( - (usb_switch_state[0] == USB_SWITCH_DISCONNECT && - usb_switch_state[1] == USB_SWITCH_DISCONNECT) - ? CONFIG_BD9995X_POWER_SAVE_MODE : BD9995X_PWR_SAVE_OFF); -#endif - - bd9995x_update_ucd_set_reg(CHARGER_SOLO, port, - BD9995X_CMD_UCD_SET_USB_SW, - usb_switch_state[port] == USB_SWITCH_CONNECT); -} - -void bd9995x_vbus_interrupt(enum gpio_signal signal) -{ - task_wake(TASK_ID_USB_CHG); -} - -static void bd9995x_usb_charger_task(const int unused) -{ - static int initialized; - int changed, port, interrupts; - int sleep_usec; - uint64_t bc12_det_mark[CONFIG_USB_PD_PORT_MAX_COUNT]; -#ifdef CONFIG_USB_PD_DISCHARGE - int vbus_reg, voltage; -#endif - -#ifdef CONFIG_BD9995X_DELAY_INPUT_PORT_SELECT - select_input_port_update = 0; - vbus_voltage = 0; -#endif - - for (port = 0; port < board_get_usb_pd_port_count(); port++) { - bc12_detected_type[port] = CHARGE_SUPPLIER_NONE; - bd9995x_enable_vbus_detect_interrupts(CHARGER_SOLO, port, 1); - bc12_det_mark[port] = 0; - } - - while (1) { - sleep_usec = -1; - changed = 0; - for (port = 0; port < board_get_usb_pd_port_count(); port++) { - /* Get port interrupts */ - interrupts = bd9995x_get_interrupts(CHARGER_SOLO, port); - if (interrupts & BD9995X_CMD_INT_VBUS_DET || - !initialized) { - /* - * Detect based on current state of VBUS. If - * VBUS is provided, then need to wait for - * bc12_type to be available. If VBUS is not - * provided, then disable wait for this port. - */ - bc12_det_mark[port] = - usb_charger_process(CHARGER_SOLO, port) - ? get_time().val + BC12_DETECT_US : 0; - changed = 1; - } -#ifdef CONFIG_USB_PD_DISCHARGE - if (interrupts & BD9995X_CMD_INT_VBUS_TH || - !initialized) { - /* Get VBUS voltage */ - vbus_reg = (port == BD9995X_CHARGE_PORT_VBUS) ? - BD9995X_CMD_VBUS_VAL : - BD9995X_CMD_VCC_VAL; - if (ch_raw_read16(CHARGER_SOLO, vbus_reg, - &voltage, - BD9995X_EXTENDED_COMMAND)) - voltage = 0; - - /* Set discharge accordingly */ - pd_set_vbus_discharge(port, - voltage < BD9995X_VBUS_DISCHARGE_TH); - changed = 1; - } -#endif - if (bc12_det_mark[port] && (get_time().val > - bc12_det_mark[port])) { - /* - * bc12_type result should be available. If not - * available still, then function will return - * 1. Set up additional 100 msec wait. Note that - * if VBUS is no longer provided when this call - * happens the function will return 0. - */ - bc12_det_mark[port] = - bd9995x_bc12_check_type(CHARGER_SOLO, - port) ? - get_time().val + 100 * MSEC : 0; - /* Reset BC1.2 regs to skip auto-detection. */ - bd9995x_bc12_detect(CHARGER_SOLO, port, 0); - } - - /* - * Determine if a wait for reading bc12_type needs to be - * scheduled. Use the scheduled wait for this port if - * it's less than the wait needed for a previous - * port. If previous port(s) don't need a wait, then - * sleep_usec will be -1. - */ - if (bc12_det_mark[port]) { - int bc12_wait_usec; - - bc12_wait_usec = bc12_det_mark[port] - - get_time().val; - if ((sleep_usec < 0) || - (sleep_usec > bc12_wait_usec)) - sleep_usec = bc12_wait_usec; - } - } - - initialized = 1; -#ifdef CONFIG_BD9995X_DELAY_INPUT_PORT_SELECT -/* - * When a charge port is selected and VBUS is 5V, the inrush current on some - * devices causes VBUS to droop, which could signal a sink disconnection. - * - * To mitigate the problem, charge port selection is delayed until VBUS - * is stable or one second has passed. Hopefully PD has negotiated a VBUS - * voltage of at least 9V before the one second timeout. - */ - if (select_input_port_update) { - sleep_usec = VBUS_CHECK_MSEC; - changed = 0; - - switch (vbus_state) { - case START: - vbus_timeout = get_time().val + STABLE_TIMEOUT; - vbus_state = STABLE; - break; - case STABLE: - if (get_time().val > vbus_timeout) { - vbus_state = DEBOUNCE; - vbus_timeout = get_time().val + - DEBOUNCE_TIMEOUT; - } - break; - case DEBOUNCE: - if (bd9995x_vbus_debounce(CHARGER_SOLO, port_update) || - get_time().val > vbus_timeout) { - select_input_port_update = 0; - bd9995x_select_input_port_private( - port_update, select_update); - } - break; - } - } -#endif - - /* - * Re-read interrupt registers immediately if we got an - * interrupt. We're dealing with multiple independent - * interrupt sources and the interrupt pin may have - * never deasserted if both sources were not in clear - * state simultaneously. - */ - if (!changed) - task_wait_event(sleep_usec); - } -} -#endif /* HAS_TASK_USB_CHG */ - - -/*** Console commands ***/ -#ifdef CONFIG_CMD_CHARGER_DUMP -static int read_bat(int chgnum, uint8_t cmd) -{ - int read = 0; - - ch_raw_read16(chgnum, cmd, &read, BD9995X_BAT_CHG_COMMAND); - return read; -} - -static int read_ext(int chgnum, uint8_t cmd) -{ - int read = 0; - - ch_raw_read16(chgnum, cmd, &read, BD9995X_EXTENDED_COMMAND); - return read; -} - -/* Dump all readable registers on bd9995x */ -static int console_bd9995x_dump_regs(int argc, char **argv) -{ - int i; - uint8_t regs[] = { 0x14, 0x15, 0x3c, 0x3d, 0x3e, 0x3f }; - - /* Battery group registers */ - for (i = 0; i < ARRAY_SIZE(regs); ++i) - ccprintf("BAT REG %4x: %4x\n", regs[i], read_bat(CHARGER_SOLO, - regs[i])); - - /* Extended group registers */ - for (i = 0; i < 0x7f; ++i) { - ccprintf("EXT REG %4x: %4x\n", i, read_ext(CHARGER_SOLO, i)); - cflush(); - } - - return 0; -} -DECLARE_CONSOLE_COMMAND(charger_dump, console_bd9995x_dump_regs, - NULL, - "Dump all charger registers"); -#endif /* CONFIG_CMD_CHARGER_DUMP */ - -#ifdef CONFIG_CMD_CHARGER -static int console_command_bd9995x(int argc, char **argv) -{ - int rv, reg, data, val; - char rw, *e; - enum bd9995x_command cmd; - - if (argc < 4) - return EC_ERROR_PARAM_COUNT; - - rw = argv[1][0]; - if (rw == 'w' && argc < 5) - return EC_ERROR_PARAM_COUNT; - else if (rw != 'w' && rw != 'r') - return EC_ERROR_PARAM1; - - reg = strtoi(argv[2], &e, 16); - if (*e || reg < 0) - return EC_ERROR_PARAM2; - - cmd = strtoi(argv[3], &e, 0); - if (*e || cmd < 0) - return EC_ERROR_PARAM3; - - if (rw == 'r') - rv = ch_raw_read16(CHARGER_SOLO, reg, &data, cmd); - else { - val = strtoi(argv[4], &e, 16); - if (*e || val < 0) - return EC_ERROR_PARAM4; - - rv = ch_raw_write16(CHARGER_SOLO, reg, val, cmd); - if (rv == EC_SUCCESS) - rv = ch_raw_read16(CHARGER_SOLO, reg, &data, cmd); - } - - if (rv == EC_SUCCESS) - CPRINTS("register 0x%x [%d] = 0x%x [%d]", reg, reg, data, data); - - return rv; -} -DECLARE_CONSOLE_COMMAND(bd9995x, console_command_bd9995x, - "bd9995x <r/w> <reg_hex> <cmd_type> | <val_hex>", - "Read or write a charger register"); -#endif /* CONFIG_CMD_CHARGER */ - -#ifdef CONFIG_CHARGER_PSYS_READ -static int bd9995x_psys_charger_adc(int chgnum) -{ - int i; - int reg; - uint64_t ipmon = 0; - - for (i = 0; i < BD9995X_PMON_IOUT_ADC_READ_COUNT; i++) { - if (ch_raw_read16(chgnum, BD9995X_CMD_PMON_DACIN_VAL, ®, - BD9995X_EXTENDED_COMMAND)) - return 0; - - /* Conversion Interval is 200us */ - usleep(200); - ipmon += reg; - } - - /* - * Calculate power in mW - * PSYS = VACP×IACP+VBAT×IBAT = IPMON / GPMON - */ - return (int) ((ipmon * 1000) / (BIT(BD9995X_PSYS_GAIN_SELECT) * - BD9995X_PMON_IOUT_ADC_READ_COUNT)); -} - -static int bd9995x_enable_psys(int chgnum) -{ - int rv; - int reg; - - rv = ch_raw_read16(chgnum, BD9995X_CMD_PMON_IOUT_CTRL_SET, ®, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - /* Enable PSYS & Select PSYS Gain */ - reg &= ~BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_MASK; - reg |= (BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_INSEL | - BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_OUT_EN | - BD9995X_PSYS_GAIN_SELECT); - - return ch_raw_write16(chgnum, BD9995X_CMD_PMON_IOUT_CTRL_SET, reg, - BD9995X_EXTENDED_COMMAND); -} - -/** - * Get system power. - * - * TODO(b:71520677): Implement charger_get_system_power, disable psys readout - * when not needed (the code below leaves it enabled after the first access), - * update "psys" console command to use charger_get_system_power and move it - * to some common code. - */ -static int console_command_psys(int argc, char **argv) -{ - int rv; - - rv = bd9995x_enable_psys(CHARGER_SOLO); - if (rv) - return rv; - - CPRINTS("PSYS from chg_adc: %d mW", - bd9995x_psys_charger_adc(CHARGER_SOLO)); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(psys, console_command_psys, - NULL, - "Get the system power in mW"); -#endif /* CONFIG_CHARGER_PSYS_READ */ - -#ifdef CONFIG_CMD_CHARGER_ADC_AMON_BMON -static int bd9995x_amon_bmon_chg_adc(int chgnum) -{ - int i; - int reg; - int iout = 0; - - for (i = 0; i < BD9995X_PMON_IOUT_ADC_READ_COUNT; i++) { - ch_raw_read16(chgnum, BD9995X_CMD_IOUT_DACIN_VAL, ®, - BD9995X_EXTENDED_COMMAND); - iout += reg; - - /* Conversion Interval is 200us */ - usleep(200); - } - - /* - * Discharge current in mA - * IDCHG = iout * GIDCHG - * IADP = iout * GIADP - * - * VIDCHG = GIDCHG * (VSRN- VSRP) = GIDCHG * IDCHG / IDCHG_RES - * VIADP = GIADP * (VACP- VACN) = GIADP * IADP / IADP_RES - */ - return (iout * (5 << BD9995X_IOUT_GAIN_SELECT)) / - (10 * BD9995X_PMON_IOUT_ADC_READ_COUNT); -} - -static int bd9995x_amon_bmon(int chgnum, int amon_bmon) -{ - int rv; - int reg; - int imon; - int sns_res; - - rv = ch_raw_read16(chgnum, BD9995X_CMD_PMON_IOUT_CTRL_SET, ®, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - /* Enable monitor */ - reg &= ~BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_GAIN_SET_MASK; - reg |= (BD9995X_CMD_PMON_IOUT_CTRL_SET_IMON_INSEL | - BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_OUT_EN | - (BD9995X_IOUT_GAIN_SELECT << 4)); - - if (amon_bmon) { - reg |= BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_SOURCE_SEL; - sns_res = CONFIG_CHARGER_SENSE_RESISTOR_AC; - } else { - reg &= ~BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_SOURCE_SEL; - sns_res = CONFIG_CHARGER_SENSE_RESISTOR; - } - - rv = ch_raw_write16(chgnum, BD9995X_CMD_PMON_IOUT_CTRL_SET, reg, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - imon = bd9995x_amon_bmon_chg_adc(chgnum); - - CPRINTS("%cMON from chg_adc: %d uV, %d mA]", - amon_bmon ? 'A' : 'B', - imon * sns_res, - imon); - - return EC_SUCCESS; -} - -/** - * Get charger AMON and BMON current. - */ -static int console_command_amon_bmon(int argc, char **argv) -{ - int rv = EC_ERROR_PARAM1; - - /* Switch to AMON */ - if (argc == 1 || (argc >= 2 && argv[1][0] == 'a')) - rv = bd9995x_amon_bmon(CHARGER_SOLO, 1); - - /* Switch to BMON */ - if (argc == 1 || (argc >= 2 && argv[1][0] == 'b')) - rv = bd9995x_amon_bmon(CHARGER_SOLO, 0); - - return rv; -} -DECLARE_CONSOLE_COMMAND(amonbmon, console_command_amon_bmon, - "amonbmon [a|b]", - "Get charger AMON/BMON voltage diff, current"); -#endif /* CONFIG_CMD_CHARGER_ADC_AMON_BMON */ - -#ifdef CONFIG_CMD_I2C_STRESS_TEST_CHARGER -static int bd9995x_i2c_read(const int reg, int *data) -{ - return ch_raw_read16(CHARGER_SOLO, reg, data, BD9995X_EXTENDED_COMMAND); -} - -static int bd9995x_i2c_write(const int reg, int data) -{ - return ch_raw_write16(CHARGER_SOLO, reg, data, - BD9995X_EXTENDED_COMMAND); -} - -/* BD9995X_CMD_CHIP_ID register value may vary by chip. */ -struct i2c_stress_test_dev bd9995x_i2c_stress_test_dev = { - .reg_info = { - .read_reg = BD9995X_CMD_CHIP_ID, - .read_val = BD99956_CHIP_ID, - .write_reg = BD9995X_CMD_ITRICH_SET, - }, - .i2c_read_dev = &bd9995x_i2c_read, - .i2c_write_dev = &bd9995x_i2c_write, -}; -#endif /* CONFIG_CMD_I2C_STRESS_TEST_CHARGER */ - -const struct charger_drv bd9995x_drv = { - .post_init = &bd9995x_post_init, - .get_info = &bd9995x_get_info, - .get_status = &bd9995x_get_status, - .set_mode = &bd9995x_set_mode, - .get_current = &bd9995x_get_current, - .set_current = &bd9995x_set_current, - .get_voltage = &bd9995x_get_voltage, - .set_voltage = &bd9995x_set_voltage, - .discharge_on_ac = &bd9995x_discharge_on_ac, - .get_vbus_voltage = &bd9995x_get_vbus_voltage, - .set_input_current_limit = &bd9995x_set_input_current_limit, - .get_input_current_limit = &bd9995x_get_input_current_limit, - .manufacturer_id = &bd9995x_manufacturer_id, - .device_id = &bd9995x_device_id, - .get_option = &bd9995x_get_option, - .set_option = &bd9995x_set_option, -}; - -#ifdef CONFIG_BC12_SINGLE_DRIVER -/* provide a default bc12_ports[] for backward compatibility */ -struct bc12_config bc12_ports[BD9995X_CHARGE_PORT_COUNT] = { - { - .drv = &(const struct bc12_drv) { - .usb_charger_task = bd9995x_usb_charger_task, - .set_switches = bd9995x_set_switches, -#if defined(CONFIG_CHARGE_RAMP_SW) - .ramp_allowed = bd9995x_ramp_allowed, - .ramp_max = bd9995x_ramp_max, -#endif /* CONFIG_CHARGE_RAMP_SW */ - }, - }, - { - .drv = &(const struct bc12_drv) { - /* bd9995x uses a single task thread for both ports */ - .usb_charger_task = NULL, - .set_switches = bd9995x_set_switches, -#if defined(CONFIG_CHARGE_RAMP_SW) - .ramp_allowed = bd9995x_ramp_allowed, - .ramp_max = bd9995x_ramp_max, -#endif /* CONFIG_CHARGE_RAMP_SW */ - }, - }, -}; -BUILD_ASSERT(ARRAY_SIZE(bc12_ports) == CHARGE_PORT_COUNT); -#else -/* - * TODO: - * This driver assumes its two ports is always on number 0 and 1. - * Prohibit multiple driver for safety. - */ -#error config not supported -#endif /* CONFIG_BC12_SINGLE_DRIVER */ diff --git a/driver/charger/bd9995x.h b/driver/charger/bd9995x.h deleted file mode 100644 index a1f1bdb64f..0000000000 --- a/driver/charger/bd9995x.h +++ /dev/null @@ -1,352 +0,0 @@ -/* Copyright 2016 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. - * - * ROHM BD9995X battery charger driver. - */ - -#ifndef __CROS_EC_BD9995X_H -#define __CROS_EC_BD9995X_H - -#define BD9995X_ADDR_FLAGS 0x09 - -#define BD9995X_CHARGER_NAME "bd9995x" -#define BD99955_CHIP_ID 0x221 -#define BD99956_CHIP_ID 0x331 - -/* BD9995X commands to change the command code map */ -enum bd9995x_command { - BD9995X_BAT_CHG_COMMAND, - BD9995X_EXTENDED_COMMAND, - BD9995X_DEBUG_COMMAND, - BD9995X_INVALID_COMMAND -}; - -/* - * BD9995X has two external VBUS inputs (named VBUS and VCC) and two sets - * of registers / bits for control. This entire driver is written under the - * assumption that the physical VBUS port corresponds to PD port 0, and the - * physical VCC port corresponds to PD port 1. - */ -enum bd9995x_charge_port { - BD9995X_CHARGE_PORT_VBUS, - BD9995X_CHARGE_PORT_VCC, - BD9995X_CHARGE_PORT_BOTH, -}; - -/* Min. charge current w/ no battery to prevent collapse */ -#define BD9995X_NO_BATTERY_CHARGE_I_MIN 512 - -/* - * BC1.2 minimum voltage threshold. - * BC1.2 charging port output voltage range is 4.75V to 5.25V, - * BD9995X Anti-Collapse Threshold Voltage Accuracy is -100mV to +100mV, - * and Delta of 50mV. - */ -#define BD9995X_BC12_MIN_VOLTAGE 4600 - -/* Battery Charger Commands */ -#define BD9995X_CMD_CHG_CURRENT 0x14 -#define BD9995X_CMD_CHG_VOLTAGE 0x15 -#define BD9995X_CMD_IBUS_LIM_SET 0x3C -#define BD9995X_CMD_ICC_LIM_SET 0x3D -#define BD9995X_CMD_PROTECT_SET 0x3E -#define BD9995X_CMD_MAP_SET 0x3F - -/* Extended commands */ -#define BD9995X_CMD_CHGSTM_STATUS 0x00 -#define BD9995X_CMD_VBAT_VSYS_STATUS 0x01 -#define BD9995X_CMD_VBUS_VCC_STATUS 0x02 -#define BD9995X_CMD_VBUS_VCC_STATUS_VCC_DETECT BIT(8) -#define BD9995X_CMD_VBUS_VCC_STATUS_VBUS_DETECT BIT(0) - -#define BD9995X_CMD_CHGOP_STATUS 0x03 -#define BD9995X_CMD_CHGOP_STATUS_BATTEMP2 BIT(10) -#define BD9995X_CMD_CHGOP_STATUS_BATTEMP1 BIT(9) -#define BD9995X_CMD_CHGOP_STATUS_BATTEMP0 BIT(8) -#define BD9995X_BATTTEMP_MASK 0x700 -#define BD9995X_CMD_CHGOP_STATUS_BATTEMP_ROOMTEMP 0 -#define BD9995X_CMD_CHGOP_STATUS_BATTEMP_HOT1 1 -#define BD9995X_CMD_CHGOP_STATUS_BATTEMP_HOT2 2 -#define BD9995X_CMD_CHGOP_STATUS_BATTEMP_HOT3 3 -#define BD9995X_CMD_CHGOP_STATUS_BATTEMP_COLD1 4 -#define BD9995X_CMD_CHGOP_STATUS_BATTEMP_COLD2 5 -#define BD9995X_CMD_CHGOP_STATUS_BATTEMP_DISABLE 6 -#define BD9995X_CMD_CHGOP_STATUS_BATTEMP_BATOPEN 7 -#define BD9995X_CMD_CHGOP_STATUS_RBOOST_UV BIT(1) - -#define BD9995X_CMD_WDT_STATUS 0x04 -#define BD9995X_CMD_CUR_ILIM_VAL 0x05 -#define BD9995X_CMD_SEL_ILIM_VAL 0x06 -#define BD9995X_CMD_EXT_IBUS_LIM_SET 0x07 -#define BD9995X_CMD_EXT_ICC_LIM_SET 0x08 -#define BD9995X_CMD_IOTG_LIM_SET 0x09 -#define BD9995X_CMD_VIN_CTRL_SET 0x0A -#define BD9995X_CMD_VIN_CTRL_SET_VSYS_PRIORITY BIT(4) - -#define BD9995X_CMD_VIN_CTRL_SET_PP_BOTH_THRU BIT(11) -#define BD9995X_CMD_VIN_CTRL_SET_VBUS_PRIORITY BIT(7) -#define BD9995X_CMD_VIN_CTRL_SET_VBUS_EN BIT(6) -#define BD9995X_CMD_VIN_CTRL_SET_VCC_EN BIT(5) - -#define BD9995X_CMD_CHGOP_SET1 0x0B -#define BD9995X_CMD_CHGOP_SET1_DCP_2500_SEL BIT(15) -#define BD9995X_CMD_CHGOP_SET1_SDP_500_SEL BIT(14) -#define BD9995X_CMD_CHGOP_SET1_ILIM_AUTO_DISEN BIT(13) -#define BD9995X_CMD_CHGOP_SET1_VCC_BC_DISEN BIT(11) -#define BD9995X_CMD_CHGOP_SET1_VBUS_BC_DISEN BIT(10) -#define BD9995X_CMD_CHGOP_SET1_SDP_CHG_TRIG_EN BIT(9) -#define BD9995X_CMD_CHGOP_SET1_SDP_CHG_TRIG BIT(8) - -#define BD9995X_CMD_CHGOP_SET2 0x0C -#define BD9995X_CMD_CHGOP_SET2_BATT_LEARN BIT(8) -#define BD9995X_CMD_CHGOP_SET2_CHG_EN BIT(7) -#define BD9995X_CMD_CHGOP_SET2_USB_SUS BIT(6) -#define BD9995X_CMD_CHGOP_SET2_DCDC_CLK_SEL (3 << 2) -#define BD9995X_CMD_CHGOP_SET2_DCDC_CLK_SEL_600 (0 << 2) -#define BD9995X_CMD_CHGOP_SET2_DCDC_CLK_SEL_857 BIT(2) -#define BD9995X_CMD_CHGOP_SET2_DCDC_CLK_SEL_1000 (2 << 2) -#define BD9995X_CMD_CHGOP_SET2_DCDC_CLK_SEL_1200 (3 << 2) - -#define BD9995X_CMD_VBUSCLPS_TH_SET 0x0D -#define BD9995X_CMD_VCCCLPS_TH_SET 0x0E -#define BD9995X_CMD_CHGWDT_SET 0x0F -#define BD9995X_CMD_BATTWDT_SET 0x10 -#define BD9995X_CMD_VSYSREG_SET 0x11 -#define BD9995X_CMD_VSYSVAL_THH_SET 0x12 -#define BD9995X_CMD_VSYSVAL_THL_SET 0x13 -#define BD9995X_CMD_ITRICH_SET 0x14 - -#define BD9995X_CMD_IPRECH_SET 0x15 -#define BD9995X_IPRECH_MAX 1024 - -#define BD9995X_CMD_ICHG_SET 0x16 -#define BD9995X_CMD_ITERM_SET 0x17 -#define BD9995X_CMD_VPRECHG_TH_SET 0x18 -#define BD9995X_CMD_VRBOOST_SET 0x19 -#define BD9995X_CMD_VFASTCHG_REG_SET1 0x1A -#define BD9995X_CMD_VFASTCHG_REG_SET2 0x1B -#define BD9995X_CMD_VFASTCHG_REG_SET3 0x1C -#define BD9995X_CMD_VRECHG_SET 0x1D -#define BD9995X_CMD_VBATOVP_SET 0x1E -#define BD9995X_CMD_IBATSHORT_SET 0x1F -#define BD9995X_CMD_PROCHOT_CTRL_SET 0x20 -#define BD9995X_CMD_PROCHOT_CTRL_SET_PROCHOT_EN4 BIT(4) -#define BD9995X_CMD_PROCHOT_CTRL_SET_PROCHOT_EN3 BIT(3) -#define BD9995X_CMD_PROCHOT_CTRL_SET_PROCHOT_EN2 BIT(2) -#define BD9995X_CMD_PROCHOT_CTRL_SET_PROCHOT_EN1 BIT(1) -#define BD9995X_CMD_PROCHOT_CTRL_SET_PROCHOT_EN0 BIT(0) - -#define BD9995X_CMD_PROCHOT_ICRIT_SET 0x21 -#define BD9995X_CMD_PROCHOT_INORM_SET 0x22 -#define BD9995X_CMD_PROCHOT_IDCHG_SET 0x23 -#define BD9995X_CMD_PROCHOT_VSYS_SET 0x24 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET 0x25 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_IMON_INSEL BIT(9) -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_INSEL BIT(8) -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_OUT_EN BIT(7) -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_SOURCE_SEL BIT(6) -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_GAIN_SET_MASK 0x30 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_GAIN_SET_40V 0x03 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_GAIN_SET_20V 0x02 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_GAIN_SET_10V 0x01 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_GAIN_SET_05V 0x00 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_OUT_EN BIT(3) -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_MASK 0x07 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_64UAW 0x06 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_32UAW 0x05 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_16UAW 0x04 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_08UAW 0x03 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_04UAW 0x02 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_02UAW 0x01 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_01UAW 0x00 -#define BD9995X_PMON_IOUT_ADC_READ_COUNT 128 - -#define BD9995X_CMD_PMON_DACIN_VAL 0x26 -#define BD9995X_CMD_IOUT_DACIN_VAL 0x27 -#define BD9995X_CMD_VCC_UCD_SET 0x28 -/* Bits for both VCC_UCD_SET and VBUS_UCD_SET regs */ -/* Retry BC1.2 detection on set */ -#define BD9995X_CMD_UCD_SET_BCSRETRY BIT(12) -/* Enable BC1.2 detection, will automatically occur on VBUS detect */ -#define BD9995X_CMD_UCD_SET_USBDETEN BIT(7) -/* USB switch state auto-control */ -#define BD9995X_CMD_UCD_SET_USB_SW_EN BIT(1) -/* USB switch state, 1 = ON, only meaningful when USB_SW_EN = 0 */ -#define BD9995X_CMD_UCD_SET_USB_SW BIT(0) - -#define BD9995X_CMD_VCC_UCD_STATUS 0x29 -/* Bits for both VCC_UCD_STATUS and VBUS_UCD_STATUS regs */ -#define BD9995X_CMD_UCD_STATUS_DCDFAIL BIT(15) -#define BD9995X_CMD_UCD_STATUS_CHGPORT1 BIT(13) -#define BD9995X_CMD_UCD_STATUS_CHGPORT0 BIT(12) -#define BD9995X_CMD_UCD_STATUS_PUPDET BIT(11) -#define BD9995X_CMD_UCD_STATUS_CHGDET BIT(6) -#define BD9995X_TYPE_MASK (BD9995X_CMD_UCD_STATUS_DCDFAIL | \ - BD9995X_CMD_UCD_STATUS_CHGPORT1 | \ - BD9995X_CMD_UCD_STATUS_CHGPORT0 | \ - BD9995X_CMD_UCD_STATUS_PUPDET | \ - BD9995X_CMD_UCD_STATUS_CHGDET) - -/* BC1.2 chargers */ -#define BD9995X_TYPE_CDP (BD9995X_CMD_UCD_STATUS_CHGPORT1 | \ - BD9995X_CMD_UCD_STATUS_CHGDET) -#define BD9995X_TYPE_DCP (BD9995X_CMD_UCD_STATUS_CHGPORT1 | \ - BD9995X_CMD_UCD_STATUS_CHGPORT0 | \ - BD9995X_CMD_UCD_STATUS_CHGDET) -#define BD9995X_TYPE_SDP (BD9995X_CMD_UCD_STATUS_CHGPORT0) -/* non-standard BC1.2 chargers */ -#define BD9995X_TYPE_OTHER (BD9995X_CMD_UCD_STATUS_DCDFAIL | \ - BD9995X_CMD_UCD_STATUS_CHGPORT1 | \ - BD9995X_CMD_UCD_STATUS_CHGPORT0 | \ - BD9995X_CMD_UCD_STATUS_CHGDET) -#define BD9995X_TYPE_PUP_PORT (BD9995X_CMD_UCD_STATUS_DCDFAIL | \ - BD9995X_CMD_UCD_STATUS_CHGPORT0 | \ - BD9995X_CMD_UCD_STATUS_PUPDET) -/* Open ports */ -#define BD9995X_TYPE_OPEN_PORT (BD9995X_CMD_UCD_STATUS_DCDFAIL | \ - BD9995X_CMD_UCD_STATUS_CHGPORT0) -#define BD9995X_TYPE_VBUS_OPEN 0 - -#define BD9995X_CMD_VCC_IDD_STATUS 0x2A -#define BD9995X_CMD_VCC_UCD_FCTRL_SET 0x2B -#define BD9995X_CMD_VCC_UCD_FCTRL_EN 0x2C -#define BD9995X_CMD_VBUS_UCD_SET 0x30 -#define BD9995X_CMD_VBUS_UCD_STATUS 0x31 -#define BD9995X_CMD_VBUS_IDD_STATUS 0x32 -#define BD9995X_CMD_VBUS_UCD_FCTRL_SET 0x33 -#define BD9995X_CMD_VBUS_UCD_FCTRL_EN 0x34 -#define BD9995X_CMD_CHIP_ID 0x38 -#define BD9995X_CMD_CHIP_REV 0x39 -#define BD9995X_CMD_IC_SET1 0x3A -#define BD9995X_CMD_IC_SET2 0x3B -#define BD9995X_CMD_SYSTEM_STATUS 0x3C -#define BD9995X_CMD_SYSTEM_STATUS_OTPLD_STATE BIT(1) -#define BD9995X_CMD_SYSTEM_STATUS_ALLRST_STATE BIT(0) - -#define BD9995X_CMD_SYSTEM_CTRL_SET 0x3D -#define BD9995X_CMD_SYSTEM_CTRL_SET_OTPLD BIT(1) -#define BD9995X_CMD_SYSTEM_CTRL_SET_ALLRST BIT(0) - -#define BD9995X_CMD_EXT_PROTECT_SET 0x3E -#define BD9995X_CMD_EXT_MAP_SET 0x3F -#define BD9995X_CMD_VM_CTRL_SET 0x40 -#define BD9995X_CMD_VM_CTRL_SET_EXTIADPEN BIT(9) -#define BD9995X_CMD_THERM_WINDOW_SET1 0x41 -#define BD9995X_CMD_THERM_WINDOW_SET2 0x42 -#define BD9995X_CMD_THERM_WINDOW_SET3 0x43 -#define BD9995X_CMD_THERM_WINDOW_SET4 0x44 -#define BD9995X_CMD_THERM_WINDOW_SET5 0x45 -#define BD9995X_CMD_IBATP_TH_SET 0x46 -#define BD9995X_CMD_IBATM_TH_SET 0x47 -#define BD9995X_CMD_VBAT_TH_SET 0x48 -#define BD9995X_CMD_THERM_TH_SET 0x49 -#define BD9995X_CMD_IACP_TH_SET 0x4A -#define BD9995X_CMD_VACP_TH_SET 0x4B - -/* Enable discharge when VBUS falls below BD9995X_VBUS_DISCHARGE_TH */ -#define BD9995X_VBUS_DISCHARGE_TH 3900 -#define BD9995X_CMD_VBUS_TH_SET 0x4C -#define BD9995X_CMD_VCC_TH_SET 0x4D - -#define BD9995X_CMD_VSYS_TH_SET 0x4E -#define BD9995X_CMD_EXTIADP_TH_SET 0x4F -#define BD9995X_CMD_IBATP_VAL 0x50 -#define BD9995X_CMD_IBATP_AVE_VAL 0x51 -#define BD9995X_CMD_IBATM_VAL 0x52 -#define BD9995X_CMD_IBATM_AVE_VAL 0x53 -#define BD9995X_CMD_VBAT_VAL 0x54 -#define BD9995X_CMD_VBAT_AVE_VAL 0x55 -#define BD9995X_CMD_THERM_VAL 0x56 -#define BD9995X_CMD_VTH_VAL 0x57 -#define BD9995X_CMD_IACP_VAL 0x58 -#define BD9995X_CMD_IACP_AVE_VAL 0x59 -#define BD9995X_CMD_VACP_VAL 0x5A -#define BD9995X_CMD_VACP_AVE_VAL 0x5B -#define BD9995X_CMD_VBUS_VAL 0x5C -#define BD9995X_CMD_VBUS_AVE_VAL 0x5D -#define BD9995X_CMD_VCC_VAL 0x5E -#define BD9995X_CMD_VCC_AVE_VAL 0x5F -#define BD9995X_CMD_VSYS_VAL 0x60 -#define BD9995X_CMD_VSYS_AVE_VAL 0x61 -#define BD9995X_CMD_EXTIADP_VAL 0x62 -#define BD9995X_CMD_EXTIADP_AVE_VAL 0x63 -#define BD9995X_CMD_VACPCLPS_TH_SET 0x64 -#define BD9995X_CMD_INT0_SET 0x68 -#define BD9995X_CMD_INT0_SET_INT2_EN BIT(2) -#define BD9995X_CMD_INT0_SET_INT1_EN BIT(1) -#define BD9995X_CMD_INT0_SET_INT0_EN BIT(0) - -#define BD9995X_CMD_INT1_SET 0x69 -/* Bits for both INT1 & INT2 reg */ -#define BD9995X_CMD_INT_SET_TH_DET BIT(9) -#define BD9995X_CMD_INT_SET_TH_RES BIT(8) -#define BD9995X_CMD_INT_SET_DET BIT(1) -#define BD9995X_CMD_INT_SET_RES BIT(0) -#define BD9995X_CMD_INT_VBUS_DET (BD9995X_CMD_INT_SET_RES | \ - BD9995X_CMD_INT_SET_DET) -#define BD9995X_CMD_INT_VBUS_TH (BD9995X_CMD_INT_SET_TH_RES | \ - BD9995X_CMD_INT_SET_TH_DET) - -#define BD9995X_CMD_INT2_SET 0x6A -#define BD9995X_CMD_INT3_SET 0x6B -#define BD9995X_CMD_INT4_SET 0x6C -#define BD9995X_CMD_INT5_SET 0x6D -#define BD9995X_CMD_INT6_SET 0x6E -#define BD9995X_CMD_INT7_SET 0x6F -#define BD9995X_CMD_INT0_STATUS 0x70 -#define BD9995X_CMD_INT1_STATUS 0x71 -/* Bits for both INT1_STATUS & INT2_STATUS reg */ -#define BD9995X_CMD_INT_STATUS_DET BIT(1) -#define BD9995X_CMD_INT_STATUS_RES BIT(0) - -#define BD9995X_CMD_INT2_STATUS 0x72 -#define BD9995X_CMD_INT3_STATUS 0x73 -#define BD9995X_CMD_INT4_STATUS 0x74 -#define BD9995X_CMD_INT5_STATUS 0x75 -#define BD9995X_CMD_INT6_STATUS 0x76 -#define BD9995X_CMD_INT7_STATUS 0x77 -#define BD9995X_CMD_REG0 0x78 -#define BD9995X_CMD_REG1 0x79 -#define BD9995X_CMD_OTPREG0 0x7A -#define BD9995X_CMD_OTPREG1 0x7B -#define BD9995X_CMD_SMBREG 0x7C -/* Normal functionality - power save mode disabled. */ -#define BD9995X_PWR_SAVE_OFF 0 -/* BGATE ON w/ PROCHOT# monitored only system voltage. */ -#define BD9995X_PWR_SAVE_LOW 0x1 -/* BGATE ON w/ PROCHOT# monitored only system voltage every 1ms. */ -#define BD9995X_PWR_SAVE_MED 0x2 -/* BGATE ON w/o PROCHOT# monitoring. */ -#define BD9995X_PWR_SAVE_HIGH 0x5 -/* BGATE OFF */ -#define BD9995X_PWR_SAVE_MAX 0x6 -#define BD9995X_CMD_DEBUG_MODE_SET 0x7F - -/* - * Non-standard interface functions - bd9995x integrates additional - * functionality not part of the standard charger interface. - */ - -/* Is VBUS provided or external power present */ -int bd9995x_is_vbus_provided(enum bd9995x_charge_port port); -/* Select or deselect input port from {VCC, VBUS, VCC&VBUS}. */ -int bd9995x_select_input_port(enum bd9995x_charge_port port, int select); -/* Enable/Disable charging triggered by BC1.2 */ -int bd9995x_bc12_enable_charging(int port, int enable); -/* Interrupt handler for USB charger VBUS */ -void bd9995x_vbus_interrupt(enum gpio_signal signal); -/* Read temperature measurement value (in Celsius) */ -int bd9995x_get_battery_temp(int *temp_ptr); -/* Set power save mode */ -void bd9995x_set_power_save_mode(int mode); -/* Get Battery Voltage Measurement Value */ -int bd9995x_get_battery_voltage(void); - -#ifdef CONFIG_CMD_I2C_STRESS_TEST_CHARGER -extern struct i2c_stress_test_dev bd9995x_i2c_stress_test_dev; -#endif - -extern const struct charger_drv bd9995x_drv; - -#endif /* __CROS_EC_BD9995X_H */ diff --git a/driver/charger/bq24715.c b/driver/charger/bq24715.c deleted file mode 100644 index d2eb0e432a..0000000000 --- a/driver/charger/bq24715.c +++ /dev/null @@ -1,252 +0,0 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * TI bq24715 battery charger driver. - */ - -#include "battery_smart.h" -#include "bq24715.h" -#include "charger.h" -#include "console.h" -#include "common.h" -#include "i2c.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 bq24715_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), -}; - -static inline enum ec_error_list sbc_read(int chgnum, int cmd, int *param) -{ - return i2c_read16(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - cmd, param); -} - -static inline enum ec_error_list sbc_write(int chgnum, int cmd, int param) -{ - return i2c_write16(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - cmd, param); -} - -static enum ec_error_list bq24715_set_input_current_limit(int chgnum, - int input_current) -{ - return sbc_write(chgnum, BQ24715_INPUT_CURRENT, - CURRENT_TO_REG(input_current, R_AC)); -} - -static enum ec_error_list bq24715_get_input_current_limit(int chgnum, - int *input_current) -{ - int rv; - int reg; - - rv = sbc_read(chgnum, BQ24715_INPUT_CURRENT, ®); - if (rv) - return rv; - - *input_current = REG_TO_CURRENT(reg, R_AC); - - return EC_SUCCESS; -} - -static enum ec_error_list bq24715_manufacturer_id(int chgnum, int *id) -{ - return sbc_read(chgnum, BQ24715_MANUFACTURER_ID, id); -} - -static enum ec_error_list bq24715_device_id(int chgnum, int *id) -{ - return sbc_read(chgnum, BQ24715_DEVICE_ID, id); -} - -static enum ec_error_list bq24715_get_option(int chgnum, int *option) -{ - return sbc_read(chgnum, BQ24715_CHARGE_OPTION, option); -} - -static enum ec_error_list bq24715_set_option(int chgnum, int option) -{ - return sbc_write(chgnum, BQ24715_CHARGE_OPTION, option); -} - -/* Charger interfaces */ - -static const struct charger_info *bq24715_get_info(int chgnum) -{ - return &bq24715_charger_info; -} - -static enum ec_error_list bq24715_get_status(int chgnum, int *status) -{ - int rv; - int option; - - rv = bq24715_get_option(chgnum, &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; -} - -static enum ec_error_list bq24715_set_mode(int chgnum, int mode) -{ - int rv; - int option; - - rv = bq24715_get_option(chgnum, &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 bq24715_set_option(chgnum, option); -} - -static enum ec_error_list bq24715_get_current(int chgnum, int *current) -{ - int rv; - int reg; - - rv = sbc_read(chgnum, SB_CHARGING_CURRENT, ®); - if (rv) - return rv; - - *current = REG_TO_CURRENT(reg, R_SNS); - return EC_SUCCESS; -} - -static enum ec_error_list bq24715_set_current(int chgnum, int current) -{ - current = charger_closest_current(current); - - return sbc_write(chgnum, 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; - -static enum ec_error_list bq24715_get_voltage(int chgnum, int *voltage) -{ - int ret; - - if (cached_voltage == 0) { - *voltage = cached_voltage; - return EC_SUCCESS; - } - - ret = sbc_read(chgnum, SB_CHARGING_VOLTAGE, &cached_voltage); - - if (ret == EC_SUCCESS) - *voltage = cached_voltage; - - return ret; -} - -static enum ec_error_list bq24715_set_voltage(int chgnum, int voltage) -{ - cached_voltage = voltage; - return sbc_write(chgnum, SB_CHARGING_VOLTAGE, voltage); -} - -/* Charging power state initialization */ -static enum ec_error_list bq24715_post_init(int chgnum) -{ - int rv; - int option; - - rv = bq24715_get_option(chgnum, &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; - option &= ~OPT_LEARN_MASK; - - /* Enable dynamic power management */ - option |= OPT_IDPM_ENABLE; - - rv = bq24715_set_option(chgnum, option); - if (rv) - return rv; - - rv = bq24715_set_input_current_limit(chgnum, - CONFIG_CHARGER_INPUT_CURRENT); - return rv; -} - -static enum ec_error_list bq24715_discharge_on_ac(int chgnum, int enable) -{ - int rv; - int option; - - rv = bq24715_get_option(chgnum, &option); - if (rv) - return rv; - - option &= ~OPT_LEARN_MASK; - if (enable) - option |= OPT_LEARN_ENABLE; - else - option |= OPT_LEARN_DISABLE; - rv = bq24715_set_option(chgnum, option); - - return rv; -} - -const struct charger_drv bq24715_drv = { - .post_init = &bq24715_post_init, - .get_info = &bq24715_get_info, - .get_status = &bq24715_get_status, - .set_mode = &bq24715_set_mode, - .get_current = &bq24715_get_current, - .set_current = &bq24715_set_current, - .get_voltage = &bq24715_get_voltage, - .set_voltage = &bq24715_set_voltage, - .discharge_on_ac = &bq24715_discharge_on_ac, - .set_input_current_limit = &bq24715_set_input_current_limit, - .get_input_current_limit = &bq24715_get_input_current_limit, - .manufacturer_id = &bq24715_manufacturer_id, - .device_id = &bq24715_device_id, - .get_option = &bq24715_get_option, - .set_option = &bq24715_set_option, -}; diff --git a/driver/charger/bq24715.h b/driver/charger/bq24715.h deleted file mode 100644 index 644f995f2e..0000000000 --- a/driver/charger/bq24715.h +++ /dev/null @@ -1,132 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * TI bq24715 battery charger driver. - */ - -#ifndef __CROS_EC_BQ24715_H -#define __CROS_EC_BQ24715_H - -/* NOTES: - * If battery is not present keep charge current register (0x14) at 0. - * Max charge voltage (0x15) needs to be programmed before 0x14. - */ - -/* Chip specific registers */ -#define BQ24715_CHARGE_OPTION 0x12 -#define BQ24715_CHARGE_CURRENT 0x14 -#define BQ24715_MAX_CHARGE_VOLTAGE 0x15 -#define BQ24715_MIN_SYSTEM_VOLTAGE 0x3e -#define BQ24715_INPUT_CURRENT 0x3f -#define BQ24715_MANUFACTURER_ID 0xfe -#define BQ24715_DEVICE_ID 0xff - -/* ChargeOption Register - 0x12 */ -#define OPT_LOWPOWER_MASK BIT(15) -#define OPT_LOWPOWER_DSCHRG_I_MON_ON (0 << 15) -#define OPT_LOWPOWER_DSCHRG_I_MON_OFF BIT(15) -#define OPT_WATCHDOG_MASK (3 << 13) -#define OPT_WATCHDOG_DISABLE (0 << 13) -#define OPT_WATCHDOG_44SEC BIT(13) -#define OPT_WATCHDOG_88SEC (2 << 13) -#define OPT_WATCHDOG_175SEC (3 << 13) -#define OPT_SYSOVP_MASK BIT(12) -#define OPT_SYSOVP_15P1_3SEC_10P1_2SEC (0 << 12) -#define OPT_SYSOVP_17P0_3SEC_11P3_2SEC BIT(12) -#define OPT_SYSOVP_STATUS_MASK BIT(11) -#define OPT_SYSOVP_STATUS BIT(11) -#define OPT_AUDIO_FREQ_LIMIT_MASK BIT(10) -#define OPT_AUDIO_FREQ_NO_LIMIT (0 << 10) -#define OPT_AUDIO_FREQ_40KHZ_LIMIT BIT(10) -#define OPT_SWITCH_FREQ_MASK (3 << 8) -#define OPT_SWITCH_FREQ_600KHZ (0 << 8) -#define OPT_SWITCH_FREQ_800KHZ BIT(8) -#define OPT_SWITCH_FREQ_1MHZ (2 << 8) -#define OPT_SWITCH_FREQ_800KHZ_DUP (3 << 8) -#define OPT_ACOC_MASK BIT(7) -#define OPT_ACOC_DISABLED (0 << 7) -#define OPT_ACOC_333PCT_IPDM BIT(7) -#define OPT_LSFET_OCP_MASK BIT(6) -#define OPT_LSFET_OCP_250MV (0 << 6) -#define OPT_LSFET_OCP_350MV BIT(6) -#define OPT_LEARN_MASK BIT(5) -#define OPT_LEARN_DISABLE (0 << 5) -#define OPT_LEARN_ENABLE BIT(5) -#define OPT_IOUT_MASK BIT(4) -#define OPT_IOUT_40X (0 << 4) -#define OPT_IOUT_16X BIT(4) -#define OPT_FIX_IOUT_MASK BIT(3) -#define OPT_FIX_IOUT_IDPM_EN (0 << 3) -#define OPT_FIX_IOUT_ALWAYS BIT(3) -#define OPT_LDO_MODE_MASK BIT(2) -#define OPT_LDO_DISABLE (0 << 2) -#define OPT_LDO_ENABLE BIT(2) -#define OPT_IDPM_MASK BIT(1) -#define OPT_IDPM_DISABLE (0 << 1) -#define OPT_IDPM_ENABLE BIT(1) -#define OPT_CHARGE_INHIBIT_MASK BIT(0) -#define OPT_CHARGE_ENABLE (0 << 0) -#define OPT_CHARGE_DISABLE BIT(0) - - -/* ChargeCurrent Register - 0x14 - * The ChargeCurrent register controls a DAC. Therefore - * the below definitions are cummulative. */ -#define CHARGE_I_64MA BIT(6) -#define CHARGE_I_128MA BIT(7) -#define CHARGE_I_256MA BIT(8) -#define CHARGE_I_512MA BIT(9) -#define CHARGE_I_1024MA BIT(10) -#define CHARGE_I_2048MA BIT(11) -#define CHARGE_I_4096MA BIT(12) -#define CHARGE_I_OFF (0) -#define CHARGE_I_MIN (128) -#define CHARGE_I_MAX (8128) -#define CHARGE_I_STEP (64) - -/* MaxChargeVoltage Register - 0x15 - * The MaxChargeVoltage register controls a DAC. Therefore - * the below definitions are cummulative. */ -#define CHARGE_V_16MV BIT(4) -#define CHARGE_V_32MV BIT(5) -#define CHARGE_V_64MV BIT(6) -#define CHARGE_V_128MV BIT(7) -#define CHARGE_V_256MV BIT(8) -#define CHARGE_V_512MV BIT(9) -#define CHARGE_V_1024MV BIT(10) -#define CHARGE_V_2048MV BIT(11) -#define CHARGE_V_4096MV BIT(12) -#define CHARGE_V_8192MV BIT(13) -#define CHARGE_V_MIN (4096) -#define CHARGE_V_MAX (0x3ff0) -#define CHARGE_V_STEP (16) - -/* MinSystemVoltage Register - 0x3e - * The MinSystemVoltage register controls a DAC. Therefore - * the below definitions are cummulative. */ -#define MIN_SYS_V_256MV BIT(8) -#define MIN_SYS_V_512MV BIT(9) -#define MIN_SYS_V_1024MV BIT(10) -#define MIN_SYS_V_2048MV BIT(11) -#define MIN_SYS_V_4096MV BIT(12) -#define MIN_SYS_V_8192MV BIT(13) -#define MIN_SYS_V_MIN (4096) - -/* InputCurrent Register - 0x3f - * The InputCurrent register controls a DAC. Therefore - * the below definitions are cummulative. */ -#define INPUT_I_64MA BIT(6) -#define INPUT_I_128MA BIT(7) -#define INPUT_I_256MA BIT(8) -#define INPUT_I_512MA BIT(9) -#define INPUT_I_1024MA BIT(10) -#define INPUT_I_2048MA BIT(11) -#define INPUT_I_4096MA BIT(12) -#define INPUT_I_MIN (128) -#define INPUT_I_MAX (8064) -#define INPUT_I_STEP (64) - -extern const struct charger_drv bq24715_drv; - -#endif /* __CROS_EC_BQ24715_H */ diff --git a/driver/charger/bq24773.c b/driver/charger/bq24773.c deleted file mode 100644 index d242f105c6..0000000000 --- a/driver/charger/bq24773.c +++ /dev/null @@ -1,308 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * TI bq24773 battery charger driver. - */ - -#include "battery_smart.h" -#include "bq24773.h" -#include "charger.h" -#include "console.h" -#include "common.h" -#include "util.h" - -/* - * on the I2C version of the charger, - * some registers are 8-bit only (eg input current) - * and they are shifted by 6 bits compared to the SMBUS version (bq24770). - */ -#define REG8_SHIFT 6 -#define R8 (1 << (REG8_SHIFT)) -/* 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) -#define REG8_TO_CURRENT(REG, RS) ((REG) * DEFAULT_SENSE_RESISTOR / (RS) * R8) -#define CURRENT_TO_REG8(CUR, RS) ((CUR) * (RS) / DEFAULT_SENSE_RESISTOR / R8) - -/* ChargeCurrent Register - 0x14 (mA) */ -#define CHARGE_I_OFF 0 -#define CHARGE_I_MIN 128 -#define CHARGE_I_MAX 8128 -#define CHARGE_I_STEP 64 - -/* MaxChargeVoltage Register - 0x15 (mV) */ -#define CHARGE_V_MIN 1024 -#define CHARGE_V_MAX 19200 -#define CHARGE_V_STEP 16 - -/* InputCurrent Register - 0x3f (mA) */ -#define INPUT_I_MIN 128 -#define INPUT_I_MAX 8128 -#define INPUT_I_STEP 64 - -/* Charger parameters */ -static const struct charger_info bq2477x_charger_info = { - .name = CHARGER_NAME, - .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), -}; - -#ifdef CONFIG_CHARGER_BQ24773 -static inline enum ec_error_list raw_read8(int chgnum, int offset, int *value) -{ - return i2c_read8(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - offset, value); -} - -static inline enum ec_error_list raw_write8(int chgnum, int offset, int value) -{ - return i2c_write8(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - offset, value); -} -#endif - -static inline enum ec_error_list raw_read16(int chgnum, int offset, int *value) -{ - return i2c_read16(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - offset, value); -} - -static inline enum ec_error_list raw_write16(int chgnum, int offset, int value) -{ - return i2c_write16(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - offset, value); -} - - -/* chip specific interfaces */ - -static enum ec_error_list bq2477x_set_input_current_limit(int chgnum, - int input_current) -{ -#ifdef CONFIG_CHARGER_BQ24770 - return raw_write16(chgnum, REG_INPUT_CURRENT, - CURRENT_TO_REG(input_current, R_AC)); -#elif defined(CONFIG_CHARGER_BQ24773) - return raw_write8(chgnum, REG_INPUT_CURRENT, - CURRENT_TO_REG8(input_current, R_AC)); -#endif -} - -static enum ec_error_list bq2477x_get_input_current_limit(int chgnum, - int *input_current) -{ - int rv; - int reg; - -#ifdef CONFIG_CHARGER_BQ24770 - rv = raw_read16(chgnum, REG_INPUT_CURRENT, ®); -#elif defined(CONFIG_CHARGER_BQ24773) - rv = raw_read8(chgnum, REG_INPUT_CURRENT, ®); -#endif - if (rv) - return rv; - -#ifdef CONFIG_CHARGER_BQ24770 - *input_current = REG_TO_CURRENT(reg, R_AC); -#elif defined(CONFIG_CHARGER_BQ24773) - *input_current = REG8_TO_CURRENT(reg, R_AC); -#endif - return EC_SUCCESS; -} - -static enum ec_error_list bq2477x_manufacturer_id(int chgnum, int *id) -{ -#ifdef CONFIG_CHARGER_BQ24770 - return raw_read16(chgnum, REG_MANUFACTURE_ID, id); -#elif defined(CONFIG_CHARGER_BQ24773) - *id = 0x40; /* TI */ - return EC_SUCCESS; -#endif -} - -static enum ec_error_list bq2477x_device_id(int chgnum, int *id) -{ -#ifdef CONFIG_CHARGER_BQ24770 - return raw_read16(chgnum, REG_DEVICE_ADDRESS, id); -#elif defined(CONFIG_CHARGER_BQ24773) - return raw_read8(chgnum, REG_DEVICE_ADDRESS, id); -#endif -} - -static enum ec_error_list bq2477x_get_option(int chgnum, int *option) -{ - return raw_read16(chgnum, REG_CHARGE_OPTION0, option); -} - -static enum ec_error_list bq2477x_set_option(int chgnum, int option) -{ - return raw_write16(chgnum, REG_CHARGE_OPTION0, option); -} - -/* Charger interfaces */ - -static const struct charger_info *bq2477x_get_info(int chgnum) -{ - return &bq2477x_charger_info; -} - -static enum ec_error_list bq2477x_get_status(int chgnum, int *status) -{ - int rv; - int option; - - rv = bq2477x_get_option(chgnum, &option); - if (rv) - return rv; - - /* Default status */ - *status = CHARGER_LEVEL_2; - - if (option & OPTION0_CHARGE_INHIBIT) - *status |= CHARGER_CHARGE_INHIBITED; - - return EC_SUCCESS; -} - -static enum ec_error_list bq2477x_set_mode(int chgnum, int mode) -{ - int rv; - int option; - - rv = bq2477x_get_option(chgnum, &option); - if (rv) - return rv; - - if (mode & CHARGE_FLAG_INHIBIT_CHARGE) - option |= OPTION0_CHARGE_INHIBIT; - else - option &= ~OPTION0_CHARGE_INHIBIT; - return bq2477x_set_option(chgnum, option); -} - -static enum ec_error_list bq2477x_get_current(int chgnum, int *current) -{ - int rv; - int reg; - - rv = raw_read16(chgnum, REG_CHARGE_CURRENT, ®); - - if (rv) - return rv; - - *current = REG_TO_CURRENT(reg, R_SNS); - return EC_SUCCESS; -} - -static enum ec_error_list bq2477x_set_current(int chgnum, int current) -{ - current = charger_closest_current(current); - return raw_write16(chgnum, REG_CHARGE_CURRENT, - CURRENT_TO_REG(current, R_SNS)); -} - -static enum ec_error_list bq2477x_get_voltage(int chgnum, int *voltage) -{ - return raw_read16(chgnum, REG_MAX_CHARGE_VOLTAGE, voltage); -} - -static enum ec_error_list bq2477x_set_voltage(int chgnum, int voltage) -{ - voltage = charger_closest_voltage(voltage); - return raw_write16(chgnum, REG_MAX_CHARGE_VOLTAGE, voltage); -} - -/* Charging power state initialization */ -static enum ec_error_list bq2477x_post_init(int chgnum) -{ - int rv, option; -#ifdef CONFIG_CHARGER_ILIM_PIN_DISABLED - int option2; -#endif - - rv = bq2477x_get_option(chgnum, &option); - if (rv) - return rv; - - option &= ~OPTION0_LEARN_ENABLE; - rv = bq2477x_set_option(chgnum, option); - if (rv) - return rv; - - /* Turn off PROCHOT warning */ - rv = raw_read16(chgnum, REG_PROCHOT_OPTION1, &option); - if (rv) - return rv; - - option &= ~PROCHOT_OPTION1_SELECTOR_MASK; - rv = raw_write16(chgnum, REG_PROCHOT_OPTION1, option); - - if (rv) - return rv; - -#ifdef CONFIG_CHARGER_ILIM_PIN_DISABLED - /* Read the external ILIM pin enabled flag. */ - rv = raw_read16(chgnum, REG_CHARGE_OPTION2, &option2); - if (rv) - return rv; - - /* Set ILIM pin disabled if it is currently enabled. */ - if (option2 & OPTION2_EN_EXTILIM) { - option2 &= ~OPTION2_EN_EXTILIM; - rv = raw_write16(chgnum, REG_CHARGE_OPTION2, option2); - } - return rv; -#else - return EC_SUCCESS; -#endif -} - -static enum ec_error_list bq2477x_discharge_on_ac(int chgnum, int enable) -{ - int rv; - int option; - - rv = bq2477x_get_option(chgnum, &option); - if (rv) - return rv; - - if (enable) - rv = bq2477x_set_option(chgnum, option | OPTION0_LEARN_ENABLE); - else - rv = bq2477x_set_option(chgnum, option & ~OPTION0_LEARN_ENABLE); - - return rv; -} - -const struct charger_drv bq2477x_drv = { - .post_init = &bq2477x_post_init, - .get_info = &bq2477x_get_info, - .get_status = &bq2477x_get_status, - .set_mode = &bq2477x_set_mode, - .get_current = &bq2477x_get_current, - .set_current = &bq2477x_set_current, - .get_voltage = &bq2477x_get_voltage, - .set_voltage = &bq2477x_set_voltage, - .discharge_on_ac = &bq2477x_discharge_on_ac, - .set_input_current_limit = &bq2477x_set_input_current_limit, - .get_input_current_limit = &bq2477x_get_input_current_limit, - .manufacturer_id = &bq2477x_manufacturer_id, - .device_id = &bq2477x_device_id, - .get_option = &bq2477x_get_option, - .set_option = &bq2477x_set_option, -}; diff --git a/driver/charger/bq24773.h b/driver/charger/bq24773.h deleted file mode 100644 index 46f8939036..0000000000 --- a/driver/charger/bq24773.h +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * TI bq24773 battery charger driver. - */ - -#ifndef __CROS_EC_BQ24773_H -#define __CROS_EC_BQ24773_H - -/* for i2c_read and i2c_write functions. */ -#include "i2c.h" - -/* I2C address */ -#define BQ24770_ADDR_FLAGS 0x09 -#define BQ24773_ADDR_FLAGS 0x6a - -/* Chip specific commands */ -#define BQ24770_CHARGE_OPTION0 0x12 -#define BQ24770_CHARGE_OPTION1 0x3B -#define BQ24770_CHARGE_OPTION2 0x38 -#define BQ24770_PROCHOT_OPTION0 0x3C -#define BQ24770_PROCHOT_OPTION1 0x3D -#define BQ24770_CHARGE_CURRENT 0x14 -#define BQ24770_MAX_CHARGE_VOLTAGE 0x15 -#define BQ24770_MIN_SYSTEM_VOLTAGE 0x3E -#define BQ24770_INPUT_CURRENT 0x3F -#define BQ24770_MANUFACTURE_ID 0xFE -#define BQ24770_DEVICE_ADDRESS 0xFF - -#define BQ24773_CHARGE_OPTION0 0x00 -#define BQ24773_CHARGE_OPTION1 0x02 -#define BQ24773_PROCHOT_OPTION0 0x04 -#define BQ24773_PROCHOT_OPTION1 0x06 -#define BQ24773_PROCHOT_STATUS 0x08 -#define BQ24773_DEVICE_ADDRESS 0x09 -#define BQ24773_CHARGE_CURRENT 0x0A -#define BQ24773_MAX_CHARGE_VOLTAGE 0x0C -#define BQ24773_MIN_SYSTEM_VOLTAGE 0x0E -#define BQ24773_INPUT_CURRENT 0x0F -#define BQ24773_CHARGE_OPTION2 0x10 - -/* Option bits */ -#define OPTION0_CHARGE_INHIBIT BIT(0) -#define OPTION0_LEARN_ENABLE BIT(5) -#define OPTION0_SWITCHING_FREQ_MASK (3 << 8) -#define OPTION0_SWITCHING_FREQ_600KHZ (0 << 8) -#define OPTION0_SWITCHING_FREQ_800KHZ BIT(8) -#define OPTION0_SWITCHING_FREQ_1000KHZ (2 << 8) -#define OPTION0_SWITCHING_FREQ_1200KHZ (3 << 8) - -#define OPTION2_EN_EXTILIM BIT(7) - -/* Prochot Option bits */ -#define PROCHOT_OPTION1_SELECTOR_MASK 0x7f /* [6:0] PROCHOT SELECTOR */ - -#ifdef CONFIG_CHARGER_BQ24770 - #define CHARGER_NAME "bq24770" - #define I2C_ADDR_CHARGER_FLAGS BQ24770_ADDR_FLAGS - - #define REG_CHARGE_OPTION0 BQ24770_CHARGE_OPTION0 - #define REG_CHARGE_OPTION1 BQ24770_CHARGE_OPTION1 - #define REG_CHARGE_OPTION2 BQ24770_CHARGE_OPTION2 - #define REG_PROCHOT_OPTION0 BQ24770_PROCHOT_OPTION0 - #define REG_PROCHOT_OPTION1 BQ24770_PROCHOT_OPTION1 - #define REG_CHARGE_CURRENT BQ24770_CHARGE_CURRENT - #define REG_MAX_CHARGE_VOLTAGE BQ24770_MAX_CHARGE_VOLTAGE - #define REG_MIN_SYSTEM_VOLTAGE BQ24770_MIN_SYSTEM_VOLTAGE - #define REG_INPUT_CURRENT BQ24770_INPUT_CURRENT - #define REG_MANUFACTURE_ID BQ24770_MANUFACTURE_ID - #define REG_DEVICE_ADDRESS BQ24770_DEVICE_ADDRESS - -#elif defined(CONFIG_CHARGER_BQ24773) - #define CHARGER_NAME "bq24773" - #define I2C_ADDR_CHARGER_FLAGS BQ24773_ADDR_FLAGS - - #define REG_CHARGE_OPTION0 BQ24773_CHARGE_OPTION0 - #define REG_CHARGE_OPTION1 BQ24773_CHARGE_OPTION1 - #define REG_CHARGE_OPTION2 BQ24773_CHARGE_OPTION2 - #define REG_PROCHOT_OPTION0 BQ24773_PROCHOT_OPTION0 - #define REG_PROCHOT_OPTION1 BQ24773_PROCHOT_OPTION1 - #define REG_CHARGE_CURRENT BQ24773_CHARGE_CURRENT - #define REG_MAX_CHARGE_VOLTAGE BQ24773_MAX_CHARGE_VOLTAGE - #define REG_MIN_SYSTEM_VOLTAGE BQ24773_MIN_SYSTEM_VOLTAGE - #define REG_INPUT_CURRENT BQ24773_INPUT_CURRENT - #define REG_DEVICE_ADDRESS BQ24773_DEVICE_ADDRESS -#endif - -extern const struct charger_drv bq2477x_drv; - -#endif /* __CROS_EC_BQ24773_H */ diff --git a/driver/charger/bq25710.c b/driver/charger/bq25710.c deleted file mode 100644 index df898467be..0000000000 --- a/driver/charger/bq25710.c +++ /dev/null @@ -1,752 +0,0 @@ -/* Copyright 2018 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 bq25710 battery charger driver. - */ - -#include "battery.h" -#include "battery_smart.h" -#include "bq25710.h" -#include "charge_ramp.h" -#include "charge_state_v2.h" -#include "charger.h" -#include "common.h" -#include "console.h" -#include "hooks.h" -#include "i2c.h" -#include "task.h" -#include "system.h" -#include "timer.h" -#include "util.h" - -#ifndef CONFIG_CHARGER_NARROW_VDC -#error "BQ25710 is a NVDC charger, please enable CONFIG_CHARGER_NARROW_VDC." -#endif - -/* - * Delay required from taking the bq25710 out of low power mode and having the - * correct value in register 0x3E for VSYS_MIN voltage. The length of the delay - * was determined by experiment. Less than 12 msec was not enough of delay, so - * the value here is set to 20 msec to have plenty of margin. - */ -#define BQ25710_VDDA_STARTUP_DELAY_MSEC 20 - -/* Sense resistor configurations and macros */ -#define DEFAULT_SENSE_RESISTOR 10 - -#ifdef CONFIG_CHARGER_SENSE_RESISTOR_AC_BQ25710 - #undef CONFIG_CHARGER_SENSE_RESISTOR_AC - #define CONFIG_CHARGER_SENSE_RESISTOR_AC \ - CONFIG_CHARGER_SENSE_RESISTOR_AC_BQ25710 -#endif - - -#define INPUT_RESISTOR_RATIO \ - ((CONFIG_CHARGER_SENSE_RESISTOR_AC) / DEFAULT_SENSE_RESISTOR) - -#define CHARGING_RESISTOR_RATIO \ - ((CONFIG_CHARGER_SENSE_RESISTOR) / DEFAULT_SENSE_RESISTOR) -#define REG_TO_CHARGING_CURRENT(REG) ((REG) / CHARGING_RESISTOR_RATIO) -#define CHARGING_CURRENT_TO_REG(CUR) ((CUR) * CHARGING_RESISTOR_RATIO) -#ifdef CONFIG_CHARGER_BQ25720 -#define VMIN_AP_VSYS_TH2_TO_REG(DV) ((DV) - 32) -#endif - -/* Console output macros */ -#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args) - -#ifdef CONFIG_CHARGER_BQ25710_IDCHG_LIMIT_MA -/* - * If this config option is defined, then the bq25710 needs to remain in - * performance mode when the AP is in S0. Performance mode is active whenever AC - * power is connected or when the EN_LWPWR bit in ChargeOption0 is clear. - */ -static uint32_t bq25710_perf_mode_req; -static struct mutex bq25710_perf_mode_mutex; -#endif - -/* Charger parameters */ -static const struct charger_info bq25710_charger_info = { - .name = "bq25710", - .voltage_max = 19200, - .voltage_min = 1024, - .voltage_step = 8, - .current_max = 8128 / CHARGING_RESISTOR_RATIO, - .current_min = 64 / CHARGING_RESISTOR_RATIO, - .current_step = 64 / CHARGING_RESISTOR_RATIO, - .input_current_max = 6400 / INPUT_RESISTOR_RATIO, - .input_current_min = 50 / INPUT_RESISTOR_RATIO, - .input_current_step = 50 / INPUT_RESISTOR_RATIO, -}; - -static enum ec_error_list bq25710_get_option(int chgnum, int *option); -static enum ec_error_list bq25710_set_option(int chgnum, int option); - -static inline int iin_dpm_reg_to_current(int reg) -{ - return (reg + 1) * BQ25710_IIN_DPM_CURRENT_STEP_MA / - INPUT_RESISTOR_RATIO; -} - -static inline int iin_host_current_to_reg(int current) -{ - return (current * INPUT_RESISTOR_RATIO / - BQ25710_IIN_HOST_CURRENT_STEP_MA) - 1; -} - -static inline enum ec_error_list raw_read16(int chgnum, int offset, int *value) -{ - return i2c_read16(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - offset, value); -} - -static inline int min_system_voltage_to_reg(int voltage_mv) -{ - return (voltage_mv / BQ25710_MIN_SYSTEM_VOLTAGE_STEP_MV) << - BQ25710_MIN_SYSTEM_VOLTAGE_SHIFT; -} - -static inline enum ec_error_list raw_write16(int chgnum, int offset, int value) -{ - return i2c_write16(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - offset, value); -} - -#if defined(CONFIG_CHARGE_RAMP_HW) || \ - defined(CONFIG_USB_PD_VBUS_MEASURE_CHARGER) -static int bq25710_get_low_power_mode(int chgnum, int *mode) -{ - int rv; - int reg; - - rv = raw_read16(chgnum, BQ25710_REG_CHARGE_OPTION_0, ®); - if (rv) - return rv; - - *mode = !!(reg & BQ25710_CHARGE_OPTION_0_LOW_POWER_MODE); - - return EC_SUCCESS; -} - -static int bq25710_set_low_power_mode(int chgnum, int enable) -{ - int rv; - int reg; - - rv = raw_read16(chgnum, BQ25710_REG_CHARGE_OPTION_0, ®); - if (rv) - return rv; - -#ifdef CONFIG_CHARGER_BQ25710_IDCHG_LIMIT_MA - mutex_lock(&bq25710_perf_mode_mutex); - /* - * Performance mode means not in low power mode. The bit that controls - * this is EN_LWPWR in ChargeOption0. The 'enable' param in this - * function is refeerring to low power mode, so enabling low power mode - * means disabling performance mode and vice versa. - */ - if (enable) - bq25710_perf_mode_req &= ~(1 << task_get_current()); - else - bq25710_perf_mode_req |= (1 << task_get_current()); - enable = !bq25710_perf_mode_req; -#endif - - if (enable) - reg |= BQ25710_CHARGE_OPTION_0_LOW_POWER_MODE; - else - reg &= ~BQ25710_CHARGE_OPTION_0_LOW_POWER_MODE; - - rv = raw_write16(chgnum, BQ25710_REG_CHARGE_OPTION_0, reg); -#ifdef CONFIG_CHARGER_BQ25710_IDCHG_LIMIT_MA - mutex_unlock(&bq25710_perf_mode_mutex); -#endif - if (rv) - return rv; - - return EC_SUCCESS; -} - -static int bq25710_adc_start(int chgnum, int adc_en_mask) -{ - int reg; - int mode; - int tries_left = BQ25710_ADC_OPTION_ADC_CONV_MS; - - /* Save current mode to restore same state after ADC read */ - if (bq25710_get_low_power_mode(chgnum, &mode)) - return EC_ERROR_UNKNOWN; - - /* Exit low power mode so ADC conversion takes typical time */ - if (bq25710_set_low_power_mode(chgnum, 0)) - return EC_ERROR_UNKNOWN; - - /* - * Turn on the ADC for one reading. Note that adc_en_mask - * maps to bit[7:0] in ADCOption register. - */ - reg = (adc_en_mask & BQ25710_ADC_OPTION_EN_ADC_ALL) | - BQ25710_ADC_OPTION_ADC_START; - if (raw_write16(chgnum, BQ25710_REG_ADC_OPTION, reg)) - return EC_ERROR_UNKNOWN; - - /* - * Wait until the ADC operation completes. The spec says typical - * conversion time is 10 msec (25 msec on bq25720). If low power - * mode isn't exited first, then the conversion time jumps to - * ~60 msec. - */ - do { - /* sleep 2 ms so we time out after 2x the expected time */ - msleep(2); - raw_read16(chgnum, BQ25710_REG_ADC_OPTION, ®); - } while (--tries_left && (reg & BQ25710_ADC_OPTION_ADC_START)); - - /* ADC reading attempt complete, go back to low power mode */ - if (bq25710_set_low_power_mode(chgnum, mode)) - return EC_ERROR_UNKNOWN; - - /* Could not complete read */ - if (reg & BQ25710_ADC_OPTION_ADC_START) - return EC_ERROR_TIMEOUT; - - return EC_SUCCESS; -} -#endif - -static void bq25710_init(int chgnum) -{ - int reg; - int vsys; - int rv; - - /* - * Reset registers to their default settings. There is no reset pin for - * this chip so without a full power cycle, some registers may not be at - * their default values. Note, need to save the POR value of - * MIN_SYSTEM_VOLTAGE register prior to setting the reset so that the - * correct value is preserved. In order to have the correct value read, - * the bq25710 must not be in low power mode, otherwise the VDDA rail - * may not be powered if AC is not connected. Note, this reset is only - * required when running out of RO and not following sysjump to RW. - */ - if (!system_jumped_late()) { - rv = bq25710_set_low_power_mode(chgnum, 0); - /* Allow enough time for VDDA to be powered */ - msleep(BQ25710_VDDA_STARTUP_DELAY_MSEC); - rv |= raw_read16(chgnum, BQ25710_REG_MIN_SYSTEM_VOLTAGE, &vsys); - rv |= raw_read16(chgnum, BQ25710_REG_CHARGE_OPTION_3, ®); - if (!rv) { - reg |= BQ25710_CHARGE_OPTION_3_RESET_REG; - /* Set all registers to default values */ - raw_write16(chgnum, BQ25710_REG_CHARGE_OPTION_3, reg); - /* Restore VSYS_MIN voltage to POR reset value */ - raw_write16(chgnum, BQ25710_REG_MIN_SYSTEM_VOLTAGE, - vsys); - } - /* Reenable low power mode */ - bq25710_set_low_power_mode(chgnum, 1); - } - - if (!raw_read16(chgnum, BQ25710_REG_PROCHOT_OPTION_1, ®)) { - /* Disable VDPM prochot profile at initialization */ - reg &= ~BQ25710_PROCHOT_PROFILE_VDPM; - /* - * Enable PROCHOT to be asserted with VSYS min detection. Note - * that when no battery is present, then VSYS will be set to the - * value in register 0x3E (MinSysVoltage) which means that when - * no battery is present prochot will continuosly be asserted. - */ - reg |= BQ25710_PROCHOT_PROFILE_VSYS; -#ifdef CONFIG_CHARGER_BQ25710_IDCHG_LIMIT_MA - /* - * Set the IDCHG limit who's value is defined in the config - * option in mA. Also, enable IDCHG trigger for prochot. - */ - reg &= ~BQ25710_PROCHOT_IDCHG_VTH_MASK; - /* - * IDCHG limit is in 512 mA steps. Note there is a 128 mA offset - * so the actual IDCHG limit will be the value stored in bits - * 15:10 + 128 mA. - */ - reg |= ((CONFIG_CHARGER_BQ25710_IDCHG_LIMIT_MA << 1) & - BQ25710_PROCHOT_IDCHG_VTH_MASK); - reg |= BQ25710_PROCHOT_PROFILE_IDCHG; -#endif - raw_write16(chgnum, BQ25710_REG_PROCHOT_OPTION_1, reg); -#ifdef CONFIG_CHARGER_BQ25720_VSYS_TH2_DV - /* - * The default VSYS_TH2 is 5.9v for a 2S config. Boards - * may need to increase this for stability. PROCHOT is - * asserted when the threshold is reached. - */ - if (!raw_read16(chgnum, BQ25720_REG_VMIN_ACTIVE_PROTECTION, - ®)) { - reg &= ~BQ25720_VMIN_AP_VSYS_TH2_MASK; - reg |= VMIN_AP_VSYS_TH2_TO_REG( - CONFIG_CHARGER_BQ25720_VSYS_TH2_DV) << - BQ25720_VMIN_AP_VSYS_TH2_SHIFT; - raw_write16(chgnum, BQ25720_REG_VMIN_ACTIVE_PROTECTION, - reg); - } -#endif - } - - /* Reduce ILIM from default of 150% to 105% */ - if (!raw_read16(chgnum, BQ25710_REG_PROCHOT_OPTION_0, ®)) { - reg &= ~BQ25710_PROCHOT0_ILIM_VTH_MASK; - raw_write16(chgnum, BQ25710_REG_PROCHOT_OPTION_0, reg); - } - - /* - * Reduce peak power mode overload and relax cycle time from default 20 - * msec to the minimum of 5 msec. - */ - if (!raw_read16(chgnum, BQ25710_REG_CHARGE_OPTION_2, ®)) { - reg &= ~BQ25710_CHARGE_OPTION_2_TMAX_MASK; - raw_write16(chgnum, BQ25710_REG_CHARGE_OPTION_2, reg); - } -} - -/* Charger interfaces */ -static const struct charger_info *bq25710_get_info(int chgnum) -{ - return &bq25710_charger_info; -} - -static enum ec_error_list bq25710_post_init(int chgnum) -{ - /* - * Note: bq25710 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 - * discharge on AC = disabled - */ - - return EC_SUCCESS; -} - -static enum ec_error_list bq25710_get_status(int chgnum, int *status) -{ - int rv; - int option; - - rv = bq25710_get_option(chgnum, &option); - if (rv) - return rv; - - /* Default status */ - *status = CHARGER_LEVEL_2; - - if (option & BQ25710_CHARGE_OPTION_0_CHRG_INHIBIT) - *status |= CHARGER_CHARGE_INHIBITED; - - return EC_SUCCESS; -} - -static enum ec_error_list bq25710_set_mode(int chgnum, int mode) -{ - int rv; - int option; - - rv = bq25710_get_option(chgnum, &option); - if (rv) - return rv; - - if (mode & CHARGER_CHARGE_INHIBITED) - option |= BQ25710_CHARGE_OPTION_0_CHRG_INHIBIT; - else - option &= ~BQ25710_CHARGE_OPTION_0_CHRG_INHIBIT; - - return bq25710_set_option(chgnum, option); -} - -static enum ec_error_list bq25710_enable_otg_power(int chgnum, int enabled) -{ - /* This is controlled with the EN_OTG pin. Support not added yet. */ - return EC_ERROR_UNIMPLEMENTED; -} - -static enum ec_error_list bq25710_set_otg_current_voltage(int chgum, - int output_current, - int output_voltage) -{ - /* Add when needed. */ - return EC_ERROR_UNIMPLEMENTED; -} - -static enum ec_error_list bq25710_get_current(int chgnum, int *current) -{ - int rv, reg; - - rv = raw_read16(chgnum, BQ25710_REG_CHARGE_CURRENT, ®); - if (!rv) - *current = REG_TO_CHARGING_CURRENT(reg); - - return rv; -} - -static enum ec_error_list bq25710_set_current(int chgnum, int current) -{ - return raw_write16(chgnum, BQ25710_REG_CHARGE_CURRENT, - CHARGING_CURRENT_TO_REG(current)); -} - -/* Get/set charge voltage limit in mV */ -static enum ec_error_list bq25710_get_voltage(int chgnum, int *voltage) -{ - return raw_read16(chgnum, BQ25710_REG_MAX_CHARGE_VOLTAGE, voltage); -} - -static enum ec_error_list bq25710_set_voltage(int chgnum, int voltage) -{ - return raw_write16(chgnum, BQ25710_REG_MAX_CHARGE_VOLTAGE, voltage); -} - -/* Discharge battery when on AC power. */ -static enum ec_error_list bq25710_discharge_on_ac(int chgnum, int enable) -{ - int rv, option; - - rv = bq25710_get_option(chgnum, &option); - if (rv) - return rv; - - if (enable) - option |= BQ25710_CHARGE_OPTION_0_EN_LEARN; - else - option &= ~BQ25710_CHARGE_OPTION_0_EN_LEARN; - - return bq25710_set_option(chgnum, option); -} - -static enum ec_error_list bq25710_set_input_current_limit(int chgnum, - int input_current) -{ - int num_steps = iin_host_current_to_reg(input_current); - - return raw_write16(chgnum, BQ25710_REG_IIN_HOST, - num_steps << BQ25710_IIN_HOST_CURRENT_SHIFT); -} - -static enum ec_error_list bq25710_get_input_current_limit(int chgnum, - int *input_current) -{ - int rv, reg; - - /* - * IIN_DPM register reflects the actual input current limit programmed - * in the register, either from host or from ICO. After ICO, the - * current limit used by DPM regulation may differ from the IIN_HOST - * register settings. - */ - rv = raw_read16(chgnum, BQ25710_REG_IIN_DPM, ®); - if (!rv) - *input_current = - iin_dpm_reg_to_current(reg >> - BQ25710_IIN_DPM_CURRENT_SHIFT); - - return rv; -} - -static enum ec_error_list bq25710_manufacturer_id(int chgnum, int *id) -{ - return raw_read16(chgnum, BQ25710_REG_MANUFACTURER_ID, id); -} - -static enum ec_error_list bq25710_device_id(int chgnum, int *id) -{ - return raw_read16(chgnum, BQ25710_REG_DEVICE_ADDRESS, id); -} - -#ifdef CONFIG_USB_PD_VBUS_MEASURE_CHARGER - -#if defined(CONFIG_CHARGER_BQ25720) - -static int reg_adc_vbus_to_mv(int reg) -{ - /* - * LSB => 96mV, no DC offset. - */ - return reg * BQ25720_ADC_VBUS_STEP_MV; -} - -#elif defined(CONFIG_CHARGER_BQ25710) - -static int reg_adc_vbus_to_mv(int reg) -{ - /* - * LSB => 64mV. - * Return 0 when VBUS <= 3.2V as ADC can't measure it. - */ - return reg ? - (reg * BQ25710_ADC_VBUS_STEP_MV + BQ25710_ADC_VBUS_BASE_MV) : 0; -} - -#else -#error Only the BQ25720 and BQ25710 are supported by bq25710 driver. -#endif - -static enum ec_error_list bq25710_get_vbus_voltage(int chgnum, int port, - int *voltage) -{ - int reg, rv; - - rv = bq25710_adc_start(chgnum, BQ25710_ADC_OPTION_EN_ADC_VBUS); - if (rv) - goto error; - - /* Read ADC value */ - rv = raw_read16(chgnum, BQ25710_REG_ADC_VBUS_PSYS, ®); - if (rv) - goto error; - - reg >>= BQ25710_ADC_VBUS_STEP_BIT_OFFSET; - *voltage = reg_adc_vbus_to_mv(reg); - -error: - if (rv) - CPRINTF("Could not read VBUS ADC! Error: %d\n", rv); - return rv; -} -#endif - -static enum ec_error_list bq25710_get_option(int chgnum, int *option) -{ - /* There are 4 option registers, but we only need the first for now. */ - return raw_read16(chgnum, BQ25710_REG_CHARGE_OPTION_0, option); -} - -static enum ec_error_list bq25710_set_option(int chgnum, int option) -{ - /* There are 4 option registers, but we only need the first for now. */ - return raw_write16(chgnum, BQ25710_REG_CHARGE_OPTION_0, option); -} - -int bq25710_set_min_system_voltage(int chgnum, int mv) -{ - int reg; - - reg = min_system_voltage_to_reg(mv); - return raw_write16(chgnum, BQ25710_REG_MIN_SYSTEM_VOLTAGE, reg); -} - -#ifdef CONFIG_CHARGE_RAMP_HW - -static void bq25710_chg_ramp_handle(void) -{ - int ramp_curr; - int chgnum = 0; - - if (IS_ENABLED(CONFIG_OCPC)) - chgnum = charge_get_active_chg_chip(); - - /* - * Once the charge ramp is stable write back the stable ramp - * current to the host input current limit register - */ - ramp_curr = chg_ramp_get_current_limit(); - if (chg_ramp_is_stable()) { - if (ramp_curr && - !charger_set_input_current_limit(chgnum, ramp_curr)) - CPRINTF("bq25710: stable ramp current=%d\n", ramp_curr); - } else { - CPRINTF("bq25710: ICO stall, ramp current=%d\n", ramp_curr); - } - /* - * Disable ICO mode. When ICO mode is active the input current limit is - * given by the value in register IIN_DPM (0x22) - */ - charger_set_hw_ramp(0); -} -DECLARE_DEFERRED(bq25710_chg_ramp_handle); - -static enum ec_error_list bq25710_set_hw_ramp(int chgnum, int enable) -{ - int option3_reg, option2_reg, rv; - - rv = raw_read16(chgnum, BQ25710_REG_CHARGE_OPTION_3, &option3_reg); - if (rv) - return rv; - rv = raw_read16(chgnum, BQ25710_REG_CHARGE_OPTION_2, &option2_reg); - if (rv) - return rv; - - if (enable) { - /* - * ICO mode can only be used when a battery is present. If there - * is no battery, or if the battery has not recovered yet from - * cutoff, then enabling ICO mode will lead to VSYS - * dropping out. - */ - if (!battery_is_present() || (battery_get_disconnect_state() != - BATTERY_NOT_DISCONNECTED)) { - CPRINTF("bq25710: no battery, skip ICO enable\n"); - return EC_ERROR_UNKNOWN; - } - - /* Set InputVoltage register to BC1.2 minimum ramp voltage */ - rv = raw_write16(chgnum, BQ25710_REG_INPUT_VOLTAGE, - BQ25710_BC12_MIN_VOLTAGE_MV); - if (rv) - return rv; - - /* Enable ICO algorithm */ - option3_reg |= BQ25710_CHARGE_OPTION_3_EN_ICO_MODE; - - /* 0b: Input current limit is set by BQ25710_REG_IIN_HOST */ - option2_reg &= ~BQ25710_CHARGE_OPTION_2_EN_EXTILIM; - - /* Charge ramp may take up to 2s to settle down */ - hook_call_deferred(&bq25710_chg_ramp_handle_data, (4 * SECOND)); - } else { - /* Disable ICO algorithm */ - option3_reg &= ~BQ25710_CHARGE_OPTION_3_EN_ICO_MODE; - - /* - * 1b: Input current limit is set by the lower value of - * ILIM_HIZ pin and BQ25710_REG_IIN_HOST - */ - option2_reg |= BQ25710_CHARGE_OPTION_2_EN_EXTILIM; - } - - rv = raw_write16(chgnum, BQ25710_REG_CHARGE_OPTION_2, option2_reg); - if (rv) - return rv; - return raw_write16(chgnum, BQ25710_REG_CHARGE_OPTION_3, option3_reg); -} - -static int bq25710_ramp_is_stable(int chgnum) -{ - int reg; - - if (raw_read16(chgnum, BQ25710_REG_CHARGER_STATUS, ®)) - return 0; - - return reg & BQ25710_CHARGE_STATUS_ICO_DONE; -} - -static int bq25710_ramp_get_current_limit(int chgnum) -{ - int reg, rv; - - rv = raw_read16(chgnum, BQ25710_REG_IIN_DPM, ®); - if (rv) { - CPRINTF("Could not read iin_dpm current limit! Error: %d\n", - rv); - return 0; - } - - return iin_dpm_reg_to_current(reg >> BQ25710_IIN_DPM_CURRENT_SHIFT); -} -#endif /* CONFIG_CHARGE_RAMP_HW */ - -#ifdef CONFIG_CHARGER_BQ25710_IDCHG_LIMIT_MA -/* Called on AP S5 -> S3 and S3/S0iX -> S0 transition */ -static void bq25710_chipset_startup(void) -{ - bq25710_set_low_power_mode(CHARGER_SOLO, 0); -} -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, bq25710_chipset_startup, HOOK_PRIO_DEFAULT); -DECLARE_HOOK(HOOK_CHIPSET_RESUME, bq25710_chipset_startup, HOOK_PRIO_DEFAULT); - - -/* Called on AP S0 -> S0iX/S3 or S3 -> S5 transition */ -static void bq25710_chipset_suspend(void) -{ - bq25710_set_low_power_mode(CHARGER_SOLO, 1); -} -DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, bq25710_chipset_suspend, HOOK_PRIO_DEFAULT); -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, bq25710_chipset_suspend, HOOK_PRIO_DEFAULT); -#endif - -#ifdef CONFIG_CMD_CHARGER_DUMP -static int console_bq25710_dump_regs(int argc, char **argv) -{ - int i; - int val; - int chgnum = 0; - char *e; - - /* Dump all readable registers on bq25710. */ - static const uint8_t regs[] = { - BQ25710_REG_CHARGE_OPTION_0, - BQ25710_REG_CHARGE_CURRENT, - BQ25710_REG_MAX_CHARGE_VOLTAGE, - BQ25710_REG_CHARGER_STATUS, - BQ25710_REG_PROCHOT_STATUS, - BQ25710_REG_IIN_DPM, - BQ25710_REG_ADC_VBUS_PSYS, - BQ25710_REG_ADC_IBAT, - BQ25710_REG_ADC_CMPIN_IIN, - BQ25710_REG_ADC_VSYS_VBAT, - BQ25710_REG_CHARGE_OPTION_1, - BQ25710_REG_CHARGE_OPTION_2, - BQ25710_REG_CHARGE_OPTION_3, - BQ25710_REG_PROCHOT_OPTION_0, - BQ25710_REG_PROCHOT_OPTION_1, - BQ25710_REG_ADC_OPTION, -#ifdef CONFIG_CHARGER_BQ25720 - BQ25720_REG_CHARGE_OPTION_4, - BQ25720_REG_VMIN_ACTIVE_PROTECTION, -#endif - BQ25710_REG_OTG_VOLTAGE, - BQ25710_REG_OTG_CURRENT, - BQ25710_REG_INPUT_VOLTAGE, - BQ25710_REG_MIN_SYSTEM_VOLTAGE, - BQ25710_REG_IIN_HOST, - BQ25710_REG_MANUFACTURER_ID, - BQ25710_REG_DEVICE_ADDRESS, - }; - if (argc >= 2) { - chgnum = strtoi(argv[1], &e, 10); - if (*e) - return EC_ERROR_PARAM1; - } - - for (i = 0; i < ARRAY_SIZE(regs); ++i) { - if (raw_read16(chgnum, regs[i], &val)) - continue; - ccprintf("BQ25710 REG 0x%02x: 0x%04x\n", regs[i], val); - } - - - return 0; -} -DECLARE_CONSOLE_COMMAND(charger_dump, console_bq25710_dump_regs, - "charger_dump <chgnum>", - "Dump all charger registers"); - -#endif /* CONFIG_CMD_CHARGER_DUMP */ - -const struct charger_drv bq25710_drv = { - .init = &bq25710_init, - .post_init = &bq25710_post_init, - .get_info = &bq25710_get_info, - .get_status = &bq25710_get_status, - .set_mode = &bq25710_set_mode, - .enable_otg_power = &bq25710_enable_otg_power, - .set_otg_current_voltage = &bq25710_set_otg_current_voltage, - .get_current = &bq25710_get_current, - .set_current = &bq25710_set_current, - .get_voltage = &bq25710_get_voltage, - .set_voltage = &bq25710_set_voltage, - .discharge_on_ac = &bq25710_discharge_on_ac, - .get_vbus_voltage = &bq25710_get_vbus_voltage, - .set_input_current_limit = &bq25710_set_input_current_limit, - .get_input_current_limit = &bq25710_get_input_current_limit, - .manufacturer_id = &bq25710_manufacturer_id, - .device_id = &bq25710_device_id, - .get_option = &bq25710_get_option, - .set_option = &bq25710_set_option, -#ifdef CONFIG_CHARGE_RAMP_HW - .set_hw_ramp = &bq25710_set_hw_ramp, - .ramp_is_stable = &bq25710_ramp_is_stable, - .ramp_get_current_limit = &bq25710_ramp_get_current_limit, -#endif /* CONFIG_CHARGE_RAMP_HW */ -}; diff --git a/driver/charger/bq25710.h b/driver/charger/bq25710.h deleted file mode 100644 index 68c7619ceb..0000000000 --- a/driver/charger/bq25710.h +++ /dev/null @@ -1,143 +0,0 @@ -/* Copyright 2018 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 bq25710 battery charger driver. - */ - -#ifndef __CROS_EC_BQ25710_H -#define __CROS_EC_BQ25710_H - -/* SMBUS Interface */ -#define BQ25710_SMBUS_ADDR1_FLAGS 0x09 - -#define BQ25710_BC12_MIN_VOLTAGE_MV 1408 - -/* Registers */ -#define BQ25710_REG_CHARGE_OPTION_0 0x12 -#define BQ25710_REG_CHARGE_CURRENT 0x14 -#define BQ25710_REG_MAX_CHARGE_VOLTAGE 0x15 -#define BQ25710_REG_CHARGER_STATUS 0x20 -#define BQ25710_REG_PROCHOT_STATUS 0x21 -#define BQ25710_REG_IIN_DPM 0x22 -#define BQ25710_REG_ADC_VBUS_PSYS 0x23 -#define BQ25710_REG_ADC_IBAT 0x24 -#define BQ25710_REG_ADC_CMPIN_IIN 0x25 -#define BQ25710_REG_ADC_VSYS_VBAT 0x26 -#define BQ25710_REG_CHARGE_OPTION_1 0x30 -#define BQ25710_REG_CHARGE_OPTION_2 0x31 -#define BQ25710_REG_CHARGE_OPTION_3 0x32 -#define BQ25710_REG_PROCHOT_OPTION_0 0x33 -#define BQ25710_REG_PROCHOT_OPTION_1 0x34 -#define BQ25710_REG_ADC_OPTION 0x35 -#ifdef CONFIG_CHARGER_BQ25720 -#define BQ25720_REG_CHARGE_OPTION_4 0x36 -#define BQ25720_REG_VMIN_ACTIVE_PROTECTION 0x37 -#endif -#define BQ25710_REG_OTG_VOLTAGE 0x3B -#define BQ25710_REG_OTG_CURRENT 0x3C -#define BQ25710_REG_INPUT_VOLTAGE 0x3D -#define BQ25710_REG_MIN_SYSTEM_VOLTAGE 0x3E -#define BQ25710_REG_IIN_HOST 0x3F -#define BQ25710_REG_MANUFACTURER_ID 0xFE -#define BQ25710_REG_DEVICE_ADDRESS 0xFF - -/* ChargeOption0 Register */ -#define BQ25710_CHARGE_OPTION_0_LOW_POWER_MODE BIT(15) -#define BQ25710_CHARGE_OPTION_0_IDPM_AUTO_DIS BIT(12) -#define BQ25710_CHARGE_OPTION_0_EN_LEARN BIT(5) -#define BQ25710_CHARGE_OPTION_0_IADP_GAIN BIT(4) -#define BQ25710_CHARGE_OPTION_0_EN_IDPM BIT(1) -#define BQ25710_CHARGE_OPTION_0_CHRG_INHIBIT BIT(0) - -/* ChargeOption2 Register */ -#define BQ25710_CHARGE_OPTION_2_EN_EXTILIM BIT(7) -#define BQ25710_CHARGE_OPTION_2_TMAX_SHIFT 8 -#define BQ25710_CHARGE_OPTION_2_TMAX_MASK (0x3 << \ - BQ25710_CHARGE_OPTION_2_TMAX_SHIFT) - -/* ChargeOption3 Register */ -#define BQ25710_CHARGE_OPTION_3_RESET_REG BIT(14) -#define BQ25710_CHARGE_OPTION_3_EN_ICO_MODE BIT(11) - -/* ChargeStatus Register */ -#define BQ25710_CHARGE_STATUS_ICO_DONE BIT(14) - -/* IIN_DPM Register */ -#define BQ25710_IIN_DPM_CURRENT_SHIFT 8 -#define BQ25710_IIN_DPM_CURRENT_STEP_MA 50 - -/* ADCOption Register */ -#define BQ25710_ADC_OPTION_ADC_START BIT(14) -#define BQ25710_ADC_OPTION_EN_ADC_VBUS BIT(6) -#define BQ25710_ADC_OPTION_EN_ADC_IIN BIT(4) -#define BQ25710_ADC_OPTION_EN_ADC_ALL 0xFF - -/* ADC conversion time ins ms */ -#if defined(CONFIG_CHARGER_BQ25720) -#define BQ25710_ADC_OPTION_ADC_CONV_MS 25 -#elif defined(CONFIG_CHARGER_BQ25710) -#define BQ25710_ADC_OPTION_ADC_CONV_MS 10 -#else -#error Only the BQ25720 and BQ25710 are supported by bq25710 driver. -#endif - -/* ADCVBUS/PSYS Register */ -#if defined(CONFIG_CHARGER_BQ25720) -#define BQ25720_ADC_VBUS_STEP_MV 96 -#elif defined(CONFIG_CHARGER_BQ25710) -#define BQ25710_ADC_VBUS_STEP_MV 64 -#define BQ25710_ADC_VBUS_BASE_MV 3200 -#else -#error Only the BQ25720 and BQ25710 are supported by bq25710 driver. -#endif -#define BQ25710_ADC_VBUS_STEP_BIT_OFFSET 8 - -/* ADCIIN Register */ -#define BQ25710_ADC_IIN_STEP_MA 50 -#define BQ25710_ADC_IIN_STEP_BIT_OFFSET 8 - -/* ProchotOption0 Register */ -#define BQ25710_PROCHOT0_ILIM_VTH_SHIFT 11 -#define BQ25710_PROCHOT0_ILIM_VTH_MASK (0x1f << \ - BQ25710_PROCHOT0_ILIM_VTH_SHIFT) - -/* ProchotOption1 Register */ -#define BQ25710_PROCHOT_PROFILE_VDPM BIT(7) -#define BQ25710_PROCHOT_PROFILE_IDCHG BIT(3) -#define BQ25710_PROCHOT_PROFILE_VSYS BIT(2) -#define BQ25710_PROCHOT_IDCHG_VTH_MASK 0xFC00 - -/* IIN_HOST Register */ -#define BQ25710_IIN_HOST_CURRENT_SHIFT 8 -#define BQ25710_IIN_HOST_CURRENT_STEP_MA 50 - -#if defined(CONFIG_CHARGER_BQ25720) -/* Vmin Active Protection Register */ -#define BQ25720_VMIN_AP_VSYS_TH2_SHIFT 2 -#define BQ25720_VMIN_AP_VSYS_TH2_MASK GENMASK(7, \ - BQ25720_VMIN_AP_VSYS_TH2_SHIFT) -#endif - -/* Min System Voltage Register */ -#if defined(CONFIG_CHARGER_BQ25720) -#define BQ25710_MIN_SYSTEM_VOLTAGE_STEP_MV 100 -#elif defined(CONFIG_CHARGER_BQ25710) -#define BQ25710_MIN_SYSTEM_VOLTAGE_STEP_MV 256 -#else -#error Only the BQ25720 and BQ25710 are supported by bq25710 driver. -#endif -#define BQ25710_MIN_SYSTEM_VOLTAGE_SHIFT 8 - -extern const struct charger_drv bq25710_drv; - -/** - * Set VSYS_MIN - * - * @param chgnum: Index into charger chips - * @param mv: min system voltage in mV - * @return EC_SUCCESS or error - */ -int bq25710_set_min_system_voltage(int chgnum, int mv); - -#endif /* __CROS_EC_BQ25710_H */ diff --git a/driver/charger/isl923x.c b/driver/charger/isl923x.c deleted file mode 100644 index 9e3284c29f..0000000000 --- a/driver/charger/isl923x.c +++ /dev/null @@ -1,1471 +0,0 @@ -/* Copyright 2015 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. - * - * Intersil ISL-9237/8 battery charger driver. - */ - -#include "adc.h" -#include "battery.h" -#include "battery_smart.h" -#include "charge_state_v2.h" -#include "charger.h" -#include "compile_time_macros.h" -#include "console.h" -#include "common.h" -#include "hooks.h" -#include "i2c.h" -#include "isl923x.h" -#include "ocpc.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "usb_pd_tcpm.h" -#include "util.h" - -#ifndef CONFIG_CHARGER_NARROW_VDC -#error "ISL9237/8 is a NVDC charger, please enable CONFIG_CHARGER_NARROW_VDC." -#endif - -#if defined(CONFIG_CHARGER_ISL9238) || defined(CONFIG_CHARGER_ISL9238C) -#define CHARGER_ISL9238X -#endif - -#ifdef CONFIG_CHARGER_SENSE_RESISTOR_AC_ISL9238 - #undef CONFIG_CHARGER_SENSE_RESISTOR_AC - #define CONFIG_CHARGER_SENSE_RESISTOR_AC \ - CONFIG_CHARGER_SENSE_RESISTOR_AC_ISL9238 -#endif - - -#define DEFAULT_R_AC 20 -#define DEFAULT_R_SNS 10 -#define R_AC CONFIG_CHARGER_SENSE_RESISTOR_AC -#define R_SNS CONFIG_CHARGER_SENSE_RESISTOR -#define REG_TO_CURRENT(REG) ((REG) * DEFAULT_R_SNS / R_SNS) -#define CURRENT_TO_REG(CUR) ((CUR) * R_SNS / DEFAULT_R_SNS) -#define AC_REG_TO_CURRENT(REG) ((REG) * DEFAULT_R_AC / R_AC) -#define AC_CURRENT_TO_REG(CUR) ((CUR) * R_AC / DEFAULT_R_AC) - -#if defined(CONFIG_CHARGER_ISL9237) -#define CHARGER_NAME "isl9237" -#define CHARGE_V_MAX ISL9237_SYS_VOLTAGE_REG_MAX -#define CHARGE_V_MIN ISL923X_SYS_VOLTAGE_REG_MIN -#define CHARGE_V_STEP 8 -#elif defined(CONFIG_CHARGER_ISL9238) -#define CHARGER_NAME "isl9238" -#define CHARGE_V_MAX ISL9238_SYS_VOLTAGE_REG_MAX -#define CHARGE_V_MIN ISL923X_SYS_VOLTAGE_REG_MIN -#define CHARGE_V_STEP 8 -#elif defined(CONFIG_CHARGER_ISL9238C) -#define CHARGER_NAME "isl9238c" -#define CHARGE_V_MAX ISL9238_SYS_VOLTAGE_REG_MAX -#define CHARGE_V_MIN ISL923X_SYS_VOLTAGE_REG_MIN -#define CHARGE_V_STEP 8 -#elif defined(CONFIG_CHARGER_RAA489000) -#define CHARGER_NAME "raa489000" -#define CHARGE_V_MAX RAA489000_SYS_VOLTAGE_REG_MAX -#define CHARGE_V_MIN RAA489000_SYS_VOLTAGE_REG_MIN -#define CHARGE_V_STEP 8 -#endif - -#ifdef CONFIG_CHARGER_RAA489000 -#define CHARGE_I_MAX RAA489000_CURRENT_REG_MAX -#else -#define CHARGE_I_MAX ISL923X_CURRENT_REG_MAX -#endif /* CONFIG_CHARGER_RAA489000 */ -#define CHARGE_I_MIN 4 -#define CHARGE_I_OFF 0 -#define CHARGE_I_STEP 4 -#ifdef CONFIG_CHARGER_RAA489000 -#define INPUT_I_MAX RAA489000_CURRENT_REG_MAX -#else -#define INPUT_I_MAX ISL923X_CURRENT_REG_MAX -#endif /* CONFIG_CHARGER_RAA489000 */ -#define INPUT_I_MIN 4 -#define INPUT_I_STEP 4 - -/* Console output macros */ -#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args) -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) - -enum isl923x_amon_bmon { AMON, BMON }; -enum isl923x_mon_dir { MON_CHARGE = 0, MON_DISCHARGE = 1 }; - -static int learn_mode; - -/* Mutex for CONTROL1 register, that can be updated from multiple tasks. */ -K_MUTEX_DEFINE(control1_mutex); - -static enum ec_error_list isl923x_discharge_on_ac(int chgnum, int enable); - -/* Charger parameters */ -static const struct charger_info isl9237_charger_info = { - .name = CHARGER_NAME, - .voltage_max = CHARGE_V_MAX, - .voltage_min = CHARGE_V_MIN, - .voltage_step = CHARGE_V_STEP, - .current_max = REG_TO_CURRENT(CHARGE_I_MAX), - .current_min = REG_TO_CURRENT(CHARGE_I_MIN), - .current_step = REG_TO_CURRENT(CHARGE_I_STEP), - .input_current_max = AC_REG_TO_CURRENT(INPUT_I_MAX), - .input_current_min = AC_REG_TO_CURRENT(INPUT_I_MIN), - .input_current_step = AC_REG_TO_CURRENT(INPUT_I_STEP), -}; - -static inline enum ec_error_list raw_read8(int chgnum, int offset, int *value) -{ - return i2c_read8(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - offset, value); -} - -static inline enum ec_error_list raw_read16(int chgnum, int offset, int *value) -{ - return i2c_read16(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - offset, value); -} - -static inline enum ec_error_list raw_write16(int chgnum, int offset, int value) -{ - return i2c_write16(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - offset, value); -} - -static inline enum ec_error_list raw_update16(int chgnum, int offset, int mask, - enum mask_update_action action) -{ - return i2c_update16(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - offset, mask, action); -} - -static enum ec_error_list isl9237_set_current(int chgnum, uint16_t current) -{ - return raw_write16(chgnum, ISL923X_REG_CHG_CURRENT, - CURRENT_TO_REG(current)); -} - -static enum ec_error_list isl9237_set_voltage(int chgnum, uint16_t voltage) -{ - return raw_write16(chgnum, ISL923X_REG_SYS_VOLTAGE_MAX, voltage); -} - -/* chip specific interfaces */ - -static enum ec_error_list isl923x_set_input_current_limit(int chgnum, - int input_current) -{ - int rv; - uint16_t reg = AC_CURRENT_TO_REG(input_current); - - rv = raw_write16(chgnum, ISL923X_REG_ADAPTER_CURRENT_LIMIT1, reg); - if (rv) - return rv; - - return raw_write16(chgnum, ISL923X_REG_ADAPTER_CURRENT_LIMIT2, reg); -} - -#ifdef CONFIG_CMD_CHARGER_ADC_AMON_BMON -static int get_amon_bmon(int chgnum, enum isl923x_amon_bmon amon, - enum isl923x_mon_dir direction, int *adc) -{ - int reg, ret; - - if (IS_ENABLED(CHARGER_ISL9238X)) { - ret = raw_read16(chgnum, ISL9238_REG_CONTROL3, ®); - if (ret) - return ret; - - /* Switch direction */ - if (direction) - reg |= ISL9238_C3_AMON_BMON_DIRECTION; - else - reg &= ~ISL9238_C3_AMON_BMON_DIRECTION; - ret = raw_write16(chgnum, ISL9238_REG_CONTROL3, reg); - if (ret) - return ret; - } - - mutex_lock(&control1_mutex); - - ret = raw_read16(chgnum, ISL923X_REG_CONTROL1, ®); - if (!ret) { - /* Switch between AMON/BMON */ - if (amon == AMON) - reg &= ~ISL923X_C1_SELECT_BMON; - else - reg |= ISL923X_C1_SELECT_BMON; - - /* Enable monitor */ - reg &= ~ISL923X_C1_DISABLE_MON; - ret = raw_write16(chgnum, ISL923X_REG_CONTROL1, reg); - } - - mutex_unlock(&control1_mutex); - - if (ret) - return ret; - - *adc = adc_read_channel(ADC_AMON_BMON); - - return ret; -} -#endif - -static enum ec_error_list isl923x_get_input_current_limit(int chgnum, - int *input_current) -{ - int rv; - int regval; - - rv = raw_read16(chgnum, ISL923X_REG_ADAPTER_CURRENT_LIMIT1, ®val); - if (rv) - return rv; - - *input_current = AC_REG_TO_CURRENT(regval); - return EC_SUCCESS; -} - -#ifdef CONFIG_CHARGER_RAA489000 -static enum ec_error_list raa489000_get_input_current(int chgnum, - int *input_current) -{ - int rv; - int regval; - int reg; - - reg = RAA489000_REG_ADC_INPUT_CURRENT; - - rv = raw_read16(chgnum, reg, ®val); - if (rv) - return rv; - - /* The value is in 22.2mA increments. */ - regval *= 222; - regval /= 10; - - *input_current = AC_REG_TO_CURRENT(regval); - return EC_SUCCESS; -} -#elif defined(CONFIG_CMD_CHARGER_ADC_AMON_BMON) -static enum ec_error_list isl923x_get_input_current(int chgnum, - int *input_current) -{ - int rv, adc; - - rv = get_amon_bmon(chgnum, AMON, MON_CHARGE, &adc); - if (rv) - return rv; - - *input_current = adc / CONFIG_CHARGER_SENSE_RESISTOR_AC; - - return EC_SUCCESS; -} -#endif /* CONFIG_CHARGER_RAA489000 */ - -#if defined(CONFIG_CHARGER_OTG) && defined(CHARGER_ISL9238X) -static enum ec_error_list isl923x_enable_otg_power(int chgnum, int enabled) -{ - int rv, control1; - - mutex_lock(&control1_mutex); - - rv = raw_read16(chgnum, ISL923X_REG_CONTROL1, &control1); - if (rv) - goto out; - - if (enabled) - control1 |= ISL923X_C1_OTG; - else - control1 &= ~ISL923X_C1_OTG; - - rv = raw_write16(chgnum, ISL923X_REG_CONTROL1, control1); - -out: - mutex_unlock(&control1_mutex); - - return rv; -} - -/* - * TODO(b:67920792): OTG is not implemented for ISL9237 that has different - * register scale and range. - */ -static enum ec_error_list isl923x_set_otg_current_voltage(int chgnum, - int output_current, - int output_voltage) -{ - int rv; - uint16_t volt_reg = (output_voltage / ISL9238_OTG_VOLTAGE_STEP) - << ISL9238_OTG_VOLTAGE_SHIFT; - uint16_t current_reg = - DIV_ROUND_UP(output_current, ISL923X_OTG_CURRENT_STEP) - << ISL923X_OTG_CURRENT_SHIFT; - - if (output_current < 0 || output_current > ISL923X_OTG_CURRENT_MAX || - output_voltage > ISL9238_OTG_VOLTAGE_MAX) - return EC_ERROR_INVAL; - - /* Set voltage. */ - rv = raw_write16(chgnum, ISL923X_REG_OTG_VOLTAGE, volt_reg); - if (rv) - return rv; - - /* Set current. */ - return raw_write16(chgnum, ISL923X_REG_OTG_CURRENT, current_reg); -} -#endif /* CONFIG_CHARGER_OTG && CHARGER_ISL9238X */ - -static enum ec_error_list isl923x_manufacturer_id(int chgnum, int *id) -{ - int rv; - int reg; - - rv = raw_read16(chgnum, ISL923X_REG_MANUFACTURER_ID, ®); - if (rv) - return rv; - - *id = reg; - return EC_SUCCESS; -} - -static enum ec_error_list isl923x_device_id(int chgnum, int *id) -{ - int rv; - int reg; - - rv = raw_read16(chgnum, ISL923X_REG_DEVICE_ID, ®); - if (rv) - return rv; - - *id = reg; - return EC_SUCCESS; -} - -static enum ec_error_list isl923x_get_option(int chgnum, int *option) -{ - int rv; - uint32_t controls; - int reg; - - rv = raw_read16(chgnum, ISL923X_REG_CONTROL0, ®); - if (rv) - return rv; - - controls = reg; - rv = raw_read16(chgnum, ISL923X_REG_CONTROL1, ®); - if (rv) - return rv; - - controls |= reg << 16; - *option = controls; - return EC_SUCCESS; -} - -static enum ec_error_list isl923x_set_option(int chgnum, int option) -{ - int rv; - uint16_t reg; - - reg = option & 0xffff; - rv = raw_write16(chgnum, ISL923X_REG_CONTROL0, reg); - - if (rv) - return rv; - - reg = (option >> 16) & 0xffff; - return raw_write16(chgnum, ISL923X_REG_CONTROL1, reg); -} - -/* Charger interfaces */ - -static const struct charger_info *isl923x_get_info(int chgnum) -{ - return &isl9237_charger_info; -} - -static enum ec_error_list isl923x_get_status(int chgnum, int *status) -{ - *status = CHARGER_LEVEL_2; - - return EC_SUCCESS; -} - -static enum ec_error_list isl923x_set_mode(int chgnum, int mode) -{ - int rv = EC_SUCCESS; - - /* - * See crosbug.com/p/51196. Always disable learn mode unless it was set - * explicitly. - */ - if (!learn_mode) - rv = isl923x_discharge_on_ac(chgnum, 0); - - /* ISL923X does not support inhibit mode setting. */ - return rv; -} - -#ifdef CONFIG_CHARGER_RAA489000 -static enum ec_error_list raa489000_get_actual_current(int chgnum, int *current) -{ - int rv; - int reg; - - rv = raw_read16(chgnum, RAA489000_REG_ADC_CHARGE_CURRENT, ®); - /* The value is in 22.2mA increments. */ - reg *= 222; - reg /= 10; - - *current = REG_TO_CURRENT(reg); - return rv; -} -#endif /* CONFIG_CHARGER_RAA489000 */ - -static enum ec_error_list isl923x_get_current(int chgnum, int *current) -{ - int rv; - int reg; - - rv = raw_read16(chgnum, ISL923X_REG_CHG_CURRENT, ®); - if (rv) - return rv; - - *current = REG_TO_CURRENT(reg); - return EC_SUCCESS; -} - -static enum ec_error_list isl923x_set_current(int chgnum, int current) -{ - return isl9237_set_current(chgnum, current); -} - -#ifdef CONFIG_CHARGER_RAA489000 -static enum ec_error_list raa489000_get_actual_voltage(int chgnum, int *voltage) -{ - int rv; - int reg; - - rv = raw_read16(chgnum, RAA489000_REG_ADC_VSYS, ®); - if (rv) - return rv; - - /* The voltage is returned in bits 13:6. LSB is 96mV. */ - reg &= GENMASK(13, 6); - reg >>= 6; - reg *= 96; - - *voltage = reg; - return EC_SUCCESS; -} -#endif /* CONFIG_CHARGER_RAA489000 */ - -static enum ec_error_list isl923x_get_voltage(int chgnum, int *voltage) -{ - return raw_read16(chgnum, ISL923X_REG_SYS_VOLTAGE_MAX, voltage); -} - -static enum ec_error_list isl923x_set_voltage(int chgnum, int voltage) -{ - /* The ISL923X will drop voltage to as low as requested. As the - * charger state machine will pass in 0 voltage, protect the system - * voltage by capping to the minimum. The reason is that the ISL923X - * only can regulate the system voltage which will kill the board's - * power if below 0. */ - if (voltage == 0) { - const struct battery_info *bi = battery_get_info(); - voltage = bi->voltage_min; - } - - return isl9237_set_voltage(chgnum, voltage); -} - -static enum ec_error_list isl923x_post_init(int chgnum) -{ - /* - * charger_post_init() is called every time AC becomes present in the - * system. It's called this frequently because there are some charger - * ICs which become unpowered when AC is not present. Therefore, upon - * AC becoming present again, the chargers need to be reinitialized. - * The ISL9237/8 can be powered from VSYS and therefore do not need to - * be reinitialized everytime. This is why isl923x_init() is called - * once at HOOK_INIT time. - */ - return EC_SUCCESS; -} - -int isl923x_set_ac_prochot(int chgnum, uint16_t ma) -{ - int rv; - - if (ma > ISL923X_AC_PROCHOT_CURRENT_MAX) { - CPRINTS("%s: invalid current (%d mA)", CHARGER_NAME, ma); - return EC_ERROR_INVAL; - } - - rv = raw_write16(chgnum, ISL923X_REG_PROCHOT_AC, AC_CURRENT_TO_REG(ma)); - if (rv) - CPRINTS("%s set_ac_prochot failed (%d)", CHARGER_NAME, rv); - return rv; -} - -int isl923x_set_dc_prochot(int chgnum, uint16_t ma) -{ - int rv; - - if (ma > ISL923X_DC_PROCHOT_CURRENT_MAX) { - CPRINTS("%s: invalid current (%d mA)", CHARGER_NAME, ma); - return EC_ERROR_INVAL; - } - - rv = raw_write16(chgnum, ISL923X_REG_PROCHOT_DC, CURRENT_TO_REG(ma)); - if (rv) - CPRINTS("%s set_dc_prochot failed (%d)", CHARGER_NAME, rv); - return rv; -} - -int isl923x_set_comparator_inversion(int chgnum, int invert) -{ - int rv; - int regval; - - rv = i2c_read16(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - ISL923X_REG_CONTROL2, ®val); - if (invert) - regval |= ISL923X_C2_INVERT_CMOUT; - else - regval &= ~ISL923X_C2_INVERT_CMOUT; - - if (!rv) - rv |= i2c_write16(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - ISL923X_REG_CONTROL2, regval); - - if (rv) - CPRINTS("%s (%d) set_comparator_inversion failed (rv: %d)", - CHARGER_NAME, chgnum, rv); - - return rv; -} - -static void isl923x_init(int chgnum) -{ - int reg; - const struct battery_info *bi = battery_get_info(); - int precharge_voltage = bi->precharge_voltage ? - bi->precharge_voltage : bi->voltage_min; - - if (IS_ENABLED(CONFIG_CHARGER_RAA489000)) { - if (CONFIG_CHARGER_SENSE_RESISTOR == - CONFIG_CHARGER_SENSE_RESISTOR_AC) { - /* - * A 1:1 ratio for Rs1:Rs2 is allowed, but Control4 - * register Bit<11> must be set. - */ - if (raw_read16(chgnum, ISL9238_REG_CONTROL4, ®)) - goto init_fail; - - if (raw_write16(chgnum, ISL9238_REG_CONTROL4, - reg | - RAA489000_C4_PSYS_RSNS_RATIO_1_TO_1)) - goto init_fail; - } - - /* - * Enable hysteresis for CCM/DCM boundary to help with ripple. - */ - if (raw_read16(chgnum, ISL9238_REG_CONTROL3, ®)) - goto init_fail; - - if (raw_write16(chgnum, ISL9238_REG_CONTROL3, - reg | - RAA489000_C3_DCM_CCM_HYSTERESIS_ENABLE)) - goto init_fail; - - /* Set switching frequency to 600KHz to help with ripple. */ - if (raw_read16(chgnum, ISL923X_REG_CONTROL1, ®)) - goto init_fail; - - reg &= ~ISL923X_C1_SWITCH_FREQ_MASK; - - if (raw_write16(chgnum, ISL923X_REG_CONTROL1, - reg | - ISL9237_C1_SWITCH_FREQ_599K)) - goto init_fail; - } - - if (IS_ENABLED(CONFIG_TRICKLE_CHARGING)) - if (raw_write16(chgnum, ISL923X_REG_SYS_VOLTAGE_MIN, - precharge_voltage)) - goto init_fail; - - /* - * [10:9]: Prochot# Debounce time - * 11b: 1ms - */ - if (raw_read16(chgnum, ISL923X_REG_CONTROL2, ®)) - goto init_fail; - - if (!IS_ENABLED(CONFIG_CHARGER_RAA489000)) - reg |= ISL923X_C2_OTG_DEBOUNCE_150; - - if (IS_ENABLED(CONFIG_CHARGER_RAA489000)) - reg |= ISL923X_C2_PROCHOT_DEBOUNCE_500; - else - reg |= ISL923X_C2_PROCHOT_DEBOUNCE_1000; - - if (raw_write16(chgnum, ISL923X_REG_CONTROL2, - reg | - ISL923X_C2_ADAPTER_DEBOUNCE_150)) - goto init_fail; - - if (IS_ENABLED(CONFIG_CHARGE_RAMP_HW)) { - if (IS_ENABLED(CONFIG_CHARGER_ISL9237)) { - if (raw_read16(chgnum, ISL923X_REG_CONTROL0, ®)) - goto init_fail; - - /* - * Set input voltage regulation reference voltage for - * charge ramp. - */ - reg &= ~ISL9237_C0_VREG_REF_MASK; - reg |= ISL9237_C0_VREG_REF_4200; - - if (raw_write16(chgnum, ISL923X_REG_CONTROL0, reg)) - goto init_fail; - } else { - /* - * For the ISL9238, set the input voltage regulation to - * 4.439V. Note, the voltage is set in 341.3 mV steps. - * - * For the RAA489000, set the input voltage regulation - * to 4.437V. Note, that the voltage is set in 85.33 mV - * steps. - */ - if (IS_ENABLED(CONFIG_CHARGER_RAA489000)) - reg = (4437 / RAA489000_INPUT_VOLTAGE_REF_STEP) - << RAA489000_INPUT_VOLTAGE_REF_SHIFT; - else - reg = (4439 / ISL9238_INPUT_VOLTAGE_REF_STEP) - << ISL9238_INPUT_VOLTAGE_REF_SHIFT; - - if (raw_write16(chgnum, ISL9238_REG_INPUT_VOLTAGE, reg)) - goto init_fail; - } - } else { - if (raw_read16(chgnum, ISL923X_REG_CONTROL0, ®)) - goto init_fail; - - /* Disable voltage regulation loop to disable charge ramp */ - reg |= ISL923X_C0_DISABLE_VREG; - - if (raw_write16(chgnum, ISL923X_REG_CONTROL0, reg)) - goto init_fail; - } - - if (IS_ENABLED(CONFIG_CHARGER_ISL9238C)) { - /* b/155366741: enable slew rate control */ - if (raw_read16(chgnum, ISL9238C_REG_CONTROL6, ®)) - goto init_fail; - - reg |= ISL9238C_C6_SLEW_RATE_CONTROL; - - if (raw_write16(chgnum, ISL9238C_REG_CONTROL6, reg)) - goto init_fail; - } - - if (IS_ENABLED(CONFIG_CHARGER_RAA489000)) { - /* - * Return the BFET to normal operation as it may have been - * turned off when entering hibernate. - */ - if (raw_read16(chgnum, ISL923X_REG_CONTROL1, ®)) - goto init_fail; - reg &= ~RAA489000_C1_BGATE_FORCE_OFF; - if (raw_write16(chgnum, ISL923X_REG_CONTROL1, reg)) - goto init_fail; - } - - /* Revert all changes done by isl9238c_hibernate(). */ - if (IS_ENABLED(CONFIG_CHARGER_ISL9238C) && isl9238c_resume(chgnum)) - goto init_fail; - - if (IS_ENABLED(CHARGER_ISL9238X) || - IS_ENABLED(CONFIG_CHARGER_RAA489000)) { - /* - * Don't reread the prog pin and don't reload the ILIM on ACIN. - * For the RAA489000, just don't reload ACLIM. - */ - if (raw_read16(chgnum, ISL9238_REG_CONTROL3, ®)) - goto init_fail; - reg |= ISL9238_C3_NO_RELOAD_ACLIM_ON_ACIN; - if (!IS_ENABLED(CONFIG_CHARGER_RAA489000)) - reg |= ISL9238_C3_NO_REREAD_PROG_PIN; - - /* - * Disable autonomous charging initially since 1) it causes boot - * loop issues with 2S batteries, and 2) it will automatically - * get disabled as soon as we manually set the current limit - * anyway. - * - * Note: This bit is inverted on the RAA489000. - */ - if (IS_ENABLED(CONFIG_CHARGER_RAA489000)) - reg &= ~ISL9238_C3_DISABLE_AUTO_CHARING; - else - reg |= ISL9238_C3_DISABLE_AUTO_CHARING; - if (raw_write16(chgnum, ISL9238_REG_CONTROL3, reg)) - goto init_fail; - - /* - * No need to proceed with the rest of init if we sysjump'd to - * this image as the input current limit has already been set. - */ - if (system_jumped_late()) - return; - - /* - * Initialize the input current limit to the board's default. - */ - if (isl923x_set_input_current_limit( - chgnum, CONFIG_CHARGER_INPUT_CURRENT)) - goto init_fail; - } - -#ifdef CONFIG_OCPC - if (IS_ENABLED(CONFIG_CHARGER_RAA489000)) { - /* - * Ignore BATGONE on auxiliary charger ICs as it's not connected - * there. - * Clear DISABLE_GP_CMP & MCU_LDO_BAT_STATE_DISABLE to - * enable ALERT_B with control the power of sub-board - */ - if (chgnum != CHARGER_PRIMARY) { - if (raw_read16(chgnum, ISL9238_REG_CONTROL4, ®)) - goto init_fail; - - reg |= RAA489000_C4_BATGONE_DISABLE; - reg &= ~RAA489000_C4_DISABLE_GP_CMP; - - if (raw_write16(chgnum, ISL9238_REG_CONTROL4, reg)) - goto init_fail; - - if (raw_read16(chgnum, RAA489000_REG_CONTROL8, ®)) - goto init_fail; - - reg &= ~RAA489000_C8_MCU_LDO_BAT_STATE_DISABLE; - - if (raw_write16(chgnum, RAA489000_REG_CONTROL8, reg)) - goto init_fail; - } - } -#endif /* CONFIG_OCPC */ - - return; -init_fail: - CPRINTS("%s init failed!", CHARGER_NAME); -} - -static enum ec_error_list isl923x_discharge_on_ac(int chgnum, int enable) -{ - int rv; - int control1; - - mutex_lock(&control1_mutex); - - rv = raw_read16(chgnum, ISL923X_REG_CONTROL1, &control1); - if (rv) - goto out; - - control1 &= ~ISL923X_C1_LEARN_MODE_AUTOEXIT; - if (enable) - control1 |= ISL923X_C1_LEARN_MODE_ENABLE; - else - control1 &= ~ISL923X_C1_LEARN_MODE_ENABLE; - - rv = raw_write16(chgnum, ISL923X_REG_CONTROL1, control1); - - learn_mode = !rv && enable; - -out: - mutex_unlock(&control1_mutex); - return rv; -} - -#ifdef CONFIG_CHARGER_RAA489000 -enum ec_error_list raa489000_is_acok(int chgnum, bool *acok) -{ - int regval, rv; - - if ((chgnum < 0) || (chgnum > board_get_charger_chip_count())) { - CPRINTS("%s: Invalid chgnum! (%d)", __func__, chgnum); - return EC_ERROR_INVAL; - } - - rv = raw_read16(chgnum, ISL9238_REG_INFO2, ®val); - if (rv != EC_SUCCESS) - return rv; - *acok = (regval & RAA489000_INFO2_ACOK); - - return EC_SUCCESS; -} - -int raa489000_enable_asgate(int chgnum, bool enable) -{ - enum mask_update_action action = enable ? MASK_SET : MASK_CLR; - - return raw_update16(chgnum, RAA489000_REG_CONTROL8, - RAA489000_C8_ASGATE_ON_READY, action); -} - -void raa489000_hibernate(int chgnum, bool disable_adc) -{ - int rv, regval; - - if ((chgnum < 0) || (chgnum > board_get_charger_chip_count())) { - CPRINTS("%s: Invalid chgnum! (%d)", __func__, chgnum); - return; - } - - rv = raw_read16(chgnum, ISL923X_REG_CONTROL0, ®val); - if (!rv) { - /* set BGATE to normal operation */ - regval &= ~RAA489000_C0_BGATE_FORCE_ON; - - /* set normal charge pump operation */ - regval &= ~RAA489000_C0_EN_CHG_PUMPS_TO_100PCT; - - rv = raw_write16(chgnum, ISL923X_REG_CONTROL0, regval); - } - if (rv) - CPRINTS("%s(%d): Failed to set Control0!", __func__, chgnum); - - rv = raw_read16(chgnum, ISL923X_REG_CONTROL1, ®val); - if (!rv) { - /* Disable Supplemental support */ - regval &= ~RAA489000_C1_ENABLE_SUPP_SUPPORT_MODE; - - /* - * Force BGATE off. For devices that utilize the Z-state, the - * LDO will be powered through the BFET's body diode. - */ - regval |= RAA489000_C1_BGATE_FORCE_OFF; - - /* Disable AMON/BMON */ - regval |= ISL923X_C1_DISABLE_MON; - - /* Disable PSYS */ - regval &= ~ISL923X_C1_ENABLE_PSYS; - - rv = raw_write16(chgnum, ISL923X_REG_CONTROL1, regval); - } - if (rv) - CPRINTS("%s(%d): Failed to set Control1!", __func__, chgnum); - - rv = raw_read16(chgnum, ISL9238_REG_CONTROL3, ®val); - if (!rv) { - if (disable_adc) - /* ADC is active only when adapter plugged in */ - regval &= ~RAA489000_ENABLE_ADC; - else - regval |= RAA489000_ENABLE_ADC; - - rv = raw_write16(chgnum, ISL9238_REG_CONTROL3, regval); - } - if (rv) - CPRINTS("%s(%d): Failed to set Control3!", __func__, chgnum); - - rv = raw_read16(chgnum, ISL9238_REG_CONTROL4, ®val); - if (!rv) { - /* Disable GP comparator for battery only mode */ - regval |= RAA489000_C4_DISABLE_GP_CMP; - - rv = raw_write16(chgnum, ISL9238_REG_CONTROL4, regval); - } - if (rv) - CPRINTS("%s(%d):Failed to set Control4!", __func__, chgnum); - -#ifdef CONFIG_OCPC - /* The LDO is needed in the Z-state on the primary charger */ - if (chgnum != CHARGER_PRIMARY) { - rv = raw_read16(chgnum, RAA489000_REG_CONTROL8, ®val); - if (!rv) { - /* Disable MCU LDO in battery state */ - regval |= RAA489000_C8_MCU_LDO_BAT_STATE_DISABLE; - - rv = raw_write16(chgnum, RAA489000_REG_CONTROL8, - regval); - } - if (rv) - CPRINTS("%s(%d):Failed to set Control8!", __func__, - chgnum); - } - - /* Disable DVC on the main charger to reduce power consumption. */ - if (chgnum == CHARGER_PRIMARY) { - rv = raw_write16(chgnum, RAA489000_REG_CONTROL10, 0); - if (rv) - CPRINTS("%s(%d):Failed to set Control10!", __func__, - chgnum); - } -#endif - - cflush(); -} -#endif /* CONFIG_CHARGER_RAA489000 */ - -#ifdef CONFIG_CHARGER_ISL9238C -enum ec_error_list isl9238c_hibernate(int chgnum) -{ - /* Disable IMON */ - RETURN_ERROR(raw_update16(chgnum, ISL923X_REG_CONTROL1, - ISL923X_C1_DISABLE_MON, MASK_SET)); - - /* Disable PSYS */ - RETURN_ERROR(raw_update16(chgnum, ISL923X_REG_CONTROL1, - ISL923X_C1_ENABLE_PSYS, MASK_CLR)); - - /* Disable GP comparator */ - RETURN_ERROR(raw_update16(chgnum, ISL923X_REG_CONTROL2, - ISL923X_C2_COMPARATOR, MASK_SET)); - - /* Force BGATE off */ - RETURN_ERROR(raw_update16(chgnum, ISL9238_REG_CONTROL3, - ISL9238_C3_BGATE_OFF, MASK_SET)); - - - return EC_SUCCESS; -} - -enum ec_error_list isl9238c_resume(int chgnum) -{ - /* Revert everything in isl9238c_hibernate() */ - RETURN_ERROR(raw_update16(chgnum, ISL923X_REG_CONTROL1, - ISL923X_C1_DISABLE_MON, MASK_CLR)); - - RETURN_ERROR(raw_update16(chgnum, ISL923X_REG_CONTROL1, - ISL923X_C1_ENABLE_PSYS, MASK_SET)); - - RETURN_ERROR(raw_update16(chgnum, ISL923X_REG_CONTROL2, - ISL923X_C2_COMPARATOR, MASK_CLR)); - - RETURN_ERROR(raw_update16(chgnum, ISL9238_REG_CONTROL3, - ISL9238_C3_BGATE_OFF, MASK_CLR)); - - return EC_SUCCESS; -} -#endif /* CONFIG_CHARGER_ISL9238C */ - - -/*****************************************************************************/ -/* Hardware current ramping */ - -#ifdef CONFIG_CHARGE_RAMP_HW -static enum ec_error_list isl923x_set_hw_ramp(int chgnum, int enable) -{ - int rv, reg; - - rv = raw_read16(chgnum, ISL923X_REG_CONTROL0, ®); - if (rv) - return rv; - - /* HW ramp is controlled by input voltage regulation reference bits */ - if (enable) - reg &= ~ISL923X_C0_DISABLE_VREG; - else - reg |= ISL923X_C0_DISABLE_VREG; - - return raw_write16(chgnum, ISL923X_REG_CONTROL0, reg); -} - -static int isl923x_ramp_is_stable(int chgnum) -{ - /* - * Since ISL cannot read the current limit that the ramp has settled - * on, then we can never consider the ramp stable, because we never - * know what the stable limit is. - */ - return 0; -} - -static int isl923x_ramp_is_detected(int chgnum) -{ - return 1; -} - -static int isl923x_ramp_get_current_limit(int chgnum) -{ - /* - * ISL doesn't have a way to get this info, so return the nominal - * current limit as an estimate. - */ - int input_current; - - if (isl923x_get_input_current_limit(chgnum, &input_current)) - return 0; - return input_current; -} -#endif /* CONFIG_CHARGE_RAMP_HW */ - - -#ifdef CONFIG_CHARGER_PSYS -static int psys_enabled; -/* - * TODO(b/147440290): Set to appropriate charger with multiple charger support, - * hardcode to 0 for now - */ -static void charger_enable_psys(void) -{ - int val; - - mutex_lock(&control1_mutex); - - /* - * enable system power monitor PSYS function - */ - if (raw_read16(CHARGER_SOLO, ISL923X_REG_CONTROL1, &val)) - goto out; - - val |= ISL923X_C1_ENABLE_PSYS; - - if (raw_write16(CHARGER_SOLO, ISL923X_REG_CONTROL1, val)) - goto out; - - psys_enabled = 1; - -out: - mutex_unlock(&control1_mutex); -} -DECLARE_HOOK(HOOK_CHIPSET_RESUME, charger_enable_psys, HOOK_PRIO_DEFAULT); - -static void charger_disable_psys(void) -{ - int val; - - mutex_lock(&control1_mutex); - - /* - * disable system power monitor PSYS function - */ - if (raw_read16(CHARGER_SOLO, ISL923X_REG_CONTROL1, &val)) - goto out; - - val &= ~ISL923X_C1_ENABLE_PSYS; - - if (raw_write16(CHARGER_SOLO, ISL923X_REG_CONTROL1, val)) - goto out; - - psys_enabled = 0; - -out: - mutex_unlock(&control1_mutex); -} -DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, charger_disable_psys, HOOK_PRIO_DEFAULT); - -#ifdef CONFIG_CHARGER_PSYS_READ -int charger_get_system_power(void) -{ - int adc; - - /* - * If PSYS is not enabled, AP is probably off, and the value is usually - * too small to be measured acurately anyway. - */ - if (!psys_enabled) - return -1; - - /* - * We assume that the output gain is always left to the default - * 1.44 uA/W, and that the ADC scaling values are setup accordingly in - * board file, so that the value is indicated in uW. - */ - adc = adc_read_channel(ADC_PSYS); - - return adc; -} - -static int console_command_psys(int argc, char **argv) -{ - ccprintf("PSYS = %d uW\n", charger_get_system_power()); - return 0; -} -DECLARE_CONSOLE_COMMAND(psys, console_command_psys, - NULL, - "Get the system power in mW"); -#endif /* CONFIG_CHARGER_PSYS_READ */ -#endif /* CONFIG_CHARGER_PSYS */ - -#ifdef CONFIG_CMD_CHARGER_ADC_AMON_BMON -static int print_amon_bmon(int chgnum, enum isl923x_amon_bmon amon, - enum isl923x_mon_dir direction, int resistor) -{ - int ret, adc, curr; - - ret = get_amon_bmon(chgnum, amon, direction, &adc); - if (ret) - return ret; - - curr = adc / resistor; - ccprintf("%cMON(%sharging): %d uV, %d mA\n", amon == AMON ? 'A' : 'B', - direction == MON_DISCHARGE ? "Disc" : "C", adc, curr); - - return ret; -} - -/** - * Get charger AMON and BMON current. - */ -static int console_command_amon_bmon(int argc, char **argv) -{ - int ret = EC_SUCCESS; - int print_ac = 1; - int print_battery = 1; - int print_charge = 1; - int print_discharge = 1; - int chgnum = 0; - char *e; - - if (argc >= 2) { - print_ac = (argv[1][0] == 'a'); - print_battery = (argv[1][0] == 'b'); - if (IS_ENABLED(CHARGER_ISL9238X) && argv[1][1] != '\0') { - print_charge = (argv[1][1] == 'c'); - print_discharge = (argv[1][1] == 'd'); - } - if (argc >= 3) { - chgnum = strtoi(argv[2], &e, 10); - if (*e) - return EC_ERROR_PARAM2; - } - } - - if (print_ac) { - if (print_charge) - ret |= print_amon_bmon(chgnum, AMON, MON_CHARGE, - CONFIG_CHARGER_SENSE_RESISTOR_AC); - if (IS_ENABLED(CHARGER_ISL9238X) && print_discharge) - ret |= print_amon_bmon(chgnum, AMON, MON_DISCHARGE, - CONFIG_CHARGER_SENSE_RESISTOR_AC); - } - - if (print_battery) { - if (IS_ENABLED(CHARGER_ISL9238X) && print_charge) - ret |= print_amon_bmon(chgnum, BMON, MON_CHARGE, - /* - * charging current monitor has - * 2x amplification factor - */ - 2 * CONFIG_CHARGER_SENSE_RESISTOR); - if (print_discharge) - ret |= print_amon_bmon(chgnum, BMON, MON_DISCHARGE, - CONFIG_CHARGER_SENSE_RESISTOR); - } - - return ret; -} -DECLARE_CONSOLE_COMMAND(amonbmon, console_command_amon_bmon, -#ifdef CONFIG_CHARGER_ISL9237 - "amonbmon [a|b] <chgnum>", -#else - "amonbmon [a[c|d]|b[c|d]] <chgnum>", -#endif - "Get charger AMON/BMON voltage diff, current"); -#endif /* CONFIG_CMD_CHARGER_ADC_AMON_BMON */ - -#ifdef CONFIG_CMD_CHARGER_DUMP -static void dump_reg_range(int chgnum, int low, int high) -{ - int reg; - int regval; - int rv; - - for (reg = low; reg <= high; reg++) { - CPRINTF("[%Xh] = ", reg); - rv = i2c_read16(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - reg, ®val); - if (!rv) - CPRINTF("0x%04x\n", regval); - else - CPRINTF("ERR (%d)\n", rv); - cflush(); - } -} - -static int command_isl923x_dump(int argc, char **argv) -{ - int chgnum = 0; - char *e; - - if (argc >= 2) { - chgnum = strtoi(argv[1], &e, 10); - if (*e) - return EC_ERROR_PARAM1; - } - - dump_reg_range(chgnum, 0x14, 0x15); - if (IS_ENABLED(CONFIG_CHARGER_ISL9238C)) - dump_reg_range(chgnum, 0x37, 0x37); - dump_reg_range(chgnum, 0x38, 0x3F); - dump_reg_range(chgnum, 0x47, 0x4A); - if (IS_ENABLED(CHARGER_ISL9238X) || - IS_ENABLED(CONFIG_CHARGER_RAA489000)) - dump_reg_range(chgnum, 0x4B, 0x4E); - dump_reg_range(chgnum, 0xFE, 0xFF); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(charger_dump, command_isl923x_dump, - "charger_dump <chgnum>", "Dumps ISL923x registers"); -#endif /* CONFIG_CMD_CHARGER_DUMP */ - -static enum ec_error_list isl923x_get_vbus_voltage(int chgnum, int port, - int *voltage) -{ - int val; - int rv; - - rv = raw_read16(chgnum, RAA489000_REG_ADC_VBUS, &val); - if (rv) - return rv; - - /* The VBUS voltage is returned in bits 13:6. The LSB is 96mV. */ - val &= GENMASK(13, 6); - val = val >> 6; - val *= 96; - *voltage = val; - - return EC_SUCCESS; -} - -#if defined(CONFIG_CHARGER_RAA489000) && defined(CONFIG_OCPC) -static enum ec_error_list raa489000_enable_linear_charge(int chgnum, - bool enable) -{ - const struct battery_info *batt_info; - int trickle_regval; - int precharge_current; - int regval; - enum ec_error_list rv; - int act_chg = charge_get_active_chg_chip(); - - batt_info = battery_get_info(); - - if (enable) { - /* Set the auxiliary max VSYS to 300mV + min VSYS. */ - rv = isl9237_set_voltage(act_chg, batt_info->voltage_min + 300); - - /* Disable charge current loop for the aux charger. */ - rv |= raw_update16(act_chg, RAA489000_REG_CONTROL10, - RAA489000_C10_DISABLE_DVC_CC_LOOP, - MASK_SET); - - /* - * Set primary charger charge current to the desired precharge - * current. - */ - rv |= isl9237_set_current(CHARGER_PRIMARY, - batt_info->precharge_current); - - /* - * Set primary charger max VSYS to the max of the battery. - */ - rv |= isl9237_set_voltage(CHARGER_PRIMARY, - batt_info->voltage_max); - - /* - * Set trickle charging level. - * - * 64mA is the minimum current level we must set. - */ - precharge_current = MAX(64, batt_info->precharge_current); - trickle_regval = precharge_current / 32; - trickle_regval--; /* convert to 0-based field */ - rv |= raw_read16(CHARGER_PRIMARY, ISL923X_REG_CONTROL2, - ®val); - regval &= ~(GENMASK(15, 13)); - regval |= trickle_regval << 13; - rv |= raw_write16(CHARGER_PRIMARY, ISL923X_REG_CONTROL2, - regval); - - /* Enable DVC trickle charge and DVC charge mode. */ - rv |= raw_update16(CHARGER_PRIMARY, RAA489000_REG_CONTROL10, - RAA489000_C10_ENABLE_DVC_MODE | - RAA489000_C10_ENABLE_DVC_TRICKLE_CHARGE, - MASK_SET); - - if (rv) - return EC_ERROR_UNKNOWN; - - } else { - /* Disable DVC trickle charge. */ - rv = raw_update16(CHARGER_PRIMARY, RAA489000_REG_CONTROL10, - RAA489000_C10_ENABLE_DVC_TRICKLE_CHARGE, - MASK_CLR); - } - - return rv; -} - -static enum ec_error_list raa489000_set_vsys_compensation(int chgnum, - struct ocpc_data *o, - int current_ma, - int voltage_mv) -{ - int device_id = 0; - int rv; - int rp1; - int rp2; - int regval; - - /* This should never be called against the primary charger. */ - ASSERT(chgnum != CHARGER_PRIMARY); - - /* Only B0+ silicon supports VSYS compensation. */ - rv = isl923x_device_id(chgnum, &device_id); - if (rv) - return EC_ERROR_UNKNOWN; - - /* - * Note: this makes the assumption that this charger IC is used on the - * primary port as well. - */ - - if (device_id < RAA489000_DEV_ID_B0) - return EC_ERROR_UNIMPLEMENTED; - - /* - * Need to set board resistance values: Rp1 and Rp2. These are expected - * to be fairly constant once we are able to calculate their values. - * - * Rp1 is the total resistance from the right-hand side of the - * auxiliary sense resistor to the actual VSYS node. It should include: - * a. resistance of sub board sense resistor - * b. connector/cable resistance - * c. sub board PCB resistance to the actual VSYS node - * - * Rp2 is the total resistance from the actual VSYS node to the battery. - * It should include: - * a. resistance of primary charger sense resistor (battery side) - * b. Rds(on) of BGATE FET - * c. main board PCB resistance to the battery - * d. battery internal resistance - */ - - /* - * Rp1 is set between 36-156mOhms in 4mOhm increments. This must be - * non-zero in order for compensation to work. - * - * To get Rp1, we need to look at the delta between VSYS measured by the - * auxiliary charger IC and the primary charger IC where the actual VSYS - * node is as well as the current provided by the auxiliary charger IC. - * The system keeps track of combined resistance; therefore, Rp2 is the - * difference between the combined resistance and Rp1 that we calculate. - * If Rp1 is less than 36mOhms, then the compensation is disabled. - */ - - rp1 = MIN(o->rsys_mo, RAA489000_RP1_MAX); - rp1 -= RAA489000_RP1_MIN; - if (rp1 < 0) { - if (o->last_vsys == OCPC_UNINIT) - CPRINTS("RAA489000(%d): Disabling DVC (Rp1 < 36mOhms)", - chgnum); - rp1 = 0; - } else { - rp1 /= 4; - rp1++; /* Rp1 min starts at register value 1 */ - } - - /* Rp2 is set between 0-124mOhms in 4mOhm increments. */ - rp2 = o->rbatt_mo; - rp2 = CLAMP(rp2, RAA489000_RP2_MIN, RAA489000_RP2_MAX); - rp2 /= 4; - - rv |= raw_read16(chgnum, RAA489000_REG_CONTROL10, ®val); - if (!rv) { - /* Set Rp1 and Rp2 */ - regval &= ~RAA489000_C10_RP1_MASK; - regval &= ~RAA489000_C10_RP2_MASK; - regval |= rp2; - regval |= (rp1 << RAA489000_C10_RP1_SHIFT); - - /* Enable DVC mode */ - regval |= RAA489000_C10_ENABLE_DVC_MODE; - - /* Disable charge current loop */ - regval |= RAA489000_C10_DISABLE_DVC_CC_LOOP; - - rv |= raw_write16(chgnum, RAA489000_REG_CONTROL10, regval); - } - - if (rv) { - CPRINTS("%s(%d) Failed to enable DVC!", __func__, chgnum); - return EC_ERROR_UNKNOWN; - } - - /* Lastly, enable DVC fast charge mode for the primary charger IC. */ - rv = raw_read16(CHARGER_PRIMARY, RAA489000_REG_CONTROL10, ®val); - regval |= RAA489000_C10_ENABLE_DVC_CHARGE_MODE; - rv |= raw_write16(CHARGER_PRIMARY, RAA489000_REG_CONTROL10, regval); - if (rv) { - CPRINTS("%s Failed to enable DVC on primary charger!", - __func__); - return EC_ERROR_UNKNOWN; - } - - /* - * We'll need to use the PID loop in order to properly set VSYS such - * such that we get the desired charge current. - */ - return EC_ERROR_UNIMPLEMENTED; -} -#endif /* CONFIG_CHARGER_RAA489000 && CONFIG_OCPC */ - -const struct charger_drv isl923x_drv = { - .init = &isl923x_init, - .post_init = &isl923x_post_init, - .get_info = &isl923x_get_info, - .get_status = &isl923x_get_status, - .set_mode = &isl923x_set_mode, -#if defined(CONFIG_CHARGER_OTG) && defined(CHARGER_ISL9238X) - .enable_otg_power = &isl923x_enable_otg_power, - .set_otg_current_voltage = &isl923x_set_otg_current_voltage, -#endif -#ifdef CONFIG_CHARGER_RAA489000 - .get_actual_current = &raa489000_get_actual_current, -#endif - .get_current = &isl923x_get_current, - .set_current = &isl923x_set_current, -#ifdef CONFIG_CHARGER_RAA489000 - .get_actual_voltage = &raa489000_get_actual_voltage, -#endif - .get_voltage = &isl923x_get_voltage, - .set_voltage = &isl923x_set_voltage, - .discharge_on_ac = &isl923x_discharge_on_ac, - .get_vbus_voltage = &isl923x_get_vbus_voltage, - .set_input_current_limit = &isl923x_set_input_current_limit, - .get_input_current_limit = &isl923x_get_input_current_limit, -#ifdef CONFIG_CHARGER_RAA489000 - .get_input_current = &raa489000_get_input_current, -#elif defined(CONFIG_CMD_CHARGER_ADC_AMON_BMON) - .get_input_current = &isl923x_get_input_current, -#endif - .manufacturer_id = &isl923x_manufacturer_id, - .device_id = &isl923x_device_id, - .get_option = &isl923x_get_option, - .set_option = &isl923x_set_option, -#ifdef CONFIG_CHARGE_RAMP_HW - .set_hw_ramp = &isl923x_set_hw_ramp, - .ramp_is_stable = &isl923x_ramp_is_stable, - .ramp_is_detected = &isl923x_ramp_is_detected, - .ramp_get_current_limit = &isl923x_ramp_get_current_limit, -#endif -#if defined(CONFIG_CHARGER_RAA489000) && defined(CONFIG_OCPC) - .enable_linear_charge = &raa489000_enable_linear_charge, - .set_vsys_compensation = &raa489000_set_vsys_compensation, -#endif -}; diff --git a/driver/charger/isl923x.h b/driver/charger/isl923x.h deleted file mode 100644 index 558c17f971..0000000000 --- a/driver/charger/isl923x.h +++ /dev/null @@ -1,352 +0,0 @@ -/* Copyright 2015 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. - * - * Intersil ISL-9237/8 battery charger driver. - * Also supports Renesas RAA489000 battery charger. - */ - -#ifndef __CROS_EC_ISL923X_H -#define __CROS_EC_ISL923X_H - -#include "driver/charger/isl923x_public.h" - -/* Registers */ -#define ISL923X_REG_CHG_CURRENT 0x14 -#define ISL923X_REG_ADAPTER_CURRENT_LIMIT1 0x3f -#define ISL923X_REG_ADAPTER_CURRENT_LIMIT2 0x3b -#define ISL923X_REG_SYS_VOLTAGE_MAX 0x15 -#define ISL923X_REG_SYS_VOLTAGE_MIN 0x3e -#define ISL923X_REG_PROCHOT_AC 0x47 -#define ISL923X_REG_PROCHOT_DC 0x48 -#define ISL923X_REG_T1_T2 0x38 -#define ISL923X_REG_CONTROL0 0x39 -#define ISL923X_REG_CONTROL1 0x3c -#define ISL923X_REG_CONTROL2 0x3d -#define ISL9238_REG_CONTROL3 0x4c -#define ISL9238_REG_CONTROL4 0x4e -#define ISL9238C_REG_CONTROL6 0x37 -#define ISL923X_REG_INFO 0x3a -#define ISL9238_REG_INFO2 0x4d -#define ISL923X_REG_OTG_VOLTAGE 0x49 -#define ISL923X_REG_OTG_CURRENT 0x4a -#define ISL9238_REG_INPUT_VOLTAGE 0x4b -#define ISL923X_REG_MANUFACTURER_ID 0xfe -#define ISL923X_REG_DEVICE_ID 0xff -#define RAA489000_REG_CONTROL8 0x37 -#define RAA489000_REG_CONTROL10 0x35 - -/* Sense resistor default values in mOhm */ -#define ISL923X_DEFAULT_SENSE_RESISTOR_AC 20 -#define ISL923X_DEFAULT_SENSE_RESISTOR 10 - -/* Maximum charging current register value */ -#define ISL923X_CURRENT_REG_MAX 0x17c0 /* bit<12:2> 10111110000 */ -#define RAA489000_CURRENT_REG_MAX 0x1ffc - -/* 2-level adpater current limit duration T1 & T2 in micro seconds */ -#define ISL923X_T1_10000 0x00 -#define ISL923X_T1_20000 0x01 -#define ISL923X_T1_15000 0x02 -#define ISL923X_T1_5000 0x03 -#define ISL923X_T1_1000 0x04 -#define ISL923X_T1_500 0x05 -#define ISL923X_T1_100 0x06 -#define ISL923X_T1_0 0x07 -#define ISL923X_T2_10 (0x00 << 8) -#define ISL923X_T2_100 (0x01 << 8) -#define ISL923X_T2_500 (0x02 << 8) -#define ISL923X_T2_1000 (0x03 << 8) -#define ISL923X_T2_300 (0x04 << 8) -#define ISL923X_T2_750 (0x05 << 8) -#define ISL923X_T2_2000 (0x06 << 8) -#define ISL923X_T2_10000 (0x07 << 8) - -#define ISL9237_SYS_VOLTAGE_REG_MAX 13824 -#define ISL9238_SYS_VOLTAGE_REG_MAX 18304 -#define ISL923X_SYS_VOLTAGE_REG_MIN 2048 -#define RAA489000_SYS_VOLTAGE_REG_MAX 18304 -#define RAA489000_SYS_VOLTAGE_REG_MIN 64 - -/* PROCHOT# debounce time and duration time in micro seconds */ -#define ISL923X_PROCHOT_DURATION_10000 (0 << 6) -#define ISL923X_PROCHOT_DURATION_20000 BIT(6) -#define ISL923X_PROCHOT_DURATION_15000 (2 << 6) -#define ISL923X_PROCHOT_DURATION_5000 (3 << 6) -#define ISL923X_PROCHOT_DURATION_1000 (4 << 6) -#define ISL923X_PROCHOT_DURATION_500 (5 << 6) -#define ISL923X_PROCHOT_DURATION_100000 (6 << 6) -#define ISL923X_PROCHOT_DURATION_0 (7 << 6) -#define ISL923X_PROCHOT_DURATION_MASK (7 << 6) - -#define ISL923X_PROCHOT_DEBOUNCE_10 (0 << 9) -#define ISL923X_PROCHOT_DEBOUNCE_100 BIT(9) -#define ISL923X_PROCHOT_DEBOUNCE_500 (2 << 9) -#define ISL923X_PROCHOT_DEBOUNCE_1000 (3 << 9) -#define ISL923X_PROCHOT_DEBOUNCE_MASK (3 << 9) - -/* Maximum PROCHOT register value */ -#define ISL923X_PROCHOT_AC_REG_MAX 6400 -#define ISL923X_PROCHOT_DC_REG_MAX 12800 - -/* Control0: adapter voltage regulation reference */ -#define ISL9237_C0_VREG_REF_3900 0 -#define ISL9237_C0_VREG_REF_4200 1 -#define ISL9237_C0_VREG_REF_4500 2 -#define ISL9237_C0_VREG_REF_4800 3 -#define ISL9237_C0_VREG_REF_MASK 0x03 - -/* Control0: disable adapter voltaqe regulation */ -#define ISL923X_C0_DISABLE_VREG BIT(2) - -/* Control0: battery DCHOT reference for RS2 == 20mOhm */ -#define ISL923X_C0_DCHOT_6A (0 << 3) -#define ISL923X_C0_DCHOT_5A BIT(3) -#define ISL923X_C0_DCHOT_4A (2 << 3) -#define ISL923X_C0_DCHOT_3A (3 << 3) -#define ISL923X_C0_DCHOT_MASK (3 << 3) - -/* Control0: BGATE force on */ -#define RAA489000_C0_BGATE_FORCE_ON BIT(10) -#define RAA489000_C0_EN_CHG_PUMPS_TO_100PCT BIT(6) - -/* Control1: general purpose comparator debounce time in micro second */ -#define ISL923X_C1_GP_DEBOUNCE_2 (0 << 14) -#define ISL923X_C1_GP_DEBOUNCE_12 BIT(14) -#define ISL923X_C1_GP_DEBOUNCE_2000 (2 << 14) -#define ISL923X_C1_GP_DEBOUNCE_5000000 (3 << 14) -#define ISL923X_C1_GP_DEBOUNCE_MASK (3 << 14) - -/* Control1: learn mode */ -#define ISL923X_C1_LEARN_MODE_AUTOEXIT BIT(13) -#define ISL923X_C1_LEARN_MODE_ENABLE BIT(12) - -/* Control1: OTG enable */ -#define ISL923X_C1_OTG BIT(11) - -/* Control1: audio filter */ -#define ISL923X_C1_AUDIO_FILTER BIT(10) - -/* Control1: switch frequency, ISL9238 defines bit 7 as unused */ -#define ISL923X_C1_SWITCH_FREQ_PROG (0 << 7) /* 1000kHz or PROG */ -#define ISL9237_C1_SWITCH_FREQ_913K BIT(7) -#define ISL923X_C1_SWITCH_FREQ_839K (2 << 7) -#define ISL9237_C1_SWITCH_FREQ_777K (3 << 7) -#define ISL923X_C1_SWITCH_FREQ_723K (4 << 7) -#define ISL9237_C1_SWITCH_FREQ_676K (5 << 7) -#define ISL923X_C1_SWITCH_FREQ_635K (6 << 7) -#define ISL9237_C1_SWITCH_FREQ_599K (7 << 7) -#define ISL923X_C1_SWITCH_FREQ_MASK (7 << 7) - -/* Control1: turbo mode */ -#define ISL923X_C1_TURBO_MODE BIT(6) - -/* Control1: AMON & BMON */ -#define ISL923X_C1_DISABLE_MON BIT(5) -#define ISL923X_C1_SELECT_BMON BIT(4) - -/* Control1: PSYS, VSYS, VSYSLO */ -#define ISL923X_C1_ENABLE_PSYS BIT(3) -#define ISL923X_C1_ENABLE_VSYS BIT(2) -#define ISL923X_C1_VSYSLO_REF_6000 0 -#define ISL923X_C1_VSYSLO_REF_6300 1 -#define ISL923X_C1_VSYSLO_REF_6600 2 -#define ISL923X_C1_VSYSLO_REF_6900 3 -#define ISL923X_C1_VSYSLO_REF_MASK 3 - -/* Control1: Supplemental mode support */ -#define RAA489000_C1_ENABLE_SUPP_SUPPORT_MODE BIT(10) - -/* Control1: BGATE Force Off */ -#define RAA489000_C1_BGATE_FORCE_OFF BIT(6) - -/* Control2: trickle charging current in mA */ -#define ISL923X_C2_TRICKLE_256 (0 << 14) -#define ISL923X_C2_TRICKLE_128 BIT(14) -#define ISL923X_C2_TRICKLE_64 (2 << 14) -#define ISL923X_C2_TRICKLE_512 (3 << 14) -#define ISL923X_C2_TRICKLE_MASK (3 << 14) - -/* Control2: OTGEN debounce time in ms */ -#define ISL923X_C2_OTG_DEBOUNCE_1300 (0 << 13) -#define ISL923X_C2_OTG_DEBOUNCE_150 BIT(13) -#define ISL923X_C2_OTG_DEBOUNCE_MASK BIT(13) - -/* Control2: 2-level adapter over current */ -#define ISL923X_C2_2LVL_OVERCURRENT BIT(12) - -/* Control2: adapter insertion debounce time in ms */ -#define ISL923X_C2_ADAPTER_DEBOUNCE_1300 (0 << 11) -#define ISL923X_C2_ADAPTER_DEBOUNCE_150 BIT(11) -#define ISL923X_C2_ADAPTER_DEBOUNCE_MASK BIT(11) - -/* Control2: PROCHOT debounce time in uS */ -#define ISL9238_C2_PROCHOT_DEBOUNCE_7 (0 << 9) -#define ISL9237_C2_PROCHOT_DEBOUNCE_10 (0 << 9) -#define ISL923X_C2_PROCHOT_DEBOUNCE_100 BIT(9) -#define ISL923X_C2_PROCHOT_DEBOUNCE_500 (2 << 9) -#define ISL923X_C2_PROCHOT_DEBOUNCE_1000 (3 << 9) -#define ISL923X_C2_PROCHOT_DEBOUNCE_MASK (3 << 9) - -/* Control2: min PROCHOT duration in uS */ -#define ISL923X_C2_PROCHOT_DURATION_10000 (0 << 6) -#define ISL923X_C2_PROCHOT_DURATION_20000 BIT(6) -#define ISL923X_C2_PROCHOT_DURATION_15000 (2 << 6) -#define ISL923X_C2_PROCHOT_DURATION_5000 (3 << 6) -#define ISL923X_C2_PROCHOT_DURATION_1000 (4 << 6) -#define ISL923X_C2_PROCHOT_DURATION_500 (5 << 6) -#define ISL923X_C2_PROCHOT_DURATION_100 (6 << 6) -#define ISL923X_C2_PROCHOT_DURATION_0 (7 << 6) -#define ISL923X_C2_PROCHOT_DURATION_MASK (7 << 6) - -/* Control2: turn off ASGATE in OTG mode */ -#define ISL923X_C2_ASGATE_OFF BIT(5) - -/* Control2: CMIN, general purpose comparator reference in mV */ -#define ISL923X_C2_CMIN_2000 (0 << 4) -#define ISL923X_C2_CMIN_1200 BIT(4) - -/* Control2: general purpose comparator enable */ -#define ISL923X_C2_COMPARATOR BIT(3) - -/* Control2: invert CMOUT, general purpose comparator output, polarity */ -#define ISL923X_C2_INVERT_CMOUT BIT(2) - -/* Control2: disable WOC, way over current */ -#define ISL923X_C2_WOC_OFF BIT(1) - -/* Control2: PSYS gain in uA/W (ISL9237 only) */ -#define ISL9237_C2_PSYS_GAIN BIT(0) - -/* Control3: Enable ADC for all modes */ -#define RAA489000_ENABLE_ADC BIT(0) - -/* - * Control3: Buck-Boost switching period - * 0: x1 frequency, 1: half frequency. - */ -#define ISL9238_C3_BB_SWITCHING_PERIOD BIT(1) - -/* - * Control3: AMON/BMON direction. - * 0: adapter/charging, 1:OTG/discharging (ISL9238 only) - */ -#define ISL9238_C3_AMON_BMON_DIRECTION BIT(3) - -/* - * Control3: Disables Autonomous Charing - * - * Note: This is disabled automatically when ever we set the current limit - * manually (which we always do). - */ -#define ISL9238_C3_DISABLE_AUTO_CHARING BIT(7) - -/* Control3: PSYS gain in uA/W (ISL9238 only) */ -#define ISL9238_C3_PSYS_GAIN BIT(9) - -/* Control3: Enables or disables Battery Ship mode */ -#define ISL9238_C3_BGATE_OFF BIT(10) - -/* Control3: Enable or disable DCM/CCM Hysteresis */ -#define RAA489000_C3_DCM_CCM_HYSTERESIS_ENABLE BIT(10) - -/* Control3: Don't reload ACLIM on ACIN. */ -#define ISL9238_C3_NO_RELOAD_ACLIM_ON_ACIN BIT(14) - -/* Control3: Don't reread PROG pin. */ -#define ISL9238_C3_NO_REREAD_PROG_PIN BIT(15) - -/* Control4: PSYS Rsense ratio. */ -#define RAA489000_C4_PSYS_RSNS_RATIO_1_TO_1 BIT(11) - -/* Control4: GP comparator control bit */ -#define RAA489000_C4_DISABLE_GP_CMP BIT(12) - -/* Control4: Ignores BATGONE input */ -#define RAA489000_C4_BATGONE_DISABLE BIT(15) - -/* Control6: charger current and maximum system voltage slew rate control. */ -#define ISL9238C_C6_SLEW_RATE_CONTROL BIT(6) - -/* Control8: MCU_LDO - BAT state disable */ -#define RAA489000_C8_MCU_LDO_BAT_STATE_DISABLE BIT(14) -#define RAA489000_C8_ASGATE_ON_READY BIT(13) - -/* OTG voltage limit in mV, current limit in mA */ -#define ISL9237_OTG_VOLTAGE_MIN 4864 -#define ISL9237_OTG_VOLTAGE_MAX 5376 -#define ISL9238_OTG_VOLTAGE_MAX 27456 -#define ISL923X_OTG_CURRENT_MAX 4096 - -#define ISL9238_OTG_VOLTAGE_STEP 12 -#define ISL9238_OTG_VOLTAGE_SHIFT 3 -#define ISL923X_OTG_CURRENT_STEP 128 -#define ISL923X_OTG_CURRENT_SHIFT 7 - -/* Input voltage regulation voltage reference */ -#define ISL9238_INPUT_VOLTAGE_REF_STEP 341 -#define ISL9238_INPUT_VOLTAGE_REF_SHIFT 8 -#define RAA489000_INPUT_VOLTAGE_REF_STEP 85 -#define RAA489000_INPUT_VOLTAGE_REF_SHIFT 6 - -/* Info register fields */ -#define ISL9237_INFO_PROG_RESISTOR_MASK 0xf -#define ISL923X_INFO_TRICKLE_ACTIVE_MASK BIT(4) -#define ISL9237_INFO_PSTATE_SHIFT 5 -#define ISL9237_INFO_PSTATE_MASK 3 -#define RAA489000_INFO2_ACOK BIT(14) - -/* ADC registers */ -#define RAA489000_REG_ADC_INPUT_CURRENT 0x83 -#define RAA489000_REG_ADC_CHARGE_CURRENT 0x85 -#define RAA489000_REG_ADC_VSYS 0x86 -#define RAA489000_REG_ADC_VBUS 0x89 - -enum isl9237_power_stage { - BUCK_MODE, - BOOST_MODE, - BUCK_BOOST_MODE, - REVERSE_BUCK_MODE -}; - -#define ISL9237_INFO_FSM_STATE_SHIFT 7 -#define ISL9237_INFO_FSM_STATE_MASK 7 - -enum isl9237_fsm_state { - FSM_OFF, - FSM_BAT, - FSM_ADPT, - FSM_ACOK, - FSM_VSYS, - FSM_CHRG, - FSM_ENTOG, - FSM_OTG -}; - -#define ISL923X_INFO_VSYSLO BIT(10) -#define ISL923X_INFO_DCHOT BIT(11) -#define ISL9237_INFO_ACHOT BIT(12) - -#define RAA489000_DEV_ID_B0 0x11 - -/* DVC - Dynamic Voltage Compensation */ -#define RAA489000_RP1_MAX 156 -#define RAA489000_RP1_MIN 36 -#define RAA489000_RP2_MAX 124 -#define RAA489000_RP2_MIN 0 - -#define RAA489000_C10_RP2_MASK GENMASK(4, 0) -#define RAA489000_C10_DISABLE_DVC_AUTO_ZERO BIT(5) -#define RAA489000_C10_ENABLE_DVC_TRICKLE_CHARGE BIT(6) -#define RAA489000_C10_DISABLE_DVC_CC_LOOP BIT(8) -#define RAA489000_C10_ENABLE_DVC_CHARGE_MODE BIT(9) -#define RAA489000_C10_RP1_MASK GENMASK(14, 10) -#define RAA489000_C10_RP1_SHIFT 10 -#define RAA489000_C10_ENABLE_DVC_MODE BIT(15) - -#define I2C_ADDR_CHARGER_FLAGS ISL923X_ADDR_FLAGS - -#define ISL923X_AC_PROCHOT_CURRENT_MAX 6400 /* mA */ -#define ISL923X_DC_PROCHOT_CURRENT_MAX 12800 /* mA */ - -#endif /* __CROS_EC_ISL923X_H */ diff --git a/driver/charger/isl9241.c b/driver/charger/isl9241.c deleted file mode 100644 index 794ea0b342..0000000000 --- a/driver/charger/isl9241.c +++ /dev/null @@ -1,599 +0,0 @@ -/* Copyright 2019 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. - * - * Renesas (Intersil) ISL-9241 battery charger driver. - */ - -/* TODO(b/175881324) */ -#ifndef CONFIG_ZEPHYR -#include "adc.h" -#endif -#include "battery.h" -#include "battery_smart.h" -#include "charger.h" -#include "charge_state.h" -#include "console.h" -#include "common.h" -#include "hooks.h" -#include "i2c.h" -#include "isl9241.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -#ifndef CONFIG_CHARGER_NARROW_VDC -#error "ISL9241 is a NVDC charger, please enable CONFIG_CHARGER_NARROW_VDC." -#endif - -/* Sense resistor default values in milli Ohm */ -#define ISL9241_DEFAULT_RS1 20 /* Input current sense resistor */ -#define ISL9241_DEFAULT_RS2 10 /* Battery charge current sense resistor */ - -#define BOARD_RS1 CONFIG_CHARGER_SENSE_RESISTOR_AC -#define BOARD_RS2 CONFIG_CHARGER_SENSE_RESISTOR - -#define BC_REG_TO_CURRENT(REG) (((REG) * ISL9241_DEFAULT_RS2) / BOARD_RS2) -#define BC_CURRENT_TO_REG(CUR) (((CUR) * BOARD_RS2) / ISL9241_DEFAULT_RS2) - -#define AC_REG_TO_CURRENT(REG) (((REG) * ISL9241_DEFAULT_RS1) / BOARD_RS1) -#define AC_CURRENT_TO_REG(CUR) (((CUR) * BOARD_RS1) / ISL9241_DEFAULT_RS1) - -/* Console output macros */ -#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args) - -static int learn_mode; - -/* Mutex for CONTROL1 register, that can be updated from multiple tasks. */ -K_MUTEX_DEFINE(control1_mutex); - -/* Charger parameters */ -static const struct charger_info isl9241_charger_info = { - .name = CHARGER_NAME, - .voltage_max = CHARGE_V_MAX, - .voltage_min = CHARGE_V_MIN, - .voltage_step = CHARGE_V_STEP, - .current_max = CHARGE_I_MAX, - .current_min = CHARGE_I_MIN, - .current_step = CHARGE_I_STEP, - .input_current_max = INPUT_I_MAX, - .input_current_min = INPUT_I_MIN, - .input_current_step = INPUT_I_STEP, -}; - -static enum ec_error_list isl9241_discharge_on_ac(int chgnum, int enable); - -static inline enum ec_error_list isl9241_read(int chgnum, int offset, - int *value) -{ - return i2c_read16(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - offset, value); -} - -static inline enum ec_error_list isl9241_write(int chgnum, int offset, - int value) -{ - return i2c_write16(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - offset, value); -} - -static inline enum ec_error_list isl9241_update(int chgnum, int offset, - uint16_t mask, - enum mask_update_action action) -{ - return i2c_update16(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - offset, mask, action); -} - -/* chip specific interfaces */ - -/*****************************************************************************/ -/* Charger interfaces */ -static enum ec_error_list isl9241_set_input_current_limit(int chgnum, - int input_current) -{ - int rv; - uint16_t reg = AC_CURRENT_TO_REG(input_current); - - rv = isl9241_write(chgnum, ISL9241_REG_ADAPTER_CUR_LIMIT1, reg); - if (rv) - return rv; - - return isl9241_write(chgnum, ISL9241_REG_ADAPTER_CUR_LIMIT2, reg); -} - -static enum ec_error_list isl9241_get_input_current_limit(int chgnum, - int *input_current) -{ - int rv; - - rv = isl9241_read(chgnum, ISL9241_REG_ADAPTER_CUR_LIMIT1, - input_current); - if (rv) - return rv; - - *input_current = AC_REG_TO_CURRENT(*input_current); - return EC_SUCCESS; -} - -static enum ec_error_list isl9241_manufacturer_id(int chgnum, int *id) -{ - return isl9241_read(chgnum, ISL9241_REG_MANUFACTURER_ID, id); -} - -static enum ec_error_list isl9241_device_id(int chgnum, int *id) -{ - return isl9241_read(chgnum, ISL9241_REG_DEVICE_ID, id); -} - -static enum ec_error_list isl9241_get_option(int chgnum, int *option) -{ - int rv; - uint32_t controls; - int reg; - - rv = isl9241_read(chgnum, ISL9241_REG_CONTROL0, ®); - if (rv) - return rv; - - controls = reg; - rv = isl9241_read(chgnum, ISL9241_REG_CONTROL1, ®); - if (rv) - return rv; - - controls |= reg << 16; - *option = controls; - return EC_SUCCESS; -} - -static enum ec_error_list isl9241_set_option(int chgnum, int option) -{ - int rv; - - rv = isl9241_write(chgnum, ISL9241_REG_CONTROL0, option & 0xFFFF); - if (rv) - return rv; - - return isl9241_write(chgnum, ISL9241_REG_CONTROL1, - (option >> 16) & 0xFFFF); -} - -static const struct charger_info *isl9241_get_info(int chgnum) -{ - return &isl9241_charger_info; -} - -static enum ec_error_list isl9241_get_status(int chgnum, int *status) -{ - int rv; - int reg; - - /* Level 2 charger */ - *status = CHARGER_LEVEL_2; - - /* Charge inhibit status */ - rv = isl9241_read(chgnum, ISL9241_REG_MIN_SYSTEM_VOLTAGE, ®); - if (rv) - return rv; - if (!reg) - *status |= CHARGER_CHARGE_INHIBITED; - - /* Battery present & AC present status */ - rv = isl9241_read(chgnum, ISL9241_REG_INFORMATION2, ®); - if (rv) - return rv; - if (!(reg & ISL9241_INFORMATION2_BATGONE_PIN)) - *status |= CHARGER_BATTERY_PRESENT; - if (reg & ISL9241_INFORMATION2_ACOK_PIN) - *status |= CHARGER_AC_PRESENT; - - return EC_SUCCESS; -} - -static enum ec_error_list isl9241_set_mode(int chgnum, int mode) -{ - int rv; - - /* - * See crosbug.com/p/51196. Always disable learn mode unless it was set - * explicitly. - */ - if (!learn_mode) { - rv = isl9241_discharge_on_ac(chgnum, 0); - if (rv) - return rv; - } - - /* - * Charger inhibit - * MinSystemVoltage 0x00h = disables all battery charging - */ - rv = isl9241_write(chgnum, ISL9241_REG_MIN_SYSTEM_VOLTAGE, - mode & CHARGE_FLAG_INHIBIT_CHARGE ? - 0 : battery_get_info()->voltage_min); - if (rv) - return rv; - - /* POR reset */ - if (mode & CHARGE_FLAG_POR_RESET) { - rv = isl9241_write(chgnum, ISL9241_REG_CONTROL3, - ISL9241_CONTROL3_DIGITAL_RESET); - } - - return rv; -} - -static enum ec_error_list isl9241_get_current(int chgnum, int *current) -{ - int rv; - - rv = isl9241_read(chgnum, ISL9241_REG_CHG_CURRENT_LIMIT, current); - if (rv) - return rv; - - *current = BC_REG_TO_CURRENT(*current); - return EC_SUCCESS; -} - -static enum ec_error_list isl9241_set_current(int chgnum, int current) -{ - return isl9241_write(chgnum, ISL9241_REG_CHG_CURRENT_LIMIT, - BC_CURRENT_TO_REG(current)); -} - -static enum ec_error_list isl9241_get_voltage(int chgnum, int *voltage) -{ - return isl9241_read(chgnum, ISL9241_REG_MAX_SYSTEM_VOLTAGE, voltage); -} - -static enum ec_error_list isl9241_set_voltage(int chgnum, int voltage) -{ - return isl9241_write(chgnum, ISL9241_REG_MAX_SYSTEM_VOLTAGE, voltage); -} - -static enum ec_error_list isl9241_get_vbus_voltage(int chgnum, int port, - int *voltage) -{ - int adc_val = 0; - int ctl3_val; - int rv; - - /* Get current Control3 value */ - rv = isl9241_read(chgnum, ISL9241_REG_CONTROL3, &ctl3_val); - if (rv) - goto error; - - /* Enable ADC */ - if (!(ctl3_val & ISL9241_CONTROL3_ENABLE_ADC)) { - rv = isl9241_write(chgnum, ISL9241_REG_CONTROL3, - ctl3_val | ISL9241_CONTROL3_ENABLE_ADC); - if (rv) - goto error; - } - - /* Read voltage ADC value */ - rv = isl9241_read(chgnum, ISL9241_REG_VIN_ADC_RESULTS, &adc_val); - if (rv) - goto error_restore_ctl3; - - /* - * Adjust adc_val - * - * raw adc_val has VIN_ADC in bits [13:6], so shift this down - * this puts adc_val in the range of 0..255, which maps to 0..24.48V - * each step in adc_val is 96mv - */ - adc_val >>= ISL9241_VIN_ADC_BIT_OFFSET; - adc_val *= ISL9241_VIN_ADC_STEP_MV; - *voltage = adc_val; - -error_restore_ctl3: - /* Restore Control3 value */ - if (!(ctl3_val & ISL9241_CONTROL3_ENABLE_ADC)) - (void)isl9241_write(chgnum, ISL9241_REG_CONTROL3, ctl3_val); - -error: - if (rv) - CPRINTF("Could not read VBUS ADC! Error: %d\n", rv); - - return rv; -} - -static enum ec_error_list isl9241_post_init(int chgnum) -{ - return EC_SUCCESS; -} - -static enum ec_error_list isl9241_discharge_on_ac(int chgnum, int enable) -{ - int rv; - - mutex_lock(&control1_mutex); - - rv = isl9241_update(chgnum, ISL9241_REG_CONTROL1, - ISL9241_CONTROL1_LEARN_MODE, - (enable) ? MASK_SET : MASK_CLR); - if (!rv) - learn_mode = enable; - - mutex_unlock(&control1_mutex); - return rv; -} - -int isl9241_set_ac_prochot(int chgnum, int ma) -{ - int rv; - uint16_t reg; - - /* - * The register reserves bits [6:0] and bits [15:13]. - * This routine should ensure these bits are not set - * before writing the register. - */ - if (ma > AC_REG_TO_CURRENT(ISL9241_AC_PROCHOT_CURRENT_MAX)) - reg = ISL9241_AC_PROCHOT_CURRENT_MAX; - else if (ma < AC_REG_TO_CURRENT(ISL9241_AC_PROCHOT_CURRENT_MIN)) - reg = ISL9241_AC_PROCHOT_CURRENT_MIN; - else - reg = AC_CURRENT_TO_REG(ma); - - rv = isl9241_write(chgnum, ISL9241_REG_AC_PROCHOT, reg); - if (rv) - CPRINTF("set_ac_prochot failed (%d)\n", rv); - - return rv; -} - -int isl9241_set_dc_prochot(int chgnum, int ma) -{ - int rv; - - /* - * The register reserves bits [7:0] and bits [15:14]. - * This routine should ensure these bits are not set - * before writing the register. - */ - if (ma > ISL9241_DC_PROCHOT_CURRENT_MAX) - ma = ISL9241_DC_PROCHOT_CURRENT_MAX; - else if (ma < ISL9241_DC_PROCHOT_CURRENT_MIN) - ma = ISL9241_DC_PROCHOT_CURRENT_MIN; - - rv = isl9241_write(chgnum, ISL9241_REG_DC_PROCHOT, ma); - if (rv) - CPRINTF("set_dc_prochot failed (%d)\n", rv); - - return rv; -} - -/*****************************************************************************/ -/* ISL-9241 initialization */ -static void isl9241_init(int chgnum) -{ -#ifdef CONFIG_ISL9241_SWITCHING_FREQ - int ctl_val; -#endif - - const struct battery_info *bi = battery_get_info(); - - /* - * Set the MaxSystemVoltage to battery maximum, - * 0x00=disables switching charger states - */ - if (isl9241_write(chgnum, ISL9241_REG_MAX_SYSTEM_VOLTAGE, - bi->voltage_max)) - goto init_fail; - - /* - * Set the MinSystemVoltage to battery minimum, - * 0x00=disables all battery charging - */ - if (isl9241_write(chgnum, ISL9241_REG_MIN_SYSTEM_VOLTAGE, - bi->voltage_min)) - goto init_fail; - - /* - * Set control2 register to - * [15:13]: Trickle Charging Current (battery pre-charge current) - * [10:9] : Prochot# Debounce time (1000us) - */ - if (isl9241_update(chgnum, ISL9241_REG_CONTROL2, - (ISL9241_CONTROL2_TRICKLE_CHG_CURR( - bi->precharge_current) | - ISL9241_CONTROL2_PROCHOT_DEBOUNCE_1000), - MASK_SET)) - goto init_fail; - - /* - * Set control3 register to - * [14]: ACLIM Reload (Do not reload) - */ - if (isl9241_update(chgnum, ISL9241_REG_CONTROL3, - ISL9241_CONTROL3_ACLIM_RELOAD, - MASK_SET)) - goto init_fail; - - /* - * Set control4 register to - * [13]: Slew rate control enable (sets VSYS ramp to 8mV/us) - */ - if (isl9241_update(chgnum, ISL9241_REG_CONTROL4, - ISL9241_CONTROL4_SLEW_RATE_CTRL, - MASK_SET)) - goto init_fail; - -#ifndef CONFIG_CHARGE_RAMP_HW - if (isl9241_update(chgnum, ISL9241_REG_CONTROL0, - ISL9241_CONTROL0_INPUT_VTG_REGULATION, - MASK_SET)) - goto init_fail; -#endif - -#ifdef CONFIG_ISL9241_SWITCHING_FREQ - if (isl9241_read(chgnum, ISL9241_REG_CONTROL1, &ctl_val)) - goto init_fail; - ctl_val &= ~ISL9241_CONTROL1_SWITCHING_FREQ_MASK; - ctl_val |= ((CONFIG_ISL9241_SWITCHING_FREQ << 7) & - ISL9241_CONTROL1_SWITCHING_FREQ_MASK); - if (isl9241_write(chgnum, ISL9241_REG_CONTROL1, ctl_val)) - goto init_fail; -#endif - - /* - * No need to proceed with the rest of init if we sysjump'd to this - * image as the input current limit has already been set. - */ - if (system_jumped_late()) - return; - - /* Initialize the input current limit to the board's default. */ - if (isl9241_set_input_current_limit(chgnum, - CONFIG_CHARGER_INPUT_CURRENT)) - goto init_fail; - - return; - -init_fail: - CPRINTF("ISL9241_init failed!\n"); -} - -/*****************************************************************************/ -/* Hardware current ramping */ - -#ifdef CONFIG_CHARGE_RAMP_HW -static enum ec_error_list isl9241_set_hw_ramp(int chgnum, int enable) -{ - /* HW ramp is controlled by input voltage regulation reference bits */ - return isl9241_update(chgnum, ISL9241_REG_CONTROL0, - ISL9241_CONTROL0_INPUT_VTG_REGULATION, - (enable) ? MASK_CLR : MASK_SET); -} - -static int isl9241_ramp_is_stable(int chgnum) -{ - /* - * Since ISL cannot read the current limit that the ramp has settled - * on, then we can never consider the ramp stable, because we never - * know what the stable limit is. - */ - return 0; -} - -static int isl9241_ramp_is_detected(int chgnum) -{ - return 1; -} - -static int isl9241_ramp_get_current_limit(int chgnum) -{ - int reg; - - if (isl9241_read(chgnum, ISL9241_REG_IADP_ADC_RESULTS, ®)) - return 0; - - /* LSB value of register = 22.2mA */ - return (reg * 222) / 10; -} -#endif /* CONFIG_CHARGE_RAMP_HW */ - -/* - * When fully charged in a low-power state, the ISL9241 may get stuck - * in CCM. Toggle learning mode for 50 ms to enter DCM and save power. - * This is a workaround provided by Renesas. See b/183771327. - * Note: the charger_get_state() returns the last known charge value, - * so need to check the battery is not disconnected when the system - * comes from the battery cutoff. - */ -static void isl9241_restart_charge_voltage_when_full(void) -{ - if (!chipset_in_or_transitioning_to_state(CHIPSET_STATE_ON) - && charge_get_state() == PWR_STATE_CHARGE_NEAR_FULL - && battery_get_disconnect_state() == BATTERY_NOT_DISCONNECTED) { - charger_discharge_on_ac(1); - msleep(50); - charger_discharge_on_ac(0); - } -} -DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, - isl9241_restart_charge_voltage_when_full, - HOOK_PRIO_DEFAULT); -DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, - isl9241_restart_charge_voltage_when_full, - HOOK_PRIO_DEFAULT); -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, - isl9241_restart_charge_voltage_when_full, - HOOK_PRIO_DEFAULT); - -/*****************************************************************************/ -#ifdef CONFIG_CMD_CHARGER_DUMP -static void dump_reg_range(int chgnum, int low, int high) -{ - int reg; - int regval; - int rv; - - for (reg = low; reg <= high; reg++) { - CPRINTF("[%Xh] = ", reg); - rv = isl9241_read(chgnum, reg, ®val); - if (!rv) - CPRINTF("0x%04x\n", regval); - else - CPRINTF("ERR (%d)\n", rv); - cflush(); - } -} - -static int command_isl9241_dump(int argc, char **argv) -{ - char *e; - int chgnum = 0; - - if (argc >= 2) { - chgnum = strtoi(argv[1], &e, 10); - if (*e) - return EC_ERROR_PARAM1; - } - - dump_reg_range(chgnum, 0x14, 0x15); - dump_reg_range(chgnum, 0x38, 0x40); - dump_reg_range(chgnum, 0x43, 0x43); - dump_reg_range(chgnum, 0x47, 0x4F); - dump_reg_range(chgnum, 0x80, 0x87); - dump_reg_range(chgnum, 0x90, 0x91); - dump_reg_range(chgnum, 0xFE, 0xFF); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(charger_dump, command_isl9241_dump, - "charger_dump <chgnum>", - "Dumps ISL9241 registers"); -#endif /* CONFIG_CMD_CHARGER_DUMP */ - -const struct charger_drv isl9241_drv = { - .init = &isl9241_init, - .post_init = &isl9241_post_init, - .get_info = &isl9241_get_info, - .get_status = &isl9241_get_status, - .set_mode = &isl9241_set_mode, - .get_current = &isl9241_get_current, - .set_current = &isl9241_set_current, - .get_voltage = &isl9241_get_voltage, - .set_voltage = &isl9241_set_voltage, - .discharge_on_ac = &isl9241_discharge_on_ac, - .get_vbus_voltage = &isl9241_get_vbus_voltage, - .set_input_current_limit = &isl9241_set_input_current_limit, - .get_input_current_limit = &isl9241_get_input_current_limit, - .manufacturer_id = &isl9241_manufacturer_id, - .device_id = &isl9241_device_id, - .get_option = &isl9241_get_option, - .set_option = &isl9241_set_option, -#ifdef CONFIG_CHARGE_RAMP_HW - .set_hw_ramp = &isl9241_set_hw_ramp, - .ramp_is_stable = &isl9241_ramp_is_stable, - .ramp_is_detected = &isl9241_ramp_is_detected, - .ramp_get_current_limit = &isl9241_ramp_get_current_limit, -#endif -}; diff --git a/driver/charger/isl9241.h b/driver/charger/isl9241.h deleted file mode 100644 index 0e5acd09df..0000000000 --- a/driver/charger/isl9241.h +++ /dev/null @@ -1,140 +0,0 @@ -/* Copyright 2019 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. - * - * Renesas (Intersil) ISL-9241 battery charger driver header. - */ - -#ifndef __CROS_EC_ISL9241_H -#define __CROS_EC_ISL9241_H - -#include "driver/charger/isl9241_public.h" - -#define CHARGER_NAME "ISL9241" -#define CHARGE_V_MAX 18304 -#define CHARGE_V_MIN 64 -#define CHARGE_V_STEP 8 -#define CHARGE_I_MAX 6140 -#define CHARGE_I_MIN 4 -#define CHARGE_I_STEP 4 -#define INPUT_I_MAX 6140 -#define INPUT_I_MIN 4 -#define INPUT_I_STEP 4 - -/* Registers */ - -/* - * ChargeCurrentLimit [12:2] 11-bit (0x0000h = disables fast charging, - * trickle charging is allowed) - */ -#define ISL9241_REG_CHG_CURRENT_LIMIT 0x14 - -/* MaxSystemVoltage [14:3] 12-bit, (0x0000h = disables switching) */ -#define ISL9241_REG_MAX_SYSTEM_VOLTAGE 0x15 - -#define ISL9241_REG_CONTROL7 0x38 - -/* Configures various charger options */ -#define ISL9241_REG_CONTROL0 0x39 -/* 2: Input Voltage Regulation (0 = Enable (default), 1 = Disable) */ -#define ISL9241_CONTROL0_INPUT_VTG_REGULATION BIT(2) - - -#define ISL9241_REG_INFORMATION1 0x3A -#define ISL9241_REG_ADAPTER_CUR_LIMIT2 0x3B - -/* Configures various charger options */ -#define ISL9241_REG_CONTROL1 0x3C -#define ISL9241_CONTROL1_PSYS BIT(3) -#define ISL9241_CONTROL1_LEARN_MODE BIT(12) -/* - * 9:7 - Switching Frequency - */ -#define ISL9241_CONTROL1_SWITCHING_FREQ_MASK 0x380 -#define ISL9241_CONTROL1_SWITCHING_FREQ_1420KHZ 0 -#define ISL9241_CONTROL1_SWITCHING_FREQ_1180KHZ 1 -#define ISL9241_CONTROL1_SWITCHING_FREQ_1020KHZ 2 -#define ISL9241_CONTROL1_SWITCHING_FREQ_890KHZ 3 -#define ISL9241_CONTROL1_SWITCHING_FREQ_808KHZ 4 -#define ISL9241_CONTROL1_SWITCHING_FREQ_724KHZ 5 -#define ISL9241_CONTROL1_SWITCHING_FREQ_656KHZ 6 -#define ISL9241_CONTROL1_SWITCHING_FREQ_600KHZ 7 - -/* Configures various charger options */ -#define ISL9241_REG_CONTROL2 0x3D -/* - * 15:13 - Trickle Charging Current - * <000> 32mA (do not use) - * <001> 64mA - * <010> 96mA - * <011> 128mA (default) - * <100> 160mA - * <101> 192mA - * <110> 224mA - * <111> 256mA - */ -#define ISL9241_CONTROL2_TRICKLE_CHG_CURR(curr) ((((curr) >> 5) - 1) << 13) -/* 12 - Two-Level Adapter Current Limit */ -#define ISL9241_CONTROL2_TWO_LEVEL_ADP_CURR BIT(12) -/* 10:9 PROCHOT# debounce time in uS */ -#define ISL9241_CONTROL2_PROCHOT_DEBOUNCE_MASK GENMASK(10, 9) -#define ISL9241_CONTROL2_PROCHOT_DEBOUNCE_500 (2 << 9) -#define ISL9241_CONTROL2_PROCHOT_DEBOUNCE_1000 (3 << 9) - -/* MinSystemVoltage [13:6] 8-bit (0x0000h = disables all battery charging) */ -#define ISL9241_REG_MIN_SYSTEM_VOLTAGE 0x3E - -#define ISL9241_REG_ADAPTER_CUR_LIMIT1 0x3F -#define ISL9241_REG_ACOK_REFERENCE 0x40 -#define ISL9241_REG_CONTROL6 0x43 -#define ISL9241_REG_AC_PROCHOT 0x47 -#define ISL9241_REG_DC_PROCHOT 0x48 -#define ISL9241_REG_OTG_VOLTAGE 0x49 -#define ISL9241_REG_OTG_CURRENT 0x4A - -/* VIN Voltage (ADP Min Voltage) (default 4.096V) */ -#define ISL9241_REG_VIN_VOLTAGE 0x4B - -/* Configures various charger options */ -#define ISL9241_REG_CONTROL3 0x4C -/* 14: ACLIM Reload (0 - reload, 1 - Do not reload */ -#define ISL9241_CONTROL3_ACLIM_RELOAD BIT(14) -/* 2: Digital Reset (0 - Idle, 1 - Reset */ -#define ISL9241_CONTROL3_DIGITAL_RESET BIT(2) -/* 0: Enable ADC (0 - Active when charging, 1 - Active always) */ -#define ISL9241_CONTROL3_ENABLE_ADC BIT(0) - -/* Indicates various charger status */ -#define ISL9241_REG_INFORMATION2 0x4D -/* 12: BATGONE pin status (0 = Battery is present, 1 = No battery) */ -#define ISL9241_INFORMATION2_BATGONE_PIN BIT(12) -/* 14: ACOK pin status (0 = No adapter, 1 = Adapter is present) */ -#define ISL9241_INFORMATION2_ACOK_PIN BIT(14) - -#define ISL9241_REG_CONTROL4 0x4E -/* 11: Rsense (Rs1:Rs2) ratio for PSYS (0 - 2:1, 1 - 1:1) */ -#define ISL9241_CONTROL4_PSYS_RSENSE_RATIO BIT(11) -/* 13: Enable VSYS slew rate control (0 - disable, 1 - enable) */ -#define ISL9241_CONTROL4_SLEW_RATE_CTRL BIT(13) - -#define ISL9241_REG_CONTROL5 0x4F -#define ISL9241_REG_NTC_ADC_RESULTS 0x80 -#define ISL9241_REG_VBAT_ADC_RESULTS 0x81 -#define ISL9241_REG_TJ_ADC_RESULTS 0x82 - -/* ADC result for adapter current measurements, LSB = 22.2mA */ -#define ISL9241_REG_IADP_ADC_RESULTS 0x83 - -#define ISL9241_REG_DC_ADC_RESULTS 0x84 -#define ISL9241_REG_CC_ADC_RESULTS 0x85 -#define ISL9241_REG_VSYS_ADC_RESULTS 0x86 -#define ISL9241_REG_VIN_ADC_RESULTS 0x87 -#define ISL9241_REG_INFORMATION3 0x90 -#define ISL9241_REG_INFORMATION4 0x91 -#define ISL9241_REG_MANUFACTURER_ID 0xFE -#define ISL9241_REG_DEVICE_ID 0xFF - -#define ISL9241_VIN_ADC_BIT_OFFSET 6 -#define ISL9241_VIN_ADC_STEP_MV 96 - -#endif /* __CROS_EC_ISL9241_H */ diff --git a/driver/charger/rt946x.c b/driver/charger/rt946x.c deleted file mode 100644 index a4cfa5d2eb..0000000000 --- a/driver/charger/rt946x.c +++ /dev/null @@ -1,1927 +0,0 @@ -/* Copyright 2017 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. - * - * Richtek rt946x, Mediatek mt6370 battery charger driver. - */ - -#include "battery.h" -#include "battery_smart.h" -#include "charger.h" -#include "charge_manager.h" -#include "common.h" -#include "compile_time_macros.h" -#include "config.h" -#include "console.h" -#include "extpower.h" -#include "hooks.h" -#include "i2c.h" -#include "printf.h" -#include "driver/wpc/p9221.h" -#include "rt946x.h" -#include "task.h" -#include "tcpm/tcpm.h" -#include "timer.h" -#include "usb_charge.h" -#include "usb_pd.h" -#include "util.h" - -/* Console output macros */ -#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args) -#define CPRINTS(format, args...) \ - cprints(CC_CHARGER, "%s " format, "RT946X", ## args) - -/* Charger parameters */ -#define CHARGER_NAME RT946X_CHARGER_NAME -#define CHARGE_V_MAX 4710 -#define CHARGE_V_MIN 3900 -#define CHARGE_V_STEP 10 -#define CHARGE_I_MAX 5000 -#define CHARGE_I_MIN 100 -#define CHARGE_I_OFF 0 -#define CHARGE_I_STEP 100 -#define INPUT_I_MAX 3250 -#define INPUT_I_MIN 100 -#define INPUT_I_STEP 50 - -/* Charger parameters */ -static const struct charger_info rt946x_charger_info = { - .name = CHARGER_NAME, - .voltage_max = CHARGE_V_MAX, - .voltage_min = CHARGE_V_MIN, - .voltage_step = CHARGE_V_STEP, - .current_max = CHARGE_I_MAX, - .current_min = CHARGE_I_MIN, - .current_step = CHARGE_I_STEP, - .input_current_max = INPUT_I_MAX, - .input_current_min = INPUT_I_MIN, - .input_current_step = INPUT_I_STEP, -}; - -static const struct rt946x_init_setting default_init_setting = { - .eoc_current = 400, - .mivr = 4000, - .ircmp_vclamp = 32, - .ircmp_res = 25, - .boost_voltage = 5050, - .boost_current = 1500, -}; - -__attribute__((weak)) -const struct rt946x_init_setting *board_rt946x_init_setting(void) -{ - return &default_init_setting; -} - -enum rt946x_ilmtsel { - RT946X_ILMTSEL_PSEL_OTG, - RT946X_ILMTSEL_AICR = 2, - RT946X_ILMTSEL_LOWER_LEVEL, /* lower of above two */ -}; - -enum rt946x_chg_stat { - RT946X_CHGSTAT_READY = 0, - RT946X_CHGSTAT_IN_PROGRESS, - RT946X_CHGSTAT_DONE, - RT946X_CHGSTAT_FAULT, -}; - -static struct mutex adc_access_lock; - -#ifdef CONFIG_CHARGER_MT6370 -/* - * Unit for each ADC parameter - * 0 stands for reserved - */ -static const int mt6370_adc_unit[MT6370_ADC_MAX] = { - 0, - MT6370_ADC_UNIT_VBUS_DIV5, - MT6370_ADC_UNIT_VBUS_DIV2, - MT6370_ADC_UNIT_VSYS, - MT6370_ADC_UNIT_VBAT, - 0, - MT6370_ADC_UNIT_TS_BAT, - 0, - MT6370_ADC_UNIT_IBUS, - MT6370_ADC_UNIT_IBAT, - 0, - MT6370_ADC_UNIT_CHG_VDDP, - MT6370_ADC_UNIT_TEMP_JC, -}; - -static const int mt6370_adc_offset[MT6370_ADC_MAX] = { - 0, - MT6370_ADC_OFFSET_VBUS_DIV5, - MT6370_ADC_OFFSET_VBUS_DIV2, - MT6370_ADC_OFFSET_VSYS, - MT6370_ADC_OFFSET_VBAT, - 0, - MT6370_ADC_OFFSET_TS_BAT, - 0, - MT6370_ADC_OFFSET_IBUS, - MT6370_ADC_OFFSET_IBAT, - 0, - MT6370_ADC_OFFSET_CHG_VDDP, - MT6370_ADC_OFFSET_TEMP_JC, -}; - -static int hidden_mode_cnt = 0; -static struct mutex hidden_mode_lock; -static const unsigned char mt6370_reg_en_hidden_mode[] = { - MT6370_REG_HIDDENPASCODE1, - MT6370_REG_HIDDENPASCODE2, - MT6370_REG_HIDDENPASCODE3, - MT6370_REG_HIDDENPASCODE4, -}; - -static const unsigned char mt6370_val_en_hidden_mode[] = { - 0x96, 0x69, 0xC3, 0x3C, -}; - -static const unsigned char mt6370_val_en_test_mode[] = { - 0x69, 0x96, 0x63, 0x70, -}; -#endif /* CONFIG_CHARGER_MT6370 */ - -#if defined(CONFIG_CHARGER_RT9466) || defined(CONFIG_CHARGER_RT9467) -enum rt946x_irq { - RT946X_IRQ_CHGSTATC = 0, - RT946X_IRQ_CHGFAULT, - RT946X_IRQ_TSSTATC, - RT946X_IRQ_CHGIRQ1, - RT946X_IRQ_CHGIRQ2, - RT946X_IRQ_CHGIRQ3, -#ifdef CONFIG_CHARGER_RT9467 - RT946X_IRQ_DPDMIRQ, -#endif - RT946X_IRQ_COUNT, -}; - -static uint8_t rt946x_irqmask[RT946X_IRQ_COUNT] = { - 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, -#ifdef CONFIG_CHARGER_RT9467 - 0xFC, -#endif -}; - -static const uint8_t rt946x_irq_maskall[RT946X_IRQ_COUNT] = { - 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, -#ifdef CONFIG_CHARGER_RT9467 - 0xFF, -#endif -}; -#elif defined(CONFIG_CHARGER_MT6370) -enum rt946x_irq { - MT6370_IRQ_CHGSTAT1 = 0, - MT6370_IRQ_CHGSTAT2, - MT6370_IRQ_CHGSTAT3, - MT6370_IRQ_CHGSTAT4, - MT6370_IRQ_CHGSTAT5, - MT6370_IRQ_CHGSTAT6, - MT6370_IRQ_DPDMSTAT, - MT6370_IRQ_DICHGSTAT, - MT6370_IRQ_OVPCTRLSTAT, - MT6370_IRQ_FLEDSTAT1, - MT6370_IRQ_FLEDSTAT2, - MT6370_IRQ_BASESTAT, - MT6370_IRQ_LDOSTAT, - MT6370_IRQ_RGBSTAT, - MT6370_IRQ_BLSTAT, - MT6370_IRQ_DBSTAT, - RT946X_IRQ_COUNT, -}; - -static uint8_t rt946x_irqmask[RT946X_IRQ_COUNT] = { - 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, -}; - -static const uint8_t rt946x_irq_maskall[RT946X_IRQ_COUNT] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, -}; -#endif - -static enum ec_error_list rt946x_set_current(int chgnum, int current); -static enum ec_error_list rt946x_get_current(int chgnum, int *current); -static enum ec_error_list rt946x_set_voltage(int chgnum, int voltage); -static enum ec_error_list rt946x_enable_otg_power(int chgnum, int enabled); -static const struct charger_info *rt946x_get_info(int chgnum); - -/* Must be in ascending order */ -static const uint16_t rt946x_boost_current[] = { - 500, 700, 1100, 1300, 1800, 2100, 2400, -}; - -static enum ec_error_list rt946x_read8(int chgnum, int reg, int *val) -{ - return i2c_read8(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, reg, val); -} - -static enum ec_error_list rt946x_write8(int chgnum, int reg, int val) -{ - return i2c_write8(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, reg, val); -} - -static enum ec_error_list rt946x_block_write(int chgnum, int reg, - const uint8_t *val, int len) -{ - return i2c_write_block(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - reg, val, len); -} - -static int rt946x_update_bits(int chgnum, int reg, int mask, int val) -{ - int rv; - int reg_val = 0; - - rv = rt946x_read8(chgnum, reg, ®_val); - if (rv) - return rv; - reg_val &= ~mask; - reg_val |= (mask & val); - rv = rt946x_write8(chgnum, reg, reg_val); - return rv; -} - -static inline int rt946x_set_bit(int chgnum, int reg, int mask) -{ - return rt946x_update_bits(chgnum, reg, mask, mask); -} - -static inline int rt946x_clr_bit(int chgnum, int reg, int mask) -{ - return rt946x_update_bits(chgnum, reg, mask, 0x00); -} - -static inline int mt6370_pmu_reg_test_bit(int chgnum, int cmd, int shift, - int *is_one) -{ - int rv, data; - - rv = rt946x_read8(chgnum, cmd, &data); - if (rv) { - *is_one = 0; - return rv; - } - - *is_one = !!(data & BIT(shift)); - return rv; -} - -static inline uint8_t rt946x_closest_reg(uint16_t min, uint16_t max, - uint16_t step, uint16_t target) -{ - if (target < min) - return 0; - if (target >= max) - return ((max - min) / step); - return (target - min) / step; -} - -static int rt946x_get_ieoc(int chgnum, uint32_t *ieoc) -{ - int ret, reg_ieoc; - - ret = rt946x_read8(chgnum, RT946X_REG_CHGCTRL9, ®_ieoc); - if (ret) - return ret; - - *ieoc = RT946X_IEOC_MIN + - RT946X_IEOC_STEP * - ((reg_ieoc & RT946X_MASK_IEOC) >> RT946X_SHIFT_IEOC); - - return EC_SUCCESS; -} - -#ifdef CONFIG_CHARGER_MT6370 -static int mt6370_enable_hidden_mode(int chgnum, int en) -{ - int rv = 0; - - if (in_interrupt_context()) { - CPRINTS("Err: use hidden mode in IRQ"); - return EC_ERROR_INVAL; - } - - mutex_lock(&hidden_mode_lock); - if (en) { - if (hidden_mode_cnt == 0) { - rv = rt946x_block_write(chgnum, - mt6370_reg_en_hidden_mode[0], - mt6370_val_en_hidden_mode, - ARRAY_SIZE(mt6370_val_en_hidden_mode)); - if (rv) - goto out; - } - hidden_mode_cnt++; - } else { - if (hidden_mode_cnt == 1) /* last one */ - rv = rt946x_write8(chgnum, mt6370_reg_en_hidden_mode[0], - 0x00); - hidden_mode_cnt--; - if (rv) - goto out; - } - -out: - mutex_unlock(&hidden_mode_lock); - return rv; -} - -/* - * Vsys short protection: - * When the system is charging at 500mA, and if Isys > 3600mA, the - * power path will be turned off and cause the system shutdown. - * When Ichg < 400mA, then power path is roughly 1/8 of the original. - * When Isys > 3600mA, this cause the voltage between Vbat and Vsys too - * huge (Vbat - Vsys > Vsys short portection) and turns off the power - * path. - * To workaround this, - * 1. disable Vsys short protection when Ichg is set below 900mA - * 2. forbids Ichg <= 400mA (this is done natually on mt6370, since mt6370's - * minimum current is 512) - */ -static int mt6370_ichg_workaround(int chgnum, int new_ichg) -{ - int rv = EC_SUCCESS; - int curr_ichg; - - /* - * TODO(b:144532905): The workaround should be applied to rt9466 as - * well. But this needs rt9466's hidden register datasheet. Enable - * this if we need it in the future. - */ - if (!IS_ENABLED(CONFIG_CHARGER_MT6370)) - return EC_SUCCESS; - - rv = rt946x_get_current(chgnum, &curr_ichg); - if (rv) - return rv; - - mt6370_enable_hidden_mode(chgnum, 1); - - /* disable Vsys protect if if the new ichg is below 900mA */ - if (curr_ichg >= 900 && new_ichg < 900) - rv = rt946x_update_bits(chgnum, RT946X_REG_CHGHIDDENCTRL7, - RT946X_MASK_HIDDENCTRL7_VSYS_PROTECT, - 0); - /* enable Vsys protect if the new ichg is above 900mA */ - else if (new_ichg >= 900 && curr_ichg < 900) - rv = rt946x_update_bits(chgnum, RT946X_REG_CHGHIDDENCTRL7, - RT946X_MASK_HIDDENCTRL7_VSYS_PROTECT, - RT946X_ENABLE_VSYS_PROTECT); - - mt6370_enable_hidden_mode(chgnum, 0); - return rv; -} -#endif /* CONFIG_CHARGER_MT6370 */ - -static inline int rt946x_enable_wdt(int chgnum, int en) -{ - return (en ? rt946x_set_bit : rt946x_clr_bit) - (chgnum, RT946X_REG_CHGCTRL13, RT946X_MASK_WDT_EN); -} - -/* Enable high-impedance mode */ -static inline int rt946x_enable_hz(int chgnum, int en) -{ - return (en ? rt946x_set_bit : rt946x_clr_bit) - (chgnum, RT946X_REG_CHGCTRL1, RT946X_MASK_HZ_EN); -} - -int rt946x_por_reset(void) -{ - int rv, val; - -#ifdef CONFIG_CHARGER_MT6370 - /* Soft reset. It takes only 1ns for resetting. b/116682788 */ - val = RT946X_MASK_SOFT_RST; - /* - * MT6370 has to set passcodes before resetting all the registers and - * logics. - */ - rv = rt946x_write8(CHARGER_SOLO, MT6370_REG_RSTPASCODE1, - MT6370_MASK_RSTPASCODE1); - rv |= rt946x_write8(CHARGER_SOLO, MT6370_REG_RSTPASCODE2, - MT6370_MASK_RSTPASCODE2); -#else - /* Hard reset, may take several milliseconds. */ - val = RT946X_MASK_RST; - rv = rt946x_enable_hz(CHARGER_SOLO, 0); -#endif - if (rv) - return rv; - - return rt946x_set_bit(CHARGER_SOLO, RT946X_REG_CORECTRL_RST, val); -} - -static int rt946x_reset_to_zero(int chgnum) -{ - int rv; - - rv = rt946x_set_current(chgnum, 0); - if (rv) - return rv; - - rv = rt946x_set_voltage(chgnum, 0); - if (rv) - return rv; - - return rt946x_enable_hz(chgnum, 1); -} - -static int rt946x_enable_bc12_detection(int chgnum, int en) -{ -#if defined(CONFIG_CHARGER_RT9467) || defined(CONFIG_CHARGER_MT6370) - int rv; - - if (en) { -#ifdef CONFIG_CHARGER_MT6370_BC12_GPIO - gpio_set_level(GPIO_BC12_DET_EN, 1); -#endif /* CONFIG_CHARGER_MT6370_BC12_GPIO */ - return rt946x_set_bit(chgnum, RT946X_REG_DPDM1, - RT946X_MASK_USBCHGEN); - } - - rv = rt946x_clr_bit(chgnum, RT946X_REG_DPDM1, RT946X_MASK_USBCHGEN); -#ifdef CONFIG_CHARGER_MT6370_BC12_GPIO - gpio_set_level(GPIO_BC12_DET_EN, 0); -#endif /* CONFIG_CHARGER_MT6370_BC12_GPIO */ - return rv; -#endif - return 0; -} - -static int rt946x_set_ieoc(int chgnum, unsigned int ieoc) -{ - uint8_t reg_ieoc; - - reg_ieoc = rt946x_closest_reg(RT946X_IEOC_MIN, RT946X_IEOC_MAX, - RT946X_IEOC_STEP, ieoc); - - CPRINTS("ieoc=%d", ieoc); - - return rt946x_update_bits(chgnum, RT946X_REG_CHGCTRL9, RT946X_MASK_IEOC, - reg_ieoc << RT946X_SHIFT_IEOC); -} - -static int rt946x_set_mivr(int chgnum, unsigned int mivr) -{ - uint8_t reg_mivr = 0; - - reg_mivr = rt946x_closest_reg(RT946X_MIVR_MIN, RT946X_MIVR_MAX, - RT946X_MIVR_STEP, mivr); - - CPRINTS("mivr=%d", mivr); - - return rt946x_update_bits(chgnum, RT946X_REG_CHGCTRL6, RT946X_MASK_MIVR, - reg_mivr << RT946X_SHIFT_MIVR); -} - -static int rt946x_set_boost_voltage(int chgnum, unsigned int voltage) -{ - uint8_t reg_voltage = 0; - - reg_voltage = rt946x_closest_reg(RT946X_BOOST_VOLTAGE_MIN, - RT946X_BOOST_VOLTAGE_MAX, RT946X_BOOST_VOLTAGE_STEP, voltage); - - CPRINTS("voltage=%d", voltage); - - return rt946x_update_bits(chgnum, RT946X_REG_CHGCTRL5, - RT946X_MASK_BOOST_VOLTAGE, - reg_voltage << RT946X_SHIFT_BOOST_VOLTAGE); -} - -static int rt946x_set_boost_current(int chgnum, unsigned int current) -{ - int i; - - /* - * Find the smallest output current threshold which can support - * our requested output current. Use the greatest achievable - * boost current (2.4A) if requested current is too large. - */ - for (i = 0; i < ARRAY_SIZE(rt946x_boost_current) - 1; i++) { - if (current < rt946x_boost_current[i]) - break; - } - - CPRINTS("current=%d", current); - - return rt946x_update_bits(chgnum, RT946X_REG_CHGCTRL10, - RT946X_MASK_BOOST_CURRENT, - i << RT946X_SHIFT_BOOST_CURRENT); -} - -static int rt946x_set_ircmp_vclamp(int chgnum, unsigned int vclamp) -{ - uint8_t reg_vclamp = 0; - - reg_vclamp = rt946x_closest_reg(RT946X_IRCMP_VCLAMP_MIN, - RT946X_IRCMP_VCLAMP_MAX, RT946X_IRCMP_VCLAMP_STEP, vclamp); - - CPRINTS("vclamp=%d", vclamp); - - return rt946x_update_bits(chgnum, RT946X_REG_CHGCTRL18, - RT946X_MASK_IRCMP_VCLAMP, - reg_vclamp << RT946X_SHIFT_IRCMP_VCLAMP); -} - -static int rt946x_set_ircmp_res(int chgnum, unsigned int res) -{ - uint8_t reg_res = 0; - - reg_res = rt946x_closest_reg(RT946X_IRCMP_RES_MIN, RT946X_IRCMP_RES_MAX, - RT946X_IRCMP_RES_STEP, res); - - CPRINTS("res=%d", res); - - return rt946x_update_bits(chgnum, RT946X_REG_CHGCTRL18, - RT946X_MASK_IRCMP_RES, - reg_res << RT946X_SHIFT_IRCMP_RES); -} - -static int rt946x_set_vprec(int chgnum, unsigned int vprec) -{ - uint8_t reg_vprec = 0; - - reg_vprec = rt946x_closest_reg(RT946X_VPREC_MIN, RT946X_VPREC_MAX, - RT946X_VPREC_STEP, vprec); - - CPRINTS("vprec=%d", vprec); - - return rt946x_update_bits(chgnum, RT946X_REG_CHGCTRL8, - RT946X_MASK_VPREC, - reg_vprec << RT946X_SHIFT_VPREC); -} - -static int rt946x_set_iprec(int chgnum, unsigned int iprec) -{ - uint8_t reg_iprec = 0; - - reg_iprec = rt946x_closest_reg(RT946X_IPREC_MIN, RT946X_IPREC_MAX, - RT946X_IPREC_STEP, iprec); - - CPRINTS("iprec=%d", iprec); - - return rt946x_update_bits(chgnum, RT946X_REG_CHGCTRL8, - RT946X_MASK_IPREC, - reg_iprec << RT946X_SHIFT_IPREC); -} - -static int rt946x_init_irq(int chgnum) -{ - int rv = 0; - int unused; - int i; - - /* Mask all interrupts */ - rv = rt946x_block_write(chgnum, RT946X_REG_CHGSTATCCTRL, - rt946x_irq_maskall, RT946X_IRQ_COUNT); - if (rv) - return rv; - - /* Clear all interrupt flags */ - for (i = 0; i < RT946X_IRQ_COUNT; i++) { - rv = rt946x_read8(chgnum, RT946X_REG_CHGSTATC + i, &unused); - if (rv) - return rv; - } - - /* Init interrupt */ - return rt946x_block_write(chgnum, RT946X_REG_CHGSTATCCTRL, - rt946x_irqmask, ARRAY_SIZE(rt946x_irqmask)); -} - -static int rt946x_init_setting(int chgnum) -{ - int rv = 0; - const struct battery_info *batt_info = battery_get_info(); - const struct rt946x_init_setting *setting = board_rt946x_init_setting(); - -#ifdef CONFIG_BATTERY_SMART - /* Disable EOC */ - rv = rt946x_enable_charge_eoc(0); - if (rv) - return rv; -#endif - -#ifdef CONFIG_CHARGER_OTG - /* Disable boost-mode output voltage */ - rv = rt946x_enable_otg_power(chgnum, 0); - if (rv) - return rv; -#endif - /* Disable BC 1.2 detection by default. It will be enabled on demand */ - rv = rt946x_enable_bc12_detection(chgnum, 0); - if (rv) - return rv; - /* Disable WDT */ - rv = rt946x_enable_wdt(chgnum, 0); - if (rv) - return rv; - /* Disable battery thermal protection */ - rv = rt946x_clr_bit(chgnum, RT946X_REG_CHGCTRL16, RT946X_MASK_JEITA_EN); - if (rv) - return rv; - /* Disable charge timer */ - rv = rt946x_clr_bit(chgnum, RT946X_REG_CHGCTRL12, RT946X_MASK_TMR_EN); - if (rv) - return rv; - rv = rt946x_set_mivr(chgnum, setting->mivr); - if (rv) - return rv; - rv = rt946x_set_ieoc(chgnum, setting->eoc_current); - if (rv) - return rv; - rv = rt946x_set_boost_voltage(chgnum, - setting->boost_voltage); - if (rv) - return rv; - rv = rt946x_set_boost_current(chgnum, - setting->boost_current); - if (rv) - return rv; - rv = rt946x_set_ircmp_vclamp(chgnum, setting->ircmp_vclamp); - if (rv) - return rv; - rv = rt946x_set_ircmp_res(chgnum, setting->ircmp_res); - if (rv) - return rv; - rv = rt946x_set_vprec(chgnum, batt_info->precharge_voltage ? - batt_info->precharge_voltage : batt_info->voltage_min); - if (rv) - return rv; - rv = rt946x_set_iprec(chgnum, batt_info->precharge_current); - if (rv) - return rv; - -#ifdef CONFIG_CHARGER_MT6370_BACKLIGHT - rt946x_write8(chgnum, MT6370_BACKLIGHT_BLEN, - MT6370_MASK_BLED_EXT_EN | MT6370_MASK_BLED_EN | - MT6370_MASK_BLED_1CH_EN | MT6370_MASK_BLED_2CH_EN | - MT6370_MASK_BLED_3CH_EN | MT6370_MASK_BLED_4CH_EN | - MT6370_BLED_CODE_LINEAR); - rt946x_update_bits(chgnum, MT6370_BACKLIGHT_BLPWM, - MT6370_MASK_BLPWM_BLED_PWM, - BIT(MT6370_SHIFT_BLPWM_BLED_PWM)); -#endif - - return rt946x_init_irq(chgnum); -} - -#ifdef CONFIG_CHARGER_OTG -static enum ec_error_list rt946x_enable_otg_power(int chgnum, int enabled) -{ - return (enabled ? rt946x_set_bit : rt946x_clr_bit) - (chgnum, RT946X_REG_CHGCTRL1, RT946X_MASK_OPA_MODE); -} - -static int rt946x_is_sourcing_otg_power(int chgnum, int port) -{ - int val; - - if (rt946x_read8(CHARGER_SOLO, RT946X_REG_CHGCTRL1, &val)) - return 0; - - return !!(val & RT946X_MASK_OPA_MODE); -} -#endif - -static enum ec_error_list rt946x_set_input_current_limit(int chgnum, - int input_current) -{ - uint8_t reg_iin = 0; - const struct charger_info * const info = rt946x_get_info(chgnum); - - reg_iin = rt946x_closest_reg(info->input_current_min, - info->input_current_max, info->input_current_step, - input_current); - - CPRINTS("iin=%d", input_current); - - return rt946x_update_bits(chgnum, RT946X_REG_CHGCTRL3, RT946X_MASK_AICR, - reg_iin << RT946X_SHIFT_AICR); -} - -static enum ec_error_list rt946x_get_input_current_limit(int chgnum, - int *input_current) -{ - int rv; - int val = 0; - const struct charger_info * const info = rt946x_get_info(chgnum); - - rv = rt946x_read8(chgnum, RT946X_REG_CHGCTRL3, &val); - if (rv) - return rv; - - val = (val & RT946X_MASK_AICR) >> RT946X_SHIFT_AICR; - *input_current = val * info->input_current_step - + info->input_current_min; - - return EC_SUCCESS; -} - -static enum ec_error_list rt946x_manufacturer_id(int chgnum, int *id) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -static enum ec_error_list rt946x_device_id(int chgnum, int *id) -{ - int rv; - - rv = rt946x_read8(chgnum, RT946X_REG_DEVICEID, id); - if (rv == EC_SUCCESS) - *id &= RT946X_MASK_VENDOR_ID; - return rv; -} - -static enum ec_error_list rt946x_get_option(int chgnum, int *option) -{ - /* Ignored: does not exist */ - *option = 0; - return EC_SUCCESS; -} - -static enum ec_error_list rt946x_set_option(int chgnum, int option) -{ - /* Ignored: does not exist */ - return EC_SUCCESS; -} - -static const struct charger_info *rt946x_get_info(int chgnum) -{ - return &rt946x_charger_info; -} - -static enum ec_error_list rt946x_get_status(int chgnum, int *status) -{ - int rv; - int val = 0; - - rv = rt946x_read8(chgnum, RT946X_REG_CHGCTRL2, &val); - if (rv) - return rv; - val = (val & RT946X_MASK_CHG_EN) >> RT946X_SHIFT_CHG_EN; - if (!val) - *status |= CHARGER_CHARGE_INHIBITED; - - rv = rt946x_read8(chgnum, RT946X_REG_CHGFAULT, &val); - if (rv) - return rv; - if (val & RT946X_MASK_CHG_VBATOV) - *status |= CHARGER_VOLTAGE_OR; - - - rv = rt946x_read8(chgnum, RT946X_REG_CHGNTC, &val); - if (rv) - return rv; - val = (val & RT946X_MASK_BATNTC_FAULT) >> RT946X_SHIFT_BATNTC_FAULT; - - switch (val) { - case RT946X_BATTEMP_WARM: - *status |= CHARGER_RES_HOT; - break; - case RT946X_BATTEMP_COOL: - *status |= CHARGER_RES_COLD; - break; - case RT946X_BATTEMP_COLD: - *status |= CHARGER_RES_COLD; - *status |= CHARGER_RES_UR; - break; - case RT946X_BATTEMP_HOT: - *status |= CHARGER_RES_HOT; - *status |= CHARGER_RES_OR; - break; - default: - break; - } - - return EC_SUCCESS; -} - -static enum ec_error_list rt946x_set_mode(int chgnum, int mode) -{ - int rv; - - if (mode & CHARGE_FLAG_POR_RESET) { - rv = rt946x_por_reset(); - if (rv) - return rv; - } - - if (mode & CHARGE_FLAG_RESET_TO_ZERO) { - rv = rt946x_reset_to_zero(chgnum); - if (rv) - return rv; - } - - return EC_SUCCESS; -} - -static enum ec_error_list rt946x_get_current(int chgnum, int *current) -{ - int rv; - int val = 0; - const struct charger_info * const info = rt946x_get_info(chgnum); - - rv = rt946x_read8(chgnum, RT946X_REG_CHGCTRL7, &val); - if (rv) - return rv; - - val = (val & RT946X_MASK_ICHG) >> RT946X_SHIFT_ICHG; - *current = val * info->current_step + info->current_min; - - return EC_SUCCESS; -} - -static enum ec_error_list rt946x_set_current(int chgnum, int current) -{ - int rv; - uint8_t reg_icc; - static int workaround; - const struct charger_info *const info = rt946x_get_info(chgnum); - - /* - * mt6370's minimum regulated current is 500mA REG17[7:2] 0b100, - * values below 0b100 are preserved. - */ - if (IS_ENABLED(CONFIG_CHARGER_MT6370)) - current = MAX(500, current); - -#ifdef CONFIG_CHARGER_MT6370 - rv = mt6370_ichg_workaround(chgnum, current); - if (rv) - return rv; -#endif - - reg_icc = rt946x_closest_reg(info->current_min, info->current_max, - info->current_step, current); - - rv = rt946x_update_bits(chgnum, RT946X_REG_CHGCTRL7, RT946X_MASK_ICHG, - reg_icc << RT946X_SHIFT_ICHG); - if (rv) - return rv; - - if (IS_ENABLED(CONFIG_CHARGER_RT9466) || - IS_ENABLED(CONFIG_CHARGER_MT6370)) { - uint32_t curr_ieoc; - - /* - * workaround to make IEOC accurate: - * witht normal charging (ICC >= 900mA), the power path is fully - * turned on. But at low charging current state (ICC < 900mA), - * the power path will only be partially turned on. So under - * such situation, the IEOC is inaccurate. - */ - rv = rt946x_get_ieoc(chgnum, &curr_ieoc); - if (rv) - return rv; - - if (current < 900 && !workaround) { - /* raise IEOC if charge current is under 900 */ - rv = rt946x_set_ieoc(chgnum, curr_ieoc + 100); - workaround = 1; - } else if (current >= 900 && workaround) { - /* reset IEOC if charge current is above 900 */ - workaround = 0; - rv = rt946x_set_ieoc(chgnum, curr_ieoc - 100); - } - } - - return rv; -} - -static enum ec_error_list rt946x_get_voltage(int chgnum, int *voltage) -{ - int rv; - int val = 0; - const struct charger_info * const info = rt946x_get_info(chgnum); - - rv = rt946x_read8(chgnum, RT946X_REG_CHGCTRL4, &val); - if (rv) - return rv; - - val = (val & RT946X_MASK_CV) >> RT946X_SHIFT_CV; - *voltage = val * info->voltage_step + info->voltage_min; - - return EC_SUCCESS; -} - -static enum ec_error_list rt946x_set_voltage(int chgnum, int voltage) -{ - uint8_t reg_cv = 0; - const struct charger_info * const info = rt946x_get_info(chgnum); - - reg_cv = rt946x_closest_reg(info->voltage_min, info->voltage_max, - info->voltage_step, voltage); - - return rt946x_update_bits(chgnum, RT946X_REG_CHGCTRL4, RT946X_MASK_CV, - reg_cv << RT946X_SHIFT_CV); -} - -static enum ec_error_list rt946x_discharge_on_ac(int chgnum, int enable) -{ - return rt946x_enable_hz(chgnum, enable); -} - -/* Setup sourcing current to prevent overload */ -#ifdef CONFIG_CHARGER_ILIM_PIN_DISABLED -static int rt946x_enable_ilim_pin(int chgnum, int en) -{ - int ret; - - ret = (en ? rt946x_set_bit : rt946x_clr_bit) - (chgnum, RT946X_REG_CHGCTRL3, RT946X_MASK_ILIMEN); - - return ret; -} - -static int rt946x_select_ilmt(int chgnum, enum rt946x_ilmtsel sel) -{ - int ret; - - ret = rt946x_update_bits(chgnum, RT946X_REG_CHGCTRL2, - RT946X_MASK_ILMTSEL, - sel << RT946X_SHIFT_ILMTSEL); - - return ret; -} -#endif /* CONFIG_CHARGER_ILIM_PIN_DISABLED */ - -/* Charging power state initialization */ -static enum ec_error_list rt946x_post_init(int chgnum) -{ -#ifdef CONFIG_CHARGER_ILIM_PIN_DISABLED - int rv; - - rv = rt946x_select_ilmt(chgnum, RT946X_ILMTSEL_AICR); - if (rv) - return rv; - - /* Need 5ms to ramp after choose current limit source */ - msleep(5); - - /* Disable ILIM pin */ - rv = rt946x_enable_ilim_pin(chgnum, 0); - if (rv) - return rv; -#endif - return EC_SUCCESS; -} - -/* Hardware current ramping (aka AICL: Average Input Current Level) */ -#ifdef CONFIG_CHARGE_RAMP_HW -static int rt946x_get_mivr(int chgnum, int *mivr) -{ - int rv; - int val = 0; - - rv = rt946x_read8(chgnum, RT946X_REG_CHGCTRL6, &val); - if (rv) - return rv; - - val = (val & RT946X_MASK_MIVR) >> RT946X_SHIFT_MIVR; - *mivr = val * RT946X_MIVR_STEP + RT946X_MIVR_MIN; - - return EC_SUCCESS; -} - -static int rt946x_set_aicl_vth(int chgnum, uint8_t aicl_vth) -{ - uint8_t reg_aicl_vth = 0; - - reg_aicl_vth = rt946x_closest_reg(RT946X_AICLVTH_MIN, - RT946X_AICLVTH_MAX, RT946X_AICLVTH_STEP, aicl_vth); - - return rt946x_update_bits(chgnum, RT946X_REG_CHGCTRL14, - RT946X_MASK_AICLVTH, - reg_aicl_vth << RT946X_SHIFT_AICLVTH); -} - -static enum ec_error_list rt946x_set_hw_ramp(int chgnum, int enable) -{ - int rv; - unsigned int mivr = 0; - - if (!enable) { - rv = rt946x_clr_bit(chgnum, RT946X_REG_CHGCTRL14, - RT946X_MASK_AICLMEAS); - return rv; - } - - rv = rt946x_get_mivr(chgnum, &mivr); - if (rv < 0) - return rv; - - /* - * Check if there's a suitable AICL_VTH. - * The vendor suggests setting AICL_VTH as (MIVR + 200mV). - */ - if ((mivr + 200) > RT946X_AICLVTH_MAX) { - CPRINTS("mivr(%d) too high", mivr); - return EC_ERROR_INVAL; - } - - rv = rt946x_set_aicl_vth(chgnum, mivr + 200); - if (rv < 0) - return rv; - - return rt946x_set_bit(chgnum, RT946X_REG_CHGCTRL14, - RT946X_MASK_AICLMEAS); -} - -static int rt946x_ramp_is_stable(int chgnum) -{ - int rv; - int val = 0; - - rv = rt946x_read8(chgnum, RT946X_REG_CHGCTRL14, &val); - val = (val & RT946X_MASK_AICLMEAS) >> RT946X_SHIFT_AICLMEAS; - - return (!rv && !val); -} - -static int rt946x_ramp_is_detected(int chgnum) -{ - return 1; -} - -static int rt946x_ramp_get_current_limit(int chgnum) -{ - int rv; - int input_current = 0; - - rv = rt946x_get_input_current_limit(chgnum, &input_current); - - return rv ? -1 : input_current; -} -#endif /* CONFIG_CHARGE_RAMP_HW */ - -static void rt946x_init(int chgnum) -{ - int ret = rt946x_init_setting(chgnum); - - CPRINTS("init%d %s(%d)", chgnum, ret ? "fail" : "good", ret); -} - -#ifdef HAS_TASK_USB_CHG -#ifdef CONFIG_CHARGER_MT6370 -static int mt6370_detect_apple_samsung_ta(int chgnum, int usb_stat) -{ - int ret, reg; - int chg_type = - (usb_stat & MT6370_MASK_USB_STATUS) >> MT6370_SHIFT_USB_STATUS; - int dp_2_3v, dm_2_3v; - - /* Only SDP/CDP/DCP could possibly be Apple/Samsung TA */ - if (chg_type != MT6370_CHG_TYPE_SDPNSTD && - chg_type != MT6370_CHG_TYPE_CDP && - chg_type != MT6370_CHG_TYPE_DCP) - return chg_type; - - if (chg_type == MT6370_CHG_TYPE_SDPNSTD || - chg_type == MT6370_CHG_TYPE_CDP) - if (!(usb_stat & MT6370_MASK_DCD_TIMEOUT)) - return chg_type; - - /* Check D+ > 0.9V */ - ret = rt946x_update_bits(chgnum, MT6370_REG_QCSTATUS2, - MT6360_MASK_CHECK_DPDM, - MT6370_MASK_APP_SS_EN | MT6370_MASK_APP_SS_PL); - ret |= rt946x_read8(chgnum, MT6370_REG_QCSTATUS2, ®); - - if (ret) - return chg_type; - - /* Normal port (D+ < 0.9V) */ - if (!(reg & MT6370_MASK_SS_OUT)) - return chg_type; - - /* Samsung charger (D+ < 1.5V) */ - if (!(reg & MT6370_MASK_APP_OUT)) - return MT6370_CHG_TYPE_SAMSUNG_CHARGER; - - /* Check D+ > 2.3 V */ - ret = rt946x_update_bits(chgnum, MT6370_REG_QCSTATUS2, - MT6360_MASK_CHECK_DPDM, - MT6370_MASK_APP_REF | MT6370_MASK_APP_SS_PL | - MT6370_MASK_APP_SS_EN); - ret |= rt946x_read8(chgnum, MT6370_REG_QCSTATUS2, ®); - dp_2_3v = reg & MT6370_MASK_APP_OUT; - - /* Check D- > 2.3 V */ - ret |= rt946x_update_bits(chgnum, - MT6370_REG_QCSTATUS2, MT6360_MASK_CHECK_DPDM, - MT6370_MASK_APP_REF | MT6370_MASK_APP_DPDM_IN | - MT6370_MASK_APP_SS_PL | MT6370_MASK_APP_SS_EN); - ret |= rt946x_read8(chgnum, MT6370_REG_QCSTATUS2, ®); - dm_2_3v = reg & MT6370_MASK_APP_OUT; - - if (ret) - return chg_type; - - /* Apple charger */ - if (!dp_2_3v && !dm_2_3v) - /* Apple 2.5W charger */ - return MT6370_CHG_TYPE_APPLE_0_5A_CHARGER; - else if (!dp_2_3v && dm_2_3v) - /* Apple 5W charger */ - return MT6370_CHG_TYPE_APPLE_1_0A_CHARGER; - else if (dp_2_3v && !dm_2_3v) - /* Apple 10W charger */ - return MT6370_CHG_TYPE_APPLE_2_1A_CHARGER; - else - /* Apple 12W charger */ - return MT6370_CHG_TYPE_APPLE_2_4A_CHARGER; -} -#endif - -static int mt6370_get_bc12_device_type(int charger_type) -{ - switch (charger_type) { - case MT6370_CHG_TYPE_SDP: - case MT6370_CHG_TYPE_SDPNSTD: - return CHARGE_SUPPLIER_BC12_SDP; - case MT6370_CHG_TYPE_CDP: - return CHARGE_SUPPLIER_BC12_CDP; - case MT6370_CHG_TYPE_DCP: - case MT6370_CHG_TYPE_SAMSUNG_CHARGER: - case MT6370_CHG_TYPE_APPLE_0_5A_CHARGER: - case MT6370_CHG_TYPE_APPLE_1_0A_CHARGER: - case MT6370_CHG_TYPE_APPLE_2_1A_CHARGER: - case MT6370_CHG_TYPE_APPLE_2_4A_CHARGER: - return CHARGE_SUPPLIER_BC12_DCP; - default: - return CHARGE_SUPPLIER_NONE; - } -} - -/* Returns a mt6370 charger_type. */ -static int mt6370_get_charger_type(int chgnum) -{ -#ifdef CONFIG_CHARGER_MT6370 - int reg; - - if (rt946x_read8(chgnum, MT6370_REG_USBSTATUS1, ®)) - return CHARGE_SUPPLIER_NONE; - return mt6370_detect_apple_samsung_ta(chgnum, reg); -#else - return CHARGE_SUPPLIER_NONE; -#endif -} - -/* - * The USB Type-C specification limits the maximum amount of current from BC 1.2 - * suppliers to 1.5A. Technically, proprietary methods are not allowed, but we - * will continue to allow those. - */ -static int mt6370_get_bc12_ilim(int charge_supplier) -{ - switch (charge_supplier) { - case MT6370_CHG_TYPE_APPLE_0_5A_CHARGER: - return 500; - case MT6370_CHG_TYPE_APPLE_1_0A_CHARGER: - return 1000; - case MT6370_CHG_TYPE_APPLE_2_1A_CHARGER: - case MT6370_CHG_TYPE_APPLE_2_4A_CHARGER: - case MT6370_CHG_TYPE_DCP: - case MT6370_CHG_TYPE_CDP: - case MT6370_CHG_TYPE_SAMSUNG_CHARGER: - return USB_CHARGER_MAX_CURR_MA; - case MT6370_CHG_TYPE_SDP: - default: - return USB_CHARGER_MIN_CURR_MA; - } -} - -static int rt946x_get_bc12_device_type(int chgnum, int charger_type) -{ - int reg; - - if (rt946x_read8(chgnum, RT946X_REG_DPDM1, ®)) - return CHARGE_SUPPLIER_NONE; - - switch (reg & RT946X_MASK_BC12_TYPE) { - case RT946X_MASK_SDP: - return CHARGE_SUPPLIER_BC12_SDP; - case RT946X_MASK_CDP: - return CHARGE_SUPPLIER_BC12_CDP; - case RT946X_MASK_DCP: - return CHARGE_SUPPLIER_BC12_DCP; - default: - return CHARGE_SUPPLIER_NONE; - } -} - -static int rt946x_get_bc12_ilim(int charge_supplier) -{ - switch (charge_supplier) { - case CHARGE_SUPPLIER_BC12_DCP: - if (IS_ENABLED(CONFIG_CHARGE_RAMP_SW) || - IS_ENABLED(CONFIG_CHARGE_RAMP_HW)) - /* A conservative value to prevent a bad charger. */ - return RT946X_AICR_TYP2MAX(USB_CHARGER_MAX_CURR_MA); - /* fallback */ - case CHARGE_SUPPLIER_BC12_CDP: - return USB_CHARGER_MAX_CURR_MA; - case CHARGE_SUPPLIER_BC12_SDP: - default: - return USB_CHARGER_MIN_CURR_MA; - } -} - -static void check_ac_state(void) -{ - static uint8_t ac; - - if (ac != extpower_is_present()) { - ac = !ac; - hook_notify(HOOK_AC_CHANGE); - } -} -DECLARE_DEFERRED(check_ac_state); - -void rt946x_interrupt(enum gpio_signal signal) -{ - task_wake(TASK_ID_USB_CHG); - /* - * Generally, VBUS detection can be done immediately when the port - * plug/unplug happens. But if it's a PD plug(and will generate an - * interrupt), then it will take a few milliseconds to raise VBUS - * by PD negotiation. - */ - hook_call_deferred(&check_ac_state_data, 100 * MSEC); -} - -int rt946x_toggle_bc12_detection(void) -{ - int rv; - rv = rt946x_enable_bc12_detection(CHARGER_SOLO, 0); - if (rv) - return rv; - /* mt6370 requires 40us delay to toggle RT946X_MASK_USBCHGEN */ - udelay(40); - return rt946x_enable_bc12_detection(CHARGER_SOLO, 1); -} - -static void check_pd_capable(void) -{ - const int port = TASK_ID_TO_USB_CHG_PORT(TASK_ID_USB_CHG); - - if (!pd_capable(port)) { - enum tcpc_cc_voltage_status cc1, cc2; - - tcpm_get_cc(port, &cc1, &cc2); - /* if CC is not changed. */ - if (cc_is_rp(cc1) || cc_is_rp(cc2)) - rt946x_toggle_bc12_detection(); - } -} -DECLARE_DEFERRED(check_pd_capable); - -static void rt946x_usb_connect(void) -{ - const int port = TASK_ID_TO_USB_CHG_PORT(TASK_ID_USB_CHG); - enum tcpc_cc_voltage_status cc1, cc2; - - tcpm_get_cc(port, &cc1, &cc2); - - /* - * Only detect BC1.2 device when USB-C device recognition is - * finished to prevent a potential race condition with USB enumeration. - * If CC exists RP, then it might be a BC12 or a PD capable device. - * Check this later to ensure it's not PD capable. - */ - if (cc_is_rp(cc1) || cc_is_rp(cc2)) - /* delay extra 50 ms to ensure SrcCap received */ - hook_call_deferred(&check_pd_capable_data, - PD_T_SINK_WAIT_CAP + 50 * MSEC); - hook_call_deferred(&check_ac_state_data, 0); -} -DECLARE_HOOK(HOOK_USB_PD_CONNECT, rt946x_usb_connect, HOOK_PRIO_DEFAULT); - -static void rt946x_pd_disconnect(void) -{ - /* Type-C disconnected, disable deferred check. */ - hook_call_deferred(&check_pd_capable_data, -1); - hook_call_deferred(&check_ac_state_data, 0); -} -DECLARE_HOOK(HOOK_USB_PD_DISCONNECT, rt946x_pd_disconnect, HOOK_PRIO_DEFAULT); - -int rt946x_get_adc(enum rt946x_adc_in_sel adc_sel, int *adc_val) -{ - int rv, i, adc_start, adc_result = 0; - int adc_data_h, adc_data_l, aicr; - const int max_wait_times = 6; - - if (in_interrupt_context()) { - CPRINTS("Err: use ADC in IRQ"); - return EC_ERROR_INVAL; - } - mutex_lock(&adc_access_lock); -#ifdef CONFIG_CHARGER_MT6370 - mt6370_enable_hidden_mode(CHARGER_SOLO, 1); -#endif - - /* Select ADC to desired channel */ - rv = rt946x_update_bits(CHARGER_SOLO, RT946X_REG_CHGADC, - RT946X_MASK_ADC_IN_SEL, - adc_sel << RT946X_SHIFT_ADC_IN_SEL); - if (rv) - goto out; - - if (adc_sel == MT6370_ADC_IBUS) { - rv = charger_get_input_current_limit(CHARGER_SOLO, &aicr); - if (rv) - goto out; - } - - /* Start ADC conversation */ - rv = rt946x_set_bit(CHARGER_SOLO, RT946X_REG_CHGADC, - RT946X_MASK_ADC_START); - if (rv) - goto out; - - for (i = 0; i < max_wait_times; i++) { - msleep(35); - rv = mt6370_pmu_reg_test_bit(CHARGER_SOLO, RT946X_REG_CHGADC, - RT946X_SHIFT_ADC_START, - &adc_start); - if (!adc_start && rv == 0) - break; - } - if (i == max_wait_times) - CPRINTS("conversion fail sel=%d", adc_sel); - - /* Read ADC data */ - rv = rt946x_read8(CHARGER_SOLO, RT946X_REG_ADCDATAH, &adc_data_h); - rv = rt946x_read8(CHARGER_SOLO, RT946X_REG_ADCDATAL, &adc_data_l); - if (rv) - goto out; - -#if defined(CONFIG_CHARGER_RT9466) || defined(CONFIG_CHARGER_RT9467) - if (adc_sel == RT946X_ADC_VBUS_DIV5) - adc_result = ((adc_data_h << 8) | adc_data_l) * 25; - else - CPRINTS("unsupported channel %d", adc_sel); - *adc_val = adc_result; -#elif defined(CONFIG_CHARGER_MT6370) - /* Calculate ADC value */ - adc_result = (adc_data_h * 256 + adc_data_l) - * mt6370_adc_unit[adc_sel] + mt6370_adc_offset[adc_sel]; - - /* For TS_BAT/TS_BUS, the real unit is 0.25, here we use 25(unit) */ - if (adc_sel == MT6370_ADC_TS_BAT) - adc_result /= 100; -#endif - -out: -#ifdef CONFIG_CHARGER_MT6370 - if (adc_sel == MT6370_ADC_IBUS) { - if (aicr < 400) /* 400mA */ - adc_result = adc_result * 67 / 100; - } - - if (adc_sel != MT6370_ADC_TS_BAT && adc_sel != MT6370_ADC_TEMP_JC) - *adc_val = adc_result / 1000; - else - *adc_val = adc_result; - mt6370_enable_hidden_mode(CHARGER_SOLO, 0); -#endif - mutex_unlock(&adc_access_lock); - return rv; -} - -static enum ec_error_list rt946x_get_vbus_voltage(int chgnum, int port, - int *voltage) -{ - int vbus_mv; - int rv; - - rv = rt946x_get_adc(RT946X_ADC_VBUS_DIV5, &vbus_mv); - *voltage = vbus_mv; - - return rv; -} - -#ifdef CONFIG_CHARGER_MT6370 -static int mt6370_toggle_cfo(void) -{ - int rv, data; - - rv = rt946x_read8(CHARGER_SOLO, MT6370_REG_FLEDEN, &data); - if (rv) - return rv; - - if (data & MT6370_STROBE_EN_MASK) - return rv; - - /* read data */ - rv = rt946x_read8(CHARGER_SOLO, RT946X_REG_CHGCTRL2, &data); - if (rv) - return rv; - - /* cfo off */ - data &= ~RT946X_MASK_CFO_EN; - rv = rt946x_write8(CHARGER_SOLO, RT946X_REG_CHGCTRL2, data); - if (rv) - return rv; - - /* cfo on */ - data |= RT946X_MASK_CFO_EN; - return rt946x_write8(CHARGER_SOLO, RT946X_REG_CHGCTRL2, data); -} - -static int mt6370_pmu_chg_mivr_irq_handler(int chgnum) -{ - int rv, ibus = 0, mivr_stat; - - rv = mt6370_pmu_reg_test_bit(chgnum, MT6370_REG_CHGSTAT1, - MT6370_SHIFT_MIVR_STAT, &mivr_stat); - if (rv) - return rv; - - if (!mivr_stat) { - CPRINTS("no mivr stat"); - return rv; - } - - rv = rt946x_get_adc(MT6370_ADC_IBUS, &ibus); - if (rv) - return rv; - - if (ibus < 100) /* 100mA */ - rv = mt6370_toggle_cfo(); - - return rv; -} - -static int mt6370_irq_handler(int chgnum) -{ - int data, mask, ret, reg_val; - int stat_chg, valid_chg, stat_old, stat_new; - - ret = rt946x_write8(chgnum, MT6370_REG_IRQMASK, MT6370_IRQ_MASK_ALL); - if (ret) - return ret; - - ret = rt946x_read8(chgnum, MT6370_REG_IRQIND, ®_val); - if (ret) - return ret; - - /* read stat before reading irq evt */ - ret = rt946x_read8(chgnum, MT6370_REG_CHGSTAT1, &stat_old); - if (ret) - return ret; - - /* workaround for irq, divided irq event into upper and lower */ - ret = rt946x_read8(chgnum, MT6370_REG_CHGIRQ1, &data); - if (ret) - return ret; - - /* read stat after reading irq evt */ - ret = rt946x_read8(chgnum, MT6370_REG_CHGSTAT1, &stat_new); - if (ret) - return ret; - - ret = rt946x_read8(chgnum, MT6370_REG_CHGMASK1, &mask); - if (ret) - return ret; - - ret = rt946x_write8(chgnum, MT6370_REG_IRQMASK, 0x00); - if (ret) - return ret; - - stat_chg = stat_old ^ stat_new; - valid_chg = (stat_new & 0xF1) | (~stat_new & 0xF1); - data |= (stat_chg & valid_chg); - data &= ~mask; - if (data) - ret = mt6370_pmu_chg_mivr_irq_handler(chgnum); - return ret; -} -#endif /* CONFIG_CHARGER_MT6370 */ - -static void rt946x_bc12_workaround(void) -{ - /* - * There is a parasitic capacitance on D+, - * which results in pulling D+ up too slow while detecting BC1.2. - * So we try to fix this in two steps: - * 1. Pull D+ up to a voltage under 0.6V - * 2. re-toggling and pull D+ up to 0.6V (again) - * and then detect the voltage of D-. - */ - rt946x_toggle_bc12_detection(); - msleep(10); - rt946x_toggle_bc12_detection(); -} -DECLARE_DEFERRED(rt946x_bc12_workaround); - -static void rt946x_usb_charger_task(const int unused) -{ - struct charge_port_info chg; - int bc12_type = CHARGE_SUPPLIER_NONE; - int chg_type; - int reg = 0; - int bc12_cnt = 0; - const int max_bc12_cnt = 3; - int voltage; - - chg.voltage = USB_CHARGER_VOLTAGE_MV; - while (1) { -#ifdef CONFIG_CHARGER_MT6370 - mt6370_irq_handler(CHARGER_SOLO); -#endif /* CONFIG_CHARGER_MT6370 */ - - rt946x_read8(CHARGER_SOLO, RT946X_REG_DPDMIRQ, ®); - - /* VBUS attach event */ - if (reg & RT946X_MASK_DPDMIRQ_ATTACH) { - charger_get_vbus_voltage(0, &voltage); - CPRINTS("VBUS attached: %dmV", voltage); - if (IS_ENABLED(CONFIG_CHARGER_MT6370)) { - chg_type = - mt6370_get_charger_type(CHARGER_SOLO); - bc12_type = - mt6370_get_bc12_device_type(chg_type); - chg.current = mt6370_get_bc12_ilim(bc12_type); - } else { - bc12_type = - rt946x_get_bc12_device_type(CHARGER_SOLO, - chg_type); - chg.current = rt946x_get_bc12_ilim(bc12_type); - } - CPRINTS("BC12 type %d", bc12_type); - if (bc12_type == CHARGE_SUPPLIER_NONE) - goto bc12_none; - if (IS_ENABLED(CONFIG_WIRELESS_CHARGER_P9221_R7) && - bc12_type == CHARGE_SUPPLIER_BC12_SDP && - wpc_chip_is_online()) { - p9221_notify_vbus_change(1); - CPRINTS("WPC ON"); - } - if (bc12_type == CHARGE_SUPPLIER_BC12_SDP && - ++bc12_cnt < max_bc12_cnt) { - /* - * defer the workaround and awaiting for - * waken up by the interrupt. - */ - hook_call_deferred( - &rt946x_bc12_workaround_data, 5); - goto wait_event; - } - - charge_manager_update_charge(bc12_type, 0, &chg); -bc12_none: - rt946x_enable_bc12_detection(CHARGER_SOLO, 0); - } - - /* VBUS detach event */ - if (reg & RT946X_MASK_DPDMIRQ_DETACH && - bc12_type != CHARGE_SUPPLIER_NONE) { - CPRINTS("VBUS detached"); - bc12_cnt = 0; -#ifdef CONFIG_WIRELESS_CHARGER_P9221_R7 - p9221_notify_vbus_change(0); -#endif - charge_manager_update_charge(bc12_type, 0, NULL); - } - -wait_event: - task_wait_event(-1); - } -} - -static int rt946x_ramp_allowed(int supplier) -{ - return supplier == CHARGE_SUPPLIER_BC12_DCP; -} - -static int rt946x_ramp_max(int supplier, int sup_curr) -{ - return rt946x_get_bc12_ilim(supplier); -} -#endif /* HAS_TASK_USB_CHG */ - -/* Non-standard interface functions */ - -int rt946x_enable_charger_boost(int en) -{ - return (en ? rt946x_set_bit : rt946x_clr_bit) - (CHARGER_SOLO, RT946X_REG_CHGCTRL2, RT946X_MASK_CHG_EN); -} - -/* - * rt946x reports VBUS ready after VBUS is up for ~500ms. - * Check if this works for the use case before calling this function. - */ -int rt946x_is_vbus_ready(void) -{ - int val = 0; - - return rt946x_read8(CHARGER_SOLO, RT946X_REG_CHGSTATC, &val) ? - 0 : !!(val & RT946X_MASK_PWR_RDY); -} - -int rt946x_is_charge_done(void) -{ - int val = 0; - - if (rt946x_read8(CHARGER_SOLO, RT946X_REG_CHGSTAT, &val)) - return 0; - - val = (val & RT946X_MASK_CHG_STAT) >> RT946X_SHIFT_CHG_STAT; - - return val == RT946X_CHGSTAT_DONE; -} - -int rt946x_cutoff_battery(void) -{ -#ifdef CONFIG_CHARGER_MT6370 -/* - * We should lock ADC usage to prevent from using ADC while - * cut-off. Or this might cause the ADC power not turning off. - */ - - int rv; - - mutex_lock(&adc_access_lock); - rv = rt946x_write8(CHARGER_SOLO, MT6370_REG_RSTPASCODE1, - MT6370_MASK_RSTPASCODE1); - if (rv) - goto out; - - rv = rt946x_write8(CHARGER_SOLO, MT6370_REG_RSTPASCODE2, - MT6370_MASK_RSTPASCODE2); - if (rv) - goto out; - - /* reset all chg/fled/ldo/rgb/bl/db reg and logic */ - rv = rt946x_write8(CHARGER_SOLO, RT946X_REG_CORECTRL2, 0x7F); - if (rv) - goto out; - - /* disable chg auto sensing */ - mt6370_enable_hidden_mode(CHARGER_SOLO, 1); - rv = rt946x_clr_bit(CHARGER_SOLO, MT6370_REG_CHGHIDDENCTRL15, - MT6370_MASK_ADC_TS_AUTO); - mt6370_enable_hidden_mode(CHARGER_SOLO, 0); - if (rv) - goto out; - msleep(50); - /* enter shipping mode */ - rv = rt946x_set_bit(CHARGER_SOLO, RT946X_REG_CHGCTRL2, - RT946X_MASK_SHIP_MODE); - -out: - mutex_unlock(&adc_access_lock); - return rv; -#endif - /* enter shipping mode */ - return rt946x_set_bit(CHARGER_SOLO, RT946X_REG_CHGCTRL2, - RT946X_MASK_SHIP_MODE); -} - -int rt946x_enable_charge_termination(int en) -{ - return (en ? rt946x_set_bit : rt946x_clr_bit) - (CHARGER_SOLO, RT946X_REG_CHGCTRL2, RT946X_MASK_TE); -} - -int rt946x_enable_charge_eoc(int en) -{ - return (en ? rt946x_set_bit : rt946x_clr_bit) - (CHARGER_SOLO, RT946X_REG_CHGCTRL9, RT946X_MASK_EOC); -} - -#ifdef CONFIG_CHARGER_MT6370 -/* MT6370 LDO */ - -int mt6370_set_ldo_voltage(int mv) -{ - int rv; - int vout_val; - const int vout_mask = MT6370_MASK_LDOVOUT_EN | MT6370_MASK_LDOVOUT_VOUT; - - /* LDO output-off mode to floating. */ - rv = rt946x_update_bits(CHARGER_SOLO, MT6370_REG_LDOCFG, - MT6370_MASK_LDOCFG_OMS, 0); - if (rv) - return rv; - - /* Disable LDO if voltage is zero. */ - if (mv == 0) - return rt946x_clr_bit(CHARGER_SOLO, MT6370_REG_LDOVOUT, - MT6370_MASK_LDOVOUT_EN); - - vout_val = 1 << MT6370_SHIFT_LDOVOUT_EN; - vout_val |= rt946x_closest_reg(MT6370_LDO_MIN, MT6370_LDO_MAX, - MT6370_LDO_STEP, mv); - return rt946x_update_bits(CHARGER_SOLO, MT6370_REG_LDOVOUT, vout_mask, - vout_val); -} - -/* MT6370 Display bias */ -int mt6370_db_external_control(int en) -{ - return rt946x_update_bits(CHARGER_SOLO, MT6370_REG_DBCTRL1, - MT6370_MASK_DB_EXT_EN, - en << MT6370_SHIFT_DB_EXT_EN); -} - -int mt6370_db_set_voltages(int vbst, int vpos, int vneg) -{ - int rv; - - /* set display bias VBST */ - rv = rt946x_update_bits(CHARGER_SOLO, MT6370_REG_DBVBST, - MT6370_MASK_DB_VBST, - rt946x_closest_reg(MT6370_DB_VBST_MIN, - MT6370_DB_VBST_MAX, - MT6370_DB_VBST_STEP, vbst)); - - /* set display bias VPOS */ - rv |= rt946x_update_bits(CHARGER_SOLO, MT6370_REG_DBVPOS, - MT6370_MASK_DB_VPOS, - rt946x_closest_reg(MT6370_DB_VPOS_MIN, - MT6370_DB_VPOS_MAX, - MT6370_DB_VPOS_STEP, vpos)); - - /* set display bias VNEG */ - rv |= rt946x_update_bits(CHARGER_SOLO, MT6370_REG_DBVNEG, - MT6370_MASK_DB_VNEG, - rt946x_closest_reg(MT6370_DB_VNEG_MIN, - MT6370_DB_VNEG_MAX, - MT6370_DB_VNEG_STEP, vneg)); - - /* Enable VNEG/VPOS discharge when VNEG/VPOS rails disabled. */ - rv |= rt946x_update_bits(CHARGER_SOLO, - MT6370_REG_DBCTRL2, - MT6370_MASK_DB_VNEG_DISC | MT6370_MASK_DB_VPOS_DISC, - MT6370_MASK_DB_VNEG_DISC | MT6370_MASK_DB_VPOS_DISC); - - return rv; -} - -/* MT6370 BACKLIGHT LED */ - -int mt6370_backlight_set_dim(uint16_t dim) -{ - int rv; - - /* datasheet suggests that update BLDIM2 first then BLDIM */ - rv = rt946x_write8(CHARGER_SOLO, MT6370_BACKLIGHT_BLDIM2, - dim & MT6370_MASK_BLDIM2); - - if (rv) - return rv; - - rv = rt946x_write8(CHARGER_SOLO, MT6370_BACKLIGHT_BLDIM, - (dim >> MT6370_SHIFT_BLDIM_MSB) & MT6370_MASK_BLDIM); - - return rv; -} - -/* MT6370 RGB LED */ - -int mt6370_led_set_dim_mode(enum mt6370_led_index index, - enum mt6370_led_dim_mode mode) -{ - if (index <= MT6370_LED_ID_OFF || index >= MT6370_LED_ID_COUNT) - return EC_ERROR_INVAL; - - rt946x_update_bits(CHARGER_SOLO, MT6370_REG_RGBDIM_BASE + index, - MT6370_MASK_RGB_DIMMODE, - mode << MT6370_SHIFT_RGB_DIMMODE); - return EC_SUCCESS; -} - -int mt6370_led_set_color(uint8_t mask) -{ - return rt946x_update_bits(CHARGER_SOLO, MT6370_REG_RGBEN, - MT6370_MASK_RGB_ISNK_ALL_EN, mask); -} - -int mt6370_led_set_brightness(enum mt6370_led_index index, uint8_t brightness) -{ - if (index >= MT6370_LED_ID_COUNT || index <= MT6370_LED_ID_OFF) - return EC_ERROR_INVAL; - - rt946x_update_bits(CHARGER_SOLO, MT6370_REG_RGBISNK_BASE + index, - MT6370_MASK_RGBISNK_CURSEL, - brightness << MT6370_SHIFT_RGBISNK_CURSEL); - return EC_SUCCESS; -} - -int mt6370_led_set_pwm_dim_duty(enum mt6370_led_index index, uint8_t dim_duty) -{ - if (index >= MT6370_LED_ID_COUNT || index <= MT6370_LED_ID_OFF) - return EC_ERROR_INVAL; - - rt946x_update_bits(CHARGER_SOLO, MT6370_REG_RGBDIM_BASE + index, - MT6370_MASK_RGB_DIMDUTY, - dim_duty << MT6370_SHIFT_RGB_DIMDUTY); - return EC_SUCCESS; -} - -int mt6370_led_set_pwm_frequency(enum mt6370_led_index index, - enum mt6370_led_pwm_freq freq) -{ - if (index >= MT6370_LED_ID_COUNT || index <= MT6370_LED_ID_OFF) - return EC_ERROR_INVAL; - - rt946x_update_bits(CHARGER_SOLO, MT6370_REG_RGBISNK_BASE + index, - MT6370_MASK_RGBISNK_DIMFSEL, - freq << MT6370_SHIFT_RGBISNK_DIMFSEL); - return EC_SUCCESS; -} - -int mt6370_reduce_db_bl_driving(void) -{ - int rv; - - /* Enter test mode */ - rv = rt946x_block_write(CHARGER_SOLO, MT6370_REG_TM_PAS_CODE1, - mt6370_val_en_test_mode, - ARRAY_SIZE(mt6370_val_en_test_mode)); - if (rv) - return rv; - msleep(1); - rv = rt946x_write8(CHARGER_SOLO, MT6370_REG_BANK, MT6370_MASK_REG_TM); - if (rv) - return rv; - msleep(1); - /* reduce bl driving */ - rv = rt946x_update_bits(CHARGER_SOLO, MT6370_TM_REG_BL3, - MT6370_TM_MASK_BL3_SL, MT6370_TM_REDUCE_BL3_SL); - if (rv) - return rv; - msleep(1); - /* reduce db driving */ - rv = rt946x_update_bits(CHARGER_SOLO, MT6370_TM_REG_DSV1, - MT6370_TM_MASK_DSV1_SL, - MT6370_TM_REDUCE_DSV1_SL); - if (rv) - return rv; - msleep(1); - /* Leave test mode */ - return rt946x_write8(CHARGER_SOLO, MT6370_REG_TM_PAS_CODE1, - MT6370_LEAVE_TM); -} -#endif /* CONFIG_CHARGER_MT6370 */ - -const struct charger_drv rt946x_drv = { - .init = &rt946x_init, - .post_init = &rt946x_post_init, - .get_info = &rt946x_get_info, - .get_status = &rt946x_get_status, - .set_mode = &rt946x_set_mode, - .enable_otg_power = &rt946x_enable_otg_power, - .is_sourcing_otg_power = &rt946x_is_sourcing_otg_power, - .get_current = &rt946x_get_current, - .set_current = &rt946x_set_current, - .get_voltage = &rt946x_get_voltage, - .set_voltage = &rt946x_set_voltage, - .discharge_on_ac = &rt946x_discharge_on_ac, - .get_vbus_voltage = &rt946x_get_vbus_voltage, - .set_input_current_limit = &rt946x_set_input_current_limit, - .get_input_current_limit = &rt946x_get_input_current_limit, - .manufacturer_id = &rt946x_manufacturer_id, - .device_id = &rt946x_device_id, - .get_option = &rt946x_get_option, - .set_option = &rt946x_set_option, -#ifdef CONFIG_CHARGE_RAMP_HW - .set_hw_ramp = &rt946x_set_hw_ramp, - .ramp_is_stable = &rt946x_ramp_is_stable, - .ramp_is_detected = &rt946x_ramp_is_detected, - .ramp_get_current_limit = &rt946x_ramp_get_current_limit, -#endif -}; - -#ifdef HAS_TASK_USB_CHG -const struct bc12_drv rt946x_bc12_drv = { - .usb_charger_task = rt946x_usb_charger_task, - .ramp_allowed = rt946x_ramp_allowed, - .ramp_max = rt946x_ramp_max, -}; - -#ifdef CONFIG_BC12_SINGLE_DRIVER -/* provide a default bc12_ports[] for backward compatibility */ -struct bc12_config bc12_ports[CHARGE_PORT_COUNT] = { - [0 ... (CHARGE_PORT_COUNT - 1)] = { - .drv = &rt946x_bc12_drv, - }, -}; -#endif /* CONFIG_BC12_SINGLE_DRIVER */ -#endif diff --git a/driver/charger/rt946x.h b/driver/charger/rt946x.h deleted file mode 100644 index 5e6f9e0223..0000000000 --- a/driver/charger/rt946x.h +++ /dev/null @@ -1,853 +0,0 @@ -/* Copyright 2017 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. - * - * Richtek rt9466/rt9467, Mediatek mt6370 battery charger driver. - */ - -#ifndef __CROS_EC_RT946X_H -#define __CROS_EC_RT946X_H - -/* Registers for rt9466, rt9467 */ -#if defined(CONFIG_CHARGER_RT9466) || defined(CONFIG_CHARGER_RT9467) -#define RT946X_REG_CORECTRL0 0x00 -#define RT946X_REG_CORECTRL_RST RT946X_REG_CORECTRL0 -#define RT946X_REG_CHGCTRL1 0x01 -#define RT946X_REG_CHGCTRL2 0x02 -#define RT946X_REG_CHGCTRL3 0x03 -#define RT946X_REG_CHGCTRL4 0x04 -#define RT946X_REG_CHGCTRL5 0x05 -#define RT946X_REG_CHGCTRL6 0x06 -#define RT946X_REG_CHGCTRL7 0x07 -#define RT946X_REG_CHGCTRL8 0x08 -#define RT946X_REG_CHGCTRL9 0x09 -#define RT946X_REG_CHGCTRL10 0x0A -#define RT946X_REG_CHGCTRL11 0x0B -#define RT946X_REG_CHGCTRL12 0x0C -#define RT946X_REG_CHGCTRL13 0x0D -#define RT946X_REG_CHGCTRL14 0x0E -#define RT946X_REG_CHGCTRL15 0x0F -#define RT946X_REG_CHGCTRL16 0x10 -#define RT946X_REG_CHGADC 0x11 - -#ifdef CONFIG_CHARGER_RT9467 -#define RT946X_REG_DPDM1 0x12 -#define RT946X_REG_DPDM2 0x13 -#define RT946X_REG_DPDM3 0x14 -#endif - -#define RT946X_REG_CHGCTRL19 0x18 -#define RT946X_REG_CHGCTRL17 0x19 -#define RT946X_REG_CHGCTRL18 0x1A -#define RT946X_REG_CHGHIDDENCTRL2 0x21 -#define RT946X_REG_CHGHIDDENCTRL4 0x23 -#define RT946X_REG_CHGHIDDENCTRL6 0x25 -#define RT946X_REG_CHGHIDDENCTRL7 0x26 -#define RT946X_REG_CHGHIDDENCTRL8 0x27 -#define RT946X_REG_CHGHIDDENCTRL9 0x28 -#define RT946X_REG_CHGHIDDENCTRL15 0x2E -#define RT946X_REG_DEVICEID 0x40 -#define RT946X_REG_CHGSTAT 0x42 -#define RT946X_REG_CHGNTC 0x43 -#define RT946X_REG_ADCDATAH 0x44 -#define RT946X_REG_ADCDATAL 0x45 -#define RT946X_REG_CHGSTATC 0x50 -#define RT946X_REG_CHGFAULT 0x51 -#define RT946X_REG_TSSTATC 0x52 -#define RT946X_REG_CHGIRQ1 0x53 -#define RT946X_REG_CHGIRQ2 0x54 -#define RT946X_REG_CHGIRQ3 0x55 - -#ifdef CONFIG_CHARGER_RT9467 -#define RT946X_REG_DPDMIRQ 0x56 -#endif - -#define RT946X_REG_CHGSTATCCTRL 0x60 -#define RT946X_REG_CHGFAULTCTRL 0x61 -#define RT946X_REG_TSSTATCCTRL 0x62 -#define RT946X_REG_CHGIRQ1CTRL 0x63 -#define RT946X_REG_CHGIRQ2CTRL 0x64 -#define RT946X_REG_CHGIRQ3CTRL 0x65 - -#ifdef CONFIG_CHARGER_RT9467 -#define RT946X_REG_DPDMIRQCTRL 0x66 -#endif - -#elif defined(CONFIG_CHARGER_MT6370) -/* Registers for mt6370 */ -#define RT946X_REG_DEVICEID 0x00 -#define RT946X_REG_CORECTRL1 0x01 -#define RT946X_REG_CORECTRL2 0x02 -#define RT946X_REG_CORECTRL_RST RT946X_REG_CORECTRL2 -#define MT6370_REG_RSTPASCODE1 0x03 -#define MT6370_REG_RSTPASCODE2 0x04 -#define MT6370_REG_HIDDENPASCODE1 0x07 -#define MT6370_REG_HIDDENPASCODE2 0x08 -#define MT6370_REG_HIDDENPASCODE3 0x09 -#define MT6370_REG_HIDDENPASCODE4 0x0A -#define MT6370_REG_IRQIND 0x0B -#define MT6370_REG_IRQMASK 0x0C -#define MT6370_REG_OSCCTRL 0x10 -#define RT946X_REG_CHGCTRL1 0x11 -#define RT946X_REG_CHGCTRL2 0x12 -#define RT946X_REG_CHGCTRL3 0x13 -#define RT946X_REG_CHGCTRL4 0x14 -#define RT946X_REG_CHGCTRL5 0x15 -#define RT946X_REG_CHGCTRL6 0x16 -#define RT946X_REG_CHGCTRL7 0x17 -#define RT946X_REG_CHGCTRL8 0x18 -#define RT946X_REG_CHGCTRL9 0x19 -#define RT946X_REG_CHGCTRL10 0x1A -#define RT946X_REG_CHGCTRL11 0x1B -#define RT946X_REG_CHGCTRL12 0x1C -#define RT946X_REG_CHGCTRL13 0x1D -#define RT946X_REG_CHGCTRL14 0x1E -#define RT946X_REG_CHGCTRL15 0x1F -#define RT946X_REG_CHGCTRL16 0x20 -#define RT946X_REG_CHGADC 0x21 -#define MT6370_REG_DEVICETYPE 0x22 -#define RT946X_REG_DPDM1 MT6370_REG_DEVICETYPE -#define MT6370_REG_USBSTATUS1 0x27 -#define MT6370_REG_QCSTATUS2 0x29 -#define RT946X_REG_CHGCTRL17 0X2B -#define RT946X_REG_CHGCTRL18 0X2C -#define RT946X_REG_CHGHIDDENCTRL7 0x36 -#define MT6370_REG_CHGHIDDENCTRL15 0x3E -#define RT946X_REG_CHGSTAT 0X4A -#define RT946X_REG_CHGNTC 0X4B -#define RT946X_REG_ADCDATAH 0X4C -#define RT946X_REG_ADCDATAL 0X4D -/* FLED */ -#define MT6370_REG_FLEDEN 0x7E -/* LDO */ -#define MT6370_REG_LDOCFG 0X80 -#define MT6370_REG_LDOVOUT 0X81 -/* RGB led */ -#define MT6370_REG_RGBDIM_BASE 0x81 -#define MT6370_REG_RGB1DIM 0x82 -#define MT6370_REG_RGB2DIM 0x83 -#define MT6370_REG_RGB3DIM 0x84 -#define MT6370_REG_RGBEN 0x85 -#define MT6370_REG_RGBISNK_BASE 0x85 -#define MT6370_REG_RGB1ISNK 0x86 -#define MT6370_REG_RGB2ISNK 0x87 -#define MT6370_REG_RGB3ISNK 0x88 -#define MT6370_REG_RGBCHRINDDIM 0x92 -#define MT6370_REG_RGBCHRINDCTRL 0x93 - -/* backlight */ -#define MT6370_BACKLIGHT_BLEN 0xA0 -#define MT6370_BACKLIGHT_BLPWM 0xA2 -#define MT6370_BACKLIGHT_BLDIM2 0xA4 -#define MT6370_BACKLIGHT_BLDIM 0xA5 - -/* Display bias */ -#define MT6370_REG_DBCTRL1 0XB0 -#define MT6370_REG_DBCTRL2 0XB1 -#define MT6370_REG_DBVBST 0XB2 -#define MT6370_REG_DBVPOS 0XB3 -#define MT6370_REG_DBVNEG 0XB4 -#define MT6370_REG_CHGIRQ1 0xC0 -#define RT946X_REG_DPDMIRQ 0xC6 - -/* status event */ -#define MT6370_REG_CHGSTAT1 0xD0 -#define RT946X_REG_CHGSTATC MT6370_REG_CHGSTAT1 -#define MT6370_REG_CHGSTAT2 0xD1 -#define RT946X_REG_CHGFAULT MT6370_REG_CHGSTAT2 -#define MT6370_REG_CHGSTAT3 0xD2 -#define MT6370_REG_CHGSTAT4 0xD3 -#define MT6370_REG_CHGSTAT5 0xD4 -#define MT6370_REG_CHGSTAT6 0xD5 -#define MT6370_REG_DPDMSTAT 0xD6 -#define MT6370_REG_DICHGSTAT 0xD7 -#define MT6370_REG_OVPCTRLSTAT 0xD8 -#define MT6370_REG_FLEDSTAT1 0xD9 -#define MT6370_REG_FLEDSTAT2 0xDA -#define MT6370_REG_BASESTAT 0xDB -#define MT6370_REG_LDOSTAT 0xDC -#define MT6370_REG_RGBSTAT 0xDD -#define MT6370_REG_BLSTAT 0xDE -#define MT6370_REG_DBSTAT 0xDF -/* irq mask */ -#define MT6370_REG_CHGMASK1 0xE0 -#define RT946X_REG_CHGSTATCCTRL MT6370_REG_CHGMASK1 -#define MT6370_REG_CHGMASK2 0xE1 -#define MT6370_REG_CHGMASK3 0xE2 -#define MT6370_REG_CHGMASK4 0xE3 -#define MT6370_REG_CHGMASK5 0xE4 -#define MT6370_REG_CHGMASK6 0xE5 -#define MT6370_REG_DPDMMASK1 0xE6 -#define MT6370_REG_DICHGMASK 0xE7 -#define MT6370_REG_OVPCTRLMASK 0xE8 -#define MT6370_REG_FLEDMASK1 0xE9 -#define MT6370_REG_FLEDMASK2 0xEA -#define MT6370_REG_BASEMASK 0xEB -#define MT6370_REG_LDOMASK 0xEC -#define MT6370_REG_RGBMASK 0xED -#define MT6370_REG_BLMASK 0xEE -#define MT6370_REG_DBMASK 0xEF -#define MT6370_REG_TM_PAS_CODE1 0xF0 -#define MT6370_REG_BANK 0xFF -/* TM REGISTER */ -#define MT6370_TM_REG_BL3 0x34 -#define MT6370_TM_REG_DSV1 0x37 -#else -#error "No suitable charger option defined" -#endif - -/* EOC current */ -#define RT946X_IEOC_MIN 100 -#define RT946X_IEOC_MAX 850 -#define RT946X_IEOC_STEP 50 - -/* Minimum Input Voltage Regulator */ -#define RT946X_MIVR_MIN 3900 -#define RT946X_MIVR_MAX 13400 -#define RT946X_MIVR_STEP 100 - -/* Boost voltage */ -#define RT946X_BOOST_VOLTAGE_MIN 4425 -#define RT946X_BOOST_VOLTAGE_MAX 5825 -#define RT946X_BOOST_VOLTAGE_STEP 25 - -/* IR compensation resistor */ -#define RT946X_IRCMP_RES_MIN 0 -#define RT946X_IRCMP_RES_MAX 175 -#define RT946X_IRCMP_RES_STEP 25 - -/* IR compensation voltage clamp */ -#define RT946X_IRCMP_VCLAMP_MIN 0 -#define RT946X_IRCMP_VCLAMP_MAX 224 -#define RT946X_IRCMP_VCLAMP_STEP 32 - -/* Pre-charge mode threshold voltage */ -#define RT946X_VPREC_MIN 2000 -#define RT946X_VPREC_MAX 3500 -#define RT946X_VPREC_STEP 100 - -/* Pre-charge current */ -#define RT946X_IPREC_MIN 100 -#define RT946X_IPREC_MAX 850 -#define RT946X_IPREC_STEP 50 - -/* AICLVTH */ -#define RT946X_AICLVTH_MIN 4100 -#define RT946X_AICLVTH_MAX 4800 -#define RT946X_AICLVTH_STEP 100 - -/* NTC */ -#define RT946X_BATTEMP_NORMAL 0x00 -#define RT946X_BATTEMP_WARM 0x02 -#define RT946X_BATTEMP_COOL 0x03 -#define RT946X_BATTEMP_COLD 0x05 -#define RT946X_BATTEMP_HOT 0x06 - -/* LDO voltage */ -#define MT6370_LDO_MIN 1600 -#define MT6370_LDO_MAX 4000 -#define MT6370_LDO_STEP 200 - -/* ========== CORECTRL0 0x00 ============ */ -#define RT946X_SHIFT_RST 7 -#define RT946X_SHIFT_CHG_RST 6 -#define RT946X_SHIFT_FLED_RST 5 -#define RT946X_SHIFT_LDO_RST 4 -#define RT946X_SHIFT_RGB_RST 3 -#define RT946X_SHIFT_BL_RST 2 -#define RT946X_SHIFT_DB_RST 1 -#define RT946X_SHIFT_REG_RST 0 - -#define RT946X_MASK_RST BIT(RT946X_SHIFT_RST) -#define RT946X_MASK_CHG_RST BIT(RT946X_SHIFT_CHG_RST) -#define RT946X_MASK_FLED_RST BIT(RT946X_SHIFT_FLED_RST) -#define RT946X_MASK_LDO_RST BIT(RT946X_SHIFT_LDO_RST) -#define RT946X_MASK_RGB_RST BIT(RT946X_SHIFT_RGB_RST) -#define RT946X_MASK_BL_RST BIT(RT946X_SHIFT_BL_RST) -#define RT946X_MASK_DB_RST BIT(RT946X_SHIFT_DB_RST) -#define RT946X_MASK_REG_RST BIT(RT946X_SHIFT_REG_RST) -#define RT946X_MASK_SOFT_RST \ - (RT946X_MASK_CHG_RST | RT946X_MASK_FLED_RST | RT946X_MASK_LDO_RST | \ - RT946X_MASK_RGB_RST | RT946X_MASK_BL_RST | RT946X_MASK_DB_RST | \ - RT946X_MASK_REG_RST) - -/* ========== CHGCTRL1 0x01 ============ */ -#define RT946X_SHIFT_OPA_MODE 0 -#define RT946X_SHIFT_HZ_EN 2 -#define RT946X_SHIFT_STAT_EN 4 - -#define RT946X_MASK_OPA_MODE BIT(RT946X_SHIFT_OPA_MODE) -#define RT946X_MASK_HZ_EN BIT(RT946X_SHIFT_HZ_EN) -#define RT946X_MASK_STAT_EN BIT(RT946X_SHIFT_STAT_EN) - -/* ========== CHGCTRL2 0x02 ============ */ -#define RT946X_SHIFT_SHIP_MODE 7 -#define RT946X_SHIFT_TE 4 -#define RT946X_SHIFT_ILMTSEL 2 -#define RT946X_SHIFT_CFO_EN 1 -#define RT946X_SHIFT_CHG_EN 0 - -#define RT946X_MASK_SHIP_MODE BIT(RT946X_SHIFT_SHIP_MODE) -#define RT946X_MASK_TE BIT(RT946X_SHIFT_TE) -#define RT946X_MASK_ILMTSEL (0x3 << RT946X_SHIFT_ILMTSEL) -#define RT946X_MASK_CFO_EN BIT(RT946X_SHIFT_CFO_EN) -#define RT946X_MASK_CHG_EN BIT(RT946X_SHIFT_CHG_EN) - -/* ========== RSTPASCODE1 0x03 (mt6370) ============ */ -#define MT6370_MASK_RSTPASCODE1 0xA9 - -/* ========== CHGCTRL3 0x03 ============ */ -#define RT946X_SHIFT_AICR 2 -#define RT946X_SHIFT_ILIMEN 0 - -#define RT946X_MASK_AICR (0x3F << RT946X_SHIFT_AICR) -#define RT946X_MASK_ILIMEN BIT(RT946X_SHIFT_ILIMEN) - -/* - * The accuracy of AICR is 7%. So if AICR = 2150, - * then Max=2150, Typ=2000, Min=1860. And plus 25 since the AICR - * is 50ma a step. - */ -#define RT946X_AICR_TYP2MAX(x) ((x) * 107 / 100 + 25) - -/* ========== RSTPASCODE2 0x04 (mt6370) ============ */ -#define MT6370_MASK_RSTPASCODE2 0x96 - -/* ========== CHGCTRL4 0x04 ============ */ -#define RT946X_SHIFT_CV 1 - -#define RT946X_MASK_CV 0xFE - -/* ========== CHGCTRL5 0x05 ============ */ -#define RT946X_SHIFT_BOOST_VOLTAGE 2 - -#define RT946X_MASK_BOOST_VOLTAGE 0xFC - -/* ========== CHGCTRL6 0x06 ============ */ -#define RT946X_SHIFT_MIVR 1 - -#define RT946X_MASK_MIVR (0x7F << RT946X_SHIFT_MIVR) - -/* ========== CHGCTRL7 0x07 ============ */ -#define RT946X_SHIFT_ICHG 2 - -#define RT946X_MASK_ICHG (0x3F << RT946X_SHIFT_ICHG) - -/* ========== CHGCTRL8 0x08 ============ */ -#define RT946X_SHIFT_VPREC 4 -#define RT946X_SHIFT_IPREC 0 - -#define RT946X_MASK_VPREC (0xF << RT946X_SHIFT_VPREC) -#define RT946X_MASK_IPREC (0xF << RT946X_SHIFT_IPREC) - -/* ========== CHGCTRL9 0x09 ============ */ -#define RT946X_SHIFT_EOC 3 -#define RT946X_SHIFT_IEOC 4 - -#define RT946X_MASK_EOC BIT(RT946X_SHIFT_EOC) -#define RT946X_MASK_IEOC (0xF << RT946X_SHIFT_IEOC) - -/* ========== CHGCTRL10 0x0A ============ */ -#define RT946X_SHIFT_BOOST_CURRENT 0 - -#define RT946X_MASK_BOOST_CURRENT 0x07 - -/* ========== CHGCTRL12 0x0C ============ */ -#define RT946X_SHIFT_TMR_EN 1 -#define MT6370_IRQ_MASK_ALL 0xFE - -#define RT946X_MASK_TMR_EN BIT(RT946X_SHIFT_TMR_EN) - -/* ========== CHGCTRL13 0x0D ============ */ -#define RT946X_SHIFT_WDT_EN 7 - -#define RT946X_MASK_WDT_EN BIT(RT946X_SHIFT_WDT_EN) - -/* ========== CHGCTRL14 0x0E ============ */ -#define RT946X_SHIFT_AICLMEAS 7 -#define RT946X_SHIFT_AICLVTH 0 - -#define RT946X_MASK_AICLMEAS BIT(RT946X_SHIFT_AICLMEAS) -#define RT946X_MASK_AICLVTH 0x07 - -/* ========== CHGCTRL16 0x10 ============ */ -#define RT946X_SHIFT_JEITA_EN 4 - -#define RT946X_MASK_JEITA_EN BIT(RT946X_SHIFT_JEITA_EN) - -/* ========== CHGADC 0x11 ============ */ -#define RT946X_SHIFT_ADC_IN_SEL 4 -#define RT946X_SHIFT_ADC_START 0 - -#define RT946X_MASK_ADC_IN_SEL (0xF << RT946X_SHIFT_ADC_IN_SEL) -#define RT946X_MASK_ADC_START BIT(RT946X_SHIFT_ADC_START) - -/* ========== CHGDPDM1 0x12 (rt946x) DEVICETYPE 0x22 (mt6370) ============ */ -#define RT946X_SHIFT_USBCHGEN 7 -#define RT946X_SHIFT_DCDTIMEOUT 6 -#define RT946X_SHIFT_DCP 2 -#define RT946X_SHIFT_CDP 1 -#define RT946X_SHIFT_SDP 0 - -#define RT946X_MASK_USBCHGEN BIT(RT946X_SHIFT_USBCHGEN) -#define RT946X_MASK_DCDTIMEOUT BIT(RT946X_SHIFT_DCDTIMEOUT) -#define RT946X_MASK_DCP BIT(RT946X_SHIFT_DCP) -#define RT946X_MASK_CDP BIT(RT946X_SHIFT_CDP) -#define RT946X_MASK_SDP BIT(RT946X_SHIFT_SDP) - -#define RT946X_MASK_BC12_TYPE (RT946X_MASK_DCP | \ - RT946X_MASK_CDP | \ - RT946X_MASK_SDP) - -/* ========== USBSTATUS1 0x27 (mt6370) ============ */ -#define MT6370_SHIFT_DCD_TIMEOUT 2 -#define MT6370_SHIFT_USB_STATUS 4 - -#define MT6370_MASK_USB_STATUS 0x70 - -#define MT6370_CHG_TYPE_NOVBUS 0 -#define MT6370_CHG_TYPE_BUSY 1 -#define MT6370_CHG_TYPE_SDP 2 -#define MT6370_CHG_TYPE_SDPNSTD 3 -#define MT6370_CHG_TYPE_DCP 4 -#define MT6370_CHG_TYPE_CDP 5 -#define MT6370_CHG_TYPE_SAMSUNG_CHARGER 6 -#define MT6370_CHG_TYPE_APPLE_0_5A_CHARGER 7 -#define MT6370_CHG_TYPE_APPLE_1_0A_CHARGER 8 -#define MT6370_CHG_TYPE_APPLE_2_1A_CHARGER 9 -#define MT6370_CHG_TYPE_APPLE_2_4A_CHARGER 10 - -#define MT6370_MASK_DCD_TIMEOUT BIT(MT6370_SHIFT_DCD_TIMEOUT) - -/* ========== QCSTATUS2 0x29 (mt6370) ============ */ -#define MT6370_SHIFT_APP_OUT 5 -#define MT6370_SHIFT_SS_OUT 4 -#define MT6370_SHIFT_APP_REF 3 -#define MT6370_SHIFT_APP_DPDM_IN 2 -#define MT6370_SHIFT_APP_SS_PL 1 -#define MT6370_SHIFT_APP_SS_EN 0 - -#define MT6370_MASK_APP_OUT BIT(MT6370_SHIFT_APP_OUT) -#define MT6370_MASK_SS_OUT BIT(MT6370_SHIFT_SS_OUT) -#define MT6370_MASK_APP_REF BIT(MT6370_SHIFT_APP_REF) -#define MT6370_MASK_APP_DPDM_IN BIT(MT6370_SHIFT_APP_DPDM_IN) -#define MT6370_MASK_APP_SS_PL BIT(MT6370_SHIFT_APP_SS_PL) -#define MT6370_MASK_APP_SS_EN BIT(MT6370_SHIFT_APP_SS_EN) - -#define MT6360_MASK_CHECK_DPDM (MT6370_MASK_APP_SS_EN | \ - MT6370_MASK_APP_SS_PL | \ - MT6370_MASK_APP_DPDM_IN | \ - MT6370_MASK_APP_REF) - -/* ========= CHGHIDDENCTRL7 0x36 (mt6370) ======== */ -#define RT946X_ENABLE_VSYS_PROTECT 0x40 - -#define RT946X_SHIFT_HIDDENCTRL7_VSYS_PROTECT 5 -#define RT946X_MASK_HIDDENCTRL7_VSYS_PROTECT \ - (0x3 << RT946X_SHIFT_HIDDENCTRL7_VSYS_PROTECT) - -/* ========== CHGCTRL18 0x1A ============ */ -#define RT946X_SHIFT_IRCMP_RES 3 -#define RT946X_SHIFT_IRCMP_VCLAMP 0 - -#define RT946X_MASK_IRCMP_RES (0x7 << RT946X_SHIFT_IRCMP_RES) -#define RT946X_MASK_IRCMP_VCLAMP (0x7 << RT946X_SHIFT_IRCMP_VCLAMP) - -/* ========== HIDDEN CTRL15 0x3E ============ */ -#define MT6370_SHIFT_ADC_TS_AUTO 0 -#define MT6370_MASK_ADC_TS_AUTO BIT(MT6370_SHIFT_ADC_TS_AUTO) - -/* ========== DEVICE_ID 0x40 ============ */ -#define RT946X_MASK_VENDOR_ID 0xF0 -#define RT946X_MASK_CHIP_REV 0x0F - -/* ========== CHGSTAT 0x42 ============ */ -#define RT946X_SHIFT_CHG_STAT 6 -#define RT946X_SHIFT_ADC_STAT 0 - -#define RT946X_MASK_CHG_STAT (0x3 << RT946X_SHIFT_CHG_STAT) -#define RT946X_MASK_ADC_STAT BIT(RT946X_SHIFT_ADC_STAT) - -/* ========== CHGNTC 0x43 ============ */ -#define RT946X_SHIFT_BATNTC_FAULT 4 - -#define RT946X_MASK_BATNTC_FAULT 0x70 - -/* ========== CHGSTATC 0x50 (rt946x) ============ */ -#define RT946X_SHIFT_PWR_RDY 7 - -#define RT946X_MASK_PWR_RDY BIT(RT946X_SHIFT_PWR_RDY) - -/* ========== CHGFAULT 0x51 (rt946x) ============ */ -#if defined(CONFIG_CHARGER_RT9466) || defined(CONFIG_CHARGER_RT9467) -#define RT946X_SHIFT_CHG_VSYSUV 4 -#define RT946X_SHIFT_CHG_VSYSOV 5 -#define RT946X_SHIFT_CHG_VBATOV 6 -#define RT946X_SHIFT_CHG_VBUSOV 7 - -#define RT946X_MASK_CHG_VSYSUV BIT(RT946X_SHIFT_CHG_VSYSUV) -#define RT946X_MASK_CHG_VSYSOV BIT(RT946X_SHIFT_CHG_VSYSOV) -#define RT946X_MASK_CHG_VBATOV BIT(RT946X_SHIFT_CHG_VBATOV) -#define RT946X_MASK_CHG_VBUSOV BIT(RT946X_SHIFT_CHG_VBUSOV) -#endif - -/* ========== DPDMIRQ 0x56 ============ */ -#if defined(CONFIG_CHARGER_RT9467) || defined(CONFIG_CHARGER_MT6370) -#define RT946X_SHIFT_DPDMIRQ_DETACH 1 -#define RT946X_SHIFT_DPDMIRQ_ATTACH 0 - -#define RT946X_MASK_DPDMIRQ_DETACH BIT(RT946X_SHIFT_DPDMIRQ_DETACH) -#define RT946X_MASK_DPDMIRQ_ATTACH BIT(RT946X_SHIFT_DPDMIRQ_ATTACH) -#endif - -/* ========== FLED EN 0x7E (mt6370) ============ */ -#define MT6370_STROBE_EN_MASK 0x04 - -/* ========== LDOCFG 0x80 (mt6370) ============ */ -#define MT6370_SHIFT_LDOCFG_OMS 6 - -#define MT6370_MASK_LDOCFG_OMS BIT(MT6370_SHIFT_LDOCFG_OMS) - -/* ========== LDOVOUT 0x81 (mt6370) ============ */ -#define MT6370_SHIFT_LDOVOUT_EN 7 -#define MT6370_SHIFT_LDOVOUT_VOUT 0 - -#define MT6370_MASK_LDOVOUT_EN BIT(MT6370_SHIFT_LDOVOUT_EN) -#define MT6370_MASK_LDOVOUT_VOUT (0xf << MT6370_SHIFT_LDOVOUT_VOUT) - -/* ========== RGBDIM 0x82/0x83/0x84 (mt6370) ============ */ -#define MT6370_LED_PWM_DIMDUTY_MIN 0x00 -#define MT6370_LED_PWM_DIMDUTY_MAX 0x1f - -#define MT6370_SHIFT_RGB_DIMMODE 5 -#define MT6370_SHIFT_RGB_DIMDUTY 0 - -#define MT6370_MASK_RGB_DIMMODE (3 << MT6370_SHIFT_RGB_DIMMODE) -#define MT6370_MASK_RGB_DIMDUTY (0x1f << MT6370_SHIFT_RGB_DIMDUTY) - -/* ========== RGBEN 0x85 (mt6370) ============ */ -#define MT6370_SHIFT_RGB_ISNK1DIM 7 -#define MT6370_SHIFT_RGB_ISNK2DIM 6 -#define MT6370_SHIFT_RGB_ISNK3DIM 5 -#define MT6370_SHIFT_RGB_ISNKDIM_BASE 8 - -#define MT6370_MASK_RGB_ISNK1DIM_EN BIT(MT6370_SHIFT_RGB_ISNK1DIM) -#define MT6370_MASK_RGB_ISNK2DIM_EN BIT(MT6370_SHIFT_RGB_ISNK2DIM) -#define MT6370_MASK_RGB_ISNK3DIM_EN BIT(MT6370_SHIFT_RGB_ISNK3DIM) -#define MT6370_MASK_RGB_ISNK_ALL_EN (MT6370_MASK_RGB_ISNK1DIM_EN | \ - MT6370_MASK_RGB_ISNK2DIM_EN | \ - MT6370_MASK_RGB_ISNK3DIM_EN) - -/* ========== RGB_ISNK 0x86/0x87/0x88 (mt6370) ============ */ -#define MT6370_LED_BRIGHTNESS_MIN 0 -#define MT6370_LED_BRIGHTNESS_MAX 7 - -#define MT6370_SHIFT_RGBISNK_CURSEL 0 -#define MT6370_SHIFT_RGBISNK_DIMFSEL 3 -#define MT6370_MASK_RGBISNK_CURSEL (0x7 << MT6370_SHIFT_RGBISNK_CURSEL) -#define MT6370_MASK_RGBISNK_DIMFSEL (0x7 << MT6370_SHIFT_RGBISNK_DIMFSEL) - -/* ========== DBCTRL1 (mt6370) ============ */ -#define MT6370_SHIFT_DB_EXT_EN 0 -#define MT6370_SHIFT_DB_PERIODIC_FIX 4 -#define MT6370_SHIFT_DB_SINGLE_PIN 5 -#define MT6370_SHIFT_DB_FREQ_PM 6 -#define MT6370_SHIFT_DB_PERIODIC_MODE 7 - -#define MT6370_MASK_DB_EXT_EN 1 -#define MT6370_MASK_DB_PERIODIC_FIX 1 -#define MT6370_MASK_DB_SINGLE_PIN 1 -#define MT6370_MASK_DB_FREQ_PM 1 -#define MT6370_MASK_DB_PERIODIC_MODE 1 - -/* ========== DBCTRL1 (mt6370) ============ */ -#define MT6370_MASK_DB_VNEG_DISC BIT(2) -#define MT6370_MASK_DB_VPOS_DISC BIT(5) - -/* ========== DBVBST (mt6370) ============ */ -#define MT6370_SHIFT_DB_VBST 0 - -#define MT6370_MASK_DB_VBST 0x3f - -#define MT6370_DB_VBST_MAX 6200 -#define MT6370_DB_VBST_MIN 4000 -#define MT6370_DB_VBST_STEP 50 - -/* ========== DBVPOS (mt6370) ============ */ -#define MT6370_SHIFT_DB_VPOS 0 - -#define MT6370_MASK_DB_VPOS 0x3f - -#define MT6370_DB_VPOS_MAX 6000 -#define MT6370_DB_VPOS_MIN 4000 -#define MT6370_DB_VPOS_STEP 50 - -/* ========== DBVNEG (mt6370) ============ */ -#define MT6370_SHIFT_DB_VNEG 0 - -#define MT6370_MASK_DB_VNEG 0x3f - -#define MT6370_DB_VNEG_MAX 6000 -#define MT6370_DB_VNEG_MIN 4000 -#define MT6370_DB_VNEG_STEP 50 - -/* ========== BLEN 0xA0 (mt6370) ============ */ -#define MT6370_SHIFT_BLED_EXT_EN 7 -#define MT6370_SHIFT_BLED_EN 6 -#define MT6370_SHIFT_BLED_1CH_EN 5 -#define MT6370_SHIFT_BLED_2CH_EN 4 -#define MT6370_SHIFT_BLED_3CH_EN 3 -#define MT6370_SHIFT_BLED_4CH_EN 2 -#define MT6370_SHIFT_BLED_CODE 1 -#define MT6370_SHIFT_BLED_CONFIG 0 - -#define MT6370_MASK_BLED_EXT_EN BIT(MT6370_SHIFT_BLED_EXT_EN) -#define MT6370_MASK_BLED_EN BIT(MT6370_SHIFT_BLED_EN) -#define MT6370_MASK_BLED_1CH_EN BIT(MT6370_SHIFT_BLED_1CH_EN) -#define MT6370_MASK_BLED_2CH_EN BIT(MT6370_SHIFT_BLED_2CH_EN) -#define MT6370_MASK_BLED_3CH_EN BIT(MT6370_SHIFT_BLED_3CH_EN) -#define MT6370_MASK_BLED_4CH_EN BIT(MT6370_SHIFT_BLED_4CH_EN) - -#define MT6370_BLED_CODE_LINEAR BIT(MT6370_SHIFT_BLED_CODE) -#define MT6370_BLED_CODE_EXP 0 - -#define MT6370_BLED_CONFIG_ACTIVE_HIGH BIT(MT6370_SHIFT_BLED_CONFIG) -#define MT6370_BLED_CONFIG_ACTIVE_LOW 0 - -/* ========== BLPWM 0xA2 (mt6370) ============ */ -#define MT6370_SHIFT_BLPWM_BLED_PWM 7 - -#define MT6370_MASK_BLPWM_BLED_PWM BIT(MT6370_SHIFT_BLPWM_BLED_PWM) - -/* ========== BLDIM2 0xA4 (mt6370) ============ */ -#define MT6370_MASK_BLDIM2 0x7 - -/* ========== BLDIM 0xA5 (mt6370) ============ */ -#define MT6370_SHIFT_BLDIM_MSB 3 -#define MT6370_MASK_BLDIM 0xff - -#define MT6370_BLDIM_DEFAULT 0x7ff - -/* ========== CHG_IRQ1 0xC0 (mt6370) ============ */ -#define MT6370_SHIFT_MIVR_EVT 6 -#define MT6370_MASK_MIVR_EVT BIT(MT6370_SHIFT_MIVR_EVT) - -/* ========== CHGSTAT2 0xD0 (mt6370) ============ */ -#define MT6370_SHIFT_MIVR_STAT 6 - -/* ========== CHGSTAT2 0xD1 (mt6370) ============ */ -#ifdef CONFIG_CHARGER_MT6370 -#define MT6370_SHIFT_CHG_VBUSOV_STAT 7 -#define MT6370_SHIFT_CHG_VBATOV_STAT 6 - -#define RT946X_MASK_CHG_VBATOV MT6370_SHIFT_CHG_VBATOV_STAT - -#define MT6370_MASK_CHG_VBUSOV_STAT BIT(MT6370_SHIFT_CHG_VBUSOV_STAT) -#define MT6370_MASK_CHG_VBATOV_STAT BIT(MT6370_SHIFT_CHG_VBATOV_STAT) -#endif - -/* ========== TM PAS CODE1 0xF0 (mt6370) ============ */ -#define MT6370_LEAVE_TM 0x00 - -/* ========== BANK REG 0xFF (mt6370) ============ */ -#define MT6370_MASK_REG_TM 0x69 - -/* ========== TM REG 0x34 (mt6370) ============ */ -#define MT6370_TM_MASK_BL3_SL 0xC0 -#define MT6370_TM_REDUCE_BL3_SL 0xC0 - -/* ========== TM REG 0x37 (mt6370) ============ */ -#define MT6370_TM_MASK_DSV1_SL 0xC0 -#define MT6370_TM_REDUCE_DSV1_SL 0x00 - -/* ADC unit/offset */ -#define MT6370_ADC_UNIT_VBUS_DIV5 25000 /* uV */ -#define MT6370_ADC_UNIT_VBUS_DIV2 10000 /* uV */ -#define MT6370_ADC_UNIT_VSYS 5000 /* uV */ -#define MT6370_ADC_UNIT_VBAT 5000 /* uV */ -#define MT6370_ADC_UNIT_TS_BAT 25 /* 0.01% */ -#define MT6370_ADC_UNIT_IBUS 50000 /* uA */ -#define MT6370_ADC_UNIT_IBAT 50000 /* uA */ -#define MT6370_ADC_UNIT_CHG_VDDP 5000 /* uV */ -#define MT6370_ADC_UNIT_TEMP_JC 2 /* degree */ - -#define MT6370_ADC_OFFSET_VBUS_DIV5 0 /* mV */ -#define MT6370_ADC_OFFSET_VBUS_DIV2 0 /* mV */ -#define MT6370_ADC_OFFSET_VSYS 0 /* mV */ -#define MT6370_ADC_OFFSET_VBAT 0 /* mV */ -#define MT6370_ADC_OFFSET_TS_BAT 0 /* % */ -#define MT6370_ADC_OFFSET_IBUS 0 /* mA */ -#define MT6370_ADC_OFFSET_IBAT 0 /* mA */ -#define MT6370_ADC_OFFSET_CHG_VDDP 0 /* mV */ -#define MT6370_ADC_OFFSET_TEMP_JC (-40) /* degree */ - -/* ========== Variant-specific configuration ============ */ -#if defined(CONFIG_CHARGER_RT9466) - #define RT946X_CHARGER_NAME "rt9466" - #define RT946X_VENDOR_ID 0x80 - #define RT946X_ADDR_FLAGS 0x53 -#elif defined(CONFIG_CHARGER_RT9467) - #define RT946X_CHARGER_NAME "rt9467" - #define RT946X_VENDOR_ID 0x90 - #define RT946X_ADDR_FLAGS 0x5B -#elif defined(CONFIG_CHARGER_MT6370) - #define RT946X_CHARGER_NAME "mt6370" - #define RT946X_VENDOR_ID 0xE0 - #define RT946X_ADDR_FLAGS 0x34 -#else - #error "No suitable charger option defined" -#endif - -/* RT946x specific interface functions */ - -/* Power on reset */ -int rt946x_por_reset(void); - -/* Interrupt handler for rt946x */ -void rt946x_interrupt(enum gpio_signal signal); - -/* Enable/Disable rt946x (in charger or boost mode) */ -int rt946x_enable_charger_boost(int en); - -/* - * Return 1 if VBUS is ready, which means - * UVLO < VBUS < VOVP && VBUS > BATS + VSLP - */ -int rt946x_is_vbus_ready(void); - -/* Return 1 if rt946x triggers charge termination due to full charge. */ -int rt946x_is_charge_done(void); - -/* - * Cut off the battery (force BATFET to turn off). - * Return 0 if it succeeds. - */ -int rt946x_cutoff_battery(void); - -/* Enable/Disable charge temination */ -int rt946x_enable_charge_termination(int en); - -/* Enable/Disable charge EOC */ -int rt946x_enable_charge_eoc(int en); - -enum rt946x_adc_in_sel { - RT946X_ADC_VBUS_DIV5 = 1, - RT946X_ADC_VBUS_DIV2, - MT6370_ADC_TS_BAT = 6, - MT6370_ADC_IBUS = 8, - MT6370_ADC_TEMP_JC = 12, - MT6370_ADC_MAX, -}; - -/** - * Read ADC channels - * - * @param adc_sel The ADC channel - * @param adc_val The read value - * @return EC_SUCCESS or EC_ERROR_* - */ -int rt946x_get_adc(enum rt946x_adc_in_sel adc_sel, int *adc_val); - -/** - * Toggle BC12 detection - * - * @return EC_SUCCESS or EC_ERROR_* - */ -int rt946x_toggle_bc12_detection(void); - -struct rt946x_init_setting { - uint16_t eoc_current; - uint16_t mivr; - uint16_t ircmp_vclamp; - uint16_t ircmp_res; - uint16_t boost_voltage; - uint16_t boost_current; -}; - -#ifdef CONFIG_CHARGER_MT6370 - -/* - * Set LDO voltage. - * Disable LDO if voltage is zero. - */ -int mt6370_set_ldo_voltage(int mv); - -enum mt6370_led_index { - MT6370_LED_ID_OFF = 0, - MT6370_LED_ID1 = 1, - MT6370_LED_ID2 = 2, - MT6370_LED_ID3 = 3, - MT6370_LED_ID_COUNT, /* The bound of the ID indexes. */ -}; - -enum mt6370_led_dim_mode { - MT6370_LED_DIM_MODE_PWM = 0, - MT6370_LED_DIM_MODE_BREATH = 1, - MT6370_LED_DIM_MODE_REGISTER = 3 -}; - -enum mt6370_led_pwm_freq { - MT6370_LED_PWM_FREQ01 = 0, /* 0.1 Hz */ - MT6370_LED_PWM_FREQ02 = 1, /* 0.2 Hz */ - MT6370_LED_PWM_FREQ05 = 2, /* 0.5 Hz */ - MT6370_LED_PWM_FREQ1 = 3, /* 1 Hz */ - MT6370_LED_PWM_FREQ2 = 4, /* 2 Hz */ - MT6370_LED_PWM_FREQ5 = 5, /* 5 Hz */ - MT6370_LED_PWM_FREQ200 = 6, /* 200 Hz */ - MT6370_LED_PWM_FREQ1000 = 7 /* 1000 Hz */ -}; - -/* Enable display bias external pin control. */ -int mt6370_db_external_control(int en); - -/** - * Set backlight LED dim. - * - * dim: A value from 0 to 2047. - * return: EC_SUCCESS on success, and EC_ERROR_* otherwise. - */ -int mt6370_backlight_set_dim(uint16_t dim); - -/** - * MT6370 display bias voltage settings. - * - * Set disaply bias voltages for the panel. - * - * vbst: VBST config in mv. - * vpos: VPOS config in mv. - * vneg: VNEG config in mv. - * return: EC_SUCCESS on succes, and EC_ERROR_* otherwise. - */ -int mt6370_db_set_voltages(int vbst, int vpos, int vneg); - -/* Set LED brightness */ -int mt6370_led_set_brightness(enum mt6370_led_index index, uint8_t brightness); - -/** - * Set LED Color - * - * mask: Bitmap indicating 1=on 0=off for each LED. 000 = all off. - * Combination of MT6370_MASK_RGB_ISNK1/2/3DIM_EN. - * return: EC_SUCCESS or EC_ERROR_* on error. - */ -int mt6370_led_set_color(uint8_t mask); - -/* Set LED dim mode, available modes: REGISTER, PWM, BREATH. */ -int mt6370_led_set_dim_mode(enum mt6370_led_index index, - enum mt6370_led_dim_mode mode); - -/* Set LED PWM mode duty */ -int mt6370_led_set_pwm_dim_duty(enum mt6370_led_index index, uint8_t dim_duty); - -/* Set LED PWM mode frequency */ -int mt6370_led_set_pwm_frequency(enum mt6370_led_index index, - enum mt6370_led_pwm_freq freq); - -/* Reduce mt6370 DB and BL driving capacity */ -int mt6370_reduce_db_bl_driving(void); -#endif - -extern const struct charger_drv rt946x_drv; -extern const struct bc12_drv rt946x_bc12_drv; - -#endif /* __CROS_EC_RT946X_H */ diff --git a/driver/charger/sm5803.c b/driver/charger/sm5803.c deleted file mode 100644 index 460dcf4093..0000000000 --- a/driver/charger/sm5803.c +++ /dev/null @@ -1,1933 +0,0 @@ -/* Copyright 2020 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. - * - * Silicon Mitus SM5803 Buck-Boost Charger - */ -#include "atomic.h" -#include "battery.h" -#include "battery_smart.h" -#include "charge_state_v2.h" -#include "charger.h" -#include "extpower.h" -#include "gpio.h" -#include "hooks.h" -#include "i2c.h" -#include "sm5803.h" -#include "system.h" -#include "stdbool.h" -#include "throttle_ap.h" -#include "timer.h" -#include "usb_charge.h" -#include "usb_pd.h" -#include "usbc_ocp.h" -#include "util.h" -#include "watchdog.h" - -#ifndef CONFIG_CHARGER_NARROW_VDC -#error "SM5803 is a NVDC charger, please enable CONFIG_CHARGER_NARROW_VDC." -#endif - -/* Console output macros */ -#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args) -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) - -#define UNKNOWN_DEV_ID -1 -static int dev_id = UNKNOWN_DEV_ID; - -static const struct charger_info sm5803_charger_info = { - .name = CHARGER_NAME, - .voltage_max = CHARGE_V_MAX, - .voltage_min = CHARGE_V_MIN, - .voltage_step = CHARGE_V_STEP, - .current_max = CHARGE_I_MAX, - .current_min = CHARGE_I_MIN, - .current_step = CHARGE_I_STEP, - .input_current_max = INPUT_I_MAX, - .input_current_min = INPUT_I_MIN, - .input_current_step = INPUT_I_STEP, -}; - -static uint32_t irq_pending; /* Bitmask of chips with interrupts pending */ - -static struct mutex flow1_access_lock[CHARGER_NUM]; -static struct mutex flow2_access_lock[CHARGER_NUM]; - -static int charger_vbus[CHARGER_NUM]; - -/* Tracker for charging failures per port */ -struct { - int count; - timestamp_t time; -} failure_tracker[CHARGER_NUM] = {}; - -/* Port to restart charging on */ -static int active_restart_port = CHARGE_PORT_NONE; - -/* - * If powered from the sub board port, we need to attempt to enable the BFET - * before proceeding with charging. - */ -static int attempt_bfet_enable; - -/* - * Note if auto fast charge for the primary port is disabled due to a - * disconnected battery, at re-enable auto fast charge later when the battery - * has connected. - */ -static bool fast_charge_disabled; - - -#define CHARGING_FAILURE_MAX_COUNT 5 -#define CHARGING_FAILURE_INTERVAL MINUTE - -static int sm5803_is_sourcing_otg_power(int chgnum, int port); -static enum ec_error_list sm5803_get_dev_id(int chgnum, int *id); -static enum ec_error_list sm5803_set_current(int chgnum, int current); - -static inline enum ec_error_list chg_read8(int chgnum, int offset, int *value) -{ - return i2c_read8(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - offset, value); -} - -static inline enum ec_error_list chg_write8(int chgnum, int offset, int value) -{ - return i2c_write8(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - offset, value); -} - -static inline enum ec_error_list meas_read8(int chgnum, int offset, int *value) -{ - return i2c_read8(chg_chips[chgnum].i2c_port, - SM5803_ADDR_MEAS_FLAGS, - offset, value); -} - -static inline enum ec_error_list meas_write8(int chgnum, int offset, int value) -{ - return i2c_write8(chg_chips[chgnum].i2c_port, - SM5803_ADDR_MEAS_FLAGS, - offset, value); -} - -static inline enum ec_error_list main_read8(int chgnum, int offset, int *value) -{ - return i2c_read8(chg_chips[chgnum].i2c_port, - SM5803_ADDR_MAIN_FLAGS, - offset, value); -} - -static inline enum ec_error_list main_write8(int chgnum, int offset, int value) -{ - return i2c_write8(chg_chips[chgnum].i2c_port, - SM5803_ADDR_MAIN_FLAGS, - offset, value); -} - -static inline enum ec_error_list test_write8(int chgnum, int offset, int value) -{ - return i2c_write8(chg_chips[chgnum].i2c_port, - SM5803_ADDR_TEST_FLAGS, - offset, value); -} - -static inline enum ec_error_list test_update8(int chgnum, const int offset, - const uint8_t mask, - const enum mask_update_action action) -{ - return i2c_update8(chg_chips[chgnum].i2c_port, - SM5803_ADDR_TEST_FLAGS, offset, mask, action); -} - -static enum ec_error_list sm5803_flow1_update(int chgnum, const uint8_t mask, - const enum mask_update_action action) -{ - int rv; - - /* Safety checks done, onto the actual register update */ - mutex_lock(&flow1_access_lock[chgnum]); - - rv = i2c_update8(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - SM5803_REG_FLOW1, - mask, action); - - mutex_unlock(&flow1_access_lock[chgnum]); - - return rv; -} - -static enum ec_error_list sm5803_flow2_update(int chgnum, const uint8_t mask, - const enum mask_update_action action) -{ - int rv; - - mutex_lock(&flow2_access_lock[chgnum]); - - rv = i2c_update8(chg_chips[chgnum].i2c_port, - chg_chips[chgnum].i2c_addr_flags, - SM5803_REG_FLOW2, - mask, action); - - mutex_unlock(&flow2_access_lock[chgnum]); - - return rv; -} - -static bool is_platform_id_2s(uint32_t platform_id) -{ - return platform_id >= 0x06 && platform_id <= 0x0D; -} - -static bool is_platform_id_3s(uint32_t platform_id) -{ - return platform_id >= 0x0E && platform_id <= 0x16; -} - -int sm5803_is_vbus_present(int chgnum) -{ - return charger_vbus[chgnum]; -} - -enum ec_error_list sm5803_configure_gpio0(int chgnum, - enum sm5803_gpio0_modes mode, int od) -{ - enum ec_error_list rv; - int reg; - - rv = main_read8(chgnum, SM5803_REG_GPIO0_CTRL, ®); - if (rv) - return rv; - - reg &= ~SM5803_GPIO0_MODE_MASK; - reg |= mode << 1; - - if (od) - reg |= SM5803_GPIO0_OPEN_DRAIN_EN; - else - reg &= ~SM5803_GPIO0_OPEN_DRAIN_EN; - - rv = main_write8(chgnum, SM5803_REG_GPIO0_CTRL, reg); - return rv; -} - -enum ec_error_list sm5803_set_gpio0_level(int chgnum, int level) -{ - enum ec_error_list rv; - int reg; - - rv = main_read8(chgnum, SM5803_REG_GPIO0_CTRL, ®); - if (rv) - return rv; - - if (level) - reg |= SM5803_GPIO0_VAL; - else - reg &= ~SM5803_GPIO0_VAL; - - rv = main_write8(chgnum, SM5803_REG_GPIO0_CTRL, reg); - return rv; -} - -enum ec_error_list sm5803_configure_chg_det_od(int chgnum, int enable) -{ - enum ec_error_list rv; - int reg; - - rv = main_read8(chgnum, SM5803_REG_GPIO0_CTRL, ®); - if (rv) - return rv; - - if (enable) - reg |= SM5803_CHG_DET_OPEN_DRAIN_EN; - else - reg &= ~SM5803_CHG_DET_OPEN_DRAIN_EN; - - rv = main_write8(chgnum, SM5803_REG_GPIO0_CTRL, reg); - return rv; -} - -enum ec_error_list sm5803_get_chg_det(int chgnum, int *chg_det) -{ - enum ec_error_list rv; - int reg; - - rv = main_read8(chgnum, SM5803_REG_STATUS1, ®); - if (rv) - return rv; - - *chg_det = (reg & SM5803_STATUS1_CHG_DET) != 0; - - return EC_SUCCESS; -} - -enum ec_error_list sm5803_set_vbus_disch(int chgnum, int enable) -{ - enum ec_error_list rv; - int reg; - - rv = main_read8(chgnum, SM5803_REG_PORTS_CTRL, ®); - if (rv) - return rv; - - if (enable) - reg |= SM5803_PORTS_VBUS_DISCH; - else - reg &= ~SM5803_PORTS_VBUS_DISCH; - - rv = main_write8(chgnum, SM5803_REG_PORTS_CTRL, reg); - return rv; -} - -enum ec_error_list sm5803_vbus_sink_enable(int chgnum, int enable) -{ - enum ec_error_list rv; - int regval; - - rv = sm5803_get_dev_id(chgnum, &dev_id); - if (rv) - return rv; - - if (enable) { - if (chgnum == CHARGER_PRIMARY) { - /* Magic for new silicon */ - if (dev_id >= 3) { - rv |= main_write8(chgnum, 0x1F, 0x1); - rv |= test_write8(chgnum, 0x44, 0x2); - rv |= main_write8(chgnum, 0x1F, 0); - } - /* - * Only enable auto fast charge when a battery is - * connected and out of cutoff. - */ - if (battery_get_disconnect_state() == - BATTERY_NOT_DISCONNECTED) { - rv = sm5803_flow2_update(chgnum, - SM5803_FLOW2_AUTO_ENABLED, - MASK_SET); - fast_charge_disabled = false; - } else { - rv = sm5803_flow2_update(chgnum, - SM5803_FLOW2_AUTO_TRKL_EN | - SM5803_FLOW2_AUTO_PRECHG_EN, - MASK_SET); - fast_charge_disabled = true; - } - } else { - if (dev_id >= 3) { - /* Touch of magic on the primary charger */ - rv |= main_write8(CHARGER_PRIMARY, 0x1F, 0x1); - rv |= test_write8(CHARGER_PRIMARY, 0x44, 0x20); - rv |= main_write8(CHARGER_PRIMARY, 0x1F, 0x0); - - /* - * Disable linear, pre-charge, and linear fast - * charge for primary charger. - */ - rv = chg_read8(CHARGER_PRIMARY, - SM5803_REG_FLOW3, ®val); - regval &= ~(BIT(6) | BIT(5) | BIT(4)); - - rv |= chg_write8(CHARGER_PRIMARY, - SM5803_REG_FLOW3, regval); - } - } - - /* Last but not least, enable sinking */ - rv |= sm5803_flow1_update(chgnum, CHARGER_MODE_SINK, MASK_SET); - } else { - if (chgnum == CHARGER_PRIMARY) - rv |= sm5803_flow2_update(chgnum, - SM5803_FLOW2_AUTO_ENABLED, - MASK_CLR); - - if (chgnum == CHARGER_SECONDARY) { - rv |= sm5803_flow1_update(CHARGER_PRIMARY, - SM5803_FLOW1_LINEAR_CHARGE_EN, - MASK_CLR); - - rv = chg_read8(CHARGER_PRIMARY, SM5803_REG_FLOW3, - ®val); - regval &= ~(BIT(6) | BIT(5) | BIT(4)); - rv |= chg_write8(CHARGER_PRIMARY, SM5803_REG_FLOW3, - regval); - } - - - /* Disable sink mode, unless currently sourcing out */ - if (!sm5803_is_sourcing_otg_power(chgnum, chgnum)) - rv |= sm5803_flow1_update(chgnum, CHARGER_MODE_SINK, - MASK_CLR); - } - - return rv; - -} - -/* - * Track and store whether we've initialized the charger chips already on this - * boot. This should prevent us from re-running inits after sysjumps. - */ -static bool chip_inited[CHARGER_NUM]; -#define SM5803_SYSJUMP_TAG 0x534D /* SM */ -#define SM5803_HOOK_VERSION 1 - -static void init_status_preserve(void) -{ - system_add_jump_tag(SM5803_SYSJUMP_TAG, SM5803_HOOK_VERSION, - sizeof(chip_inited), &chip_inited); -} -DECLARE_HOOK(HOOK_SYSJUMP, init_status_preserve, HOOK_PRIO_DEFAULT); - -static void init_status_retrieve(void) -{ - const uint8_t *tag_contents; - int version, size; - - tag_contents = system_get_jump_tag(SM5803_SYSJUMP_TAG, - &version, &size); - if (tag_contents && (version == SM5803_HOOK_VERSION) && - (size == sizeof(chip_inited))) - /* Valid init status found, restore before charger chip init */ - memcpy(&chip_inited, tag_contents, size); -} -DECLARE_HOOK(HOOK_INIT, init_status_retrieve, HOOK_PRIO_FIRST); - -static void sm5803_init(int chgnum) -{ - enum ec_error_list rv; - int reg; - int vbus_mv; - const struct battery_info *batt_info; - int pre_term; - int cells; - - /* - * If a charger is not currently present, disable switching per OCPC - * requirements - */ - rv = charger_get_vbus_voltage(chgnum, &vbus_mv); - if (rv == EC_SUCCESS) { - if (vbus_mv < 4000) { - /* - * No charger connected, disable CHG_EN - * (note other bits default to 0) - */ - rv = chg_write8(chgnum, SM5803_REG_FLOW1, 0); - } else if (!sm5803_is_sourcing_otg_power(chgnum, chgnum)) { - charger_vbus[chgnum] = 1; - } - } else { - CPRINTS("%s %d: Failed to read VBUS voltage during init", - CHARGER_NAME, chgnum); - return; - } - - /* - * A previous boot already ran inits, safe to return now that we've - * checked i2c communication to the chip and cached Vbus presence - */ - if (chip_inited[chgnum]) { - CPRINTS("%s %d: Already initialized", CHARGER_NAME, chgnum); - return; - } - - rv |= charger_device_id(®); - if (reg == 0x02) { - /* --- Special register init --- - * For early silicon (ID 2) with 3S batteries - */ - rv |= main_write8(chgnum, 0x20, 0x08); - rv |= main_write8(chgnum, 0x30, 0xC0); - rv |= main_write8(chgnum, 0x80, 0x01); - - rv |= meas_write8(chgnum, 0x08, 0xC2); - - rv |= chg_write8(chgnum, 0x1D, 0x40); - rv |= chg_write8(chgnum, 0x1F, 0x09); - - rv |= chg_write8(chgnum, 0x22, 0xB3); - rv |= chg_write8(chgnum, 0x23, 0x81); - rv |= chg_write8(chgnum, 0x28, 0xB7); - - rv |= chg_write8(chgnum, 0x4A, 0x82); - rv |= chg_write8(chgnum, 0x4B, 0xA3); - rv |= chg_write8(chgnum, 0x4C, 0xA8); - rv |= chg_write8(chgnum, 0x4D, 0xCA); - rv |= chg_write8(chgnum, 0x4E, 0x07); - rv |= chg_write8(chgnum, 0x4F, 0xFF); - - rv |= chg_write8(chgnum, 0x50, 0x98); - rv |= chg_write8(chgnum, 0x51, 0x00); - rv |= chg_write8(chgnum, 0x52, 0x77); - rv |= chg_write8(chgnum, 0x53, 0xD2); - rv |= chg_write8(chgnum, 0x54, 0x02); - rv |= chg_write8(chgnum, 0x55, 0xD1); - rv |= chg_write8(chgnum, 0x56, 0x7F); - rv |= chg_write8(chgnum, 0x57, 0x02); - rv |= chg_write8(chgnum, 0x58, 0xD1); - rv |= chg_write8(chgnum, 0x59, 0x7F); - rv |= chg_write8(chgnum, 0x5A, 0x13); - rv |= chg_write8(chgnum, 0x5B, 0x50); - rv |= chg_write8(chgnum, 0x5C, 0x5B); - rv |= chg_write8(chgnum, 0x5D, 0xB0); - rv |= chg_write8(chgnum, 0x5E, 0x3C); - rv |= chg_write8(chgnum, 0x5F, 0x3C); - - rv |= chg_write8(chgnum, 0x60, 0x44); - rv |= chg_write8(chgnum, 0x61, 0x20); - rv |= chg_write8(chgnum, 0x65, 0x35); - rv |= chg_write8(chgnum, 0x66, 0x29); - rv |= chg_write8(chgnum, 0x67, 0x64); - rv |= chg_write8(chgnum, 0x68, 0x88); - rv |= chg_write8(chgnum, 0x69, 0xC7); - - /* Inits to access page 0x37 and enable trickle charging */ - rv |= main_write8(chgnum, 0x1F, 0x01); - rv |= test_update8(chgnum, 0x8E, BIT(5), MASK_SET); - rv |= main_write8(chgnum, 0x1F, 0x00); - } else if (reg == 0x03) { - uint32_t platform_id; - - rv = main_read8(chgnum, SM5803_REG_PLATFORM, &platform_id); - if (rv) { - CPRINTS("%s %d: Failed to read platform during init", - CHARGER_NAME, chgnum); - return; - } - platform_id &= SM5803_PLATFORM_ID; - - if (is_platform_id_3s(platform_id)) { - /* 3S Battery inits */ - /* set 13.3V VBAT_SNSP TH GPADC THRESHOLD*/ - rv |= meas_write8(chgnum, 0x26, - SM5803_VBAT_SNSP_MAXTH_3S_LEVEL); - /* OV_VBAT HW second level (14.1V) */ - rv |= chg_write8(chgnum, 0x21, - SM5803_VBAT_PWR_MINTH_3S_LEVEL); - rv |= main_write8(chgnum, 0x30, 0xC0); - rv |= main_write8(chgnum, 0x80, 0x01); - rv |= main_write8(chgnum, 0x1A, 0x08); - - rv |= meas_write8(chgnum, 0x08, 0xC2); - - rv |= chg_write8(chgnum, 0x1D, 0x40); - - rv |= chg_write8(chgnum, 0x22, 0xB3); - - rv |= chg_write8(chgnum, 0x3E, 0x3C); - - rv |= chg_write8(chgnum, 0x4B, 0xA6); - rv |= chg_write8(chgnum, 0x4F, 0xBF); - - rv |= chg_write8(chgnum, 0x52, 0x77); - rv |= chg_write8(chgnum, 0x53, 0xD2); - rv |= chg_write8(chgnum, 0x54, 0x02); - rv |= chg_write8(chgnum, 0x55, 0xD1); - rv |= chg_write8(chgnum, 0x56, 0x7F); - rv |= chg_write8(chgnum, 0x57, 0x01); - rv |= chg_write8(chgnum, 0x58, 0x50); - rv |= chg_write8(chgnum, 0x59, 0x7F); - rv |= chg_write8(chgnum, 0x5A, 0x13); - rv |= chg_write8(chgnum, 0x5B, 0x50); - rv |= chg_write8(chgnum, 0x5D, 0xB0); - - rv |= chg_write8(chgnum, 0x60, 0x44); - rv |= chg_write8(chgnum, 0x65, 0x35); - rv |= chg_write8(chgnum, 0x66, 0x29); - - rv |= chg_write8(chgnum, 0x7D, 0x67); - rv |= chg_write8(chgnum, 0x7E, 0x04); - - rv |= chg_write8(chgnum, 0x33, 0x3C); - - rv |= chg_write8(chgnum, 0x5C, 0x7A); - } else if (is_platform_id_2s(platform_id)) { - /* 2S Battery inits */ - - /* - * Set 9V as higher threshold for VBATSNSP_MAX_TH GPADC - * threshold for interrupt generation. - */ - rv |= meas_write8(chgnum, 0x26, - SM5803_VBAT_SNSP_MAXTH_2S_LEVEL); - - /* Set OV_VBAT HW second level threshold as 9.4V */ - rv |= chg_write8(chgnum, 0x21, - SM5803_VBAT_PWR_MINTH_2S_LEVEL); - - rv |= main_write8(chgnum, 0x30, 0xC0); - rv |= main_write8(chgnum, 0x80, 0x01); - rv |= main_write8(chgnum, 0x1A, 0x08); - - rv |= meas_write8(chgnum, 0x08, 0xC2); - - rv |= chg_write8(chgnum, 0x1D, 0x40); - - rv |= chg_write8(chgnum, 0x22, 0xB3); - - rv |= chg_write8(chgnum, 0x3E, 0x3C); - - rv |= chg_write8(chgnum, 0x4F, 0xBF); - - rv |= chg_write8(chgnum, 0x52, 0x77); - rv |= chg_write8(chgnum, 0x53, 0xD2); - rv |= chg_write8(chgnum, 0x54, 0x02); - rv |= chg_write8(chgnum, 0x55, 0xD1); - rv |= chg_write8(chgnum, 0x56, 0x7F); - rv |= chg_write8(chgnum, 0x57, 0x01); - rv |= chg_write8(chgnum, 0x58, 0x50); - rv |= chg_write8(chgnum, 0x59, 0x7F); - rv |= chg_write8(chgnum, 0x5A, 0x13); - rv |= chg_write8(chgnum, 0x5B, 0x52); - rv |= chg_write8(chgnum, 0x5D, 0xD0); - - rv |= chg_write8(chgnum, 0x60, 0x44); - rv |= chg_write8(chgnum, 0x65, 0x35); - rv |= chg_write8(chgnum, 0x66, 0x29); - - rv |= chg_write8(chgnum, 0x7D, 0x97); - rv |= chg_write8(chgnum, 0x7E, 0x07); - - rv |= chg_write8(chgnum, 0x33, 0x3C); - - rv |= chg_write8(chgnum, 0x5C, 0x7A); - } - - rv |= chg_write8(chgnum, 0x73, 0x22); - rv |= chg_write8(chgnum, 0x50, 0x88); - rv |= chg_read8(chgnum, 0x34, ®); - reg |= BIT(7); - rv |= chg_write8(chgnum, 0x34, reg); - rv |= main_write8(chgnum, 0x1F, 0x1); - rv |= test_write8(chgnum, 0x43, 0x10); - rv |= test_write8(chgnum, 0x47, 0x10); - rv |= test_write8(chgnum, 0x48, 0x04); - rv |= main_write8(chgnum, 0x1F, 0x0); - } - - /* Enable LDO bits */ - rv |= main_read8(chgnum, SM5803_REG_REFERENCE, ®); - reg &= ~(BIT(0) | BIT(1)); - rv |= main_write8(chgnum, SM5803_REG_REFERENCE, reg); - - /* Set a higher clock speed in case it was lowered for z-state */ - rv |= main_read8(chgnum, SM5803_REG_CLOCK_SEL, ®); - reg &= ~SM5803_CLOCK_SEL_LOW; - rv |= main_write8(chgnum, SM5803_REG_CLOCK_SEL, reg); - - /* - * Turn on GPADCs to default. Enable the IBAT_CHG ADC in order to - * measure battery current and calculate system resistance. - */ - reg = SM5803_GPADCC1_TINT_EN | - SM5803_GPADCC1_VSYS_EN | - SM5803_GPADCC1_VCHGPWR_EN | - SM5803_GPADCC1_VBUS_EN | - SM5803_GPADCC1_IBAT_CHG_EN | - SM5803_GPADCC1_IBAT_DIS_EN | - SM5803_GPADCC1_VBATSNSP_EN; - rv |= meas_write8(chgnum, SM5803_REG_GPADC_CONFIG1, reg); - - /* Enable Psys DAC */ - rv |= meas_read8(chgnum, SM5803_REG_PSYS1, ®); - reg |= SM5803_PSYS1_DAC_EN; - rv |= meas_write8(chgnum, SM5803_REG_PSYS1, reg); - - /* Enable ADC sigma delta */ - rv |= chg_read8(chgnum, SM5803_REG_CC_CONFIG1, ®); - reg |= SM5803_CC_CONFIG1_SD_PWRUP; - rv |= chg_write8(chgnum, SM5803_REG_CC_CONFIG1, reg); - - /* Enable PROCHOT comparators except Ibus */ - rv |= chg_read8(chgnum, SM5803_REG_PHOT1, ®); - reg |= SM5803_PHOT1_COMPARATOR_EN; - reg &= ~SM5803_PHOT1_IBUS_PHOT_COMP_EN; - rv |= chg_write8(chgnum, SM5803_REG_PHOT1, reg); - - /* Set DPM Voltage to 4200 mv, see b:172173517 */ - reg = SM5803_VOLTAGE_TO_REG(4200); - rv = chg_write8(chgnum, SM5803_REG_DPM_VL_SET_MSB, (reg >> 3)); - rv |= chg_write8(chgnum, SM5803_REG_DPM_VL_SET_LSB, (reg & 0x7)); - - /* Set default input current */ - reg = SM5803_CURRENT_TO_REG(CONFIG_CHARGER_INPUT_CURRENT) - & SM5803_CHG_ILIM_RAW; - rv |= chg_write8(chgnum, SM5803_REG_CHG_ILIM, reg); - - /* Configure charger insertion interrupts */ - rv |= main_write8(chgnum, SM5803_REG_INT1_EN, SM5803_INT1_CHG); - /* Enable end of charge interrupts for logging */ - rv |= main_write8(chgnum, SM5803_REG_INT4_EN, SM5803_INT4_CHG_FAIL | - SM5803_INT4_CHG_DONE | - SM5803_INT4_OTG_FAIL); - - /* Set TINT interrupts for higher threshold 360 K */ - rv |= meas_write8(chgnum, SM5803_REG_TINT_HIGH_TH, - SM5803_TINT_HIGH_LEVEL); - /* - * Set TINT interrupts for lower threshold to 0 when not - * throttled to prevent trigger interrupts continually - */ - rv |= meas_write8(chgnum, SM5803_REG_TINT_LOW_TH, - SM5803_TINT_MIN_LEVEL); - - /* - * Configure VBAT_SNSP high interrupt to fire after thresholds are set. - */ - rv |= main_read8(chgnum, SM5803_REG_INT2_EN, ®); - reg |= SM5803_INT2_VBATSNSP; - rv |= main_write8(chgnum, SM5803_REG_INT2_EN, reg); - - - /* Configure TINT interrupts to fire after thresholds are set */ - rv |= main_write8(chgnum, SM5803_REG_INT2_EN, SM5803_INT2_TINT); - - /* - * Configure CHG_ENABLE to only be set through I2C by setting - * HOST_MODE_EN bit (all other register bits are 0 by default) - */ - rv |= chg_write8(chgnum, SM5803_REG_FLOW2, SM5803_FLOW2_HOST_MODE_EN); - - if (chgnum == CHARGER_PRIMARY) { - int ibat_eoc_ma; - - /* Set end of fast charge threshold */ - batt_info = battery_get_info(); - ibat_eoc_ma = batt_info->precharge_current - 50; - ibat_eoc_ma /= 100; - ibat_eoc_ma = CLAMP(ibat_eoc_ma, 0, SM5803_CONF5_IBAT_EOC_TH); - rv |= chg_read8(chgnum, SM5803_REG_FAST_CONF5, ®); - reg &= ~SM5803_CONF5_IBAT_EOC_TH; - reg |= ibat_eoc_ma; - rv |= chg_write8(CHARGER_PRIMARY, SM5803_REG_FAST_CONF5, reg); - - /* Setup the proper precharge thresholds. */ - cells = batt_info->voltage_max / 4; - pre_term = batt_info->voltage_min / cells; - pre_term /= 100; /* Convert to decivolts. */ - pre_term = CLAMP(pre_term, SM5803_VBAT_PRE_TERM_MIN_DV, - SM5803_VBAT_PRE_TERM_MAX_DV); - pre_term -= SM5803_VBAT_PRE_TERM_MIN_DV; /* Convert to regval */ - - rv |= chg_read8(chgnum, SM5803_REG_PRE_FAST_CONF_REG1, ®); - reg &= ~SM5803_VBAT_PRE_TERM; - reg |= pre_term << SM5803_VBAT_PRE_TERM_SHIFT; - rv |= chg_write8(chgnum, SM5803_REG_PRE_FAST_CONF_REG1, reg); - - /* - * Set up precharge current - * Note it is preferred to under-shoot the precharge current - * requested. Upper bits of this register are read/write 1 to - * clear - */ - reg = SM5803_CURRENT_TO_REG(batt_info->precharge_current); - reg = MIN(reg, SM5803_PRECHG_ICHG_PRE_SET); - rv |= chg_write8(chgnum, SM5803_REG_PRECHG, reg); - - /* - * Set up BFET alerts - * - * We'll set the soft limit at 1.5W and the hard limit at 6W. - * - * The register is 29.2 mW per bit. - */ - reg = (1500 * 10) / 292; - rv |= meas_write8(chgnum, SM5803_REG_BFET_PWR_MAX_TH, reg); - reg = (6000 * 10) / 292; - rv |= meas_write8(chgnum, SM5803_REG_BFET_PWR_HWSAFE_MAX_TH, - reg); - rv |= main_read8(chgnum, SM5803_REG_INT3_EN, ®); - reg |= SM5803_INT3_BFET_PWR_LIMIT | - SM5803_INT3_BFET_PWR_HWSAFE_LIMIT; - rv |= main_write8(chgnum, SM5803_REG_INT3_EN, reg); - - rv |= chg_read8(chgnum, SM5803_REG_FLOW3, ®); - reg &= ~SM5803_FLOW3_SWITCH_BCK_BST; - rv |= chg_write8(chgnum, SM5803_REG_FLOW3, reg); - - rv |= chg_read8(chgnum, SM5803_REG_SWITCHER_CONF, ®); - reg |= SM5803_SW_BCK_BST_CONF_AUTO; - rv |= chg_write8(chgnum, SM5803_REG_SWITCHER_CONF, reg); - } - - if (rv) - CPRINTS("%s %d: Failed initialization", CHARGER_NAME, chgnum); - else - chip_inited[chgnum] = true; -} - -static enum ec_error_list sm5803_post_init(int chgnum) -{ - /* Nothing to do, charger is always powered */ - return EC_SUCCESS; -} - -void sm5803_hibernate(int chgnum) -{ - enum ec_error_list rv; - int reg; - - rv = main_read8(chgnum, SM5803_REG_REFERENCE, ®); - if (rv) { - CPRINTS("%s %d: Failed to read REFERENCE reg", CHARGER_NAME, - chgnum); - return; - } - - /* Disable LDO bits - note the primary LDO should not be disabled */ - if (chgnum != CHARGER_PRIMARY) { - reg |= (BIT(0) | BIT(1)); - rv |= main_write8(chgnum, SM5803_REG_REFERENCE, reg); - } - - /* Slow the clock speed */ - rv |= main_read8(chgnum, SM5803_REG_CLOCK_SEL, ®); - reg |= SM5803_CLOCK_SEL_LOW; - rv |= main_write8(chgnum, SM5803_REG_CLOCK_SEL, reg); - - /* Turn off GPADCs */ - rv |= meas_write8(chgnum, SM5803_REG_GPADC_CONFIG1, 0); - rv |= meas_write8(chgnum, SM5803_REG_GPADC_CONFIG2, 0); - - /* Disable Psys DAC */ - rv |= meas_read8(chgnum, SM5803_REG_PSYS1, ®); - reg &= ~SM5803_PSYS1_DAC_EN; - rv |= meas_write8(chgnum, SM5803_REG_PSYS1, reg); - - /* Disable ADC sigma delta */ - rv |= chg_read8(chgnum, SM5803_REG_CC_CONFIG1, ®); - reg &= ~SM5803_CC_CONFIG1_SD_PWRUP; - rv |= chg_write8(chgnum, SM5803_REG_CC_CONFIG1, reg); - - /* Disable PROCHOT comparators */ - rv |= chg_read8(chgnum, SM5803_REG_PHOT1, ®); - reg &= ~SM5803_PHOT1_COMPARATOR_EN; - rv |= chg_write8(chgnum, SM5803_REG_PHOT1, reg); - - if (rv) - CPRINTS("%s %d: Failed to set hibernate", CHARGER_NAME, chgnum); -} - -static void sm5803_disable_runtime_low_power_mode(void) -{ - enum ec_error_list rv; - int reg; - int chgnum = TASK_ID_TO_PD_PORT(task_get_current()); - - CPRINTS("%s %d: disable runtime low power mode", CHARGER_NAME, chgnum); - rv = main_read8(chgnum, SM5803_REG_REFERENCE, ®); - if (rv) { - CPRINTS("%s %d: Failed to read REFERENCE reg", CHARGER_NAME, - chgnum); - return; - } - /* Set a higher clock speed */ - rv |= main_read8(chgnum, SM5803_REG_CLOCK_SEL, ®); - reg &= ~SM5803_CLOCK_SEL_LOW; - rv |= main_write8(chgnum, SM5803_REG_CLOCK_SEL, reg); - - /* Enable ADC sigma delta */ - rv |= chg_read8(chgnum, SM5803_REG_CC_CONFIG1, ®); - reg |= SM5803_CC_CONFIG1_SD_PWRUP; - rv |= chg_write8(chgnum, SM5803_REG_CC_CONFIG1, reg); - - if (rv) - CPRINTS("%s %d: Failed to set in disable runtime LPM", - CHARGER_NAME, chgnum); -} -DECLARE_HOOK(HOOK_USB_PD_CONNECT, - sm5803_disable_runtime_low_power_mode, - HOOK_PRIO_FIRST); - -static enum ec_error_list sm5803_enable_linear_charge(int chgnum, bool enable) -{ - int rv; - int regval; - const struct battery_info *batt_info; - - if (enable) { - /* - * We need to wait for the BFET enable attempt to complete, - * otherwise we may end up disabling linear charge. - */ - if (!attempt_bfet_enable) - return EC_ERROR_TRY_AGAIN; - rv = main_write8(chgnum, 0x1F, 0x1); - rv |= test_write8(chgnum, 0x44, 0x20); - rv |= main_write8(chgnum, 0x1F, 0); - - /* - * Precharge thresholds have already been set up as a part of - * init, however set fast charge current equal to the precharge - * current in case the battery moves beyond that threshold. - */ - batt_info = battery_get_info(); - rv |= sm5803_set_current(CHARGER_PRIMARY, - batt_info->precharge_current); - - /* Enable linear charge mode. */ - rv |= sm5803_flow1_update(chgnum, - SM5803_FLOW1_LINEAR_CHARGE_EN, - MASK_SET); - rv |= chg_read8(chgnum, SM5803_REG_FLOW3, ®val); - regval |= BIT(6) | BIT(5) | BIT(4); - rv |= chg_write8(chgnum, SM5803_REG_FLOW3, regval); - } else { - rv = sm5803_flow1_update(chgnum, - SM5803_FLOW1_LINEAR_CHARGE_EN, - MASK_CLR); - rv |= sm5803_flow2_update(chgnum, - SM5803_FLOW2_AUTO_ENABLED, - MASK_CLR); - rv |= chg_read8(chgnum, SM5803_REG_FLOW3, ®val); - regval &= ~(BIT(6) | BIT(5) | BIT(4) | - SM5803_FLOW3_SWITCH_BCK_BST); - rv |= chg_write8(chgnum, SM5803_REG_FLOW3, regval); - rv |= chg_read8(chgnum, SM5803_REG_SWITCHER_CONF, ®val); - regval |= SM5803_SW_BCK_BST_CONF_AUTO; - rv |= chg_write8(chgnum, SM5803_REG_SWITCHER_CONF, regval); - } - - return rv; -} - -static void sm5803_enable_runtime_low_power_mode(void) -{ - enum ec_error_list rv; - int reg; - int chgnum = TASK_ID_TO_PD_PORT(task_get_current()); - - CPRINTS("%s %d: enable runtime low power mode", CHARGER_NAME, chgnum); - rv = main_read8(chgnum, SM5803_REG_REFERENCE, ®); - if (rv) { - CPRINTS("%s %d: Failed to read REFERENCE reg", CHARGER_NAME, - chgnum); - return; - } - /* Slow the clock speed */ - rv |= main_read8(chgnum, SM5803_REG_CLOCK_SEL, ®); - reg |= SM5803_CLOCK_SEL_LOW; - rv |= main_write8(chgnum, SM5803_REG_CLOCK_SEL, reg); - - /* Disable ADC sigma delta */ - rv |= chg_read8(chgnum, SM5803_REG_CC_CONFIG1, ®); - reg &= ~SM5803_CC_CONFIG1_SD_PWRUP; - rv |= chg_write8(chgnum, SM5803_REG_CC_CONFIG1, reg); - - /* If the system is off, all PROCHOT comparators may be turned off */ - if (chipset_in_state(CHIPSET_STATE_ANY_OFF | - CHIPSET_STATE_ANY_SUSPEND)) { - rv |= chg_read8(chgnum, SM5803_REG_PHOT1, ®); - reg &= ~SM5803_PHOT1_COMPARATOR_EN; - rv |= chg_write8(chgnum, SM5803_REG_PHOT1, reg); - } - - if (rv) - CPRINTS("%s %d: Failed to set in enable runtime LPM", - CHARGER_NAME, chgnum); -} -DECLARE_HOOK(HOOK_USB_PD_DISCONNECT, - sm5803_enable_runtime_low_power_mode, - HOOK_PRIO_LAST); - -void sm5803_disable_low_power_mode(int chgnum) -{ - enum ec_error_list rv; - int reg; - - CPRINTS("%s %d: disable low power mode", CHARGER_NAME, chgnum); - rv = main_read8(chgnum, SM5803_REG_REFERENCE, ®); - if (rv) { - CPRINTS("%s %d: Failed to read REFERENCE reg", CHARGER_NAME, - chgnum); - return; - } - /* Enable Psys DAC */ - rv |= meas_read8(chgnum, SM5803_REG_PSYS1, ®); - reg |= SM5803_PSYS1_DAC_EN; - rv |= meas_write8(chgnum, SM5803_REG_PSYS1, reg); - - /* Enable PROCHOT comparators except Ibus */ - rv |= chg_read8(chgnum, SM5803_REG_PHOT1, ®); - reg |= SM5803_PHOT1_COMPARATOR_EN; - reg &= ~SM5803_PHOT1_IBUS_PHOT_COMP_EN; - rv |= chg_write8(chgnum, SM5803_REG_PHOT1, reg); - - if (rv) - CPRINTS("%s %d: Failed to set in disable low power mode", - CHARGER_NAME, chgnum); -} - -void sm5803_enable_low_power_mode(int chgnum) -{ - enum ec_error_list rv; - int reg; - - CPRINTS("%s %d: enable low power mode", CHARGER_NAME, chgnum); - rv = main_read8(chgnum, SM5803_REG_REFERENCE, ®); - if (rv) { - CPRINTS("%s %d: Failed to read REFERENCE reg", CHARGER_NAME, - chgnum); - return; - } - /* Disable Psys DAC */ - rv |= meas_read8(chgnum, SM5803_REG_PSYS1, ®); - reg &= ~SM5803_PSYS1_DAC_EN; - rv |= meas_write8(chgnum, SM5803_REG_PSYS1, reg); - - /* - * Disable all PROCHOT comparators only if port is inactive. Vbus - * sourcing requires that the Vbus comparator be enabled, and it - * cannot be enabled from HOOK_USB_PD_CONNECT since that is - * called after Vbus has turned on. - */ - rv |= chg_read8(chgnum, SM5803_REG_PHOT1, ®); - reg &= ~SM5803_PHOT1_COMPARATOR_EN; - if (pd_is_connected(chgnum)) - reg |= SM5803_PHOT1_VBUS_MON_EN; - rv |= chg_write8(chgnum, SM5803_REG_PHOT1, reg); - - - if (rv) - CPRINTS("%s %d: Failed to set in enable low power mode", - CHARGER_NAME, chgnum); -} - -/* - * Restart charging on the active port, if it's still active and it hasn't - * exceeded our maximum number of restarts. - */ -void sm5803_restart_charging(void) -{ - int act_chg = charge_manager_get_active_charge_port(); - timestamp_t now = get_time(); - - if (act_chg == active_restart_port) { - if (timestamp_expired(failure_tracker[act_chg].time, &now)) { - /* - * Enough time has passed since our last failure, - * restart the timing and count from now. - */ - failure_tracker[act_chg].time.val = now.val + - CHARGING_FAILURE_INTERVAL; - failure_tracker[act_chg].count = 1; - - sm5803_vbus_sink_enable(act_chg, 1); - } else if (++failure_tracker[act_chg].count > - CHARGING_FAILURE_MAX_COUNT) { - CPRINTS("%s %d: Exceeded charging failure retries", - CHARGER_NAME, act_chg); - } else { - sm5803_vbus_sink_enable(act_chg, 1); - } - } - - active_restart_port = CHARGE_PORT_NONE; -} -DECLARE_DEFERRED(sm5803_restart_charging); - -/* - * Process interrupt registers and report any Vbus changes. Alert the AP if the - * charger has become too hot. - */ -void sm5803_handle_interrupt(int chgnum) -{ - enum ec_error_list rv; - int int_reg, meas_reg; - static bool throttled; - struct batt_params bp; - int act_chg, val; - - /* Note: Interrupt registers are clear on read */ - rv = main_read8(chgnum, SM5803_REG_INT1_REQ, &int_reg); - if (rv) { - CPRINTS("%s %d: Failed read int1 register", CHARGER_NAME, - chgnum); - return; - } - - if (int_reg & SM5803_INT1_CHG) { - rv = main_read8(chgnum, SM5803_REG_STATUS1, &meas_reg); - if (!(meas_reg & SM5803_STATUS1_CHG_DET)) { - charger_vbus[chgnum] = 0; - if (IS_ENABLED(CONFIG_USB_CHARGER)) - usb_charger_vbus_change(chgnum, 0); - } else { - charger_vbus[chgnum] = 1; - if (IS_ENABLED(CONFIG_USB_CHARGER)) - usb_charger_vbus_change(chgnum, 1); - } - board_check_extpower(); - } - - rv = main_read8(chgnum, SM5803_REG_INT2_REQ, &int_reg); - if (rv) { - CPRINTS("%s %d: Failed read int2 register", CHARGER_NAME, - chgnum); - return; - } - - if (int_reg & SM5803_INT2_TINT) { - rv = meas_read8(chgnum, SM5803_REG_TINT_MEAS_MSB, &meas_reg); - if ((meas_reg <= SM5803_TINT_LOW_LEVEL) && throttled) { - throttled = false; - throttle_ap(THROTTLE_OFF, THROTTLE_HARD, - THROTTLE_SRC_THERMAL); - /* - * Set back higher threshold to 360 K and set lower - * threshold to 0. - */ - rv |= meas_write8(chgnum, SM5803_REG_TINT_LOW_TH, - SM5803_TINT_MIN_LEVEL); - rv |= meas_write8(chgnum, SM5803_REG_TINT_HIGH_TH, - SM5803_TINT_HIGH_LEVEL); - } else if (meas_reg >= SM5803_TINT_HIGH_LEVEL) { - throttled = true; - throttle_ap(THROTTLE_ON, THROTTLE_HARD, - THROTTLE_SRC_THERMAL); - /* - * Set back lower threshold to 330 K and set higher - * threshold to maximum. - */ - rv |= meas_write8(chgnum, SM5803_REG_TINT_HIGH_TH, - SM5803_TINT_MAX_LEVEL); - rv |= meas_write8(chgnum, SM5803_REG_TINT_LOW_TH, - SM5803_TINT_LOW_LEVEL); - } - /* - * If the interrupt came in and we're not currently throttling - * or the level is below the upper threshold, it can likely be - * ignored. - */ - } - - if (int_reg & SM5803_INT2_VBATSNSP) { - int meas_volt; - uint32_t platform_id; - - rv = main_read8(chgnum, SM5803_REG_PLATFORM, &platform_id); - if (rv) { - CPRINTS("%s %d: Failed to read platform in interrupt", - CHARGER_NAME, chgnum); - return; - } - platform_id &= SM5803_PLATFORM_ID; - act_chg = charge_manager_get_active_charge_port(); - rv = meas_read8(CHARGER_PRIMARY, - SM5803_REG_VBATSNSP_MEAS_MSB, - &meas_reg); - if (rv) - return; - meas_volt = meas_reg << 2; - rv = meas_read8(CHARGER_PRIMARY, - SM5803_REG_VBATSNSP_MEAS_LSB, - &meas_reg); - if (rv) - return; - meas_volt |= meas_reg & 0x03; - rv = meas_read8(CHARGER_PRIMARY, - SM5803_REG_VBATSNSP_MAX_TH, &meas_reg); - if (rv) - return; - - if (is_platform_id_2s(platform_id)) { - /* 2S Battery */ - CPRINTS("%s %d : VBAT_SNSP_HIGH_TH: %d mV ! - " - "VBAT %d mV", - CHARGER_NAME, CHARGER_PRIMARY, - meas_reg * 408/10, - meas_volt * 102/10); - } - - if (is_platform_id_3s(platform_id)) { - /* 3S Battery */ - CPRINTS("%s %d : VBAT_SNSP_HIGH_TH: %d mV ! " - "- VBAT %d mV", - CHARGER_NAME, CHARGER_PRIMARY, - meas_reg * 616/10, - meas_volt * 154/10); - } - - /* Set Vbat Threshold to Max value to re-arm the interrupt */ - rv = meas_write8(CHARGER_PRIMARY, - SM5803_REG_VBATSNSP_MAX_TH, 0xFF); - - /* Disable battery charge */ - rv |= sm5803_flow1_update(chgnum, CHARGER_MODE_DISABLED, - MASK_CLR); - if (is_platform_id_2s(platform_id)) { - /* 2S battery: set VBAT_SENSP TH 9V */ - rv |= meas_write8(CHARGER_PRIMARY, - SM5803_REG_VBATSNSP_MAX_TH, - SM5803_VBAT_SNSP_MAXTH_2S_LEVEL); - } - if (is_platform_id_3s(platform_id)) { - /* 3S battery: set VBAT_SENSP TH 13.3V */ - rv |= meas_write8(CHARGER_PRIMARY, - SM5803_REG_VBATSNSP_MAX_TH, - SM5803_VBAT_SNSP_MAXTH_3S_LEVEL); - } - - active_restart_port = act_chg; - hook_call_deferred(&sm5803_restart_charging_data, 1 * SECOND); - } - - /* TODO(b/159376384): Take action on fatal BFET power alert. */ - rv = main_read8(chgnum, SM5803_REG_INT3_REQ, &int_reg); - if (rv) { - CPRINTS("%s %d: Failed to read int3 register", CHARGER_NAME, - chgnum); - return; - } - - if ((int_reg & SM5803_INT3_BFET_PWR_LIMIT) || - (int_reg & SM5803_INT3_BFET_PWR_HWSAFE_LIMIT)) { - battery_get_params(&bp); - act_chg = charge_manager_get_active_charge_port(); - CPRINTS("%s BFET power limit reached! (%s)", CHARGER_NAME, - (int_reg & SM5803_INT3_BFET_PWR_LIMIT) ? "warn" : - "FATAL"); - CPRINTS("\tVbat: %dmV", bp.voltage); - CPRINTS("\tIbat: %dmA", bp.current); - charger_get_voltage(act_chg, &val); - CPRINTS("\tVsys(aux): %dmV", val); - charger_get_current(act_chg, &val); - CPRINTS("\tIsys: %dmA", val); - cflush(); - } - - rv = main_read8(chgnum, SM5803_REG_INT4_REQ, &int_reg); - if (rv) { - CPRINTS("%s %d: Failed to read int4 register", CHARGER_NAME, - chgnum); - return; - } - - if (int_reg & SM5803_INT4_CHG_FAIL) { - int status_reg; - - act_chg = charge_manager_get_active_charge_port(); - chg_read8(chgnum, SM5803_REG_STATUS_CHG_REG, &status_reg); - CPRINTS("%s %d: CHG_FAIL_INT fired. Status 0x%02x", - CHARGER_NAME, chgnum, status_reg); - - /* Write 1 to clear status interrupts */ - chg_write8(chgnum, SM5803_REG_STATUS_CHG_REG, status_reg); - - /* - * If a survivable fault happened, re-start sinking on the - * active charger after an appropriate delay. - */ - if (status_reg & SM5803_STATUS_CHG_OV_ITEMP) { - active_restart_port = act_chg; - hook_call_deferred(&sm5803_restart_charging_data, - 30 * SECOND); - } else if ((status_reg & SM5803_STATUS_CHG_OV_VBAT) && - act_chg == CHARGER_PRIMARY) { - active_restart_port = act_chg; - hook_call_deferred(&sm5803_restart_charging_data, - 1 * SECOND); - } - } - - if (int_reg & SM5803_INT4_CHG_DONE) - CPRINTS("%s %d: CHG_DONE_INT fired!!!", CHARGER_NAME, chgnum); - - if (int_reg & SM5803_INT4_OTG_FAIL) { - int status_reg; - - /* - * Gather status to detect if this was overcurrent - * - * Note: a status of 0 with this interrupt also indicates an - * overcurrent (see b/170517117) - */ - chg_read8(chgnum, SM5803_REG_STATUS_DISCHG, &status_reg); - CPRINTS("%s %d: OTG_FAIL_INT fired. Status 0x%02x", - CHARGER_NAME, chgnum, status_reg); - if ((status_reg == 0) || - (status_reg == SM5803_STATUS_DISCHG_VBUS_SHORT)) { - pd_handle_overcurrent(chgnum); - } - - /* - * Clear source mode here when status is 0, since OTG disable - * will detect us as sinking in this failure case. - */ - if (status_reg == 0) - rv = sm5803_flow1_update(chgnum, CHARGER_MODE_SOURCE | - SM5803_FLOW1_DIRECTCHG_SRC_EN, - MASK_CLR); - } - -} - -static void sm5803_irq_deferred(void) -{ - int i; - uint32_t pending = atomic_clear(&irq_pending); - - for (i = 0; i < CHARGER_NUM; i++) - if (BIT(i) & pending) - sm5803_handle_interrupt(i); -} -DECLARE_DEFERRED(sm5803_irq_deferred); - -void sm5803_interrupt(int chgnum) -{ - atomic_or(&irq_pending, BIT(chgnum)); - hook_call_deferred(&sm5803_irq_deferred_data, 0); -} - -static enum ec_error_list sm5803_get_dev_id(int chgnum, int *id) -{ - int rv = EC_SUCCESS; - - if (dev_id == UNKNOWN_DEV_ID) - rv = main_read8(chgnum, SM5803_REG_CHIP_ID, &dev_id); - - if (!rv) - *id = dev_id; - - return rv; - -} - -static const struct charger_info *sm5803_get_info(int chgnum) -{ - return &sm5803_charger_info; -} - -static enum ec_error_list sm5803_get_status(int chgnum, int *status) -{ - enum ec_error_list rv; - int reg; - - /* Charger obeys smart battery requests - making it level 2 */ - *status = CHARGER_LEVEL_2; - - rv = chg_read8(chgnum, SM5803_REG_FLOW1, ®); - if (rv) - return rv; - - - if ((reg & SM5803_FLOW1_MODE) == CHARGER_MODE_DISABLED && - !(reg & SM5803_FLOW1_LINEAR_CHARGE_EN)) - *status |= CHARGER_CHARGE_INHIBITED; - - return EC_SUCCESS; -} - -static enum ec_error_list sm5803_set_mode(int chgnum, int mode) -{ - enum ec_error_list rv = EC_SUCCESS; - - if (mode & CHARGE_FLAG_INHIBIT_CHARGE) { - rv = sm5803_flow1_update(chgnum, 0xFF, MASK_CLR); - rv |= sm5803_flow2_update(chgnum, SM5803_FLOW2_AUTO_ENABLED, - MASK_CLR); - } - - return rv; -} - -static enum ec_error_list sm5803_get_actual_current(int chgnum, int *current) -{ - enum ec_error_list rv; - int reg; - int curr; - - rv = meas_read8(chgnum, SM5803_REG_IBAT_CHG_AVG_MEAS_MSB, ®); - if (rv) - return rv; - curr = reg << 2; - - rv = meas_read8(chgnum, SM5803_REG_IBAT_CHG_AVG_MEAS_LSB, ®); - if (rv) - return rv; - curr |= reg & SM5803_IBAT_CHG_MEAS_LSB; - - /* The LSB is 7.32mA */ - *current = curr * 732 / 100; - return EC_SUCCESS; -} - -static enum ec_error_list sm5803_get_current(int chgnum, int *current) -{ - enum ec_error_list rv; - int reg; - - rv = chg_read8(chgnum, SM5803_REG_FAST_CONF4, ®); - if (rv) - return rv; - - reg &= SM5803_CONF4_ICHG_FAST; - *current = SM5803_REG_TO_CURRENT(reg); - - return EC_SUCCESS; -} - -static enum ec_error_list sm5803_set_current(int chgnum, int current) -{ - enum ec_error_list rv; - int reg; - - rv = chg_read8(chgnum, SM5803_REG_FAST_CONF4, ®); - if (rv) - return rv; - - reg &= ~SM5803_CONF4_ICHG_FAST; - reg |= SM5803_CURRENT_TO_REG(current); - - rv = chg_write8(chgnum, SM5803_REG_FAST_CONF4, reg); - return rv; -} - -static enum ec_error_list sm5803_get_actual_voltage(int chgnum, int *voltage) -{ - enum ec_error_list rv; - int reg; - int volt_bits; - - rv = meas_read8(chgnum, SM5803_REG_VSYS_AVG_MEAS_MSB, ®); - if (rv) - return rv; - volt_bits = reg << 2; - - rv = meas_read8(chgnum, SM5803_REG_VSYS_AVG_MEAS_LSB, ®); - if (rv) - return rv; - volt_bits |= reg & 0x3; - - /* The LSB is 23.4mV */ - *voltage = volt_bits * 234 / 10; - - return EC_SUCCESS; -} - -static enum ec_error_list sm5803_get_voltage(int chgnum, int *voltage) -{ - enum ec_error_list rv; - int regval; - int v; - - rv = chg_read8(chgnum, SM5803_REG_VBAT_FAST_MSB, ®val); - v = regval << 3; - rv |= chg_read8(chgnum, SM5803_REG_VBAT_FAST_LSB, ®val); - v |= (regval & 0x3); - - *voltage = SM5803_REG_TO_VOLTAGE(v); - - if (rv) - return EC_ERROR_UNKNOWN; - - return EC_SUCCESS; -} - -static enum ec_error_list sm5803_set_voltage(int chgnum, int voltage) -{ - enum ec_error_list rv; - int regval; - - regval = SM5803_VOLTAGE_TO_REG(voltage); - - /* - * Note: Set both voltages on both chargers. Vbat will only be used on - * primary, which enables charging. - */ - rv = chg_write8(chgnum, SM5803_REG_VSYS_PREREG_MSB, (regval >> 3)); - rv |= chg_write8(chgnum, SM5803_REG_VSYS_PREREG_LSB, (regval & 0x7)); - rv |= chg_write8(chgnum, SM5803_REG_VBAT_FAST_MSB, (regval >> 3)); - rv |= chg_write8(chgnum, SM5803_REG_VBAT_FAST_LSB, (regval & 0x7)); - - /* Once battery is connected, set up fast charge enable */ - if (fast_charge_disabled && chgnum == CHARGER_PRIMARY && - battery_get_disconnect_state() == BATTERY_NOT_DISCONNECTED) { - rv = sm5803_flow2_update(chgnum, - SM5803_FLOW2_AUTO_ENABLED, - MASK_SET); - fast_charge_disabled = false; - } - - if (IS_ENABLED(CONFIG_OCPC) && chgnum != CHARGER_PRIMARY) { - /* - * Check to see if the BFET is enabled. If not, enable it by - * toggling linear mode on the primary charger. The BFET can be - * disabled if the system is powered up from an auxiliary charge - * port and the battery is dead. - */ - rv |= chg_read8(CHARGER_PRIMARY, SM5803_REG_LOG1, ®val); - if (!(regval & SM5803_BATFET_ON) && !attempt_bfet_enable) { - CPRINTS("SM5803: Attempting to turn on BFET"); - cflush(); - rv |= sm5803_flow1_update(CHARGER_PRIMARY, - SM5803_FLOW1_LINEAR_CHARGE_EN, - MASK_SET); - rv |= sm5803_flow1_update(CHARGER_PRIMARY, - SM5803_FLOW1_LINEAR_CHARGE_EN, - MASK_CLR); - attempt_bfet_enable = 1; - sm5803_vbus_sink_enable(chgnum, 1); - } - /* There's no need to attempt it if the BFET's already on. */ - if (regval & SM5803_BATFET_ON) - attempt_bfet_enable = 1; - } - - return rv; -} - -static enum ec_error_list sm5803_discharge_on_ac(int chgnum, int enable) -{ - enum ec_error_list rv = EC_SUCCESS; - - if (enable) { - rv = sm5803_vbus_sink_enable(chgnum, 0); - } else { - if (chgnum == charge_manager_get_active_charge_port()) - rv = sm5803_vbus_sink_enable(chgnum, 1); - } - - return rv; -} - -static enum ec_error_list sm5803_get_vbus_voltage(int chgnum, int port, - int *voltage) -{ - enum ec_error_list rv; - int reg; - int volt_bits; - - rv = meas_read8(chgnum, SM5803_REG_VBUS_MEAS_MSB, ®); - if (rv) - return rv; - - volt_bits = reg << 2; - - rv = meas_read8(chgnum, SM5803_REG_VBUS_MEAS_LSB, ®); - - volt_bits |= reg & SM5803_VBUS_MEAS_LSB; - - /* Vbus ADC is in 23.4 mV steps */ - *voltage = (volt_bits * 234) / 10; - return rv; -} - -static enum ec_error_list sm5803_set_input_current_limit(int chgnum, - int input_current) -{ - int reg; - - reg = SM5803_CURRENT_TO_REG(input_current) & SM5803_CHG_ILIM_RAW; - - return chg_write8(chgnum, SM5803_REG_CHG_ILIM, reg); -} - -static enum ec_error_list sm5803_get_input_current_limit(int chgnum, - int *input_current) -{ - int rv; - int val; - - rv = chg_read8(chgnum, SM5803_REG_CHG_ILIM, &val); - if (rv) - return rv; - - *input_current = SM5803_REG_TO_CURRENT(val & SM5803_CHG_ILIM_RAW); - return rv; -} - -static enum ec_error_list sm5803_get_input_current(int chgnum, - int *input_current) -{ - enum ec_error_list rv; - int reg; - int curr; - - rv = meas_read8(chgnum, SM5803_REG_IBUS_CHG_MEAS_MSB, ®); - if (rv) - return rv; - curr = reg << 2; - - rv = meas_read8(chgnum, SM5803_REG_IBUS_CHG_MEAS_LSB, ®); - if (rv) - return rv; - curr |= reg & 0x3; - - /* The LSB is 7.32mA */ - *input_current = curr * 732 / 100; - return EC_SUCCESS; -} - -static enum ec_error_list sm5803_get_option(int chgnum, int *option) -{ - enum ec_error_list rv; - uint32_t control; - int reg; - - rv = chg_read8(chgnum, SM5803_REG_FLOW1, ®); - control = reg; - - rv |= chg_read8(chgnum, SM5803_REG_FLOW2, ®); - control |= reg << 8; - - rv |= chg_read8(chgnum, SM5803_REG_FLOW3, ®); - control |= reg << 16; - - return rv; -} - -enum ec_error_list sm5803_is_acok(int chgnum, bool *acok) -{ - int rv; - int reg, vbus_mv; - - rv = main_read8(chgnum, SM5803_REG_STATUS1, ®); - - if (rv) - return rv; - - /* If we're not sinking, then AC can't be OK. */ - if (!(reg & SM5803_STATUS1_CHG_DET)) { - *acok = false; - return EC_SUCCESS; - } - - /* - * Okay, we're sinking. Check that VBUS has some voltage. This - * should indicate that the path is good. - */ - rv = charger_get_vbus_voltage(chgnum, &vbus_mv); - - if (rv) - return rv; - - /* Assume that ACOK would be asserted if VBUS is higher than ~4V. */ - *acok = vbus_mv >= 4000; - - return EC_SUCCESS; -} - -static enum ec_error_list sm5803_is_input_current_limit_reached(int chgnum, - bool *reached) -{ - enum ec_error_list rv; - int reg; - - rv = chg_read8(chgnum, SM5803_REG_LOG2, ®); - if (rv) - return rv; - - *reached = (reg & SM5803_ISOLOOP_ON) ? true : false; - - return EC_SUCCESS; -} - -static enum ec_error_list sm5803_set_option(int chgnum, int option) -{ - enum ec_error_list rv; - int reg; - - mutex_lock(&flow1_access_lock[chgnum]); - - reg = option & 0xFF; - rv = chg_write8(chgnum, SM5803_REG_FLOW1, reg); - - mutex_unlock(&flow1_access_lock[chgnum]); - if (rv) - return rv; - - reg = (option >> 8) & 0xFF; - rv = chg_write8(chgnum, SM5803_REG_FLOW2, reg); - if (rv) - return rv; - - reg = (option >> 16) & 0xFF; - rv = chg_write8(chgnum, SM5803_REG_FLOW3, reg); - - return rv; -} - -static enum ec_error_list sm5803_set_otg_current_voltage(int chgnum, - int output_current, - int output_voltage) -{ - enum ec_error_list rv; - int reg; - - rv = chg_read8(chgnum, SM5803_REG_DISCH_CONF5, ®); - if (rv) - return rv; - - reg &= ~SM5803_DISCH_CONF5_CLS_LIMIT; - reg |= MIN((output_current / SM5803_CLS_CURRENT_STEP), - SM5803_DISCH_CONF5_CLS_LIMIT); - rv |= chg_write8(chgnum, SM5803_REG_DISCH_CONF5, reg); - - reg = SM5803_VOLTAGE_TO_REG(output_voltage); - rv = chg_write8(chgnum, SM5803_REG_VPWR_MSB, (reg >> 3)); - rv |= chg_write8(chgnum, SM5803_REG_DISCH_CONF2, - reg & SM5803_DISCH_CONF5_VPWR_LSB); - - return rv; -} - -static enum ec_error_list sm5803_enable_otg_power(int chgnum, int enabled) -{ - enum ec_error_list rv; - int reg, status; - - if (enabled) { - int selected_current; - - rv = chg_read8(chgnum, SM5803_REG_ANA_EN1, ®); - if (rv) - return rv; - - /* Enable current limit */ - reg &= ~SM5803_ANA_EN1_CLS_DISABLE; - rv = chg_write8(chgnum, SM5803_REG_ANA_EN1, reg); - - /* Disable ramps on current set in discharge */ - rv |= chg_read8(chgnum, SM5803_REG_DISCH_CONF6, ®); - reg |= SM5803_DISCH_CONF6_RAMPS_DIS; - rv |= chg_write8(chgnum, SM5803_REG_DISCH_CONF6, reg); - - /* - * In order to ensure the Vbus output doesn't overshoot too - * much, turn the starting voltage down to 4.8 V and ramp up - * after 4 ms - */ - rv = chg_read8(chgnum, SM5803_REG_DISCH_CONF5, ®); - if (rv) - return rv; - - selected_current = (reg & SM5803_DISCH_CONF5_CLS_LIMIT) * - SM5803_CLS_CURRENT_STEP; - sm5803_set_otg_current_voltage(chgnum, selected_current, 4800); - - /* - * Enable: SOURCE_MODE - enable sourcing out - * DIRECTCHG_SOURCE_EN - enable current loop - * (for designs with no external Vbus FET) - */ - rv = sm5803_flow1_update(chgnum, CHARGER_MODE_SOURCE | - SM5803_FLOW1_DIRECTCHG_SRC_EN, - MASK_SET); - usleep(4000); - - sm5803_set_otg_current_voltage(chgnum, selected_current, 5000); - } else { - /* Always clear out discharge status before clearing FLOW1 */ - rv = chg_read8(chgnum, SM5803_REG_STATUS_DISCHG, &status); - if (rv) - return rv; - - if (status) - CPRINTS("%s %d: Discharge failure 0x%02x", CHARGER_NAME, - chgnum, status); - - rv |= chg_write8(chgnum, SM5803_REG_STATUS_DISCHG, status); - - /* Re-enable ramps on current set in discharge */ - rv |= chg_read8(chgnum, SM5803_REG_DISCH_CONF6, ®); - reg &= ~SM5803_DISCH_CONF6_RAMPS_DIS; - rv |= chg_write8(chgnum, SM5803_REG_DISCH_CONF6, reg); - - /* - * PD tasks will always turn off previous sourcing on init. - * Protect ourselves from brown out on init by checking if we're - * sinking right now. The init process should only leave sink - * mode enabled if a charger is plugged in; otherwise it's - * expected to be 0. - * - * Always clear out sourcing if the previous source-out failed. - */ - rv |= chg_read8(chgnum, SM5803_REG_FLOW1, ®); - if (rv) - return rv; - - if ((reg & SM5803_FLOW1_MODE) != CHARGER_MODE_SINK || status) - rv = sm5803_flow1_update(chgnum, CHARGER_MODE_SOURCE | - SM5803_FLOW1_DIRECTCHG_SRC_EN, - MASK_CLR); - } - - return rv; -} - -static int sm5803_is_sourcing_otg_power(int chgnum, int port) -{ - enum ec_error_list rv; - int reg; - - rv = chg_read8(chgnum, SM5803_REG_FLOW1, ®); - if (rv) - return 0; - - /* - * Note: In linear mode, MB charger will read a reserved mode when - * sourcing, so bit 1 is the most reliable way to detect sourcing. - */ - return (reg & BIT(1)); -} - -static enum ec_error_list sm5803_set_vsys_compensation(int chgnum, - struct ocpc_data *ocpc, - int current_ma, - int voltage_mv) -{ - - int rv; - int regval; - int r; - - /* Set IR drop compensation */ - r = ocpc->combined_rsys_rbatt_mo * 100 / 167; /* 1.67mOhm steps */ - r = MAX(0, r); - rv = chg_write8(chgnum, SM5803_REG_IR_COMP2, r & 0x7F); - rv |= chg_read8(chgnum, SM5803_REG_IR_COMP1, ®val); - regval &= ~SM5803_IR_COMP_RES_SET_MSB; - r = r >> 8; /* Bits 9:8 */ - regval |= (r & 0x3) << SM5803_IR_COMP_RES_SET_MSB_SHIFT; - regval |= SM5803_IR_COMP_EN; - rv |= chg_write8(chgnum, SM5803_REG_IR_COMP1, regval); - - if (rv) - return EC_ERROR_UNKNOWN; - - return EC_ERROR_UNIMPLEMENTED; -} - -/* Hardware current ramping (aka DPM: Dynamic Power Management) */ - -#ifdef CONFIG_CHARGE_RAMP_HW -static enum ec_error_list sm5803_set_hw_ramp(int chgnum, int enable) -{ - enum ec_error_list rv; - int reg; - - rv = chg_read8(chgnum, SM5803_REG_CHG_MON_REG, ®); - - if (enable) - reg |= SM5803_DPM_LOOP_EN; - else - reg &= ~SM5803_DPM_LOOP_EN; - - rv |= chg_write8(chgnum, SM5803_REG_CHG_MON_REG, reg); - - return rv; -} - -static int sm5803_ramp_is_stable(int chgnum) -{ - /* - * There is no way to read current limit that the ramp has - * settled on with sm5803, so we don't consider the ramp stable, - * because we never know what the stable limit is. - */ - return 0; -} - -static int sm5803_ramp_is_detected(int chgnum) -{ - return 1; -} - -static int sm5803_ramp_get_current_limit(int chgnum) -{ - int rv; - int input_current = 0; - - rv = sm5803_get_input_current_limit(chgnum, &input_current); - - return rv ? -1 : input_current; -} -#endif /* CONFIG_CHARGE_RAMP_HW */ - -#ifdef CONFIG_CMD_CHARGER_DUMP -static int command_sm5803_dump(int argc, char **argv) -{ - int reg; - int regval; - int chgnum = 0; - - if (argc > 1) - chgnum = atoi(argv[1]); - - /* Dump base regs */ - ccprintf("BASE regs\n"); - for (reg = 0x01; reg <= 0x30; reg++) { - if (!main_read8(chgnum, reg, ®val)) - ccprintf("[0x%02X] = 0x%02x\n", reg, regval); - if (reg & 0xf) { - cflush(); /* Flush periodically */ - watchdog_reload(); - } - } - - /* Dump measure regs */ - ccprintf("MEAS regs\n"); - for (reg = 0x01; reg <= 0xED; reg++) { - if (!meas_read8(chgnum, reg, ®val)) - ccprintf("[0x%02X] = 0x%02x\n", reg, regval); - if (reg & 0xf) { - cflush(); /* Flush periodically */ - watchdog_reload(); - } - } - - /* Dump Charger regs from 0x1C to 0x7F */ - ccprintf("CHG regs\n"); - for (reg = 0x1C; reg <= 0x7F; reg++) { - if (!chg_read8(chgnum, reg, ®val)) - ccprintf("[0x%02X] = 0x%02x\n", reg, regval); - if (reg & 0xf) { - cflush(); /* Flush periodically */ - watchdog_reload(); - } - } - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(charger_dump, command_sm5803_dump, - "charger_dump [chgnum]", "Dumps SM5803 registers"); -#endif /* CONFIG_CMD_CHARGER_DUMP */ - -const struct charger_drv sm5803_drv = { - .init = &sm5803_init, - .post_init = &sm5803_post_init, - .get_info = &sm5803_get_info, - .get_status = &sm5803_get_status, - .set_mode = &sm5803_set_mode, - .get_actual_current = &sm5803_get_actual_current, - .get_current = &sm5803_get_current, - .set_current = &sm5803_set_current, - .get_actual_voltage = &sm5803_get_actual_voltage, - .get_voltage = &sm5803_get_voltage, - .set_voltage = &sm5803_set_voltage, - .discharge_on_ac = &sm5803_discharge_on_ac, - .get_vbus_voltage = &sm5803_get_vbus_voltage, - .set_input_current_limit = &sm5803_set_input_current_limit, - .get_input_current_limit = &sm5803_get_input_current_limit, - .get_input_current = &sm5803_get_input_current, - .device_id = &sm5803_get_dev_id, - .get_option = &sm5803_get_option, - .set_option = &sm5803_set_option, - .set_otg_current_voltage = &sm5803_set_otg_current_voltage, - .enable_otg_power = &sm5803_enable_otg_power, - .is_sourcing_otg_power = &sm5803_is_sourcing_otg_power, - .set_vsys_compensation = &sm5803_set_vsys_compensation, - .is_icl_reached = &sm5803_is_input_current_limit_reached, - .enable_linear_charge = &sm5803_enable_linear_charge, -#ifdef CONFIG_CHARGE_RAMP_HW - .set_hw_ramp = &sm5803_set_hw_ramp, - .ramp_is_stable = &sm5803_ramp_is_stable, - .ramp_is_detected = &sm5803_ramp_is_detected, - .ramp_get_current_limit = &sm5803_ramp_get_current_limit, -#endif -}; diff --git a/driver/charger/sm5803.h b/driver/charger/sm5803.h deleted file mode 100644 index b7638411e4..0000000000 --- a/driver/charger/sm5803.h +++ /dev/null @@ -1,432 +0,0 @@ -/* Copyright 2020 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. - * - * Silicon Mitus SM5803 Buck-Boost Charger - */ - -#ifndef __CROS_EC_SM5803_H -#define __CROS_EC_SM5803_H - -#include "common.h" - -/* Note: configure charger struct with CHARGER_FLAGS */ -#define SM5803_ADDR_MAIN_FLAGS 0x30 -#define SM5803_ADDR_MEAS_FLAGS 0x31 -#define SM5803_ADDR_CHARGER_FLAGS 0x32 -#define SM5803_ADDR_TEST_FLAGS 0x37 - -/* Main registers (address 0x30) */ - -#define SM5803_REG_CHIP_ID 0x00 - -#define SM5803_REG_STATUS1 0x01 -#define SM5803_STATUS1_VSYS_OK BIT(0) -#define SM5803_STATUS1_VPWR_OK BIT(1) -#define SM5803_STATUS1_VBUS_UVL BIT(3) -#define SM5803_STATUS1_VBUS_SHORT BIT(4) -#define SM5803_STATUS1_VBUS_OVH BIT(5) -#define SM5803_STATUS1_CHG_DET BIT(6) -#define SM5803_STATUS1_BAT_DET BIT(7) - -#define SM5803_REG_STATUS2 0x02 -#define SM5803_STATUS2_BAT_DET_FG BIT(1) -#define SM5803_STATUS2_VBAT_SHORT BIT(0) - -#define SM5803_REG_INT1_REQ 0x05 -#define SM5803_REG_INT1_EN 0x0A -#define SM5803_INT1_VBUS_PWR_HWSAFE_LIMIT BIT(0) -#define SM5803_INT1_CHG BIT(2) -#define SM5803_INT1_BAT BIT(3) -#define SM5803_INT1_CLS_OC BIT(4) -#define SM5803_INT1_SLV_DET BIT(5) -#define SM5803_INT1_SWL_DISCH BIT(6) -#define SM5803_INT1_PREREG BIT(7) - -#define SM5803_REG_INT2_REQ 0x06 -#define SM5803_REG_INT2_EN 0x0B -#define SM5803_INT2_VBATSNSP BIT(0) -#define SM5803_INT2_IBAT_DISCHG BIT(1) -#define SM5803_INT2_IBAT_CHG BIT(2) -#define SM5803_INT2_IBUS BIT(3) -#define SM5803_INT2_VBUS BIT(4) -#define SM5803_INT2_VCHGPWR BIT(5) -#define SM5803_INT2_VSYS BIT(6) -#define SM5803_INT2_TINT BIT(7) - -#define SM5803_REG_INT3_REQ 0x07 -#define SM5803_REG_INT3_EN 0x0C -#define SM5803_INT3_GPADC0 BIT(0) -#define SM5803_INT3_BFET_PWR_LIMIT BIT(1) -#define SM5803_INT3_BFET_PWR_HWSAFE_LIMIT BIT(2) -#define SM5803_INT3_SPARE BIT(3) -#define SM5803_INT3_VBUS_PWR_LIMIT BIT(4) -#define SM5803_INT3_IBAT BIT(5) - -#define SM5803_REG_INT4_REQ 0x08 -#define SM5803_REG_INT4_EN 0x0D -#define SM5803_INT4_CHG_FAIL BIT(0) -#define SM5803_INT4_CHG_DONE BIT(1) -#define SM5803_INT4_CHG_START BIT(2) -#define SM5803_INT4_SLP_EXIT BIT(3) -#define SM5803_INT4_OTG_FAIL BIT(4) -#define SM5803_INT4_CHG_ILIM BIT(5) -#define SM5803_INT4_IBAT_CC BIT(6) -#define SM5803_INT4_CC BIT(7) - -#define SM5803_REG_MISC_CONFIG 0x15 -#define SM5803_MISC_INV_INT BIT(0) -#define SM5803_INT_CLEAR_MODE BIT(1) -#define SM5803_INT_MASK_MODE BIT(2) - -#define SM5803_REG_PLATFORM 0x18 -#define SM5803_PLATFORM_ID GENMASK(4, 0) - -#define SM5803_REG_REFERENCE 0x20 -#define SM5803_REFERENCE_LDO3P3_PGOOD BIT(4) -#define SM5803_REFERENCE_LDO5_PGOOD BIT(5) - -#define SM5803_REG_CLOCK_SEL 0x2A -#define SM5803_CLOCK_SEL_LOW BIT(0) - -#define SM5803_REG_GPIO0_CTRL 0x30 -#define SM5803_GPIO0_VAL BIT(0) -#define SM5803_GPIO0_MODE_MASK GENMASK(2, 1) -#define SM5803_GPIO0_OPEN_DRAIN_EN BIT(6) -#define SM5803_CHG_DET_OPEN_DRAIN_EN BIT(7) - -#define SM5803_REG_VBATSNSP_MEAS_MSB 0x40 -#define SM5803_REG_VBATSNSP_MEAS_LSB 0x41 - -enum sm5803_gpio0_modes { - GPIO0_MODE_PROCHOT, - GPIO0_MODE_OUTPUT, - GPIO0_MODE_INPUT -}; - -#define SM5803_REG_BFET_PWR_MAX_TH 0x35 -#define SM5803_REG_BFET_PWR_HWSAFE_MAX_TH 0x36 - -#define SM5803_REG_PORTS_CTRL 0x40 -#define SM5803_PORTS_VBUS_DISCH BIT(0) -#define SM5803_PORTS_VBUS_PULLDOWN BIT(1) -#define SM5803_PORTS_VBUS_SNS_DISCH BIT(2) -#define SM5803_PORTS_VBUS_SNS_PULLDOWN BIT(3) - -/* ADC Registers (address 0x31) */ - -/* - * Note: Some register bits must be enabled for the DC-DC converter to properly - * handle transitions. - */ -#define SM5803_REG_GPADC_CONFIG1 0x01 -#define SM5803_GPADCC1_VBATSNSP_EN BIT(0) -#define SM5803_GPADCC1_IBAT_DIS_EN BIT(1) -#define SM5803_GPADCC1_IBAT_CHG_EN BIT(2) -#define SM5803_GPADCC1_IBUS_EN BIT(3) -#define SM5803_GPADCC1_VBUS_EN BIT(4) -#define SM5803_GPADCC1_VCHGPWR_EN BIT(5) /* NOTE: DO NOT CLEAR */ -#define SM5803_GPADCC1_VSYS_EN BIT(6) /* NOTE: DO NOT CLEAR */ -#define SM5803_GPADCC1_TINT_EN BIT(7) - -#define SM5803_REG_GPADC_CONFIG2 0x02 - -#define SM5803_REG_PSYS1 0x04 -#define SM5803_PSYS1_DAC_EN BIT(0) - -/* Note: Threshold registers all assume lower 2 bits are 0 */ -#define SM5803_REG_VBUS_LOW_TH 0x1A -#define SM5803_REG_VBATSNSP_MAX_TH 0x26 -#define SM5803_REG_VBUS_HIGH_TH 0x2A -#define SM5803_REG_VCHG_PWR_LOW_TH 0x1B -#define SM5803_REG_VCHG_PWR_HIGH_TH 0x2B -#define SM5803_REG_TINT_LOW_TH 0x1D -#define SM5803_REG_TINT_HIGH_TH 0x2D - -/* - * Vbus levels increment in 23.4 mV, set thresholds to below 3.5V and above 4.0V - * to mirror what TCPCI uses for Vbus present indication - */ -#define SM5803_VBUS_LOW_LEVEL 0x25 -#define SM5803_VBUS_HIGH_LEVEL 0x2C - - - -/* - * TINT thresholds. TINT steps are in 0.43 K with the upper threshold set to - * 360 K and lower threshold to de-assert PROCHOT at 330 K. - */ -#define SM5803_TINT_LOW_LEVEL 0xBF -#define SM5803_TINT_HIGH_LEVEL 0xD1 - -#define SM5803_TINT_MAX_LEVEL 0xFF -#define SM5803_TINT_MIN_LEVEL 0x00 - -/* - * Set minimum thresholds for VBUS_PWR_LOW_TH interrupt generation - * 2S battery 9.4v - * 3S battery 14.1V VBUS_PWR MIN TH - */ -#define SM5803_VBAT_PWR_MINTH_3S_LEVEL 0x9B -#define SM5803_VBAT_PWR_MINTH_2S_LEVEL 0x9B - -/* - * Set thresholds for VBATSNSP_MAX_TH GPADC interrupt generation - * 2S battery 9v - * 3S battery 13.3V - */ -#define SM5803_VBAT_SNSP_MAXTH_3S_LEVEL 0xD8 -#define SM5803_VBAT_SNSP_MAXTH_2S_LEVEL 0xDC - -/* IBAT levels - The IBAT levels increment in 7.32mA */ -#define SM5803_REG_IBAT_CHG_MEAS_MSB 0x44 -#define SM5803_REG_IBAT_CHG_MEAS_LSB 0x45 -#define SM5803_REG_IBAT_CHG_AVG_MEAS_MSB 0xC4 -#define SM5803_REG_IBAT_CHG_AVG_MEAS_LSB 0xC5 -#define SM5803_IBAT_CHG_MEAS_LSB GENMASK(1, 0) - -/* IBUS levels - The IBUS levels increment in 7.32mA */ -#define SM5803_REG_IBUS_CHG_MEAS_MSB 0x46 -#define SM5803_REG_IBUS_CHG_MEAS_LSB 0x47 -#define SM5803_IBUS_CHG_MEAS_LSB GENMASK(1, 0) - -#define SM5803_REG_VBUS_MEAS_MSB 0x48 -#define SM5803_REG_VBUS_MEAS_LSB 0x49 -#define SM5803_VBUS_MEAS_LSB GENMASK(1, 0) -#define SM5803_VBUS_MEAS_BAT_DET BIT(2) -#define SM5803_VBUS_MEAS_VBUS_SHORT BIT(4) -#define SM5803_VBUS_MEAS_OV_TEMP BIT(5) -#define SM5803_VBUS_MEAS_CHG_DET BIT(6) - -/* VCHGPWR levels - The VCHGPWR levels increment in 23.4mV steps. */ -#define SM5803_REG_VCHG_PWR_MSB 0x4A - -#define SM5803_REG_TINT_MEAS_MSB 0x4E - -/* VSYS levels - The VSYS levels increment in 23.4mV steps. */ -#define SM5803_REG_VSYS_MEAS_MSB 0x4C -#define SM5803_REG_VSYS_MEAS_LSB 0x4D -#define SM5803_REG_VSYS_AVG_MEAS_MSB 0xCC -#define SM5803_REG_VSYS_AVG_MEAS_LSB 0xCD -#define SM5803_VSYS_MEAS_LSB GENMASK(1, 0) - -/* Charger registers (address 0x32) */ - -#define SM5803_REG_CC_CONFIG1 0x01 -#define SM5803_CC_CONFIG1_SD_PWRUP BIT(3) - -#define SM5803_REG_FLOW1 0x1C -#define SM5803_FLOW1_MODE GENMASK(1, 0) -#define SM5803_FLOW1_DIRECTCHG_SRC_EN BIT(2) -#define SM5803_FLOW1_LINEAR_CHARGE_EN BIT(3) -#define SM5803_FLOW1_USB_SUSP BIT(7) - -enum sm5803_charger_modes { - CHARGER_MODE_DISABLED, - CHARGER_MODE_SINK, - CHARGER_MODE_RESERVED, - CHARGER_MODE_SOURCE, -}; - -#define SM5803_REG_FLOW2 0x1D -#define SM5803_FLOW2_AUTO_TRKL_EN BIT(0) -#define SM5803_FLOW2_AUTO_PRECHG_EN BIT(1) -#define SM5803_FLOW2_AUTO_FASTCHG_EN BIT(2) -#define SM5803_FLOW2_AUTO_ENABLED GENMASK(2, 0) -#define SM5803_FLOW2_FW_TRKL_CMD BIT(3) -#define SM5803_FLOW2_FW_PRECHG_CMD BIT(4) -#define SM5803_FLOW2_FW_FASTCHG_CMD BIT(5) -#define SM5803_FLOW2_HOST_MODE_EN BIT(6) -#define SM5803_FLOW2_AUTO_CHGEN_SET BIT(7) - -#define SM5803_REG_FLOW3 0x1E -#define SM5803_FLOW3_SWITCH_BCK_BST BIT(0) -#define SM5803_FLOW3_FW_SWITCH_RESUME BIT(1) -#define SM5803_FLOW3_FW_SWITCH_PAUSE BIT(2) -#define SM5803_FLOW3_SOFT_DISABLE_EN BIT(3) - -#define SM5803_REG_SWITCHER_CONF 0x1F -#define SM5803_SW_BCK_BST_CONF_AUTO BIT(0) - -#define SM5803_REG_ANA_EN1 0x21 -#define SM5803_ANA_EN1_CLS_DISABLE BIT(7) - -/* - * Input current limit is CHG_ILIM_RAW *100 mA - */ -#define SM5803_REG_CHG_ILIM 0x24 -#define SM5803_CHG_ILIM_RAW GENMASK(4, 0) -#define SM5803_CURRENT_STEP 100 -#define SM5803_REG_TO_CURRENT(r) ((r) * SM5803_CURRENT_STEP) -#define SM5803_CURRENT_TO_REG(c) ((c) / SM5803_CURRENT_STEP) - -/* - * DPM Voltage loop regulation contains the 8 bits with MSB register - * and the lower 3 bits with LSB register. - * The regulation value is 2.72 V + DPM_VL_SET * 10mV - */ -#define SM5803_REG_DPM_VL_SET_MSB 0x26 -#define SM5803_REG_DPM_VL_SET_LSB 0x27 - -/* - * Output voltage uses the same equation as Vsys - * Lower saturation value is 3 V, upper 20.5 V - */ -#define SM5803_REG_VPWR_MSB 0x30 -#define SM5803_REG_DISCH_CONF2 0x31 -#define SM5803_DISCH_CONF5_VPWR_LSB GENMASK(2, 0) - -/* - * Output current limit is CLS_LIMIT * 50 mA and saturates to 3.2 A - */ -#define SM5803_REG_DISCH_CONF5 0x34 -#define SM5803_DISCH_CONF5_CLS_LIMIT GENMASK(6, 0) -#define SM5803_CLS_CURRENT_STEP 50 - -#define SM5803_REG_DISCH_CONF6 0x35 -#define SM5803_DISCH_CONF6_RAMPS_DIS BIT(0) -#define SM5803_DISCH_CONF6_SMOOTH_DIS BIT(1) - -/* - * Vsys is 11 bits, with the lower 3 bits in the LSB register. - * The pre-regulation value is 2.72 V + Vsys_prereg * 10 mV - * Lower saturation value is 3V, upper is 20V - */ -#define SM5803_REG_VSYS_PREREG_MSB 0x36 -#define SM5803_REG_VSYS_PREREG_LSB 0x37 -#define SM5803_VOLTAGE_STEP 10 -#define SM5803_VOLTAGE_SHIFT 2720 -#define SM5803_REG_TO_VOLTAGE(r) (SM5803_VOLTAGE_SHIFT + \ - (r) * SM5803_VOLTAGE_STEP) -#define SM5803_VOLTAGE_TO_REG(v) (((v) - SM5803_VOLTAGE_SHIFT) \ - / SM5803_VOLTAGE_STEP) - -/* - * Precharge Termination threshold. - */ -#define SM5803_REG_PRE_FAST_CONF_REG1 0x39 -#define SM5803_VBAT_PRE_TERM_MIN_DV 23 -/* 3.8V+ gets rounded to 4V */ -#define SM5803_VBAT_PRE_TERM_MAX_DV 38 -#define SM5803_VBAT_PRE_TERM GENMASK(7, 4) -#define SM5803_VBAT_PRE_TERM_SHIFT 4 - -/* - * Vbat for fast charge uses the same equation as Vsys - * Lower saturation value is 3V, upper is dependent on number of cells - */ -#define SM5803_REG_VBAT_FAST_MSB 0x3A -#define SM5803_REG_VBAT_FAST_LSB 0x3B - -/* - * Fast charge current limit is ICHG_FAST * 100 mA - * Value read back may be adjusted if tempearture limits are exceeded - */ -#define SM5803_REG_FAST_CONF4 0x3C -#define SM5803_CONF4_ICHG_FAST GENMASK(5, 0) - -/* Fast charge Termination */ -#define SM5803_REG_FAST_CONF5 0x3D -#define SM5803_CONF5_IBAT_EOC_TH GENMASK(3, 0) - -/* IR drop compensation */ -#define SM5803_REG_IR_COMP1 0x3F -#define SM5803_IR_COMP_RES_SET_MSB GENMASK(7, 6) -#define SM5803_IR_COMP_RES_SET_MSB_SHIFT 6 -#define SM5803_IR_COMP_EN BIT(5) - -/* LSB is in 1.67mOhm steps. */ -#define SM5803_REG_IR_COMP2 0x40 - -/* Precharge current limit is also intervals of 100 mA */ -#define SM5803_REG_PRECHG 0x41 -#define SM5803_PRECHG_ICHG_PRE_SET GENMASK(5, 0) - -#define SM5803_REG_LOG1 0x42 -#define SM5803_BATFET_ON BIT(2) - -#define SM5803_REG_LOG2 0x43 -#define SM5803_ISOLOOP_ON BIT(1) - -#define SM5803_REG_STATUS_CHG_REG 0x48 -#define SM5803_STATUS_CHG_BATT_REMOVAL BIT(0) -#define SM5803_STATUS_CHG_CHG_REMOVAL BIT(1) -#define SM5803_STATUS_CHG_BATTEMP_NOK BIT(2) -#define SM5803_STATUS_CHG_CHGWDG_EXP BIT(3) -#define SM5803_STATUS_CHG_VBUS_OC BIT(4) -#define SM5803_STATUS_CHG_OV_VBAT BIT(5) -#define SM5803_STATUS_CHG_TIMEOUT BIT(6) -#define SM5803_STATUS_CHG_OV_ITEMP BIT(7) - -#define SM5803_REG_STATUS_DISCHG 0x49 -#define SM5803_STATUS_DISCHG_BATT_REM BIT(0) -#define SM5803_STATUS_DISCHG_UV_VBAT BIT(1) -#define SM5803_STATUS_DISCHG_VBUS_OC BIT(2) -#define SM5803_STATUS_DISCHG_VBUS_PWR GENMASK(4, 3) -#define SM5803_STATUS_DISCHG_ISO_CURR BIT(5) -#define SM5803_STATUS_DISCHG_VBUS_SHORT BIT(6) -#define SM5803_STATUS_DISCHG_OV_ITEMP BIT(7) - -#define SM5803_REG_CHG_MON_REG 0x5C -#define SM5803_DPM_LOOP_EN BIT(0) - -#define SM5803_REG_PHOT1 0x72 -#define SM5803_PHOT1_IBAT_PHOT_COMP_EN BIT(0) -#define SM5803_PHOT1_IBUS_PHOT_COMP_EN BIT(1) -#define SM5803_PHOT1_VSYS_MON_EN BIT(2) -#define SM5803_PHOT1_VBUS_MON_EN BIT(3) -#define SM5803_PHOT1_COMPARATOR_EN GENMASK(3, 0) -#define SM5803_PHOT1_DURATION GENMASK(6, 4) -#define SM5803_PHOT1_DURATION_SHIFT 4 -#define SM5803_PHOT1_IRQ_MODE BIT(7) - -#define CHARGER_NAME "sm5803" - -#define CHARGE_V_MAX 20000 -#define CHARGE_V_MIN SM5803_VOLTAGE_SHIFT -#define CHARGE_V_STEP SM5803_VOLTAGE_STEP - -#define CHARGE_I_MAX 6300 -#define CHARGE_I_MIN 0 -#define CHARGE_I_STEP SM5803_CURRENT_STEP - -#define INPUT_I_MAX 3100 -#define INPUT_I_MIN 0 -#define INPUT_I_STEP SM5803_CURRENT_STEP - -/* Expose cached Vbus presence */ -int sm5803_is_vbus_present(int chgnum); - -/* Expose functions to control charger's GPIO and CHG_DET configuration */ -enum ec_error_list sm5803_configure_gpio0(int chgnum, - enum sm5803_gpio0_modes mode, int od); -enum ec_error_list sm5803_set_gpio0_level(int chgnum, int level); -enum ec_error_list sm5803_configure_chg_det_od(int chgnum, int enable); -enum ec_error_list sm5803_get_chg_det(int chgnum, int *chg_det); - -/* Expose Vbus discharge function */ -enum ec_error_list sm5803_set_vbus_disch(int chgnum, int enable); -enum ec_error_list sm5803_vbus_sink_enable(int chgnum, int enable); - -void sm5803_hibernate(int chgnum); -void sm5803_interrupt(int chgnum); - -/** - * Return whether ACOK is high or low. - * - * @param chgnum index into chg_chips table. - * @param acok will be set to true if ACOK is asserted, otherwise false. - * @return EC_SUCCESS, error otherwise. - */ -enum ec_error_list sm5803_is_acok(int chgnum, bool *acok); - -/* Expose low power mode functions */ -void sm5803_disable_low_power_mode(int chgnum); -void sm5803_enable_low_power_mode(int chgnum); - -extern const struct charger_drv sm5803_drv; - -/* Expose interrupt handler for processing in PD_INT task when needed */ -void sm5803_handle_interrupt(int chgnum); - -#endif diff --git a/driver/charger/sy21612.c b/driver/charger/sy21612.c deleted file mode 100644 index 7bc6caa4ea..0000000000 --- a/driver/charger/sy21612.c +++ /dev/null @@ -1,213 +0,0 @@ -/* Copyright 2017 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. - * - * SILERGY SY21612 buck-boost converter driver. - */ - - -#include "console.h" -#include "hooks.h" -#include "i2c.h" -#include "sy21612.h" -#include "task.h" -#include "util.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_CHARGER, outstr) -#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args) -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) - -static int sy21612_clear_set_reg(int reg, int clear, int set) -{ - int val, old_val, rv; - - rv = i2c_read8(I2C_PORT_SY21612, SY21612_ADDR_FLAGS, reg, &old_val); - if (rv) - return rv; - - val = old_val; - val &= ~clear; - val |= set; - - if (val != old_val || clear || set) - rv = i2c_write8(I2C_PORT_SY21612, SY21612_ADDR_FLAGS, - reg, val); - - return rv; -} - -static int sy21612_read(int reg, int *val) -{ - return i2c_read8(I2C_PORT_SY21612, SY21612_ADDR_FLAGS, reg, val); -} - -int sy21612_enable_regulator(int enable) -{ - return enable ? - sy21612_clear_set_reg(SY21612_CTRL1, 0, SY21612_CTRL1_REG_EN) : - sy21612_clear_set_reg(SY21612_CTRL1, SY21612_CTRL1_REG_EN, 0); -} - -int sy21612_enable_adc(int enable) -{ - return enable ? - sy21612_clear_set_reg(SY21612_CTRL1, 0, SY21612_CTRL1_ADC_EN) : - sy21612_clear_set_reg(SY21612_CTRL1, SY21612_CTRL1_ADC_EN, 0); -} - -int sy21612_set_adc_mode(int auto_mode) -{ - return auto_mode ? - sy21612_clear_set_reg(SY21612_CTRL1, - 0, SY21612_CTRL1_ADC_AUTO_MODE) : - sy21612_clear_set_reg(SY21612_CTRL1, - SY21612_CTRL1_ADC_AUTO_MODE, 0); -} - -int sy21612_set_vbus_discharge(int auto_discharge) -{ - return auto_discharge ? - sy21612_clear_set_reg(SY21612_CTRL1, - SY21612_CTRL1_VBUS_NDISCHG, 0) : - sy21612_clear_set_reg(SY21612_CTRL1, - 0, SY21612_CTRL1_VBUS_NDISCHG); -} - -int sy21612_set_switching_freq(enum sy21612_switching_freq freq) -{ - return sy21612_clear_set_reg(SY21612_CTRL2, - SY21612_CTRL2_FREQ_MASK, - freq << SY21612_CTRL2_FREQ_SHIFT); -} - -int sy21612_set_vbus_volt(enum sy21612_vbus_volt volt) -{ - return sy21612_clear_set_reg(SY21612_CTRL2, - SY21612_CTRL2_VBUS_MASK, - volt << SY21612_CTRL2_VBUS_SHIFT); -} - -int sy21612_set_vbus_adj(enum sy21612_vbus_adj adj) -{ - return sy21612_clear_set_reg(SY21612_CTRL2, - SY21612_CTRL2_VBUS_ADJ_MASK, - adj << SY21612_CTRL2_VBUS_ADJ_SHIFT); -} - -int sy21612_set_sink_mode(int sink_mode) -{ - return sink_mode ? - sy21612_clear_set_reg(SY21612_PROT2, - 0, SY21612_PROT2_SINK_MODE) : - sy21612_clear_set_reg(SY21612_PROT2, - SY21612_PROT2_SINK_MODE, 0); -} - -int sy21612_is_power_good(void) -{ - int reg; - - if (sy21612_read(SY21612_STATE, ®)) - return 0; - - return reg & SY21612_STATE_POWER_GOOD; -} - -int sy21612_read_clear_int(void) -{ - int reg; - - if (sy21612_read(SY21612_INT, ®)) - return 0; - - return reg; -} - -int sy21612_get_vbat_voltage(void) -{ - int reg; - - if (sy21612_read(SY21612_VBAT_VOLT, ®)) - return 0; - - return reg * 25000 / 255; -} - -int sy21612_get_vbus_voltage(void) -{ - int reg; - - if (sy21612_read(SY21612_VBUS_VOLT, ®)) - return 0; - - return reg * 25000 / 255; -} - -int sy21612_get_vbus_current(void) -{ - int reg; - - if (sy21612_read(SY21612_VBUS_CURRENT, ®)) - return 0; - - /* - * delta V in range 0 ~ 67mV - * sense resistor 10 mOhm - */ - return reg * 6700 / 255; -} - -void sy21612_int(enum gpio_signal signal) -{ -#ifdef HAS_TASK_SY21612 - task_wake(TASK_ID_SY21612); -#endif -} - -#ifdef HAS_TASK_SY21612 -void sy21612_task(void *u) -{ - int flags; - - while (1) { - task_wait_event(-1); - if (sy21612_read(SY21612_INT, &flags)) - continue; - /* TODO: notify the error condition and enable regulator */ - if (flags & SY21612_INT_VBUS_OCP) - CPUTS("buck-boost VBUS OCP\n"); - if (flags & SY21612_INT_INDUCTOR_OCP) - CPUTS("buck-boost inductor OCP\n"); - if (flags & SY21612_INT_UVP) - CPUTS("buck-boost UVP\n"); - if (flags & SY21612_INT_OTP) - CPUTS("buck-boost OTP\n"); - } -} -#endif - -#ifdef CONFIG_CMD_CHARGER -static int command_sy21612(int argc, char **argv) -{ - int i, val, rv; - - ccputs("sy21612 regs:\n"); - for (i = 0; i < 9; i++) { - ccprintf("[%02x] ", i); - rv = sy21612_read(i, &val); - if (rv) - ccprintf(" x (%d)\n", rv); - else - ccprintf("%02x - %pb\n", val, BINARY_VALUE(val, 8)); - } - - ccprintf("vbat voltage: %d mV\n", sy21612_get_vbat_voltage()); - ccprintf("vbus voltage: %d mV\n", sy21612_get_vbus_voltage()); - ccprintf("vbus current: %d mA\n", sy21612_get_vbus_current()); - - return 0; -} -DECLARE_CONSOLE_COMMAND(sy21612, command_sy21612, - NULL, NULL); -#endif diff --git a/driver/charger/sy21612.h b/driver/charger/sy21612.h deleted file mode 100644 index befb8e6a35..0000000000 --- a/driver/charger/sy21612.h +++ /dev/null @@ -1,164 +0,0 @@ -/* Copyright 2017 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. - * - * SILERGY SY21612 buck-boost converter driver. - */ - -#ifndef __CROS_EC_SY21612_H -#define __CROS_EC_SY21612_H - -#include "gpio.h" - -#ifndef SY21612_ADDR_FLAGS -#define SY21612_ADDR_FLAGS 0x71 -#endif - -enum sy21612_switching_freq { - SY21612_FREQ_250KHZ = 0, - SY21612_FREQ_500KHZ, - SY21612_FREQ_750KHZ, - SY21612_FREQ_1MHZ -}; - -enum sy21612_vbus_volt { - SY21612_VBUS_5V = 2, - SY21612_VBUS_7V, - SY21612_VBUS_9V, - SY21612_VBUS_12V, - SY21612_VBUS_15V, - SY21612_VBUS_20V, -}; - -enum sy21612_vbus_adj { - SY21612_VBUS_M2_5 = 0, - SY21612_VBUS_M1_25, - SY21612_VBUS_0, - SY21612_VBUS_1_25, - SY21612_VBUS_2_5, - SY21612_VBUS_3_75, - SY21612_VBUS_5, -}; - -#define SY21612_CTRL1 0x00 -#define SY21612_CTRL1_REG_EN BIT(7) -#define SY21612_CTRL1_LOW_BAT_MASK (7 << 4) -#define SY21612_CTRL1_LOW_BAT_10_2V (0 << 4) -#define SY21612_CTRL1_LOW_BAT_10_7V BIT(4) -#define SY21612_CTRL1_LOW_BAT_11_2V (2 << 4) -#define SY21612_CTRL1_LOW_BAT_11_7V (3 << 4) -#define SY21612_CTRL1_LOW_BAT_22_0V (4 << 4) -#define SY21612_CTRL1_LOW_BAT_22_5V (5 << 4) -#define SY21612_CTRL1_LOW_BAT_23_0V (6 << 4) -#define SY21612_CTRL1_LOW_BAT_23_5V (7 << 4) -#define SY21612_CTRL1_ADC_EN BIT(3) -#define SY21612_CTRL1_ADC_AUTO_MODE BIT(2) -#define SY21612_CTRL1_VBUS_NDISCHG BIT(1) - -#define SY21612_CTRL2 0x01 -#define SY21612_CTRL2_FREQ_MASK (3 << 6) -#define SY21612_CTRL2_FREQ_SHIFT 6 -#define SY21612_CTRL2_FREQ_250K (0 << 6) -#define SY21612_CTRL2_FREQ_500K BIT(6) -#define SY21612_CTRL2_FREQ_750K (2 << 6) -#define SY21612_CTRL2_FREQ_1M (3 << 6) -#define SY21612_CTRL2_VBUS_MASK (7 << 3) -#define SY21612_CTRL2_VBUS_SHIFT 3 -#define SY21612_CTRL2_VBUS_5V (2 << 3) -#define SY21612_CTRL2_VBUS_7V (3 << 3) -#define SY21612_CTRL2_VBUS_9V (4 << 3) -#define SY21612_CTRL2_VBUS_12V (5 << 3) -#define SY21612_CTRL2_VBUS_15V (6 << 3) -#define SY21612_CTRL2_VBUS_20V (7 << 3) -#define SY21612_CTRL2_VBUS_ADJ_MASK 7 -#define SY21612_CTRL2_VBUS_ADJ_SHIFT 0 -#define SY21612_CTRL2_VBUS_ADJ_M2_5 0 -#define SY21612_CTRL2_VBUS_ADJ_M1_25 1 -#define SY21612_CTRL2_VBUS_ADJ_0 2 -#define SY21612_CTRL2_VBUS_ADJ_1_25 3 -#define SY21612_CTRL2_VBUS_ADJ_2_5 4 -#define SY21612_CTRL2_VBUS_ADJ_3_75 5 -#define SY21612_CTRL2_VBUS_ADJ_5 6 - -#define SY21612_PROT1 0x02 -#define SY21612_PROT1_I_THRESH_MASK (7 << 5) -#define SY21612_PROT1_I_THRESH_18MV (0 << 5) -#define SY21612_PROT1_I_THRESH_22MV BIT(5) -#define SY21612_PROT1_I_THRESH_27MV (2 << 5) -#define SY21612_PROT1_I_THRESH_31MV (3 << 5) -#define SY21612_PROT1_I_THRESH_36MV (4 << 5) -#define SY21612_PROT1_I_THRESH_45MV (5 << 5) -#define SY21612_PROT1_I_THRESH_54MV (6 << 5) -#define SY21612_PROT1_I_THRESH_64MV (7 << 5) -#define SY21612_PROT1_OVP_THRESH_MASK (3 << 3) -#define SY21612_PROT1_OVP_THRESH_110 (0 << 3) -#define SY21612_PROT1_OVP_THRESH_115 BIT(3) -#define SY21612_PROT1_OVP_THRESH_120 (2 << 3) -#define SY21612_PROT1_OVP_THRESH_125 (3 << 3) -#define SY21612_PROT1_UVP_THRESH_MASK (3 << 1) -#define SY21612_PROT1_UVP_THRESH_50 (0 << 1) -#define SY21612_PROT1_UVP_THRESH_60 BIT(1) -#define SY21612_PROT1_UVP_THRESH_70 (2 << 1) -#define SY21612_PROT1_UVP_THRESH_80 (3 << 1) - -#define SY21612_PROT2 0x03 -#define SY21612_PROT2_I_LIMIT_MASK (3 << 6) -#define SY21612_PROT2_I_LIMIT_6A (0 << 6) -#define SY21612_PROT2_I_LIMIT_8A (2 << 6) -#define SY21612_PROT2_I_LIMIT_10A (3 << 6) -#define SY21612_PROT2_OCP_AUTORECOVER BIT(5) -#define SY21612_PROT2_UVP_AUTORECOVER BIT(4) -#define SY21612_PROT2_OTP_AUTORECOVER BIT(3) -#define SY21612_PROT2_SINK_MODE BIT(2) - -#define SY21612_STATE 0x04 -#define SY21612_STATE_POWER_GOOD BIT(7) -#define SY21612_STATE_VBAT_LT_VBUS BIT(6) -#define SY21612_STATE_VBAT_LOW BIT(5) - -#define SY21612_INT 0x05 -#define SY21612_INT_ADC_READY BIT(7) -#define SY21612_INT_VBUS_OCP BIT(6) -#define SY21612_INT_INDUCTOR_OCP BIT(5) -#define SY21612_INT_UVP BIT(4) -#define SY21612_INT_OTP BIT(3) - -/* Battery voltage range: 0 ~ 25V */ -#define SY21612_VBAT_VOLT 0x06 - -/* VBUS voltage range: 0 ~ 25V */ -#define SY21612_VBUS_VOLT 0x07 - -/* Output current sense voltage range 0 ~ 67mV */ -#define SY21612_VBUS_CURRENT 0x08 - -/* Enable or disable the regulator */ -int sy21612_enable_regulator(int enable); -/* Enable internal adc */ -int sy21612_enable_adc(int enable); -/* Set ADC mode to single or auto */ -int sy21612_set_adc_mode(int auto_mode); -/* Enable VBUS auto discharge when regulator is disabled */ -int sy21612_set_vbus_discharge(int auto_discharge); -/* Set buck-boost switching frequency */ -int sy21612_set_switching_freq(enum sy21612_switching_freq freq); -/* Set VBUS output voltage */ -int sy21612_set_vbus_volt(enum sy21612_vbus_volt volt); -/* Adjust VBUS output voltage */ -int sy21612_set_vbus_adj(enum sy21612_vbus_adj adj); -/* Set bidirection mode */ -int sy21612_set_sink_mode(int sink_mode); -/* Get power good status */ -int sy21612_is_power_good(void); -/* Read and clear interrupt flags */ -int sy21612_read_clear_int(void); -/* Get VBUS voltage in mV */ -int sy21612_get_vbat_voltage(void); -/* Get VBUS voltage in mV */ -int sy21612_get_vbus_voltage(void); -/* Get VBUS current in mA */ -int sy21612_get_vbus_current(void); -/* Interrupt handler */ -void sy21612_int(enum gpio_signal signal); - -#endif /* __CROS_EC_SY21612_H */ |