^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Driver for GRLIB serial ports (APBUART)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Based on linux/drivers/serial/amba.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2000 Deep Blue Solutions Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2003 Konrad Eisele <eiselekd@web.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (C) 2006 Daniel Hellstrom <daniel@gaisler.com>, Aeroflex Gaisler AB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (C) 2008 Gilead Kutnick <kutnickg@zin-tech.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Copyright (C) 2009 Kristoffer Glembo <kristoffer@gaisler.com>, Aeroflex Gaisler AB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/tty.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/tty_flip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/serial.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/console.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/sysrq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/kthread.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/serial_core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include "apbuart.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define SERIAL_APBUART_MAJOR TTY_MAJOR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define SERIAL_APBUART_MINOR 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define UART_DUMMY_RSR_RX 0x8000 /* for ignore all read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static void apbuart_tx_chars(struct uart_port *port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static void apbuart_stop_tx(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) unsigned int cr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) cr = UART_GET_CTRL(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) cr &= ~UART_CTRL_TI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) UART_PUT_CTRL(port, cr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static void apbuart_start_tx(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) unsigned int cr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) cr = UART_GET_CTRL(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) cr |= UART_CTRL_TI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) UART_PUT_CTRL(port, cr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (UART_GET_STATUS(port) & UART_STATUS_THE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) apbuart_tx_chars(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static void apbuart_stop_rx(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) unsigned int cr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) cr = UART_GET_CTRL(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) cr &= ~(UART_CTRL_RI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) UART_PUT_CTRL(port, cr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static void apbuart_rx_chars(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) unsigned int status, ch, rsr, flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) unsigned int max_chars = port->fifosize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) status = UART_GET_STATUS(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) while (UART_RX_DATA(status) && (max_chars--)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) ch = UART_GET_CHAR(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) flag = TTY_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) port->icount.rx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) rsr = UART_GET_STATUS(port) | UART_DUMMY_RSR_RX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) UART_PUT_STATUS(port, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (rsr & UART_STATUS_ERR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (rsr & UART_STATUS_BR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) rsr &= ~(UART_STATUS_FE | UART_STATUS_PE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) port->icount.brk++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (uart_handle_break(port))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) goto ignore_char;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) } else if (rsr & UART_STATUS_PE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) port->icount.parity++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) } else if (rsr & UART_STATUS_FE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) port->icount.frame++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (rsr & UART_STATUS_OE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) port->icount.overrun++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) rsr &= port->read_status_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (rsr & UART_STATUS_PE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) flag = TTY_PARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) else if (rsr & UART_STATUS_FE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) flag = TTY_FRAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (uart_handle_sysrq_char(port, ch))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) goto ignore_char;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) uart_insert_char(port, rsr, UART_STATUS_OE, ch, flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) ignore_char:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) status = UART_GET_STATUS(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) spin_unlock(&port->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) tty_flip_buffer_push(&port->state->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) spin_lock(&port->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static void apbuart_tx_chars(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) struct circ_buf *xmit = &port->state->xmit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (port->x_char) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) UART_PUT_CHAR(port, port->x_char);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) port->icount.tx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) port->x_char = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) apbuart_stop_tx(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /* amba: fill FIFO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) count = port->fifosize >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) port->icount.tx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (uart_circ_empty(xmit))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) } while (--count > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) uart_write_wakeup(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (uart_circ_empty(xmit))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) apbuart_stop_tx(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) static irqreturn_t apbuart_int(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) struct uart_port *port = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) unsigned int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) spin_lock(&port->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) status = UART_GET_STATUS(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (status & UART_STATUS_DR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) apbuart_rx_chars(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (status & UART_STATUS_THE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) apbuart_tx_chars(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) spin_unlock(&port->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) static unsigned int apbuart_tx_empty(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) unsigned int status = UART_GET_STATUS(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return status & UART_STATUS_THE ? TIOCSER_TEMT : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static unsigned int apbuart_get_mctrl(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /* The GRLIB APBUART handles flow control in hardware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static void apbuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) /* The GRLIB APBUART handles flow control in hardware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static void apbuart_break_ctl(struct uart_port *port, int break_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /* We don't support sending break */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static int apbuart_startup(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) unsigned int cr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /* Allocate the IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) retval = request_irq(port->irq, apbuart_int, 0, "apbuart", port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /* Finally, enable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) cr = UART_GET_CTRL(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) UART_PUT_CTRL(port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) cr | UART_CTRL_RE | UART_CTRL_TE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) UART_CTRL_RI | UART_CTRL_TI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static void apbuart_shutdown(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) unsigned int cr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /* disable all interrupts, disable the port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) cr = UART_GET_CTRL(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) UART_PUT_CTRL(port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) cr & ~(UART_CTRL_RE | UART_CTRL_TE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) UART_CTRL_RI | UART_CTRL_TI));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) /* Free the interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) free_irq(port->irq, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static void apbuart_set_termios(struct uart_port *port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) struct ktermios *termios, struct ktermios *old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) unsigned int cr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) unsigned int baud, quot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) /* Ask the core to calculate the divisor for us. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (baud == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) panic("invalid baudrate %i\n", port->uartclk / 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) /* uart_get_divisor calc a *16 uart freq, apbuart is *8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) quot = (uart_get_divisor(port, baud)) * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) cr = UART_GET_CTRL(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) cr &= ~(UART_CTRL_PE | UART_CTRL_PS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (termios->c_cflag & PARENB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) cr |= UART_CTRL_PE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if ((termios->c_cflag & PARODD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) cr |= UART_CTRL_PS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /* Enable flow control. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (termios->c_cflag & CRTSCTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) cr |= UART_CTRL_FL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) spin_lock_irqsave(&port->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) /* Update the per-port timeout. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) uart_update_timeout(port, termios->c_cflag, baud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) port->read_status_mask = UART_STATUS_OE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (termios->c_iflag & INPCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) port->read_status_mask |= UART_STATUS_FE | UART_STATUS_PE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) /* Characters to ignore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) port->ignore_status_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (termios->c_iflag & IGNPAR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) port->ignore_status_mask |= UART_STATUS_FE | UART_STATUS_PE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /* Ignore all characters if CREAD is not set. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if ((termios->c_cflag & CREAD) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) port->ignore_status_mask |= UART_DUMMY_RSR_RX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) /* Set baud rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) quot -= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) UART_PUT_SCAL(port, quot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) UART_PUT_CTRL(port, cr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) spin_unlock_irqrestore(&port->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) static const char *apbuart_type(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return port->type == PORT_APBUART ? "GRLIB/APBUART" : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) static void apbuart_release_port(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) release_mem_region(port->mapbase, 0x100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) static int apbuart_request_port(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return request_mem_region(port->mapbase, 0x100, "grlib-apbuart")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) != NULL ? 0 : -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) /* Configure/autoconfigure the port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) static void apbuart_config_port(struct uart_port *port, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (flags & UART_CONFIG_TYPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) port->type = PORT_APBUART;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) apbuart_request_port(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) /* Verify the new serial_struct (for TIOCSSERIAL) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) static int apbuart_verify_port(struct uart_port *port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) struct serial_struct *ser)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (ser->type != PORT_UNKNOWN && ser->type != PORT_APBUART)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (ser->irq < 0 || ser->irq >= NR_IRQS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (ser->baud_base < 9600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) static const struct uart_ops grlib_apbuart_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) .tx_empty = apbuart_tx_empty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) .set_mctrl = apbuart_set_mctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) .get_mctrl = apbuart_get_mctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) .stop_tx = apbuart_stop_tx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) .start_tx = apbuart_start_tx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) .stop_rx = apbuart_stop_rx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) .break_ctl = apbuart_break_ctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) .startup = apbuart_startup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) .shutdown = apbuart_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) .set_termios = apbuart_set_termios,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) .type = apbuart_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) .release_port = apbuart_release_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) .request_port = apbuart_request_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) .config_port = apbuart_config_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) .verify_port = apbuart_verify_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) static struct uart_port grlib_apbuart_ports[UART_NR];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) static struct device_node *grlib_apbuart_nodes[UART_NR];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) static int apbuart_scan_fifo_size(struct uart_port *port, int portnumber)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) int ctrl, loop = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) int fifosize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) ctrl = UART_GET_CTRL(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * Enable the transceiver and wait for it to be ready to send data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * Clear interrupts so that this process will not be externally
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * interrupted in the middle (which can cause the transceiver to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * drain prematurely).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) UART_PUT_CTRL(port, ctrl | UART_CTRL_TE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) while (!UART_TX_READY(UART_GET_STATUS(port)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) loop++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) * Disable the transceiver so data isn't actually sent during the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) * actual test.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) UART_PUT_CTRL(port, ctrl & ~(UART_CTRL_TE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) fifosize = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) UART_PUT_CHAR(port, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) * So long as transmitting a character increments the tranceivier FIFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * length the FIFO must be at least that big. These bytes will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * automatically drain off of the FIFO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) status = UART_GET_STATUS(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) while (((status >> 20) & 0x3F) == fifosize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) fifosize++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) UART_PUT_CHAR(port, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) status = UART_GET_STATUS(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) fifosize--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) UART_PUT_CTRL(port, ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (fifosize == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) fifosize = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return fifosize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) static void apbuart_flush_fifo(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) for (i = 0; i < port->fifosize; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) UART_GET_CHAR(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) /* ======================================================================== */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) /* Console driver, if enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) /* ======================================================================== */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) #ifdef CONFIG_SERIAL_GRLIB_GAISLER_APBUART_CONSOLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) static void apbuart_console_putchar(struct uart_port *port, int ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) unsigned int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) status = UART_GET_STATUS(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) } while (!UART_TX_READY(status));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) UART_PUT_CHAR(port, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) apbuart_console_write(struct console *co, const char *s, unsigned int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) struct uart_port *port = &grlib_apbuart_ports[co->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) unsigned int status, old_cr, new_cr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) /* First save the CR then disable the interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) old_cr = UART_GET_CTRL(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) new_cr = old_cr & ~(UART_CTRL_RI | UART_CTRL_TI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) UART_PUT_CTRL(port, new_cr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) uart_console_write(port, s, count, apbuart_console_putchar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) * Finally, wait for transmitter to become empty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) * and restore the TCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) status = UART_GET_STATUS(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) } while (!UART_TX_READY(status));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) UART_PUT_CTRL(port, old_cr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) static void __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) apbuart_console_get_options(struct uart_port *port, int *baud,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) int *parity, int *bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (UART_GET_CTRL(port) & (UART_CTRL_RE | UART_CTRL_TE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) unsigned int quot, status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) status = UART_GET_STATUS(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) *parity = 'n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (status & UART_CTRL_PE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if ((status & UART_CTRL_PS) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) *parity = 'e';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) *parity = 'o';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) *bits = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) quot = UART_GET_SCAL(port) / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) *baud = port->uartclk / (16 * (quot + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) static int __init apbuart_console_setup(struct console *co, char *options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) struct uart_port *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) int baud = 38400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) int bits = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) int parity = 'n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) int flow = 'n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) pr_debug("apbuart_console_setup co=%p, co->index=%i, options=%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) co, co->index, options);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) * Check whether an invalid uart number has been specified, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) * if so, search for the first available port that does have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) * console support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (co->index >= grlib_apbuart_port_nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) co->index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) port = &grlib_apbuart_ports[co->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) spin_lock_init(&port->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) uart_parse_options(options, &baud, &parity, &bits, &flow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) apbuart_console_get_options(port, &baud, &parity, &bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) return uart_set_options(port, co, baud, parity, bits, flow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) static struct uart_driver grlib_apbuart_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) static struct console grlib_apbuart_console = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) .name = "ttyS",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) .write = apbuart_console_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) .device = uart_console_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) .setup = apbuart_console_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) .flags = CON_PRINTBUFFER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) .index = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) .data = &grlib_apbuart_driver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) static int grlib_apbuart_configure(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) static int __init apbuart_console_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (grlib_apbuart_configure())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) register_console(&grlib_apbuart_console);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) console_initcall(apbuart_console_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) #define APBUART_CONSOLE (&grlib_apbuart_console)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) #define APBUART_CONSOLE NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) static struct uart_driver grlib_apbuart_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) .driver_name = "serial",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) .dev_name = "ttyS",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) .major = SERIAL_APBUART_MAJOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) .minor = SERIAL_APBUART_MINOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) .nr = UART_NR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) .cons = APBUART_CONSOLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) /* ======================================================================== */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) /* OF Platform Driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) /* ======================================================================== */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) static int apbuart_probe(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) struct uart_port *port = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) for (i = 0; i < grlib_apbuart_port_nr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (op->dev.of_node == grlib_apbuart_nodes[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) port = &grlib_apbuart_ports[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) port->dev = &op->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) port->irq = op->archdata.irqs[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) uart_add_one_port(&grlib_apbuart_driver, (struct uart_port *) port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) apbuart_flush_fifo((struct uart_port *) port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) printk(KERN_INFO "grlib-apbuart at 0x%llx, irq %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) (unsigned long long) port->mapbase, port->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) static const struct of_device_id apbuart_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) .name = "GAISLER_APBUART",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) .name = "01_00c",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) MODULE_DEVICE_TABLE(of, apbuart_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) static struct platform_driver grlib_apbuart_of_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) .probe = apbuart_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) .name = "grlib-apbuart",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) .of_match_table = apbuart_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) static int __init grlib_apbuart_configure(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) int line = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) for_each_matching_node(np, apbuart_match) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) const int *ampopts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) const u32 *freq_hz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) const struct amba_prom_registers *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) struct uart_port *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) ampopts = of_get_property(np, "ampopts", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (ampopts && (*ampopts == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) continue; /* Ignore if used by another OS instance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) regs = of_get_property(np, "reg", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) /* Frequency of APB Bus is frequency of UART */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) freq_hz = of_get_property(np, "freq", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) if (!regs || !freq_hz || (*freq_hz == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) grlib_apbuart_nodes[line] = np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) addr = regs->phys_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) port = &grlib_apbuart_ports[line];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) port->mapbase = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) port->membase = ioremap(addr, sizeof(struct grlib_apbuart_regs_map));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) port->irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) port->iotype = UPIO_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) port->ops = &grlib_apbuart_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_GRLIB_GAISLER_APBUART_CONSOLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) port->flags = UPF_BOOT_AUTOCONF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) port->line = line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) port->uartclk = *freq_hz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) port->fifosize = apbuart_scan_fifo_size((struct uart_port *) port, line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) line++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) /* We support maximum UART_NR uarts ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (line == UART_NR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) grlib_apbuart_driver.nr = grlib_apbuart_port_nr = line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) return line ? 0 : -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) static int __init grlib_apbuart_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) /* Find all APBUARTS in device the tree and initialize their ports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) ret = grlib_apbuart_configure();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) printk(KERN_INFO "Serial: GRLIB APBUART driver\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) ret = uart_register_driver(&grlib_apbuart_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) printk(KERN_ERR "%s: uart_register_driver failed (%i)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) __FILE__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) ret = platform_driver_register(&grlib_apbuart_of_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) printk(KERN_ERR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) "%s: platform_driver_register failed (%i)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) __FILE__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) uart_unregister_driver(&grlib_apbuart_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) static void __exit grlib_apbuart_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) for (i = 0; i < grlib_apbuart_port_nr; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) uart_remove_one_port(&grlib_apbuart_driver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) &grlib_apbuart_ports[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) uart_unregister_driver(&grlib_apbuart_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) platform_driver_unregister(&grlib_apbuart_of_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) module_init(grlib_apbuart_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) module_exit(grlib_apbuart_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) MODULE_AUTHOR("Aeroflex Gaisler AB");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) MODULE_DESCRIPTION("GRLIB APBUART serial driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) MODULE_VERSION("2.1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) MODULE_LICENSE("GPL");