summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2020-08-10 15:52:38 +0200
committerBrian Nemec <bnemec@chromium.org>2020-08-19 00:13:20 +0000
commitd0df4e7e32fb26e77577e7811aca4ae254bb889f (patch)
tree332ccd4274ca3b93e3beb9d13234ced7d4001020
parentb184c26e2c2c9b564b04ca477adf18735b6ab1d8 (diff)
downloadchrome-ec-d0df4e7e32fb26e77577e7811aca4ae254bb889f.tar.gz
servo_v4: optimize USB PD TX switching
Optimize the duration when switching the USB PD path to TX, in order to meet the PD spec tStartDive timing between when we start driving the line and the start of the preamble waveform. Try to decrease the number of operations on the GPIO registers which might be clocked slowly in order to achieve this, this includes abandoning the high level GPIO functions and writing directly the useful GPIO registers and knowing in advance between which modes we are switching. A few constant values in the GPIO registers for the TX path are now written in the pd_tx_init function. The current version uses the regular GPIO functions *but* it will glitch these GPIOs, we might want to switch to a lower level implementation and avoid the glitch. Signed-off-by: Vincent Palatin <vpalatin@chromium.org> BUG=b:155202697 BRANCH=none TEST=make BOARD=servo_v4p1 TEST=probe TX_DATA on the scope and measure the duration before the preamble Change-Id: I84c8321ed9be045087e228a74f6e0ddb3f677d76 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2346804 Reviewed-by: Nitin Kolluru <nkolluru@google.com> Reviewed-by: Wai-Hong Tam <waihong@google.com> Tested-by: Nitin Kolluru <nkolluru@google.com> (cherry picked from commit ca827c348942c8bb9a4f71dbf4e593d6d46510dc) Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2363290 Reviewed-by: Vincent Palatin <vpalatin@chromium.org> Reviewed-by: Brian Nemec <bnemec@chromium.org> Tested-by: Brian Nemec <bnemec@chromium.org> Auto-Submit: Brian Nemec <bnemec@chromium.org> Commit-Queue: Brian Nemec <bnemec@chromium.org>
-rw-r--r--board/servo_v4/usb_pd_config.h99
-rw-r--r--board/servo_v4p1/usb_pd_config.h99
2 files changed, 88 insertions, 110 deletions
diff --git a/board/servo_v4/usb_pd_config.h b/board/servo_v4/usb_pd_config.h
index 9d0a79cf2d..b865057618 100644
--- a/board/servo_v4/usb_pd_config.h
+++ b/board/servo_v4/usb_pd_config.h
@@ -146,69 +146,40 @@ static inline void pd_tx_spi_reset(int port)
}
}
+static const uint8_t tx_gpio[2 /* port */][2 /* polarity */] = {
+ { GPIO_USB_CHG_CC1_TX_DATA, GPIO_USB_CHG_CC2_TX_DATA },
+ { GPIO_USB_DUT_CC1_TX_DATA, GPIO_USB_DUT_CC2_TX_DATA },
+};
+static const uint8_t ref_gpio[2 /* port */][2 /* polarity */] = {
+ { GPIO_USB_CHG_CC1_PD, GPIO_USB_CHG_CC2_PD },
+ { GPIO_USB_DUT_CC1_PD, GPIO_USB_DUT_CC2_PD },
+};
+
/* Drive the CC line from the TX block */
static inline void pd_tx_enable(int port, int polarity)
{
- if (port == 0) {
- /* put SPI function on TX pin */
- if (polarity) {
- const struct gpio_info *g = gpio_list +
- GPIO_USB_CHG_CC2_TX_DATA;
- gpio_set_alternate_function(g->port, g->mask, 0);
-
- /* set the low level reference */
- gpio_set_flags(GPIO_USB_CHG_CC2_PD, GPIO_OUT_LOW);
- } else {
- const struct gpio_info *g = gpio_list +
- GPIO_USB_CHG_CC1_TX_DATA;
- gpio_set_alternate_function(g->port, g->mask, 0);
-
- /* set the low level reference */
- gpio_set_flags(GPIO_USB_CHG_CC1_PD, GPIO_OUT_LOW);
- }
- } else {
- /* put SPI function on TX pin */
- /* MCU ADC pin output low */
- if (polarity) {
- /* USB_DUT_CC2_TX_DATA: PC2 is SPI2 MISO */
- const struct gpio_info *g = gpio_list +
- GPIO_USB_DUT_CC2_TX_DATA;
- gpio_set_alternate_function(g->port, g->mask, 1);
-
- /* set the low level reference */
- gpio_set_flags(GPIO_USB_DUT_CC2_PD, GPIO_OUT_LOW);
- } else {
- /* USB_DUT_CC1_TX_DATA: PB14 is SPI2 MISO */
- const struct gpio_info *g = gpio_list +
- GPIO_USB_DUT_CC1_TX_DATA;
- gpio_set_alternate_function(g->port, g->mask, 0);
-
- /* set the low level reference */
- gpio_set_flags(GPIO_USB_DUT_CC1_PD, GPIO_OUT_LOW);
- }
- }
+#ifndef VIF_BUILD /* genvif doesn't like tricks with GPIO macros */
+ const struct gpio_info *tx = gpio_list + tx_gpio[port][polarity];
+ const struct gpio_info *ref = gpio_list + ref_gpio[port][polarity];
+
+ /* use directly GPIO registers, latency before the PD preamble is key */
+
+ /* switch the TX pin Mode from Input (00) to Alternate (10) for SPI */
+ STM32_GPIO_MODER(tx->port) |= 2 << ((31 - __builtin_clz(tx->mask)) * 2);
+ /* switch the ref pin Mode from analog (11) to Out (01) for low level */
+ STM32_GPIO_MODER(ref->port) &=
+ ~(2 << ((31 - __builtin_clz(ref->mask)) * 2));
+#endif /* !VIF_BUILD */
}
/* Put the TX driver in Hi-Z state */
static inline void pd_tx_disable(int port, int polarity)
{
- if (port == 0) {
- if (polarity) {
- gpio_set_flags(GPIO_USB_CHG_CC2_TX_DATA, GPIO_INPUT);
- gpio_set_flags(GPIO_USB_CHG_CC2_PD, GPIO_ANALOG);
- } else {
- gpio_set_flags(GPIO_USB_CHG_CC1_TX_DATA, GPIO_INPUT);
- gpio_set_flags(GPIO_USB_CHG_CC1_PD, GPIO_ANALOG);
- }
- } else {
- if (polarity) {
- gpio_set_flags(GPIO_USB_DUT_CC2_TX_DATA, GPIO_INPUT);
- gpio_set_flags(GPIO_USB_DUT_CC2_PD, GPIO_ANALOG);
- } else {
- gpio_set_flags(GPIO_USB_DUT_CC1_TX_DATA, GPIO_INPUT);
- gpio_set_flags(GPIO_USB_DUT_CC1_PD, GPIO_ANALOG);
- }
- }
+ const struct gpio_info *tx = gpio_list + tx_gpio[port][polarity];
+ const struct gpio_info *ref = gpio_list + ref_gpio[port][polarity];
+
+ gpio_set_flags_by_mask(tx->port, tx->mask, GPIO_INPUT);
+ gpio_set_flags_by_mask(ref->port, ref->mask, GPIO_ANALOG);
}
/* we know the plug polarity, do the right configuration */
@@ -235,7 +206,25 @@ static inline void pd_select_polarity(int port, int polarity)
/* Initialize pins used for TX and put them in Hi-Z */
static inline void pd_tx_init(void)
{
+ const struct gpio_info *c2 = gpio_list + GPIO_USB_CHG_CC2_TX_DATA;
+ const struct gpio_info *c1 = gpio_list + GPIO_USB_CHG_CC1_TX_DATA;
+ const struct gpio_info *d2 = gpio_list + GPIO_USB_DUT_CC2_TX_DATA;
+ const struct gpio_info *d1 = gpio_list + GPIO_USB_DUT_CC1_TX_DATA;
+
gpio_config_module(MODULE_USB_PD, 1);
+ /* Select the proper alternate SPI function on TX_DATA pins */
+ /* USB_CHG_CC2_TX_DATA: PA6 is SPI1 MISO (AF0) */
+ gpio_set_alternate_function(c2->port, c2->mask, 0);
+ gpio_set_flags_by_mask(c2->port, c2->mask, GPIO_INPUT);
+ /* USB_CHG_CC1_TX_DATA: PB4 is SPI1 MISO (AF0) */
+ gpio_set_alternate_function(c1->port, c1->mask, 0);
+ gpio_set_flags_by_mask(c1->port, c1->mask, GPIO_INPUT);
+ /* USB_DUT_CC2_TX_DATA: PC2 is SPI2 MISO (AF1) */
+ gpio_set_alternate_function(d2->port, d2->mask, 1);
+ gpio_set_flags_by_mask(d2->port, d2->mask, GPIO_INPUT);
+ /* USB_DUT_CC1_TX_DATA: PB14 is SPI2 MISO (AF0) */
+ gpio_set_alternate_function(d1->port, d1->mask, 0);
+ gpio_set_flags_by_mask(d1->port, d1->mask, GPIO_INPUT);
}
static inline void pd_set_host_mode(int port, int enable)
diff --git a/board/servo_v4p1/usb_pd_config.h b/board/servo_v4p1/usb_pd_config.h
index 4f33e83e0e..7946ea5a6e 100644
--- a/board/servo_v4p1/usb_pd_config.h
+++ b/board/servo_v4p1/usb_pd_config.h
@@ -149,69 +149,40 @@ static inline void pd_tx_spi_reset(int port)
}
}
+static const uint8_t tx_gpio[2 /* port */][2 /* polarity */] = {
+ { GPIO_USB_CHG_CC1_TX_DATA, GPIO_USB_CHG_CC2_TX_DATA },
+ { GPIO_USB_DUT_CC1_TX_DATA, GPIO_USB_DUT_CC2_TX_DATA },
+};
+static const uint8_t ref_gpio[2 /* port */][2 /* polarity */] = {
+ { GPIO_USB_CHG_CC1_MCU, GPIO_USB_CHG_CC2_MCU },
+ { GPIO_USB_DUT_CC1_MCU, GPIO_USB_DUT_CC2_MCU },
+};
+
/* Drive the CC line from the TX block */
static inline void pd_tx_enable(int port, int polarity)
{
- if (port == 0) {
- /* put SPI function on TX pin */
- if (polarity) {
- const struct gpio_info *g = gpio_list +
- GPIO_USB_CHG_CC2_TX_DATA;
- gpio_set_alternate_function(g->port, g->mask, 0);
-
- /* set the low level reference */
- gpio_set_flags(GPIO_USB_CHG_CC2_MCU, GPIO_OUT_LOW);
- } else {
- const struct gpio_info *g = gpio_list +
- GPIO_USB_CHG_CC1_TX_DATA;
- gpio_set_alternate_function(g->port, g->mask, 0);
-
- /* set the low level reference */
- gpio_set_flags(GPIO_USB_CHG_CC1_MCU, GPIO_OUT_LOW);
- }
- } else {
- /* put SPI function on TX pin */
- /* MCU ADC pin output low */
- if (polarity) {
- /* USB_DUT_CC2_TX_DATA: PC2 is SPI2 MISO */
- const struct gpio_info *g = gpio_list +
- GPIO_USB_DUT_CC2_TX_DATA;
- gpio_set_alternate_function(g->port, g->mask, 1);
-
- /* set the low level reference */
- gpio_set_flags(GPIO_USB_DUT_CC2_MCU, GPIO_OUT_LOW);
- } else {
- /* USB_DUT_CC1_TX_DATA: PB14 is SPI2 MISO */
- const struct gpio_info *g = gpio_list +
- GPIO_USB_DUT_CC1_TX_DATA;
- gpio_set_alternate_function(g->port, g->mask, 0);
-
- /* set the low level reference */
- gpio_set_flags(GPIO_USB_DUT_CC1_MCU, GPIO_OUT_LOW);
- }
- }
+#ifndef VIF_BUILD /* genvif doesn't like tricks with GPIO macros */
+ const struct gpio_info *tx = gpio_list + tx_gpio[port][polarity];
+ const struct gpio_info *ref = gpio_list + ref_gpio[port][polarity];
+
+ /* use directly GPIO registers, latency before the PD preamble is key */
+
+ /* switch the TX pin Mode from Input (00) to Alternate (10) for SPI */
+ STM32_GPIO_MODER(tx->port) |= 2 << ((31 - __builtin_clz(tx->mask)) * 2);
+ /* switch the ref pin Mode from analog (11) to Out (01) for low level */
+ STM32_GPIO_MODER(ref->port) &=
+ ~(2 << ((31 - __builtin_clz(ref->mask)) * 2));
+#endif /* !VIF_BUILD */
}
/* Put the TX driver in Hi-Z state */
static inline void pd_tx_disable(int port, int polarity)
{
- if (port == 0) {
- if (polarity) {
- gpio_set_flags(GPIO_USB_CHG_CC2_TX_DATA, GPIO_INPUT);
- gpio_set_flags(GPIO_USB_CHG_CC2_MCU, GPIO_ANALOG);
- } else {
- gpio_set_flags(GPIO_USB_CHG_CC1_TX_DATA, GPIO_INPUT);
- gpio_set_flags(GPIO_USB_CHG_CC1_MCU, GPIO_ANALOG);
- }
- } else {
- if (polarity) {
- gpio_set_flags(GPIO_USB_DUT_CC2_TX_DATA, GPIO_INPUT);
- gpio_set_flags(GPIO_USB_DUT_CC2_MCU, GPIO_ANALOG);
- } else {
- gpio_set_flags(GPIO_USB_DUT_CC1_TX_DATA, GPIO_INPUT);
- gpio_set_flags(GPIO_USB_DUT_CC1_MCU, GPIO_ANALOG);
- }
- }
+ const struct gpio_info *tx = gpio_list + tx_gpio[port][polarity];
+ const struct gpio_info *ref = gpio_list + ref_gpio[port][polarity];
+
+ gpio_set_flags_by_mask(tx->port, tx->mask, GPIO_INPUT);
+ gpio_set_flags_by_mask(ref->port, ref->mask, GPIO_ANALOG);
}
/* we know the plug polarity, do the right configuration */
@@ -238,7 +209,25 @@ static inline void pd_select_polarity(int port, int polarity)
/* Initialize pins used for TX and put them in Hi-Z */
static inline void pd_tx_init(void)
{
+ const struct gpio_info *c2 = gpio_list + GPIO_USB_CHG_CC2_TX_DATA;
+ const struct gpio_info *c1 = gpio_list + GPIO_USB_CHG_CC1_TX_DATA;
+ const struct gpio_info *d2 = gpio_list + GPIO_USB_DUT_CC2_TX_DATA;
+ const struct gpio_info *d1 = gpio_list + GPIO_USB_DUT_CC1_TX_DATA;
+
gpio_config_module(MODULE_USB_PD, 1);
+ /* Select the proper alternate SPI function on TX_DATA pins */
+ /* USB_CHG_CC2_TX_DATA: PA6 is SPI1 MISO (AF0) */
+ gpio_set_alternate_function(c2->port, c2->mask, 0);
+ gpio_set_flags_by_mask(c2->port, c2->mask, GPIO_INPUT);
+ /* USB_CHG_CC1_TX_DATA: PB4 is SPI1 MISO (AF0) */
+ gpio_set_alternate_function(c1->port, c1->mask, 0);
+ gpio_set_flags_by_mask(c1->port, c1->mask, GPIO_INPUT);
+ /* USB_DUT_CC2_TX_DATA: PC2 is SPI2 MISO (AF1) */
+ gpio_set_alternate_function(d2->port, d2->mask, 1);
+ gpio_set_flags_by_mask(d2->port, d2->mask, GPIO_INPUT);
+ /* USB_DUT_CC1_TX_DATA: PB14 is SPI2 MISO (AF0) */
+ gpio_set_alternate_function(d1->port, d1->mask, 0);
+ gpio_set_flags_by_mask(d1->port, d1->mask, GPIO_INPUT);
}
static inline void pd_set_host_mode(int port, int enable)