Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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");