summaryrefslogtreecommitdiff
path: root/driver/bc12
diff options
context:
space:
mode:
authorScott Collyer <scollyer@google.com>2019-02-21 17:36:56 -0800
committerchrome-bot <chrome-bot@chromium.org>2019-03-14 13:24:17 -0700
commit5a9e6a5551647b6cbff634072b9d2368e79962cb (patch)
tree856b588616e32a2b99e08742e9a422727ed646c7 /driver/bc12
parent6e46ec5a25f4eefd8d0ecc928850e0bed74f28d6 (diff)
downloadchrome-ec-5a9e6a5551647b6cbff634072b9d2368e79962cb.tar.gz
pi3usb9201: Use USB_CHG data role and cc_open events
The initial version of this driver relied on VBUS changes to wake up the USB_CHG task and trigger bc1.2 detection in client mode or to set CDP host mode. This was modeling the max14637 driver which is a client mode only device. However, the ps3usb9201 supports both host and client modes and should be controlled more directly. This CL modifies the primary triggers for bc1.2 operations to be data role changes to start bc1.2 for either client or host mode and CC open detection as the trigger for power down mode. BUG=b:124612788 BRANCH=none TEST=Tested both external chargers, adapters, and charge through hubs. Verfied that bc1.2 detection is triggered as expected when chargers are connected and verified that when the type C port is in source mode, then the pi3usb9201 is in host CDP mode. Change-Id: I625e82a4b7af4469ba59b8619d498a283ba4849e Signed-off-by: Scott Collyer <scollyer@google.com> Reviewed-on: https://chromium-review.googlesource.com/1503954 Commit-Ready: Scott Collyer <scollyer@chromium.org> Tested-by: Scott Collyer <scollyer@chromium.org> Reviewed-by: Furquan Shaikh <furquan@chromium.org>
Diffstat (limited to 'driver/bc12')
-rw-r--r--driver/bc12/pi3usb9201.c189
-rw-r--r--driver/bc12/pi3usb9201.h4
2 files changed, 112 insertions, 81 deletions
diff --git a/driver/bc12/pi3usb9201.c b/driver/bc12/pi3usb9201.c
index d70a3e53f6..44bb1ca62e 100644
--- a/driver/bc12/pi3usb9201.c
+++ b/driver/bc12/pi3usb9201.c
@@ -107,32 +107,53 @@ static int pi3usb9201_set_mode(int port, int desired_mode)
desired_mode << PI3USB9201_REG_CTRL_1_MODE_SHIFT);
}
-static void bc12_update_charge_manager(int port)
+static int pi3usb9201_get_mode(int port, int *mode)
{
- int client_status;
int rv;
- enum pi3usb9201_client_sts type;
+
+ rv = raw_read8(port, PI3USB9201_REG_CTRL_1, mode);
+ if (rv)
+ return rv;
+
+ *mode &= PI3USB9201_REG_CTRL_1_MODE_MASK;
+ *mode >>= PI3USB9201_REG_CTRL_1_MODE_SHIFT;
+
+ return EC_SUCCESS;
+}
+
+static int pi3usb9201_get_status(int port, int *client, int *host)
+{
+ int rv;
+ int status;
+
+ rv = raw_read8(port, PI3USB9201_REG_CLIENT_STS, &status);
+ if (client)
+ *client = status;
+ rv |= raw_read8(port, PI3USB9201_REG_HOST_STS, &status);
+ if (host)
+ *host = status;
+
+ return rv;
+}
+
+static void bc12_update_charge_manager(int port, int client_status)
+{
struct charge_port_info new_chg;
enum charge_supplier supplier;
+ int bit_pos;
/* Set charge voltage to 5V */
new_chg.voltage = USB_CHARGER_VOLTAGE_MV;
- /* Read BC 1.2 client mode detection result */
- rv = raw_read8(port, PI3USB9201_REG_CLIENT_STS, &client_status);
- /* Find set bit position. If no bits set will return 0 */
- type = __builtin_ffs(client_status) - 1;
-
- if (!rv && (type >= 0)) {
- new_chg.current = bc12_chg_limits[type].current_limit;
- supplier = bc12_chg_limits[type].supplier;
- } else {
- /*
- * If bc 1.2 detetion failed for some reason, then set limit to
- * minimum and set supplier to other.
- */
- new_chg.current = 500;
- supplier = CHARGE_SUPPLIER_OTHER;
- }
+
+ /*
+ * Find set bit position. Note that this funciton is only called if a
+ * bit was set in client_status, so bit_pos won't be negative.
+ */
+ bit_pos = __builtin_ffs(client_status) - 1;
+
+ new_chg.current = bc12_chg_limits[bit_pos].current_limit;
+ supplier = bc12_chg_limits[bit_pos].supplier;
+
CPRINTS("pi3usb9201[p%d]: sts = 0x%x, lim = %d mA, supplier = %d",
port, client_status, new_chg.current, supplier);
/* bc1.2 is complete and start bit does not auto clear */
@@ -144,6 +165,13 @@ static void bc12_update_charge_manager(int port)
static int bc12_detect_start(int port)
{
int rv;
+
+ /*
+ * Read both status registers to ensure that all interrupt indications
+ * are cleared prior to starting bc1.2 detection.
+ */
+ pi3usb9201_get_status(port, NULL, NULL);
+
/* Put pi3usb9201 into client mode */
rv = pi3usb9201_set_mode(port, PI3USB9201_CLIENT_MODE);
if (rv)
@@ -168,53 +196,6 @@ static void bc12_power_down(int port)
charge_manager_update_charge(CHARGE_SUPPLIER_NONE, port, NULL);
}
-static void bc12_handle_vbus_change(int port)
-{
- int role = pd_get_role(port);
- int vbus = pd_snk_is_vbus_provided(port);
-
-#ifndef CONFIG_USB_PD_VBUS_DETECT_TCPC
- CPRINTS("VBUS p%d %d", port, vbus);
-#endif
- /*
- * TODO(b/124061702): For host mode, currently only setting it to host
- * CDP mode. However, there are 3 host status bits to know things such
- * as an adapter connected, but no USB device present, or bc1.2 activity
- * detected.
- */
- if (role == PD_ROLE_SOURCE &&
- board_vbus_source_enabled(port)) {
- /*
- * For source role, if vbus is present, then set
- * CDP host mode (will close D+/D-) switches. If
- * vbus is not present, then put into power down
- * mode.
- */
- if (pi3usb9201_set_mode(port,
- PI3USB9201_CDP_HOST_MODE))
- CPRINTS("pi3usb9201[p%d]: failed to set host mode",
- port);
- } else if (vbus) {
- if (bc12_detect_start(port)) {
- struct charge_port_info new_chg;
-
- /*
- * VBUS is present, but starting bc1.2 detection failed
- * for some reason. So limit charge current to default
- * 500 mA for this case.
- */
-
- new_chg.voltage = USB_CHARGER_VOLTAGE_MV;
- new_chg.current = 500;
- charge_manager_update_charge(CHARGE_SUPPLIER_OTHER,
- port, &new_chg);
- CPRINTS("pi3usb9201[p%d]: bc1.2 start failed", port);
- }
- } else {
- bc12_power_down(port);
- }
-}
-
void usb_charger_task(void *u)
{
int port = (task_get_current() == TASK_ID_USB_CHG_P0 ? 0 : 1);
@@ -225,25 +206,74 @@ void usb_charger_task(void *u)
* than enabling the interrupt mask.
*/
pi3usb9201_interrupt_mask(port, 1);
- /*
- * Upon EC reset, there likely won't be a VBUS status change to set the
- * event to wake up this task. So need to check if VBUS is
- * present to make sure that D+/D- switches remain in the correct state
- * and bc1.2 detection is triggered (for client mode) to set the correct
- * input current limit.
- */
- bc12_handle_vbus_change(port);
while (1) {
/* Wait for interrupt */
evt = task_wait_event(-1);
/* Interrupt from the Pericom chip, determine charger type */
- if (evt & USB_CHG_EVENT_BC12)
- bc12_update_charge_manager(port);
+ if (evt & USB_CHG_EVENT_BC12) {
+ int client;
+ int rv;
+
+ rv = pi3usb9201_get_status(port, &client, NULL);
+ if (!rv && client)
+ /*
+ * Any bit set in client status register
+ * indicates that BC1.2 detection has
+ * completed.
+ */
+ bc12_update_charge_manager(port, client);
+ }
+#ifndef CONFIG_USB_PD_VBUS_DETECT_TCPC
if (evt & USB_CHG_EVENT_VBUS)
- bc12_handle_vbus_change(port);
+ CPRINTS("VBUS p%d %d", port,
+ pd_snk_is_vbus_provided(port));
+#endif
+
+ if (evt & USB_CHG_EVENT_DR_UFP) {
+ if (bc12_detect_start(port)) {
+ struct charge_port_info new_chg;
+
+ /*
+ * VBUS is present, but starting bc1.2 detection
+ * failed for some reason. So limit charge
+ * current to default 500 mA for this case.
+ */
+
+ new_chg.voltage = USB_CHARGER_VOLTAGE_MV;
+ new_chg.current = USB_CHARGER_MIN_CURR_MA;
+ charge_manager_update_charge(
+ CHARGE_SUPPLIER_OTHER,
+ port, &new_chg);
+ CPRINTS("pi3usb9201[p%d]: bc1.2 failed use "
+ "defaults", port);
+ }
+ }
+
+ /*
+ * TODO(b/124061702): For host mode, currently only setting it
+ * to host CDP mode. However, there are 3 host status bits to
+ * know things such as an adapter connected, but no USB device
+ * present, or bc1.2 activity detected.
+ */
+ if (evt & USB_CHG_EVENT_DR_DFP) {
+ int mode;
+ int rv;
+
+ /*
+ * If the port is in DFP mode, then need to set mode to
+ * CDP_HOST which will auto close D+/D- switches.
+ */
+ rv = pi3usb9201_get_mode(port, &mode);
+ if (!rv && (mode != PI3USB9201_CDP_HOST_MODE))
+ pi3usb9201_set_mode(port,
+ PI3USB9201_CDP_HOST_MODE);
+ }
+
+ if (evt & USB_CHG_EVENT_CC_OPEN)
+ bc12_power_down(port);
}
}
@@ -258,9 +288,10 @@ void usb_charger_set_switches(int port, enum usb_switch setting)
#if defined(CONFIG_CHARGE_RAMP_SW) || defined(CONFIG_CHARGE_RAMP_HW)
int usb_charger_ramp_allowed(int supplier)
{
- /* Don't allow ramp if charge supplier is OTHER or SDP */
+ /* Don't allow ramp if charge supplier is OTHER, SDP, or NONE */
return !(supplier == CHARGE_SUPPLIER_OTHER ||
- supplier == CHARGE_SUPPLIER_BC12_SDP);
+ supplier == CHARGE_SUPPLIER_BC12_SDP ||
+ supplier == CHARGE_SUPPLIER_NONE);
}
int usb_charger_ramp_max(int supplier, int sup_curr)
diff --git a/driver/bc12/pi3usb9201.h b/driver/bc12/pi3usb9201.h
index a710a5b2e9..71b235c8d1 100644
--- a/driver/bc12/pi3usb9201.h
+++ b/driver/bc12/pi3usb9201.h
@@ -19,8 +19,8 @@
/* Control_1 regiter bit definitions */
#define PI3USB9201_REG_CTRL_1_INT_MASK (1 << 0)
#define PI3USB9201_REG_CTRL_1_MODE_SHIFT 1
-#define PI3USB9201_REG_CTRL_1_MODE_MASK ( \
- 0x7 << PI3USB9201_REG_CTRL_1_MODE_SHIFT)
+#define PI3USB9201_REG_CTRL_1_MODE_MASK (0x7 << \
+ PI3USB9201_REG_CTRL_1_MODE_SHIFT)
/* Control_2 regiter bit definitions */
#define PI3USB9201_REG_CTRL_2_AUTO_SW (1 << 1)