From b9b457173ea7f194c13a2d025496c3c49cf05792 Mon Sep 17 00:00:00 2001 From: Todd Broch Date: Mon, 15 Dec 2014 21:28:39 -0800 Subject: pd: hoho: mcdp28x0 serial driver. Add initial serial driver for mdcp2850 dp->hdmi converter. Driver implements 'get information' (cmd:0x40) to provide rudimentary method to test mcdp for functionality and assert GPIO if successful. Future CLs may expose more serial functionality if necessary. Signed-off-by: Todd Broch BRANCH=samus BUG=chrome-os-partner:34122 TEST=manual, when compiles with #define MCDP_DEBUG see successful serial communication and result from get info. buf:[00]0x04 [01]0x40 [02]0x00 [03]0xbc ... buf:[00]0x0f [01]0x40 [02]0x00 [03]0x0e [04]0x00 [05]0x01 [06]0x01 [07]0x00 [08]0x00 [09]0x00 [10]0x00 [11]0x00 [12]0x00 [13]0x00 family:000e chipid:0001 irom:1.0.0 fw:0.0.0 Change-Id: I35f9d9b0437633d1bd6a6c9fa14413bedb12f5c2 Reviewed-on: https://chromium-review.googlesource.com/235930 Trybot-Ready: Todd Broch Tested-by: Todd Broch Reviewed-by: Vincent Palatin Commit-Queue: Todd Broch --- board/hoho/board.c | 20 ++++++- board/hoho/board.h | 5 ++ driver/build.mk | 3 ++ driver/mcdp28x0.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++++ driver/mcdp28x0.h | 56 ++++++++++++++++++++ 5 files changed, 231 insertions(+), 2 deletions(-) create mode 100644 driver/mcdp28x0.c create mode 100644 driver/mcdp28x0.h diff --git a/board/hoho/board.c b/board/hoho/board.c index 406bdebd77..324f79b2ef 100644 --- a/board/hoho/board.c +++ b/board/hoho/board.c @@ -10,6 +10,7 @@ #include "ec_version.h" #include "gpio.h" #include "hooks.h" +#include "mcdp28x0.h" #include "registers.h" #include "task.h" #include "usb.h" @@ -131,6 +132,21 @@ static void board_init_spi2(void) } #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) == 0xe) && + (MCDP_CHIPID(info.chipid) == 0x1)) + gpio_set_level(GPIO_MCDP_READY, 1); + + mcdp_disable(); +} +DECLARE_DEFERRED(factory_validation_deferred); + /* Initialize board. */ static void board_init(void) { @@ -144,8 +160,8 @@ static void board_init(void) gpio_enable_interrupt(GPIO_DP_HPD); gpio_set_level(GPIO_STM_READY, 1); /* factory test only */ - /* TODO(crosbug.com/p/34122): Add real check for MCDP function */ - gpio_set_level(GPIO_MCDP_READY, 1); /* factory test only */ + /* Delay needed to allow HDMI MCU to boot. */ + hook_call_deferred(factory_validation_deferred, 200*MSEC); } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); diff --git a/board/hoho/board.h b/board/hoho/board.h index 1345c4e1b7..1b43a4fe5a 100644 --- a/board/hoho/board.h +++ b/board/hoho/board.h @@ -43,6 +43,11 @@ #define CONFIG_USB_PD_IDENTITY_HW_VERS 1 #define CONFIG_USB_PD_IDENTITY_SW_VERS 1 #define CONFIG_USB_PD_NO_VBUS_DETECT +/* mcdp2850 serial interface */ +#define CONFIG_MCDP28X0 usart3_hw +#define CONFIG_STREAM +#define CONFIG_STREAM_USART +#define CONFIG_STREAM_USART3 #undef CONFIG_WATCHDOG_HELP #undef CONFIG_LID_SWITCH #undef CONFIG_TASK_PROFILING diff --git a/driver/build.mk b/driver/build.mk index 2d5de551a8..923be6ac1a 100644 --- a/driver/build.mk +++ b/driver/build.mk @@ -53,3 +53,6 @@ driver-$(CONFIG_USB_SWITCH_TSU6721)+=usb_switch_tsu6721.o # Firmware Update driver-$(CONFIG_SB_FIRMWARE_UPDATE)+=battery/sb_fw_update.o + +# video converters +driver-$(CONFIG_MCDP28X0)+=mcdp28x0.o diff --git a/driver/mcdp28x0.c b/driver/mcdp28x0.c new file mode 100644 index 0000000000..de334b5c59 --- /dev/null +++ b/driver/mcdp28x0.c @@ -0,0 +1,149 @@ +/* Copyright (c) 2014 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. + * + * Megachips DisplayPort to HDMI protocol converter / level shifter driver. + */ + +#include "config.h" +#include "console.h" +#include "common.h" +#include "mcdp28x0.h" +#include "timer.h" +#include "usart-stm32f0.h" +#include "util.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) + +#undef MCDP_DEBUG + +#ifdef MCDP_DEBUG +static inline void print_buffer(uint8_t *buf, int cnt) +{ + int i; + CPRINTF("buf:"); + for (i = 0; i < cnt; i++) { + if (i && !(i % 4)) + CPRINTF("\n "); + CPRINTF("[%02d]0x%02x ", i, buf[i]); + } + CPRINTF("\n"); +} +#else +static inline void print_buffer(uint8_t *buf, int cnt) {} +#endif + +USART_CONFIG(usart_mcdp, CONFIG_MCDP28X0, 115200, MCDP_INBUF_MAX, + MCDP_OUTBUF_MAX, NULL, NULL); + +/** + * Compute checksum. + * + * @msg message bytes to compute checksum on. + * @cnt count of message bytes. + * @return partial checksum. + */ +static uint8_t compute_checksum(const uint8_t *msg, int cnt) +{ + int i; + /* 1st byte (not in msg) is always cnt + 2, so seed chksum with that */ + uint8_t chksum = cnt + 2; + + for (i = 0; i < cnt; i++) + chksum += msg[i]; + return ~chksum + 1; +} + +/** + * transmit message over serial + * + * Packet consists of: + * msg[0] == length including this byte + cnt + chksum + * msg[1] == 1st message byte + * msg[cnt+1] == last message byte + * msg[cnt+2] == checksum + * + * @msg message bytes + * @cnt count of message bytes + * @return zero if success, error code otherwise + */ +static int tx_serial(const uint8_t *msg, int cnt) +{ + uint8_t out = cnt + 2; + uint8_t chksum = compute_checksum(msg, cnt); + + if (out_stream_write(&usart_mcdp.out, &out, 1) != 1) + return EC_ERROR_UNKNOWN; + + if (out_stream_write(&usart_mcdp.out, msg, cnt) != cnt) + return EC_ERROR_UNKNOWN; + + if (out_stream_write(&usart_mcdp.out, &chksum, 1) != 1) + return EC_ERROR_UNKNOWN; + + print_buffer(usart_mcdp_tx_buffer, cnt + 2); + + return EC_SUCCESS; +} + +/** + * receive message over serial + * + * @msg pointer to buffer to read message into + * @cnt count of message bytes + * @return zero if success, error code otherwise + */ +static int rx_serial(uint8_t *msg, int cnt) +{ + size_t read; + int retry = 2; + + read = in_stream_read(&usart_mcdp.in, msg, cnt); + while ((read < cnt) && retry) { + usleep(100*MSEC); + read += in_stream_read(&usart_mcdp.in, msg + read, + cnt - read); + retry--; + } + + print_buffer(msg, cnt); + + return !(read == cnt); +} + +void mcdp_enable(void) +{ + usart_init(&usart_mcdp); +} + +void mcdp_disable(void) +{ + usart_shutdown(&usart_mcdp); +} + +int mcdp_get_info(struct mcdp_info *info) +{ + uint8_t inbuf[MCDP_RSP_LEN(MCDP_LEN_GETINFO)]; + const uint8_t msg[2] = {MCDP_CMD_GETINFO, 0x00}; /* cmd + msg type */ + + if (tx_serial(msg, sizeof(msg))) + return EC_ERROR_UNKNOWN; + + if (rx_serial(inbuf, sizeof(inbuf))) + return EC_ERROR_UNKNOWN; + + /* check length & returned command ... no checksum provided */ + if (((inbuf[0] - 1) != sizeof(inbuf)) || + (inbuf[1] != MCDP_CMD_GETINFO)) + return EC_ERROR_UNKNOWN; + + memcpy(info, &inbuf[2], MCDP_LEN_GETINFO); + +#ifdef MCDP_DEBUG + CPRINTF("family:%04x chipid:%04x irom:%d.%d.%d fw:%d.%d.%d\n", + MCDP_FAMILY(info->family), MCDP_CHIPID(info->chipid), + info->irom.major, info->irom.minor, info->irom.build, + info->fw.major, info->fw.minor, info->fw.build); +#endif + return EC_SUCCESS; +} diff --git a/driver/mcdp28x0.h b/driver/mcdp28x0.h new file mode 100644 index 0000000000..c753816495 --- /dev/null +++ b/driver/mcdp28x0.h @@ -0,0 +1,56 @@ +/* Copyright (c) 2014 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. + * + * Megachips DisplayPort to HDMI protocol converter / level shifter driver. + */ + +#ifndef MCDP28X0_H +#define MCDP28X0_H + +#include + +#define MCDP_OUTBUF_MAX 16 +#define MCDP_INBUF_MAX 16 + +#define MCDP_CHIPID(chipid) ((chipid[0] << 8) | chipid[1]) +#define MCDP_FAMILY(family) ((family[0] << 8) | family[1]) + +#define MCDP_CMD_GETINFO 0x40 +#define MCDP_LEN_GETINFO 12 + +/* length byte + cmd byte + data len */ +#define MCDP_RSP_LEN(len) (len + 2) + +struct mcdp_version { + uint8_t major; + uint8_t minor; + uint16_t build; +}; + +struct mcdp_info { + uint8_t family[2]; + uint8_t chipid[2]; + struct mcdp_version irom; + struct mcdp_version fw; +}; + +/** + * Enable mcdp driver. + */ +void mcdp_enable(void); + +/** + * Disable mcdp driver. + */ +void mcdp_disable(void); + +/** + * get get information command from mcdp. + * + * @info pointer to mcdp_info structure + * @return zero if success, error code otherwise. + */ +int mcdp_get_info(struct mcdp_info *info); + +#endif -- cgit v1.2.1