summaryrefslogtreecommitdiff
path: root/driver/ppc/sn5s330.c
diff options
context:
space:
mode:
Diffstat (limited to 'driver/ppc/sn5s330.c')
-rw-r--r--driver/ppc/sn5s330.c752
1 files changed, 0 insertions, 752 deletions
diff --git a/driver/ppc/sn5s330.c b/driver/ppc/sn5s330.c
deleted file mode 100644
index 4abf85cf50..0000000000
--- a/driver/ppc/sn5s330.c
+++ /dev/null
@@ -1,752 +0,0 @@
-/* Copyright 2017 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/* TI SN5S330 USB-C Power Path Controller */
-
-/*
- * PP1 : Sourcing power path.
- * PP2 : Sinking power path.
- */
-
-#include "common.h"
-#include "console.h"
-#include "sn5s330.h"
-#include "hooks.h"
-#include "i2c.h"
-#include "system.h"
-#include "timer.h"
-#include "usb_charge.h"
-#include "usb_pd_tcpm.h"
-#include "usb_pd.h"
-#include "usbc_ppc.h"
-#include "util.h"
-
-#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
-
-static uint32_t irq_pending; /* Bitmask of ports signaling an interrupt. */
-static int source_enabled[CONFIG_USB_PD_PORT_MAX_COUNT];
-
-static int read_reg(uint8_t port, int reg, int *regval)
-{
- return i2c_read8(ppc_chips[port].i2c_port,
- ppc_chips[port].i2c_addr_flags,
- reg,
- regval);
-}
-
-static int write_reg(uint8_t port, int reg, int regval)
-{
- return i2c_write8(ppc_chips[port].i2c_port,
- ppc_chips[port].i2c_addr_flags,
- reg,
- regval);
-}
-
-static int set_flags(const int port, const int addr, const int flags_to_set)
-{
- int val, rv;
-
- rv = read_reg(port, addr, &val);
- if (rv)
- return rv;
-
- val |= flags_to_set;
-
- return write_reg(port, addr, val);
-}
-
-
-static int clr_flags(const int port, const int addr, const int flags_to_clear)
-{
- int val, rv;
-
- rv = read_reg(port, addr, &val);
- if (rv)
- return rv;
-
- val &= ~flags_to_clear;
-
- return write_reg(port, addr, val);
-}
-
-#ifdef CONFIG_CMD_PPC_DUMP
-static int sn5s330_dump(int port)
-{
- int i;
- int data;
- const int i2c_port = ppc_chips[port].i2c_port;
- const uint16_t i2c_addr_flags = ppc_chips[port].i2c_addr_flags;
-
- /* Flush after every set otherwise console buffer may get full. */
-
- for (i = SN5S330_FUNC_SET1; i <= SN5S330_FUNC_SET12; i++) {
- i2c_read8(i2c_port, i2c_addr_flags, i, &data);
- ccprintf("FUNC_SET%d [%02Xh] = 0x%02x\n",
- i - SN5S330_FUNC_SET1 + 1,
- i,
- data);
- }
-
- cflush();
-
- for (i = SN5S330_INT_STATUS_REG1; i <= SN5S330_INT_STATUS_REG4; i++) {
- i2c_read8(i2c_port, i2c_addr_flags, i, &data);
- ccprintf("INT_STATUS_REG%d [%02Xh] = 0x%02x\n",
- i - SN5S330_INT_STATUS_REG1 + 1,
- i,
- data);
- }
-
- cflush();
-
- for (i = SN5S330_INT_TRIP_RISE_REG1; i <= SN5S330_INT_TRIP_RISE_REG3;
- i++) {
- i2c_read8(i2c_port, i2c_addr_flags, i, &data);
- ccprintf("INT_TRIP_RISE_REG%d [%02Xh] = 0x%02x\n",
- i - SN5S330_INT_TRIP_RISE_REG1 + 1,
- i,
- data);
- }
-
- cflush();
-
- for (i = SN5S330_INT_TRIP_FALL_REG1; i <= SN5S330_INT_TRIP_FALL_REG3;
- i++) {
- i2c_read8(i2c_port, i2c_addr_flags, i, &data);
- ccprintf("INT_TRIP_FALL_REG%d [%02Xh] = 0x%02x\n",
- i - SN5S330_INT_TRIP_FALL_REG1 + 1,
- i,
- data);
- }
-
- cflush();
-
- for (i = SN5S330_INT_MASK_RISE_REG1; i <= SN5S330_INT_MASK_RISE_REG3;
- i++) {
- i2c_read8(i2c_port, i2c_addr_flags, i, &data);
- ccprintf("INT_MASK_RISE_REG%d [%02Xh] = 0x%02x\n",
- i - SN5S330_INT_MASK_RISE_REG1 + 1,
- i,
- data);
- }
-
- cflush();
-
- for (i = SN5S330_INT_MASK_FALL_REG1; i <= SN5S330_INT_MASK_FALL_REG3;
- i++) {
- i2c_read8(i2c_port, i2c_addr_flags, i, &data);
- ccprintf("INT_MASK_FALL_REG%d [%02Xh] = 0x%02x\n",
- i - SN5S330_INT_MASK_FALL_REG1 + 1,
- i,
- data);
- }
-
- cflush();
-
- return EC_SUCCESS;
-}
-#endif /* defined(CONFIG_CMD_PPC_DUMP) */
-
-static int sn5s330_pp_fet_enable(uint8_t port, enum sn5s330_pp_idx pp,
- int enable)
-{
- int status;
- int pp_bit;
-
- if (pp == SN5S330_PP1)
- pp_bit = SN5S330_PP1_EN;
- else if (pp == SN5S330_PP2)
- pp_bit = SN5S330_PP2_EN;
- else
- return EC_ERROR_INVAL;
-
- status = enable ? set_flags(port, SN5S330_FUNC_SET3, pp_bit)
- : clr_flags(port, SN5S330_FUNC_SET3, pp_bit);
-
- if (status) {
- ppc_prints("Failed to set FUNC_SET3!", port);
- return status;
- }
-
- if (pp == SN5S330_PP1)
- source_enabled[port] = enable;
-
- return EC_SUCCESS;
-}
-
-static int sn5s330_init(int port)
-{
- int regval;
- int status;
- int retries;
- int reg;
- const int i2c_port = ppc_chips[port].i2c_port;
- const uint16_t i2c_addr_flags = ppc_chips[port].i2c_addr_flags;
-
-#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT
- /* Set the sourcing current limit value. */
- switch (CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) {
- case TYPEC_RP_3A0:
- /* Set current limit to ~3A. */
- regval = SN5S330_ILIM_3_06;
- break;
-
- case TYPEC_RP_1A5:
- default:
- /* Set current limit to ~1.5A. */
- regval = SN5S330_ILIM_1_62;
- break;
- }
-#else /* !defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */
- /* Default SRC current limit to ~1.5A. */
- regval = SN5S330_ILIM_1_62;
-#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */
-
- /*
- * It seems that sometimes setting the FUNC_SET1 register fails
- * initially. Therefore, we'll retry a couple of times.
- */
- retries = 0;
- do {
- status = i2c_write8(i2c_port, i2c_addr_flags,
- SN5S330_FUNC_SET1, regval);
- if (status) {
- ppc_prints("Failed to set FUNC_SET1! Retrying..",
- port);
- retries++;
- msleep(1);
- } else {
- break;
- }
- } while (retries < 10);
-
- /* Set Vbus OVP threshold to ~22.325V. */
- regval = 0x37;
- status = i2c_write8(i2c_port, i2c_addr_flags,
- SN5S330_FUNC_SET5, regval);
- if (status) {
- ppc_prints("Failed to set FUNC_SET5!", port);
- return status;
- }
-
- /* Set Vbus UVP threshold to ~2.75V. */
- status = i2c_read8(i2c_port, i2c_addr_flags,
- SN5S330_FUNC_SET6, &regval);
- if (status) {
- ppc_prints("Failed to read FUNC_SET6!", port);
- return status;
- }
- regval &= ~0x3F;
- regval |= 1;
- status = i2c_write8(i2c_port, i2c_addr_flags,
- SN5S330_FUNC_SET6, regval);
- if (status) {
- ppc_prints("Failed to write FUNC_SET6!", port);
- return status;
- }
-
- /* Enable SBU Fets and set PP2 current limit to ~3A. */
- regval = SN5S330_SBU_EN | 0x8;
- status = i2c_write8(i2c_port, i2c_addr_flags,
- SN5S330_FUNC_SET2, regval);
- if (status) {
- ppc_prints("Failed to set FUNC_SET2!", port);
- return status;
- }
-
- /*
- * Indicate we are using PP2 configuration 2 and enable OVP comparator
- * for CC lines.
- *
- * Also, turn off under-voltage protection for incoming Vbus as it would
- * prevent us from enabling SNK path before we hibernate the ec. We
- * need to enable the SNK path so USB power will assert ACOK and wake
- * the EC up went inserting USB power. We always turn off under-voltage
- * protection because the battery charger will boost the voltage up
- * to the needed battery voltage either way (and it will have its own
- * low voltage protection).
- */
- regval = SN5S330_OVP_EN_CC | SN5S330_PP2_CONFIG | SN5S330_CONFIG_UVP;
- status = i2c_write8(i2c_port, i2c_addr_flags,
- SN5S330_FUNC_SET9, regval);
- if (status) {
- ppc_prints("Failed to set FUNC_SET9!", port);
- return status;
- }
-
- /*
- * Set analog current limit delay to 200 us for PP1,
- * set 1000 us for PP2 for compatibility.
- */
- regval = (PPX_ILIM_DEGLITCH_0_US_200 << 3) |
- PPX_ILIM_DEGLITCH_0_US_1000;
- status = i2c_write8(i2c_port, i2c_addr_flags, SN5S330_FUNC_SET11,
- regval);
- if (status) {
- ppc_prints("Failed to set FUNC_SET11", port);
- return status;
- }
-
-#ifdef CONFIG_USBC_PPC_VCONN
- /*
- * Set the deglitch timeout on the Vconn current limit to 640us. This
- * improves compatibility with some USB C -> HDMI devices versus the
- * reset default (20 us).
- */
- regval = 0;
- status = i2c_read8(i2c_port, i2c_addr_flags,
- SN5S330_FUNC_SET8, &regval);
- if (status) {
- ppc_prints("Failed to read FUNC_SET8!", port);
- return status;
- }
- regval &= ~SN5S330_VCONN_DEGLITCH_MASK;
- regval |= SN5S330_VCONN_DEGLITCH_640_US;
- status = i2c_write8(i2c_port, i2c_addr_flags,
- SN5S330_FUNC_SET8, regval);
- if (status) {
- ppc_prints("Failed to set FUNC_SET8!", port);
- return status;
- }
-#endif /* CONFIG_USBC_PPC_VCONN */
-
- /*
- * Turn off dead battery resistors, turn on CC FETs, and set the higher
- * of the two VCONN current limits (min 0.6A). Many VCONN accessories
- * trip the default current limit of min 0.35A.
- */
- status = set_flags(port, SN5S330_FUNC_SET4,
- SN5S330_CC_EN | SN5S330_VCONN_ILIM_SEL);
- if (status) {
- ppc_prints("Failed to set FUNC_SET4!", port);
- return status;
- }
-
- /* Set ideal diode mode for both PP1 and PP2. */
- status = set_flags(port, SN5S330_FUNC_SET3,
- SN5S330_SET_RCP_MODE_PP1 | SN5S330_SET_RCP_MODE_PP2);
- if (status) {
- ppc_prints("Failed to set FUNC_SET3!", port);
- return status;
- }
-
- /* Turn off PP1 FET. */
- status = sn5s330_pp_fet_enable(port, SN5S330_PP1, 0);
- if (status) {
- ppc_prints("Failed to turn off PP1 FET!", port);
- }
-
- /*
- * Don't proceed with the rest of initialization if we're sysjumping.
- * We would have already done this before.
- */
- if (system_jumped_late())
- return EC_SUCCESS;
-
- /*
- * Clear the digital reset bit, and mask off and clear vSafe0V
- * interrupts. Leave the dead battery mode bit unchanged since it
- * is checked below.
- */
- regval = SN5S330_DIG_RES | SN5S330_VSAFE0V_MASK;
- status = i2c_write8(i2c_port, i2c_addr_flags,
- SN5S330_INT_STATUS_REG4, regval);
- if (status) {
- ppc_prints("Failed to write INT_STATUS_REG4!", port);
- return status;
- }
-
- /*
- * Before turning on the PP2 FET, mask off all unwanted interrupts and
- * then clear all pending interrupts.
- *
- * TODO(aaboagye): Unmask fast-role swap events once fast-role swap is
- * implemented in the PD stack.
- */
-
- /* Enable PP1 overcurrent interrupts. */
- regval = ~SN5S330_ILIM_PP1_MASK;
- status = i2c_write8(i2c_port, i2c_addr_flags,
- SN5S330_INT_MASK_RISE_REG1, regval);
- if (status) {
- ppc_prints("Failed to write INT_MASK_RISE1!", port);
- return status;
- }
-
- status = i2c_write8(i2c_port, i2c_addr_flags,
- SN5S330_INT_MASK_FALL_REG1, 0xFF);
- if (status) {
- ppc_prints("Failed to write INT_MASK_FALL1!", port);
- return status;
- }
-
- /* Enable VCONN overcurrent and CC1/CC2 overvoltage interrupts. */
- regval = ~(SN5S330_VCONN_ILIM | SN5S330_CC1_CON | SN5S330_CC2_CON);
- status = i2c_write8(i2c_port, i2c_addr_flags,
- SN5S330_INT_MASK_RISE_REG2, regval);
- if (status) {
- ppc_prints("Failed to write INT_MASK_RISE2!", port);
- return status;
- }
-
- status = i2c_write8(i2c_port, i2c_addr_flags,
- SN5S330_INT_MASK_FALL_REG2, 0xFF);
- if (status) {
- ppc_prints("Failed to write INT_MASK_FALL2!", 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_flags,
- SN5S330_INT_MASK_RISE_REG3, regval);
- if (status) {
- ppc_prints("Failed to write INT_MASK_RISE3!", port);
- return status;
- }
-
- status = i2c_write8(i2c_port, i2c_addr_flags,
- SN5S330_INT_MASK_FALL_REG3, regval);
- if (status) {
- ppc_prints("Failed to write INT_MASK_FALL3!", port);
- return status;
- }
-
- /* Now clear any pending interrupts. */
- for (reg = SN5S330_INT_TRIP_RISE_REG1;
- reg <= SN5S330_INT_TRIP_FALL_REG3;
- reg++) {
- status = i2c_write8(i2c_port, i2c_addr_flags,
- reg, 0xFF);
- if (status) {
- CPRINTS("ppc p%d: Failed to write reg 0x%2x!",
- port, reg);
- return status;
- }
- }
-
-
- /*
- * For PP2, check to see if we booted in dead battery mode. If we
- * booted in dead battery mode, the PP2 FET will already be enabled.
- */
- status = i2c_read8(i2c_port, i2c_addr_flags,
- SN5S330_INT_STATUS_REG4, &regval);
- if (status) {
- ppc_prints("Failed to read INT_STATUS_REG4!", port);
- return status;
- }
-
- if (regval & SN5S330_DB_BOOT) {
- /*
- * Clear the bit by writing 1 and keep vSafe0V_MASK
- * unchanged.
- */
- i2c_write8(i2c_port, i2c_addr_flags,
- SN5S330_INT_STATUS_REG4, regval);
-
- /* Turn on PP2 FET. */
- status = sn5s330_pp_fet_enable(port, SN5S330_PP2, 1);
- if (status) {
- ppc_prints("Failed to turn on PP2 FET!", port);
- return status;
- }
- }
-
- return EC_SUCCESS;
-}
-
-#ifdef CONFIG_USB_PD_VBUS_DETECT_PPC
-static int sn5s330_is_vbus_present(int port)
-{
- int regval;
- int rv;
-
- rv = read_reg(port, SN5S330_INT_STATUS_REG3, &regval);
- if (rv) {
- ppc_err_prints("VBUS present error", port, rv);
- return 0;
- }
-
- return !!(regval & SN5S330_VBUS_GOOD);
-}
-#endif /* defined(CONFIG_USB_PD_VBUS_DETECT_PPC) */
-
-static int sn5s330_is_sourcing_vbus(int port)
-{
- return source_enabled[port];
-}
-
-#ifdef CONFIG_USBC_PPC_POLARITY
-static int sn5s330_set_polarity(int port, int polarity)
-{
- if (polarity)
- /* CC2 active. */
- return set_flags(port, SN5S330_FUNC_SET4, SN5S330_CC_POLARITY);
- else
- /* CC1 active. */
- return clr_flags(port, SN5S330_FUNC_SET4, SN5S330_CC_POLARITY);
-}
-#endif
-
-static int sn5s330_set_vbus_source_current_limit(int port,
- enum tcpc_rp_value rp)
-{
- int regval;
- int status;
-
- status = read_reg(port, SN5S330_FUNC_SET1, &regval);
- if (status)
- return status;
-
- /*
- * Note that we chose the lowest current limit setting that is just
- * above indicated Rp value. This is because these are minimum values
- * and we must be able to provide the current that we advertise.
- */
- regval &= ~0x1F; /* The current limit settings are 4:0. */
- switch (rp) {
- case TYPEC_RP_3A0:
- regval |= SN5S330_ILIM_3_06;
- break;
-
- case TYPEC_RP_1A5:
- regval |= SN5S330_ILIM_1_62;
- break;
-
- case TYPEC_RP_USB:
- default:
- regval |= SN5S330_ILIM_0_63;
- break;
- };
-
- status = write_reg(port, SN5S330_FUNC_SET1, regval);
-
- return status;
-}
-
-static int sn5s330_discharge_vbus(int port, int enable)
-{
- int status = enable ? set_flags(port, SN5S330_FUNC_SET3,
- SN5S330_VBUS_DISCH_EN)
- : clr_flags(port, SN5S330_FUNC_SET3,
- SN5S330_VBUS_DISCH_EN);
-
- if (status) {
- CPRINTS("ppc p%d: Failed to %s vbus discharge",
- port, enable ? "enable" : "disable");
- return status;
- }
-
- return EC_SUCCESS;
-}
-
-static int sn5s330_enter_low_power_mode(int port)
-{
- int rv;
-
- /* Turn off both SRC and SNK FETs */
- rv = clr_flags(port, SN5S330_FUNC_SET3,
- SN5S330_PP1_EN | SN5S330_PP2_EN);
-
- if (rv) {
- ppc_err_prints("Could not disable both FETS", port, rv);
- return rv;
- }
-
- /* Turn off Vconn power */
- rv = clr_flags(port, SN5S330_FUNC_SET4, SN5S330_VCONN_EN);
-
- if (rv) {
- ppc_err_prints("Could not disable Vconn", port, rv);
- return rv;
- }
-
- /* Turn off SBU path */
- rv = clr_flags(port, SN5S330_FUNC_SET2, SN5S330_SBU_EN);
-
- if (rv) {
- ppc_err_prints("Could not disable SBU path", port, rv);
- return rv;
- }
-
- /*
- * Turn off the Over Voltage Protection circuits. Needs to happen after
- * FETs are disabled, otherwise OVP can automatically turned back on.
- * Since FETs are off, any over voltage does not make it to the board
- * side of the PPC.
- */
- rv = clr_flags(port, SN5S330_FUNC_SET9,
- SN5S330_FORCE_OVP_EN_SBU | SN5S330_FORCE_ON_VBUS_OVP |
- SN5S330_FORCE_ON_VBUS_UVP);
-
- if (rv) {
- ppc_err_prints("Could not disable OVP circuit", port, rv);
- return rv;
- }
-
- return EC_SUCCESS;
-}
-
-#ifdef CONFIG_USBC_PPC_VCONN
-static int sn5s330_set_vconn(int port, int enable)
-{
- int regval;
- int status;
-
- status = read_reg(port, SN5S330_FUNC_SET4, &regval);
- if (status)
- return status;
-
- if (enable)
- regval |= SN5S330_VCONN_EN;
- else
- regval &= ~SN5S330_VCONN_EN;
-
- return write_reg(port, SN5S330_FUNC_SET4, regval);
-}
-#endif
-
-static int sn5s330_vbus_sink_enable(int port, int enable)
-{
- return sn5s330_pp_fet_enable(port, SN5S330_PP2, !!enable);
-}
-
-static int sn5s330_vbus_source_enable(int port, int enable)
-{
- return sn5s330_pp_fet_enable(port, SN5S330_PP1, !!enable);
-}
-
-#ifdef CONFIG_USBC_PPC_SBU
-static int sn5s330_set_sbu(int port, int enable)
-{
- int rv;
-
- if (enable)
- rv = set_flags(port, SN5S330_FUNC_SET2, SN5S330_SBU_EN);
- else
- rv = clr_flags(port, SN5S330_FUNC_SET2, SN5S330_SBU_EN);
-
- return rv;
-}
-#endif /* CONFIG_USBC_PPC_SBU */
-
-static void sn5s330_handle_interrupt(int port)
-{
- int attempt = 0;
-
- /*
- * SN5S330's /INT pin is level, so process interrupts until it
- * deasserts if the chip has a dedicated interrupt pin.
- */
-#ifdef CONFIG_USBC_PPC_DEDICATED_INT
- while (ppc_get_alert_status(port))
-#endif
- {
- int rise = 0;
- int fall = 0;
-
- attempt++;
-
- if (attempt > 1)
- ppc_prints("Could not clear interrupts on first "
- "try, retrying", port);
-
- read_reg(port, SN5S330_INT_TRIP_RISE_REG1, &rise);
- read_reg(port, SN5S330_INT_TRIP_FALL_REG1, &fall);
-
- /* Notify the system about the overcurrent event. */
- if (rise & SN5S330_ILIM_PP1_MASK)
- pd_handle_overcurrent(port);
-
- /* Clear the interrupt sources. */
- write_reg(port, SN5S330_INT_TRIP_RISE_REG1, rise);
- write_reg(port, SN5S330_INT_TRIP_FALL_REG1, fall);
-
- read_reg(port, SN5S330_INT_TRIP_RISE_REG2, &rise);
- read_reg(port, SN5S330_INT_TRIP_FALL_REG2, &fall);
-
- /*
- * VCONN may be latched off due to an overcurrent. Indicate
- * when the VCONN overcurrent happens.
- */
- if (rise & SN5S330_VCONN_ILIM)
- ppc_prints("VCONN OC!", port);
-
- /* Notify the system about the CC overvoltage event. */
- if (rise & SN5S330_CC1_CON || rise & SN5S330_CC2_CON) {
- ppc_prints("CC OV!", port);
- pd_handle_cc_overvoltage(port);
- }
-
- /* Clear the interrupt sources. */
- write_reg(port, SN5S330_INT_TRIP_RISE_REG2, rise);
- write_reg(port, SN5S330_INT_TRIP_FALL_REG2, 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)
-{
- int i;
- uint32_t pending = atomic_clear(&irq_pending);
-
- for (i = 0; i < board_get_usb_pd_port_count(); i++)
- if (BIT(i) & pending)
- sn5s330_handle_interrupt(i);
-}
-DECLARE_DEFERRED(sn5s330_irq_deferred);
-
-void sn5s330_interrupt(int port)
-{
- atomic_or(&irq_pending, BIT(port));
- hook_call_deferred(&sn5s330_irq_deferred_data, 0);
-}
-
-const struct ppc_drv sn5s330_drv = {
- .init = &sn5s330_init,
- .is_sourcing_vbus = &sn5s330_is_sourcing_vbus,
- .vbus_sink_enable = &sn5s330_vbus_sink_enable,
- .vbus_source_enable = &sn5s330_vbus_source_enable,
- .set_vbus_source_current_limit = &sn5s330_set_vbus_source_current_limit,
- .discharge_vbus = &sn5s330_discharge_vbus,
- .enter_low_power_mode = &sn5s330_enter_low_power_mode,
-#ifdef CONFIG_CMD_PPC_DUMP
- .reg_dump = &sn5s330_dump,
-#endif
-#ifdef CONFIG_USB_PD_VBUS_DETECT_PPC
- .is_vbus_present = &sn5s330_is_vbus_present,
-#endif
-#ifdef CONFIG_USBC_PPC_POLARITY
- .set_polarity = &sn5s330_set_polarity,
-#endif
-#ifdef CONFIG_USBC_PPC_SBU
- .set_sbu = &sn5s330_set_sbu,
-#endif /* defined(CONFIG_USBC_PPC_SBU) */
-#ifdef CONFIG_USBC_PPC_VCONN
- .set_vconn = &sn5s330_set_vconn,
-#endif
-};