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 /board/coffeecake/board.c | |
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>
Diffstat (limited to 'board/coffeecake/board.c')
-rw-r--r-- | board/coffeecake/board.c | 249 |
1 files changed, 249 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), +}; |