summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlec Berg <alecaberg@chromium.org>2014-11-19 09:08:30 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-01-09 21:28:07 +0000
commit1ac80fd3f895f9d5fd383a2146bd11f5100ba443 (patch)
treecaebc4410282438935d45858de57a144bd1262a1
parent49d2682b724aa49f53344dcc2768f8ac1af41dda (diff)
downloadchrome-ec-1ac80fd3f895f9d5fd383a2146bd11f5100ba443.tar.gz
ryu: add charge manager
Add charge manager to ryu to set how much current to draw from the port. BUG=none BRANCH=samus TEST=make buildall Signed-off-by: Alec Berg <alecaberg@chromium.org> Change-Id: Ia545532e1bf6586566c0b964d966b5d69c0d4b61 Reviewed-on: https://chromium-review.googlesource.com/230760 Tested-by: Vic Yang <victoryang@chromium.org> Reviewed-by: Shawn N <shawnn@chromium.org> Commit-Queue: Vic Yang <victoryang@chromium.org>
-rw-r--r--board/ryu/board.c131
-rw-r--r--board/ryu/board.h23
-rw-r--r--board/ryu/gpio.inc2
-rw-r--r--board/ryu/usb_pd_config.h5
-rw-r--r--board/ryu/usb_pd_policy.c19
-rw-r--r--board/samus_pd/board.c2
-rw-r--r--board/samus_pd/board.h2
-rw-r--r--common/charge_manager.c4
8 files changed, 178 insertions, 10 deletions
diff --git a/board/ryu/board.c b/board/ryu/board.c
index 7d6bf76042..856b93ecd4 100644
--- a/board/ryu/board.c
+++ b/board/ryu/board.c
@@ -8,6 +8,8 @@
#include "adc_chip.h"
#include "battery.h"
#include "case_closed_debug.h"
+#include "charge_manager.h"
+#include "charge_state.h"
#include "charger.h"
#include "common.h"
#include "console.h"
@@ -29,6 +31,8 @@
#include "util.h"
#include "pi3usb9281.h"
+#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args)
+
void vbus_evt(enum gpio_signal signal)
{
ccprintf("VBUS %d, %d!\n", signal, gpio_get_level(signal));
@@ -40,6 +44,58 @@ void unhandled_evt(enum gpio_signal signal)
ccprintf("Unhandled INT %d,%d!\n", signal, gpio_get_level(signal));
}
+/*
+ * Update available charge. Called from deferred task, queued on Pericom
+ * interrupt.
+ */
+static void board_usb_charger_update(void)
+{
+ int device_type, charger_status;
+ struct charge_port_info charge;
+ int type;
+ charge.voltage = USB_BC12_CHARGE_VOLTAGE;
+
+ /* Read interrupt register to clear */
+ pi3usb9281_get_interrupts(0);
+
+ /* Set device type */
+ device_type = pi3usb9281_get_device_type(0);
+ charger_status = pi3usb9281_get_charger_status(0);
+ if (PI3USB9281_CHG_STATUS_ANY(charger_status))
+ type = CHARGE_SUPPLIER_PROPRIETARY;
+ else if (device_type & PI3USB9281_TYPE_CDP)
+ type = CHARGE_SUPPLIER_BC12_CDP;
+ else if (device_type & PI3USB9281_TYPE_DCP)
+ type = CHARGE_SUPPLIER_BC12_DCP;
+ else if (device_type & PI3USB9281_TYPE_SDP)
+ type = CHARGE_SUPPLIER_BC12_SDP;
+ else
+ type = CHARGE_SUPPLIER_OTHER;
+
+ /* Attachment: decode + update available charge */
+ if (device_type || PI3USB9281_CHG_STATUS_ANY(charger_status)) {
+ charge.current = pi3usb9281_get_ilim(device_type,
+ charger_status);
+ charge_manager_update(type, 0, &charge);
+ } else { /* Detachment: update available charge to 0 */
+ charge.current = 0;
+ charge_manager_update(CHARGE_SUPPLIER_PROPRIETARY, 0,
+ &charge);
+ charge_manager_update(CHARGE_SUPPLIER_BC12_CDP, 0, &charge);
+ charge_manager_update(CHARGE_SUPPLIER_BC12_DCP, 0, &charge);
+ charge_manager_update(CHARGE_SUPPLIER_BC12_SDP, 0, &charge);
+ charge_manager_update(CHARGE_SUPPLIER_OTHER, 0, &charge);
+ }
+
+ /* notify host of power info change */
+ /*pd_send_host_event(PD_EVENT_POWER_CHANGE);*/
+}
+
+void usb_evt(enum gpio_signal signal)
+{
+ hook_call_deferred(board_usb_charger_update, 0);
+}
+
#include "gpio_list.h"
const void *const usb_strings[] = {
@@ -55,6 +111,23 @@ BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT);
/* Initialize board. */
static void board_init(void)
{
+ struct charge_port_info charge;
+
+ /* Initialize all pericom charge suppliers to 0 */
+ charge.voltage = USB_BC12_CHARGE_VOLTAGE;
+ charge.current = 0;
+ charge_manager_update(CHARGE_SUPPLIER_PROPRIETARY, 0,
+ &charge);
+ charge_manager_update(CHARGE_SUPPLIER_BC12_CDP, 0, &charge);
+ charge_manager_update(CHARGE_SUPPLIER_BC12_DCP, 0, &charge);
+ charge_manager_update(CHARGE_SUPPLIER_BC12_SDP, 0, &charge);
+ charge_manager_update(CHARGE_SUPPLIER_OTHER, 0, &charge);
+
+ /* Enable pericom BC1.2 interrupts. */
+ gpio_enable_interrupt(GPIO_USBC_BC12_INT_L);
+ pi3usb9281_set_interrupt_mask(0, 0xff);
+ pi3usb9281_enable_interrupts(0);
+
/*
* Determine recovery mode is requested by the power, volup, and
* voldown buttons being pressed.
@@ -96,6 +169,18 @@ const struct adc_t adc_channels[] = {
};
BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT);
+/* 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
+};
+BUILD_ASSERT(ARRAY_SIZE(supplier_priority) == CHARGE_SUPPLIER_COUNT);
+
/* I2C ports */
const struct i2c_port_t i2c_ports[] = {
{"master", I2C_PORT_MASTER, 100,
@@ -194,3 +279,49 @@ void usb_board_disconnect(void)
{
gpio_set_level(GPIO_USB_PU_EN_L, 1);
}
+
+/* Charge manager callback function, called on delayed override timeout */
+void board_charge_manager_override_timeout(void)
+{
+ /* TODO: Implement me! */
+}
+DECLARE_DEFERRED(board_charge_manager_override_timeout);
+
+/**
+ * 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)
+{
+ int ret = EC_SUCCESS;
+
+ if (charge_port >= 0 && charge_port < PD_PORT_COUNT &&
+ pd_get_role(charge_port) != PD_ROLE_SINK) {
+ CPRINTS("Port %d is not a sink, skipping enable", charge_port);
+ charge_port = CHARGE_PORT_NONE;
+ ret = EC_ERROR_INVAL;
+ }
+ if (charge_port == CHARGE_PORT_NONE) {
+ /* Disable charging */
+ charge_set_input_current_limit(0);
+ }
+
+ return ret;
+}
+
+/**
+ * Set the charge limit based upon desired maximum.
+ *
+ * @param charge_ma Desired charge limit (mA).
+ */
+void board_set_charge_limit(int charge_ma)
+{
+ int rv = charge_set_input_current_limit(MAX(charge_ma,
+ CONFIG_CHARGER_INPUT_CURRENT));
+ if (rv < 0)
+ CPRINTS("Failed to set input current limit for PD");
+}
diff --git a/board/ryu/board.h b/board/ryu/board.h
index 1dab8da727..5453965d2d 100644
--- a/board/ryu/board.h
+++ b/board/ryu/board.h
@@ -20,6 +20,7 @@
/* Optional features */
#undef CONFIG_CMD_HASH
+#define CONFIG_CHARGE_MANAGER
#define CONFIG_FORCE_CONSOLE_RESUME
#define CONFIG_STM_HWTIMER32
#define CONFIG_USB_POWER_DELIVERY
@@ -98,6 +99,10 @@
/* Enable Case Closed Debugging */
#define CONFIG_CASE_CLOSED_DEBUG
+/* Maximum number of deferrable functions */
+#undef DEFERRABLE_MAX_COUNT
+#define DEFERRABLE_MAX_COUNT 9
+
#ifndef __ASSEMBLER__
/* Timer selection */
@@ -125,6 +130,21 @@ 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_COUNT
+};
+
+/* supplier_priority table defined in board.c */
+extern const int supplier_priority[];
+
/* USB string indexes */
enum usb_strings {
USB_STR_DESC = 0,
@@ -139,6 +159,9 @@ enum usb_strings {
/* Discharge battery when on AC power for factory test. */
int board_discharge_on_ac(int enable);
+/* Set the charge current limit. */
+void board_set_charge_limit(int charge_ma);
+
#endif /* !__ASSEMBLER__ */
#endif /* __BOARD_H */
diff --git a/board/ryu/gpio.inc b/board/ryu/gpio.inc
index 686f629ce8..4b6d5cc717 100644
--- a/board/ryu/gpio.inc
+++ b/board/ryu/gpio.inc
@@ -9,7 +9,7 @@
GPIO(CHGR_ACOK, D, 4, GPIO_INT_BOTH | GPIO_PULL_UP, vbus_evt)
GPIO(BC_TEMP_ALERT_L, C, 5, GPIO_INT_FALLING, unhandled_evt)
GPIO(POWER_BUTTON_L, C, 13, GPIO_INT_BOTH, power_button_interrupt) /* active high, the name is for compatibility with existing code */
-GPIO(USBC_BC12_INT_L, D, 11, GPIO_INT_FALLING | GPIO_PULL_UP, unhandled_evt)
+GPIO(USBC_BC12_INT_L, D, 11, GPIO_INT_FALLING | GPIO_PULL_UP, usb_evt)
GPIO(LID_OPEN, E, 1, GPIO_INT_BOTH | GPIO_PULL_UP, lid_interrupt)
GPIO(CHARGE_DONE, E, 6, GPIO_INT_BOTH, inductive_charging_interrupt)
GPIO(LB_INT_L, E, 7, GPIO_INT_FALLING | GPIO_PULL_UP, unhandled_evt)
diff --git a/board/ryu/usb_pd_config.h b/board/ryu/usb_pd_config.h
index 994759163b..453014b2c2 100644
--- a/board/ryu/usb_pd_config.h
+++ b/board/ryu/usb_pd_config.h
@@ -8,6 +8,9 @@
#ifndef __USB_PD_CONFIG_H
#define __USB_PD_CONFIG_H
+#include "charge_state.h"
+#include "registers.h"
+
/* Port and task configuration */
#define PD_PORT_COUNT 1
#define PORT_TO_TASK_ID(port) TASK_ID_PD
@@ -126,6 +129,7 @@ static inline void pd_set_host_mode(int port, int enable)
if (enable) {
/* We never charging in power source mode */
gpio_set_level(GPIO_USBC_CHARGE_EN_L, 1);
+ charge_set_input_current_limit(0);
/* High-Z is used for host mode. */
gpio_set_level(GPIO_USBC_CC1_DEVICE_ODL, 1);
gpio_set_level(GPIO_USBC_CC2_DEVICE_ODL, 1);
@@ -135,7 +139,6 @@ static inline void pd_set_host_mode(int port, int enable)
/* Pull low for device mode. */
gpio_set_level(GPIO_USBC_CC1_DEVICE_ODL, 0);
gpio_set_level(GPIO_USBC_CC2_DEVICE_ODL, 0);
- /* Enable the charging path*/
gpio_set_level(GPIO_USBC_CHARGE_EN_L, 0);
}
diff --git a/board/ryu/usb_pd_policy.c b/board/ryu/usb_pd_policy.c
index b914cabc83..d6bd8c5598 100644
--- a/board/ryu/usb_pd_policy.c
+++ b/board/ryu/usb_pd_policy.c
@@ -3,7 +3,7 @@
* found in the LICENSE file.
*/
-#include "charge_state.h"
+#include "charge_manager.h"
#include "common.h"
#include "console.h"
#include "gpio.h"
@@ -35,10 +35,19 @@ const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo);
void pd_set_input_current_limit(int port, uint32_t max_ma,
uint32_t supply_voltage)
{
- int rv = charge_set_input_current_limit(MAX(max_ma,
- CONFIG_CHARGER_INPUT_CURRENT));
- if (rv < 0)
- CPRINTS("Failed to set input current limit for PD");
+ struct charge_port_info charge;
+ charge.current = max_ma;
+ charge.voltage = supply_voltage;
+ charge_manager_update(CHARGE_SUPPLIER_PD, port, &charge);
+}
+
+void typec_set_input_current_limit(int port, uint32_t max_ma,
+ uint32_t supply_voltage)
+{
+ struct charge_port_info charge;
+ charge.current = max_ma;
+ charge.voltage = supply_voltage;
+ charge_manager_update(CHARGE_SUPPLIER_TYPEC, port, &charge);
}
int pd_check_requested_voltage(uint32_t rdo)
diff --git a/board/samus_pd/board.c b/board/samus_pd/board.c
index 8359d770f2..8266e19ae8 100644
--- a/board/samus_pd/board.c
+++ b/board/samus_pd/board.c
@@ -418,7 +418,7 @@ const struct adc_t adc_channels[] = {
[ADC_C1_CC2_PD] = {"C1_CC2_PD", 3300, 4096, 0, STM32_AIN(5)},
/* Vbus sensing. Converted to mV, full ADC is equivalent to 25.774V. */
- [ADC_BOOSTIN] = {"V_BOOSTIN", 25774, 4096, 0, STM32_AIN(11)},
+ [ADC_VBUS] = {"VBUS", 25774, 4096, 0, STM32_AIN(11)},
};
BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT);
diff --git a/board/samus_pd/board.h b/board/samus_pd/board.h
index a607d690ed..8089acb74c 100644
--- a/board/samus_pd/board.h
+++ b/board/samus_pd/board.h
@@ -85,7 +85,7 @@ enum adc_channel {
ADC_C1_CC1_PD,
ADC_C0_CC2_PD,
ADC_C1_CC2_PD,
- ADC_BOOSTIN,
+ ADC_VBUS,
/* Number of ADC channels */
ADC_CH_COUNT
};
diff --git a/common/charge_manager.c b/common/charge_manager.c
index ffb2912b4f..470c20d08c 100644
--- a/common/charge_manager.c
+++ b/common/charge_manager.c
@@ -3,8 +3,10 @@
* found in the LICENSE file.
*/
+#include "adc.h"
#include "charge_manager.h"
#include "console.h"
+#include "gpio.h"
#include "hooks.h"
#include "host_command.h"
#include "timer.h"
@@ -515,7 +517,7 @@ static int hc_pd_power_info(struct host_cmd_handler_args *args)
r->role == USB_PD_PORT_POWER_SINK_NOT_CHARGING)
r->voltage_now = 5000;
else
- r->voltage_now = adc_read_channel(ADC_BOOSTIN);
+ r->voltage_now = adc_read_channel(ADC_VBUS);
}
args->response_size = sizeof(*r);