summaryrefslogtreecommitdiff
path: root/board/coffeecake/board.c
diff options
context:
space:
mode:
authorRong Chang <rongchang@chromium.org>2017-09-04 14:01:59 +0800
committerchrome-bot <chrome-bot@chromium.org>2017-11-29 04:04:12 -0800
commitcf0153224ebe3acd6264fb15c514184b282e78bb (patch)
treee221d37d46429cd9721cf84deadbe8eae3198b82 /board/coffeecake/board.c
parent216bb5f9d7fdeac65e3ed572b463ca13982b7e83 (diff)
downloadchrome-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.c249
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),
+};