diff options
author | Mary Ruthven <mruthven@chromium.org> | 2016-03-30 16:24:37 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-04-07 13:00:39 -0700 |
commit | 8264b91a5b6769d3ed42849befcdcb4e3cbe3448 (patch) | |
tree | e61e57669ecd962f89c86abc051c4950ecd7de8c /chip | |
parent | fa643a9fc754e6a5c18181ecb928fa9a5c12e7ae (diff) | |
download | chrome-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>
Diffstat (limited to 'chip')
-rw-r--r-- | chip/g/build.mk | 1 | ||||
-rw-r--r-- | chip/g/uart.c | 8 | ||||
-rw-r--r-- | chip/g/uartn.c | 8 | ||||
-rw-r--r-- | chip/g/usart.c | 125 | ||||
-rw-r--r-- | chip/g/usart.h | 69 |
5 files changed, 208 insertions, 3 deletions
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 */ |