summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2016-10-28 17:46:22 +0200
committerchrome-bot <chrome-bot@chromium.org>2016-11-17 04:35:32 -0800
commite9584bc6cea8677979ffe2929e75f2ef037ec764 (patch)
tree2a95594252132a672b7b680d6fbde46c5416b86d
parent64f1823a742e4cd39e56f0621d86bae41c709210 (diff)
downloadchrome-ec-e9584bc6cea8677979ffe2929e75f2ef037ec764.tar.gz
reef/pyro/eve/snappy: source 3A on one port
Add a new source policy to provide 3A if there is only one port used as a source. Also ensure that the load switch on VBUS when sourcing power is properly configured to limit the current to 1.5A or 3.0A depending on the case. Signed-off-by: Vincent Palatin <vpalatin@chromium.org> BRANCH=none BUG=chrome-os-partner:56110 TEST=manual: connect the laptop to a type-C sink with Twinkie in between, without anything else connected on the laptop, see 3A flowing when measuring with Twinkie ('tw vbus'), plug a dangling C-to-A receptacle dongle on the other port and see 1.5A flowing through Twinkie. Force the input current limit on the sink to 3.0A and see the laptop cutting VBUS. Change-Id: Ic94ba186fc0648e770c8d13be0f96b23e968f855 Reviewed-on: https://chromium-review.googlesource.com/403851 Commit-Ready: Vincent Palatin <vpalatin@chromium.org> Tested-by: Vincent Palatin <vpalatin@chromium.org> Reviewed-by: Shawn N <shawnn@chromium.org>
-rw-r--r--board/eve/board.c3
-rw-r--r--board/eve/board.h1
-rw-r--r--board/eve/gpio.inc4
-rw-r--r--board/eve/usb_pd_policy.c53
-rw-r--r--board/pyro/board.c3
-rw-r--r--board/pyro/board.h1
-rw-r--r--board/pyro/gpio.inc4
-rw-r--r--board/pyro/usb_pd_policy.c53
-rw-r--r--board/reef/board.c3
-rw-r--r--board/reef/board.h1
-rw-r--r--board/reef/gpio.inc4
-rw-r--r--board/reef/usb_pd_policy.c53
-rw-r--r--board/snappy/board.c3
-rw-r--r--board/snappy/board.h1
-rw-r--r--board/snappy/gpio.inc4
-rw-r--r--board/snappy/usb_pd_policy.c53
16 files changed, 196 insertions, 48 deletions
diff --git a/board/eve/board.c b/board/eve/board.c
index d3edc9c072..7479b558e2 100644
--- a/board/eve/board.c
+++ b/board/eve/board.c
@@ -413,8 +413,7 @@ int board_set_active_charge_port(int charge_port)
case 0:
case 1:
/* Don't charge from a source port */
- if (gpio_get_level(charge_port == 0 ?
- GPIO_USB_C0_5V_EN : GPIO_USB_C1_5V_EN))
+ if (board_vbus_source_enabled(charge_port))
return -1;
bd9995x_port = bd9995x_pd_port_to_chg_port(charge_port);
diff --git a/board/eve/board.h b/board/eve/board.h
index 05a451c9a8..2212fecb85 100644
--- a/board/eve/board.h
+++ b/board/eve/board.h
@@ -122,6 +122,7 @@
#define CONFIG_USB_PD_DUAL_ROLE
#define CONFIG_USB_PD_LOGGING
#define CONFIG_USB_PD_LOG_SIZE 512
+#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0
#define CONFIG_USB_PD_PORT_COUNT 2
#define CONFIG_USB_PD_QUIRK_SLOW_CC_STATUS
#define CONFIG_USB_PD_VBUS_DETECT_CHARGER
diff --git a/board/eve/gpio.inc b/board/eve/gpio.inc
index 7d88a44998..172900781b 100644
--- a/board/eve/gpio.inc
+++ b/board/eve/gpio.inc
@@ -72,8 +72,8 @@ GPIO(TOUCHPAD_WAKE_L, PIN(7, 1), GPIO_INPUT | GPIO_SEL_1P8V) /* INT# from Trac
GPIO(DSP_WAKE_L, PIN(C, 6), GPIO_INPUT | GPIO_SEL_1P8V) /* INT# from DSP Mic */
/* 5V enables: INPUT=1.5A, OUT_LOW=OFF, OUT_HIGH=3A */
-GPIO(USB_C0_5V_EN, PIN(4, 2), GPIO_OUT_LOW) /* C0 5V Enable */
-GPIO(USB_C1_5V_EN, PIN(B, 1), GPIO_OUT_LOW) /* C1 5V Enable */
+GPIO(USB_C0_5V_EN, PIN(4, 2), GPIO_OUT_LOW | GPIO_PULL_UP) /* C0 5V Enable */
+GPIO(USB_C1_5V_EN, PIN(B, 1), GPIO_OUT_LOW | GPIO_PULL_UP) /* C1 5V Enable */
GPIO(USB_C0_CABLE_DET, PIN(D, 2), GPIO_INPUT) /* C0 Cable Detect */
GPIO(USB_C1_CABLE_DET, PIN(D, 3), GPIO_INPUT) /* C1 Cable Detect */
GPIO(USB_C0_PD_RST_L, PIN(0, 3), GPIO_OUT_LOW) /* C0 PD Reset */
diff --git a/board/eve/usb_pd_policy.c b/board/eve/usb_pd_policy.c
index 3311f13b73..dbc510caf1 100644
--- a/board/eve/usb_pd_policy.c
+++ b/board/eve/usb_pd_policy.c
@@ -21,6 +21,7 @@
#include "util.h"
#include "usb_mux.h"
#include "usb_pd.h"
+#include "usb_pd_tcpm.h"
#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
@@ -33,6 +34,10 @@ const uint32_t pd_src_pdo[] = {
PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS),
};
const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo);
+const uint32_t pd_src_pdo_max[] = {
+ PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS),
+};
+const int pd_src_pdo_max_cnt = ARRAY_SIZE(pd_src_pdo_max);
const uint32_t pd_snk_pdo[] = {
PDO_FIXED(5000, 500, PDO_FIXED_FLAGS),
@@ -51,9 +56,37 @@ void pd_transition_voltage(int idx)
/* No-operation: we are always 5V */
}
+static uint8_t vbus_en[CONFIG_USB_PD_PORT_COUNT];
+static uint8_t vbus_rp[CONFIG_USB_PD_PORT_COUNT] = {TYPEC_RP_1A5, TYPEC_RP_1A5};
+
int board_vbus_source_enabled(int port)
{
- return gpio_get_level(port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN);
+ return vbus_en[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);
+}
+
+void typec_set_source_current_limit(int port, int rp)
+{
+ vbus_rp[port] = rp;
+
+ /* change the GPIO driving the load switch if needed */
+ board_vbus_update_source_current(port);
}
int pd_set_power_supply_ready(int port)
@@ -61,11 +94,13 @@ int pd_set_power_supply_ready(int port)
/* Ensure we're not charging from this port */
bd9995x_select_input_port(bd9995x_pd_port_to_chg_port(port), 0);
- /* Provide VBUS */
- gpio_set_level(port ? GPIO_USB_C1_5V_EN :
- GPIO_USB_C0_5V_EN, 1);
+ /* 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);
/* notify host of power info change */
pd_send_host_event(PD_EVENT_POWER_CHANGE);
@@ -75,19 +110,21 @@ int pd_set_power_supply_ready(int port)
void pd_power_supply_reset(int port)
{
- enum gpio_signal gpio;
int prev_en;
- gpio = port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN;
- prev_en = gpio_get_level(gpio);
+ prev_en = vbus_en[port];
/* Disable VBUS */
- gpio_set_level(gpio, 0);
+ vbus_en[port] = 0;
+ board_vbus_update_source_current(port);
/* Enable discharge if we were previously sourcing 5V */
if (prev_en)
pd_set_vbus_discharge(port, 1);
+ /* Give back the current quota we are no longer using */
+ charge_manager_source_port(port, 0);
+
/* notify host of power info change */
pd_send_host_event(PD_EVENT_POWER_CHANGE);
}
diff --git a/board/pyro/board.c b/board/pyro/board.c
index ebdb6d6198..7af0038af4 100644
--- a/board/pyro/board.c
+++ b/board/pyro/board.c
@@ -516,8 +516,7 @@ int board_set_active_charge_port(int charge_port)
case 0:
case 1:
/* Don't charge from a source port */
- if (gpio_get_level(charge_port == 0 ?
- GPIO_USB_C0_5V_EN : GPIO_USB_C1_5V_EN))
+ if (board_vbus_source_enabled(charge_port))
return -1;
bd9995x_port = bd9995x_pd_port_to_chg_port(charge_port);
diff --git a/board/pyro/board.h b/board/pyro/board.h
index 40533f0e05..e22ebb95a8 100644
--- a/board/pyro/board.h
+++ b/board/pyro/board.h
@@ -85,6 +85,7 @@
#define CONFIG_USB_PD_DISCHARGE_TCPC
#define CONFIG_USB_PD_LOGGING
#define CONFIG_USB_PD_LOG_SIZE 512
+#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0
#define CONFIG_USB_PD_PORT_COUNT 2
#define CONFIG_USB_PD_QUIRK_SLOW_CC_STATUS
#define CONFIG_USB_PD_VBUS_DETECT_CHARGER
diff --git a/board/pyro/gpio.inc b/board/pyro/gpio.inc
index fea1b8e81a..fca8bd3a0b 100644
--- a/board/pyro/gpio.inc
+++ b/board/pyro/gpio.inc
@@ -130,8 +130,8 @@ GPIO(USB_C1_PD_RST_ODL, PIN(7, 4), GPIO_ODR_LOW)
* Configure as input to enable @ 1.5A, output-low to turn off, or output-high
* to enable @ 3A.
*/
-GPIO(USB_C0_5V_EN, PIN(D, 3), GPIO_OUT_LOW) /* EN_USB_C0_5V_OUT, Enable C0 */
-GPIO(USB_C1_5V_EN, PIN(D, 2), GPIO_OUT_LOW) /* EN_USB_C1_5V_OUT, Enable C1 */
+GPIO(USB_C0_5V_EN, PIN(D, 3), GPIO_OUT_LOW | GPIO_PULL_UP) /* EN_USB_C0_5V_OUT, Enable C0 */
+GPIO(USB_C1_5V_EN, PIN(D, 2), GPIO_OUT_LOW | GPIO_PULL_UP) /* EN_USB_C1_5V_OUT, Enable C1 */
/* Clear for non-HDI breakout, must be pulled high */
GPIO(NC1, PIN(0, 0), GPIO_INPUT | GPIO_PULL_UP | GPIO_SEL_1P8V)
diff --git a/board/pyro/usb_pd_policy.c b/board/pyro/usb_pd_policy.c
index cf83ea05bc..3a77eb6cad 100644
--- a/board/pyro/usb_pd_policy.c
+++ b/board/pyro/usb_pd_policy.c
@@ -21,6 +21,7 @@
#include "util.h"
#include "usb_mux.h"
#include "usb_pd.h"
+#include "usb_pd_tcpm.h"
#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
@@ -33,6 +34,10 @@ const uint32_t pd_src_pdo[] = {
PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS),
};
const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo);
+const uint32_t pd_src_pdo_max[] = {
+ PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS),
+};
+const int pd_src_pdo_max_cnt = ARRAY_SIZE(pd_src_pdo_max);
const uint32_t pd_snk_pdo[] = {
PDO_FIXED(5000, 500, PDO_FIXED_FLAGS),
@@ -51,9 +56,37 @@ void pd_transition_voltage(int idx)
/* No-operation: we are always 5V */
}
+static uint8_t vbus_en[CONFIG_USB_PD_PORT_COUNT];
+static uint8_t vbus_rp[CONFIG_USB_PD_PORT_COUNT] = {TYPEC_RP_1A5, TYPEC_RP_1A5};
+
int board_vbus_source_enabled(int port)
{
- return gpio_get_level(port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN);
+ return vbus_en[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);
+}
+
+void typec_set_source_current_limit(int port, int rp)
+{
+ vbus_rp[port] = rp;
+
+ /* change the GPIO driving the load switch if needed */
+ board_vbus_update_source_current(port);
}
int pd_set_power_supply_ready(int port)
@@ -61,11 +94,13 @@ int pd_set_power_supply_ready(int port)
/* Ensure we're not charging from this port */
bd9995x_select_input_port(bd9995x_pd_port_to_chg_port(port), 0);
- /* Provide VBUS */
- gpio_set_level(port ? GPIO_USB_C1_5V_EN :
- GPIO_USB_C0_5V_EN, 1);
+ /* 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);
/* notify host of power info change */
pd_send_host_event(PD_EVENT_POWER_CHANGE);
@@ -75,19 +110,21 @@ int pd_set_power_supply_ready(int port)
void pd_power_supply_reset(int port)
{
- enum gpio_signal gpio;
int prev_en;
- gpio = port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN;
- prev_en = gpio_get_level(gpio);
+ prev_en = vbus_en[port];
/* Disable VBUS */
- gpio_set_level(gpio, 0);
+ vbus_en[port] = 0;
+ board_vbus_update_source_current(port);
/* Enable discharge if we were previously sourcing 5V */
if (prev_en)
pd_set_vbus_discharge(port, 1);
+ /* Give back the current quota we are no longer using */
+ charge_manager_source_port(port, 0);
+
/* notify host of power info change */
pd_send_host_event(PD_EVENT_POWER_CHANGE);
}
diff --git a/board/reef/board.c b/board/reef/board.c
index 997664d3a1..655a319506 100644
--- a/board/reef/board.c
+++ b/board/reef/board.c
@@ -547,8 +547,7 @@ int board_set_active_charge_port(int charge_port)
case 0:
case 1:
/* Don't charge from a source port */
- if (gpio_get_level(charge_port == 0 ?
- GPIO_USB_C0_5V_EN : GPIO_USB_C1_5V_EN))
+ if (board_vbus_source_enabled(charge_port))
return -1;
bd9995x_port = bd9995x_pd_port_to_chg_port(charge_port);
diff --git a/board/reef/board.h b/board/reef/board.h
index fae92a26ad..d2c6166ee9 100644
--- a/board/reef/board.h
+++ b/board/reef/board.h
@@ -87,6 +87,7 @@
#define CONFIG_USB_PD_DISCHARGE_TCPC
#define CONFIG_USB_PD_LOGGING
#define CONFIG_USB_PD_LOG_SIZE 512
+#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0
#define CONFIG_USB_PD_PORT_COUNT 2
#define CONFIG_USB_PD_QUIRK_SLOW_CC_STATUS
#define CONFIG_USB_PD_VBUS_DETECT_CHARGER
diff --git a/board/reef/gpio.inc b/board/reef/gpio.inc
index 2a7f7442f0..8a883251fc 100644
--- a/board/reef/gpio.inc
+++ b/board/reef/gpio.inc
@@ -126,8 +126,8 @@ GPIO(USB_C1_PD_RST_ODL, PIN(7, 4), GPIO_ODR_LOW)
* Configure as input to enable @ 1.5A, output-low to turn off, or output-high
* to enable @ 3A.
*/
-GPIO(USB_C0_5V_EN, PIN(D, 3), GPIO_OUT_LOW) /* EN_USB_C0_5V_OUT, Enable C0 */
-GPIO(USB_C1_5V_EN, PIN(D, 2), GPIO_OUT_LOW) /* EN_USB_C1_5V_OUT, Enable C1 */
+GPIO(USB_C0_5V_EN, PIN(D, 3), GPIO_OUT_LOW | GPIO_PULL_UP) /* EN_USB_C0_5V_OUT, Enable C0 */
+GPIO(USB_C1_5V_EN, PIN(D, 2), GPIO_OUT_LOW | GPIO_PULL_UP) /* EN_USB_C1_5V_OUT, Enable C1 */
/* Clear for non-HDI breakout, must be pulled high */
GPIO(NC1, PIN(0, 0), GPIO_INPUT | GPIO_PULL_UP | GPIO_SEL_1P8V)
diff --git a/board/reef/usb_pd_policy.c b/board/reef/usb_pd_policy.c
index 693bd6e2e4..bc530687bd 100644
--- a/board/reef/usb_pd_policy.c
+++ b/board/reef/usb_pd_policy.c
@@ -21,6 +21,7 @@
#include "util.h"
#include "usb_mux.h"
#include "usb_pd.h"
+#include "usb_pd_tcpm.h"
#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
@@ -33,6 +34,10 @@ const uint32_t pd_src_pdo[] = {
PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS),
};
const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo);
+const uint32_t pd_src_pdo_max[] = {
+ PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS),
+};
+const int pd_src_pdo_max_cnt = ARRAY_SIZE(pd_src_pdo_max);
const uint32_t pd_snk_pdo[] = {
PDO_FIXED(5000, 500, PDO_FIXED_FLAGS),
@@ -51,9 +56,37 @@ void pd_transition_voltage(int idx)
/* No-operation: we are always 5V */
}
+static uint8_t vbus_en[CONFIG_USB_PD_PORT_COUNT];
+static uint8_t vbus_rp[CONFIG_USB_PD_PORT_COUNT] = {TYPEC_RP_1A5, TYPEC_RP_1A5};
+
int board_vbus_source_enabled(int port)
{
- return gpio_get_level(port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN);
+ return vbus_en[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);
+}
+
+void typec_set_source_current_limit(int port, int rp)
+{
+ vbus_rp[port] = rp;
+
+ /* change the GPIO driving the load switch if needed */
+ board_vbus_update_source_current(port);
}
int pd_set_power_supply_ready(int port)
@@ -61,11 +94,13 @@ int pd_set_power_supply_ready(int port)
/* Ensure we're not charging from this port */
bd9995x_select_input_port(bd9995x_pd_port_to_chg_port(port), 0);
- /* Provide VBUS */
- gpio_set_level(port ? GPIO_USB_C1_5V_EN :
- GPIO_USB_C0_5V_EN, 1);
+ /* 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);
/* notify host of power info change */
pd_send_host_event(PD_EVENT_POWER_CHANGE);
@@ -75,19 +110,21 @@ int pd_set_power_supply_ready(int port)
void pd_power_supply_reset(int port)
{
- enum gpio_signal gpio;
int prev_en;
- gpio = port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN;
- prev_en = gpio_get_level(gpio);
+ prev_en = vbus_en[port];
/* Disable VBUS */
- gpio_set_level(gpio, 0);
+ vbus_en[port] = 0;
+ board_vbus_update_source_current(port);
/* Enable discharge if we were previously sourcing 5V */
if (prev_en)
pd_set_vbus_discharge(port, 1);
+ /* Give back the current quota we are no longer using */
+ charge_manager_source_port(port, 0);
+
/* notify host of power info change */
pd_send_host_event(PD_EVENT_POWER_CHANGE);
}
diff --git a/board/snappy/board.c b/board/snappy/board.c
index 58c83929a3..6510f2bdb4 100644
--- a/board/snappy/board.c
+++ b/board/snappy/board.c
@@ -515,8 +515,7 @@ int board_set_active_charge_port(int charge_port)
case 0:
case 1:
/* Don't charge from a source port */
- if (gpio_get_level(charge_port == 0 ?
- GPIO_USB_C0_5V_EN : GPIO_USB_C1_5V_EN))
+ if (board_vbus_source_enabled(charge_port))
return -1;
bd9995x_port = bd9995x_pd_port_to_chg_port(charge_port);
diff --git a/board/snappy/board.h b/board/snappy/board.h
index f7461676e7..b6cdfd8a62 100644
--- a/board/snappy/board.h
+++ b/board/snappy/board.h
@@ -84,6 +84,7 @@
#define CONFIG_USB_PD_DISCHARGE_TCPC
#define CONFIG_USB_PD_LOGGING
#define CONFIG_USB_PD_LOG_SIZE 512
+#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0
#define CONFIG_USB_PD_PORT_COUNT 2
#define CONFIG_USB_PD_QUIRK_SLOW_CC_STATUS
#define CONFIG_USB_PD_VBUS_DETECT_CHARGER
diff --git a/board/snappy/gpio.inc b/board/snappy/gpio.inc
index 5794f6f9fd..9cd800c5d0 100644
--- a/board/snappy/gpio.inc
+++ b/board/snappy/gpio.inc
@@ -131,8 +131,8 @@ GPIO(USB_C1_PD_RST_ODL, PIN(7, 4), GPIO_ODR_LOW)
* Configure as input to enable @ 1.5A, output-low to turn off, or output-high
* to enable @ 3A.
*/
-GPIO(USB_C0_5V_EN, PIN(D, 3), GPIO_OUT_LOW) /* EN_USB_C0_5V_OUT, Enable C0 */
-GPIO(USB_C1_5V_EN, PIN(D, 2), GPIO_OUT_LOW) /* EN_USB_C1_5V_OUT, Enable C1 */
+GPIO(USB_C0_5V_EN, PIN(D, 3), GPIO_OUT_LOW | GPIO_PULL_UP) /* EN_USB_C0_5V_OUT, Enable C0 */
+GPIO(USB_C1_5V_EN, PIN(D, 2), GPIO_OUT_LOW | GPIO_PULL_UP) /* EN_USB_C1_5V_OUT, Enable C1 */
/* Clear for non-HDI breakout, must be pulled high */
GPIO(NC1, PIN(0, 0), GPIO_INPUT | GPIO_PULL_UP | GPIO_SEL_1P8V)
diff --git a/board/snappy/usb_pd_policy.c b/board/snappy/usb_pd_policy.c
index cf83ea05bc..3a77eb6cad 100644
--- a/board/snappy/usb_pd_policy.c
+++ b/board/snappy/usb_pd_policy.c
@@ -21,6 +21,7 @@
#include "util.h"
#include "usb_mux.h"
#include "usb_pd.h"
+#include "usb_pd_tcpm.h"
#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
@@ -33,6 +34,10 @@ const uint32_t pd_src_pdo[] = {
PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS),
};
const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo);
+const uint32_t pd_src_pdo_max[] = {
+ PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS),
+};
+const int pd_src_pdo_max_cnt = ARRAY_SIZE(pd_src_pdo_max);
const uint32_t pd_snk_pdo[] = {
PDO_FIXED(5000, 500, PDO_FIXED_FLAGS),
@@ -51,9 +56,37 @@ void pd_transition_voltage(int idx)
/* No-operation: we are always 5V */
}
+static uint8_t vbus_en[CONFIG_USB_PD_PORT_COUNT];
+static uint8_t vbus_rp[CONFIG_USB_PD_PORT_COUNT] = {TYPEC_RP_1A5, TYPEC_RP_1A5};
+
int board_vbus_source_enabled(int port)
{
- return gpio_get_level(port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN);
+ return vbus_en[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);
+}
+
+void typec_set_source_current_limit(int port, int rp)
+{
+ vbus_rp[port] = rp;
+
+ /* change the GPIO driving the load switch if needed */
+ board_vbus_update_source_current(port);
}
int pd_set_power_supply_ready(int port)
@@ -61,11 +94,13 @@ int pd_set_power_supply_ready(int port)
/* Ensure we're not charging from this port */
bd9995x_select_input_port(bd9995x_pd_port_to_chg_port(port), 0);
- /* Provide VBUS */
- gpio_set_level(port ? GPIO_USB_C1_5V_EN :
- GPIO_USB_C0_5V_EN, 1);
+ /* 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);
/* notify host of power info change */
pd_send_host_event(PD_EVENT_POWER_CHANGE);
@@ -75,19 +110,21 @@ int pd_set_power_supply_ready(int port)
void pd_power_supply_reset(int port)
{
- enum gpio_signal gpio;
int prev_en;
- gpio = port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN;
- prev_en = gpio_get_level(gpio);
+ prev_en = vbus_en[port];
/* Disable VBUS */
- gpio_set_level(gpio, 0);
+ vbus_en[port] = 0;
+ board_vbus_update_source_current(port);
/* Enable discharge if we were previously sourcing 5V */
if (prev_en)
pd_set_vbus_discharge(port, 1);
+ /* Give back the current quota we are no longer using */
+ charge_manager_source_port(port, 0);
+
/* notify host of power info change */
pd_send_host_event(PD_EVENT_POWER_CHANGE);
}