diff options
-rw-r--r-- | board/tigertail/board.c | 394 | ||||
-rw-r--r-- | board/tigertail/board.h | 136 | ||||
-rw-r--r-- | board/tigertail/build.mk | 13 | ||||
-rw-r--r-- | board/tigertail/ec.tasklist | 21 | ||||
-rw-r--r-- | board/tigertail/gpio.inc | 55 | ||||
-rw-r--r-- | chip/stm32/registers.h | 1 | ||||
-rwxr-xr-x | util/flash_ec | 1 |
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=( |