summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 */