summaryrefslogtreecommitdiff
path: root/common/charge_manager.c
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2016-08-22 17:11:27 +0200
committerchrome-bot <chrome-bot@chromium.org>2016-09-01 19:52:35 -0700
commit02b80c49f473b872360a782f6a95c607c6734717 (patch)
tree4c4e9b53f264b81d57206a0035a3ce8adbf323a2 /common/charge_manager.c
parentf4863ef03d76fc3923c49bccdfaf28b47ddc80f9 (diff)
downloadchrome-ec-02b80c49f473b872360a782f6a95c607c6734717.tar.gz
pd: manage total source current available
Add a policy to handle the case where the device can source the `CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT` over one of its type-C port if there is no sink connected on the other ones. Signed-off-by: Vincent Palatin <vpalatin@chromium.org> BRANCH=none BUG=chrome-os-partner:56110 TEST=manual: on Kevin, plug and unplug various devices on the 2 ports, while measuring the type-C pull-up with Twinkie. Change-Id: Id5961f04d0a1b1073f5ab340068efd9079918209 Reviewed-on: https://chromium-review.googlesource.com/373818 Commit-Ready: Vincent Palatin <vpalatin@chromium.org> Tested-by: Vincent Palatin <vpalatin@chromium.org> Reviewed-by: Shawn N <shawnn@chromium.org>
Diffstat (limited to 'common/charge_manager.c')
-rw-r--r--common/charge_manager.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/common/charge_manager.c b/common/charge_manager.c
index 13f85e38d0..becb6cc91d 100644
--- a/common/charge_manager.c
+++ b/common/charge_manager.c
@@ -4,6 +4,7 @@
*/
#include "adc.h"
+#include "atomic.h"
#include "battery.h"
#include "charge_manager.h"
#include "charge_ramp.h"
@@ -13,8 +14,10 @@
#include "hooks.h"
#include "host_command.h"
#include "system.h"
+#include "tcpm.h"
#include "timer.h"
#include "usb_pd.h"
+#include "usb_pd_tcpm.h"
#include "util.h"
#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args)
@@ -72,6 +75,10 @@ static int override_port = OVERRIDE_OFF;
static int delayed_override_port = OVERRIDE_OFF;
static timestamp_t delayed_override_deadline;
+/* Bitmap of ports used as power source */
+static volatile uint32_t source_port_bitmap;
+BUILD_ASSERT(sizeof(source_port_bitmap)*8 >= CONFIG_USB_PD_PORT_COUNT);
+
enum charge_manager_change_type {
CHANGE_CHARGE,
CHANGE_DUALROLE,
@@ -885,6 +892,52 @@ int charge_manager_get_power_limit_uw(void)
return current_ma * voltage_mv;
}
+#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT
+void charge_manager_source_port(int port, int enable)
+{
+ uint32_t prev_bitmap = source_port_bitmap;
+ int p;
+
+ if (enable)
+ atomic_or(&source_port_bitmap, 1 << port);
+ else
+ atomic_clear(&source_port_bitmap, 1 << port);
+
+ /* No change, exit early. */
+ if (prev_bitmap == source_port_bitmap)
+ return;
+
+ /* Set port limit according to policy */
+ for (p = 0; p < CONFIG_USB_PD_PORT_COUNT; p++) {
+ /*
+ * if we are the only active source port or there is none,
+ * advertise all the available power.
+ */
+ int rp = (source_port_bitmap & ~(1 << p)) ? CONFIG_USB_PD_PULLUP
+ : CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT;
+
+ tcpm_select_rp_value(p, rp);
+ pd_update_contract(p);
+ }
+}
+
+int charge_manager_get_source_pdo(const uint32_t **src_pdo)
+{
+ int p;
+ int count = 0;
+
+ /* count the number of connected sinks */
+ for (p = 0; p < CONFIG_USB_PD_PORT_COUNT; p++)
+ if (source_port_bitmap & (1 << p))
+ count++;
+
+ /* send the maximum current if we are sourcing only on one port */
+ *src_pdo = count <= 1 ? pd_src_pdo_max : pd_src_pdo;
+
+ return count <= 1 ? pd_src_pdo_cnt : pd_src_pdo_max_cnt;
+}
+#endif /* CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT */
+
#ifndef TEST_BUILD
static int hc_pd_power_info(struct host_cmd_handler_args *args)
{