diff options
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 */ |