summaryrefslogtreecommitdiff
path: root/board
diff options
context:
space:
mode:
authorRong Chang <rongchang@chromium.org>2015-06-08 20:55:47 +0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-06-10 15:49:35 +0000
commit2b129cc3b79d9940be9e80b660d2523e399eb732 (patch)
tree70cac0df0d61f270b0d97bc132a44d8b5f64eb46 /board
parentffd83ca8e9b3652527aa0966414f528daf068244 (diff)
downloadchrome-ec-2b129cc3b79d9940be9e80b660d2523e399eb732.tar.gz
oak: enable CHARGE_MANAGER to handle charging on both ports
This CL copies CL:275686 that enables charge manager to handle charging on two ports. Since oak has the same PD design, so both CHARGE_L controls need to be enabled to detect VBUS when no charger is plugged in. That means if you set chgoverride -1, this actually enable charging on both ports. BRANCH=none BUG=chrome-os-partner:41167 TEST=manual plug in zinger and donette onto both ports. verify that we charge from the first one plugged in. Change-Id: If5ed360e55f6c6b1a0315a68a5a6d924ae856c6d Signed-off-by: Rong Chang <rongchang@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/275853 Reviewed-by: Alec Berg <alecaberg@chromium.org>
Diffstat (limited to 'board')
-rw-r--r--board/oak/board.c83
-rw-r--r--board/oak/board.h19
-rw-r--r--board/oak/usb_pd_policy.c36
3 files changed, 119 insertions, 19 deletions
diff --git a/board/oak/board.c b/board/oak/board.c
index f8c2408a45..b49155b430 100644
--- a/board/oak/board.c
+++ b/board/oak/board.c
@@ -7,6 +7,8 @@
#include "adc_chip.h"
#include "battery.h"
+#include "charge_manager.h"
+#include "charge_state.h"
#include "charger.h"
#include "chipset.h"
#include "common.h"
@@ -35,6 +37,10 @@
#define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH)
#define GPIO_KB_OUTPUT GPIO_ODR_HIGH
+/* Default input current limit when VBUS is present */
+#define DEFAULT_CURR_LIMIT 500 /* mA */
+#define USB_BC12_CHARGE_VOLTAGE 5000 /* mV */
+
static void ap_reset_deferred(void)
{
/* Warm reset AP */
@@ -102,6 +108,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);
+
static int discharging_on_ac;
/**
@@ -149,6 +168,70 @@ static void board_init(void)
}
DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT);
+/**
+ * Set active charge port -- only one port can active at a time.
+ *
+ * @param charge_port Charge port to enable.
+ *
+ * Return 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 physical port */
+ int is_real_port = (charge_port >= 0 &&
+ charge_port < CONFIG_USB_PD_PORT_COUNT);
+ /* check if we are source VBUS on the port */
+ int source = gpio_get_level(charge_port == 0 ? GPIO_USB_C0_5V_OUT :
+ GPIO_USB_C1_5V_OUT);
+
+ if (is_real_port && source) {
+ CPRINTF("Skip enable p%d", charge_port);
+ return EC_ERROR_INVAL;
+ }
+
+ CPRINTF("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 changing, 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_L, 0);
+ gpio_set_level(GPIO_USB_C1_CHARGE_L, 0);
+ } else {
+ /* Make sure non-charging port is disabled */
+ gpio_set_level(charge_port ? GPIO_USB_C0_CHARGE_L :
+ GPIO_USB_C1_CHARGE_L, 1);
+ /* Enable charging port */
+ gpio_set_level(charge_port ? GPIO_USB_C1_CHARGE_L :
+ GPIO_USB_C0_CHARGE_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);
+
#ifndef CONFIG_AP_WARM_RESET_INTERRUPT
/* Using this hook if system doesn't have enough external line. */
static void check_ap_reset_second(void)
diff --git a/board/oak/board.h b/board/oak/board.h
index c810b0d4f3..9a29c9badc 100644
--- a/board/oak/board.h
+++ b/board/oak/board.h
@@ -18,6 +18,7 @@
/* Add for AC adaptor, charger, battery */
#define CONFIG_BATTERY_CUT_OFF
#define CONFIG_BATTERY_SMART
+#define CONFIG_CHARGE_MANAGER
#define CONFIG_CHARGER
#ifdef CONFIG_BOARD_OAK_REV_1
@@ -69,7 +70,7 @@
#undef CONFIG_UART_RX_DMA
#undef DEFERRABLE_MAX_COUNT
-#define DEFERRABLE_MAX_COUNT 9
+#define DEFERRABLE_MAX_COUNT 10
/*
* Allow dangerous commands.
@@ -136,6 +137,22 @@ enum adc_channel {
ADC_CH_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/oak/usb_pd_policy.c b/board/oak/usb_pd_policy.c
index 73bc31bce3..5f403ba45a 100644
--- a/board/oak/usb_pd_policy.c
+++ b/board/oak/usb_pd_policy.c
@@ -73,31 +73,31 @@ 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_L, 1);
- /* Provide VBUS */
- gpio_set_level(GPIO_USB_C0_5V_OUT, 1);
- }
+ /* Disable charging */
+ gpio_set_level(port ? GPIO_USB_C1_CHARGE_L :
+ GPIO_USB_C0_CHARGE_L, 1);
+ /* Provide VBUS */
+ gpio_set_level(port ? GPIO_USB_C1_5V_OUT :
+ GPIO_USB_C0_5V_OUT, 1);
+
return EC_SUCCESS; /* we are ready */
}
void pd_power_supply_reset(int port)
{
+ /* Disable VBUS */
+ gpio_set_level(port ? GPIO_USB_C1_5V_OUT :
+ GPIO_USB_C0_5V_OUT, 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_l is
+ * asserted, so, if there is no active charge port, then enable
+ * charge_l. 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_OUT, 0);
- /* Enable charging */
- gpio_set_level(GPIO_USB_C0_CHARGE_L, 0);
- }
+ if (charge_manager_get_active_charge_port() != !port)
+ gpio_set_level(port ? GPIO_USB_C1_CHARGE_L :
+ GPIO_USB_C0_CHARGE_L, 0);
}
void pd_set_input_current_limit(int port, uint32_t max_ma,