sn5s330: Enable VBUS interrupts

If the sn5s330 PPC is being used to detect VBUS presence
(CONFIG_USB_PD_VBUS_DETECT_PPC), then enable interrupts and call
usb_charger_vbus_change when VBUS_GOOD changes.

BUG=b:72007153,b:72007492
BRANCH=none
TEST=Connect 3A and 1A USB-A chargers to each of Grunt's USB-C ports,
check that BC1.2 detection is working:
	With 1A:
	> chgsup
	port=0/1, type=7, cur=500mA, vtg=5000mV, lsm=1
	With 3A:
	> chgsup
	port=0/1, type=7, cur=2400mA, vtg=5000mV, lsm=1
TEST=Boot Grunt to OS, then connect USB2 mouse or USB3 flash drive to each
of Grunt's USB-C ports. Devices do not work due to b:71772180, but gpioget
shows EC is setting USB_C0/1_BC12_VBUS_ON_L correctly.

Change-Id: Iffc352105a321997adb364b9fbb8bafef248c224
Signed-off-by: Edward Hill <ecgh@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/887938
Reviewed-by: Jett Rink <jettrink@chromium.org>
This commit is contained in:
Edward Hill
2018-01-25 16:13:22 -07:00
committed by chrome-bot
parent eb60e291e8
commit 11bda19561
6 changed files with 58 additions and 39 deletions

View File

@@ -173,16 +173,7 @@ void typec_set_source_current_limit(int port, int rp)
int pd_snk_is_vbus_provided(int port)
{
int vbus_present = 0;
int rv;
rv = ppc_is_vbus_present(port, &vbus_present);
if (rv) {
CPRINTS("p%d: VBUS present error (%d)", port, rv);
return 0;
}
return vbus_present;
return ppc_is_vbus_present(port);
}
int board_vbus_source_enabled(int port)

View File

@@ -75,7 +75,8 @@ void usb_charger_vbus_change(int port, int vbus_level)
task_set_event(USB_CHG_PORT_TO_TASK_ID(port), USB_CHG_EVENT_VBUS, 0);
#endif
#ifdef CONFIG_USB_PD_VBUS_DETECT_CHARGER
#if (defined(CONFIG_USB_PD_VBUS_DETECT_CHARGER) \
|| defined(CONFIG_USB_PD_VBUS_DETECT_PPC))
/* USB PD task */
task_wake(PD_PORT_TO_TASK_ID(port));
#endif

View File

@@ -75,12 +75,14 @@ int ppc_vbus_source_enable(int port, int enable)
}
#ifdef CONFIG_USB_PD_VBUS_DETECT_PPC
int ppc_is_vbus_present(int port, int *vbus_present)
int ppc_is_vbus_present(int port)
{
if (port >= ppc_cnt)
return EC_ERROR_INVAL;
if ((port < 0) || (port >= ppc_cnt)) {
CPRINTS("%s(%d) Invalid port!", __func__, port);
return 0;
}
return ppc_chips[port].drv->is_vbus_present(port, vbus_present);
return ppc_chips[port].drv->is_vbus_present(port);
}
#endif /* defined(CONFIG_USB_PD_VBUS_DETECT_PPC) */

View File

