^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 AMBA serial ports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright 1999 ARM Limited
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2000 Deep Blue Solutions Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * This is a generic driver for ARM AMBA-type serial ports. They
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * have a lot of 16550-like features, but are not register compatible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Note that although they do have CTS, DCD and DSR inputs, they do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * not have an RI input, nor do they have DTR or RTS outputs. If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * required, these have to be supplied via some other means (eg, GPIO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * and hooked into this driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/console.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/sysrq.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/tty.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/tty_flip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/serial_core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/serial.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/amba/bus.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/amba/serial.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define UART_NR 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define SERIAL_AMBA_MAJOR 204
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define SERIAL_AMBA_MINOR 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define SERIAL_AMBA_NR UART_NR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define AMBA_ISR_PASS_LIMIT 256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define UART_RX_DATA(s) (((s) & UART01x_FR_RXFE) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define UART_TX_READY(s) (((s) & UART01x_FR_TXFF) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define UART_DUMMY_RSR_RX 256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define UART_PORT_SIZE 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * We wrap our port structure around the generic uart_port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct uart_amba_port {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct uart_port port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct amba_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct amba_pl010_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) unsigned int old_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static void pl010_stop_tx(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct uart_amba_port *uap =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) container_of(port, struct uart_amba_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) unsigned int cr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) cr = readb(uap->port.membase + UART010_CR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) cr &= ~UART010_CR_TIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) writel(cr, uap->port.membase + UART010_CR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static void pl010_start_tx(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct uart_amba_port *uap =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) container_of(port, struct uart_amba_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) unsigned int cr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) cr = readb(uap->port.membase + UART010_CR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) cr |= UART010_CR_TIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) writel(cr, uap->port.membase + UART010_CR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static void pl010_stop_rx(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct uart_amba_port *uap =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) container_of(port, struct uart_amba_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) unsigned int cr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) cr = readb(uap->port.membase + UART010_CR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) cr &= ~(UART010_CR_RIE | UART010_CR_RTIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) writel(cr, uap->port.membase + UART010_CR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static void pl010_disable_ms(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct uart_amba_port *uap = (struct uart_amba_port *)port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) unsigned int cr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) cr = readb(uap->port.membase + UART010_CR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) cr &= ~UART010_CR_MSIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) writel(cr, uap->port.membase + UART010_CR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static void pl010_enable_ms(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct uart_amba_port *uap =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) container_of(port, struct uart_amba_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) unsigned int cr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) cr = readb(uap->port.membase + UART010_CR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) cr |= UART010_CR_MSIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) writel(cr, uap->port.membase + UART010_CR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static void pl010_rx_chars(struct uart_amba_port *uap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) unsigned int status, ch, flag, rsr, max_count = 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) status = readb(uap->port.membase + UART01x_FR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) while (UART_RX_DATA(status) && max_count--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) ch = readb(uap->port.membase + UART01x_DR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) flag = TTY_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) uap->port.icount.rx++;
^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) * Note that the error handling code is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * out of the main execution path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) rsr = readb(uap->port.membase + UART01x_RSR) | UART_DUMMY_RSR_RX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (unlikely(rsr & UART01x_RSR_ANY)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) writel(0, uap->port.membase + UART01x_ECR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (rsr & UART01x_RSR_BE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) uap->port.icount.brk++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (uart_handle_break(&uap->port))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) goto ignore_char;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) } else if (rsr & UART01x_RSR_PE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) uap->port.icount.parity++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) else if (rsr & UART01x_RSR_FE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) uap->port.icount.frame++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (rsr & UART01x_RSR_OE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) uap->port.icount.overrun++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) rsr &= uap->port.read_status_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (rsr & UART01x_RSR_BE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) flag = TTY_BREAK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) else if (rsr & UART01x_RSR_PE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) flag = TTY_PARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) else if (rsr & UART01x_RSR_FE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) flag = TTY_FRAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (uart_handle_sysrq_char(&uap->port, ch))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) goto ignore_char;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) uart_insert_char(&uap->port, rsr, UART01x_RSR_OE, ch, flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) ignore_char:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) status = readb(uap->port.membase + UART01x_FR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) spin_unlock(&uap->port.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) tty_flip_buffer_push(&uap->port.state->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) spin_lock(&uap->port.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static void pl010_tx_chars(struct uart_amba_port *uap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct circ_buf *xmit = &uap->port.state->xmit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (uap->port.x_char) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) writel(uap->port.x_char, uap->port.membase + UART01x_DR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) uap->port.icount.tx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) uap->port.x_char = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) pl010_stop_tx(&uap->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return;
^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) count = uap->port.fifosize >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) writel(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) uap->port.icount.tx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (uart_circ_empty(xmit))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) } while (--count > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) uart_write_wakeup(&uap->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (uart_circ_empty(xmit))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) pl010_stop_tx(&uap->port);
^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 void pl010_modem_status(struct uart_amba_port *uap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) unsigned int status, delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) writel(0, uap->port.membase + UART010_ICR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) status = readb(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) delta = status ^ uap->old_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) uap->old_status = status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (!delta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (delta & UART01x_FR_DCD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) uart_handle_dcd_change(&uap->port, status & UART01x_FR_DCD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (delta & UART01x_FR_DSR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) uap->port.icount.dsr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (delta & UART01x_FR_CTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) uart_handle_cts_change(&uap->port, status & UART01x_FR_CTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) wake_up_interruptible(&uap->port.state->port.delta_msr_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static irqreturn_t pl010_int(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) struct uart_amba_port *uap = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) int handled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) spin_lock(&uap->port.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) status = readb(uap->port.membase + UART010_IIR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (status & (UART010_IIR_RTIS | UART010_IIR_RIS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) pl010_rx_chars(uap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (status & UART010_IIR_MIS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) pl010_modem_status(uap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (status & UART010_IIR_TIS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) pl010_tx_chars(uap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (pass_counter-- == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) status = readb(uap->port.membase + UART010_IIR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) } while (status & (UART010_IIR_RTIS | UART010_IIR_RIS |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) UART010_IIR_TIS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) handled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) spin_unlock(&uap->port.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return IRQ_RETVAL(handled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static unsigned int pl010_tx_empty(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) struct uart_amba_port *uap =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) container_of(port, struct uart_amba_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) unsigned int status = readb(uap->port.membase + UART01x_FR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return status & UART01x_FR_BUSY ? 0 : TIOCSER_TEMT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) static unsigned int pl010_get_mctrl(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) struct uart_amba_port *uap =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) container_of(port, struct uart_amba_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) unsigned int result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) unsigned int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) status = readb(uap->port.membase + UART01x_FR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (status & UART01x_FR_DCD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) result |= TIOCM_CAR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (status & UART01x_FR_DSR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) result |= TIOCM_DSR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (status & UART01x_FR_CTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) result |= TIOCM_CTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) static void pl010_set_mctrl(struct uart_port *port, unsigned int mctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) struct uart_amba_port *uap =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) container_of(port, struct uart_amba_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (uap->data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) uap->data->set_mctrl(uap->dev, uap->port.membase, mctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) static void pl010_break_ctl(struct uart_port *port, int break_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) struct uart_amba_port *uap =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) container_of(port, struct uart_amba_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) unsigned int lcr_h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) spin_lock_irqsave(&uap->port.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) lcr_h = readb(uap->port.membase + UART010_LCRH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (break_state == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) lcr_h |= UART01x_LCRH_BRK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) lcr_h &= ~UART01x_LCRH_BRK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) writel(lcr_h, uap->port.membase + UART010_LCRH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) spin_unlock_irqrestore(&uap->port.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) static int pl010_startup(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) struct uart_amba_port *uap =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) container_of(port, struct uart_amba_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) * Try to enable the clock producer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) retval = clk_prepare_enable(uap->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) uap->port.uartclk = clk_get_rate(uap->clk);
^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) * Allocate the IRQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) retval = request_irq(uap->port.irq, pl010_int, 0, "uart-pl010", uap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) goto clk_dis;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * initialise the old status of the modem signals
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) uap->old_status = readb(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) * Finally, enable interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) writel(UART01x_CR_UARTEN | UART010_CR_RIE | UART010_CR_RTIE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) uap->port.membase + UART010_CR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) clk_dis:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) clk_disable_unprepare(uap->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) static void pl010_shutdown(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) struct uart_amba_port *uap =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) container_of(port, struct uart_amba_port, 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) * Free the interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) free_irq(uap->port.irq, uap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) * disable all interrupts, disable the port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) writel(0, uap->port.membase + UART010_CR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) /* disable break condition and fifos */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) writel(readb(uap->port.membase + UART010_LCRH) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) uap->port.membase + UART010_LCRH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) * Shut down the clock producer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) clk_disable_unprepare(uap->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) pl010_set_termios(struct uart_port *port, struct ktermios *termios,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) struct ktermios *old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) struct uart_amba_port *uap =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) container_of(port, struct uart_amba_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) unsigned int lcr_h, old_cr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) unsigned int baud, quot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) * Ask the core to calculate the divisor for us.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) baud = uart_get_baud_rate(port, termios, old, 0, uap->port.uartclk/16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) quot = uart_get_divisor(port, baud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) switch (termios->c_cflag & CSIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) case CS5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) lcr_h = UART01x_LCRH_WLEN_5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) case CS6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) lcr_h = UART01x_LCRH_WLEN_6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) case CS7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) lcr_h = UART01x_LCRH_WLEN_7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) default: // CS8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) lcr_h = UART01x_LCRH_WLEN_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (termios->c_cflag & CSTOPB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) lcr_h |= UART01x_LCRH_STP2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (termios->c_cflag & PARENB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) lcr_h |= UART01x_LCRH_PEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (!(termios->c_cflag & PARODD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) lcr_h |= UART01x_LCRH_EPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (uap->port.fifosize > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) lcr_h |= UART01x_LCRH_FEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) spin_lock_irqsave(&uap->port.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) * Update the per-port timeout.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) uart_update_timeout(port, termios->c_cflag, baud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) uap->port.read_status_mask = UART01x_RSR_OE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (termios->c_iflag & INPCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) uap->port.read_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) uap->port.read_status_mask |= UART01x_RSR_BE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) * Characters to ignore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) uap->port.ignore_status_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (termios->c_iflag & IGNPAR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) uap->port.ignore_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (termios->c_iflag & IGNBRK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) uap->port.ignore_status_mask |= UART01x_RSR_BE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) * If we're ignoring parity and break indicators,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) * ignore overruns too (for real raw support).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (termios->c_iflag & IGNPAR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) uap->port.ignore_status_mask |= UART01x_RSR_OE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) * Ignore all characters if CREAD is not set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if ((termios->c_cflag & CREAD) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) uap->port.ignore_status_mask |= UART_DUMMY_RSR_RX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) old_cr = readb(uap->port.membase + UART010_CR) & ~UART010_CR_MSIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (UART_ENABLE_MS(port, termios->c_cflag))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) old_cr |= UART010_CR_MSIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) /* Set baud rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) quot -= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) writel((quot & 0xf00) >> 8, uap->port.membase + UART010_LCRM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) writel(quot & 0xff, uap->port.membase + UART010_LCRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) * ----------v----------v----------v----------v-----
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) * ----------^----------^----------^----------^-----
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) writel(lcr_h, uap->port.membase + UART010_LCRH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) writel(old_cr, uap->port.membase + UART010_CR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) spin_unlock_irqrestore(&uap->port.lock, flags);
^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) static void pl010_set_ldisc(struct uart_port *port, struct ktermios *termios)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (termios->c_line == N_PPS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) port->flags |= UPF_HARDPPS_CD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) spin_lock_irq(&port->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) pl010_enable_ms(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) spin_unlock_irq(&port->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) port->flags &= ~UPF_HARDPPS_CD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (!UART_ENABLE_MS(port, termios->c_cflag)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) spin_lock_irq(&port->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) pl010_disable_ms(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) spin_unlock_irq(&port->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) static const char *pl010_type(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) return port->type == PORT_AMBA ? "AMBA" : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) * Release the memory region(s) being used by 'port'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) static void pl010_release_port(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) release_mem_region(port->mapbase, UART_PORT_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) * Request the memory region(s) being used by 'port'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) static int pl010_request_port(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) return request_mem_region(port->mapbase, UART_PORT_SIZE, "uart-pl010")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) != NULL ? 0 : -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) * Configure/autoconfigure the port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) static void pl010_config_port(struct uart_port *port, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (flags & UART_CONFIG_TYPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) port->type = PORT_AMBA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) pl010_request_port(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * verify the new serial_struct (for TIOCSSERIAL).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (ser->irq < 0 || ser->irq >= nr_irqs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (ser->baud_base < 9600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) static const struct uart_ops amba_pl010_pops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) .tx_empty = pl010_tx_empty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) .set_mctrl = pl010_set_mctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) .get_mctrl = pl010_get_mctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) .stop_tx = pl010_stop_tx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) .start_tx = pl010_start_tx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) .stop_rx = pl010_stop_rx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) .enable_ms = pl010_enable_ms,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) .break_ctl = pl010_break_ctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) .startup = pl010_startup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) .shutdown = pl010_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) .set_termios = pl010_set_termios,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) .set_ldisc = pl010_set_ldisc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) .type = pl010_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) .release_port = pl010_release_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) .request_port = pl010_request_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) .config_port = pl010_config_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) .verify_port = pl010_verify_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) static struct uart_amba_port *amba_ports[UART_NR];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) #ifdef CONFIG_SERIAL_AMBA_PL010_CONSOLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) static void pl010_console_putchar(struct uart_port *port, int ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) struct uart_amba_port *uap =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) container_of(port, struct uart_amba_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) unsigned int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) status = readb(uap->port.membase + UART01x_FR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) barrier();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) } while (!UART_TX_READY(status));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) writel(ch, uap->port.membase + UART01x_DR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) pl010_console_write(struct console *co, const char *s, unsigned int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) struct uart_amba_port *uap = amba_ports[co->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) unsigned int status, old_cr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) clk_enable(uap->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) * First save the CR then disable the interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) old_cr = readb(uap->port.membase + UART010_CR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) writel(UART01x_CR_UARTEN, uap->port.membase + UART010_CR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) uart_console_write(&uap->port, s, count, pl010_console_putchar);
^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) * Finally, wait for transmitter to become empty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) * and restore the TCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) status = readb(uap->port.membase + UART01x_FR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) barrier();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) } while (status & UART01x_FR_BUSY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) writel(old_cr, uap->port.membase + UART010_CR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) clk_disable(uap->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) static void __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) pl010_console_get_options(struct uart_amba_port *uap, int *baud,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) int *parity, int *bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if (readb(uap->port.membase + UART010_CR) & UART01x_CR_UARTEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) unsigned int lcr_h, quot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) lcr_h = readb(uap->port.membase + UART010_LCRH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) *parity = 'n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if (lcr_h & UART01x_LCRH_PEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (lcr_h & UART01x_LCRH_EPS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) *parity = 'e';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) *parity = 'o';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) if ((lcr_h & 0x60) == UART01x_LCRH_WLEN_7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) *bits = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) *bits = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) quot = readb(uap->port.membase + UART010_LCRL) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) readb(uap->port.membase + UART010_LCRM) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) *baud = uap->port.uartclk / (16 * (quot + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) static int __init pl010_console_setup(struct console *co, char *options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) struct uart_amba_port *uap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) int baud = 38400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) int bits = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) int parity = 'n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) int flow = 'n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) * Check whether an invalid uart number has been specified, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) * if so, search for the first available port that does have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) * console support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if (co->index >= UART_NR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) co->index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) uap = amba_ports[co->index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (!uap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) ret = clk_prepare(uap->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) uap->port.uartclk = clk_get_rate(uap->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) if (options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) uart_parse_options(options, &baud, &parity, &bits, &flow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) pl010_console_get_options(uap, &baud, &parity, &bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) return uart_set_options(&uap->port, co, baud, parity, bits, flow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) static struct uart_driver amba_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) static struct console amba_console = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) .name = "ttyAM",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) .write = pl010_console_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) .device = uart_console_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) .setup = pl010_console_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) .flags = CON_PRINTBUFFER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) .index = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) .data = &amba_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) #define AMBA_CONSOLE &amba_console
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) #define AMBA_CONSOLE NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) static DEFINE_MUTEX(amba_reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) static struct uart_driver amba_reg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) .driver_name = "ttyAM",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) .dev_name = "ttyAM",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) .major = SERIAL_AMBA_MAJOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) .minor = SERIAL_AMBA_MINOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) .nr = UART_NR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) .cons = AMBA_CONSOLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) static int pl010_probe(struct amba_device *dev, const struct amba_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) struct uart_amba_port *uap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) if (amba_ports[i] == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) if (i == ARRAY_SIZE(amba_ports))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) uap = devm_kzalloc(&dev->dev, sizeof(struct uart_amba_port),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if (!uap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) base = devm_ioremap(&dev->dev, dev->res.start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) resource_size(&dev->res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) if (!base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) uap->clk = devm_clk_get(&dev->dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if (IS_ERR(uap->clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) return PTR_ERR(uap->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) uap->port.dev = &dev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) uap->port.mapbase = dev->res.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) uap->port.membase = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) uap->port.iotype = UPIO_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) uap->port.irq = dev->irq[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) uap->port.fifosize = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) uap->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_AMBA_PL010_CONSOLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) uap->port.ops = &amba_pl010_pops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) uap->port.flags = UPF_BOOT_AUTOCONF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) uap->port.line = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) uap->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) uap->data = dev_get_platdata(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) amba_ports[i] = uap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) amba_set_drvdata(dev, uap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) mutex_lock(&amba_reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) if (!amba_reg.state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) ret = uart_register_driver(&amba_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) mutex_unlock(&amba_reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) dev_err(uap->port.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) "Failed to register AMBA-PL010 driver\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) mutex_unlock(&amba_reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) ret = uart_add_one_port(&amba_reg, &uap->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) amba_ports[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) static void pl010_remove(struct amba_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) struct uart_amba_port *uap = amba_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) bool busy = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) uart_remove_one_port(&amba_reg, &uap->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) if (amba_ports[i] == uap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) amba_ports[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) else if (amba_ports[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) busy = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (!busy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) uart_unregister_driver(&amba_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) static int pl010_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) struct uart_amba_port *uap = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (uap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) uart_suspend_port(&amba_reg, &uap->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) static int pl010_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) struct uart_amba_port *uap = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) if (uap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) uart_resume_port(&amba_reg, &uap->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) static SIMPLE_DEV_PM_OPS(pl010_dev_pm_ops, pl010_suspend, pl010_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) static const struct amba_id pl010_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) .id = 0x00041010,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) .mask = 0x000fffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) { 0, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) MODULE_DEVICE_TABLE(amba, pl010_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) static struct amba_driver pl010_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) .drv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) .name = "uart-pl010",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) .pm = &pl010_dev_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) .id_table = pl010_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) .probe = pl010_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) .remove = pl010_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) static int __init pl010_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) printk(KERN_INFO "Serial: AMBA driver\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) return amba_driver_register(&pl010_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) static void __exit pl010_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) amba_driver_unregister(&pl010_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) module_init(pl010_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) module_exit(pl010_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) MODULE_AUTHOR("ARM Ltd/Deep Blue Solutions Ltd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) MODULE_DESCRIPTION("ARM AMBA serial port driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) MODULE_LICENSE("GPL");