summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlec Berg <alecaberg@chromium.org>2015-08-03 16:33:44 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-08-05 16:50:46 +0000
commitfeea8de21bb7d73624eddaeb536a0bc298ccc61e (patch)
treebeeeda82a2bf7b7d536bedd55d2ba4aa44a38967
parent38eb374fceed84ea499c5e27c8b2ded869c5d75f (diff)
downloadchrome-ec-feea8de21bb7d73624eddaeb536a0bc298ccc61e.tar.gz
usb_charger: move common usb charger code out of board directory
Move common USB charger code out of board directory including setting VBUS supplier when VBUS changes, and initializing BC1.2 supplier types on init. This also enables re-enabling of Pericom BC1.2 detection interrupts when VBUS is changed on all boards that use USB_CHG task. BUG=chrome-os-partner:42292 BRANCH=none TEST=make -j buildall. Tested on glados and samus by plugging in a few different chargers and making sure we charge. Change-Id: Ib102fbf7a6aace998e6fcb6d35f3c97e5f03f5c2 Signed-off-by: Alec Berg <alecaberg@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/290453 Reviewed-by: Shawn N <shawnn@chromium.org> Reviewed-by: Rong Chang <rongchang@chromium.org>
-rw-r--r--board/glados/board.c59
-rw-r--r--board/kunimitsu/board.c59
-rw-r--r--board/ryu/board.c45
-rw-r--r--board/samus_pd/board.c92
-rw-r--r--board/strago/board.c47
-rw-r--r--common/usb_charger.c280
-rw-r--r--include/usb_charge.h11
7 files changed, 211 insertions, 382 deletions
diff --git a/board/glados/board.c b/board/glados/board.c
index fe7773d085..5e026b71b6 100644
--- a/board/glados/board.c
+++ b/board/glados/board.c
@@ -47,51 +47,28 @@ static void pd_mcu_interrupt(enum gpio_signal signal)
host_command_pd_send_status(0);
}
-static void update_vbus_supplier(int port, int vbus_level)
-{
- struct charge_port_info charge;
-
- /*
- * If VBUS is low, or VBUS is high and we are not outputting VBUS
- * ourselves, then update the VBUS supplier.
- */
- if (!vbus_level || !usb_charger_port_is_sourcing_vbus(port)) {
- charge.voltage = USB_CHARGER_VOLTAGE_MV;
- charge.current = vbus_level ? USB_CHARGER_MIN_CURR_MA : 0;
- charge_manager_update_charge(CHARGE_SUPPLIER_VBUS,
- port,
- &charge);
- }
-}
-
void vbus0_evt(enum gpio_signal signal)
{
/* VBUS present GPIO is inverted */
- int vbus_level = !gpio_get_level(signal);
-
- CPRINTF("VBUS C0, %d\n", vbus_level);
- update_vbus_supplier(0, vbus_level);
+ usb_charger_vbus_change(0, !gpio_get_level(signal));
task_wake(TASK_ID_PD_C0);
}
void vbus1_evt(enum gpio_signal signal)
{
/* VBUS present GPIO is inverted */
- int vbus_level = !gpio_get_level(signal);
-
- CPRINTF("VBUS C1, %d\n", vbus_level);
- update_vbus_supplier(0, vbus_level);
+ usb_charger_vbus_change(1, !gpio_get_level(signal));
task_wake(TASK_ID_PD_C1);
}
void usb0_evt(enum gpio_signal signal)
{
- task_wake(TASK_ID_USB_CHG_P0);
+ task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0);
}
void usb1_evt(enum gpio_signal signal)
{
- task_wake(TASK_ID_USB_CHG_P1);
+ task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0);
}
#include "gpio_list.h"
@@ -234,40 +211,12 @@ 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;
-
/* 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_CHARGER_VOLTAGE_MV;
- 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 */
- update_vbus_supplier(0, !gpio_get_level(GPIO_USB_C0_VBUS_WAKE_L));
- update_vbus_supplier(1, !gpio_get_level(GPIO_USB_C1_VBUS_WAKE_L));
-
/* Enable pericom BC1.2 interrupts */
gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L);
gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L);
diff --git a/board/kunimitsu/board.c b/board/kunimitsu/board.c
index e9cade936f..16b75e9b8a 100644
--- a/board/kunimitsu/board.c
+++ b/board/kunimitsu/board.c
@@ -53,51 +53,28 @@ static void pd_mcu_interrupt(enum gpio_signal signal)
host_command_pd_send_status(0);
}
-static void update_vbus_supplier(int port, int vbus_level)
-{
- struct charge_port_info charge;
-
- /*
- * If VBUS is low, or VBUS is high and we are not outputting VBUS
- * ourselves, then update the VBUS supplier.
- */
- if (!vbus_level || !usb_charger_port_is_sourcing_vbus(port)) {
- charge.voltage = USB_CHARGER_VOLTAGE_MV;
- charge.current = vbus_level ? USB_CHARGER_MIN_CURR_MA : 0;
- charge_manager_update_charge(CHARGE_SUPPLIER_VBUS,
- port,
- &charge);
- }
-}
-
void vbus0_evt(enum gpio_signal signal)
{
/* VBUS present GPIO is inverted */
- int vbus_level = !gpio_get_level(signal);
-
- CPRINTF("VBUS C0, %d\n", vbus_level);
- update_vbus_supplier(0, vbus_level);
+ usb_charger_vbus_change(0, !gpio_get_level(signal));
task_wake(TASK_ID_PD_C0);
}
void vbus1_evt(enum gpio_signal signal)
{
/* VBUS present GPIO is inverted */
- int vbus_level = !gpio_get_level(signal);
-
- CPRINTF("VBUS C1, %d\n", vbus_level);
- update_vbus_supplier(0, vbus_level);
+ usb_charger_vbus_change(1, !gpio_get_level(signal));
task_wake(TASK_ID_PD_C1);
}
void usb0_evt(enum gpio_signal signal)
{
- task_wake(TASK_ID_USB_CHG_P0);
+ task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0);
}
void usb1_evt(enum gpio_signal signal)
{
- task_wake(TASK_ID_USB_CHG_P1);
+ task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0);
}
#include "gpio_list.h"
@@ -320,40 +297,12 @@ BUILD_ASSERT(ARRAY_SIZE(buttons) == CONFIG_BUTTON_COUNT);
/* Initialize board. */
static void board_init(void)
{
- int i;
- struct charge_port_info charge_none;
-
/* 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_CHARGER_VOLTAGE_MV;
- 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 */
- update_vbus_supplier(0, !gpio_get_level(GPIO_USB_C0_VBUS_WAKE_L));
- update_vbus_supplier(1, !gpio_get_level(GPIO_USB_C1_VBUS_WAKE_L));
-
/* Enable pericom BC1.2 interrupts */
gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L);
gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L);
diff --git a/board/ryu/board.c b/board/ryu/board.c
index ad1f5788b6..045fbe3dd4 100644
--- a/board/ryu/board.c
+++ b/board/ryu/board.c
@@ -58,34 +58,15 @@ static int charge_current_limit;
*/
static struct ec_response_host_event_status host_event_status __aligned(4);
-static void vbus_log(void)
-{
- CPRINTS("VBUS %d", gpio_get_level(GPIO_CHGR_ACOK));
-}
-DECLARE_DEFERRED(vbus_log);
-
void vbus_evt(enum gpio_signal signal)
{
- struct charge_port_info charge;
- int vbus_level = gpio_get_level(signal);
-
- /*
- * If VBUS is low, or VBUS is high and we are not outputting VBUS
- * ourselves, then update the VBUS supplier.
- */
- if (!vbus_level || !gpio_get_level(GPIO_CHGR_OTG)) {
- charge.voltage = USB_CHARGER_VOLTAGE_MV;
- charge.current = vbus_level ? USB_CHARGER_MIN_CURR_MA : 0;
- charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, 0, &charge);
- }
-
- hook_call_deferred(vbus_log, 0);
+ usb_charger_vbus_change(0, gpio_get_level(signal));
task_wake(TASK_ID_PD);
}
void usb_evt(enum gpio_signal signal)
{
- task_wake(TASK_ID_USB_CHG_P0);
+ task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0);
}
#include "gpio_list.h"
@@ -152,28 +133,6 @@ BUILD_ASSERT(ARRAY_SIZE(pi3usb9281_chips) ==
static void board_init(void)
{
int i;
- struct charge_port_info charge_none, charge_vbus;
-
- /* Initialize all pericom charge suppliers to 0 */
- charge_none.voltage = USB_CHARGER_VOLTAGE_MV;
- charge_none.current = 0;
- charge_manager_update_charge(CHARGE_SUPPLIER_PROPRIETARY,
- 0,
- &charge_none);
- charge_manager_update_charge(CHARGE_SUPPLIER_BC12_CDP, 0, &charge_none);
- charge_manager_update_charge(CHARGE_SUPPLIER_BC12_DCP, 0, &charge_none);
- charge_manager_update_charge(CHARGE_SUPPLIER_BC12_SDP, 0, &charge_none);
- charge_manager_update_charge(CHARGE_SUPPLIER_OTHER, 0, &charge_none);
-
- /* Initialize VBUS supplier based on whether or not VBUS is present */
- charge_vbus.voltage = USB_CHARGER_VOLTAGE_MV;
- charge_vbus.current = USB_CHARGER_MIN_CURR_MA;
- if (gpio_get_level(GPIO_CHGR_ACOK))
- charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, 0,
- &charge_vbus);
- else
- charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, 0,
- &charge_none);
/* Enable pericom BC1.2 interrupts. */
gpio_enable_interrupt(GPIO_USBC_BC12_INT_L);
diff --git a/board/samus_pd/board.c b/board/samus_pd/board.c
index eb2273121b..e59646058c 100644
--- a/board/samus_pd/board.c
+++ b/board/samus_pd/board.c
@@ -102,67 +102,24 @@ DECLARE_DEFERRED(pericom_port1_reenable_interrupts);
void vbus0_evt(enum gpio_signal signal)
{
- struct charge_port_info charge;
- int vbus_level = gpio_get_level(signal);
-
- /*
- * If VBUS is low, or VBUS is high and we are not outputting VBUS
- * ourselves, then update the VBUS supplier.
- */
- if (!vbus_level || !gpio_get_level(GPIO_USB_C0_5V_EN)) {
- charge.voltage = USB_CHARGER_VOLTAGE_MV;
- charge.current = vbus_level ? USB_CHARGER_MIN_CURR_MA : 0;
- charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, 0, &charge);
- }
-
- /*
- * Re-enable interrupts on pericom charger detector since the
- * chip may periodically reset itself, and come back up with
- * registers in default state. TODO(crosbug.com/p/33823): Fix
- * these unwanted resets.
- */
- hook_call_deferred(pericom_port0_reenable_interrupts, 0);
+ usb_charger_vbus_change(0, gpio_get_level(signal));
task_wake(TASK_ID_PD_C0);
}
void vbus1_evt(enum gpio_signal signal)
{
- struct charge_port_info charge;
- int vbus_level = gpio_get_level(signal);
-
- /*
- * If VBUS is low, or VBUS is high and we are not outputting VBUS
- * ourselves, then update the VBUS supplier.
- */
- if (!vbus_level || !gpio_get_level(GPIO_USB_C1_5V_EN)) {
- charge.voltage = USB_CHARGER_VOLTAGE_MV;
- charge.current = vbus_level ? USB_CHARGER_MIN_CURR_MA : 0;
- charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, 1, &charge);
- }
-
- /*
- * Re-enable interrupts on pericom charger detector since the
- * chip may periodically reset itself, and come back up with
- * registers in default state. TODO(crosbug.com/p/33823): Fix
- * these unwanted resets.
- */
- hook_call_deferred(pericom_port1_reenable_interrupts, 0);
+ usb_charger_vbus_change(1, gpio_get_level(signal));
task_wake(TASK_ID_PD_C1);
}
-static void wake_usb_charger_task(int port)
-{
- task_wake(port ? TASK_ID_USB_CHG_P1 : TASK_ID_USB_CHG_P0);
-}
-
void usb0_evt(enum gpio_signal signal)
{
- wake_usb_charger_task(0);
+ task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0);
}
void usb1_evt(enum gpio_signal signal)
{
- wake_usb_charger_task(1);
+ task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_BC12, 0);
}
static void chipset_s5_to_s3(void)
@@ -252,10 +209,9 @@ void board_config_pre_init(void)
/* Initialize board. */
static void board_init(void)
{
- int pd_enable, i;
+ int pd_enable;
int slp_s5 = gpio_get_level(GPIO_PCH_SLP_S5_L);
int slp_s3 = gpio_get_level(GPIO_PCH_SLP_S3_L);
- struct charge_port_info charge_none, charge_vbus;
/*
* Enable CC lines after all GPIO have been initialized. Note, it is
@@ -268,44 +224,6 @@ static void board_init(void)
gpio_enable_interrupt(GPIO_USB_C0_VBUS_WAKE);
gpio_enable_interrupt(GPIO_USB_C1_VBUS_WAKE);
- /* Initialize all pericom charge suppliers to 0 */
- charge_none.voltage = USB_CHARGER_VOLTAGE_MV;
- 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_CHARGER_VOLTAGE_MV;
- charge_vbus.current = USB_CHARGER_MIN_CURR_MA;
- if (gpio_get_level(GPIO_USB_C0_VBUS_WAKE))
- 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))
- charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, 1,
- &charge_vbus);
- else
- charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, 1,
- &charge_none);
-
/* Enable pericom BC1.2 interrupts. */
gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L);
gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L);
diff --git a/board/strago/board.c b/board/strago/board.c
index a2c5b75992..6b6b3a7089 100644
--- a/board/strago/board.c
+++ b/board/strago/board.c
@@ -56,35 +56,16 @@ static void pd_mcu_interrupt(enum gpio_signal signal)
#endif
}
-static void update_vbus_supplier(int port, int vbus_level)
-{
- struct charge_port_info charge;
-
- /*
- * If VBUS is low, or VBUS is high and we are not outputting VBUS
- * ourselves, then update the VBUS supplier.
- */
- if (!vbus_level || !usb_charger_port_is_sourcing_vbus(port)) {
- charge.voltage = USB_CHARGER_VOLTAGE_MV;
- charge.current = vbus_level ? USB_CHARGER_MIN_CURR_MA : 0;
- charge_manager_update_charge(CHARGE_SUPPLIER_VBUS,
- port,
- &charge);
- }
-}
-
void vbus0_evt(enum gpio_signal signal)
{
/* VBUS present GPIO is inverted */
- int vbus_level = !gpio_get_level(signal);
-
- update_vbus_supplier(0, vbus_level);
+ usb_charger_vbus_change(0, !gpio_get_level(signal));
task_wake(TASK_ID_PD);
}
void usb0_evt(enum gpio_signal signal)
{
- task_wake(TASK_ID_USB_CHG_P0);
+ task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_BC12, 0);
}
#include "gpio_list.h"
@@ -311,35 +292,11 @@ DECLARE_HOOK(HOOK_INIT, adc_pre_init, HOOK_PRIO_INIT_ADC - 1);
/* Initialize board. */
static void board_init(void)
{
- struct charge_port_info charge_none;
-
/* Enable PD MCU interrupt */
gpio_enable_interrupt(GPIO_PD_MCU_INT);
/* Enable VBUS interrupt */
gpio_enable_interrupt(GPIO_USB_C0_VBUS_WAKE_L);
- /* Initialize all pericom charge suppliers to 0 */
- charge_none.voltage = USB_CHARGER_VOLTAGE_MV;
- charge_none.current = 0;
- charge_manager_update_charge(CHARGE_SUPPLIER_PROPRIETARY,
- 0,
- &charge_none);
- charge_manager_update_charge(CHARGE_SUPPLIER_BC12_CDP,
- 0,
- &charge_none);
- charge_manager_update_charge(CHARGE_SUPPLIER_BC12_DCP,
- 0,
- &charge_none);
- charge_manager_update_charge(CHARGE_SUPPLIER_BC12_SDP,
- 0,
- &charge_none);
- charge_manager_update_charge(CHARGE_SUPPLIER_OTHER,
- 0,
- &charge_none);
-
- /* Initialize VBUS supplier based on whether or not VBUS is present */
- update_vbus_supplier(0, !gpio_get_level(GPIO_USB_C0_VBUS_WAKE_L));
-
/* Enable pericom BC1.2 interrupts */
gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L);
}
diff --git a/common/usb_charger.c b/common/usb_charger.c
index de81ad0497..f686ffaff1 100644
--- a/common/usb_charger.c
+++ b/common/usb_charger.c
@@ -11,14 +11,18 @@
#include "charge_manager.h"
#include "common.h"
+#include "console.h"
#include "ec_commands.h"
#include "gpio.h"
+#include "hooks.h"
#include "pi3usb9281.h"
#include "task.h"
#include "timer.h"
#include "usb_charge.h"
#include "usb_pd.h"
+#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args)
+
/* Wait after a charger is detected to debounce pin contact order */
#define USB_CHG_DEBOUNCE_DELAY_MS 1000
/*
@@ -34,6 +38,23 @@
static int usb_switch_state[CONFIG_USB_PD_PORT_COUNT];
static struct mutex usb_switch_lock[CONFIG_USB_PD_PORT_COUNT];
+static void update_vbus_supplier(int port, int vbus_level)
+{
+ struct charge_port_info charge;
+
+ /*
+ * If VBUS is low, or VBUS is high and we are not outputting VBUS
+ * ourselves, then update the VBUS supplier.
+ */
+ if (!vbus_level || !usb_charger_port_is_sourcing_vbus(port)) {
+ charge.voltage = USB_CHARGER_VOLTAGE_MV;
+ charge.current = vbus_level ? USB_CHARGER_MIN_CURR_MA : 0;
+ charge_manager_update_charge(CHARGE_SUPPLIER_VBUS,
+ port,
+ &charge);
+ }
+}
+
int usb_charger_port_is_sourcing_vbus(int port)
{
if (port == 0)
@@ -59,121 +80,186 @@ void usb_charger_set_switches(int port, enum usb_switch setting)
mutex_unlock(&usb_switch_lock[port]);
}
-void usb_charger_task(void)
+void usb_charger_vbus_change(int port, int vbus_level)
{
- int port = (task_get_current() == TASK_ID_USB_CHG_P0 ? 0 : 1);
+ /* Update VBUS supplier and signal VBUS change to USB_CHG task */
+ update_vbus_supplier(port, vbus_level);
+#if CONFIG_USB_PD_PORT_COUNT == 2
+ task_set_event(port ? TASK_ID_USB_CHG_P1 : TASK_ID_USB_CHG_P0,
+ USB_CHG_EVENT_VBUS, 0);
+#else
+ task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_VBUS, 0);
+#endif
+}
+static void usb_charger_bc12_detect(int port)
+{
int device_type, charger_status;
struct charge_port_info charge;
int type;
charge.voltage = USB_CHARGER_VOLTAGE_MV;
+ /* Read interrupt register to clear on chip */
+ pi3usb9281_get_interrupts(port);
+
+ if (usb_charger_port_is_sourcing_vbus(port)) {
+ /* If we're sourcing VBUS then we're not charging */
+ device_type = charger_status = 0;
+ } else {
+ /* Set device type */
+ device_type = pi3usb9281_get_device_type(port);
+ charger_status = pi3usb9281_get_charger_status(port);
+ }
+
+ /* Debounce pin plug order if we detect a charger */
+ if (device_type || PI3USB9281_CHG_STATUS_ANY(charger_status)) {
+ msleep(USB_CHG_DEBOUNCE_DELAY_MS);
+
+ /* next operation might trigger a detach interrupt */
+ pi3usb9281_disable_interrupts(port);
+ /* Ensure D+/D- are open before resetting */
+ pi3usb9281_set_switch_manual(port, 1);
+ pi3usb9281_set_pins(port, 0);
+ /* Let D+/D- relax to their idle state */
+ msleep(40);
+
+ /*
+ * Trigger chip reset to refresh detection registers.
+ * WARNING: This reset is acceptable for samus_pd,
+ * but may not be acceptable for devices that have
+ * an OTG / device mode, as we may be interrupting
+ * the connection.
+ */
+ pi3usb9281_reset(port);
+ /*
+ * Restore data switch settings - switches return to
+ * closed on reset until restored.
+ */
+ usb_charger_set_switches(port, USB_SWITCH_RESTORE);
+ /* Clear possible disconnect interrupt */
+ pi3usb9281_get_interrupts(port);
+ /* Mask attach interrupt */
+ pi3usb9281_set_interrupt_mask(port,
+ 0xff &
+ ~PI3USB9281_INT_ATTACH);
+ /* Re-enable interrupts */
+ pi3usb9281_enable_interrupts(port);
+ msleep(USB_CHG_RESET_DELAY_MS);
+
+ /* Clear possible attach interrupt */
+ pi3usb9281_get_interrupts(port);
+ /* Re-enable attach interrupt */
+ pi3usb9281_set_interrupt_mask(port, 0xff);
+
+ /* Re-read ID registers */
+ device_type = pi3usb9281_get_device_type(port);
+ charger_status = pi3usb9281_get_charger_status(port);
+ }
+
+ /* Attachment: decode + update available charge */
+ if (device_type || PI3USB9281_CHG_STATUS_ANY(charger_status)) {
+ 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;
+
+ charge.current = pi3usb9281_get_ilim(device_type,
+ charger_status);
+ charge_manager_update_charge(type, port, &charge);
+ } else { /* Detachment: update available charge to 0 */
+ charge.current = 0;
+ charge_manager_update_charge(
+ CHARGE_SUPPLIER_PROPRIETARY,
+ port,
+ &charge);
+ charge_manager_update_charge(
+ CHARGE_SUPPLIER_BC12_CDP,
+ port,
+ &charge);
+ charge_manager_update_charge(
+ CHARGE_SUPPLIER_BC12_DCP,
+ port,
+ &charge);
+ charge_manager_update_charge(
+ CHARGE_SUPPLIER_BC12_SDP,
+ port,
+ &charge);
+ charge_manager_update_charge(
+ CHARGE_SUPPLIER_OTHER,
+ port,
+ &charge);
+ }
+
+ /* notify host of power info change */
+ pd_send_host_event(PD_EVENT_POWER_CHANGE);
+}
+
+void usb_charger_task(void)
+{
+ int port = (task_get_current() == TASK_ID_USB_CHG_P0 ? 0 : 1);
+ uint32_t evt;
+
/* Initialize chip and enable interrupts */
pi3usb9281_init(port);
+ usb_charger_bc12_detect(port);
+
while (1) {
- /* Read interrupt register to clear on chip */
- pi3usb9281_get_interrupts(port);
+ /* Wait for interrupt */
+ evt = task_wait_event(-1);
- if (usb_charger_port_is_sourcing_vbus(port)) {
- /* If we're sourcing VBUS then we're not charging */
- device_type = charger_status = 0;
- } else {
- /* Set device type */
- device_type = pi3usb9281_get_device_type(port);
- charger_status = pi3usb9281_get_charger_status(port);
- }
+ /* Interrupt from the Pericom chip, determine charger type */
+ if (evt & USB_CHG_EVENT_BC12)
+ usb_charger_bc12_detect(port);
- /* Debounce pin plug order if we detect a charger */
- if (device_type || PI3USB9281_CHG_STATUS_ANY(charger_status)) {
- msleep(USB_CHG_DEBOUNCE_DELAY_MS);
-
- /* next operation might trigger a detach interrupt */
- pi3usb9281_disable_interrupts(port);
- /* Ensure D+/D- are open before resetting */
- pi3usb9281_set_switch_manual(port, 1);
- pi3usb9281_set_pins(port, 0);
- /* Let D+/D- relax to their idle state */
- msleep(40);
-
- /*
- * Trigger chip reset to refresh detection registers.
- * WARNING: This reset is acceptable for samus_pd,
- * but may not be acceptable for devices that have
- * an OTG / device mode, as we may be interrupting
- * the connection.
- */
- pi3usb9281_reset(port);
- /*
- * Restore data switch settings - switches return to
- * closed on reset until restored.
- */
- usb_charger_set_switches(port, USB_SWITCH_RESTORE);
- /* Clear possible disconnect interrupt */
- pi3usb9281_get_interrupts(port);
- /* Mask attach interrupt */
- pi3usb9281_set_interrupt_mask(port,
- 0xff &
- ~PI3USB9281_INT_ATTACH);
- /* Re-enable interrupts */
+ /*
+ * Re-enable interrupts on pericom charger detector since the
+ * chip may periodically reset itself, and come back up with
+ * registers in default state. TODO(crosbug.com/p/33823): Fix
+ * these unwanted resets.
+ */
+ if (evt & USB_CHG_EVENT_VBUS) {
pi3usb9281_enable_interrupts(port);
- msleep(USB_CHG_RESET_DELAY_MS);
-
- /* Clear possible attach interrupt */
- pi3usb9281_get_interrupts(port);
- /* Re-enable attach interrupt */
- pi3usb9281_set_interrupt_mask(port, 0xff);
-
- /* Re-read ID registers */
- device_type = pi3usb9281_get_device_type(port);
- charger_status = pi3usb9281_get_charger_status(port);
+ CPRINTS("VBUS p%d %d", port,
+ pd_snk_is_vbus_provided(port));
}
+ }
+}
- /* Attachment: decode + update available charge */
- if (device_type || PI3USB9281_CHG_STATUS_ANY(charger_status)) {
- 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;
-
- charge.current = pi3usb9281_get_ilim(device_type,
- charger_status);
- charge_manager_update_charge(type, port, &charge);
- } else { /* Detachment: update available charge to 0 */
- charge.current = 0;
- charge_manager_update_charge(
- CHARGE_SUPPLIER_PROPRIETARY,
- port,
- &charge);
- charge_manager_update_charge(
- CHARGE_SUPPLIER_BC12_CDP,
- port,
- &charge);
- charge_manager_update_charge(
- CHARGE_SUPPLIER_BC12_DCP,
- port,
- &charge);
- charge_manager_update_charge(
- CHARGE_SUPPLIER_BC12_SDP,
- port,
- &charge);
- charge_manager_update_charge(
- CHARGE_SUPPLIER_OTHER,
- port,
- &charge);
- }
+static void usb_charger_init(void)
+{
+ int i;
+ struct charge_port_info charge_none;
- /* notify host of power info change */
- pd_send_host_event(PD_EVENT_POWER_CHANGE);
+ /* Initialize all pericom charge suppliers to 0 */
+ charge_none.voltage = USB_CHARGER_VOLTAGE_MV;
+ 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);
- /* Wait for interrupt */
- task_wait_event(-1);
+ /* Initialize VBUS supplier based on whether VBUS is present */
+ update_vbus_supplier(i, pd_snk_is_vbus_provided(i));
}
}
+DECLARE_HOOK(HOOK_INIT, usb_charger_init, HOOK_PRIO_DEFAULT);
diff --git a/include/usb_charge.h b/include/usb_charge.h
index 60f2c9742c..e7d620bd81 100644
--- a/include/usb_charge.h
+++ b/include/usb_charge.h
@@ -47,6 +47,10 @@ int usb_charge_set_mode(int usb_port_id, enum usb_charge_mode mode);
*/
int usb_charge_ports_enabled(void);
+/* Events handled by the USB_CHG task */
+#define USB_CHG_EVENT_BC12 TASK_EVENT_CUSTOM(1)
+#define USB_CHG_EVENT_VBUS TASK_EVENT_CUSTOM(2)
+
/**
* Returns true if the passed port is a power source.
*
@@ -69,5 +73,12 @@ enum usb_switch {
*/
void usb_charger_set_switches(int port, enum usb_switch setting);
+/**
+ * Notify USB_CHG task that VBUS level has changed.
+ *
+ * @param port port number.
+ * @param vbus_level new VBUS level
+ */
+void usb_charger_vbus_change(int port, int vbus_level);
#endif /* __CROS_EC_USB_CHARGE_H */