summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/tigertail/board.c394
-rw-r--r--board/tigertail/board.h136
-rw-r--r--board/tigertail/build.mk13
-rw-r--r--board/tigertail/ec.tasklist21
-rw-r--r--board/tigertail/gpio.inc55
-rw-r--r--chip/stm32/registers.h1
-rwxr-xr-xutil/flash_ec1
7 files changed, 621 insertions, 0 deletions
diff --git a/board/tigertail/board.c b/board/tigertail/board.c
new file mode 100644
index 0000000000..8229aaadd8
--- /dev/null
+++ b/board/tigertail/board.c
@@ -0,0 +1,394 @@
+/* Copyright 2017 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.
+ */
+
+/* Tigertail board configuration */
+
+#include "adc.h"
+#include "adc_chip.h"
+#include "common.h"
+#include "console.h"
+#include "ec_version.h"
+#include "gpio.h"
+#include "hooks.h"
+#include "i2c.h"
+#include "ina2xx.h"
+#include "queue_policies.h"
+#include "registers.h"
+#include "task.h"
+#include "timer.h"
+#include "update_fw.h"
+#include "usart-stm32f0.h"
+#include "usart_tx_dma.h"
+#include "usart_rx_dma.h"
+#include "usb_i2c.h"
+#include "usb-stream.h"
+#include "util.h"
+
+#include "gpio_list.h"
+
+
+#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args)
+
+
+/******************************************************************************
+ * Forward UARTs as a USB serial interface.
+ */
+
+#define USB_STREAM_RX_SIZE 16
+#define USB_STREAM_TX_SIZE 16
+
+/******************************************************************************
+ * Forward USART1 as a simple USB serial interface.
+ */
+static struct usart_config const usart1;
+struct usb_stream_config const usart1_usb;
+
+static struct queue const usart1_to_usb = QUEUE_DIRECT(64, uint8_t,
+ usart1.producer, usart1_usb.consumer);
+static struct queue const usb_to_usart1 = QUEUE_DIRECT(64, uint8_t,
+ usart1_usb.producer, usart1.consumer);
+
+static struct usart_config const usart1 =
+ USART_CONFIG(usart1_hw,
+ usart_rx_interrupt,
+ usart_tx_interrupt,
+ 115200,
+ usart1_to_usb,
+ usb_to_usart1);
+
+USB_STREAM_CONFIG(usart1_usb,
+ USB_IFACE_USART1_STREAM,
+ USB_STR_USART1_STREAM_NAME,
+ USB_EP_USART1_STREAM,
+ USB_STREAM_RX_SIZE,
+ USB_STREAM_TX_SIZE,
+ usb_to_usart1,
+ usart1_to_usb)
+
+
+/******************************************************************************
+ * Define the strings used in our USB descriptors.
+ */
+const void *const usb_strings[] = {
+ [USB_STR_DESC] = usb_string_desc,
+ [USB_STR_VENDOR] = USB_STRING_DESC("Google Inc."),
+ [USB_STR_PRODUCT] = USB_STRING_DESC("Tigertail"),
+ [USB_STR_SERIALNO] = 0,
+ [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32),
+ [USB_STR_I2C_NAME] = USB_STRING_DESC("I2C"),
+ [USB_STR_USART1_STREAM_NAME] = USB_STRING_DESC("DUT UART"),
+ [USB_STR_CONSOLE_NAME] = USB_STRING_DESC("Tigertail Console"),
+ [USB_STR_UPDATE_NAME] = USB_STRING_DESC("Firmware update"),
+};
+
+BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT);
+
+/******************************************************************************
+ * ADC support for SBU flip detect.
+ */
+/* ADC channels */
+const struct adc_t adc_channels[] = {
+ [ADC_SBU1] = {"SBU1", 3300, 4096, 0, STM32_AIN(6)},
+ [ADC_SBU2] = {"SBU2", 3300, 4096, 0, STM32_AIN(7)},
+};
+BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT);
+
+
+
+/******************************************************************************
+ * Support I2C bridging over USB, this requires usb_i2c_board_enable and
+ * usb_i2c_board_disable to be defined to enable and disable the SPI bridge.
+ */
+
+/* I2C ports */
+const struct i2c_port_t i2c_ports[] = {
+ {"master", I2C_PORT_MASTER, 100,
+ GPIO_MASTER_I2C_SCL, GPIO_MASTER_I2C_SDA},
+};
+const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
+
+int usb_i2c_board_enable(void) {return EC_SUCCESS; }
+void usb_i2c_board_disable(void) {}
+
+
+/******************************************************************************
+ * Support firmware upgrade over USB. We can update whichever section is not
+ * the current section.
+ */
+
+/*
+ * This array defines possible sections available for the firmware update.
+ * The section which does not map the current executing code is picked as the
+ * valid update area. The values are offsets into the flash space.
+ */
+const struct section_descriptor board_rw_sections[] = {
+ {CONFIG_RO_MEM_OFF,
+ CONFIG_RO_MEM_OFF + CONFIG_RO_SIZE},
+ {CONFIG_RW_MEM_OFF,
+ CONFIG_RW_MEM_OFF + CONFIG_RW_SIZE},
+};
+const struct section_descriptor * const rw_sections = board_rw_sections;
+const int num_rw_sections = ARRAY_SIZE(board_rw_sections);
+
+
+
+/******************************************************************************
+ * Console commands.
+ */
+
+/* State to indicate current GPIO config. */
+static int uart_state = UART_OFF;
+/* State to indicate current autodetect mode. */
+static int uart_detect = UART_DETECT_AUTO;
+
+/* Set GPIOs to configure UART mode. */
+static void set_uart_gpios(int state)
+{
+ int uart = 0;
+ int dir = 0;
+ int enabled = (state == UART_ON) || (state == UART_FLIP);
+
+ gpio_set_level(GPIO_ST_UART_LVL_DIS, 1);
+
+ uart = GPIO_INPUT;
+
+ if (state == UART_ON) {
+ uart = GPIO_ALTERNATE;
+ dir = 1;
+ }
+ if (state == UART_FLIP) {
+ uart = GPIO_ALTERNATE;
+ dir = 0;
+ }
+
+ /* Set level shifter direction. */
+ gpio_set_level(GPIO_ST_UART_TX_DIR, dir);
+ gpio_set_level(GPIO_ST_UART_TX_DIR_N, !dir);
+
+ /* Enable STM pinmux */
+ gpio_set_flags(GPIO_USART1_TX, uart);
+ gpio_set_flags(GPIO_USART1_RX, uart);
+
+ /* Flip uart orientation if necessary. */
+ STM32_USART_CR1(STM32_USART1_BASE) &= ~(STM32_USART_CR1_UE);
+ if (dir)
+ STM32_USART_CR2(STM32_USART1_BASE) &= ~(STM32_USART_CR2_SWAP);
+ else
+ STM32_USART_CR2(STM32_USART1_BASE) |= (STM32_USART_CR2_SWAP);
+ STM32_USART_CR1(STM32_USART1_BASE) |= STM32_USART_CR1_UE;
+
+ /* Enable level shifter. */
+ gpio_set_level(GPIO_ST_UART_LVL_DIS, !enabled);
+}
+
+/* Detect if a UART is plugged into SBU. Tigertail UART must be off
+ * for this to return useful info.
+ */
+static int detect_uart_orientation(void)
+{
+ int sbu1 = adc_read_channel(ADC_SBU1);
+ int sbu2 = adc_read_channel(ADC_SBU2);
+ int state = UART_OFF;
+
+ /*
+ * Here we check if one or the other SBU is 1.8v, as DUT
+ * TX should idle high.
+ */
+ if ((sbu1 < 150) && (sbu2 > 1600) && (sbu2 < 1900))
+ state = UART_ON;
+ else if ((sbu2 < 150) && (sbu1 > 1600) && (sbu1 < 1900))
+ state = UART_FLIP;
+ else
+ state = UART_OFF;
+
+ return state;
+}
+
+/*
+ * Detect if UART has been unplugged. Normal UARTs should
+ * have both lines idling high at 1.8v.
+ */
+static int detect_uart_idle(void)
+{
+ int sbu1 = adc_read_channel(ADC_SBU1);
+ int sbu2 = adc_read_channel(ADC_SBU2);
+ int enabled = 0;
+
+ if ((sbu1 > 1600) && (sbu1 < 1900) &&
+ (sbu2 > 1600) && (sbu2 < 1900))
+ enabled = 1;
+
+ return enabled;
+}
+
+/* Set the UART state and gpios, and autodetect if necessary. */
+void set_uart_state(int state)
+{
+ if (state == UART_AUTO) {
+ set_uart_gpios(UART_OFF);
+ msleep(10);
+
+ uart_detect = UART_DETECT_AUTO;
+ state = detect_uart_orientation();
+ } else {
+ uart_detect = UART_DETECT_OFF;
+ }
+
+ uart_state = state;
+ set_uart_gpios(state);
+}
+
+/*
+ * Autodetect UART state:
+ * We will check every 250ms, and change state if 1 second has passed
+ * in the new state.
+ */
+void uart_sbu_tick(void)
+{
+ static int debounce; /* = 0 */
+
+ if (uart_detect != UART_DETECT_AUTO)
+ return;
+
+ if (uart_state == UART_OFF) {
+ int state = detect_uart_orientation();
+
+ if (state != UART_OFF) {
+ debounce++;
+ if (debounce > 4) {
+ debounce = 0;
+ CPRINTS("UART autoenable\n");
+ set_uart_state(state);
+ }
+ return;
+ }
+ } else {
+ int enabled = detect_uart_idle();
+
+ if (!enabled) {
+ debounce++;
+ if (debounce > 4) {
+ debounce = 0;
+ CPRINTS("UART autodisable\n");
+ set_uart_state(UART_OFF);
+ }
+ return;
+ }
+ }
+ debounce = 0;
+}
+DECLARE_HOOK(HOOK_TICK, uart_sbu_tick, HOOK_PRIO_DEFAULT);
+
+static int command_uart(int argc, char **argv)
+{
+ char *uart_state_str = "off";
+ char *uart_detect_str = "manual";
+
+ if (argc > 1) {
+ if (!strcasecmp("off", argv[1]))
+ set_uart_state(UART_OFF);
+ else if (!strcasecmp("on", argv[1]))
+ set_uart_state(UART_ON);
+ else if (!strcasecmp("flip", argv[1]))
+ set_uart_state(UART_FLIP);
+ else if (!strcasecmp("auto", argv[1]))
+ set_uart_state(UART_AUTO);
+ else
+ return EC_ERROR_PARAM1;
+ }
+
+ if (uart_state == UART_ON)
+ uart_state_str = "on";
+ if (uart_state == UART_FLIP)
+ uart_state_str = "flip";
+ if (uart_detect == UART_DETECT_AUTO)
+ uart_detect_str = "auto";
+ ccprintf("UART mux is: %s, setting: %s\n",
+ uart_state_str, uart_detect_str);
+
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(uart, command_uart,
+ "[off|on|flip|auto]",
+ "Get/set the flip and enable state of the SBU UART");
+
+/* State we intend the mux GPIOs to be set. */
+static int mux_state = MUX_OFF;
+
+/* Set the state variable and GPIO configs to mux as requested. */
+void set_mux_state(int state)
+{
+ int enabled = (state == MUX_A) || (state == MUX_B);
+ /* dir: 0 -> A, dir: 1 -> B */
+ int dir = (state == MUX_B);
+
+ /* Disconnect first. */
+ gpio_set_level(GPIO_USB_C_OE_N, 1);
+ gpio_set_level(GPIO_SEL_RELAY_A, 0);
+ gpio_set_level(GPIO_SEL_RELAY_B, 0);
+
+ /* Reconnect in the requested direction. */
+ gpio_set_level(GPIO_SEL_RELAY_A, !dir && enabled);
+ gpio_set_level(GPIO_SEL_RELAY_B, dir && enabled);
+
+ gpio_set_level(GPIO_USB_C_SEL_B, dir);
+ gpio_set_level(GPIO_USB_C_OE_N, !enabled);
+
+ if (!enabled)
+ mux_state = MUX_OFF;
+ else
+ mux_state = state;
+}
+
+static int command_mux(int argc, char **argv)
+{
+ char *mux_state_str = "off";
+
+ if (argc > 1) {
+ if (!strcasecmp("off", argv[1]))
+ set_mux_state(MUX_OFF);
+ else if (!strcasecmp("a", argv[1]))
+ set_mux_state(MUX_A);
+ else if (!strcasecmp("b", argv[1]))
+ set_mux_state(MUX_B);
+ else
+ return EC_ERROR_PARAM1;
+ }
+
+ if (mux_state == MUX_A)
+ mux_state_str = "A";
+ if (mux_state == MUX_B)
+ mux_state_str = "B";
+ ccprintf("TYPE-C mux is %s\n", mux_state_str);
+
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(mux, command_mux,
+ "[off|A|B]",
+ "Get/set the mux and enable state of the TYPE-C mux");
+
+/******************************************************************************
+ * Initialize board.
+ */
+static void board_init(void)
+{
+ /* USB to serial queues */
+ queue_init(&usart1_to_usb);
+ queue_init(&usb_to_usart1);
+
+ /* UART init */
+ usart_init(&usart1);
+ /* No default type-c mux. TODO: would we like this to be set? */
+ set_mux_state(MUX_OFF);
+ /* Note that we can't enable AUTO until after init. */
+ set_uart_gpios(UART_OFF);
+
+ /* Calibrate INA0 (VBUS) with 1mA/LSB scale */
+ ina2xx_init(0, 0x8000, INA2XX_CALIB_1MA(15 /*mOhm*/));
+ ina2xx_init(1, 0x8000, INA2XX_CALIB_1MA(15 /*mOhm*/));
+ ina2xx_init(4, 0x8000, INA2XX_CALIB_1MA(15 /*mOhm*/));
+}
+DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT);
+
diff --git a/board/tigertail/board.h b/board/tigertail/board.h
new file mode 100644
index 0000000000..1340398943
--- /dev/null
+++ b/board/tigertail/board.h
@@ -0,0 +1,136 @@
+/* Copyright 2017 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.
+ */
+
+/* Tigertail configuration */
+
+#ifndef __CROS_EC_BOARD_H
+#define __CROS_EC_BOARD_H
+
+/* 48 MHz SYSCLK clock frequency */
+#define CPU_CLOCK 48000000
+
+/* Enable USART1 USB streams */
+#define CONFIG_STREAM_USART
+#define CONFIG_STREAM_USART1
+#define CONFIG_STREAM_USB
+#define CONFIG_CMD_USART_INFO
+
+/* The UART console is on USART1 (PA9/PA10) */
+#undef CONFIG_UART_CONSOLE
+#define CONFIG_UART_CONSOLE 2
+#undef CONFIG_UART_TX_DMA
+#undef CONFIG_UART_RX_DMA
+
+/* Optional features */
+#define CONFIG_STM_HWTIMER32
+#define CONFIG_HW_CRC
+
+/* USB Configuration */
+#define CONFIG_USB
+#define CONFIG_USB_PID 0x5027
+#define CONFIG_USB_CONSOLE
+#define CONFIG_USB_UPDATE
+
+#undef CONFIG_USB_MAXPOWER_MA
+#define CONFIG_USB_MAXPOWER_MA 100
+
+#define CONFIG_USB_SERIALNO
+#define DEFAULT_SERIALNO "Uninitialized"
+
+/* USB interface indexes (use define rather than enum to expand them) */
+#define USB_IFACE_CONSOLE 0
+#define USB_IFACE_UPDATE 1
+#define USB_IFACE_USART1_STREAM 2
+#define USB_IFACE_I2C 3
+#define USB_IFACE_COUNT 4
+
+/* USB endpoint indexes (use define rather than enum to expand them) */
+#define USB_EP_CONTROL 0
+#define USB_EP_CONSOLE 1
+#define USB_EP_UPDATE 2
+#define USB_EP_USART1_STREAM 3
+#define USB_EP_I2C 4
+#define USB_EP_COUNT 5
+
+/* Enable console recasting of GPIO type. */
+#define CONFIG_CMD_GPIO_EXTENDED
+
+/* This is not actually an EC so disable some features. */
+#undef CONFIG_WATCHDOG_HELP
+#undef CONFIG_LID_SWITCH
+
+/* Enable control of I2C over USB */
+#define CONFIG_USB_I2C
+#define CONFIG_I2C
+#define CONFIG_I2C_MASTER
+#define I2C_PORT_MASTER 0
+#define CONFIG_INA231
+
+/* Enable ADC */
+#define CONFIG_ADC
+
+/*
+ * Allow dangerous commands all the time, since we don't have a write protect
+ * switch.
+ */
+#define CONFIG_SYSTEM_UNLOCKED
+
+
+#ifndef __ASSEMBLER__
+
+/* Timer selection */
+#define TIM_CLOCK32 2
+#define TIM_ADC 3
+
+
+
+#include "gpio_signal.h"
+
+/* USB string indexes */
+enum usb_strings {
+ USB_STR_DESC = 0,
+ USB_STR_VENDOR,
+ USB_STR_PRODUCT,
+ USB_STR_SERIALNO,
+ USB_STR_VERSION,
+ USB_STR_I2C_NAME,
+ USB_STR_USART1_STREAM_NAME,
+ USB_STR_CONSOLE_NAME,
+ USB_STR_UPDATE_NAME,
+
+ USB_STR_COUNT
+};
+
+/* ADC signal */
+enum adc_channel {
+ ADC_SBU1 = 0,
+ ADC_SBU2,
+ /* Number of ADC channels */
+ ADC_CH_COUNT
+};
+
+void set_uart_state(int state);
+
+enum uart_states {
+ UART_OFF = 0,
+ UART_ON,
+ UART_FLIP,
+ UART_AUTO,
+};
+
+enum uart_detect_states {
+ UART_DETECT_OFF = 0,
+ UART_DETECT_AUTO,
+};
+
+void set_mux_state(int state);
+enum mux_states {
+ MUX_OFF = 0,
+ MUX_A,
+ MUX_B,
+};
+
+#endif /* !__ASSEMBLER__ */
+#endif /* __CROS_EC_BOARD_H */
diff --git a/board/tigertail/build.mk b/board/tigertail/build.mk
new file mode 100644
index 0000000000..9e7fae1c07
--- /dev/null
+++ b/board/tigertail/build.mk
@@ -0,0 +1,13 @@
+# -*- makefile -*-
+# Copyright 2017 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.
+#
+# Board specific files build
+
+# the IC is STmicro STM32F072CBU6
+CHIP:=stm32
+CHIP_FAMILY:=stm32f0
+CHIP_VARIANT:=stm32f07x
+
+board-y=board.o
diff --git a/board/tigertail/ec.tasklist b/board/tigertail/ec.tasklist
new file mode 100644
index 0000000000..3218df7df3
--- /dev/null
+++ b/board/tigertail/ec.tasklist
@@ -0,0 +1,21 @@
+/* Copyright 2017 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.
+ */
+
+/**
+ * List of enabled tasks in the priority order
+ *
+ * The first one has the lowest priority.
+ *
+ * For each task, use the macro TASK_ALWAYS(n, r, d, s) for base tasks and
+ * TASK_NOTEST(n, r, d, s) for tasks that can be excluded in test binaries,
+ * where :
+ * 'n' in the name of the task
+ * 'r' in the main routine of the task
+ * 'd' in an opaque parameter passed to the routine at startup
+ * 's' is the stack size in bytes; must be a multiple of 8
+ */
+#define CONFIG_TASK_LIST \
+ TASK_ALWAYS(HOOKS, hook_task, NULL, VENTI_TASK_STACK_SIZE) \
+ TASK_ALWAYS(CONSOLE, console_task, NULL, TASK_STACK_SIZE)
diff --git a/board/tigertail/gpio.inc b/board/tigertail/gpio.inc
new file mode 100644
index 0000000000..d7eabf21e1
--- /dev/null
+++ b/board/tigertail/gpio.inc
@@ -0,0 +1,55 @@
+/* -*- mode:c -*-
+ *
+ * Copyright 2017 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.
+ */
+
+/* Outputs */
+GPIO(SEL_CC2_A, PIN(A, 14), GPIO_OUT_LOW)
+GPIO(SEL_VBUS_A, PIN(A, 15), GPIO_OUT_LOW)
+GPIO(SEL_CC2_B, PIN(B, 0), GPIO_OUT_LOW)
+GPIO(SEL_VBUS_B, PIN(B, 1), GPIO_OUT_LOW)
+GPIO(SEL_RELAY_A, PIN(B, 2), GPIO_OUT_LOW)
+GPIO(SEL_RELAY_B, PIN(B, 3), GPIO_OUT_LOW)
+GPIO(USB_C_SEL_B, PIN(B, 4), GPIO_OUT_LOW)
+GPIO(USB_C_OE_N, PIN(B, 5), GPIO_OUT_HIGH)
+
+GPIO(ST_UART_LVL_DIS, PIN(B, 10), GPIO_OUT_HIGH)
+GPIO(ST_UART_TX_DIR, PIN(B, 12), GPIO_OUT_HIGH)
+GPIO(ST_UART_TX_DIR_N, PIN(B, 15), GPIO_OUT_LOW)
+
+GPIO(LED_G, PIN(B, 11), GPIO_OUT_HIGH)
+GPIO(LED_R, PIN(B, 13), GPIO_OUT_LOW)
+GPIO(LED_B, PIN(B, 14), GPIO_OUT_HIGH)
+
+/* Inputs */
+GPIO(USB_C_SBU1_DET, PIN(A, 6), GPIO_INPUT)
+GPIO(USB_C_SBU2_DET, PIN(A, 7), GPIO_INPUT)
+
+/* USART interface */
+GPIO(USART2_CTS, PIN(A, 0), GPIO_INPUT)
+GPIO(USART2_RTS, PIN(A, 1), GPIO_INPUT)
+GPIO(USART2_TX, PIN(A, 2), GPIO_INPUT)
+GPIO(USART2_RX, PIN(A, 3), GPIO_INPUT)
+GPIO(USART2_CK, PIN(A, 4), GPIO_INPUT)
+
+GPIO(USART1_TX, PIN(A, 9), GPIO_INPUT)
+GPIO(USART1_RX, PIN(A, 10), GPIO_INPUT)
+
+/* I2C pins should be configured as inputs until I2C module is */
+/* initialized. This will avoid driving the lines unintentionally.*/
+GPIO(MASTER_I2C_SCL, PIN(B, 8), GPIO_INPUT)
+GPIO(MASTER_I2C_SDA, PIN(B, 9), GPIO_INPUT)
+
+/* Unimplemented signals since we are not an EC */
+UNIMPLEMENTED(ENTERING_RW)
+UNIMPLEMENTED(WP_L)
+
+/* USART2: PA2/PA3 - Console UART */
+ALTERNATE(PIN_MASK(A, 0x000C), 1, MODULE_UART, 0)
+/* USART1: PA09/PA10 - AP/SBU UART */
+ALTERNATE(PIN_MASK(A, 0x0600), 1, MODULE_USART, 0)
+
+/* I2C MASTER:PB8/9 GPIO_ODR_HIGH */
+ALTERNATE(PIN_MASK(B, 0x0300), 1, MODULE_I2C, 0)
diff --git a/chip/stm32/registers.h b/chip/stm32/registers.h
index 4f79beb769..a8104114cf 100644
--- a/chip/stm32/registers.h
+++ b/chip/stm32/registers.h
@@ -224,6 +224,7 @@
#define STM32_USART_CR1_TXEIE (1 << 7)
#define STM32_USART_CR1_OVER8 (1 << 15)
#define STM32_USART_CR2(base) STM32_USART_REG(base, 0x04)
+#define STM32_USART_CR2_SWAP (1 << 15)
#define STM32_USART_CR3(base) STM32_USART_REG(base, 0x08)
#define STM32_USART_CR3_EIE (1 << 0)
#define STM32_USART_CR3_DMAR (1 << 6)
diff --git a/util/flash_ec b/util/flash_ec
index 797d4b02b6..6c36d2f1e2 100755
--- a/util/flash_ec
+++ b/util/flash_ec
@@ -91,6 +91,7 @@ BOARDS_STM32_DFU=(
sweetberry
polyberry
stm32f446e-eval
+ tigertail
)
BOARDS_NPCX_5M5G_JTAG=(