diff options
-rw-r--r-- | board/cr50/board.c | 2 | ||||
-rw-r--r-- | board/cr50/board.h | 4 | ||||
-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 |
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 */ |