@@ -17,6 +17,7 @@
#include "i2c.h"
#include "system.h"
#include "timer.h"
#include "usb_charge.h"
#include "usb_pd_tcpm.h"
#include "usbc_ppc.h"
#include "util.h"
@@ -326,7 +327,8 @@ static int sn5s330_init(int port)
/*
* Before turning on the PP2 FET, let's mask off all interrupts except
* for the PP1 overcurrent condition and then clear all pending
* interrupts.
* interrupts. If PPC is being used to detect VBUS, then also enable
* interrupts for VBUS presence.
*
* TODO(aaboagye): Unmask fast-role swap events once fast-role swap is
* implemented in the PD stack.
@@ -362,15 +364,22 @@ static int sn5s330_init(int port)
return status;
}
#if defined(CONFIG_USB_PD_VBUS_DETECT_PPC) && defined(CONFIG_USB_CHARGER)
/* If PPC is being used to detect VBUS, enable VBUS interrupts. */
regval = ~SN5S330_VBUS_GOOD_MASK;
#else
regval = 0xFF;
#endif /* CONFIG_USB_PD_VBUS_DETECT_PPC && CONFIG_USB_CHARGER */
status = i2c_write8(i2c_port, i2c_addr, SN5S330_INT_MASK_RISE_REG3,
0xFF);
regval);
if (status) {
CPRINTS("Failed to write INT_MASK_RISE3!");
return status;
}
status = i2c_write8(i2c_port, i2c_addr, SN5S330_INT_MASK_FALL_REG3,
0xFF);
regval);
if (status) {
CPRINTS("Failed to write INT_MASK_FALL3!");
return status;
@@ -416,16 +425,18 @@ static int sn5s330_init(int port)
}
#ifdef CONFIG_USB_PD_VBUS_DETECT_PPC
static int sn5s330_is_vbus_present(int port, int *vbus_present)
static int sn5s330_is_vbus_present(int port)
{
int regval;
int rv;
rv = read_reg(port, SN5S330_INT_STATUS_REG3, &regval);
if (!rv)
*vbus_present = !!(regval & SN5S330_VBUS_GOOD);
if (rv) {
CPRINTS("p%d: VBUS present error (%d)", port, rv);
return 0;
}
return rv;
return !!(regval & SN5S330_VBUS_GOOD);
}
#endif /* defined(CONFIG_USB_PD_VBUS_DETECT_PPC) */
@@ -436,7 +447,7 @@ static int sn5s330_is_sourcing_vbus(int port)
rv = sn5s330_is_pp_fet_enabled(port, SN5S330_PP1, &is_sourcing_vbus);
if (rv) {
CPRINTS("C%d: Failed to determine source FET status! (%d)",
CPRINTS("p%d: Failed to determine source FET status! (%d)",
port, rv);
return 0;
}
@@ -520,7 +531,7 @@ static void sn5s330_handle_interrupt(int port)
/*
* The only interrupts that should be enabled are the PP1 overcurrent
* condition.
* condition, and for VBUS_GOOD if PPC is being used to detect VBUS.
*/
read_reg(port, SN5S330_INT_TRIP_RISE_REG1, &rise);
read_reg(port, SN5S330_INT_TRIP_FALL_REG1, &fall);
@@ -532,6 +543,20 @@ static void sn5s330_handle_interrupt(int port)
/* Clear the interrupt sources. */
write_reg(port, SN5S330_INT_TRIP_RISE_REG1, rise);
write_reg(port, SN5S330_INT_TRIP_FALL_REG1, fall);
#if defined(CONFIG_USB_PD_VBUS_DETECT_PPC) && defined(CONFIG_USB_CHARGER)
read_reg(port, SN5S330_INT_TRIP_RISE_REG3, &rise);
read_reg(port, SN5S330_INT_TRIP_FALL_REG3, &fall);
/* Inform other modules about VBUS level */
if (rise & SN5S330_VBUS_GOOD_MASK
|| fall & SN5S330_VBUS_GOOD_MASK)
usb_charger_vbus_change(port, sn5s330_is_vbus_present(port));
/* Clear the interrupt sources. */
write_reg(port, SN5S330_INT_TRIP_RISE_REG3, rise);
write_reg(port, SN5S330_INT_TRIP_FALL_REG3, fall);
#endif /* CONFIG_USB_PD_VBUS_DETECT_PPC && CONFIG_USB_CHARGER */
}
static void sn5s330_irq_deferred(void)

View File

@@ -120,13 +120,23 @@ enum sn5s330_pp_idx {
*/
#define SN5S330_ILIM_PP1_MASK (1 << 4)
/*
* INT_MASK_RISE/FALL_EDGE_3
*
* The VBUS_GOOD bit indicates VBUS has increased beyond a 4.0V threshold.
* For rising edge registers, this indicates VBUS has risen above 4.0V.
* For falling edge registers, this indicates VBUS has fallen below 4.0V.
*/
#define SN5S330_VBUS_GOOD_MASK (1 << 0)
extern const struct ppc_drv sn5s330_drv;
/**
* Interrupt Handler for the SN5S330.
*
* By default, the only interrupt sources that are unmasked are overcurrent
* conditions for PP1.
* conditions for PP1, and VBUS_GOOD if PPC is being used to detect VBUS
* (CONFIG_USB_PD_VBUS_DETECT_PPC).
*
* @param port: The Type-C port which triggered the interrupt.
*/

View File

@@ -77,21 +77,13 @@ struct ppc_drv {
#endif /* defined(CONFIG_CMD_PPC_DUMP) */
#ifdef CONFIG_USB_PD_VBUS_DETECT_PPC
/*
* TODO(aaboagye): In order for VBUS detection to work properly for our
* system, we need to enable VBUS interrupts and send the appropriate
* notifications.
*/
/**
* Determine if VBUS is present or not.
*
* @param port: The Type-C port number.
* @param vbus_present: 1: VBUS is present. 0: VBUS is not present.
* @return EC_SUCCESS if able to determine VBUS status, otherwise an
* error.
* @return 1 if VBUS is present, 0 if not.
*/
int (*is_vbus_present)(int port, int *vbus_present);
int (*is_vbus_present)(int port);
#endif /* defined(CONFIG_USB_PD_VBUS_DETECT_PPC) */
};
@@ -116,11 +108,9 @@ int ppc_init(int port);
* Determine if VBUS is present or not.
*
* @param port: The Type-C port number.
* @param vbus_present: 1: VBUS is present. 0: VBUS is not present.
* @return EC_SUCCESS if able to determine VBUS status, otherwise an
* error.
* @return 1 if VBUS is present, 0 if not.
*/
int ppc_is_vbus_present(int port, int *vbus_present);
int ppc_is_vbus_present(int port);
/**
* Is the port sourcing Vbus?