Patrick Rudolph has uploaded this change for review.

View Change

[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 ? */
+}

To view, visit change 29946. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: I67eb4ee8e0ad297a8d1984d55102146688c291fc
Gerrit-Change-Number: 29946
Gerrit-PatchSet: 1
Gerrit-Owner: Patrick Rudolph <patrick.rudolph@9elements.com>
Gerrit-MessageType: newchange