diff options
author | Rong Chang <rongchang@chromium.org> | 2017-09-04 14:01:59 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-11-29 04:04:12 -0800 |
commit | cf0153224ebe3acd6264fb15c514184b282e78bb (patch) | |
tree | e221d37d46429cd9721cf84deadbe8eae3198b82 | |
parent | 216bb5f9d7fdeac65e3ed572b463ca13982b7e83 (diff) | |
download | chrome-ec-cf0153224ebe3acd6264fb15c514184b282e78bb.tar.gz |
coffeecake: initial commit
Clone HoHo board to CoffeeCake.
BRANCH=none
BUG=none
TEST=make BOARD=coffeecake -j
Signed-off-by: Rong Chang <rongchang@chromium.org>
Change-Id: I62b4bf92a2eaffbc145197c7f36cfb7a29722bf5
Reviewed-on: https://chromium-review.googlesource.com/673963
Reviewed-by: Benson Leung <bleung@chromium.org>
-rw-r--r-- | board/coffeecake/board.c | 249 | ||||
-rw-r--r-- | board/coffeecake/board.h | 115 | ||||
-rw-r--r-- | board/coffeecake/build.mk | 14 | ||||
-rw-r--r-- | board/coffeecake/dev_key.pem | 27 | ||||
-rw-r--r-- | board/coffeecake/ec.tasklist | 22 | ||||
-rw-r--r-- | board/coffeecake/gpio.inc | 37 | ||||
-rw-r--r-- | board/coffeecake/usb_pd_config.h | 128 | ||||
-rw-r--r-- | board/coffeecake/usb_pd_policy.c | 281 | ||||
-rwxr-xr-x | util/flash_ec | 1 |
9 files changed, 874 insertions, 0 deletions
diff --git a/board/coffeecake/board.c b/board/coffeecake/board.c new file mode 100644 index 0000000000..27a5070651 --- /dev/null +++ b/board/coffeecake/board.c @@ -0,0 +1,249 @@ +/* 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. + */ +/* Coffeecake dock configuration */ + +#include "adc.h" +#include "adc_chip.h" +#include "common.h" +#include "ec_commands.h" +#include "ec_version.h" +#include "gpio.h" +#include "hooks.h" +#include "mcdp28x0.h" +#include "registers.h" +#include "task.h" +#include "usb_bb.h" +#include "usb_descriptor.h" +#include "usb_pd.h" +#include "timer.h" +#include "util.h" + +static volatile uint64_t hpd_prev_ts; +static volatile int hpd_prev_level; + +void hpd_event(enum gpio_signal signal); +#include "gpio_list.h" + +/** + * Hotplug detect deferred task + * + * Called after level change on hpd GPIO to evaluate (and debounce) what event + * has occurred. There are 3 events that occur on HPD: + * 1. low : downstream display sink is deattached + * 2. high : downstream display sink is attached + * 3. irq : downstream display sink signalling an interrupt. + * + * The debounce times for these various events are: + * HPD_USTREAM_DEBOUNCE_LVL : min pulse width of level value. + * HPD_USTREAM_DEBOUNCE_IRQ : min pulse width of IRQ low pulse. + * + * lvl(n-2) lvl(n-1) lvl prev_delta now_delta event + * ---------------------------------------------------- + * 1 0 1 <IRQ n/a low glitch (ignore) + * 1 0 1 >IRQ <LVL irq + * x 0 1 n/a >LVL high + * 0 1 0 <LVL n/a high glitch (ignore) + * x 1 0 n/a >LVL low + */ + +void hpd_irq_deferred(void) +{ + pd_send_hpd(0, hpd_irq); +} +DECLARE_DEFERRED(hpd_irq_deferred); + +void hpd_lvl_deferred(void) +{ + int level = gpio_get_level(GPIO_DP_HPD); + + if (level != hpd_prev_level) + /* It's a glitch while in deferred or canceled action */ + return; + + pd_send_hpd(0, (level) ? hpd_high : hpd_low); +} +DECLARE_DEFERRED(hpd_lvl_deferred); + +void hpd_event(enum gpio_signal signal) +{ + timestamp_t now = get_time(); + int level = gpio_get_level(signal); + uint64_t cur_delta = now.val - hpd_prev_ts; + + /* store current time */ + hpd_prev_ts = now.val; + + /* All previous hpd level events need to be re-triggered */ + hook_call_deferred(&hpd_lvl_deferred_data, -1); + + /* It's a glitch. Previous time moves but level is the same. */ + if (cur_delta < HPD_USTREAM_DEBOUNCE_IRQ) + return; + + if ((!hpd_prev_level && level) && + (cur_delta < HPD_USTREAM_DEBOUNCE_LVL)) + /* It's an irq */ + hook_call_deferred(&hpd_irq_deferred_data, 0); + else if (cur_delta >= HPD_USTREAM_DEBOUNCE_LVL) + hook_call_deferred(&hpd_lvl_deferred_data, + HPD_USTREAM_DEBOUNCE_LVL); + + hpd_prev_level = level; +} + +/* Initialize board. */ +void board_config_pre_init(void) +{ + /* enable SYSCFG clock */ + STM32_RCC_APB2ENR |= 1 << 0; + /* Remap USART DMA to match the USART driver */ + STM32_SYSCFG_CFGR1 |= (1 << 9) | (1 << 10);/* Remap USART1 RX/TX DMA */ +} + +#ifdef CONFIG_SPI_FLASH + +static void board_init_spi2(void) +{ + /* Remap SPI2 to DMA channels 6 and 7 */ + STM32_SYSCFG_CFGR1 |= (1 << 24); + + /* Set pin NSS to general purpose output mode (01b). */ + /* Set pins SCK, MISO, and MOSI to alternate function (10b). */ + STM32_GPIO_MODER(GPIO_B) &= ~0xff000000; + STM32_GPIO_MODER(GPIO_B) |= 0xa9000000; + + /* Set all four pins to alternate function 0 */ + STM32_GPIO_AFRH(GPIO_B) &= ~(0xffff0000); + + /* Set all four pins to output push-pull */ + STM32_GPIO_OTYPER(GPIO_B) &= ~(0xf000); + + /* Set pullup on NSS */ + STM32_GPIO_PUPDR(GPIO_B) |= 0x1000000; + + /* Set all four pins to high speed */ + STM32_GPIO_OSPEEDR(GPIO_B) |= 0xff000000; + + /* Reset SPI2 */ + STM32_RCC_APB1RSTR |= (1 << 14); + STM32_RCC_APB1RSTR &= ~(1 << 14); + + /* Enable clocks to SPI2 module */ + STM32_RCC_APB1ENR |= STM32_RCC_PB1_SPI2; +} +#endif /* CONFIG_SPI_FLASH */ + +static void factory_validation_deferred(void) +{ + struct mcdp_info info; + + mcdp_enable(); + + /* test mcdp via serial to validate function */ + if (!mcdp_get_info(&info) && (MCDP_FAMILY(info.family) == 0x0010) && + (MCDP_CHIPID(info.chipid) == 0x2850)) { + gpio_set_level(GPIO_MCDP_READY, 1); + pd_log_event(PD_EVENT_VIDEO_CODEC, + PD_LOG_PORT_SIZE(0, sizeof(info)), + 0, &info); + } + + mcdp_disable(); +} +DECLARE_DEFERRED(factory_validation_deferred); + +/* Initialize board. */ +static void board_init(void) +{ + timestamp_t now; +#ifdef CONFIG_SPI_FLASH + board_init_spi2(); +#endif + now = get_time(); + hpd_prev_level = gpio_get_level(GPIO_DP_HPD); + hpd_prev_ts = now.val; + gpio_enable_interrupt(GPIO_DP_HPD); + + gpio_set_level(GPIO_STM_READY, 1); /* factory test only */ + /* Delay needed to allow HDMI MCU to boot. */ + hook_call_deferred(&factory_validation_deferred_data, 200*MSEC); +} + +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +/* ADC channels */ +const struct adc_t adc_channels[] = { + /* USB PD CC lines sensing. Converted to mV (3300mV/4096). */ + [ADC_CH_CC1_PD] = {"USB_C_CC1_PD", 3300, 4096, 0, STM32_AIN(1)}, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +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("Hoho"), + [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32), + [USB_STR_BB_URL] = USB_STRING_DESC(USB_GOOGLE_TYPEC_URL), +}; +BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); + +/** + * USB configuration + * Any type-C device with alternate mode capabilities must have the following + * set of descriptors. + * + * 1. Standard Device + * 2. BOS + * 2a. Container ID + * 2b. Billboard Caps + */ +struct my_bos { + struct usb_bos_hdr_descriptor bos; + struct usb_contid_caps_descriptor contid_caps; + struct usb_bb_caps_base_descriptor bb_caps; + struct usb_bb_caps_svid_descriptor bb_caps_svids[1]; +}; + +static struct my_bos bos_desc = { + .bos = { + .bLength = USB_DT_BOS_SIZE, + .bDescriptorType = USB_DT_BOS, + .wTotalLength = (USB_DT_BOS_SIZE + USB_DT_CONTID_SIZE + + USB_BB_CAPS_BASE_SIZE + + USB_BB_CAPS_SVID_SIZE * 1), + .bNumDeviceCaps = 2, /* contid + bb_caps */ + }, + .contid_caps = { + .bLength = USB_DT_CONTID_SIZE, + .bDescriptorType = USB_DT_DEVICE_CAPABILITY, + .bDevCapabilityType = USB_DC_DTYPE_CONTID, + .bReserved = 0, + .ContainerID = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }, + .bb_caps = { + .bLength = (USB_BB_CAPS_BASE_SIZE + USB_BB_CAPS_SVID_SIZE * 1), + .bDescriptorType = USB_DT_DEVICE_CAPABILITY, + .bDevCapabilityType = USB_DC_DTYPE_BILLBOARD, + .iAdditionalInfoURL = USB_STR_BB_URL, + .bNumberOfAlternateModes = 1, + .bPreferredAlternateMode = 1, + .VconnPower = 0, + .bmConfigured = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + .bReserved = 0, + }, + .bb_caps_svids = { + { + .wSVID = 0xff01, /* TODO(tbroch) def'd in other CL remove hardcode */ + .bAlternateMode = 1, + .iAlternateModeString = USB_STR_BB_URL, /* TODO(crosbug.com/p/32687) */ + }, + }, +}; + +const struct bos_context bos_ctx = { + .descp = (void *)&bos_desc, + .size = sizeof(struct my_bos), +}; diff --git a/board/coffeecake/board.h b/board/coffeecake/board.h new file mode 100644 index 0000000000..f7bc554a21 --- /dev/null +++ b/board/coffeecake/board.h @@ -0,0 +1,115 @@ +/* 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. + */ + +/* Coffee cake configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* 48 MHz SYSCLK clock frequency */ +#define CPU_CLOCK 48000000 + +/* the UART console is on USART1 (PA9/PA10) */ +#define CONFIG_UART_CONSOLE 1 + +/* Optional features */ +#define CONFIG_STM_HWTIMER32 +#define CONFIG_ADC +#define CONFIG_BOARD_PRE_INIT +#define CONFIG_CMD_SPI_FLASH +#define CONFIG_HW_CRC +#define CONFIG_RSA +#define CONFIG_RWSIG +#define CONFIG_RWSIG_TYPE_USBPD1 +#define CONFIG_SHA256 +/* TODO(tbroch) Re-enable once STM spi master can be inhibited at boot so it + doesn't interfere with HDMI loading its f/w */ +#undef CONFIG_SPI_FLASH +#define CONFIG_SPI_MASTER_PORT 2 +#define CONFIG_SPI_CS_GPIO GPIO_PD_MCDP_SPI_CS_L +#define CONFIG_USB +#define CONFIG_USB_BOS +#define CONFIG_USB_INHIBIT_CONNECT +#define CONFIG_USB_POWER_DELIVERY +#define CONFIG_USB_PD_ALT_MODE +#define CONFIG_USB_PD_HW_DEV_ID_BOARD_MAJOR USB_PD_HW_DEV_ID_HOHO +#define CONFIG_USB_PD_HW_DEV_ID_BOARD_MINOR 2 +#define CONFIG_USB_PD_DUAL_ROLE +#define CONFIG_USB_PD_CUSTOM_VDM +#define CONFIG_USB_PD_FLASH +#define CONFIG_USB_PD_INTERNAL_COMP +#define CONFIG_USB_PD_IDENTITY_HW_VERS 1 +#define CONFIG_USB_PD_IDENTITY_SW_VERS 1 +#define CONFIG_USB_PD_LOGGING +#undef CONFIG_EVENT_LOG_SIZE +#define CONFIG_EVENT_LOG_SIZE 256 +#define CONFIG_USB_PD_PORT_COUNT 1 +#define CONFIG_USB_PD_TCPC +#define CONFIG_USB_PD_TCPM_STUB +#define CONFIG_USB_PD_VBUS_DETECT_NONE +/* mcdp2850 serial interface */ +#define CONFIG_MCDP28X0 usart3_hw +#define CONFIG_STREAM_USART +#define CONFIG_STREAM_USART3 +#undef CONFIG_WATCHDOG_HELP +#undef CONFIG_LID_SWITCH +#undef CONFIG_TASK_PROFILING + +/* USB configuration */ +#define CONFIG_USB_PID 0x5010 +#define CONFIG_USB_BCD_DEV 0x0001 /* v 0.01 */ + +/* No Write-protect GPIO, force the write-protection */ +#define CONFIG_WP_ALWAYS + +#ifndef __ASSEMBLER__ + +/* Timer selection */ +#define TIM_CLOCK32 2 +#define TIM_ADC 3 + +#include "gpio_signal.h" + +/* ADC signal */ +enum adc_channel { + ADC_CH_CC1_PD = 0, + /* Number of ADC channels */ + ADC_CH_COUNT +}; + +/* USB string indexes */ +enum usb_strings { + USB_STR_DESC = 0, + USB_STR_VENDOR, + USB_STR_PRODUCT, + USB_STR_VERSION, + USB_STR_BB_URL, + + USB_STR_COUNT +}; + +/* we are never a source : don't care about power supply */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 0 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 0 /* us */ + +/* Define typical operating power and max power */ +#define PD_OPERATING_POWER_MW 1000 +#define PD_MAX_POWER_MW 1500 +#define PD_MAX_CURRENT_MA 300 +#define PD_MAX_VOLTAGE_MV 5000 + +#endif /* !__ASSEMBLER__ */ + +/* USB Device class */ +#define USB_DEV_CLASS USB_CLASS_BILLBOARD + +/* USB interface indexes (use define rather than enum to expand them) */ +#define USB_IFACE_COUNT 0 + +/* USB endpoint indexes (use define rather than enum to expand them) */ +#define USB_EP_CONTROL 0 +#define USB_EP_COUNT 1 + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/coffeecake/build.mk b/board/coffeecake/build.mk new file mode 100644 index 0000000000..277c5c60f6 --- /dev/null +++ b/board/coffeecake/build.mk @@ -0,0 +1,14 @@ +# -*- 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 STM32F072B +CHIP:=stm32 +CHIP_FAMILY:=stm32f0 +CHIP_VARIANT:=stm32f07x + +board-y=board.o +board-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o diff --git a/board/coffeecake/dev_key.pem b/board/coffeecake/dev_key.pem new file mode 100644 index 0000000000..08d5bd414c --- /dev/null +++ b/board/coffeecake/dev_key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEApfbLqgOYIM6AfRI6SJcj1Crengsp+yjHXtwZFOH6WDVP5Q9c +KSbwqoKHEKTbWJ90ymjqjfi382hl64L/V6J8SfIqGhrFztwXLhJOwFXRK5Jgzkk+ +YUByDzAKTKOlzvvRqk10Tq5a3wphg1SxGVLLOOsTGoKhGI93Wkf2j8AibMlVVZzz +Q8DmVszkYZL+Kchv6h1FgSvBW0oZa5tVod+0XToWSrPEYnBWs0zZEywCusIXMy7D +LaqMPFB4LTkDZ9Ne8jnB5xRad+ME4CgxZqUwGC7tdFdHdiiXpIwzIoxVk6xFIZUF +uusG4RR3O2ubaPJ/Fpf3UuuCWmddk37WaC7o7QIDAQABAoIBAAG4L94AEYhte0lQ +cggkgLuHAi1zAilW/9HMx/m+aaCWVNCTuym1/JJXrdyPSLJ/XG9obN2xsP41m7C3 +97tJtK3zc1o34srE3vycNfKqMPOZnaUlfx700vmzTrgCjgo5868nBEh4Z/qdmesJ +aphPkklxrg39QnwFqH/n9PcCT5j+7LyCeWeGbWxKfpzP2CT6v8XxT3XY1mtFSa4j +dfYaqb+aunYAhjEb4gqa48hyNTQAZskDOUr1TK433wbGqRughXXrQQix+FBW483u +IGo8aGgiQsjYxHX+ynNTMKW1Oap9WZRWVxF09Ph1f3MT+k3gKqM/0AejlDfBuTDu +aLxiKIUCgYEA1FZmfGn4RNlghv/ZCAlfWqbf5NA1/wA/Knk8u0R+kMQ71e8NFjOc +Ym3Uix+89KcKDBIgHn1360pNvSCeTyVU28wQ2bst5s6pvu4FYDvjym2nTgXcFJX6 +DDnZfVZ+WLSFR8E76LQLJGd00DSq0/uBw3ULyRSirkuQnFI3w3u4BH8CgYEAyBdD +UMV83kwQaDMuGgKqZtD4Ou3s/MDzMwcNgUSjLIueFdsXVnlzYQwwJXuLFkrp5COx +Zyoha/d1QQawnYehKmHWWy7qN/l0CO+F2DGb1E6pNXJrn+zn33Mgz9ms8421eqqn +ATQbq6ZQInk1IrkLfyZ3t09l6cyBMJuJjkoBrJMCgYA2Hfsq1FtJONnILmbjDHh4 +AzXm/EX2wtpWeeXHmLJlNQ5G/REpymeeEn3sI1+mPvhpkSkMfE/W8O4VOL4AT/Rr +vHvC8ljFjYBnwAQwvbLVwdK1KPspZ/v9p7TNpAC5nPCnFBGvwktgsNltwy6SrnQp +G6iwTAkWQP4PSUkbEmoZAwKBgF0OLJlQ70y3FV5Qhx1DphohD4DgjDnURoaxvf8j +e7vIxuGlPgpSe21j7LRR65KXjoUycFvpRRfgQyDVyqfInxSF4doQTI9xrRxGwPmV +wMIRPzKDHziGRiQud9ESjBPNENyWpwqxQDkpJNWThzm503Xz3vNasqv0FxUTEPsi +wfqPAoGABXPl7baUkpYzppAJqRlGNxsMjpbWscDPjmPosrGs6d81DP287s/IjfDR +ysQptvhJRK/lubM8As+d0/VLd6P8wk8dyZR1nRELwnVaPC55cS5+YIjgXK9TBmLA +hC0BIgujJS2qbXQRQF7yX925Gg77WLN2sJqtVg1Brine056pHTA= +-----END RSA PRIVATE KEY----- diff --git a/board/coffeecake/ec.tasklist b/board/coffeecake/ec.tasklist new file mode 100644 index 0000000000..5254b70e2b --- /dev/null +++ b/board/coffeecake/ec.tasklist @@ -0,0 +1,22 @@ +/* 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, TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, LARGER_TASK_STACK_SIZE) diff --git a/board/coffeecake/gpio.inc b/board/coffeecake/gpio.inc new file mode 100644 index 0000000000..cfb689d825 --- /dev/null +++ b/board/coffeecake/gpio.inc @@ -0,0 +1,37 @@ +/* -*- 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. + */ + +/* Declare symbolic names for all the GPIOs that we care about. + * Note: Those with interrupt handlers must be declared first. */ + +GPIO_INT(DP_HPD, PIN(A, 0), GPIO_INT_BOTH, hpd_event) + +GPIO(USB_C_CC1_PD, PIN(A, 1), GPIO_ANALOG) +GPIO(STM_READY, PIN(A, 2), GPIO_OUT_LOW) /* factory test only */ +GPIO(MCDP_RESET_L, PIN(A, 3), GPIO_OUT_HIGH) +GPIO(PD_DAC_REF, PIN(A, 4), GPIO_ANALOG) + +GPIO(MCDP_READY, PIN(A, 7), GPIO_OUT_LOW) /* factory test only */ +GPIO(PD_SBU_ENABLE, PIN(A, 8), GPIO_OUT_LOW) +GPIO(USB_DM, PIN(A, 11), GPIO_ANALOG) +GPIO(USB_DP, PIN(A, 12), GPIO_ANALOG) +GPIO(PD_CC1_TX_EN, PIN(A, 15), GPIO_OUT_LOW) + +GPIO(MCDP_GPIO1, PIN(B, 0), GPIO_INPUT) +GPIO(MCDP_CONFIG1, PIN(B, 1), GPIO_INPUT) +GPIO(PD_MCDP_SPI_WP_L, PIN(B, 2), GPIO_OUT_LOW) +GPIO(PD_CC1_TX_DATA, PIN(B, 4), GPIO_OUT_LOW) +GPIO(PD_MCDP_SPI_CS_L, PIN(B, 12), GPIO_INPUT) + +/* Unimplemented signals which we need to emulate for now */ +UNIMPLEMENTED(ENTERING_RW) +UNIMPLEMENTED(WP_L) + +ALTERNATE(PIN_MASK(B, 0x0008), 0, MODULE_USB_PD, 0) /* SPI1: SCK(PB3) */ +ALTERNATE(PIN_MASK(B, 0x0200), 2, MODULE_USB_PD, 0) /* TIM17_CH1: PB9 */ +ALTERNATE(PIN_MASK(A, 0x0600), 1, MODULE_UART, GPIO_PULL_UP) /* USART1: PA9/PA10 */ +ALTERNATE(PIN_MASK(B, 0x0C00), 4, MODULE_UART, GPIO_PULL_UP) /* USART3: PB10/PB11 */ diff --git a/board/coffeecake/usb_pd_config.h b/board/coffeecake/usb_pd_config.h new file mode 100644 index 0000000000..181ccd20c2 --- /dev/null +++ b/board/coffeecake/usb_pd_config.h @@ -0,0 +1,128 @@ +/* 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. + */ + +/* USB Power delivery board configuration */ + +#ifndef __CROS_EC_USB_PD_CONFIG_H +#define __CROS_EC_USB_PD_CONFIG_H + +/* Timer selection for baseband PD communication */ +#define TIM_CLOCK_PD_TX_C0 17 +#define TIM_CLOCK_PD_RX_C0 1 + +#define TIM_CLOCK_PD_TX(p) TIM_CLOCK_PD_TX_C0 +#define TIM_CLOCK_PD_RX(p) TIM_CLOCK_PD_RX_C0 + +/* Timer channel */ +#define TIM_RX_CCR_C0 1 +#define TIM_TX_CCR_C0 1 + +/* RX timer capture/compare register */ +#define TIM_CCR_C0 (&STM32_TIM_CCRx(TIM_CLOCK_PD_RX_C0, TIM_RX_CCR_C0)) +#define TIM_RX_CCR_REG(p) TIM_CCR_C0 + +/* TX and RX timer register */ +#define TIM_REG_TX_C0 (STM32_TIM_BASE(TIM_CLOCK_PD_TX_C0)) +#define TIM_REG_RX_C0 (STM32_TIM_BASE(TIM_CLOCK_PD_RX_C0)) +#define TIM_REG_TX(p) TIM_REG_TX_C0 +#define TIM_REG_RX(p) TIM_REG_RX_C0 + +/* use the hardware accelerator for CRC */ +#define CONFIG_HW_CRC + +/* TX is using SPI1 on PB3-4 */ +#define SPI_REGS(p) STM32_SPI1_REGS + +static inline void spi_enable_clock(int port) +{ + STM32_RCC_APB2ENR |= STM32_RCC_PB2_SPI1; +} + +/* SPI1_TX no remap needed */ +#define DMAC_SPI_TX(p) STM32_DMAC_CH3 + +/* RX is using COMP1 triggering TIM1 CH1 */ +#define CMP1OUTSEL STM32_COMP_CMP1OUTSEL_TIM1_IC1 +#define CMP2OUTSEL 0 + +#define TIM_TX_CCR_IDX(p) TIM_TX_CCR_C0 +#define TIM_RX_CCR_IDX(p) TIM_RX_CCR_C0 +#define TIM_CCR_CS 1 +#define EXTI_COMP_MASK(p) (1 << 21) +#define IRQ_COMP STM32_IRQ_COMP +/* triggers packet detection on comparator falling edge */ +#define EXTI_XTSR STM32_EXTI_FTSR + +/* TIM1_CH1 no remap needed */ +#define DMAC_TIM_RX(p) STM32_DMAC_CH2 + +/* the pins used for communication need to be hi-speed */ +static inline void pd_set_pins_speed(int port) +{ + /* 40 Mhz pin speed on TX_EN (PA15) */ + STM32_GPIO_OSPEEDR(GPIO_A) |= 0xC0000000; + /* 40 MHz pin speed on SPI CLK/MOSI (PB3/4) TIM17_CH1 (PB9) */ + STM32_GPIO_OSPEEDR(GPIO_B) |= 0x000C03C0; +} + +/* Reset SPI peripheral used for TX */ +static inline void pd_tx_spi_reset(int port) +{ + /* Reset SPI1 */ + STM32_RCC_APB2RSTR |= (1 << 12); + STM32_RCC_APB2RSTR &= ~(1 << 12); +} + +/* Drive the CC line from the TX block */ +static inline void pd_tx_enable(int port, int polarity) +{ + /* PB4 is SPI1_MISO */ + gpio_set_alternate_function(GPIO_B, 0x0010, 0); + + gpio_set_level(GPIO_PD_CC1_TX_EN, 1); +} + +/* Put the TX driver in Hi-Z state */ +static inline void pd_tx_disable(int port, int polarity) +{ + /* output low on SPI TX (PB4) to disable the FET */ + STM32_GPIO_MODER(GPIO_B) = (STM32_GPIO_MODER(GPIO_B) + & ~(3 << (2*4))) + | (1 << (2*4)); + /* put the low level reference in Hi-Z */ + gpio_set_level(GPIO_PD_CC1_TX_EN, 0); +} + +static inline void pd_select_polarity(int port, int polarity) +{ + /* + * use the right comparator : CC1 -> PA1 (COMP1 INP) + * use VrefInt / 2 as INM (about 600mV) + */ + STM32_COMP_CSR = (STM32_COMP_CSR & ~STM32_COMP_CMP1INSEL_MASK) + | STM32_COMP_CMP1EN | STM32_COMP_CMP1INSEL_VREF12; +} + +/* Initialize pins used for TX and put them in Hi-Z */ +static inline void pd_tx_init(void) +{ + gpio_config_module(MODULE_USB_PD, 1); +} + +static inline void pd_set_host_mode(int port, int enable) {} + +static inline void pd_config_init(int port, uint8_t power_role) +{ + /* Initialize TX pins and put them in Hi-Z */ + pd_tx_init(); +} + +static inline int pd_adc_read(int port, int cc) +{ + /* only one CC line, assume other one is always low */ + return (cc == 0) ? adc_read_channel(ADC_CH_CC1_PD) : 0; +} + +#endif /* __CROS_EC_USB_PD_CONFIG_H */ diff --git a/board/coffeecake/usb_pd_policy.c b/board/coffeecake/usb_pd_policy.c new file mode 100644 index 0000000000..2b9e9d60d3 --- /dev/null +++ b/board/coffeecake/usb_pd_policy.c @@ -0,0 +1,281 @@ +/* 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. + */ + +#include "adc.h" +#include "board.h" +#include "common.h" +#include "console.h" +#include "ec_commands.h" +#include "gpio.h" +#include "hooks.h" +#include "registers.h" +#include "task.h" +#include "timer.h" +#include "usb_api.h" +#include "usb_bb.h" +#include "usb_pd.h" +#include "util.h" +#include "version.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) + +#define PDO_FIXED_FLAGS PDO_FIXED_COMM_CAP + +/* Source PDOs */ +const uint32_t pd_src_pdo[] = {}; +const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); + +/* Fake PDOs : we just want our pre-defined voltages */ +const uint32_t pd_snk_pdo[] = { + PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), +}; +const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); + +/* Holds valid object position (opos) for entered mode */ +static int alt_mode[PD_AMODE_COUNT]; + +void pd_set_input_current_limit(int port, uint32_t max_ma, + uint32_t supply_voltage) +{ + /* No battery, nothing to do */ + return; +} + +int pd_is_valid_input_voltage(int mv) +{ + /* Any voltage less than the max is allowed */ + return 1; +} + +void pd_transition_voltage(int idx) +{ + /* No operation: sink only */ +} + +int pd_set_power_supply_ready(int port) +{ + return EC_SUCCESS; +} + +void pd_power_supply_reset(int port) +{ +} + +int pd_snk_is_vbus_provided(int port) +{ + return 1; +} + +int pd_board_checks(void) +{ + return EC_SUCCESS; +} + +int pd_check_power_swap(int port) +{ + /* Always refuse power swap */ + return 0; +} + +int pd_check_data_swap(int port, int data_role) +{ + /* Always refuse data swap */ + return 0; +} + +void pd_execute_data_swap(int port, int data_role) +{ + /* Do nothing */ +} + +void pd_check_pr_role(int port, int pr_role, int flags) +{ +} + +void pd_check_dr_role(int port, int dr_role, int flags) +{ +} +/* ----------------- Vendor Defined Messages ------------------ */ +const uint32_t vdo_idh = VDO_IDH(0, /* data caps as USB host */ + 1, /* data caps as USB device */ + IDH_PTYPE_AMA, /* Alternate mode */ + 1, /* supports alt modes */ + USB_VID_GOOGLE); + +const uint32_t vdo_product = VDO_PRODUCT(CONFIG_USB_PID, CONFIG_USB_BCD_DEV); + +const uint32_t vdo_ama = VDO_AMA(CONFIG_USB_PD_IDENTITY_HW_VERS, + CONFIG_USB_PD_IDENTITY_SW_VERS, + 0, 0, 0, 0, /* SS[TR][12] */ + 0, /* Vconn power */ + 0, /* Vconn power required */ + 1, /* Vbus power required */ + AMA_USBSS_BBONLY /* USB SS support */); + +static int svdm_response_identity(int port, uint32_t *payload) +{ + payload[VDO_I(IDH)] = vdo_idh; + /* TODO(tbroch): Do we plan to obtain TID (test ID) for hoho */ + payload[VDO_I(CSTAT)] = VDO_CSTAT(0); + payload[VDO_I(PRODUCT)] = vdo_product; + payload[VDO_I(AMA)] = vdo_ama; + return VDO_I(AMA) + 1; +} + +static int svdm_response_svids(int port, uint32_t *payload) +{ + payload[1] = VDO_SVID(USB_SID_DISPLAYPORT, USB_VID_GOOGLE); + payload[2] = 0; + return 3; +} + +#define OPOS_DP 1 +#define OPOS_GFU 1 + +const uint32_t vdo_dp_modes[1] = { + VDO_MODE_DP(0, /* UFP pin cfg supported : none */ + MODE_DP_PIN_C, /* DFP pin cfg supported */ + 1, /* no usb2.0 signalling in AMode */ + CABLE_PLUG, /* its a plug */ + MODE_DP_V13, /* DPv1.3 Support, no Gen2 */ + MODE_DP_SNK) /* Its a sink only */ +}; + +const uint32_t vdo_goog_modes[1] = { + VDO_MODE_GOOGLE(MODE_GOOGLE_FU) +}; + +static int svdm_response_modes(int port, uint32_t *payload) +{ + if (PD_VDO_VID(payload[0]) == USB_SID_DISPLAYPORT) { + memcpy(payload + 1, vdo_dp_modes, sizeof(vdo_dp_modes)); + return ARRAY_SIZE(vdo_dp_modes) + 1; + } else if (PD_VDO_VID(payload[0]) == USB_VID_GOOGLE) { + memcpy(payload + 1, vdo_goog_modes, sizeof(vdo_goog_modes)); + return ARRAY_SIZE(vdo_goog_modes) + 1; + } else { + return 0; /* nak */ + } +} + +static int dp_status(int port, uint32_t *payload) +{ + int opos = PD_VDO_OPOS(payload[0]); + int hpd = gpio_get_level(GPIO_DP_HPD); + if (opos != OPOS_DP) + return 0; /* nak */ + + payload[1] = VDO_DP_STATUS(0, /* IRQ_HPD */ + (hpd == 1), /* HPD_HI|LOW */ + 0, /* request exit DP */ + 0, /* request exit USB */ + 0, /* MF pref */ + gpio_get_level(GPIO_PD_SBU_ENABLE), + 0, /* power low */ + 0x2); + return 2; +} + +static int dp_config(int port, uint32_t *payload) +{ + if (PD_DP_CFG_DPON(payload[1])) + gpio_set_level(GPIO_PD_SBU_ENABLE, 1); + return 1; +} + +static int svdm_enter_mode(int port, uint32_t *payload) +{ + int rv = 0; /* will generate a NAK */ + + /* SID & mode request is valid */ + if ((PD_VDO_VID(payload[0]) == USB_SID_DISPLAYPORT) && + (PD_VDO_OPOS(payload[0]) == OPOS_DP)) { + alt_mode[PD_AMODE_DISPLAYPORT] = OPOS_DP; + rv = 1; + pd_log_event(PD_EVENT_VIDEO_DP_MODE, 0, 1, NULL); + } else if ((PD_VDO_VID(payload[0]) == USB_VID_GOOGLE) && + (PD_VDO_OPOS(payload[0]) == OPOS_GFU)) { + alt_mode[PD_AMODE_GOOGLE] = OPOS_GFU; + rv = 1; + } + + if (rv) + /* + * If we failed initial mode entry we'll have enumerated the USB + * Billboard class. If so we should disconnect. + */ + usb_disconnect(); + + return rv; +} + +int pd_alt_mode(int port, uint16_t svid) +{ + if (svid == USB_SID_DISPLAYPORT) + return alt_mode[PD_AMODE_DISPLAYPORT]; + else if (svid == USB_VID_GOOGLE) + return alt_mode[PD_AMODE_GOOGLE]; + return 0; +} + +static int svdm_exit_mode(int port, uint32_t *payload) +{ + if (PD_VDO_VID(payload[0]) == USB_SID_DISPLAYPORT) { + gpio_set_level(GPIO_PD_SBU_ENABLE, 0); + alt_mode[PD_AMODE_DISPLAYPORT] = 0; + pd_log_event(PD_EVENT_VIDEO_DP_MODE, 0, 0, NULL); + } else if (PD_VDO_VID(payload[0]) == USB_VID_GOOGLE) { + alt_mode[PD_AMODE_GOOGLE] = 0; + } else { + CPRINTF("Unknown exit mode req:0x%08x\n", payload[0]); + } + + return 1; /* Must return ACK */ +} + +static struct amode_fx dp_fx = { + .status = &dp_status, + .config = &dp_config, +}; + +const struct svdm_response svdm_rsp = { + .identity = &svdm_response_identity, + .svids = &svdm_response_svids, + .modes = &svdm_response_modes, + .enter_mode = &svdm_enter_mode, + .amode = &dp_fx, + .exit_mode = &svdm_exit_mode, +}; + +int pd_custom_vdm(int port, int cnt, uint32_t *payload, + uint32_t **rpayload) +{ + int rsize; + + if (PD_VDO_VID(payload[0]) != USB_VID_GOOGLE || + !alt_mode[PD_AMODE_GOOGLE]) + return 0; + + *rpayload = payload; + + rsize = pd_custom_flash_vdm(port, cnt, payload); + if (!rsize) { + int cmd = PD_VDO_CMD(payload[0]); + switch (cmd) { + case VDO_CMD_GET_LOG: + rsize = pd_vdm_get_log_entry(payload); + break; + default: + /* Unknown : do not answer */ + return 0; + } + } + + /* respond (positively) to the request */ + payload[0] |= VDO_SRC_RESPONDER; + + return rsize; +} diff --git a/util/flash_ec b/util/flash_ec index 8337b41bc0..889ded3eb6 100755 --- a/util/flash_ec +++ b/util/flash_ec @@ -58,6 +58,7 @@ BOARDS_STM32=( big blaze chell_pd + coffeecake elm eve_fp glados_pd |