]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
greybus: uart: Add support for UART error signals
authorBryan O'Donoghue <bryan.odonoghue@linaro.org>
Mon, 29 Jun 2015 17:09:14 +0000 (18:09 +0100)
committerGreg Kroah-Hartman <gregkh@google.com>
Wed, 1 Jul 2015 02:34:47 +0000 (19:34 -0700)
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>
drivers/staging/greybus/uart.c

index 3b06cd46694b82967d8296e3459cb5ddf905fdaa..73e3c992e103e6798e9fd29c3223204d09374386 100644 (file)
@@ -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;