summaryrefslogtreecommitdiff
path: root/chip/g/usart.c
diff options
context:
space:
mode:
Diffstat (limited to 'chip/g/usart.c')
-rw-r--r--chip/g/usart.c125
1 files changed, 125 insertions, 0 deletions
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