Patrick Rudolph has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/29946
Change subject: [WIP]opencelluar: Add EC interface ......................................................................
[WIP]opencelluar: Add EC interface
Add the EC driver that uses the OpenCellular Management Protocol. Implement the board_reset() method using introduced methods.
Change-Id: I67eb4ee8e0ad297a8d1984d55102146688c291fc Signed-off-by: Patrick Rudolph patrick.rudolph@9elements.com --- A src/ec/opencellular/tiva/Kconfig A src/ec/opencellular/tiva/Makefile.inc A src/ec/opencellular/tiva/ec.c A src/ec/opencellular/tiva/ec.h M src/mainboard/opencellular/elgon/Kconfig M src/mainboard/opencellular/elgon/Makefile.inc A src/mainboard/opencellular/elgon/reset.c 7 files changed, 327 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/46/29946/1
diff --git a/src/ec/opencellular/tiva/Kconfig b/src/ec/opencellular/tiva/Kconfig new file mode 100644 index 0000000..a56b06a --- /dev/null +++ b/src/ec/opencellular/tiva/Kconfig @@ -0,0 +1,5 @@ +config EC_OPENCELLULAR_TIVA + bool + depends on CONSOLE_SERIAL + help + OpenCellular Tiva EC protocol driver over serial. diff --git a/src/ec/opencellular/tiva/Makefile.inc b/src/ec/opencellular/tiva/Makefile.inc new file mode 100644 index 0000000..fadaf44 --- /dev/null +++ b/src/ec/opencellular/tiva/Makefile.inc @@ -0,0 +1,9 @@ +ifeq ($(CONFIG_EC_OPENCELLULAR_TIVA),y) + +bootblock-y += ec.c +romstage-y += ec.c +verstage-y += ec.c +postcar-y += ec.c +ramstage-y += ec.c + +endif diff --git a/src/ec/opencellular/tiva/ec.c b/src/ec/opencellular/tiva/ec.c new file mode 100644 index 0000000..d46f284 --- /dev/null +++ b/src/ec/opencellular/tiva/ec.c @@ -0,0 +1,203 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2018 Facebook, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <console/console.h> +#include <string.h> +#include <console/uart.h> +#include "ec.h" + +/* Packet definition as per OpenCellular Management Protocol */ +enum ec_iface { + EC_UART = 1, + EC_ETHERNET = 2, + EC_SBD = 3, + EC_USB = 4, +}; + +struct ec_header { + uint8_t sof; + uint8_t len; + uint8_t iface; + uint32_t seq; + uint32_t ts; +} __packed; + +struct ec_payload { + uint8_t subsystem; + uint8_t component_id; + uint8_t message_type; + uint8_t action_type; + uint16_t parameter_info; + uint8_t message[48]; +} __packed; + +struct ec_packet { + struct ec_header hdr; + struct ec_payload pld; +} __packed; + +struct ec_msg { + union { + struct ec_packet p; + uint8_t raw[sizeof(struct ec_packet)]; + }; +}; + +/* Create a packet to BMS:TIVA from given arguments */ +static size_t ec_create_tx_msg(struct ec_packet *p, + const enum ec_message_type mt, + const enum ec_action_type at, + const uint8_t parameter_info, + const enum ec_iface iface, + const uint8_t *data_in, + const uint8_t data_in_len) +{ + size_t len = sizeof(*p) - sizeof(p->pld.message) + data_in_len; + + p->pld.subsystem = EC_BMS; + p->pld.component_id = EC_TIVA; + p->pld.message_type = mt; + p->pld.action_type = at; + p->pld.parameter_info = parameter_info; + if (data_in) + memcpy(&p->pld.message, data_in, data_in_len); + + p->hdr.iface = iface; + p->hdr.len = data_in_len; + p->hdr.sof = 0x55; + p->hdr.ts = 0; /* Reserved for future use */ + p->hdr.seq = 0; /* Reserved for future use */ + + return len; +} + +/* Returns true on valid header */ +static bool ec_verify_rx_hdr(struct ec_packet *p, const enum ec_iface iface) +{ + if (p->hdr.sof != 0x55) + return false; + if (p->hdr.len > 48) + return false; + if (p->hdr.iface != iface) + return false; + return true; +} + + +/* Returns true on valid packet */ +static bool ec_verify_rx_msg(struct ec_packet *p, const enum ec_iface iface) +{ + if (!ec_verify_rx_hdr(p, iface)) + return false; + if (p->pld.subsystem != EC_BMS) + return false; + if (p->pld.component_id != EC_TIVA) + return false; + + return true; +} + +/** + * Transmits a packet to EC using one of the UARTs. + * The function is blocking until a data has been transmitted. + * + * All pointers can be NULL if not required. + * + * @param uart_idx The UART connected to EC + * @param mt Message type to transmit + * @param at Action type to transmit + * @param parameter_info Parameter info to transmit + * @param data_in Buffer to data to transmit + * @param data_in_len Length of data to transmit + * + * @return Zero on success, negative on failure + */ +int ec_transmit_msg_uart(const uint8_t uart_idx, + const enum ec_message_type mt, + const enum ec_action_type at, + const uint8_t parameter_info, + const uint8_t *data_in, + const uint8_t data_in_len) +{ + struct ec_msg msg; + + size_t len = ec_create_tx_msg(&msg.p, mt, at, parameter_info, EC_UART, + data_in, data_in_len); + + for (size_t i = 0; i < len; i++) + uart_tx_byte(uart_idx, msg.raw[i]); + + return 0; +} + +/** + * Receives a packet from EC using one of the UARTs. + * The function is blocking and waits for a SOF byte. + * + * The caller must provide a data buffer of size 48. + * If no data buffer is provided the received data (if any) is dropped. + * + * All pointers can be NULL if not required. + * + * @param uart_idx The UART connected to EC + * @param mt Receveived message type + * @param at Receveived action type + * @param parameter_info Receveived parameter info + * @param data_out Buffer to place receveived data + * @param data_out_len Length of received data + * + * @return Zero on success, negative on failure + */ +int ec_receive_msg_uart(const uint8_t uart_idx, + enum ec_message_type *mt, + enum ec_action_type *at, + uint8_t *parameter_info, + uint8_t *data_out, + uint8_t *data_out_len) +{ + struct ec_msg msg; + + do { + msg.raw[0] = uart_rx_byte(uart_idx); + } while (msg.raw[0] != 0x55); + + for (size_t i = 0; i < sizeof(struct ec_header); i++) + msg.raw[i] = uart_rx_byte(uart_idx); + + if (!ec_verify_rx_hdr(&msg.p, EC_UART)) + return -1; + + const size_t len = sizeof(msg.p.pld) - sizeof(msg.p.pld.message) + + msg.p.hdr.len; + + for (size_t i = 0; i < len; i++) + msg.raw[sizeof(struct ec_header) + i] = uart_rx_byte(uart_idx); + + if (!ec_verify_rx_msg(&msg.p, EC_UART)) + return -1; + + if (mt) + *mt = msg.p.pld.message_type; + if (at) + *at = msg.p.pld.action_type; + if (parameter_info) + *parameter_info = msg.p.pld.parameter_info; + if (data_out) + memcpy(data_out, msg.p.pld.message, msg.p.hdr.len); + if (*data_out_len) + *data_out_len = msg.p.hdr.len; + return 0; +} + diff --git a/src/ec/opencellular/tiva/ec.h b/src/ec/opencellular/tiva/ec.h new file mode 100644 index 0000000..7728f7e --- /dev/null +++ b/src/ec/opencellular/tiva/ec.h @@ -0,0 +1,77 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2018 Facebook, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <types.h> + +/** + * Command interface as per OpenCellular Management Protocol: + * + * This protocol allows to handle all the configuration, status and alert + * processing through a ‘Request-Response’ mechanism between host and MCU. + */ + +enum ec_subsystem { + EC_SYSTEM = 0, + EC_POWER = 1, + EC_BMS = 2, + EC_HCI = 3, + EC_ETHERNET_SWITCH = 4, + EC_OBC = 5, + EC_GPP = 6, + EC_SDR = 7, + EC_RF = 8, + EC_SYNC = 9, + EC_TEST_MODULE = 10, + EC_WATCHDOG = 11, + EC_ALERT_MANAGER = 12 +}; + +/* We only support subsystem BMS here */ +enum ec_subsystem_bms { + EC_ALL = 0, + EC_TIVA = 1, +}; + +enum ec_message_type { + EC_CONFIG = 1, + EC_STATUS = 2, + EC_ALERT = 3, + EC_COMMAND = 4, +}; + +enum ec_action_type { + EC_GET = 1, + EC_SET = 2, + EC_REPLY = 3, + EC_ACTIVE = 4, + EC_CLEAR = 5, + EC_RESET = 6, + EC_ENABLE = 7, + EC_DISABLE = 8, +}; + +int ec_transmit_msg_uart(const uint8_t uart_idx, + const enum ec_message_type mt, + const enum ec_action_type at, + const uint8_t parameter_info, + const uint8_t *data_in, + const uint8_t data_in_len); + +int ec_receive_msg_uart(const uint8_t uart_idx, + enum ec_message_type *mt, + enum ec_action_type *at, + uint8_t *parameter_info, + uint8_t *data_out, + uint8_t *data_out_len); diff --git a/src/mainboard/opencellular/elgon/Kconfig b/src/mainboard/opencellular/elgon/Kconfig index 3ba2a60..b9f93ab 100644 --- a/src/mainboard/opencellular/elgon/Kconfig +++ b/src/mainboard/opencellular/elgon/Kconfig @@ -25,7 +25,7 @@ select SPI_FLASH_WINBOND select MAINBOARD_HAS_I2C_TPM_GENERIC select MAINBOARD_HAS_TPM1 - select MISSING_BOARD_RESET + select EC_OPENCELLULAR_TIVA
config VBOOT select VBOOT_NO_BOARD_SUPPORT diff --git a/src/mainboard/opencellular/elgon/Makefile.inc b/src/mainboard/opencellular/elgon/Makefile.inc index 343a52e..3440833 100644 --- a/src/mainboard/opencellular/elgon/Makefile.inc +++ b/src/mainboard/opencellular/elgon/Makefile.inc @@ -16,16 +16,20 @@ bootblock-y += bootblock.c bootblock-y += memlayout.ld bootblock-y += death.c +bootblock-y += reset.c
romstage-y += memlayout.ld romstage-y += romstage.c romstage-y += bdk_devicetree.c romstage-y += death.c +romstage-y += reset.c
ramstage-y += mainboard.c ramstage-y += memlayout.ld ramstage-y += bdk_devicetree.c ramstage-y += death.c +ramstage-y += reset.c
verstage-y += memlayout.ld verstage-y += death.c +verstage-y += reset.c diff --git a/src/mainboard/opencellular/elgon/reset.c b/src/mainboard/opencellular/elgon/reset.c new file mode 100644 index 0000000..d73d9af --- /dev/null +++ b/src/mainboard/opencellular/elgon/reset.c @@ -0,0 +1,28 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2018 Facebook, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <ec/opencellular/tiva/ec.h> +#include <reset.h> +#include <soc/gpio.h> +#include "mainboard.h" + +void do_board_reset(void) +{ + /* Route UART0 to EC */ + gpio_output(ELGON_GPIO_UART_SEL, 1); + + ec_transmit_msg_uart(0, EC_COMMAND, EC_RESET, 0, NULL, 0); + /* FIXME: Is there a response ? */ +}