summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/grunt/board.c221
-rw-r--r--board/grunt/board.h68
-rw-r--r--board/grunt/ec.tasklist8
-rw-r--r--board/grunt/gpio.inc44
-rw-r--r--board/grunt/usb_pd_policy.c42
-rw-r--r--driver/bc12/bq24392.c1
6 files changed, 339 insertions, 45 deletions
diff --git a/board/grunt/board.c b/board/grunt/board.c
index 68d765dab4..23e8e0dad6 100644
--- a/board/grunt/board.c
+++ b/board/grunt/board.c
@@ -11,8 +11,11 @@
#include "charge_state.h"
#include "charge_state_v2.h"
#include "common.h"
-#include "console.h"
#include "compile_time_macros.h"
+#include "console.h"
+#include "driver/ppc/sn5s330.h"
+#include "driver/tcpm/anx74xx.h"
+#include "driver/tcpm/ps8xxx.h"
#include "ec_commands.h"
#include "extpower.h"
#include "gpio.h"
@@ -23,8 +26,9 @@
#include "power.h"
#include "power_button.h"
#include "registers.h"
-#include "system.h"
#include "switch.h"
+#include "system.h"
+#include "task.h"
#include "tcpci.h"
#include "usb_mux.h"
#include "usb_pd_tcpm.h"
@@ -32,8 +36,46 @@
static void tcpc_alert_event(enum gpio_signal signal)
{
- /* TODO(ecgh) */
+ if ((signal == GPIO_USB_C0_PD_INT_ODL) &&
+ !gpio_get_level(GPIO_USB_C0_PD_RST_L))
+ return;
+
+ if ((signal == GPIO_USB_C1_PD_INT_ODL) &&
+ !gpio_get_level(GPIO_USB_C1_PD_RST_L))
+ return;
+
+#ifdef HAS_TASK_PDCMD
+ /* Exchange status with TCPCs */
+ host_command_pd_send_status(PD_CHARGE_NO_CHANGE);
+#endif
+}
+
+#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
+static void anx74xx_cable_det_handler(void)
+{
+ int cable_det = gpio_get_level(GPIO_USB_C0_CABLE_DET);
+ int reset_n = gpio_get_level(GPIO_USB_C0_PD_RST_L);
+
+ /*
+ * A cable_det low->high transition was detected. If following the
+ * debounce time, cable_det is high, and reset_n is low, then ANX3429 is
+ * currently in standby mode and needs to be woken up. Set the
+ * TCPC_RESET event which will bring the ANX3429 out of standby
+ * mode. Setting this event is gated on reset_n being low because the
+ * ANX3429 will always set cable_det when transitioning to normal mode
+ * and if in normal mode, then there is no need to trigger a tcpc reset.
+ */
+ if (cable_det && !reset_n)
+ task_set_event(TASK_ID_PD_C0, PD_EVENT_TCPC_RESET, 0);
+}
+DECLARE_DEFERRED(anx74xx_cable_det_handler);
+
+void anx74xx_cable_det_interrupt(enum gpio_signal signal)
+{
+ /* debounce for 2 msec */
+ hook_call_deferred(&anx74xx_cable_det_handler_data, (2 * MSEC));
}
+#endif
#include "gpio_list.h"
@@ -72,6 +114,179 @@ const struct i2c_port_t i2c_ports[] = {
};
const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
+#define USB_PD_PORT_ANX74XX 0
+#define USB_PD_PORT_PS8751 1
+
+const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_COUNT] = {
+ [USB_PD_PORT_ANX74XX] = {
+ .i2c_host_port = I2C_PORT_TCPC0,
+ .i2c_slave_addr = 0x50,
+ .drv = &anx74xx_tcpm_drv,
+ .pol = TCPC_ALERT_ACTIVE_LOW,
+ },
+ [USB_PD_PORT_PS8751] = {
+ .i2c_host_port = I2C_PORT_TCPC1,
+ .i2c_slave_addr = 0x16,
+ .drv = &ps8xxx_tcpm_drv,
+ .pol = TCPC_ALERT_ACTIVE_LOW,
+ },
+};
+
+uint16_t tcpc_get_alert_status(void)
+{
+ uint16_t status = 0;
+
+ if (!gpio_get_level(GPIO_USB_C0_PD_INT_ODL)) {
+ if (gpio_get_level(GPIO_USB_C0_PD_RST_L))
+ status |= PD_STATUS_TCPC_ALERT_0;
+ }
+
+ if (!gpio_get_level(GPIO_USB_C1_PD_INT_ODL)) {
+ if (gpio_get_level(GPIO_USB_C1_PD_RST_L))
+ status |= PD_STATUS_TCPC_ALERT_1;
+ }
+
+ return status;
+}
+
+struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_COUNT] = {
+ {
+ .port_addr = USB_PD_PORT_ANX74XX, /* don't care / unused */
+ .driver = &anx74xx_tcpm_usb_mux_driver,
+ .hpd_update = &anx74xx_tcpc_update_hpd_status,
+ },
+ {
+ .port_addr = USB_PD_PORT_PS8751,
+ .driver = &tcpci_tcpm_usb_mux_driver,
+ .hpd_update = &ps8xxx_tcpc_update_hpd_status,
+ /* TODO(ecgh): ps8751_tune_mux needed? */
+ }
+};
+
+const struct sn5s330_config sn5s330_chips[] = {
+ {I2C_PORT_TCPC0, SN5S330_ADDR0},
+ {I2C_PORT_TCPC1, SN5S330_ADDR0},
+};
+const unsigned int sn5s330_cnt = ARRAY_SIZE(sn5s330_chips);
+
+const int usb_port_enable[CONFIG_USB_PORT_POWER_SMART_PORT_COUNT] = {
+ GPIO_EN_USB_A0_5V,
+ GPIO_EN_USB_A1_5V,
+};
+
+/**
+ * Power on (or off) a single TCPC.
+ * minimum on/off delays are included.
+ *
+ * @param port Port number of TCPC.
+ * @param mode 0: power off, 1: power on.
+ */
+void board_set_tcpc_power_mode(int port, int mode)
+{
+ if (port != USB_PD_PORT_ANX74XX)
+ return;
+
+ switch (mode) {
+ case ANX74XX_NORMAL_MODE:
+ gpio_set_level(GPIO_EN_USB_C0_TCPC_PWR, 1);
+ msleep(ANX74XX_PWR_H_RST_H_DELAY_MS);
+ gpio_set_level(GPIO_USB_C0_PD_RST_L, 1);
+ break;
+ case ANX74XX_STANDBY_MODE:
+ gpio_set_level(GPIO_USB_C0_PD_RST_L, 0);
+ msleep(ANX74XX_RST_L_PWR_L_DELAY_MS);
+ gpio_set_level(GPIO_EN_USB_C0_TCPC_PWR, 0);
+ msleep(ANX74XX_PWR_L_PWR_H_DELAY_MS);
+ break;
+ default:
+ break;
+ }
+}
+
+void board_reset_pd_mcu(void)
+{
+ /* Assert reset to TCPC1 (ps8751) */
+ gpio_set_level(GPIO_USB_C1_PD_RST_L, 0);
+
+ /* Assert reset to TCPC0 (anx3429) */
+ gpio_set_level(GPIO_USB_C0_PD_RST_L, 0);
+
+ /* TCPC1 (ps8751) requires 1ms reset down assertion */
+ msleep(MAX(1, ANX74XX_RST_L_PWR_L_DELAY_MS));
+
+ /* Deassert reset to TCPC1 */
+ gpio_set_level(GPIO_USB_C1_PD_RST_L, 1);
+ /* Disable TCPC0 power */
+ gpio_set_level(GPIO_EN_USB_C0_TCPC_PWR, 0);
+
+ /*
+ * anx3429 requires 10ms reset/power down assertion
+ */
+ msleep(ANX74XX_PWR_L_PWR_H_DELAY_MS);
+ board_set_tcpc_power_mode(USB_PD_PORT_ANX74XX, 1);
+}
+
+void board_tcpc_init(void)
+{
+ int port;
+
+ /* TODO(ecgh): need to wait for disconnected battery? */
+
+ /* Only reset TCPC if not sysjump */
+ if (!system_jumped_to_this_image())
+ board_reset_pd_mcu();
+
+ /* Enable TCPC0 interrupt */
+ gpio_enable_interrupt(GPIO_USB_C0_PD_INT_ODL);
+
+ /* Enable TCPC1 interrupt */
+ gpio_enable_interrupt(GPIO_USB_C1_PD_INT_ODL);
+
+#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
+ /* Enable CABLE_DET interrupt for ANX3429 wake from standby */
+ gpio_enable_interrupt(GPIO_USB_C0_CABLE_DET);
+#endif
+ /*
+ * Initialize HPD to low; after sysjump SOC needs to see
+ * HPD pulse to enable video path
+ */
+ for (port = 0; port < CONFIG_USB_PD_PORT_COUNT; port++) {
+ const struct usb_mux *mux = &usb_muxes[port];
+
+ mux->hpd_update(port, 0, 0);
+ }
+}
+
+int pd_snk_is_vbus_provided(int port)
+{
+ /* TODO(ecgh): Detect VBUS via SWCTL_INT and I2C to SN5S330 */
+ return 0;
+}
+
+int board_set_active_charge_port(int port)
+{
+ /* TODO(ecgh): how to disable/enable charge ports? */
+ /* TODO(ecgh): how to check if port sourcing VBUS? */
+ /* TODO(ecgh): disable/enable SN5S330 FETs? */
+ return EC_SUCCESS;
+}
+
+void board_set_charge_limit(int port, int supplier, int charge_ma,
+ int max_ma, int charge_mv)
+{
+ /* TODO(ecgh): check limits */
+ /*
+ * To protect the charge inductor, at voltages above 18V we should
+ * set the current limit to 2.7A.
+ */
+ if (charge_mv > 18000)
+ charge_ma = MIN(2700, charge_ma);
+
+ charge_set_input_current_limit(MAX(charge_ma,
+ CONFIG_CHARGER_INPUT_CURRENT),
+ charge_mv);
+}
+
/* Keyboard scan setting */
struct keyboard_scan_config keyscan_config = {
/* Extra delay when KSO2 is tied to Cr50. */
diff --git a/board/grunt/board.h b/board/grunt/board.h
index 5a23be8c5c..056a5f0b29 100644
--- a/board/grunt/board.h
+++ b/board/grunt/board.h
@@ -28,8 +28,24 @@
#define CONFIG_I2C
#define CONFIG_LPC
+#define CONFIG_BATTERY_CUT_OFF
+#define CONFIG_BATTERY_PRESENT_GPIO GPIO_EC_BATT_PRES_ODL
+#define CONFIG_BATTERY_SMART
+
#define CONFIG_BOARD_VERSION
+#define CONFIG_BC12_DETECT_BQ24392
+#define CONFIG_CHARGER
+#define CONFIG_CHARGER_V2
+#define CONFIG_CHARGE_MANAGER
+#define CONFIG_CHARGER_INPUT_CURRENT 128
+#define CONFIG_CHARGER_ISL9238
+#define CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON 1
+#define CONFIG_CHARGER_SENSE_RESISTOR 10
+#define CONFIG_CHARGER_SENSE_RESISTOR_AC 20
+#define CONFIG_CHARGE_RAMP_HW
+#define CONFIG_USB_CHARGER
+
#define CONFIG_CHIPSET_STONEY
#define CONFIG_CHIPSET_RESET_HOOK
#define CONFIG_EXTPOWER_GPIO
@@ -49,7 +65,57 @@
#define GPIO_VOLUME_DOWN_L GPIO_VOLDN_BTN_ODL
#define GPIO_VOLUME_UP_L GPIO_VOLUP_BTN_ODL
+#define CONFIG_USB_POWER_DELIVERY
+#define CONFIG_CMD_PD_CONTROL
+#define CONFIG_USB_PD_ALT_MODE
+#define CONFIG_USB_PD_ALT_MODE_DFP
+#define CONFIG_USB_PD_COMM_LOCKED
+#define CONFIG_USB_PD_DISCHARGE
+#define CONFIG_USB_PD_DISCHARGE_TCPC
+#define CONFIG_USB_PD_DUAL_ROLE
+#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
+#define CONFIG_USB_PD_LOGGING
+#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0
+#define CONFIG_USB_PD_PORT_COUNT 2
+#define CONFIG_USB_PD_TCPC_BOARD_INIT
+#define CONFIG_USB_PD_TCPC_LOW_POWER
+#define CONFIG_USB_PD_TCPM_ANX74XX
+#define CONFIG_USB_PD_TCPM_MUX
+#define CONFIG_USB_PD_TCPM_PS8751
+#define CONFIG_USB_PD_TCPM_TCPCI
+#define CONFIG_USB_PD_TRY_SRC
+/* TODO(ecgh): Detect VBUS via SWCTL_INT and I2C to SN5S330 */
+#define CONFIG_USB_PD_VBUS_DETECT_GPIO
+/*
+ * TODO(ecgh)
+ * CONFIG_USBC_PPC_SN5S330: Need to resolve
+ * CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT build error
+ */
+#define CONFIG_USBC_SS_MUX
+#define CONFIG_USBC_SS_MUX_DFP_ONLY
+#define CONFIG_USBC_VCONN
+#define CONFIG_USBC_VCONN_SWAP
+
+/* USB Type-A Port BC1.2 support */
+#define CONFIG_USB_PORT_POWER_SMART
+#define CONFIG_USB_PORT_POWER_SMART_CDP_SDP_ONLY
+#define CONFIG_USB_PORT_POWER_SMART_INVERTED
+#define GPIO_USB1_ILIM_SEL GPIO_USB_A0_CHARGE_EN_L
+#define GPIO_USB2_ILIM_SEL GPIO_USB_A1_CHARGE_EN_L
+
+/* TODO(b/69683108): Use correct PD delay values */
+#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */
+#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */
+#define PD_VCONN_SWAP_DELAY 5000 /* us */
+
+/* TODO(b/69683178): Use correct PD power values */
+#define PD_OPERATING_POWER_MW 15000
+#define PD_MAX_POWER_MW 45000
+#define PD_MAX_CURRENT_MA 3000
+#define PD_MAX_VOLTAGE_MV 20000
+
#define I2C_PORT_BATTERY I2C_PORT_POWER
+#define I2C_PORT_CHARGER I2C_PORT_POWER
#define I2C_PORT_POWER NPCX_I2C_PORT0_0
#define I2C_PORT_TCPC0 NPCX_I2C_PORT1_0
#define I2C_PORT_TCPC1 NPCX_I2C_PORT2_0
@@ -64,6 +130,7 @@
#include "registers.h"
enum adc_channel {
+ ADC_VBUS = -1,
ADC_TEMP_SENSOR_CHARGER,
ADC_TEMP_SENSOR_SOC,
ADC_CH_COUNT
@@ -78,6 +145,7 @@ enum power_signal {
};
void board_reset_pd_mcu(void);
+void board_tcpc_init(void);
#endif /* !__ASSEMBLER__ */
diff --git a/board/grunt/ec.tasklist b/board/grunt/ec.tasklist
index 1cc4d81ac5..0ce94f2da3 100644
--- a/board/grunt/ec.tasklist
+++ b/board/grunt/ec.tasklist
@@ -22,9 +22,15 @@
#define CONFIG_TASK_LIST \
TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \
+ TASK_ALWAYS(USB_CHG_P0, usb_charger_task, 0, TASK_STACK_SIZE) \
+ TASK_ALWAYS(USB_CHG_P1, usb_charger_task, 1, TASK_STACK_SIZE) \
+ TASK_ALWAYS(CHARGER, charger_task, NULL, LARGER_TASK_STACK_SIZE) \
TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \
TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \
+ TASK_NOTEST(PDCMD, pd_command_task, NULL, LARGER_TASK_STACK_SIZE) \
TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \
TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \
TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \
- TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE)
+ TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \
+ TASK_ALWAYS(PD_C0, pd_task, NULL, LARGER_TASK_STACK_SIZE) \
+ TASK_ALWAYS(PD_C1, pd_task, NULL, LARGER_TASK_STACK_SIZE)
diff --git a/board/grunt/gpio.inc b/board/grunt/gpio.inc
index 406c350d9b..4fae22910c 100644
--- a/board/grunt/gpio.inc
+++ b/board/grunt/gpio.inc
@@ -8,7 +8,7 @@
/* Declare symbolic names for all the GPIOs that we care about.
* Note: Those with interrupt handlers must be declared first. */
-GPIO_INT(USB_C0_PD_INT_ODL, PIN(6, 1), GPIO_INT_FALLING, tcpc_alert_event)
+GPIO_INT(USB_C0_PD_INT_ODL, PIN(A, 0), GPIO_INT_FALLING, tcpc_alert_event)
GPIO_INT(USB_C1_PD_INT_ODL, PIN(F, 5), GPIO_INT_FALLING, tcpc_alert_event)
GPIO_INT(PCH_SLP_S3_L, PIN(A, 6), GPIO_INT_BOTH, power_signal_interrupt)
GPIO_INT(PCH_SLP_S5_L, PIN(A, 3), GPIO_INT_BOTH, power_signal_interrupt)
@@ -20,6 +20,7 @@ GPIO_INT(AC_PRESENT, PIN(0, 0), GPIO_INT_BOTH | GPIO_HIB_WAKE_HIGH, extpower_in
GPIO_INT(WP_L, PIN(A, 1), GPIO_INT_BOTH, switch_interrupt)
GPIO_INT(VOLDN_BTN_ODL, PIN(7, 0), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt)
GPIO_INT(VOLUP_BTN_ODL, PIN(7, 5), GPIO_INT_BOTH | GPIO_PULL_UP, button_interrupt)
+GPIO_INT(USB_C0_CABLE_DET, PIN(3, 7), GPIO_INT_RISING, anx74xx_cable_det_interrupt)
GPIO(EN_PWR_A, PIN(E, 2), GPIO_OUT_HIGH) /* Enable Power */
GPIO(EN_PP1800_SENSOR, PIN(6, 7), GPIO_OUT_HIGH) /* Enable Power */
@@ -31,10 +32,15 @@ GPIO(PCH_RCIN_L, PIN(0, 2), GPIO_OUT_HIGH) /* Cold Reset to SOC */
GPIO(CCD_MODE_ODL, PIN(E, 3), GPIO_INPUT) /* Case Closed Debug Mode */
GPIO(ENTERING_RW, PIN(E, 1), GPIO_OUT_LOW) /* EC Entering RW */
GPIO(EC_BATT_PRES_ODL, PIN(E, 5), GPIO_INPUT) /* Battery Present */
-GPIO(PCH_SYS_PWROK, PIN(3, 7), GPIO_OUT_LOW) /* Power OK to SOC */
+GPIO(PCH_SYS_PWROK, PIN(D, 6), GPIO_OUT_LOW) /* Power OK to SOC */
GPIO(EC_APU_RST, PIN(E, 4), GPIO_INPUT) /* Reset to SOC */
-GPIO(CPU_PROCHOT, PIN(3, 4), GPIO_INPUT | GPIO_PULL_UP) /* PROCHOT to SOC */
-GPIO(EC_APU_ALERT_L, PIN(4, 0), GPIO_INPUT | GPIO_PULL_UP) /* Alert to SOC */
+GPIO(CPU_PROCHOT, PIN(3, 4), GPIO_INPUT | GPIO_SEL_1P8V) /* PROCHOT to SOC */
+GPIO(APU_ALERT_L, PIN(A, 2), GPIO_INPUT) /* Alert to SOC */
+GPIO(3AXIS_INT_L, PIN(5, 0), GPIO_INPUT | GPIO_SEL_1P8V) /* 3 Axis Accel */
+GPIO(6AXIS_INT_L, PIN(8, 6), GPIO_INPUT | GPIO_SEL_1P8V) /* 6 Axis Accel */
+
+/* We don't have 5V rail control but the BQ24392 driver expects the GPIO */
+UNIMPLEMENTED(EN_PP5000)
/* I2C pins - these will be reconfigured for alternate function below */
GPIO(I2C0_SCL, PIN(B, 5), GPIO_INPUT) /* EC_I2C_POWER_SCL */
@@ -43,33 +49,37 @@ GPIO(I2C1_SCL, PIN(9, 0), GPIO_INPUT) /* EC_I2C_USB_C0_PD_SCL */
GPIO(I2C1_SDA, PIN(8, 7), GPIO_INPUT) /* EC_I2C_USB_C0_PD_SDA */
GPIO(I2C2_SCL, PIN(9, 2), GPIO_INPUT) /* EC_I2C_USB_C1_PD_SCL */
GPIO(I2C2_SDA, PIN(9, 1), GPIO_INPUT) /* EC_I2C_USB_C1_PD_SDA */
-GPIO(I2C3_SCL, PIN(D, 1), GPIO_INPUT) /* APU_SIC */
-GPIO(I2C3_SDA, PIN(D, 0), GPIO_INPUT) /* APU_SID */
-GPIO(I2C7_SCL, PIN(B, 3), GPIO_INPUT) /* EC_I2C_SENSOR_SCL */
-GPIO(I2C7_SDA, PIN(B, 2), GPIO_INPUT) /* EC_I2C_SENSOR_SDA */
+GPIO(I2C3_SCL, PIN(D, 1), GPIO_INPUT | GPIO_SEL_1P8V) /* APU_SIC */
+GPIO(I2C3_SDA, PIN(D, 0), GPIO_INPUT | GPIO_SEL_1P8V) /* APU_SID */
+GPIO(I2C7_SCL, PIN(B, 3), GPIO_INPUT | GPIO_SEL_1P8V) /* EC_I2C_SENSOR_SCL */
+GPIO(I2C7_SDA, PIN(B, 2), GPIO_INPUT | GPIO_SEL_1P8V) /* EC_I2C_SENSOR_SDA */
GPIO(PCH_SCI_ODL, PIN(7, 6), GPIO_ODR_HIGH)
GPIO(PCH_SMI_ODL, PIN(C, 6), GPIO_ODR_HIGH)
GPIO(PCH_SLP_S0_L, PIN(A, 4), GPIO_INPUT)
-GPIO(EN_USB_A0_5V, PIN(A, 0), GPIO_OUT_LOW) /* Enable A0 5V Charging */
+GPIO(EN_USB_A0_5V, PIN(6, 1), GPIO_OUT_LOW) /* Enable A0 5V Charging */
GPIO(EN_USB_A1_5V, PIN(C, 0), GPIO_OUT_LOW) /* Enable A1 5V Charging */
-GPIO(USB_A0_CHARGE_EN_L, PIN(A, 2), GPIO_OUT_HIGH) /* Enable A0 1.5A Charging */
+GPIO(USB_A0_CHARGE_EN_L, PIN(4, 0), GPIO_OUT_HIGH) /* Enable A0 1.5A Charging */
GPIO(USB_A1_CHARGE_EN_L, PIN(D, 4), GPIO_OUT_HIGH) /* Enable A1 1.5A Charging */
GPIO(EN_USB_C0_TCPC_PWR, PIN(6, 0), GPIO_OUT_LOW) /* Enable C0 TCPC Power */
GPIO(USB_C0_OC_L, PIN(7, 3), GPIO_OUT_HIGH) /* C0 Over Current */
GPIO(USB_C1_OC_L, PIN(D, 7), GPIO_OUT_HIGH) /* C1 Over Current */
GPIO(USB_C0_PD_RST_L, PIN(F, 1), GPIO_OUT_HIGH) /* C0 PD Reset */
GPIO(USB_C1_PD_RST_L, PIN(D, 5), GPIO_OUT_HIGH) /* C1 PD Reset */
-GPIO(USB_C0_SWCTL_INT_ODL, PIN(0, 3), GPIO_INPUT) /* C0 Switch Control Interrupt */
-GPIO(USB_C1_SWCTL_INT_ODL, PIN(0, 4), GPIO_INPUT) /* C1 Switch Control Interrupt */
-GPIO(USB_C0_BC12_VBUS_ON_ODL, PIN(8, 2), GPIO_ODR_HIGH) /* C0 BC1.2 Power */
-GPIO(USB_C1_BC12_VBUS_ON_ODL, PIN(B, 1), GPIO_ODR_HIGH) /* C1 BC1.2 Power */
-GPIO(USB_C0_BC12_CHG_MAX, PIN(6, 2), GPIO_INPUT) /* C0 BC1.2 Detect */
-GPIO(USB_C1_BC12_CHG_MAX, PIN(8, 3), GPIO_INPUT) /* C1 BC1.2 Detect */
+GPIO(USB_C0_SWCTL_INT_ODL, PIN(0, 3), GPIO_INPUT) /* C0 Switch Interrupt */
+GPIO(USB_C1_SWCTL_INT_ODL, PIN(0, 4), GPIO_INPUT) /* C1 Switch Interrupt */
+GPIO(USB_C0_BC12_VBUS_ON_L, PIN(8, 2), GPIO_ODR_HIGH) /* C0 BC1.2 Power */
+GPIO(USB_C1_BC12_VBUS_ON_L, PIN(B, 1), GPIO_ODR_HIGH) /* C1 BC1.2 Power */
+GPIO(USB_C0_BC12_CHG_DET, PIN(6, 2), GPIO_INPUT) /* C0 BC1.2 Detect */
+GPIO(USB_C1_BC12_CHG_DET, PIN(8, 3), GPIO_INPUT) /* C1 BC1.2 Detect */
+
+/* TODO(ecgh): CONFIG_USB_CHARGER assumes GPIO_USB_Cx_5V_EN */
+UNIMPLEMENTED(USB_C0_5V_EN)
+UNIMPLEMENTED(USB_C1_5V_EN)
/* Board ID */
-GPIO(BOARD_VERSION1, PIN(9, 6), GPIO_INPUT)
+GPIO(BOARD_VERSION1, PIN(C, 7), GPIO_INPUT)
GPIO(BOARD_VERSION2, PIN(9, 3), GPIO_INPUT)
GPIO(BOARD_VERSION3, PIN(8, 0), GPIO_INPUT)
GPIO(SKU_ID1, PIN(F, 0), GPIO_INPUT)
diff --git a/board/grunt/usb_pd_policy.c b/board/grunt/usb_pd_policy.c
index 64b32ed937..9b9020a280 100644
--- a/board/grunt/usb_pd_policy.c
+++ b/board/grunt/usb_pd_policy.c
@@ -8,6 +8,7 @@
#include "charge_manager.h"
#include "common.h"
#include "console.h"
+#include "driver/tcpm/anx74xx.h"
#include "driver/tcpm/ps8xxx.h"
#include "gpio.h"
#include "hooks.h"
@@ -27,7 +28,7 @@
#define PDO_FIXED_FLAGS (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP |\
PDO_FIXED_COMM_CAP)
-/* TODO: fill in correct source and sink capabilities */
+/* TODO(ecgh): fill in correct source and sink capabilities */
const uint32_t pd_src_pdo[] = {
PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS),
};
@@ -64,19 +65,7 @@ int board_vbus_source_enabled(int port)
static void board_vbus_update_source_current(int port)
{
- enum gpio_signal gpio = port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN;
- int flags = (vbus_rp[port] == TYPEC_RP_1A5 && vbus_en[port]) ?
- (GPIO_INPUT | GPIO_PULL_UP) : (GPIO_OUTPUT | GPIO_PULL_UP);
-
- /*
- * Driving USB_Cx_5V_EN high, actually put a 16.5k resistance
- * (2x 33k in parallel) on the NX5P3290 load switch ILIM pin,
- * setting a minimum OCP current of 3186 mA.
- * Putting an internal pull-up on USB_Cx_5V_EN, effectively put a 33k
- * resistor on ILIM, setting a minimum OCP current of 1505 mA.
- */
- gpio_set_level(gpio, vbus_en[port]);
- gpio_set_flags(gpio, flags);
+ /* TODO(ecgh): how to set VBUS on/off and 1.5/3.0 A? */
}
void typec_set_source_current_limit(int port, int rp)
@@ -89,17 +78,14 @@ void typec_set_source_current_limit(int port, int rp)
int pd_set_power_supply_ready(int port)
{
- enum gpio_signal gpio = port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN;
- enum gpio_signal gpio_AC = port ?
- GPIO_USB_C1_20V_EN : GPIO_USB_C0_20V_EN;
- /* Ensure we're not charging from this port */
- gpio_set_level(gpio, 0);
- gpio_set_level(gpio_AC, 0);
+ /* Disable charging */
+ /* TODO(ecgh): how to disable charging? */
/* Ensure we advertise the proper available current quota */
charge_manager_source_port(port, 1);
pd_set_vbus_discharge(port, 0);
+
/* Provide VBUS */
vbus_en[port] = 1;
board_vbus_update_source_current(port);
@@ -148,8 +134,15 @@ int pd_check_power_swap(int port)
int pd_check_data_swap(int port, int data_role)
{
- /* Allow data swap if we are a UFP, otherwise don't allow */
- return (data_role == PD_ROLE_UFP) ? 1 : 0;
+ /*
+ * Allow data swap if we are a UFP, otherwise don't allow.
+ *
+ * When we are still in the Read-Only firmware, avoid swapping roles
+ * so we don't jump in RW as a SNK/DFP and potentially confuse the
+ * power supply by sending a soft-reset with wrong data role.
+ */
+ return (data_role == PD_ROLE_UFP) &&
+ (system_get_image_copy() != SYSTEM_IMAGE_RO) ? 1 : 0;
}
int pd_check_vconn_swap(int port)
@@ -187,7 +180,9 @@ void pd_check_pr_role(int port, int pr_role, int flags)
void pd_check_dr_role(int port, int dr_role, int flags)
{
/* If UFP, try to switch to DFP */
- if ((flags & PD_FLAGS_PARTNER_DR_DATA) && dr_role == PD_ROLE_UFP)
+ if ((flags & PD_FLAGS_PARTNER_DR_DATA) &&
+ dr_role == PD_ROLE_UFP &&
+ system_get_image_copy() != SYSTEM_IMAGE_RO)
pd_request_data_swap(port);
}
/* ----------------- Vendor Defined Messages ------------------ */
@@ -227,7 +222,6 @@ int pd_custom_vdm(int port, int cnt, uint32_t *payload,
is_rw ?
SYSTEM_IMAGE_RW :
SYSTEM_IMAGE_RO);
-
/*
* Send update host event unless our RW hash is
* already known to be the latest update RW.
diff --git a/driver/bc12/bq24392.c b/driver/bc12/bq24392.c
index 23e9e99eb0..8f97ad704f 100644
--- a/driver/bc12/bq24392.c
+++ b/driver/bc12/bq24392.c
@@ -23,6 +23,7 @@
#include "tcpm.h"
#include "timer.h"
#include "usb_charge.h"
+#include "usb_pd.h"
#include "util.h"
struct bq24392_pins {