diff options
-rw-r--r-- | common/usb_pd_protocol.c | 6 | ||||
-rw-r--r-- | common/usbc_ppc.c | 4 | ||||
-rw-r--r-- | driver/build.mk | 1 | ||||
-rw-r--r-- | driver/ppc/nx20p3483.c | 326 | ||||
-rw-r--r-- | driver/ppc/nx20p3483.h | 106 | ||||
-rw-r--r-- | driver/ppc/sn5s330.c | 8 | ||||
-rw-r--r-- | include/config.h | 15 | ||||
-rw-r--r-- | include/usbc_ppc.h | 13 |
8 files changed, 475 insertions, 4 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index 12b1546217..2f25e06564 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -321,9 +321,9 @@ static inline int pd_is_vbus_present(int port) static void set_polarity(int port, int polarity) { tcpm_set_polarity(port, polarity); -#ifdef CONFIG_USBC_PPC +#ifdef CONFIG_USBC_PPC_POLARITY ppc_set_polarity(port, polarity); -#endif /* defined(CONFIG_USBC_PPC) */ +#endif /* defined(CONFIG_USBC_PPC_POLARITY) */ } #ifdef CONFIG_USBC_VCONN @@ -337,7 +337,7 @@ static void set_vconn(int port, int enable) * "make before break" electrical requirements when swapping anyway. */ tcpm_set_vconn(port, enable); -#ifdef CONFIG_USBC_PPC +#ifdef CONFIG_USBC_PPC_VCONN ppc_set_vconn(port, enable); #endif } diff --git a/common/usbc_ppc.c b/common/usbc_ppc.c index 6ff79a17bf..7011309cf1 100644 --- a/common/usbc_ppc.c +++ b/common/usbc_ppc.c @@ -42,6 +42,7 @@ int ppc_is_sourcing_vbus(int port) return ppc_chips[port].drv->is_sourcing_vbus(port); } +#ifdef CONFIG_USBC_PPC_POLARITY int ppc_set_polarity(int port, int polarity) { if ((port < 0) || (port >= ppc_cnt)) @@ -49,6 +50,7 @@ int ppc_set_polarity(int port, int polarity) return ppc_chips[port].drv->set_polarity(port, polarity); } +#endif int ppc_set_vbus_source_current_limit(int port, enum tcpc_rp_value rp) { @@ -66,6 +68,7 @@ int ppc_discharge_vbus(int port, int enable) return ppc_chips[port].drv->discharge_vbus(port, enable); } +#ifdef CONFIG_USBC_PPC_VCONN int ppc_set_vconn(int port, int enable) { if ((port < 0) || (port >= ppc_cnt)) @@ -73,6 +76,7 @@ int ppc_set_vconn(int port, int enable) return ppc_chips[port].drv->set_vconn(port, enable); } +#endif int ppc_vbus_sink_enable(int port, int enable) { diff --git a/driver/build.mk b/driver/build.mk index 23eb0a2d65..924a76eecd 100644 --- a/driver/build.mk +++ b/driver/build.mk @@ -116,6 +116,7 @@ driver-$(CONFIG_USB_MUX_VIRTUAL)+=usb_mux_virtual.o # Type-C Power Path Controllers (PPC) driver-$(CONFIG_USBC_PPC_SN5S330)+=ppc/sn5s330.o +driver-$(CONFIG_USBC_PPC_NX20P3483)+=ppc/nx20p3483.o # video converters driver-$(CONFIG_MCDP28X0)+=mcdp28x0.o diff --git a/driver/ppc/nx20p3483.c b/driver/ppc/nx20p3483.c new file mode 100644 index 0000000000..7a3893443e --- /dev/null +++ b/driver/ppc/nx20p3483.c @@ -0,0 +1,326 @@ +/* Copyright 2018 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. + */ + +/* NX20P3483 USB-C Power Path Controller */ + +#include "common.h" +#include "console.h" +#include "driver/ppc/nx20p3483.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "system.h" +#include "usb_charge.h" +#include "usb_pd_tcpm.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) + +#define NX20P3483_DB_EXIT_FAIL_THRESHOLD 10 + +static uint32_t irq_pending; /* Bitmask of ports signaling an interrupt. */ +static int db_exit_fail_count[CONFIG_USB_PD_PORT_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, + 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, + reg, + regval); +} + +static int nx20p3483_is_sourcing_vbus(int port) +{ + int mode; + int rv; + + rv = read_reg(port, NX20P3483_DEVICE_STATUS_REG, &mode); + if (rv) { + CPRINTS("p%d: Failed to determine NX20P device status! (%d)", + port, rv); + return 0; + } + + return ((mode & NX20P3483_DEVICE_MODE_MASK) == NX20P3483_MODE_5V_SRC); +} + +static int nx20p3483_set_vbus_source_current_limit(int port, + enum tcpc_rp_value rp) +{ + int regval; + int status; + + status = read_reg(port, NX20P3483_5V_SRC_OCP_THRESHOLD_REG, ®val); + if (status) + return status; + + regval &= ~NX20P3483_ILIM_MASK; + switch (rp) { + case TYPEC_RP_3A0: + regval |= NX20P3483_ILIM_3_000; + break; + + case TYPEC_RP_1A5: + regval |= NX20P3483_ILIM_1_600; + break; + + case TYPEC_RP_USB: + default: + regval |= NX20P3483_ILIM_0_600; + break; + }; + + + return write_reg(port, NX20P3483_5V_SRC_OCP_THRESHOLD_REG, regval); +} + +static int nx20p3483_discharge_vbus(int port, int enable) +{ + int regval; + int status; + + status = read_reg(port, NX20P3483_DEVICE_CONTROL_REG, ®val); + if (status) + return status; + + if (enable) + regval |= NX20P3483_CTRL_VBUSDIS_EN; + else + regval &= ~NX20P3483_CTRL_VBUSDIS_EN; + + status = write_reg(port, NX20P3483_DEVICE_CONTROL_REG, regval); + if (status) { + CPRINTS("Failed to %s vbus discharge", + enable ? "enable" : "disable"); + return status; + } + + return EC_SUCCESS; +} + +static int nx20p3483_vbus_sink_enable(int port, int enable) +{ + int status; + int rv; + + enable = !!enable; + /* + * IF PPC_CFG_FLAGS_GPIO_CONTROL is set, then the SNK/SRC switch + * control is driven by the EC. Otherwise, it's controlled directly by + * the TCPC and only need to check the status. + */ + if (ppc_chips[port].flags & PPC_CFG_FLAGS_GPIO_CONTROL) { + + /* If enable, makes sure that SRC mode is disabled */ + if (enable) + gpio_set_level(ppc_chips[port].src_gpio, 0); + + /* Set SNK mode based on enable */ + gpio_set_level(ppc_chips[port].snk_gpio, enable); + } + + /* Verify switch status register */ + rv = read_reg(port, NX20P3483_SWITCH_STATUS_REG, &status); + if (rv) + return rv; + status = !!(status & NX20P3483_HVSNK_STS); + return (status == enable) ? EC_SUCCESS : EC_ERROR_UNKNOWN; +} + +static int nx20p3483_vbus_source_enable(int port, int enable) +{ + int status; + int rv; + + enable = !!enable; + /* + * IF PPC_CFG_FLAGS_GPIO_CONTROL is set, then the SNK/SRC switch + * control is driven by the EC. Otherwise, it's controlled directly by + * the TCPC and only need to check the status. + */ + if (ppc_chips[port].flags & PPC_CFG_FLAGS_GPIO_CONTROL) { + + /* If enable, makes sure that SNK mode is disabled */ + if (enable) + gpio_set_level(ppc_chips[port].snk_gpio, 0); + + /* Set SRC mode based on enable */ + gpio_set_level(ppc_chips[port].src_gpio, enable); + } + + /* Verify switch status register */ + rv = read_reg(port, NX20P3483_SWITCH_STATUS_REG, &status); + if (rv) + return rv; + status = !!(status & NX20P3483_5VSRC_STS); + return (status == enable) ? EC_SUCCESS : EC_ERROR_UNKNOWN; +} + +static int nx20p3483_init(int port) +{ + int reg; + int mask; + int rv; + + /* Set VBUS over voltage threshold (OVLO) */ + rv = read_reg(port, NX20P3483_OVLO_THRESHOLD_REG, ®); + if (rv) + return rv; + /* OVLO threshold is 3 bit field */ + reg &= ~NX20P3483_OVLO_THRESHOLD_MASK; + /* Set SNK OVP to 23.0 V */ + reg |= NX20P3483_OVLO_23_0; + rv = write_reg(port, NX20P3483_OVLO_THRESHOLD_REG, reg); + if (rv) + return rv; + + /* Mask interrupts for interrupt 2 register */ + mask = ~NX20P3483_INT2_EN_ERR; + rv = write_reg(port, NX20P3483_INTERRUPT2_MASK_REG, mask); + if (rv) + return rv; + + /* Mask interrupts for interrupt 1 register */ + mask = ~(NX20P3483_INT1_OC_5VSRC | NX20P3483_INT1_DBEXIT_ERR); + rv = write_reg(port, NX20P3483_INTERRUPT1_MASK_REG, mask); + if (rv) + return rv; + + /* Clear any pending interrupts by reading interrupt registers */ + read_reg(port, NX20P3483_INTERRUPT1_REG, ®); + read_reg(port, NX20P3483_INTERRUPT2_REG, ®); + + /* Make sure that dead battery mode is exited */ + rv = read_reg(port, NX20P3483_DEVICE_CONTROL_REG, ®); + if (rv) + return rv; + reg |= NX20P3483_CTRL_DB_EXIT; + rv = write_reg(port, NX20P3483_DEVICE_CONTROL_REG, reg); + if (rv) + return rv; + + return EC_SUCCESS; +} + +static void nx20p3483_handle_interrupt(int port) +{ + int reg; + int control_reg; + + /* + * Read interrupt 1 status register. Note, interrupt register is + * automatically cleared by reading. + */ + read_reg(port, NX20P3483_INTERRUPT1_REG, ®); + + /* Check for DBEXIT error */ + if (reg & NX20P3483_INT1_DBEXIT_ERR) { + int mask_reg; + + /* + * This failure is not expected. If for some reason, this + * keeps happening, then log an error and mask the interrupt to + * prevent interrupt floods. + */ + if (++db_exit_fail_count[port] >= + NX20P3483_DB_EXIT_FAIL_THRESHOLD) { + CPRINTS("Port %d PPC failed to exit DB mode", port); + if (read_reg(port, NX20P3483_INTERRUPT1_MASK_REG, + &mask_reg)) { + mask_reg |= NX20P3483_INT1_DBEXIT_ERR; + write_reg(port, NX20P3483_INTERRUPT1_MASK_REG, + mask_reg); + } + } + read_reg(port, NX20P3483_DEVICE_CONTROL_REG, &control_reg); + reg |= NX20P3483_CTRL_DB_EXIT; + write_reg(port, NX20P3483_DEVICE_CONTROL_REG, control_reg); + } + + /* Check for 5V OC interrupt */ + if (reg & NX20P3483_INT1_OC_5VSRC) { + /* + * TODO (b/69935262): The overcurrent action hasn't + * been completed yet, but is required for TI PPC. When that + * work is complete, tie it in here. + */ + } + + /* + * Read interrupt 2 status register. Note, interrupt register is + * automatically cleared by reading. + */ + /* + * TODO (b/75272421): Not sure if any of these interrupts + * will be used. Might want to use EN_ERR which tracks when both + * SNK_EN and SRC_EN are set. However, since for the Analogix TCPC + * these values aren't controlled by the EC directly, not sure what + * action if any can be taken. + */ + read_reg(port, NX20P3483_INTERRUPT2_REG, ®); +} + +static void nx20p3483_irq_deferred(void) +{ + int i; + uint32_t pending = atomic_read_clear(&irq_pending); + + for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) + if ((1 << i) & pending) + nx20p3483_handle_interrupt(i); +} +DECLARE_DEFERRED(nx20p3483_irq_deferred); + +void nx20p3483_interrupt(int port) +{ + atomic_or(&irq_pending, (1 << port)); + hook_call_deferred(&nx20p3483_irq_deferred_data, 0); +} + +#ifdef CONFIG_CMD_PPC_DUMP +static int nx20p3483_dump(int port) +{ + int reg_addr; + int reg; + int rv; + + ccprintf("Port %d NX20P3483 registers\n", port); + for (reg_addr = NX20P3483_DEVICE_ID_REG; reg_addr <= + NX20P3483_DEVICE_CONTROL_REG; reg_addr++) { + rv = read_reg(port, reg_addr, ®); + if (rv) { + ccprintf("nx20p: Failed to read register 0x%x\n", + reg_addr); + return rv; + } + ccprintf("[0x%02x]: 0x%02x\n", reg_addr, reg); + } + + return EC_SUCCESS; +} +#endif /* defined(CONFIG_CMD_PPC_DUMP) */ + +const struct ppc_drv nx20p3483_drv = { + .init = &nx20p3483_init, + .is_sourcing_vbus = &nx20p3483_is_sourcing_vbus, + .vbus_sink_enable = &nx20p3483_vbus_sink_enable, + .vbus_source_enable = &nx20p3483_vbus_source_enable, +#ifdef CONFIG_CMD_PPC_DUMP + .reg_dump = &nx20p3483_dump, +#endif /* defined(CONFIG_CMD_PPC_DUMP) */ + .set_vbus_source_current_limit = + &nx20p3483_set_vbus_source_current_limit, + .discharge_vbus = &nx20p3483_discharge_vbus, +}; diff --git a/driver/ppc/nx20p3483.h b/driver/ppc/nx20p3483.h new file mode 100644 index 0000000000..a85a0b72b4 --- /dev/null +++ b/driver/ppc/nx20p3483.h @@ -0,0 +1,106 @@ +/* Copyright 2018 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. + */ + +/* NX20P3483 Type-C Power Path Controller */ + +#ifndef __CROS_EC_NX20P3483_H +#define __CROS_EC_NX20P3483_H + +#define NX20P3483_ADDR0 0xE0 +#define NX20P3483_ADDR1 0xE2 +#define NX20P3483_ADDR2 0xE4 +#define NX20P3483_ADDR3 0xE6 + +/* NX20P3483 register addresses */ +#define NX20P3483_DEVICE_ID_REG 0x00 +#define NX20P3483_DEVICE_STATUS_REG 0x01 +#define NX20P3483_SWITCH_CONTROL_REG 0x02 +#define NX20P3483_SWITCH_STATUS_REG 0x03 +#define NX20P3483_INTERRUPT1_REG 0x04 +#define NX20P3483_INTERRUPT2_REG 0x05 +#define NX20P3483_INTERRUPT1_MASK_REG 0x06 +#define NX20P3483_INTERRUPT2_MASK_REG 0x07 +#define NX20P3483_OVLO_THRESHOLD_REG 0x08 +#define NX20P3483_HV_SRC_OCP_THRESHOLD_REG 0x09 +#define NX20P3483_5V_SRC_OCP_THRESHOLD_REG 0x0A +#define NX20P3483_DEVICE_CONTROL_REG 0x0B + +/* Device Control Register */ +#define NX20P3483_CTRL_FRS_AT (1 << 3) +#define NX20P3483_CTRL_DB_EXIT (1 << 2) +#define NX20P3483_CTRL_VBUSDIS_EN (1 << 1) +#define NX20P3483_CTRL_LDO_SD (1 << 0) + +/* Device Status Modes */ +#define NX20P3483_DEVICE_MODE_MASK 0x7 +#define NX20P3483_MODE_DEAD_BATTERY 0 +#define NX20P3483_MODE_HV_SNK 1 +#define NX20P3483_MODE_5V_SRC 2 +#define NX20P3483_MODE_HV_SRC 3 +#define NX20P3483_MODE_STANDBY 4 + +/* Switch Status Register */ +#define NX20P3483_HVSNK_STS (1 << 0) +#define NX20P3483_HVSRC_STS (1 << 1) +#define NX20P3483_5VSRC_STS (1 << 2) + +/* Internal 5V VBUS Switch Current Limit Settings (min) */ +#define NX20P3483_ILIM_MASK 0xF +#define NX20P3483_ILIM_0_400 0 +#define NX20P3483_ILIM_0_600 1 +#define NX20P3483_ILIM_0_800 2 +#define NX20P3483_ILIM_1_000 3 +#define NX20P3483_ILIM_1_200 4 +#define NX20P3483_ILIM_1_400 5 +#define NX20P3483_ILIM_1_600 6 +#define NX20P3483_ILIM_1_800 7 +#define NX20P3483_ILIM_2_000 8 +#define NX20P3483_ILIM_2_200 9 +#define NX20P3483_ILIM_2_400 10 +#define NX20P3483_ILIM_2_600 11 +#define NX20P3483_ILIM_2_800 12 +#define NX20P3483_ILIM_3_000 13 +#define NX20P3483_ILIM_3_200 14 +#define NX20P3483_ILIM_3_400 15 + +/* HV VBUS over voltage threshold settings V_mV*/ +#define NX20P3483_OVLO_THRESHOLD_MASK 0x7 +#define NX20P3483_OVLO_06_0 0 +#define NX20P3483_OVLO_06_8 1 +#define NX20P3483_OVLO_10_0 2 +#define NX20P3483_OVLO_11_5 3 +#define NX20P3483_OVLO_14_0 4 +#define NX20P3483_OVLO_17_0 5 +#define NX20P3483_OVLO_23_0 6 + +/* Interrupt 1 Register Bits */ +#define NX20P3483_INT1_DBEXIT_ERR (1 << 7) +#define NX20P3483_INT1_OV_5VSRC (1 << 4) +#define NX20P3483_INT1_RCP_5VSRC (1 << 3) +#define NX20P3483_INT1_SC_5VSRC (1 << 2) +#define NX20P3483_INT1_OC_5VSRC (1 << 1) +#define NX20P3483_INT1_OTP (1 << 0) + +/* Interrupt 2 Register Bits */ +#define NX20P3483_INT2_EN_ERR (1 << 7) +#define NX20P3483_INT2_RCP_HVSNK (1 << 6) +#define NX20P3483_INT2_SC_HVSNK (1 << 5) +#define NX20P3483_INT2_OV_HVSNK (1 << 4) +#define NX20P3483_INT2_RCP_HVSRC (1 << 3) +#define NX20P3483_INT2_SC_HVSRC (1 << 2) +#define NX20P3483_INT2_OC_HVSRC (1 << 1) +#define NX20P3483_INT2_OV_HVSRC (1 << 0) + +struct ppc_drv; +extern const struct ppc_drv nx20p3483_drv; + +/** + * Interrupt Handler for the NX20P3483. + * + * @param port: The Type-C port which triggered the interrupt. + */ +void nx20p3483_interrupt(int port); + +#endif /* defined(__CROS_EC_NX20P3483_H) */ diff --git a/driver/ppc/sn5s330.c b/driver/ppc/sn5s330.c index 25fa7ae022..e0abf3aacf 100644 --- a/driver/ppc/sn5s330.c +++ b/driver/ppc/sn5s330.c @@ -456,6 +456,7 @@ static int sn5s330_is_sourcing_vbus(int port) return is_sourcing_vbus; } +#ifdef CONFIG_USBC_PPC_POLARITY static int sn5s330_set_polarity(int port, int polarity) { int regval; @@ -472,6 +473,7 @@ static int sn5s330_set_polarity(int port, int polarity) return write_reg(port, SN5S330_FUNC_SET4, regval); } +#endif static int sn5s330_set_vbus_source_current_limit(int port, enum tcpc_rp_value rp) @@ -533,6 +535,7 @@ static int sn5s330_discharge_vbus(int port, int enable) return EC_SUCCESS; } +#ifdef CONFIG_USBC_PPC_VCONN static int sn5s330_set_vconn(int port, int enable) { int regval; @@ -549,6 +552,7 @@ static int sn5s330_set_vconn(int port, int enable) return write_reg(port, SN5S330_FUNC_SET4, regval); } +#endif static int sn5s330_vbus_sink_enable(int port, int enable) { @@ -623,8 +627,12 @@ const struct ppc_drv sn5s330_drv = { #ifdef CONFIG_USB_PD_VBUS_DETECT_PPC .is_vbus_present = &sn5s330_is_vbus_present, #endif /* defined(CONFIG_USB_PD_VBUS_DETECT_PPC) */ +#ifdef CONFIG_USBC_PPC_POLARITY .set_polarity = &sn5s330_set_polarity, +#endif .set_vbus_source_current_limit = &sn5s330_set_vbus_source_current_limit, .discharge_vbus = &sn5s330_discharge_vbus, +#ifdef CONFIG_USBC_PPC_VCONN .set_vconn = &sn5s330_set_vconn, +#endif }; diff --git a/include/config.h b/include/config.h index 985c017cfb..62a8bb75b0 100644 --- a/include/config.h +++ b/include/config.h @@ -2894,9 +2894,16 @@ /* USB Product ID. */ #undef CONFIG_USB_PID +/* PPC needs to be informed of CC polarity */ +#undef CONFIG_USBC_PPC_POLARITY + /* USB Type-C Power Path Controllers (PPC) */ +#undef CONFIG_USBC_PPC_NX20P3483 #undef CONFIG_USBC_PPC_SN5S330 +/* PPC is capable of providing VCONN */ +#undef CONFIG_USBC_PPC_VCONN + /* Support for USB type-c superspeed mux */ #undef CONFIG_USBC_SS_MUX @@ -3344,10 +3351,16 @@ /*****************************************************************************/ /* Define CONFIG_USBC_PPC if board has a USB Type-C Power Path Controller. */ -#if defined(CONFIG_USBC_PPC_SN5S330) +#if defined(CONFIG_USBC_PPC_SN5S330) || defined(CONFIG_USBC_PPC_NX20P3483) #define CONFIG_USBC_PPC #endif /* "has a PPC" */ +/* The TI SN5S330 supports VCONN and needs to be informed of CC polarity */ +#if defined(CONFIG_USBC_PPC_SN5S330) +#define CONFIG_USBC_PPC_POLARITY +#define CONFIG_USBC_PPC_VCONN +#endif + /*****************************************************************************/ /* * Define CONFIG_USB_PD_VBUS_MEASURE_CHARGER if the charger on the board diff --git a/include/usbc_ppc.h b/include/usbc_ppc.h index 54142b2921..1995654536 100644 --- a/include/usbc_ppc.h +++ b/include/usbc_ppc.h @@ -48,6 +48,7 @@ struct ppc_drv { */ int (*vbus_source_enable)(int port, int enable); +#ifdef CONFIG_USBC_PPC_POLARITY /** * Inform the PPC of the polarity of the CC pins. * @@ -56,6 +57,7 @@ struct ppc_drv { * @return EC_SUCCESS on success, error otherwise. */ int (*set_polarity)(int port, int polarity); +#endif /** * Set the Vbus source path current limit @@ -75,6 +77,7 @@ struct ppc_drv { */ int (*discharge_vbus)(int port, int enable); +#ifdef CONFIG_USBC_PPC_VCONN /** * Turn on/off the VCONN FET. * @@ -82,6 +85,7 @@ struct ppc_drv { * @param enable: 1: enable VCONN FET 0: disable VCONN FET. */ int (*set_vconn)(int port, int enable); +#endif #ifdef CONFIG_CMD_PPC_DUMP /** @@ -104,9 +108,18 @@ struct ppc_drv { #endif /* defined(CONFIG_USB_PD_VBUS_DETECT_PPC) */ }; + +/* PPC SNK/SRC switch control driven by EC GPIO */ +#define PPC_CFG_FLAGS_GPIO_CONTROL (1 << 0) + struct ppc_config_t { + /* Used for PPC_CFG_FLAGS_* defined above */ + uint32_t flags; int i2c_port; int i2c_addr; + /* snk|src_gpio only required if PPC_CFG_FLAGS_GPIO_CONTROL is set */ + enum gpio_signal snk_gpio; + enum gpio_signal src_gpio; const struct ppc_drv *drv; }; |