summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMary Ruthven <mruthven@chromium.org>2016-03-30 16:24:37 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-04-07 13:00:39 -0700
commit8264b91a5b6769d3ed42849befcdcb4e3cbe3448 (patch)
treee61e57669ecd962f89c86abc051c4950ecd7de8c
parentfa643a9fc754e6a5c18181ecb928fa9a5c12e7ae (diff)
downloadchrome-ec-8264b91a5b6769d3ed42849befcdcb4e3cbe3448.tar.gz
cr50: export AP and EC UART through USB
Add support for exporting the EC and AP UARTs to USB. BUG=chrome-os-partner:50702 BRANCH=none TEST=Verify the EC and AP UARTs are forwarded to the EC and AP endpoints Change-Id: Icaeb7929dbaaf71a40f0752aa6cb5a2319373651 Signed-off-by: Mary Ruthven <mruthven@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/336317 Tested-by: Bill Richardson <wfrichar@chromium.org> Reviewed-by: Bill Richardson <wfrichar@chromium.org>
-rw-r--r--board/cr50/board.c2
-rw-r--r--board/cr50/board.h4
-rw-r--r--chip/g/build.mk1
-rw-r--r--chip/g/uart.c8
-rw-r--r--chip/g/uartn.c8
-rw-r--r--chip/g/usart.c125
-rw-r--r--chip/g/usart.h69
7 files changed, 212 insertions, 5 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c
index 3f951e8b41..702e35f84d 100644
--- a/board/cr50/board.c
+++ b/board/cr50/board.c
@@ -116,6 +116,8 @@ const void * const usb_strings[] = {
[USB_STR_CONSOLE_NAME] = USB_STRING_DESC("Shell"),
[USB_STR_BLOB_NAME] = USB_STRING_DESC("Blob"),
[USB_STR_HID_NAME] = USB_STRING_DESC("PokeyPokey"),
+ [USB_STR_AP_NAME] = USB_STRING_DESC("AP"),
+ [USB_STR_EC_NAME] = USB_STRING_DESC("EC"),
};
BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT);
#endif
diff --git a/board/cr50/board.h b/board/cr50/board.h
index 83a370b23e..5781e9a22b 100644
--- a/board/cr50/board.h
+++ b/board/cr50/board.h
@@ -70,6 +70,8 @@ enum usb_strings {
USB_STR_CONSOLE_NAME,
USB_STR_BLOB_NAME,
USB_STR_HID_NAME,
+ USB_STR_AP_NAME,
+ USB_STR_EC_NAME,
USB_STR_COUNT
};
@@ -89,8 +91,6 @@ enum usb_strings {
/* UART indexes (use define rather than enum to expand them) */
#define UART_CR50 0
-#define UART_AP 1
-#define UART_EC 2
#define UARTN UART_CR50
diff --git a/chip/g/build.mk b/chip/g/build.mk
index e3f283c97f..959a0f51cf 100644
--- a/chip/g/build.mk
+++ b/chip/g/build.mk
@@ -49,6 +49,7 @@ chip-$(CONFIG_USB_CONSOLE)+=usb_console.o
chip-$(CONFIG_USB_HID)+=usb_hid.o
chip-$(CONFIG_USB_BLOB)+=blob.o
chip-$(CONFIG_STREAM_USB)+=usb-stream.o
+chip-$(CONFIG_STREAM_USART)+=usart.o
chip-$(CONFIG_LOW_POWER_IDLE)+=idle.o
diff --git a/chip/g/uart.c b/chip/g/uart.c
index 0e1534f1db..24081fbaeb 100644
--- a/chip/g/uart.c
+++ b/chip/g/uart.c
@@ -111,9 +111,11 @@ void uart_init(void)
/* Initialize the Cr50 UART */
uartn_init(UARTN);
-#if USE_UART_INTERRUPTS
- /* Enable interrupts for UART0 only */
- uart_enable_interrupt();
+#ifdef UART_AP
+ uartn_init(UART_AP);
+#endif
+#ifdef UART_EC
+ uartn_init(UART_EC);
#endif
done_uart_init_yet = 1;
diff --git a/chip/g/uartn.c b/chip/g/uartn.c
index 343f5dc981..eac35d1577 100644
--- a/chip/g/uartn.c
+++ b/chip/g/uartn.c
@@ -12,6 +12,9 @@
#include "uart.h"
#include "util.h"
+#define USE_UART_INTERRUPTS (!(defined(CONFIG_CUSTOMIZED_RO) && \
+ defined(SECTION_IS_RO)))
+
struct uartn_interrupts {
int tx_int;
int rx_int;
@@ -134,4 +137,9 @@ void uartn_init(int uart)
/* Note: doesn't do anything unless turned on in NVIC */
GR_UART_ICTRL(uart) = 0x02;
+#if USE_UART_INTERRUPTS
+ /* Enable interrupts for UART */
+ uartn_enable_interrupt(uart);
+#endif
+
}
diff --git a/chip/g/usart.c b/chip/g/usart.c
new file mode 100644
index 0000000000..0d22b94bfc
--- /dev/null
+++ b/chip/g/usart.c
@@ -0,0 +1,125 @@
+/* Copyright 2016 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.
+ */
+
+#include "queue.h"
+#include "queue_policies.h"
+#include "uartn.h"
+#include "usart.h"
+#include "usb-stream.h"
+
+#define USE_UART_INTERRUPTS (!(defined(CONFIG_CUSTOMIZED_RO) && \
+defined(SECTION_IS_RO)))
+#define QUEUE_SIZE 64
+
+struct usb_stream_config const ap_usb;
+struct usart_config const ap_uart;
+
+struct usb_stream_config const ec_usb;
+struct usart_config const ec_uart;
+
+static struct queue const ap_uart_to_usb =
+ QUEUE_DIRECT(QUEUE_SIZE, uint8_t, ap_uart.producer, ap_usb.consumer);
+static struct queue const ap_usb_to_uart =
+ QUEUE_DIRECT(QUEUE_SIZE, uint8_t, ap_usb.producer, ap_uart.consumer);
+
+static struct queue const ec_uart_to_usb =
+ QUEUE_DIRECT(QUEUE_SIZE, uint8_t, ec_uart.producer, ec_usb.consumer);
+static struct queue const ec_usb_to_uart =
+ QUEUE_DIRECT(QUEUE_SIZE, uint8_t, ec_usb.producer, ec_uart.consumer);
+
+struct usart_config const ap_uart = USART_CONFIG(UART_AP,
+ ap_uart_to_usb,
+ ap_usb_to_uart);
+struct usart_config const ec_uart = USART_CONFIG(UART_EC,
+ ec_uart_to_usb,
+ ec_usb_to_uart);
+USB_STREAM_CONFIG(ap_usb,
+ USB_IFACE_AP,
+ USB_STR_AP_NAME,
+ USB_EP_AP,
+ USB_MAX_PACKET_SIZE,
+ USB_MAX_PACKET_SIZE,
+ ap_usb_to_uart,
+ ap_uart_to_usb)
+USB_STREAM_CONFIG(ec_usb,
+ USB_IFACE_EC,
+ USB_STR_EC_NAME,
+ USB_EP_EC,
+ USB_MAX_PACKET_SIZE,
+ USB_MAX_PACKET_SIZE,
+ ec_usb_to_uart,
+ ec_uart_to_usb)
+
+void get_data_from_usb(struct usart_config const *config)
+{
+ struct queue const *uart_out = config->consumer.queue;
+ int c;
+
+ /* Copy output from buffer until TX fifo full or output buffer empty */
+ while (queue_count(uart_out) && QUEUE_REMOVE_UNITS(uart_out, &c, 1))
+ uartn_write_char(config->uart, c);
+
+ /* If output buffer is empty, disable transmit interrupt */
+ if (!queue_count(uart_out))
+ uartn_tx_stop(config->uart);
+}
+
+void send_data_to_usb(struct usart_config const *config)
+{
+ struct queue const *uart_in = config->producer.queue;
+
+ /* Copy input from buffer until RX fifo empty or the queue is full */
+ while (uartn_rx_available(config->uart) && queue_space(uart_in)) {
+ int c = uartn_read_char(config->uart);
+
+ QUEUE_ADD_UNITS(uart_in, &c, 1);
+ }
+}
+
+static void uart_read(struct producer const *producer, size_t count)
+{
+}
+
+static void uart_written(struct consumer const *consumer, size_t count)
+{
+ struct usart_config const *config =
+ DOWNCAST(consumer, struct usart_config, consumer);
+
+ if (uartn_tx_ready(config->uart), queue_count(consumer->queue))
+ uartn_tx_start(config->uart);
+}
+
+static void uart_flush(struct consumer const *consumer)
+{
+ struct usart_config const *config =
+ DOWNCAST(consumer, struct usart_config, consumer);
+
+ uartn_tx_flush(config->uart);
+}
+
+struct producer_ops const uart_producer_ops = {
+ .read = uart_read,
+};
+
+struct consumer_ops const uart_consumer_ops = {
+ .written = uart_written,
+ .flush = uart_flush,
+};
+
+#if USE_UART_INTERRUPTS
+/*
+ * Interrupt handlers for UART1
+ */
+CONFIGURE_INTERRUPTS(ap_uart,
+ GC_IRQNUM_UART1_RXINT,
+ GC_IRQNUM_UART1_TXINT)
+
+/*
+ * Interrupt handlers for UART2
+ */
+CONFIGURE_INTERRUPTS(ec_uart,
+ GC_IRQNUM_UART2_RXINT,
+ GC_IRQNUM_UART2_TXINT)
+#endif
diff --git a/chip/g/usart.h b/chip/g/usart.h
new file mode 100644
index 0000000000..79616a48e0
--- /dev/null
+++ b/chip/g/usart.h
@@ -0,0 +1,69 @@
+/* Copyright 2016 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.
+ */
+
+#include "consumer.h"
+#include "producer.h"
+#include "registers.h"
+#include "task.h"
+
+#ifndef __CROS_FORWARD_UART_H
+#define __CROS_FORWARD_UART_H
+
+struct usart_config {
+ int uart;
+
+ struct producer const producer;
+ struct consumer const consumer;
+};
+
+extern struct consumer_ops const uart_consumer_ops;
+extern struct producer_ops const uart_producer_ops;
+#define CONFIGURE_INTERRUPTS(NAME, \
+ RXINT, \
+ TXINT) \
+ void CONCAT2(NAME, _rx_int_)(void); \
+ void CONCAT2(NAME, _tx_int_)(void); \
+ DECLARE_IRQ(RXINT, CONCAT2(NAME, _rx_int_), 1); \
+ DECLARE_IRQ(TXINT, CONCAT2(NAME, _tx_int_), 1); \
+ void CONCAT2(NAME, _tx_int_)(void) \
+ { \
+ /* Clear transmit interrupt status */ \
+ GR_UART_ISTATECLR(NAME.uart) = \
+ GC_UART_ISTATECLR_TX_MASK; \
+ /* Fill output FIFO */ \
+ get_data_from_usb(&NAME); \
+ } \
+ void CONCAT2(NAME, _rx_int_)(void) \
+ { \
+ /* Clear receive interrupt status */ \
+ GR_UART_ISTATECLR(NAME.uart) = \
+ GC_UART_ISTATECLR_RX_MASK; \
+ /* Read input FIFO until empty */ \
+ send_data_to_usb(&NAME); \
+ }
+
+
+#define USART_CONFIG(UART, \
+ RX_QUEUE, \
+ TX_QUEUE) \
+ ((struct usart_config const) { \
+ .uart = UART, \
+ .consumer = { \
+ .queue = &TX_QUEUE, \
+ .ops = &uart_consumer_ops, \
+ }, \
+ .producer = { \
+ .queue = &RX_QUEUE, \
+ .ops = &uart_producer_ops, \
+ }, \
+ })
+
+
+/* Read data from UART and add it to the producer queue */
+void send_data_to_usb(struct usart_config const *config);
+
+/* Read data from the consumer queue and send it to the UART */
+void get_data_from_usb(struct usart_config const *config);
+#endif /* __CROS_FORWARD_UART_H */