diff options
Diffstat (limited to 'drivers/tty/serial/amba-pl010.c')
| -rw-r--r-- | drivers/tty/serial/amba-pl010.c | 363 |
1 files changed, 169 insertions, 194 deletions
diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c index c36840519527..c3a7fad02ac9 100644 --- a/drivers/tty/serial/amba-pl010.c +++ b/drivers/tty/serial/amba-pl010.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Driver for AMBA serial ports * @@ -6,20 +7,6 @@ * Copyright 1999 ARM Limited * Copyright (C) 2000 Deep Blue Solutions Ltd. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * * This is a generic driver for ARM AMBA-type serial ports. They * have a lot of 16550-like features, but are not register compatible. * Note that although they do have CTS, DCD and DSR inputs, they do @@ -28,10 +15,6 @@ * and hooked into this driver. */ -#if defined(CONFIG_SERIAL_AMBA_PL010_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include <linux/module.h> #include <linux/ioport.h> #include <linux/init.h> @@ -46,8 +29,7 @@ #include <linux/amba/serial.h> #include <linux/clk.h> #include <linux/slab.h> - -#include <asm/io.h> +#include <linux/io.h> #define UART_NR 8 @@ -76,7 +58,8 @@ struct uart_amba_port { static void pl010_stop_tx(struct uart_port *port) { - struct uart_amba_port *uap = (struct uart_amba_port *)port; + struct uart_amba_port *uap = + container_of(port, struct uart_amba_port, port); unsigned int cr; cr = readb(uap->port.membase + UART010_CR); @@ -86,7 +69,8 @@ static void pl010_stop_tx(struct uart_port *port) static void pl010_start_tx(struct uart_port *port) { - struct uart_amba_port *uap = (struct uart_amba_port *)port; + struct uart_amba_port *uap = + container_of(port, struct uart_amba_port, port); unsigned int cr; cr = readb(uap->port.membase + UART010_CR); @@ -96,7 +80,8 @@ static void pl010_start_tx(struct uart_port *port) static void pl010_stop_rx(struct uart_port *port) { - struct uart_amba_port *uap = (struct uart_amba_port *)port; + struct uart_amba_port *uap = + container_of(port, struct uart_amba_port, port); unsigned int cr; cr = readb(uap->port.membase + UART010_CR); @@ -104,48 +89,60 @@ static void pl010_stop_rx(struct uart_port *port) writel(cr, uap->port.membase + UART010_CR); } -static void pl010_enable_ms(struct uart_port *port) +static void pl010_disable_ms(struct uart_port *port) { struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned int cr; cr = readb(uap->port.membase + UART010_CR); + cr &= ~UART010_CR_MSIE; + writel(cr, uap->port.membase + UART010_CR); +} + +static void pl010_enable_ms(struct uart_port *port) +{ + struct uart_amba_port *uap = + container_of(port, struct uart_amba_port, port); + unsigned int cr; + + cr = readb(uap->port.membase + UART010_CR); cr |= UART010_CR_MSIE; writel(cr, uap->port.membase + UART010_CR); } -static void pl010_rx_chars(struct uart_amba_port *uap) +static void pl010_rx_chars(struct uart_port *port) { - unsigned int status, ch, flag, rsr, max_count = 256; + unsigned int status, rsr, max_count = 256; + u8 ch, flag; - status = readb(uap->port.membase + UART01x_FR); + status = readb(port->membase + UART01x_FR); while (UART_RX_DATA(status) && max_count--) { - ch = readb(uap->port.membase + UART01x_DR); + ch = readb(port->membase + UART01x_DR); flag = TTY_NORMAL; - uap->port.icount.rx++; + port->icount.rx++; /* * Note that the error handling code is * out of the main execution path */ - rsr = readb(uap->port.membase + UART01x_RSR) | UART_DUMMY_RSR_RX; + rsr = readb(port->membase + UART01x_RSR) | UART_DUMMY_RSR_RX; if (unlikely(rsr & UART01x_RSR_ANY)) { - writel(0, uap->port.membase + UART01x_ECR); + writel(0, port->membase + UART01x_ECR); if (rsr & UART01x_RSR_BE) { rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE); - uap->port.icount.brk++; - if (uart_handle_break(&uap->port)) + port->icount.brk++; + if (uart_handle_break(port)) goto ignore_char; } else if (rsr & UART01x_RSR_PE) - uap->port.icount.parity++; + port->icount.parity++; else if (rsr & UART01x_RSR_FE) - uap->port.icount.frame++; + port->icount.frame++; if (rsr & UART01x_RSR_OE) - uap->port.icount.overrun++; + port->icount.overrun++; - rsr &= uap->port.read_status_mask; + rsr &= port->read_status_mask; if (rsr & UART01x_RSR_BE) flag = TTY_BREAK; @@ -155,58 +152,35 @@ static void pl010_rx_chars(struct uart_amba_port *uap) flag = TTY_FRAME; } - if (uart_handle_sysrq_char(&uap->port, ch)) + if (uart_handle_sysrq_char(port, ch)) goto ignore_char; - uart_insert_char(&uap->port, rsr, UART01x_RSR_OE, ch, flag); + uart_insert_char(port, rsr, UART01x_RSR_OE, ch, flag); ignore_char: - status = readb(uap->port.membase + UART01x_FR); + status = readb(port->membase + UART01x_FR); } - spin_unlock(&uap->port.lock); - tty_flip_buffer_push(&uap->port.state->port); - spin_lock(&uap->port.lock); + tty_flip_buffer_push(&port->state->port); } -static void pl010_tx_chars(struct uart_amba_port *uap) +static void pl010_tx_chars(struct uart_port *port) { - struct circ_buf *xmit = &uap->port.state->xmit; - int count; - - if (uap->port.x_char) { - writel(uap->port.x_char, uap->port.membase + UART01x_DR); - uap->port.icount.tx++; - uap->port.x_char = 0; - return; - } - if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) { - pl010_stop_tx(&uap->port); - return; - } - - count = uap->port.fifosize >> 1; - do { - writel(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR); - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - uap->port.icount.tx++; - if (uart_circ_empty(xmit)) - break; - } while (--count > 0); - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(&uap->port); + u8 ch; - if (uart_circ_empty(xmit)) - pl010_stop_tx(&uap->port); + uart_port_tx_limited(port, ch, port->fifosize >> 1, + true, + writel(ch, port->membase + UART01x_DR), + ({})); } static void pl010_modem_status(struct uart_amba_port *uap) { + struct uart_port *port = &uap->port; unsigned int status, delta; - writel(0, uap->port.membase + UART010_ICR); + writel(0, port->membase + UART010_ICR); - status = readb(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY; + status = readb(port->membase + UART01x_FR) & UART01x_FR_MODEM_ANY; delta = status ^ uap->old_status; uap->old_status = status; @@ -215,63 +189,63 @@ static void pl010_modem_status(struct uart_amba_port *uap) return; if (delta & UART01x_FR_DCD) - uart_handle_dcd_change(&uap->port, status & UART01x_FR_DCD); + uart_handle_dcd_change(port, status & UART01x_FR_DCD); if (delta & UART01x_FR_DSR) - uap->port.icount.dsr++; + port->icount.dsr++; if (delta & UART01x_FR_CTS) - uart_handle_cts_change(&uap->port, status & UART01x_FR_CTS); + uart_handle_cts_change(port, status & UART01x_FR_CTS); - wake_up_interruptible(&uap->port.state->port.delta_msr_wait); + wake_up_interruptible(&port->state->port.delta_msr_wait); } static irqreturn_t pl010_int(int irq, void *dev_id) { struct uart_amba_port *uap = dev_id; + struct uart_port *port = &uap->port; unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT; int handled = 0; - spin_lock(&uap->port.lock); + uart_port_lock(port); - status = readb(uap->port.membase + UART010_IIR); + status = readb(port->membase + UART010_IIR); if (status) { do { if (status & (UART010_IIR_RTIS | UART010_IIR_RIS)) - pl010_rx_chars(uap); + pl010_rx_chars(port); if (status & UART010_IIR_MIS) pl010_modem_status(uap); if (status & UART010_IIR_TIS) - pl010_tx_chars(uap); + pl010_tx_chars(port); if (pass_counter-- == 0) break; - status = readb(uap->port.membase + UART010_IIR); + status = readb(port->membase + UART010_IIR); } while (status & (UART010_IIR_RTIS | UART010_IIR_RIS | UART010_IIR_TIS)); handled = 1; } - spin_unlock(&uap->port.lock); + uart_port_unlock(port); return IRQ_RETVAL(handled); } static unsigned int pl010_tx_empty(struct uart_port *port) { - struct uart_amba_port *uap = (struct uart_amba_port *)port; - unsigned int status = readb(uap->port.membase + UART01x_FR); + unsigned int status = readb(port->membase + UART01x_FR); + return status & UART01x_FR_BUSY ? 0 : TIOCSER_TEMT; } static unsigned int pl010_get_mctrl(struct uart_port *port) { - struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned int result = 0; unsigned int status; - status = readb(uap->port.membase + UART01x_FR); + status = readb(port->membase + UART01x_FR); if (status & UART01x_FR_DCD) result |= TIOCM_CAR; if (status & UART01x_FR_DSR) @@ -284,31 +258,32 @@ static unsigned int pl010_get_mctrl(struct uart_port *port) static void pl010_set_mctrl(struct uart_port *port, unsigned int mctrl) { - struct uart_amba_port *uap = (struct uart_amba_port *)port; + struct uart_amba_port *uap = + container_of(port, struct uart_amba_port, port); if (uap->data) - uap->data->set_mctrl(uap->dev, uap->port.membase, mctrl); + uap->data->set_mctrl(uap->dev, port->membase, mctrl); } static void pl010_break_ctl(struct uart_port *port, int break_state) { - struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned long flags; unsigned int lcr_h; - spin_lock_irqsave(&uap->port.lock, flags); - lcr_h = readb(uap->port.membase + UART010_LCRH); + uart_port_lock_irqsave(port, &flags); + lcr_h = readb(port->membase + UART010_LCRH); if (break_state == -1) lcr_h |= UART01x_LCRH_BRK; else lcr_h &= ~UART01x_LCRH_BRK; - writel(lcr_h, uap->port.membase + UART010_LCRH); - spin_unlock_irqrestore(&uap->port.lock, flags); + writel(lcr_h, port->membase + UART010_LCRH); + uart_port_unlock_irqrestore(port, flags); } static int pl010_startup(struct uart_port *port) { - struct uart_amba_port *uap = (struct uart_amba_port *)port; + struct uart_amba_port *uap = + container_of(port, struct uart_amba_port, port); int retval; /* @@ -318,25 +293,25 @@ static int pl010_startup(struct uart_port *port) if (retval) goto out; - uap->port.uartclk = clk_get_rate(uap->clk); + port->uartclk = clk_get_rate(uap->clk); /* * Allocate the IRQ */ - retval = request_irq(uap->port.irq, pl010_int, 0, "uart-pl010", uap); + retval = request_irq(port->irq, pl010_int, 0, "uart-pl010", uap); if (retval) goto clk_dis; /* * initialise the old status of the modem signals */ - uap->old_status = readb(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY; + uap->old_status = readb(port->membase + UART01x_FR) & UART01x_FR_MODEM_ANY; /* * Finally, enable interrupts */ writel(UART01x_CR_UARTEN | UART010_CR_RIE | UART010_CR_RTIE, - uap->port.membase + UART010_CR); + port->membase + UART010_CR); return 0; @@ -348,22 +323,23 @@ static int pl010_startup(struct uart_port *port) static void pl010_shutdown(struct uart_port *port) { - struct uart_amba_port *uap = (struct uart_amba_port *)port; + struct uart_amba_port *uap = + container_of(port, struct uart_amba_port, port); /* * Free the interrupt */ - free_irq(uap->port.irq, uap); + free_irq(port->irq, uap); /* * disable all interrupts, disable the port */ - writel(0, uap->port.membase + UART010_CR); + writel(0, port->membase + UART010_CR); /* disable break condition and fifos */ - writel(readb(uap->port.membase + UART010_LCRH) & + writel(readb(port->membase + UART010_LCRH) & ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN), - uap->port.membase + UART010_LCRH); + port->membase + UART010_LCRH); /* * Shut down the clock producer @@ -373,9 +349,8 @@ static void pl010_shutdown(struct uart_port *port) static void pl010_set_termios(struct uart_port *port, struct ktermios *termios, - struct ktermios *old) + const struct ktermios *old) { - struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned int lcr_h, old_cr; unsigned long flags; unsigned int baud, quot; @@ -383,7 +358,7 @@ pl010_set_termios(struct uart_port *port, struct ktermios *termios, /* * Ask the core to calculate the divisor for us. */ - baud = uart_get_baud_rate(port, termios, old, 0, uap->port.uartclk/16); + baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); quot = uart_get_divisor(port, baud); switch (termios->c_cflag & CSIZE) { @@ -407,75 +382,80 @@ pl010_set_termios(struct uart_port *port, struct ktermios *termios, if (!(termios->c_cflag & PARODD)) lcr_h |= UART01x_LCRH_EPS; } - if (uap->port.fifosize > 1) + if (port->fifosize > 1) lcr_h |= UART01x_LCRH_FEN; - spin_lock_irqsave(&uap->port.lock, flags); + uart_port_lock_irqsave(port, &flags); /* * Update the per-port timeout. */ uart_update_timeout(port, termios->c_cflag, baud); - uap->port.read_status_mask = UART01x_RSR_OE; + port->read_status_mask = UART01x_RSR_OE; if (termios->c_iflag & INPCK) - uap->port.read_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE; - if (termios->c_iflag & (BRKINT | PARMRK)) - uap->port.read_status_mask |= UART01x_RSR_BE; + port->read_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE; + if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) + port->read_status_mask |= UART01x_RSR_BE; /* * Characters to ignore */ - uap->port.ignore_status_mask = 0; + port->ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) - uap->port.ignore_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE; + port->ignore_status_mask |= UART01x_RSR_FE | UART01x_RSR_PE; if (termios->c_iflag & IGNBRK) { - uap->port.ignore_status_mask |= UART01x_RSR_BE; + port->ignore_status_mask |= UART01x_RSR_BE; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) - uap->port.ignore_status_mask |= UART01x_RSR_OE; + port->ignore_status_mask |= UART01x_RSR_OE; } /* * Ignore all characters if CREAD is not set. */ if ((termios->c_cflag & CREAD) == 0) - uap->port.ignore_status_mask |= UART_DUMMY_RSR_RX; + port->ignore_status_mask |= UART_DUMMY_RSR_RX; - /* first, disable everything */ - old_cr = readb(uap->port.membase + UART010_CR) & ~UART010_CR_MSIE; + old_cr = readb(port->membase + UART010_CR) & ~UART010_CR_MSIE; if (UART_ENABLE_MS(port, termios->c_cflag)) old_cr |= UART010_CR_MSIE; - writel(0, uap->port.membase + UART010_CR); - /* Set baud rate */ quot -= 1; - writel((quot & 0xf00) >> 8, uap->port.membase + UART010_LCRM); - writel(quot & 0xff, uap->port.membase + UART010_LCRL); + writel((quot & 0xf00) >> 8, port->membase + UART010_LCRM); + writel(quot & 0xff, port->membase + UART010_LCRL); /* * ----------v----------v----------v----------v----- * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L * ----------^----------^----------^----------^----- */ - writel(lcr_h, uap->port.membase + UART010_LCRH); - writel(old_cr, uap->port.membase + UART010_CR); + writel(lcr_h, port->membase + UART010_LCRH); + writel(old_cr, port->membase + UART010_CR); - spin_unlock_irqrestore(&uap->port.lock, flags); + uart_port_unlock_irqrestore(port, flags); } -static void pl010_set_ldisc(struct uart_port *port, int new) +static void pl010_set_ldisc(struct uart_port *port, struct ktermios *termios) { - if (new == N_PPS) { + if (termios->c_line == N_PPS) { port->flags |= UPF_HARDPPS_CD; + uart_port_lock_irq(port); pl010_enable_ms(port); - } else + uart_port_unlock_irq(port); + } else { port->flags &= ~UPF_HARDPPS_CD; + if (!UART_ENABLE_MS(port, termios->c_cflag)) { + uart_port_lock_irq(port); + pl010_disable_ms(port); + uart_port_unlock_irq(port); + } + } } static const char *pl010_type(struct uart_port *port) @@ -519,14 +499,14 @@ static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser) int ret = 0; if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA) ret = -EINVAL; - if (ser->irq < 0 || ser->irq >= nr_irqs) + if (ser->irq < 0 || ser->irq >= irq_get_nr_irqs()) ret = -EINVAL; if (ser->baud_base < 9600) ret = -EINVAL; return ret; } -static struct uart_ops amba_pl010_pops = { +static const struct uart_ops amba_pl010_pops = { .tx_empty = pl010_tx_empty, .set_mctrl = pl010_set_mctrl, .get_mctrl = pl010_get_mctrl, @@ -550,22 +530,22 @@ static struct uart_amba_port *amba_ports[UART_NR]; #ifdef CONFIG_SERIAL_AMBA_PL010_CONSOLE -static void pl010_console_putchar(struct uart_port *port, int ch) +static void pl010_console_putchar(struct uart_port *port, unsigned char ch) { - struct uart_amba_port *uap = (struct uart_amba_port *)port; unsigned int status; do { - status = readb(uap->port.membase + UART01x_FR); + status = readb(port->membase + UART01x_FR); barrier(); } while (!UART_TX_READY(status)); - writel(ch, uap->port.membase + UART01x_DR); + writel(ch, port->membase + UART01x_DR); } static void pl010_console_write(struct console *co, const char *s, unsigned int count) { struct uart_amba_port *uap = amba_ports[co->index]; + struct uart_port *port = &uap->port; unsigned int status, old_cr; clk_enable(uap->clk); @@ -573,20 +553,20 @@ pl010_console_write(struct console *co, const char *s, unsigned int count) /* * First save the CR then disable the interrupts */ - old_cr = readb(uap->port.membase + UART010_CR); - writel(UART01x_CR_UARTEN, uap->port.membase + UART010_CR); + old_cr = readb(port->membase + UART010_CR); + writel(UART01x_CR_UARTEN, port->membase + UART010_CR); - uart_console_write(&uap->port, s, count, pl010_console_putchar); + uart_console_write(port, s, count, pl010_console_putchar); /* * Finally, wait for transmitter to become empty * and restore the TCR */ do { - status = readb(uap->port.membase + UART01x_FR); + status = readb(port->membase + UART01x_FR); barrier(); } while (status & UART01x_FR_BUSY); - writel(old_cr, uap->port.membase + UART010_CR); + writel(old_cr, port->membase + UART010_CR); clk_disable(uap->clk); } @@ -668,6 +648,7 @@ static struct console amba_console = { #define AMBA_CONSOLE NULL #endif +static DEFINE_MUTEX(amba_reg_lock); static struct uart_driver amba_reg = { .owner = THIS_MODULE, .driver_name = "ttyAM", @@ -688,28 +669,22 @@ static int pl010_probe(struct amba_device *dev, const struct amba_id *id) if (amba_ports[i] == NULL) break; - if (i == ARRAY_SIZE(amba_ports)) { - ret = -EBUSY; - goto out; - } + if (i == ARRAY_SIZE(amba_ports)) + return -EBUSY; - uap = kzalloc(sizeof(struct uart_amba_port), GFP_KERNEL); - if (!uap) { - ret = -ENOMEM; - goto out; - } + uap = devm_kzalloc(&dev->dev, sizeof(struct uart_amba_port), + GFP_KERNEL); + if (!uap) + return -ENOMEM; - base = ioremap(dev->res.start, resource_size(&dev->res)); - if (!base) { - ret = -ENOMEM; - goto free; - } + base = devm_ioremap(&dev->dev, dev->res.start, + resource_size(&dev->res)); + if (!base) + return -ENOMEM; - uap->clk = clk_get(&dev->dev, NULL); - if (IS_ERR(uap->clk)) { - ret = PTR_ERR(uap->clk); - goto unmap; - } + uap->clk = devm_clk_get(&dev->dev, NULL); + if (IS_ERR(uap->clk)) + return PTR_ERR(uap->clk); uap->port.dev = &dev->dev; uap->port.mapbase = dev->res.start; @@ -717,51 +692,58 @@ static int pl010_probe(struct amba_device *dev, const struct amba_id *id) uap->port.iotype = UPIO_MEM; uap->port.irq = dev->irq[0]; uap->port.fifosize = 16; + uap->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_AMBA_PL010_CONSOLE); uap->port.ops = &amba_pl010_pops; uap->port.flags = UPF_BOOT_AUTOCONF; uap->port.line = i; uap->dev = dev; - uap->data = dev->dev.platform_data; + uap->data = dev_get_platdata(&dev->dev); amba_ports[i] = uap; amba_set_drvdata(dev, uap); + + mutex_lock(&amba_reg_lock); + if (!amba_reg.state) { + ret = uart_register_driver(&amba_reg); + if (ret < 0) { + mutex_unlock(&amba_reg_lock); + dev_err(uap->port.dev, + "Failed to register AMBA-PL010 driver\n"); + return ret; + } + } + mutex_unlock(&amba_reg_lock); + ret = uart_add_one_port(&amba_reg, &uap->port); - if (ret) { - amba_set_drvdata(dev, NULL); + if (ret) amba_ports[i] = NULL; - clk_put(uap->clk); - unmap: - iounmap(base); - free: - kfree(uap); - } - out: + return ret; } -static int pl010_remove(struct amba_device *dev) +static void pl010_remove(struct amba_device *dev) { struct uart_amba_port *uap = amba_get_drvdata(dev); int i; - - amba_set_drvdata(dev, NULL); + bool busy = false; uart_remove_one_port(&amba_reg, &uap->port); for (i = 0; i < ARRAY_SIZE(amba_ports); i++) if (amba_ports[i] == uap) amba_ports[i] = NULL; + else if (amba_ports[i]) + busy = true; - iounmap(uap->port.membase); - clk_put(uap->clk); - kfree(uap); - return 0; + if (!busy) + uart_unregister_driver(&amba_reg); } -static int pl010_suspend(struct amba_device *dev, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int pl010_suspend(struct device *dev) { - struct uart_amba_port *uap = amba_get_drvdata(dev); + struct uart_amba_port *uap = dev_get_drvdata(dev); if (uap) uart_suspend_port(&amba_reg, &uap->port); @@ -769,17 +751,20 @@ static int pl010_suspend(struct amba_device *dev, pm_message_t state) return 0; } -static int pl010_resume(struct amba_device *dev) +static int pl010_resume(struct device *dev) { - struct uart_amba_port *uap = amba_get_drvdata(dev); + struct uart_amba_port *uap = dev_get_drvdata(dev); if (uap) uart_resume_port(&amba_reg, &uap->port); return 0; } +#endif + +static SIMPLE_DEV_PM_OPS(pl010_dev_pm_ops, pl010_suspend, pl010_resume); -static struct amba_id pl010_ids[] = { +static const struct amba_id pl010_ids[] = { { .id = 0x00041010, .mask = 0x000fffff, @@ -792,33 +777,23 @@ MODULE_DEVICE_TABLE(amba, pl010_ids); static struct amba_driver pl010_driver = { .drv = { .name = "uart-pl010", + .pm = &pl010_dev_pm_ops, }, .id_table = pl010_ids, .probe = pl010_probe, .remove = pl010_remove, - .suspend = pl010_suspend, - .resume = pl010_resume, }; static int __init pl010_init(void) { - int ret; - printk(KERN_INFO "Serial: AMBA driver\n"); - ret = uart_register_driver(&amba_reg); - if (ret == 0) { - ret = amba_driver_register(&pl010_driver); - if (ret) - uart_unregister_driver(&amba_reg); - } - return ret; + return amba_driver_register(&pl010_driver); } static void __exit pl010_exit(void) { amba_driver_unregister(&pl010_driver); - uart_unregister_driver(&amba_reg); } module_init(pl010_init); |
