summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill Tsai <will_tsai@wistron.corp-partner.google.com>2022-09-07 19:40:00 +0800
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-10-19 10:26:14 +0000
commit13549841b89f14354eba1412c7a20fa018258d5f (patch)
tree304bf9dc93152a9fe959e3a1eebbf293772154cd
parentfbc8ddd25c7c569213542034feab8fa9346b99d9 (diff)
downloadchrome-ec-13549841b89f14354eba1412c7a20fa018258d5f.tar.gz
dps: limit the minimum operating power when AC only
We found that the system will fail to boot without battery if PDO 5V/3A is selected. To prevent boot failed, limit the minimum operating power to the larger PDO when the system is booting up without battery. BUG=b:240533589 TEST=On Joxer, confirm the selected power is equal to 9V when system booting, and the system boot up successfully. TEST=./twister -v -i --coverage -p native_posix -p unit_testing BRANCH=none Signed-off-by: Will Tsai <will_tsai@wistron.corp-partner.google.com> Change-Id: I5d9655b09eead6791c5a3bf161e574f26f6beb02 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3878627 Reviewed-by: Diana Z <dzigterman@chromium.org> Code-Coverage: Zoss <zoss-cl-coverage@prod.google.com> Reviewed-by: Aaron Massey <aaronmassey@google.com>
-rw-r--r--common/dps.c63
-rw-r--r--include/dps.h9
-rw-r--r--zephyr/test/drivers/default/src/integration/usbc/usb_5v_3a_pd_source.c51
-rw-r--r--zephyr/test/drivers/testcase.yaml2
4 files changed, 96 insertions, 29 deletions
diff --git a/common/dps.c b/common/dps.c
index 13f551a95d..c5a8ba4045 100644
--- a/common/dps.c
+++ b/common/dps.c
@@ -16,6 +16,7 @@
#include "charge_manager.h"
#include "charge_state.h"
#include "ec_commands.h"
+#include "hooks.h"
#include "math_util.h"
#include "task.h"
#include "timer.h"
@@ -30,13 +31,8 @@
#define T_REQUEST_STABLE_TIME (10 * SECOND)
#define T_NEXT_CHECK_TIME (5 * SECOND)
-#define DPS_FLAG_DISABLED BIT(0)
-#define DPS_FLAG_NO_SRCCAP BIT(1)
-#define DPS_FLAG_WAITING BIT(2)
-#define DPS_FLAG_SAMPLED BIT(3)
-#define DPS_FLAG_NEED_MORE_PWR BIT(4)
-
-#define DPS_FLAG_STOP_EVENTS (DPS_FLAG_DISABLED | DPS_FLAG_NO_SRCCAP)
+#define DPS_FLAG_STOP_EVENTS \
+ (DPS_FLAG_DISABLED | DPS_FLAG_NO_SRCCAP | DPS_FLAG_NO_BATTERY)
#define DPS_FLAG_ALL GENMASK(31, 0)
#define MAX_MOVING_AVG_WINDOW 5
@@ -52,7 +48,7 @@ static bool fake_enabled;
static int fake_mv, fake_ma;
static int dynamic_mv;
static int dps_port = CHARGE_PORT_NONE;
-static uint32_t flag;
+static atomic_t flag;
#define CPRINTF(format, args...) cprintf(CC_USBPD, "DPS " format, ##args)
#define CPRINTS(format, args...) cprints(CC_USBPD, "DPS " format, ##args)
@@ -370,18 +366,18 @@ __maybe_unused static bool has_new_power_request(struct pdo_candidate *cand)
*/
if (is_near_limit(input_pwr_avg, req_pwr) ||
is_near_limit(input_curr_avg, MIN(req_ma, input_curr_limit))) {
- flag |= DPS_FLAG_NEED_MORE_PWR;
+ atomic_or(&flag, DPS_FLAG_NEED_MORE_PWR);
if (!fake_enabled)
input_pwr_avg = req_pwr + 1;
} else {
- flag &= ~DPS_FLAG_NEED_MORE_PWR;
+ atomic_clear_bits(&flag, DPS_FLAG_NEED_MORE_PWR);
}
if (debug_level)
CPRINTS("C%d 0x%x last (%dmW %dmV) input (%dmW %dmV %dmA) "
"avg (%dmW, %dmA)",
- active_port, flag, req_pwr, req_mv, input_pwr, vbus,
- input_curr, input_pwr_avg, input_curr_avg);
+ active_port, (int)flag, req_pwr, req_mv, input_pwr,
+ vbus, input_curr, input_pwr_avg, input_curr_avg);
for (int i = 0; i < board_get_usb_pd_port_count(); ++i) {
const uint32_t *const src_caps = pd_get_src_caps(i);
@@ -498,29 +494,34 @@ void dps_task(void *u)
dps_reset();
task_wait_event(-1);
/* clear flags after wake up. */
- flag = 0;
+ atomic_clear(&flag);
update_timeout(dps_config.t_check);
continue;
} else if (now.val < timeout.val) {
- flag |= DPS_FLAG_WAITING;
+ atomic_or(&flag, DPS_FLAG_WAITING);
task_wait_event(timeout.val - now.val);
- flag &= ~DPS_FLAG_WAITING;
+ atomic_clear_bits(&flag, DPS_FLAG_WAITING);
continue;
}
if (!is_enabled) {
- flag |= DPS_FLAG_DISABLED;
+ atomic_or(&flag, DPS_FLAG_DISABLED);
continue;
}
if (!has_srccap()) {
- flag |= DPS_FLAG_NO_SRCCAP;
+ atomic_or(&flag, DPS_FLAG_NO_SRCCAP);
+ continue;
+ }
+
+ if (battery_is_present() != BP_YES) {
+ atomic_or(&flag, DPS_FLAG_NO_BATTERY);
continue;
}
if (!has_new_power_request(&curr_cand)) {
sample_count = 0;
- flag &= ~DPS_FLAG_SAMPLED;
+ atomic_clear_bits(&flag, DPS_FLAG_SAMPLED);
} else {
if (last_cand.port == curr_cand.port &&
last_cand.mv == curr_cand.mv &&
@@ -528,7 +529,7 @@ void dps_task(void *u)
sample_count++;
else
sample_count = 1;
- flag |= DPS_FLAG_SAMPLED;
+ atomic_or(&flag, DPS_FLAG_SAMPLED);
}
if (sample_count == dps_config.k_sample) {
@@ -536,17 +537,28 @@ void dps_task(void *u)
dps_port = curr_cand.port;
pd_dpm_request(dps_port, DPM_REQUEST_NEW_POWER_LEVEL);
sample_count = 0;
- flag &= ~(DPS_FLAG_SAMPLED | DPS_FLAG_NEED_MORE_PWR);
+ atomic_clear_bits(&flag, (DPS_FLAG_SAMPLED |
+ DPS_FLAG_NEED_MORE_PWR));
}
last_cand.port = curr_cand.port;
last_cand.mv = curr_cand.mv;
last_cand.mw = curr_cand.mw;
-
update_timeout(dps_config.t_check);
}
}
+void check_battery_present(void)
+{
+ const struct batt_params *batt = charger_current_battery_params();
+
+ if (batt->is_present == BP_YES && (flag & DPS_FLAG_NO_BATTERY)) {
+ atomic_clear_bits(&flag, DPS_FLAG_NO_BATTERY);
+ task_wake(TASK_ID_DPS);
+ }
+}
+DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, check_battery_present, HOOK_PRIO_DEFAULT);
+
static int command_dps(int argc, const char **argv)
{
int port = charge_manager_get_active_charge_port();
@@ -558,8 +570,9 @@ static int command_dps(int argc, const char **argv)
int batt_mv;
ccprintf("flag=0x%x k_more=%d k_less=%d k_sample=%d k_win=%d\n",
- flag, dps_config.k_more_pwr, dps_config.k_less_pwr,
- dps_config.k_sample, dps_config.k_window);
+ (int)flag, dps_config.k_more_pwr,
+ dps_config.k_less_pwr, dps_config.k_sample,
+ dps_config.k_window);
ccprintf("t_stable=%d t_check=%d\n",
dps_config.t_stable / SECOND,
dps_config.t_check / SECOND);
@@ -703,4 +716,8 @@ __test_only int *dps_get_debug_level(void)
{
return &debug_level;
}
+__test_only int dps_get_flag(void)
+{
+ return flag;
+}
#endif /* TEST_BUILD */
diff --git a/include/dps.h b/include/dps.h
index 0cb2a9455b..8794220ab2 100644
--- a/include/dps.h
+++ b/include/dps.h
@@ -10,6 +10,13 @@
#include "common.h"
+#define DPS_FLAG_DISABLED BIT(0)
+#define DPS_FLAG_NO_SRCCAP BIT(1)
+#define DPS_FLAG_WAITING BIT(2)
+#define DPS_FLAG_SAMPLED BIT(3)
+#define DPS_FLAG_NEED_MORE_PWR BIT(4)
+#define DPS_FLAG_NO_BATTERY BIT(5)
+
/* Dynamic PDO Selection config. */
struct dps_config_t {
/* (0, 100) coeff for transition to a lower power PDO*/
@@ -76,6 +83,8 @@ __test_only bool dps_is_fake_enabled(void);
__test_only int dps_get_fake_mv(void);
__test_only int dps_get_fake_ma(void);
__test_only int *dps_get_debug_level(void);
+__test_only int dps_get_flag(void);
+
#endif
#endif /* __CROS_EC_DPS__H */
diff --git a/zephyr/test/drivers/default/src/integration/usbc/usb_5v_3a_pd_source.c b/zephyr/test/drivers/default/src/integration/usbc/usb_5v_3a_pd_source.c
index fcc213d252..c73cf26f37 100644
--- a/zephyr/test/drivers/default/src/integration/usbc/usb_5v_3a_pd_source.c
+++ b/zephyr/test/drivers/default/src/integration/usbc/usb_5v_3a_pd_source.c
@@ -7,17 +7,23 @@
#include <zephyr/sys/slist.h>
#include <zephyr/ztest.h>
+#include "battery.h"
#include "battery_smart.h"
+#include "dps.h"
#include "emul/emul_isl923x.h"
#include "emul/emul_smart_battery.h"
#include "emul/tcpc/emul_tcpci_partner_src.h"
#include "system.h"
+#include "task.h"
#include "test/drivers/test_state.h"
#include "test/drivers/utils.h"
#include "usb_pd.h"
#define BATTERY_NODE DT_NODELABEL(battery)
+#define GPIO_BATT_PRES_ODL_PATH DT_PATH(named_gpios, ec_batt_pres_odl)
+#define GPIO_BATT_PRES_ODL_PORT DT_GPIO_PIN(GPIO_BATT_PRES_ODL_PATH, gpios)
+
struct usb_attach_5v_3a_pd_source_fixture {
struct tcpci_partner_data source_5v_3a;
struct tcpci_src_emul_data src_ext;
@@ -58,6 +64,15 @@ static void usb_attach_5v_3a_pd_source_after(void *data)
disconnect_source_from_port(fixture->tcpci_emul, fixture->charger_emul);
}
+static void control_battery_present(bool present)
+{
+ const struct device *dev =
+ DEVICE_DT_GET(DT_GPIO_CTLR(GPIO_BATT_PRES_ODL_PATH, gpios));
+
+ /* 0 means battery present */
+ zassume_ok(gpio_emul_input_set(dev, GPIO_BATT_PRES_ODL_PORT, !present));
+}
+
ZTEST_SUITE(usb_attach_5v_3a_pd_source, drivers_predicate_post_main,
usb_attach_5v_3a_pd_source_setup, usb_attach_5v_3a_pd_source_before,
usb_attach_5v_3a_pd_source_after, NULL);
@@ -68,8 +83,7 @@ ZTEST(usb_attach_5v_3a_pd_source, test_battery_is_charging)
uint16_t battery_status;
zassume_ok(sbat_emul_get_word_val(emul, SB_BATTERY_STATUS,
- &battery_status),
- NULL);
+ &battery_status));
zassert_equal(battery_status & STATUS_DISCHARGING, 0,
"Battery is discharging: %d", battery_status);
}
@@ -137,8 +151,7 @@ ZTEST_F(usb_attach_5v_3a_pd_source, test_disconnect_battery_not_charging)
disconnect_source_from_port(fixture->tcpci_emul, fixture->charger_emul);
zassert_ok(sbat_emul_get_word_val(emul, SB_BATTERY_STATUS,
- &battery_status),
- NULL);
+ &battery_status));
zassert_equal(battery_status & STATUS_DISCHARGING, STATUS_DISCHARGING,
"Battery is not discharging: %d", battery_status);
}
@@ -225,7 +238,7 @@ ZTEST(usb_attach_5v_3a_pd_source,
batt_data->design_cap / 100) -
1;
- zassert_true(system_can_boot_ap(), NULL);
+ zassert_true(system_can_boot_ap());
}
ZTEST_F(usb_attach_5v_3a_pd_source,
@@ -246,7 +259,7 @@ ZTEST_F(usb_attach_5v_3a_pd_source,
disconnect_source_from_port(fixture->tcpci_emul, fixture->charger_emul);
- zassert_false(system_can_boot_ap(), NULL);
+ zassert_false(system_can_boot_ap());
}
ZTEST_F(usb_attach_5v_3a_pd_source, test_uvdm_ignored)
@@ -282,3 +295,29 @@ ZTEST_F(usb_attach_5v_3a_pd_source, test_uvdm_ignored)
zassert_false(tcpm_response,
"Sent unstructured VDM to TCPM; TCPM did not ignore");
}
+
+ZTEST_F(usb_attach_5v_3a_pd_source, test_dps_battery_absent)
+{
+ control_battery_present(false);
+ zassert_false(battery_is_present(), "dps battery is present");
+ task_wake(TASK_ID_DPS);
+ /* wait dps_config.t_check*/
+ k_sleep(K_MSEC(5000));
+ zassert_true(dps_get_flag() & DPS_FLAG_NO_BATTERY,
+ "DPS_FLAG_NO_BATTERY is set");
+ control_battery_present(true);
+ zassert_true(battery_is_present(), "dps battery is not present");
+}
+
+ZTEST_F(usb_attach_5v_3a_pd_source, test_dps_enable)
+{
+ dps_enable(false);
+ zassert_false(dps_is_enabled());
+ task_wake(TASK_ID_DPS);
+ /* wait dps_config.t_check*/
+ k_sleep(K_MSEC(5000));
+ zassert_true(dps_get_flag() & DPS_FLAG_DISABLED,
+ "DPS_FLAG_DISABLED is set");
+ dps_enable(true);
+ zassert_true(dps_is_enabled());
+}
diff --git a/zephyr/test/drivers/testcase.yaml b/zephyr/test/drivers/testcase.yaml
index 3cc47248af..d6530bcd9a 100644
--- a/zephyr/test/drivers/testcase.yaml
+++ b/zephyr/test/drivers/testcase.yaml
@@ -10,6 +10,7 @@ tests:
- CONFIG_PLATFORM_EC_BATTERY_CUT_OFF=y
- CONFIG_PLATFORM_EC_LID_ANGLE_UPDATE=y
- CONFIG_PLATFORM_EC_CBI_EEPROM=y
+ - CONFIG_PLATFORM_EC_USB_PD_DPS=y
drivers.default.mock_power:
timeout: 240
extra_args: CONF_FILE="prj.conf;default/prj.conf"
@@ -20,6 +21,7 @@ tests:
- CONFIG_PLATFORM_EC_LID_ANGLE_UPDATE=y
- CONFIG_POWER_SEQUENCE_MOCK=y
- CONFIG_PLATFORM_EC_CBI_EEPROM=y
+ - CONFIG_PLATFORM_EC_USB_PD_DPS=y
drivers.button:
timeout: 240
extra_configs: