summaryrefslogtreecommitdiff
path: root/drivers/staging/greybus/uart.c
diff options
context:
space:
mode:
authorBryan O'Donoghue <bryan.odonoghue@linaro.org>2015-06-29 18:09:14 +0100
committerGreg Kroah-Hartman <gregkh@google.com>2015-06-30 19:34:47 -0700
commit4c025cf4168fe679b8a56eed210349458a142d07 (patch)
tree699efcb02b1d8fa45a84019647eb7ae59de7b38f /drivers/staging/greybus/uart.c
parent802362d4a621a03b394b3082b40e5471bf5268ad (diff)
greybus: uart: Add support for UART error signals
After reviewing the UART specification for greybus break, parity, framing and over-run errors were moved to the receive-data message. This patch implements that specification change in the UART protocol driver. Matching code in gbsim has been tested with this change. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers/staging/greybus/uart.c')
-rw-r--r--drivers/staging/greybus/uart.c59
1 files changed, 40 insertions, 19 deletions
diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c
index 3b06cd46694b..73e3c992e103 100644
--- a/drivers/staging/greybus/uart.c
+++ b/drivers/staging/greybus/uart.c
@@ -70,35 +70,56 @@ static atomic_t reference_count = ATOMIC_INIT(0);
/* Define get_version() routine */
define_get_version(gb_tty, UART);
+static int gb_uart_receive_data(struct gb_tty *gb_tty,
+ struct gb_connection *connection,
+ struct gb_uart_recv_data_request *receive_data)
+{
+ struct tty_port *port = &gb_tty->port;
+ u16 recv_data_size;
+ int count;
+ unsigned long tty_flags = TTY_NORMAL;
+
+ count = gb_tty->buffer_payload_max - sizeof(*receive_data);
+ recv_data_size = le16_to_cpu(receive_data->size);
+ if (!recv_data_size || recv_data_size > count)
+ return -EINVAL;
+
+ if (receive_data->flags) {
+ if (receive_data->flags & GB_UART_RECV_FLAG_BREAK)
+ tty_flags = TTY_BREAK;
+ else if (receive_data->flags & GB_UART_RECV_FLAG_PARITY)
+ tty_flags = TTY_PARITY;
+ else if (receive_data->flags & GB_UART_RECV_FLAG_FRAMING)
+ tty_flags = TTY_FRAME;
+
+ /* overrun is special, not associated with a char */
+ if (receive_data->flags & GB_UART_RECV_FLAG_OVERRUN)
+ tty_insert_flip_char(port, 0, TTY_OVERRUN);
+ }
+ count = tty_insert_flip_string_fixed_flag(port, receive_data->data,
+ tty_flags, recv_data_size);
+ if (count != recv_data_size) {
+ dev_err(&connection->dev,
+ "UART: RX 0x%08x bytes only wrote 0x%08x\n",
+ recv_data_size, count);
+ }
+ if (count)
+ tty_flip_buffer_push(port);
+ return 0;
+}
+
static int gb_uart_request_recv(u8 type, struct gb_operation *op)
{
struct gb_connection *connection = op->connection;
struct gb_tty *gb_tty = connection->private;
struct gb_message *request = op->request;
- struct gb_uart_recv_data_request *receive_data;
struct gb_uart_serial_state_request *serial_state;
- struct tty_port *port = &gb_tty->port;
- u16 recv_data_size;
- int count;
int ret = 0;
switch (type) {
case GB_UART_TYPE_RECEIVE_DATA:
- receive_data = request->payload;
- count = gb_tty->buffer_payload_max - sizeof(*receive_data);
- recv_data_size = le16_to_cpu(receive_data->size);
- if (!recv_data_size || recv_data_size > count)
- return -EINVAL;
-
- count = tty_insert_flip_string(port, receive_data->data,
- recv_data_size);
- if (count != recv_data_size) {
- dev_err(&connection->dev,
- "UART: RX 0x%08x bytes only wrote 0x%08x\n",
- recv_data_size, count);
- }
- if (count)
- tty_flip_buffer_push(port);
+ ret = gb_uart_receive_data(gb_tty, connection,
+ request->payload);
break;
case GB_UART_TYPE_SERIAL_STATE:
serial_state = request->payload;