summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlec Berg <alecaberg@chromium.org>2015-06-05 14:40:02 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-06-07 19:09:06 +0000
commitdab5edc1b4f7658fd6141ec3b8e5826ad52cd84b (patch)
treeaa3e75c80d8888f8c4699256a5fb6d5d3445e95b
parentea07b1851b0fef035a253ab2ab4e788228a06a19 (diff)
downloadchrome-ec-dab5edc1b4f7658fd6141ec3b8e5826ad52cd84b.tar.gz
glados: enable CHARGE_MANAGER to handle charging on both ports
Enable CONFIG_CHARGE_MANAGER to handle charging on two ports. For now, we only use the type-C pull-up supplier and the PD supplier. This adds Pericom BC1.2 suppliers as well even though we aren't using them. Currently, on Glados, we can't detect VBUS unless charge_en GPIO is asserted. This means, when no charger is plugged in, we must have both ports enabled. And when one charger is plugged in, we must disable the other port. Practically, this means we always charge from first charger plugged in since we can't detect the second one. And, this means that if you do chgoverride -1, which normally stops charging, this will actually enable charging on both ports. BUG=chrome-os-partner:40920 BRANCH=none TEST=load onto glados and plug in zinger and donette onto both ports. verify that we always charge from first charger plugged in. plug in hoho to either port and make sure it gets VBUS. Change-Id: Ia5d5725ee86b25f6fec0f276d4c471f533c81112 Signed-off-by: Alec Berg <alecaberg@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/275686 Reviewed-by: Shawn N <shawnn@chromium.org>
-rw-r--r--board/glados/board.c125
-rw-r--r--board/glados/board.h20
-rw-r--r--board/glados/usb_pd_policy.c35
3 files changed, 162 insertions, 18 deletions
diff --git a/board/glados/board.c b/board/glados/board.c
index 2d17d671f7..e72e631b17 100644
--- a/board/glados/board.c
+++ b/board/glados/board.c
@@ -7,6 +7,8 @@
#include "adc_chip.h"
#include "button.h"
+#include "charge_manager.h"
+#include "charge_state.h"
#include "charger.h"
#include "console.h"
#include "extpower.h"
@@ -32,6 +34,10 @@
#define I2C_ADDR_BD99992 0x60
+/* Default input current limit when VBUS is present */
+#define DEFAULT_CURR_LIMIT 500 /* mA */
+#define USB_BC12_CHARGE_VOLTAGE 5000 /* mV */
+
/* Exchange status with PD MCU. */
static void pd_mcu_interrupt(enum gpio_signal signal)
{
@@ -95,6 +101,19 @@ const struct i2c_port_t i2c_ports[] = {
};
const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
+/* Charge supplier priority: lower number indicates higher priority. */
+const int supplier_priority[] = {
+ [CHARGE_SUPPLIER_PD] = 0,
+ [CHARGE_SUPPLIER_TYPEC] = 1,
+ [CHARGE_SUPPLIER_PROPRIETARY] = 1,
+ [CHARGE_SUPPLIER_BC12_DCP] = 1,
+ [CHARGE_SUPPLIER_BC12_CDP] = 2,
+ [CHARGE_SUPPLIER_BC12_SDP] = 3,
+ [CHARGE_SUPPLIER_OTHER] = 3,
+ [CHARGE_SUPPLIER_VBUS] = 4
+};
+BUILD_ASSERT(ARRAY_SIZE(supplier_priority) == CHARGE_SUPPLIER_COUNT);
+
/**
* Discharge battery when on AC power for factory test.
*/
@@ -137,10 +156,116 @@ DECLARE_HOOK(HOOK_CHIPSET_PRE_INIT, pmic_init, HOOK_PRIO_DEFAULT);
/* Initialize board. */
static void board_init(void)
{
+ int i;
+ struct charge_port_info charge_none, charge_vbus;
+
/* Enable PD MCU interrupt */
gpio_enable_interrupt(GPIO_PD_MCU_INT);
/* Enable VBUS interrupt */
gpio_enable_interrupt(GPIO_USB_C0_VBUS_WAKE_L);
gpio_enable_interrupt(GPIO_USB_C1_VBUS_WAKE_L);
+
+ /* Initialize all pericom charge suppliers to 0 */
+ charge_none.voltage = USB_BC12_CHARGE_VOLTAGE;
+ charge_none.current = 0;
+ for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) {
+ charge_manager_update_charge(CHARGE_SUPPLIER_PROPRIETARY,
+ i,
+ &charge_none);
+ charge_manager_update_charge(CHARGE_SUPPLIER_BC12_CDP,
+ i,
+ &charge_none);
+ charge_manager_update_charge(CHARGE_SUPPLIER_BC12_DCP,
+ i,
+ &charge_none);
+ charge_manager_update_charge(CHARGE_SUPPLIER_BC12_SDP,
+ i,
+ &charge_none);
+ charge_manager_update_charge(CHARGE_SUPPLIER_OTHER,
+ i,
+ &charge_none);
+ }
+
+ /* Initialize VBUS supplier based on whether or not VBUS is present */
+ charge_vbus.voltage = USB_BC12_CHARGE_VOLTAGE;
+ charge_vbus.current = DEFAULT_CURR_LIMIT;
+ if (!gpio_get_level(GPIO_USB_C0_VBUS_WAKE_L))
+ charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, 0,
+ &charge_vbus);
+ else
+ charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, 0,
+ &charge_none);
+
+ if (!gpio_get_level(GPIO_USB_C1_VBUS_WAKE_L))
+ charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, 1,
+ &charge_vbus);
+ else
+ charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, 1,
+ &charge_none);
}
DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT);
+
+/**
+ * Set active charge port -- only one port can be active at a time.
+ *
+ * @param charge_port Charge port to enable.
+ *
+ * Returns EC_SUCCESS if charge port is accepted and made active,
+ * EC_ERROR_* otherwise.
+ */
+int board_set_active_charge_port(int charge_port)
+{
+ /* charge port is a realy physical 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);
+
+ if (is_real_port && source) {
+ CPRINTS("Skip enable p%d", charge_port);
+ return EC_ERROR_INVAL;
+ }
+
+ CPRINTS("New chg p%d", charge_port);
+
+ if (charge_port == CHARGE_PORT_NONE) {
+ /*
+ * TODO: currently we only get VBUS knowledge when charge
+ * is enabled. so, when not charging, we need to enable
+ * both ports. but, this is dangerous if you have two
+ * chargers plugged in and you set charge override to -1
+ * then it will enable both sides!
+ */
+ gpio_set_level(GPIO_USB_C0_CHARGE_EN_L, 0);
+ gpio_set_level(GPIO_USB_C1_CHARGE_EN_L, 0);
+ } else {
+ /* Make sure non-charging port is disabled */
+ gpio_set_level(charge_port ? GPIO_USB_C0_CHARGE_EN_L :
+ GPIO_USB_C1_CHARGE_EN_L, 1);
+ /* Enable charging port */
+ gpio_set_level(charge_port ? GPIO_USB_C1_CHARGE_EN_L :
+ GPIO_USB_C0_CHARGE_EN_L, 0);
+ }
+
+ return EC_SUCCESS;
+}
+
+/**
+ * Set the charge limit based upon desired maximum.
+ *
+ * @param charge_ma Desired charge limit (mA).
+ */
+void board_set_charge_limit(int charge_ma)
+{
+ charge_set_input_current_limit(MAX(charge_ma,
+ CONFIG_CHARGER_INPUT_CURRENT));
+}
+
+/* Charge manager callback function, called on delayed override timeout */
+void board_charge_manager_override_timeout(void)
+{
+ /* TODO: what to do here? */
+}
+DECLARE_DEFERRED(board_charge_manager_override_timeout);
+
diff --git a/board/glados/board.h b/board/glados/board.h
index 4f1eb3dd50..ecf0590a7e 100644
--- a/board/glados/board.h
+++ b/board/glados/board.h
@@ -12,6 +12,7 @@
#define CONFIG_ADC
#define CONFIG_BATTERY_SMART
#define CONFIG_BUTTON_COUNT 2
+#define CONFIG_CHARGE_MANAGER
#define CONFIG_CHARGER
#define CONFIG_CHARGER_V2
@@ -64,6 +65,9 @@
#define I2C_PORT_ACCEL MEC1322_I2C2
#define I2C_PORT_PMIC MEC1322_I2C3
+#undef DEFERRABLE_MAX_COUNT
+#define DEFERRABLE_MAX_COUNT 9
+
#ifndef __ASSEMBLER__
#include "gpio_signal.h"
@@ -92,6 +96,22 @@ enum power_signal {
POWER_SIGNAL_COUNT
};
+/* Charge suppliers */
+enum charge_supplier {
+ CHARGE_SUPPLIER_PD,
+ CHARGE_SUPPLIER_TYPEC,
+ CHARGE_SUPPLIER_BC12_DCP,
+ CHARGE_SUPPLIER_BC12_CDP,
+ CHARGE_SUPPLIER_BC12_SDP,
+ CHARGE_SUPPLIER_PROPRIETARY,
+ CHARGE_SUPPLIER_OTHER,
+ CHARGE_SUPPLIER_VBUS,
+ CHARGE_SUPPLIER_COUNT
+};
+
+/* supplier_priority table defined in board.c */
+extern const int supplier_priority[];
+
/* start as a sink in case we have no other power supply/battery */
#define PD_DEFAULT_STATE PD_STATE_SNK_DISCONNECTED
diff --git a/board/glados/usb_pd_policy.c b/board/glados/usb_pd_policy.c
index 891008f7ce..1799c84724 100644
--- a/board/glados/usb_pd_policy.c
+++ b/board/glados/usb_pd_policy.c
@@ -73,31 +73,30 @@ void pd_transition_voltage(int idx)
int pd_set_power_supply_ready(int port)
{
- /*
- * TODO: this only works on port 0 for now. need to include
- * charge manager to manage CHARGE_L
- */
- if (port == 0) {
- /* Disable charging */
- gpio_set_level(GPIO_USB_C0_CHARGE_EN_L, 1);
- /* Provide VBUS */
- gpio_set_level(GPIO_USB_C0_5V_EN, 1);
- }
+ /* Disable charging */
+ gpio_set_level(port ? GPIO_USB_C1_CHARGE_EN_L :
+ GPIO_USB_C0_CHARGE_EN_L, 1);
+ /* Provide VBUS */
+ gpio_set_level(port ? GPIO_USB_C1_5V_EN :
+ GPIO_USB_C0_5V_EN, 1);
+
return EC_SUCCESS; /* we are ready */
}
void pd_power_supply_reset(int port)
{
+ /* Disable VBUS */
+ gpio_set_level(port ? GPIO_USB_C1_5V_EN :
+ GPIO_USB_C0_5V_EN, 0);
/*
- * TODO: this only works on port 0 for now. need to include
- * charge manager to manage CHARGE_L
+ * TODO: Currently we can only detect VBUS when charge_en is
+ * asserted, so, if there is no active charge port, then enable
+ * charge_en. If the other port is the active charger, then leave
+ * this port disabled.
*/
- if (port == 0) {
- /* Disable VBUS */
- gpio_set_level(GPIO_USB_C0_5V_EN, 0);
- /* Enable charging */
- gpio_set_level(GPIO_USB_C0_CHARGE_EN_L, 0);
- }
+ if (charge_manager_get_active_charge_port() != !port)
+ gpio_set_level(port ? GPIO_USB_C1_CHARGE_EN_L :
+ GPIO_USB_C0_CHARGE_EN_L, 0);
}
void pd_set_input_current_limit(int port, uint32_t max_ma,