summaryrefslogtreecommitdiff
path: root/board/servo_v4
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2020-08-10 15:52:38 +0200
committerRuben Rodriguez Buchillon <coconutruben@chromium.org>2020-08-11 21:02:56 +0000
commitca827c348942c8bb9a4f71dbf4e593d6d46510dc (patch)
treedc5fefc3869d64e6bfe6b2e50dc8263c48aa603d /board/servo_v4
parent338cf6bdc85942cf45bbe89d3b9e6007bd041566 (diff)
downloadchrome-ec-ca827c348942c8bb9a4f71dbf4e593d6d46510dc.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>
Diffstat (limited to 'board/servo_v4')
-rw-r--r--board/servo_v4/usb_pd_config.h99
1 files changed, 44 insertions, 55 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)