summaryrefslogtreecommitdiff
path: root/chip/g/usart.c
blob: 0d22b94bfc61232432345242de0dd6bb35b75a03 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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