^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) * timbuart.c timberdale FPGA UART driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (c) 2009 Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) /* Supports:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Timberdale FPGA UART
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/serial_core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/tty.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/tty_flip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "timbuart.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct timbuart_port {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct uart_port port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct tasklet_struct tasklet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) int usedma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) u32 last_ier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct platform_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static int baudrates[] = {9600, 19200, 38400, 57600, 115200, 230400, 460800,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) 921600, 1843200, 3250000};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static void timbuart_mctrl_check(struct uart_port *port, u32 isr, u32 *ier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static irqreturn_t timbuart_handleinterrupt(int irq, void *devid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static void timbuart_stop_rx(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /* spin lock held by upper layer, disable all RX interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) u32 ier = ioread32(port->membase + TIMBUART_IER) & ~RXFLAGS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) iowrite32(ier, port->membase + TIMBUART_IER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static void timbuart_stop_tx(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* spinlock held by upper layer, disable TX interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) u32 ier = ioread32(port->membase + TIMBUART_IER) & ~TXBAE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) iowrite32(ier, port->membase + TIMBUART_IER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static void timbuart_start_tx(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct timbuart_port *uart =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) container_of(port, struct timbuart_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /* do not transfer anything here -> fire off the tasklet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) tasklet_schedule(&uart->tasklet);
^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 unsigned int timbuart_tx_empty(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) u32 isr = ioread32(port->membase + TIMBUART_ISR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return (isr & TXBE) ? TIOCSER_TEMT : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static void timbuart_flush_buffer(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (!timbuart_tx_empty(port)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) u8 ctl = ioread8(port->membase + TIMBUART_CTRL) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) TIMBUART_CTRL_FLSHTX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) iowrite8(ctl, port->membase + TIMBUART_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) iowrite32(TXBF, port->membase + TIMBUART_ISR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static void timbuart_rx_chars(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct tty_port *tport = &port->state->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) while (ioread32(port->membase + TIMBUART_ISR) & RXDP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) u8 ch = ioread8(port->membase + TIMBUART_RXFIFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) port->icount.rx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) tty_insert_flip_char(tport, ch, TTY_NORMAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) spin_unlock(&port->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) tty_flip_buffer_push(tport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) spin_lock(&port->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) dev_dbg(port->dev, "%s - total read %d bytes\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) __func__, port->icount.rx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static void timbuart_tx_chars(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct circ_buf *xmit = &port->state->xmit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) while (!(ioread32(port->membase + TIMBUART_ISR) & TXBF) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) !uart_circ_empty(xmit)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) iowrite8(xmit->buf[xmit->tail],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) port->membase + TIMBUART_TXFIFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) port->icount.tx++;
^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) dev_dbg(port->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) "%s - total written %d bytes, CTL: %x, RTS: %x, baud: %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) port->icount.tx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) ioread8(port->membase + TIMBUART_CTRL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) port->mctrl & TIOCM_RTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) ioread8(port->membase + TIMBUART_BAUDRATE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static void timbuart_handle_tx_port(struct uart_port *port, u32 isr, u32 *ier)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct timbuart_port *uart =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) container_of(port, struct timbuart_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct circ_buf *xmit = &port->state->xmit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (uart_circ_empty(xmit) || uart_tx_stopped(port))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (port->x_char)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (isr & TXFLAGS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) timbuart_tx_chars(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /* clear all TX interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) iowrite32(TXFLAGS, port->membase + TIMBUART_ISR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) uart_write_wakeup(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /* Re-enable any tx interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) *ier |= uart->last_ier & TXFLAGS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /* enable interrupts if there are chars in the transmit buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * Or if we delivered some bytes and want the almost empty interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * we wake up the upper layer later when we got the interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * to give it some time to go out...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (!uart_circ_empty(xmit))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) *ier |= TXBAE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) dev_dbg(port->dev, "%s - leaving\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) static void timbuart_handle_rx_port(struct uart_port *port, u32 isr, u32 *ier)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (isr & RXFLAGS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /* Some RX status is set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (isr & RXBF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) u8 ctl = ioread8(port->membase + TIMBUART_CTRL) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) TIMBUART_CTRL_FLSHRX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) iowrite8(ctl, port->membase + TIMBUART_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) port->icount.overrun++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) } else if (isr & (RXDP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) timbuart_rx_chars(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /* ack all RX interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) iowrite32(RXFLAGS, port->membase + TIMBUART_ISR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) /* always have the RX interrupts enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) *ier |= RXBAF | RXBF | RXTT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) dev_dbg(port->dev, "%s - leaving\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static void timbuart_tasklet(struct tasklet_struct *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct timbuart_port *uart = from_tasklet(uart, t, tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) u32 isr, ier = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) spin_lock(&uart->port.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) isr = ioread32(uart->port.membase + TIMBUART_ISR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) dev_dbg(uart->port.dev, "%s ISR: %x\n", __func__, isr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (!uart->usedma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) timbuart_handle_tx_port(&uart->port, isr, &ier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) timbuart_mctrl_check(&uart->port, isr, &ier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (!uart->usedma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) timbuart_handle_rx_port(&uart->port, isr, &ier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) iowrite32(ier, uart->port.membase + TIMBUART_IER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) spin_unlock(&uart->port.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) dev_dbg(uart->port.dev, "%s leaving\n", __func__);
^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 unsigned int timbuart_get_mctrl(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) u8 cts = ioread8(port->membase + TIMBUART_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) dev_dbg(port->dev, "%s - cts %x\n", __func__, cts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (cts & TIMBUART_CTRL_CTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return TIOCM_DSR | TIOCM_CAR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static void timbuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) dev_dbg(port->dev, "%s - %x\n", __func__, mctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (mctrl & TIOCM_RTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) iowrite8(TIMBUART_CTRL_RTS, port->membase + TIMBUART_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) iowrite8(0, port->membase + TIMBUART_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static void timbuart_mctrl_check(struct uart_port *port, u32 isr, u32 *ier)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) unsigned int cts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (isr & CTS_DELTA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) /* ack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) iowrite32(CTS_DELTA, port->membase + TIMBUART_ISR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) cts = timbuart_get_mctrl(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) uart_handle_cts_change(port, cts & TIOCM_CTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) wake_up_interruptible(&port->state->port.delta_msr_wait);
^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) *ier |= CTS_DELTA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static void timbuart_break_ctl(struct uart_port *port, int ctl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /* N/A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static int timbuart_startup(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) struct timbuart_port *uart =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) container_of(port, struct timbuart_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) dev_dbg(port->dev, "%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) iowrite8(TIMBUART_CTRL_FLSHRX, port->membase + TIMBUART_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) iowrite32(0x1ff, port->membase + TIMBUART_ISR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /* Enable all but TX interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) iowrite32(RXBAF | RXBF | RXTT | CTS_DELTA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) port->membase + TIMBUART_IER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return request_irq(port->irq, timbuart_handleinterrupt, IRQF_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) "timb-uart", uart);
^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 void timbuart_shutdown(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 timbuart_port *uart =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) container_of(port, struct timbuart_port, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) dev_dbg(port->dev, "%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) free_irq(port->irq, uart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) iowrite32(0, port->membase + TIMBUART_IER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) timbuart_flush_buffer(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) static int get_bindex(int baud)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) for (i = 0; i < ARRAY_SIZE(baudrates); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (baud <= baudrates[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) static void timbuart_set_termios(struct uart_port *port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) struct ktermios *termios,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) struct ktermios *old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) unsigned int baud;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) short bindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) bindex = get_bindex(baud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) dev_dbg(port->dev, "%s - bindex %d\n", __func__, bindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (bindex < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) bindex = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) baud = baudrates[bindex];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) /* The serial layer calls into this once with old = NULL when setting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) up initially */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) tty_termios_copy_hw(termios, old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) tty_termios_encode_baud_rate(termios, baud, baud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) spin_lock_irqsave(&port->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) iowrite8((u8)bindex, port->membase + TIMBUART_BAUDRATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) uart_update_timeout(port, termios->c_cflag, baud);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) spin_unlock_irqrestore(&port->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) static const char *timbuart_type(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return port->type == PORT_UNKNOWN ? "timbuart" : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) /* We do not request/release mappings of the registers here,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * currently it's done in the proble function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) static void timbuart_release_port(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) struct platform_device *pdev = to_platform_device(port->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) int size =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) resource_size(platform_get_resource(pdev, IORESOURCE_MEM, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (port->flags & UPF_IOREMAP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) iounmap(port->membase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) port->membase = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) release_mem_region(port->mapbase, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) static int timbuart_request_port(struct uart_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) struct platform_device *pdev = to_platform_device(port->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) int size =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) resource_size(platform_get_resource(pdev, IORESOURCE_MEM, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (!request_mem_region(port->mapbase, size, "timb-uart"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (port->flags & UPF_IOREMAP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) port->membase = ioremap(port->mapbase, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (port->membase == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) release_mem_region(port->mapbase, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) static irqreturn_t timbuart_handleinterrupt(int irq, void *devid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) struct timbuart_port *uart = (struct timbuart_port *)devid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (ioread8(uart->port.membase + TIMBUART_IPR)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) uart->last_ier = ioread32(uart->port.membase + TIMBUART_IER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) /* disable interrupts, the tasklet enables them again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) iowrite32(0, uart->port.membase + TIMBUART_IER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) /* fire off bottom half */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) tasklet_schedule(&uart->tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) * Configure/autoconfigure the port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) static void timbuart_config_port(struct uart_port *port, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (flags & UART_CONFIG_TYPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) port->type = PORT_TIMBUART;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) timbuart_request_port(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) static int timbuart_verify_port(struct uart_port *port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) struct serial_struct *ser)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) /* we don't want the core code to modify any port params */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return -EINVAL;
^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) static const struct uart_ops timbuart_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) .tx_empty = timbuart_tx_empty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) .set_mctrl = timbuart_set_mctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) .get_mctrl = timbuart_get_mctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) .stop_tx = timbuart_stop_tx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) .start_tx = timbuart_start_tx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) .flush_buffer = timbuart_flush_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) .stop_rx = timbuart_stop_rx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) .break_ctl = timbuart_break_ctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) .startup = timbuart_startup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) .shutdown = timbuart_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) .set_termios = timbuart_set_termios,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) .type = timbuart_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) .release_port = timbuart_release_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) .request_port = timbuart_request_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) .config_port = timbuart_config_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) .verify_port = timbuart_verify_port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) static struct uart_driver timbuart_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) .driver_name = "timberdale_uart",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) .dev_name = "ttyTU",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) .major = TIMBUART_MAJOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) .minor = TIMBUART_MINOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) .nr = 1
^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) static int timbuart_probe(struct platform_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) int err, irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) struct timbuart_port *uart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) struct resource *iomem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) dev_dbg(&dev->dev, "%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) uart = kzalloc(sizeof(*uart), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (!uart) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) goto err_mem;
^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) uart->usedma = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) uart->port.uartclk = 3250000 * 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) uart->port.fifosize = TIMBUART_FIFO_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) uart->port.regshift = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) uart->port.iotype = UPIO_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) uart->port.ops = &timbuart_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) uart->port.irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) uart->port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) uart->port.line = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) uart->port.dev = &dev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (!iomem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) goto err_register;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) uart->port.mapbase = iomem->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) uart->port.membase = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) irq = platform_get_irq(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (irq < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) goto err_register;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) uart->port.irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) tasklet_setup(&uart->tasklet, timbuart_tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) err = uart_register_driver(&timbuart_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) goto err_register;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) err = uart_add_one_port(&timbuart_driver, &uart->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) goto err_add_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) platform_set_drvdata(dev, uart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) err_add_port:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) uart_unregister_driver(&timbuart_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) err_register:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) kfree(uart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) err_mem:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) printk(KERN_ERR "timberdale: Failed to register Timberdale UART: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) static int timbuart_remove(struct platform_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) struct timbuart_port *uart = platform_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) tasklet_kill(&uart->tasklet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) uart_remove_one_port(&timbuart_driver, &uart->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) uart_unregister_driver(&timbuart_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) kfree(uart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) static struct platform_driver timbuart_platform_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) .name = "timb-uart",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) .probe = timbuart_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) .remove = timbuart_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) module_platform_driver(timbuart_platform_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) MODULE_DESCRIPTION("Timberdale UART driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) MODULE_ALIAS("platform:timb-uart");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)