diff options
-rw-r--r-- | board/amenia/board.c | 66 | ||||
-rw-r--r-- | board/amenia/board.h | 1 | ||||
-rw-r--r-- | board/amenia/ec.tasklist | 2 | ||||
-rw-r--r-- | board/chell/board.c | 4 | ||||
-rw-r--r-- | board/elm/board.c | 4 | ||||
-rw-r--r-- | board/glados/board.c | 4 | ||||
-rw-r--r-- | board/kevin/board.c | 2 | ||||
-rw-r--r-- | board/lucid/board.c | 2 | ||||
-rw-r--r-- | board/oak/board.c | 4 | ||||
-rw-r--r-- | board/reef/board.c | 4 | ||||
-rw-r--r-- | board/ryu/board.c | 4 | ||||
-rw-r--r-- | board/ryu/board.h | 2 | ||||
-rw-r--r-- | board/samus_pd/board.c | 4 | ||||
-rw-r--r-- | board/strago/board.c | 4 | ||||
-rw-r--r-- | board/wheatley/board.c | 4 | ||||
-rw-r--r-- | common/charge_manager.c | 20 | ||||
-rw-r--r-- | common/charge_ramp.c | 3 | ||||
-rw-r--r-- | driver/charger/bd99955.c | 274 | ||||
-rw-r--r-- | driver/charger/bd99955.h | 42 | ||||
-rw-r--r-- | include/charge_manager.h | 2 | ||||
-rw-r--r-- | include/config.h | 1 | ||||
-rw-r--r-- | test/charge_manager.c | 2 | ||||
-rw-r--r-- | test/charge_ramp.c | 2 |
23 files changed, 372 insertions, 85 deletions
diff --git a/board/amenia/board.c b/board/amenia/board.c index 402ae5519c..d2695d62ca 100644 --- a/board/amenia/board.c +++ b/board/amenia/board.c @@ -49,43 +49,6 @@ #define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) #define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) -#if 1 /* TODO: CHARGER / BC1.2 */ -static void update_vbus_supplier(int port, int vbus_level) -{ - struct charge_port_info charge; - - charge.voltage = USB_CHARGER_VOLTAGE_MV; - charge.current = vbus_level ? USB_CHARGER_MIN_CURR_MA : 0; - charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, port, &charge); -} - -static void reset_charge(int port) -{ - struct charge_port_info charge_none; - - charge_none.voltage = USB_CHARGER_VOLTAGE_MV; - charge_none.current = 0; - charge_manager_update_charge(CHARGE_SUPPLIER_PROPRIETARY, - port, - &charge_none); - charge_manager_update_charge(CHARGE_SUPPLIER_BC12_CDP, - port, - &charge_none); - charge_manager_update_charge(CHARGE_SUPPLIER_BC12_DCP, - port, - &charge_none); - charge_manager_update_charge(CHARGE_SUPPLIER_BC12_SDP, - port, - &charge_none); - charge_manager_update_charge(CHARGE_SUPPLIER_OTHER, - port, - &charge_none); - - /* Initialize VBUS supplier based on whether VBUS is present */ - update_vbus_supplier(port, pd_snk_is_vbus_provided(port)); -} -#endif - uint16_t tcpc_get_alert_status(void) { uint16_t status = 0; @@ -123,8 +86,7 @@ void vbus0_evt(enum gpio_signal signal) return; /* VBUS present GPIO is inverted */ - update_vbus_supplier(0, !gpio_get_level(signal)); - + usb_charger_vbus_change(0, !gpio_get_level(signal)); task_wake(TASK_ID_PD_C0); } @@ -134,8 +96,7 @@ void vbus1_evt(enum gpio_signal signal) return; /* VBUS present GPIO is inverted */ - update_vbus_supplier(1, !gpio_get_level(signal)); - + usb_charger_vbus_change(1, !gpio_get_level(signal)); task_wake(TASK_ID_PD_C1); } @@ -309,14 +270,6 @@ const struct button_config buttons[CONFIG_BUTTON_COUNT] = { /* Initialize board. */ static void board_init(void) { -#if 1 /* TODO: CHARGER / BC1.2 */ - int i; - - /* Initialize all BC1.2 charge suppliers to 0 */ - for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) - reset_charge(i); -#endif - #if 0 /* TODO: CHARGER */ /* Enable charger interrupt */ gpio_enable_interrupt(GPIO_CHARGER_INT_L); @@ -343,8 +296,7 @@ int board_set_active_charge_port(int charge_port) int is_real_port = (charge_port >= 0 && charge_port < CONFIG_USB_PD_PORT_COUNT); /* check if we are source vbus on that port */ - int source = gpio_get_level(charge_port == 0 ? GPIO_USB_C0_5V_EN : - GPIO_USB_C1_5V_EN); + int source = usb_charger_port_is_sourcing_vbus(charge_port); if (is_real_port && source) { CPRINTS("Skip enable p%d", charge_port); @@ -374,10 +326,20 @@ int board_set_active_charge_port(int charge_port) /** * Set the charge limit based upon desired maximum. * + * @param port Port number. + * @param supplier Charge supplier type. * @param charge_ma Desired charge limit (mA). */ -void board_set_charge_limit(int charge_ma) +void board_set_charge_limit(int port, int supplier, int charge_ma) { + /* Enable charging trigger by BC1.2 detection */ + if (supplier == CHARGE_SUPPLIER_BC12_CDP || + supplier == CHARGE_SUPPLIER_BC12_DCP || + supplier == CHARGE_SUPPLIER_BC12_SDP) { + if (bd99955_bc12_enable_charging(port, 1)) + return; + } + charge_set_input_current_limit(MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT)); } diff --git a/board/amenia/board.h b/board/amenia/board.h index 368e7b0b2e..b6117d23cd 100644 --- a/board/amenia/board.h +++ b/board/amenia/board.h @@ -42,6 +42,7 @@ #define CONFIG_CHARGER_NARROW_VDC #define CONFIG_CHARGER_SENSE_RESISTOR 10 #define CONFIG_CHARGER_SENSE_RESISTOR_AC 20 +#define CONFIG_USB_CHARGER #define CONFIG_CHIPSET_APOLLOLAKE #define CONFIG_CMD_ACCELS diff --git a/board/amenia/ec.tasklist b/board/amenia/ec.tasklist index f47a845f66..8418f4d0f6 100644 --- a/board/amenia/ec.tasklist +++ b/board/amenia/ec.tasklist @@ -19,6 +19,8 @@ #define CONFIG_TASK_LIST \ TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ TASK_ALWAYS(ALS, als_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P0, usb_charger_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(USB_CHG_P1, usb_charger_task, NULL, TASK_STACK_SIZE) \ TASK_ALWAYS(CHARGER, charger_task, NULL, LARGER_TASK_STACK_SIZE) \ TASK_NOTEST(MOTIONSENSE, motion_sense_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ diff --git a/board/chell/board.c b/board/chell/board.c index b1dd93881d..6404844c3b 100644 --- a/board/chell/board.c +++ b/board/chell/board.c @@ -352,9 +352,11 @@ int board_set_active_charge_port(int charge_port) /** * Set the charge limit based upon desired maximum. * + * @param port Port number. + * @param supplier Charge supplier type. * @param charge_ma Desired charge limit (mA). */ -void board_set_charge_limit(int charge_ma) +void board_set_charge_limit(int port, int supplier, int charge_ma) { charge_set_input_current_limit(MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT)); diff --git a/board/elm/board.c b/board/elm/board.c index 809680931d..3a51b0ba68 100644 --- a/board/elm/board.c +++ b/board/elm/board.c @@ -289,9 +289,11 @@ int board_set_active_charge_port(int charge_port) /** * Set the charge limit based upon desired maximum. * + * @param port Port number. + * @param supplier Charge supplier type. * @param charge_ma Desired charge limit (mA). */ -void board_set_charge_limit(int charge_ma) +void board_set_charge_limit(int port, int supplier, int charge_ma) { charge_set_input_current_limit(MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT)); diff --git a/board/glados/board.c b/board/glados/board.c index 8855ae9518..29d05f1dea 100644 --- a/board/glados/board.c +++ b/board/glados/board.c @@ -323,9 +323,11 @@ int board_set_active_charge_port(int charge_port) /** * Set the charge limit based upon desired maximum. * + * @param port Port number. + * @param supplier Charge supplier type. * @param charge_ma Desired charge limit (mA). */ -void board_set_charge_limit(int charge_ma) +void board_set_charge_limit(int port, int supplier, int charge_ma) { charge_set_input_current_limit(MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT)); diff --git a/board/kevin/board.c b/board/kevin/board.c index 1e4cb24a77..f3f99d38b9 100644 --- a/board/kevin/board.c +++ b/board/kevin/board.c @@ -196,7 +196,7 @@ int board_set_active_charge_port(int charge_port) return bd99955_select_input_port(bd99955_port); } -void board_set_charge_limit(int charge_ma) +void board_set_charge_limit(int port, int supplier, int charge_ma) { charge_set_input_current_limit(MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT)); diff --git a/board/lucid/board.c b/board/lucid/board.c index f5f03e2895..86a423b653 100644 --- a/board/lucid/board.c +++ b/board/lucid/board.c @@ -165,7 +165,7 @@ int board_set_active_charge_port(int charge_port) return EC_SUCCESS; } -void board_set_charge_limit(int charge_ma) +void board_set_charge_limit(int port, int supplier, int charge_ma) { int rv; diff --git a/board/oak/board.c b/board/oak/board.c index f66c35acee..66ac54d314 100644 --- a/board/oak/board.c +++ b/board/oak/board.c @@ -318,9 +318,11 @@ int board_set_active_charge_port(int charge_port) /** * Set the charge limit based upon desired maximum. * + * @param port Port number. + * @param supplier Charge supplier type. * @param charge_ma Desired charge limit (mA). */ -void board_set_charge_limit(int charge_ma) +void board_set_charge_limit(int port, int supplier, int charge_ma) { charge_set_input_current_limit(MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT)); diff --git a/board/reef/board.c b/board/reef/board.c index 3a6ca25559..81c7054b7a 100644 --- a/board/reef/board.c +++ b/board/reef/board.c @@ -363,9 +363,11 @@ int board_set_active_charge_port(int charge_port) /** * Set the charge limit based upon desired maximum. * + * @param port Port number. + * @param supplier Charge supplier type. * @param charge_ma Desired charge limit (mA). */ -void board_set_charge_limit(int charge_ma) +void board_set_charge_limit(int port, int supplier, int charge_ma) { charge_set_input_current_limit(MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT)); diff --git a/board/ryu/board.c b/board/ryu/board.c index aa59a6778a..0c570a4d2d 100644 --- a/board/ryu/board.c +++ b/board/ryu/board.c @@ -546,9 +546,11 @@ int board_set_active_charge_port(int charge_port) /** * Set the charge limit based upon desired maximum. * + * @param port Port number. + * @param supplier Charge supplier type. * @param charge_ma Desired charge limit (mA). */ -void board_set_charge_limit(int charge_ma) +void board_set_charge_limit(int port, int supplier, int charge_ma) { int rv; diff --git a/board/ryu/board.h b/board/ryu/board.h index 3c5be953ba..a0a20f6479 100644 --- a/board/ryu/board.h +++ b/board/ryu/board.h @@ -276,7 +276,7 @@ enum usb_strings { #define PD_PREFER_LOW_VOLTAGE /* Set the charge current limit. */ -void board_set_charge_limit(int charge_ma); +void board_set_charge_limit(int port, int supplier, int charge_ma); /* PP1800 transition GPIO interrupt handler */ void pp1800_on_off_evt(enum gpio_signal signal); diff --git a/board/samus_pd/board.c b/board/samus_pd/board.c index 80e99dd9da..de4a46729a 100644 --- a/board/samus_pd/board.c +++ b/board/samus_pd/board.c @@ -495,9 +495,11 @@ static int board_update_charge_limit(int charge_ma) /** * Set the charge limit based upon desired maximum. * + * @param port Port number. + * @param supplier Charge supplier type. * @param charge_ma Desired charge limit (mA). */ -void board_set_charge_limit(int charge_ma) +void board_set_charge_limit(int port, int supplier, int charge_ma) { /* Update current limit and notify EC if it changed */ if (board_update_charge_limit(charge_ma)) diff --git a/board/strago/board.c b/board/strago/board.c index 32ca7aa4a8..5c123e7ef4 100644 --- a/board/strago/board.c +++ b/board/strago/board.c @@ -346,9 +346,11 @@ int board_set_active_charge_port(int charge_port) /** * Set the charge limit based upon desired maximum. * + * @param port Port number. + * @param supplier Charge supplier type. * @param charge_ma Desired charge limit (mA). */ -void board_set_charge_limit(int charge_ma) +void board_set_charge_limit(int port, int supplier, int charge_ma) { charge_set_input_current_limit(MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT)); diff --git a/board/wheatley/board.c b/board/wheatley/board.c index f8754eae0c..408e833697 100644 --- a/board/wheatley/board.c +++ b/board/wheatley/board.c @@ -305,9 +305,11 @@ int board_set_active_charge_port(int charge_port) /** * Set the charge limit based upon desired maximum. * + * @param port Port number. + * @param supplier Charge supplier type. * @param charge_ma Desired charge limit (mA). */ -void board_set_charge_limit(int charge_ma) +void board_set_charge_limit(int port, int supplier, int charge_ma) { charge_set_input_current_limit(MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT)); diff --git a/common/charge_manager.c b/common/charge_manager.c index 02bcbee5e3..d57037aae8 100644 --- a/common/charge_manager.c +++ b/common/charge_manager.c @@ -527,8 +527,9 @@ static void charge_manager_refresh(void) /* Enable or disable charge ramp */ charger_set_hw_ramp(board_is_ramp_allowed(new_supplier)); #endif - board_set_charge_limit(new_charge_current); -#endif + board_set_charge_limit(new_port, new_supplier, + new_charge_current); +#endif /* HAS_TASK_CHG_RAMP */ CPRINTS("CL: p%d s%d i%d v%d", new_port, new_supplier, new_charge_current, new_charge_voltage); } @@ -996,3 +997,18 @@ DECLARE_CONSOLE_COMMAND(chglim, command_external_power_limit, "Set max charger current / voltage", NULL); #endif /* CONFIG_CHARGE_MANAGER_EXTERNAL_POWER_LIMIT */ + +#ifdef CONFIG_CMD_CHARGE_SUPPLIER_INFO +static int charge_supplier_info(int argc, char **argv) +{ + ccprintf("port=%d, type=%d, cur=%dmA, vtg=%dmV\n", + charge_manager_get_active_charge_port(), + charge_supplier, + charge_current, + charge_voltage); + + return 0; +} +DECLARE_CONSOLE_COMMAND(chgsup, charge_supplier_info, + NULL, "print chg supplier info", NULL); +#endif diff --git a/common/charge_ramp.c b/common/charge_ramp.c index e5f6d99e26..775093f837 100644 --- a/common/charge_ramp.c +++ b/common/charge_ramp.c @@ -319,7 +319,8 @@ void chg_ramp_task(void) active_icl = active_icl_new; /* Set the input current limit */ - board_set_charge_limit(chg_ramp_get_current_limit()); + board_set_charge_limit(active_port, active_sup, + chg_ramp_get_current_limit()); if (ramp_st == CHG_RAMP_STABILIZE) /* diff --git a/driver/charger/bd99955.c b/driver/charger/bd99955.c index 713a90be1c..c07cf70493 100644 --- a/driver/charger/bd99955.c +++ b/driver/charger/bd99955.c @@ -8,16 +8,28 @@ #include "battery.h" #include "battery_smart.h" #include "bd99955.h" +#include "charge_manager.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 BD99955_CHARGE_PORT_COUNT 2 /* Console output macros */ #define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) +/* TODO: Add accurate timeout for detecting BC1.2 */ +#define BC12_DETECT_RETRY 10 + /* Charger parameters */ static const struct charger_info bd99955_charger_info = { .name = CHARGER_NAME, @@ -37,6 +49,14 @@ static enum bd99955_command charger_map_cmd = BD99955_INVALID_COMMAND; static struct mutex bd99955_map_mutex; +#if defined(HAS_TASK_USB_CHG_P0) || defined(HAS_TASK_USB_CHG_P1) +/* USB switch */ +static enum usb_switch usb_switch_state[BD99955_CHARGE_PORT_COUNT] = { + USB_SWITCH_DISCONNECT, + USB_SWITCH_DISCONNECT, +}; +#endif + static inline int ch_raw_read16(int cmd, int *param, enum bd99955_command map_cmd) { @@ -108,9 +128,34 @@ static int bd99955_charger_enable(int enable) static int bd99955_por_reset(void) { - return ch_raw_write16(BD99955_CMD_SYSTEM_CTRL_SET, - BD99955_CMD_SYSTEM_CTRL_SET_OTPLD | - BD99955_CMD_SYSTEM_CTRL_SET_ALLRST, + int rv; + int reg; + int i; + + rv = ch_raw_write16(BD99955_CMD_SYSTEM_CTRL_SET, + BD99955_CMD_SYSTEM_CTRL_SET_OTPLD | + BD99955_CMD_SYSTEM_CTRL_SET_ALLRST, + BD99955_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(BD99955_CMD_SYSTEM_STATUS, ®, + BD99955_EXTENDED_COMMAND); + + if (!rv && (reg & BD99955_CMD_SYSTEM_STATUS_OTPLD_STATE) && + (reg & BD99955_CMD_SYSTEM_STATUS_ALLRST_STATE)) + break; + } + + if (rv) + return rv; + if (i == OTPROM_LOAD_WAIT_RETRY) + return EC_ERROR_TIMEOUT; + + return ch_raw_write16(BD99955_CMD_SYSTEM_CTRL_SET, 0, BD99955_EXTENDED_COMMAND); } @@ -131,6 +176,125 @@ static int bd99955_get_charger_op_status(int *status) BD99955_EXTENDED_COMMAND); } +#if defined(HAS_TASK_USB_CHG_P0) || defined(HAS_TASK_USB_CHG_P1) +static int bd99955_get_bc12_device_type(enum bd99955_charge_port port) +{ + int rv; + int reg; + + rv = ch_raw_read16((port == BD99955_CHARGE_PORT_VBUS) ? + BD99955_CMD_VBUS_UCD_STATUS : + BD99955_CMD_VCC_UCD_STATUS, + ®, BD99955_EXTENDED_COMMAND); + if (rv) + return CHARGE_SUPPLIER_NONE; + + switch (reg & BD99955_TYPE_MASK) { + case BD99955_TYPE_CDP: + return CHARGE_SUPPLIER_BC12_CDP; + case BD99955_TYPE_DCP: + return CHARGE_SUPPLIER_BC12_DCP; + case BD99955_TYPE_SDP: + return CHARGE_SUPPLIER_BC12_SDP; + case BD99955_TYPE_VBUS_OPEN: + case BD99955_TYPE_PUP_PORT: + case BD99955_TYPE_OPEN_PORT: + default: + return CHARGE_SUPPLIER_NONE; + } +} + +static int bd99955_get_bc12_ilim(int charge_supplier) +{ + switch (charge_supplier) { + case CHARGE_SUPPLIER_BC12_CDP: + return 1500; + case CHARGE_SUPPLIER_BC12_DCP: + return 2000; + case CHARGE_SUPPLIER_BC12_SDP: + return 900; + default: + return 500; + } +} + +static int bd99955_enable_usb_switch(enum bd99955_charge_port port, + enum usb_switch setting) +{ + int rv; + int reg; + int port_reg; + + port_reg = (port == BD99955_CHARGE_PORT_VBUS) ? + BD99955_CMD_VBUS_UCD_SET : BD99955_CMD_VCC_UCD_SET; + + rv = ch_raw_read16(port_reg, ®, BD99955_EXTENDED_COMMAND); + if (rv) + return rv; + + if (setting == USB_SWITCH_CONNECT) + reg |= BD99955_CMD_UCD_SET_USB_SW_EN; + else + reg &= ~BD99955_CMD_UCD_SET_USB_SW_EN; + + return ch_raw_write16(port_reg, reg, BD99955_EXTENDED_COMMAND); +} + +static int bd99955_bc12_detect(int port) +{ + int i; + int bc12_type; + struct charge_port_info charge; + + /* + * BC1.2 detection starts 100ms after VBUS/VCC attach and typically + * completes 312ms after VBUS/VCC attach. + */ + msleep(312); + for (i = 0; i < BC12_DETECT_RETRY; i++) { + /* get device type */ + bc12_type = bd99955_get_bc12_device_type(port); + + /* Detected BC1.2 */ + if (bc12_type != CHARGE_SUPPLIER_NONE) + break; + + /* TODO: Add accurate timeout for detecting BC1.2 */ + msleep(100); + } + + /* BC1.2 device attached */ + if (bc12_type != CHARGE_SUPPLIER_NONE) { + /* Update charge manager */ + charge.voltage = USB_CHARGER_VOLTAGE_MV; + charge.current = bd99955_get_bc12_ilim(bc12_type); + charge_manager_update_charge(bc12_type, port, &charge); + + /* notify host of power info change */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + } + + return bc12_type; +} + +static void bd99955_bc12_detach(int port, int type) +{ + struct charge_port_info charge = { + .voltage = USB_CHARGER_VOLTAGE_MV, + .current = 0, + }; + + /* Update charge manager */ + charge_manager_update_charge(type, port, &charge); + + /* Disable charging trigger by BC1.2 detection */ + bd99955_bc12_enable_charging(port, 0); + + /* notify host of power info change */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} +#endif /* defined(HAS_TASK_USB_CHG_P0) || defined(HAS_TASK_USB_CHG_P1) */ + /* chip specific interfaces */ @@ -140,7 +304,6 @@ int charger_set_input_current(int input_current) /* Input current step 32 mA */ input_current &= ~0x1F; - rv = ch_raw_write16(BD99955_CMD_IBUS_LIM_SET, input_current, BD99955_BAT_CHG_COMMAND); if (rv) @@ -247,9 +410,7 @@ int charger_get_status(int *status) *status |= CHARGER_POWER_FAIL; /* Safety signal ranges & battery presence */ - ch_status = (reg & BD99955_CMD_CHGOP_STATUS_BATTEMP0) | - ((reg & BD99955_CMD_CHGOP_STATUS_BATTEMP1) << 1) | - ((reg & BD99955_CMD_CHGOP_STATUS_BATTEMP2) << 2); + ch_status = (reg & BD99955_BATTTEMP_MASK) >> 8; *status |= CHARGER_BATTERY_PRESENT; @@ -346,31 +507,44 @@ static void bd99995_init(void) int reg; const struct battery_info *bi = battery_get_info(); - /* Disable BC1.2 detection on VCC */ + /* Enable BC1.2 detection on VCC */ if (ch_raw_read16(BD99955_CMD_VCC_UCD_SET, ®, BD99955_EXTENDED_COMMAND)) return; - reg &= ~BD99955_CMD_UCD_SET_USBDETEN; + reg |= BD99955_CMD_UCD_SET_USBDETEN; + reg &= ~BD99955_CMD_UCD_SET_USB_SW_EN; ch_raw_write16(BD99955_CMD_VCC_UCD_SET, reg, BD99955_EXTENDED_COMMAND); - /* Disable BC1.2 detection on VBUS */ + /* Enable BC1.2 detection on VBUS */ if (ch_raw_read16(BD99955_CMD_VBUS_UCD_SET, ®, BD99955_EXTENDED_COMMAND)) return; - reg &= ~BD99955_CMD_UCD_SET_USBDETEN; + reg |= BD99955_CMD_UCD_SET_USBDETEN; + reg &= ~BD99955_CMD_UCD_SET_USB_SW_EN; ch_raw_write16(BD99955_CMD_VBUS_UCD_SET, reg, BD99955_EXTENDED_COMMAND); - /* Disable BC1.2 charge enable trigger */ + /* Disable charging trigger by BC1.2 on VCC & VBUS. */ if (ch_raw_read16(BD99955_CMD_CHGOP_SET1, ®, BD99955_EXTENDED_COMMAND)) return; - reg |= (BD99955_CMD_CHGOP_SET1_VCC_BC_DISEN | - BD99955_CMD_CHGOP_SET1_VBUS_BC_DISEN); + reg |= (BD99955_CMD_CHGOP_SET1_SDP_CHG_TRIG_EN | + BD99955_CMD_CHGOP_SET1_SDP_CHG_TRIG | + BD99955_CMD_CHGOP_SET1_VBUS_BC_DISEN | + BD99955_CMD_CHGOP_SET1_VCC_BC_DISEN | + BD99955_CMD_CHGOP_SET1_ILIM_AUTO_DISEN); ch_raw_write16(BD99955_CMD_CHGOP_SET1, reg, BD99955_EXTENDED_COMMAND); + /* Enable BC1.2 USB charging and DC/DC converter */ + if (ch_raw_read16(BD99955_CMD_CHGOP_SET2, ®, + BD99955_EXTENDED_COMMAND)) + return; + reg &= ~(BD99955_CMD_CHGOP_SET2_USB_SUS); + ch_raw_write16(BD99955_CMD_CHGOP_SET2, reg, + BD99955_EXTENDED_COMMAND); + /* Set battery OVP to 500 + maximum battery voltage */ ch_raw_write16(BD99955_CMD_VBATOVP_SET, (bi->voltage_max + 500) & 0x7ff0, @@ -449,6 +623,78 @@ int bd99955_select_input_port(enum bd99955_charge_port port) BD99955_EXTENDED_COMMAND); } +#if defined(HAS_TASK_USB_CHG_P0) || defined(HAS_TASK_USB_CHG_P1) +int bd99955_bc12_enable_charging(enum bd99955_charge_port 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(BD99955_CMD_CHGOP_SET1, ®, + BD99955_EXTENDED_COMMAND); + if (rv) + return rv; + + mask_val = (BD99955_CMD_CHGOP_SET1_SDP_CHG_TRIG_EN | + BD99955_CMD_CHGOP_SET1_SDP_CHG_TRIG | + ((port == BD99955_CHARGE_PORT_VBUS) ? + BD99955_CMD_CHGOP_SET1_VBUS_BC_DISEN : + BD99955_CMD_CHGOP_SET1_VCC_BC_DISEN)); + + if (enable) + reg &= ~mask_val; + else + reg |= mask_val; + + return ch_raw_write16(BD99955_CMD_CHGOP_SET1, reg, + BD99955_EXTENDED_COMMAND); +} + +void usb_charger_set_switches(int port, enum usb_switch setting) +{ + /* If switch is not changing then return */ + if (setting == usb_switch_state[port] || + pd_snk_is_vbus_provided(port)) + return; + + if (setting != USB_SWITCH_RESTORE) + usb_switch_state[port] = setting; + bd99955_enable_usb_switch(port, usb_switch_state[port]); +} + +void usb_charger_task(void) +{ + int port = (task_get_current() == TASK_ID_USB_CHG_P0 ? 0 : 1); + int bc12_type = CHARGE_SUPPLIER_NONE; + int vbus_provided; + + while (1) { + vbus_provided = pd_snk_is_vbus_provided(port); + + if (vbus_provided) { + /* Charger/sync attached */ + bc12_type = bd99955_bc12_detect(port); + } else if (bc12_type != CHARGE_SUPPLIER_NONE && + !vbus_provided) { + /* Charger/sync detached */ + bd99955_bc12_detach(port, bc12_type); + bc12_type = CHARGE_SUPPLIER_NONE; + } + + /* Wait for interrupt */ + task_wait_event(-1); + } +} +#endif /* defined(HAS_TASK_USB_CHG_P0) || defined(HAS_TASK_USB_CHG_P1) */ + + +/*** Console commands ***/ + #ifdef CONFIG_CMD_CHARGER static int read_bat(uint8_t cmd) { diff --git a/driver/charger/bd99955.h b/driver/charger/bd99955.h index 0f3e4aa48d..69884dce13 100644 --- a/driver/charger/bd99955.h +++ b/driver/charger/bd99955.h @@ -58,6 +58,7 @@ enum bd99955_charge_port { #define BD99955_CMD_CHGOP_STATUS_BATTEMP2 (1 << 10) #define BD99955_CMD_CHGOP_STATUS_BATTEMP1 (1 << 9) #define BD99955_CMD_CHGOP_STATUS_BATTEMP0 (1 << 8) +#define BD99955_BATTTEMP_MASK 0x700 #define BD99955_CMD_CHGOP_STATUS_BATTEMP_ROOMTEMP 0 #define BD99955_CMD_CHGOP_STATUS_BATTEMP_HOT1 1 #define BD99955_CMD_CHGOP_STATUS_BATTEMP_HOT2 2 @@ -81,11 +82,16 @@ enum bd99955_charge_port { #define BD99955_CMD_VIN_CTRL_SET_VCC_EN (1 << 5) #define BD99955_CMD_CHGOP_SET1 0x0B +#define BD99955_CMD_CHGOP_SET1_ILIM_AUTO_DISEN (1 << 13) #define BD99955_CMD_CHGOP_SET1_VCC_BC_DISEN (1 << 11) #define BD99955_CMD_CHGOP_SET1_VBUS_BC_DISEN (1 << 10) +#define BD99955_CMD_CHGOP_SET1_SDP_CHG_TRIG_EN (1 << 9) +#define BD99955_CMD_CHGOP_SET1_SDP_CHG_TRIG (1 << 8) + #define BD99955_CMD_CHGOP_SET2 0x0C #define BD99955_CMD_CHGOP_SET2_BATT_LEARN (1 << 8) #define BD99955_CMD_CHGOP_SET2_CHG_EN (1 << 7) +#define BD99955_CMD_CHGOP_SET2_USB_SUS (1 << 6) #define BD99955_CMD_VBUSCLPS_TH_SET 0x0D #define BD99955_CMD_VCCCLPS_TH_SET 0x0E @@ -121,10 +127,39 @@ enum bd99955_charge_port { #define BD99955_CMD_PMON_DACIN_VAL 0x26 #define BD99955_CMD_IOUT_DACIN_VAL 0x27 #define BD99955_CMD_VCC_UCD_SET 0x28 -/* Bits for both VCC_UDC_SET and VBUS_UCD_SET regs */ +/* Bits for both VCC_UCD_SET and VBUS_UCD_SET regs */ #define BD99955_CMD_UCD_SET_BCSRETRY (1 << 12) #define BD99955_CMD_UCD_SET_USBDETEN (1 << 7) +#define BD99955_CMD_UCD_SET_USB_SW_EN (1 << 1) + #define BD99955_CMD_VCC_UCD_STATUS 0x29 +/* Bits for both VCC_UCD_STATUS and VBUS_UCD_STATUS regs */ +#define BD99955_CMD_UCD_STATUS_DCDFAIL (1 << 15) +#define BD99955_CMD_UCD_STATUS_CHGPORT1 (1 << 13) +#define BD99955_CMD_UCD_STATUS_CHGPORT0 (1 << 12) +#define BD99955_CMD_UCD_STATUS_PUPDET (1 << 11) +#define BD99955_CMD_UCD_STATUS_CHGDET (1 << 6) +#define BD99955_TYPE_VBUS_OPEN 0 +#define BD99955_TYPE_SDP BD99955_CMD_UCD_STATUS_CHGPORT0 +/* + * TODO: For CDP detection, from the datasheet CHGDET & CHGPORT[1] bits need + * to be high and rest need to be low. However following bits are high CHGDET, + * DCDFAIL, CHGPORT[1], CHGPORT[0] and rest low. + */ +#define BD99955_TYPE_CDP (BD99955_CMD_UCD_STATUS_CHGDET | \ + BD99955_CMD_UCD_STATUS_CHGPORT1 | \ + BD99955_CMD_UCD_STATUS_CHGPORT0 | \ + BD99955_CMD_UCD_STATUS_DCDFAIL) +#define BD99955_TYPE_DCP (BD99955_CMD_UCD_STATUS_CHGDET | \ + BD99955_CMD_UCD_STATUS_CHGPORT0 | \ + BD99955_CMD_UCD_STATUS_CHGPORT1) +#define BD99955_TYPE_PUP_PORT (BD99955_CMD_UCD_STATUS_PUPDET | \ + BD99955_CMD_UCD_STATUS_DCDFAIL | \ + BD99955_CMD_UCD_STATUS_CHGPORT0) +#define BD99955_TYPE_OPEN_PORT (BD99955_CMD_UCD_STATUS_DCDFAIL | \ + BD99955_CMD_UCD_STATUS_CHGPORT0) +#define BD99955_TYPE_MASK 0xB840 + #define BD99955_CMD_VCC_IDD_STATUS 0x2A #define BD99955_CMD_VCC_UCD_FCTRL_SET 0x2B #define BD99955_CMD_VCC_UCD_FCTRL_EN 0x2C @@ -138,6 +173,9 @@ enum bd99955_charge_port { #define BD99955_CMD_IC_SET1 0x3A #define BD99955_CMD_IC_SET2 0x3B #define BD99955_CMD_SYSTEM_STATUS 0x3C +#define BD99955_CMD_SYSTEM_STATUS_OTPLD_STATE (1 << 1) +#define BD99955_CMD_SYSTEM_STATUS_ALLRST_STATE (1 << 0) + #define BD99955_CMD_SYSTEM_CTRL_SET 0x3D #define BD99955_CMD_SYSTEM_CTRL_SET_OTPLD (1 << 1) #define BD99955_CMD_SYSTEM_CTRL_SET_ALLRST (1 << 0) @@ -213,5 +251,7 @@ enum bd99955_charge_port { int bd99955_extpower_is_present(void); /* Select input port from {VCC, VBUS, VCC&VBUS, NONE}. */ int bd99955_select_input_port(enum bd99955_charge_port port); +/* Enable/Disable charging triggered by BC1.2 */ +int bd99955_bc12_enable_charging(enum bd99955_charge_port port, int enable); #endif /* __CROS_EC_BD99955_H */ diff --git a/include/charge_manager.h b/include/charge_manager.h index ec0e35a7b1..28546e22a1 100644 --- a/include/charge_manager.h +++ b/include/charge_manager.h @@ -100,6 +100,6 @@ void charge_manager_save_log(int port); int board_set_active_charge_port(int charge_port); /* Set the charge current limit. */ -void board_set_charge_limit(int charge_ma); +void board_set_charge_limit(int port, int supplier, int charge_ma); #endif /* __CROS_EC_CHARGE_MANAGER_H */ diff --git a/include/config.h b/include/config.h index c55a234769..effc6d9cc7 100644 --- a/include/config.h +++ b/include/config.h @@ -524,6 +524,7 @@ #undef CONFIG_CMD_BATDEBUG #define CONFIG_CMD_BATTFAKE #define CONFIG_CMD_CHARGER +#define CONFIG_CMD_CHARGE_SUPPLIER_INFO #undef CONFIG_CMD_CHGRAMP #undef CONFIG_CMD_CLOCKGATES #undef CONFIG_CMD_COMXTEST diff --git a/test/charge_manager.c b/test/charge_manager.c index b60e19e0dc..962fc98a64 100644 --- a/test/charge_manager.c +++ b/test/charge_manager.c @@ -37,7 +37,7 @@ static int new_power_request[CONFIG_USB_PD_PORT_COUNT]; static int power_role[CONFIG_USB_PD_PORT_COUNT]; /* Callback functions called by CM on state change */ -void board_set_charge_limit(int charge_ma) +void board_set_charge_limit(int port, int supplier, int charge_ma) { active_charge_limit = charge_ma; } diff --git a/test/charge_ramp.c b/test/charge_ramp.c index 12973f46ff..a3279663e2 100644 --- a/test/charge_ramp.c +++ b/test/charge_ramp.c @@ -53,7 +53,7 @@ int board_is_vbus_too_low(enum chg_ramp_vbus_state ramp_state) vbus_low_current_ma; } -void board_set_charge_limit(int limit_ma) +void board_set_charge_limit(int port, int supplier, int limit_ma) { charge_limit_ma = limit_ma; if (charge_limit_ma > overcurrent_current_ma) |