summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlec Berg <alecaberg@chromium.org>2015-04-03 10:47:48 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-05-01 03:44:19 +0000
commit6dce2424d99de40763a039eb099efcd5b0a52cb2 (patch)
treed54d49f41cb50889c7c00886c3bdfb45877d56d9
parent62080646fe4312de930e4c4d766106438eae5efc (diff)
downloadchrome-ec-6dce2424d99de40763a039eb099efcd5b0a52cb2.tar.gz
charge_manager: modify PD power HC to give more info on current
Change the EC_CMD_USB_PD_POWER_INFO host command to report the input current limit and the max current theoretically possible given the charger. The input current limit field is useful for logging purposes and the max current field is useful to give to powerd to determine if we have a low power charger connected. The max current is determined by checking if the charge supplier is allowed to ramp. If the charge supplier is allowed to ramp and has not completed ramping yet, then max current is the max current that we are allowed to ramp up to. Once the ramp has completed, then max current is the stable charging current. If the charge supplier is not allowed to ramp, then max current is simply the max current as registered with charge_manager. The point here is to keep the max as high as possible until we know for sure it is lower to avoid showing the user the low power notification until we know for sure. This CL also adds a new charger type, USB_CHG_TYPE_UNKNOWN. For a short period after a charger is plugged in, the supplier type may change and PD negotiation is still in process, and therefore we tell the host we have an unknown charger type. This allows powerd to show the charging icon, but delay determining if this is a low power charger until we know for sure. BUG=chrome-os-partner:38548 BRANCH=samus TEST=tested with zinger, a DCP, an SDP, and a proprietary charger. tested that low power notification never pops up with zinger, even if you purposely wedge charge circuit with "charger voltage 7000" on EC console. tested that the other chargers all pop up low power notification once the supplier changes from UNKNOWN to the real supplier. used "ectool --name=cros_pd usbpdpower" to check current values. Change-Id: If8a9a1799504cc2a13238f4e6ec917d25d972b22 Signed-off-by: Alec Berg <alecaberg@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/265066 Reviewed-by: Sameer Nanda <snanda@chromium.org>
-rw-r--r--board/samus_pd/board.h1
-rw-r--r--common/charge_manager.c33
-rw-r--r--common/charge_ramp.c73
-rw-r--r--include/charge_ramp.h14
-rw-r--r--include/config.h3
-rw-r--r--util/ectool.c8
6 files changed, 112 insertions, 20 deletions
diff --git a/board/samus_pd/board.h b/board/samus_pd/board.h
index ea5a7ef290..5e48b5e53a 100644
--- a/board/samus_pd/board.h
+++ b/board/samus_pd/board.h
@@ -53,6 +53,7 @@
#define CONFIG_USB_PD_CUSTOM_VDM
#define CONFIG_USB_PD_DUAL_ROLE
#define CONFIG_USB_PD_FLASH_ERASE_CHECK
+#define CONFIG_USB_PD_HOST_EVENT_ON_POWER_CHANGE
#define CONFIG_USB_PD_INTERNAL_COMP
#define CONFIG_USB_PD_LOGGING
#define CONFIG_USB_PD_LOG_SIZE 512
diff --git a/common/charge_manager.c b/common/charge_manager.c
index 83b0582ddd..7e0600d8d9 100644
--- a/common/charge_manager.c
+++ b/common/charge_manager.c
@@ -192,11 +192,40 @@ static void charge_manager_fill_power_info(int port,
r->meas.voltage_max = available_charge[sup][port].voltage;
if (use_ramp_current) {
- r->meas.current_max = chg_ramp_get_current_limit();
+ /*
+ * If charge_ramp has not detected charger yet,
+ * then charger type is unknown.
+ */
+ if (!chg_ramp_is_detected())
+ r->type = USB_CHG_TYPE_UNKNOWN;
+
+ /* Current limit is output of ramp module */
+ r->meas.current_lim = chg_ramp_get_current_limit();
+
+ /*
+ * If ramp is allowed, then the max current depends
+ * on if ramp is stable. If ramp is stable, then
+ * max current is same as input current limit. If
+ * ramp is not stable, then we report the maximum
+ * current we could ramp up to for this supplier.
+ * If ramp is not allowed, max current is just the
+ * available charge current.
+ */
+ if (board_is_ramp_allowed(sup)) {
+ r->meas.current_max = chg_ramp_is_stable() ?
+ r->meas.current_lim :
+ board_get_ramp_current_limit(
+ sup,
+ available_charge[sup][port].current);
+ } else {
+ r->meas.current_max =
+ available_charge[sup][port].current;
+ }
+
r->max_power =
r->meas.current_max * r->meas.voltage_max;
} else {
- r->meas.current_max =
+ r->meas.current_max = r->meas.current_lim =
available_charge[sup][port].current;
r->max_power = POWER(available_charge[sup][port]);
}
diff --git a/common/charge_ramp.c b/common/charge_ramp.c
index dbe14e11d4..f2a2c8bf51 100644
--- a/common/charge_ramp.c
+++ b/common/charge_ramp.c
@@ -9,6 +9,7 @@
#include "charge_ramp.h"
#include "common.h"
#include "console.h"
+#include "ec_commands.h"
#include "task.h"
#include "timer.h"
#include "usb_pd.h"
@@ -48,7 +49,7 @@
enum chg_ramp_state {
CHG_RAMP_DISCONNECTED,
- CHG_RAMP_CHARGE_DETECT,
+ CHG_RAMP_CHARGE_DETECT_DELAY,
CHG_RAMP_OVERCURRENT_DETECT,
CHG_RAMP_RAMP,
CHG_RAMP_STABILIZE,
@@ -115,8 +116,8 @@ void chg_ramp_charge_supplier_change(int port, int supplier, int current,
reg_time = registration_time;
if (ramp_st != CHG_RAMP_STABILIZE) {
ramp_st = (active_port == CHARGE_PORT_NONE) ?
- CHG_RAMP_DISCONNECTED : CHG_RAMP_CHARGE_DETECT;
- CPRINTS("Ramp reset: st%d\n", ramp_st);
+ CHG_RAMP_DISCONNECTED : CHG_RAMP_CHARGE_DETECT_DELAY;
+ CPRINTS("Ramp reset: st%d", ramp_st);
task_wake(TASK_ID_CHG_RAMP);
}
}
@@ -138,10 +139,24 @@ int chg_ramp_get_current_limit(void)
}
}
+int chg_ramp_is_detected(void)
+{
+ /* Charger detected (charge detect delay has passed) */
+ return ramp_st > CHG_RAMP_CHARGE_DETECT_DELAY;
+}
+
+int chg_ramp_is_stable(void)
+{
+ return ramp_st == CHG_RAMP_STABLE;
+}
+
void chg_ramp_task(void)
{
int task_wait_time = -1;
int i;
+ uint64_t detect_end_time_us = 0, time_us;
+ int last_active_port = CHARGE_PORT_NONE;
+
/*
* Static initializer so that we don't clobber early calls to this
* module.
@@ -162,25 +177,37 @@ void chg_ramp_task(void)
/* Do nothing */
task_wait_time = -1;
break;
- case CHG_RAMP_CHARGE_DETECT:
+ case CHG_RAMP_CHARGE_DETECT_DELAY:
/* Delay for charge_manager to determine supplier */
- /* On entry to state, store the OC recovery time */
- if (ramp_st_prev != ramp_st)
+ /*
+ * On entry to state, or if port changes, store the
+ * OC recovery time, and calculate the detect end
+ * time to exit this state.
+ */
+ if (ramp_st_prev != ramp_st ||
+ active_port != last_active_port) {
+ last_active_port = active_port;
ACTIVE_OC_INFO.recover =
reg_time.val - ACTIVE_OC_INFO.ts.val;
+ detect_end_time_us = get_time().val +
+ CHARGE_DETECT_DELAY;
+ task_wait_time = CHARGE_DETECT_DELAY;
+ break;
+ }
- /*
- * If we are not drawing full charge, then don't ramp,
- * just wait in this state, until we are.
- */
- if (!board_is_consuming_full_charge()) {
- task_wait_time = CURRENT_DRAW_DELAY;
+ /* If detect delay has not passed, set wait time */
+ time_us = get_time().val;
+ if (time_us < detect_end_time_us) {
+ task_wait_time = detect_end_time_us - time_us;
break;
}
+ /* Detect delay is over, fall through to next state */
ramp_st_new = CHG_RAMP_OVERCURRENT_DETECT;
- task_wait_time = CHARGE_DETECT_DELAY;
- break;
+#ifdef CONFIG_USB_PD_HOST_EVENT_ON_POWER_CHANGE
+ /* notify host of power info change */
+ pd_send_host_event(PD_EVENT_POWER_CHANGE);
+#endif
case CHG_RAMP_OVERCURRENT_DETECT:
/* Check if we should ramp or go straight to stable */
task_wait_time = SECOND;
@@ -193,6 +220,15 @@ void chg_ramp_task(void)
}
/*
+ * If we are not drawing full charge, then don't ramp,
+ * just wait in this state, until we are.
+ */
+ if (!board_is_consuming_full_charge()) {
+ task_wait_time = CURRENT_DRAW_DELAY;
+ break;
+ }
+
+ /*
* Compare recent OCP events, if all info matches,
* then we don't need to ramp anymore.
*/
@@ -259,15 +295,20 @@ void chg_ramp_task(void)
ramp_st_new = active_port == CHARGE_PORT_NONE ?
CHG_RAMP_DISCONNECTED :
- CHG_RAMP_CHARGE_DETECT;
+ CHG_RAMP_CHARGE_DETECT_DELAY;
break;
case CHG_RAMP_STABLE:
/* Maintain input current limit */
/* On entry log charging stats */
+ if (ramp_st_prev != ramp_st) {
#ifdef CONFIG_USB_PD_LOGGING
- if (ramp_st_prev != ramp_st)
charge_manager_save_log(active_port);
#endif
+#ifdef CONFIG_USB_PD_HOST_EVENT_ON_POWER_CHANGE
+ /* notify host of power info change */
+ pd_send_host_event(PD_EVENT_POWER_CHANGE);
+#endif
+ }
/* Keep an eye on VBUS and restart ramping if it dips */
if (board_is_ramp_allowed(active_sup) &&
diff --git a/include/charge_ramp.h b/include/charge_ramp.h
index c6e0531496..5779200026 100644
--- a/include/charge_ramp.h
+++ b/include/charge_ramp.h
@@ -58,6 +58,20 @@ int board_is_vbus_too_low(enum chg_ramp_vbus_state ramp_state);
*/
int chg_ramp_get_current_limit(void);
+/**
+ * Return if charge ramping has reached stable state
+ *
+ * @return 1 if stable, 0 otherwise
+ */
+int chg_ramp_is_stable(void);
+
+/**
+ * Return if charge ramping has reached detected state
+ *
+ * @return 1 if detected, 0 otherwise
+ */
+int chg_ramp_is_detected(void);
+
#ifdef HAS_TASK_CHG_RAMP
/**
* Notify charge ramp module of supplier type change on a port. If port
diff --git a/include/config.h b/include/config.h
index 88337a2b29..6e63cec8cd 100644
--- a/include/config.h
+++ b/include/config.h
@@ -1279,6 +1279,9 @@
/* Check whether PD is the sole power source before flash erase operation */
#undef CONFIG_USB_PD_FLASH_ERASE_CHECK
+/* Send host event when power changes */
+#undef CONFIG_USB_PD_HOST_EVENT_ON_POWER_CHANGE
+
/* HW & SW version for alternate mode discover identity response (4bits each) */
#undef CONFIG_USB_PD_IDENTITY_HW_ID
#undef CONFIG_USB_PD_IDENTITY_SW_ID
diff --git a/util/ectool.c b/util/ectool.c
index 92b663e534..c809464d92 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -3771,9 +3771,13 @@ static void print_pd_power_info(struct ec_response_usb_pd_power_info *r)
case USB_CHG_TYPE_VBUS:
printf(" VBUS");
break;
+ case USB_CHG_TYPE_UNKNOWN:
+ printf(" Unknown");
+ break;
}
- printf(" %dmV max %dmV / %dmA",
- r->meas.voltage_now, r->meas.voltage_max, r->meas.current_max);
+ printf(" %dmV / %dmA, max %dmV / %dmA",
+ r->meas.voltage_now, r->meas.current_lim, r->meas.voltage_max,
+ r->meas.current_max);
if (r->max_power)
printf(" / %dmW", r->max_power / 1000);
printf("\n");