summaryrefslogtreecommitdiff
path: root/board/samus_pd/board.c
diff options
context:
space:
mode:
Diffstat (limited to 'board/samus_pd/board.c')
-rw-r--r--board/samus_pd/board.c167
1 files changed, 87 insertions, 80 deletions
diff --git a/board/samus_pd/board.c b/board/samus_pd/board.c
index d89527dfc2..3fd3f0e219 100644
--- a/board/samus_pd/board.c
+++ b/board/samus_pd/board.c
@@ -37,11 +37,9 @@ static enum power_state ps;
/* Battery state of charge */
static int batt_soc;
-static int fake_state_of_charge = -1; /* use real soc by default */
-/* Last charge port override when charging turned off due to full battery */
-static int chg_override_port = OVERRIDE_OFF;
-static int chg_is_cutoff;
+/* Default to 5V charging allowed for dead battery case */
+enum pd_charge_state charge_state = PD_CHARGE_5V;
/* PD MCU status and host event status for host command */
static struct ec_response_pd_status pd_status;
@@ -266,31 +264,6 @@ void usb1_evt(enum gpio_signal signal)
wake_usb_charger_task(1);
}
-/* When battery is full, cutoff charging by disabling AC input current */
-static void check_charging_cutoff(void)
-{
- int port;
-
- /* Only check if charging needs to be turned off when not in S0 */
- if (ps == POWER_S0)
- return;
-
- port = charge_manager_get_active_charge_port();
-
- /*
- * If battery is full disable charging, if battery is not full, restore
- * charge port.
- */
- if (!chg_is_cutoff && port != CHARGE_PORT_NONE && batt_soc == 100) {
- charge_manager_set_override(OVERRIDE_DONT_CHARGE);
- chg_is_cutoff = 1;
- } else if (chg_is_cutoff && batt_soc < 100) {
- charge_manager_set_override(chg_override_port);
- chg_is_cutoff = 0;
- }
-}
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, check_charging_cutoff, HOOK_PRIO_DEFAULT);
-
static void chipset_s5_to_s3(void)
{
ps = POWER_S3;
@@ -301,9 +274,6 @@ static void chipset_s3_to_s0(void)
{
/* Disable deep sleep and restore charge override port */
disable_sleep(SLEEP_MASK_AP_RUN);
- charge_manager_set_override(chg_override_port);
- chg_is_cutoff = 0;
-
ps = POWER_S0;
hook_notify(HOOK_CHIPSET_RESUME);
}
@@ -318,8 +288,6 @@ static void chipset_s0_to_s3(void)
{
/* Enable deep sleep and store charge override port */
enable_sleep(SLEEP_MASK_AP_RUN);
- chg_override_port = charge_manager_get_override();
-
ps = POWER_S3;
hook_notify(HOOK_CHIPSET_SUSPEND);
}
@@ -438,6 +406,9 @@ static void board_init(void)
gpio_enable_interrupt(GPIO_PCH_SLP_S3_L);
gpio_enable_interrupt(GPIO_PCH_SLP_S5_L);
+ /* Initialize active charge port to none */
+ pd_status.active_charge_port = CHARGE_PORT_NONE;
+
/*
* Do not enable PD communication in RO as a security measure.
* We don't want to allow communication to outside world until
@@ -596,7 +567,6 @@ void board_flip_usb_mux(int port)
void board_update_battery_soc(int soc)
{
batt_soc = soc;
- check_charging_cutoff();
}
int board_get_battery_soc(void)
@@ -643,26 +613,42 @@ int board_set_active_charge_port(int charge_port)
return EC_ERROR_INVAL;
}
- pd_status.active_charge_port = charge_port;
- gpio_set_level(GPIO_USB_C0_CHARGE_EN_L, !(charge_port == 0));
- gpio_set_level(GPIO_USB_C1_CHARGE_EN_L, !(charge_port == 1));
+ CPRINTS("New chg p%d", charge_port);
/*
- * If new charge port when charge is cutoff, then user must have
- * plugged in a new dedicated charger. This resets the charge
- * override port and clears the charge cutoff flag.
+ * If charging and the active charge port is changed, then disable
+ * charging to guarantee charge circuit starts up cleanly.
*/
- if (chg_is_cutoff && is_real_port) {
- chg_override_port = OVERRIDE_OFF;
- chg_is_cutoff = 0;
+ if (pd_status.active_charge_port != CHARGE_PORT_NONE &&
+ (charge_port == CHARGE_PORT_NONE ||
+ charge_port != pd_status.active_charge_port)) {
+ gpio_set_level(GPIO_USB_C0_CHARGE_EN_L, 1);
+ gpio_set_level(GPIO_USB_C1_CHARGE_EN_L, 1);
+ charge_state = PD_CHARGE_NONE;
+ pd_status.active_charge_port = charge_port;
+ CPRINTS("Chg: None\n");
+ return EC_SUCCESS;
+ }
+
+ /* Save active charge port and enable charging if allowed */
+ pd_status.active_charge_port = charge_port;
+ if (charge_state != PD_CHARGE_NONE) {
+ gpio_set_level(GPIO_USB_C0_CHARGE_EN_L, !(charge_port == 0));
+ gpio_set_level(GPIO_USB_C1_CHARGE_EN_L, !(charge_port == 1));
}
- check_charging_cutoff();
- CPRINTS("New chg p%d", charge_port);
return EC_SUCCESS;
}
/**
+ * Return if max voltage charging is allowed.
+ */
+int pd_is_max_request_allowed(void)
+{
+ return charge_state == PD_CHARGE_MAX;
+}
+
+/**
* Set the charge limit based upon desired maximum.
*
* @param charge_ma Desired charge limit (mA).
@@ -732,36 +718,6 @@ DECLARE_CONSOLE_COMMAND(pdevent, command_pd_host_event,
"Send PD host event",
NULL);
-static int command_battfake(int argc, char **argv)
-{
- char *e;
- int v;
-
- if (argc == 2) {
- v = strtoi(argv[1], &e, 0);
- if (*e || v < -1 || v > 100)
- return EC_ERROR_PARAM1;
-
- fake_state_of_charge = v;
- }
-
- if (fake_state_of_charge < 0) {
- ccprintf("Using real batt level\n");
- } else {
- ccprintf("Using fake batt level %d%%\n",
- fake_state_of_charge);
- }
-
- /* Send EC int to get batt info from EC */
- pd_send_ec_int();
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(battfake, command_battfake,
- "percent (-1 = use real level)",
- "Set fake battery level",
- NULL);
-
/****************************************************************************/
/* Host commands */
static int ec_status_host_cmd(struct host_cmd_handler_args *args)
@@ -769,9 +725,60 @@ static int ec_status_host_cmd(struct host_cmd_handler_args *args)
const struct ec_params_pd_status *p = args->params;
struct ec_response_pd_status *r = args->response;
- /* if not using fake soc, then update battery soc */
- board_update_battery_soc(fake_state_of_charge < 0 ?
- p->batt_soc : fake_state_of_charge);
+ /* update battery soc */
+ board_update_battery_soc(p->batt_soc);
+
+ if (args->version == 1) {
+ if (p->charge_state != charge_state) {
+ switch (p->charge_state) {
+ case PD_CHARGE_NONE:
+ /*
+ * No current allowed in, set new power request
+ * so that PD negotiates down to vSafe5V.
+ */
+ charge_state = p->charge_state;
+ gpio_set_level(GPIO_USB_C0_CHARGE_EN_L, 1);
+ gpio_set_level(GPIO_USB_C1_CHARGE_EN_L, 1);
+ pd_set_new_power_request(
+ pd_status.active_charge_port);
+ CPRINTS("Chg: None");
+ break;
+ case PD_CHARGE_5V:
+ /* Allow current on the active charge port */
+ charge_state = p->charge_state;
+ gpio_set_level(GPIO_USB_C0_CHARGE_EN_L,
+ !(pd_status.active_charge_port == 0));
+ gpio_set_level(GPIO_USB_C1_CHARGE_EN_L,
+ !(pd_status.active_charge_port == 1));
+ CPRINTS("Chg: 5V");
+ break;
+ case PD_CHARGE_MAX:
+ /*
+ * Allow negotiation above vSafe5V. Should only
+ * ever get this command when 5V charging is
+ * already allowed.
+ */
+ if (charge_state == PD_CHARGE_5V) {
+ charge_state = p->charge_state;
+ pd_set_new_power_request(
+ pd_status.active_charge_port);
+ CPRINTS("Chg: Max");
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ } else {
+ /*
+ * If the EC is using this command version, then it won't ever
+ * set charging allowed, so we should just assume charging at
+ * the max is allowed.
+ */
+ charge_state = PD_CHARGE_MAX;
+ pd_set_new_power_request(pd_status.active_charge_port);
+ CPRINTS("Chg: Max");
+ }
*r = pd_status;
@@ -783,7 +790,7 @@ static int ec_status_host_cmd(struct host_cmd_handler_args *args)
return EC_RES_SUCCESS;
}
DECLARE_HOST_COMMAND(EC_CMD_PD_EXCHANGE_STATUS, ec_status_host_cmd,
- EC_VER_MASK(0));
+ EC_VER_MASK(0) | EC_VER_MASK(1));
static int host_event_status_host_cmd(struct host_cmd_handler_args *args)
{