| 1 | // SPDX-License-Identifier: GPL-2.0+ | 
|---|
| 2 | /* | 
|---|
| 3 | *  Universal/legacy driver for 8250/16550-type serial ports | 
|---|
| 4 | * | 
|---|
| 5 | *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. | 
|---|
| 6 | * | 
|---|
| 7 | *  Copyright (C) 2001 Russell King. | 
|---|
| 8 | * | 
|---|
| 9 | *  Supports: | 
|---|
| 10 | *	      early_serial_setup() ports | 
|---|
| 11 | *	      userspace-configurable "phantom" ports | 
|---|
| 12 | *	      serial8250_register_8250_port() ports | 
|---|
| 13 | */ | 
|---|
| 14 |  | 
|---|
| 15 | #include <linux/acpi.h> | 
|---|
| 16 | #include <linux/hashtable.h> | 
|---|
| 17 | #include <linux/module.h> | 
|---|
| 18 | #include <linux/moduleparam.h> | 
|---|
| 19 | #include <linux/ioport.h> | 
|---|
| 20 | #include <linux/init.h> | 
|---|
| 21 | #include <linux/console.h> | 
|---|
| 22 | #include <linux/sysrq.h> | 
|---|
| 23 | #include <linux/delay.h> | 
|---|
| 24 | #include <linux/platform_device.h> | 
|---|
| 25 | #include <linux/pm_runtime.h> | 
|---|
| 26 | #include <linux/tty.h> | 
|---|
| 27 | #include <linux/ratelimit.h> | 
|---|
| 28 | #include <linux/tty_flip.h> | 
|---|
| 29 | #include <linux/serial.h> | 
|---|
| 30 | #include <linux/serial_8250.h> | 
|---|
| 31 | #include <linux/nmi.h> | 
|---|
| 32 | #include <linux/mutex.h> | 
|---|
| 33 | #include <linux/slab.h> | 
|---|
| 34 | #include <linux/string_helpers.h> | 
|---|
| 35 | #include <linux/uaccess.h> | 
|---|
| 36 | #include <linux/io.h> | 
|---|
| 37 |  | 
|---|
| 38 | #include <asm/irq.h> | 
|---|
| 39 |  | 
|---|
| 40 | #include "8250.h" | 
|---|
| 41 |  | 
|---|
| 42 | #define PASS_LIMIT	512 | 
|---|
| 43 |  | 
|---|
| 44 | struct irq_info { | 
|---|
| 45 | struct			hlist_node node; | 
|---|
| 46 | int			irq; | 
|---|
| 47 | spinlock_t		lock;	/* Protects list not the hash */ | 
|---|
| 48 | struct list_head	*head; | 
|---|
| 49 | }; | 
|---|
| 50 |  | 
|---|
| 51 | #define IRQ_HASH_BITS		5	/* Can be adjusted later */ | 
|---|
| 52 | static DEFINE_HASHTABLE(irq_lists, IRQ_HASH_BITS); | 
|---|
| 53 | static DEFINE_MUTEX(hash_mutex);	/* Used to walk the hash */ | 
|---|
| 54 |  | 
|---|
| 55 | /* | 
|---|
| 56 | * This is the serial driver's interrupt routine. | 
|---|
| 57 | * | 
|---|
| 58 | * Arjan thinks the old way was overly complex, so it got simplified. | 
|---|
| 59 | * Alan disagrees, saying that need the complexity to handle the weird | 
|---|
| 60 | * nature of ISA shared interrupts.  (This is a special exception.) | 
|---|
| 61 | * | 
|---|
| 62 | * In order to handle ISA shared interrupts properly, we need to check | 
|---|
| 63 | * that all ports have been serviced, and therefore the ISA interrupt | 
|---|
| 64 | * line has been de-asserted. | 
|---|
| 65 | * | 
|---|
| 66 | * This means we need to loop through all ports. checking that they | 
|---|
| 67 | * don't have an interrupt pending. | 
|---|
| 68 | */ | 
|---|
| 69 | static irqreturn_t serial8250_interrupt(int irq, void *dev_id) | 
|---|
| 70 | { | 
|---|
| 71 | struct irq_info *i = dev_id; | 
|---|
| 72 | struct list_head *l, *end = NULL; | 
|---|
| 73 | int pass_counter = 0, handled = 0; | 
|---|
| 74 |  | 
|---|
| 75 | guard(spinlock)(l: &i->lock); | 
|---|
| 76 |  | 
|---|
| 77 | l = i->head; | 
|---|
| 78 | do { | 
|---|
| 79 | struct uart_8250_port *up = list_entry(l, struct uart_8250_port, list); | 
|---|
| 80 | struct uart_port *port = &up->port; | 
|---|
| 81 |  | 
|---|
| 82 | if (port->handle_irq(port)) { | 
|---|
| 83 | handled = 1; | 
|---|
| 84 | end = NULL; | 
|---|
| 85 | } else if (end == NULL) | 
|---|
| 86 | end = l; | 
|---|
| 87 |  | 
|---|
| 88 | l = l->next; | 
|---|
| 89 |  | 
|---|
| 90 | if (l == i->head && pass_counter++ > PASS_LIMIT) | 
|---|
| 91 | break; | 
|---|
| 92 | } while (l != end); | 
|---|
| 93 |  | 
|---|
| 94 | return IRQ_RETVAL(handled); | 
|---|
| 95 | } | 
|---|
| 96 |  | 
|---|
| 97 | /* | 
|---|
| 98 | * To support ISA shared interrupts, we need to have one interrupt | 
|---|
| 99 | * handler that ensures that the IRQ line has been deasserted | 
|---|
| 100 | * before returning.  Failing to do this will result in the IRQ | 
|---|
| 101 | * line being stuck active, and, since ISA irqs are edge triggered, | 
|---|
| 102 | * no more IRQs will be seen. | 
|---|
| 103 | */ | 
|---|
| 104 | static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up) | 
|---|
| 105 | { | 
|---|
| 106 | spin_lock_irq(lock: &i->lock); | 
|---|
| 107 |  | 
|---|
| 108 | if (!list_empty(head: i->head)) { | 
|---|
| 109 | if (i->head == &up->list) | 
|---|
| 110 | i->head = i->head->next; | 
|---|
| 111 | list_del(entry: &up->list); | 
|---|
| 112 | } else { | 
|---|
| 113 | BUG_ON(i->head != &up->list); | 
|---|
| 114 | i->head = NULL; | 
|---|
| 115 | } | 
|---|
| 116 | spin_unlock_irq(lock: &i->lock); | 
|---|
| 117 | /* List empty so throw away the hash node */ | 
|---|
| 118 | if (i->head == NULL) { | 
|---|
| 119 | hlist_del(n: &i->node); | 
|---|
| 120 | kfree(objp: i); | 
|---|
| 121 | } | 
|---|
| 122 | } | 
|---|
| 123 |  | 
|---|
| 124 | /* | 
|---|
| 125 | * Either: | 
|---|
| 126 | * - find the corresponding info in the hashtable and return it, or | 
|---|
| 127 | * - allocate a new one, add it to the hashtable and return it. | 
|---|
| 128 | */ | 
|---|
| 129 | static struct irq_info *serial_get_or_create_irq_info(const struct uart_8250_port *up) | 
|---|
| 130 | { | 
|---|
| 131 | struct irq_info *i; | 
|---|
| 132 |  | 
|---|
| 133 | guard(mutex)(T: &hash_mutex); | 
|---|
| 134 |  | 
|---|
| 135 | hash_for_each_possible(irq_lists, i, node, up->port.irq) | 
|---|
| 136 | if (i->irq == up->port.irq) | 
|---|
| 137 | return i; | 
|---|
| 138 |  | 
|---|
| 139 | i = kzalloc(sizeof(*i), GFP_KERNEL); | 
|---|
| 140 | if (i == NULL) | 
|---|
| 141 | return ERR_PTR(error: -ENOMEM); | 
|---|
| 142 |  | 
|---|
| 143 | spin_lock_init(&i->lock); | 
|---|
| 144 | i->irq = up->port.irq; | 
|---|
| 145 | hash_add(irq_lists, &i->node, i->irq); | 
|---|
| 146 |  | 
|---|
| 147 | return i; | 
|---|
| 148 | } | 
|---|
| 149 |  | 
|---|
| 150 | static int serial_link_irq_chain(struct uart_8250_port *up) | 
|---|
| 151 | { | 
|---|
| 152 | struct irq_info *i; | 
|---|
| 153 | int ret; | 
|---|
| 154 |  | 
|---|
| 155 | i = serial_get_or_create_irq_info(up); | 
|---|
| 156 | if (IS_ERR(ptr: i)) | 
|---|
| 157 | return PTR_ERR(ptr: i); | 
|---|
| 158 |  | 
|---|
| 159 | scoped_guard(spinlock_irq, &i->lock) { | 
|---|
| 160 | if (i->head) { | 
|---|
| 161 | list_add(new: &up->list, head: i->head); | 
|---|
| 162 |  | 
|---|
| 163 | return 0; | 
|---|
| 164 | } | 
|---|
| 165 |  | 
|---|
| 166 | INIT_LIST_HEAD(list: &up->list); | 
|---|
| 167 | i->head = &up->list; | 
|---|
| 168 | } | 
|---|
| 169 |  | 
|---|
| 170 | ret = request_irq(irq: up->port.irq, handler: serial8250_interrupt, flags: up->port.irqflags, name: up->port.name, dev: i); | 
|---|
| 171 | if (ret < 0) | 
|---|
| 172 | serial_do_unlink(i, up); | 
|---|
| 173 |  | 
|---|
| 174 | return ret; | 
|---|
| 175 | } | 
|---|
| 176 |  | 
|---|
| 177 | static void serial_unlink_irq_chain(struct uart_8250_port *up) | 
|---|
| 178 | { | 
|---|
| 179 | struct irq_info *i; | 
|---|
| 180 |  | 
|---|
| 181 | guard(mutex)(T: &hash_mutex); | 
|---|
| 182 |  | 
|---|
| 183 | hash_for_each_possible(irq_lists, i, node, up->port.irq) | 
|---|
| 184 | if (i->irq == up->port.irq) { | 
|---|
| 185 | if (WARN_ON(i->head == NULL)) | 
|---|
| 186 | return; | 
|---|
| 187 |  | 
|---|
| 188 | if (list_empty(head: i->head)) | 
|---|
| 189 | free_irq(up->port.irq, i); | 
|---|
| 190 |  | 
|---|
| 191 | serial_do_unlink(i, up); | 
|---|
| 192 |  | 
|---|
| 193 | return; | 
|---|
| 194 | } | 
|---|
| 195 |  | 
|---|
| 196 | WARN_ON(1); | 
|---|
| 197 | } | 
|---|
| 198 |  | 
|---|
| 199 | /* | 
|---|
| 200 | * This function is used to handle ports that do not have an | 
|---|
| 201 | * interrupt.  This doesn't work very well for 16450's, but gives | 
|---|
| 202 | * barely passable results for a 16550A.  (Although at the expense | 
|---|
| 203 | * of much CPU overhead). | 
|---|
| 204 | */ | 
|---|
| 205 | static void serial8250_timeout(struct timer_list *t) | 
|---|
| 206 | { | 
|---|
| 207 | struct uart_8250_port *up = timer_container_of(up, t, timer); | 
|---|
| 208 |  | 
|---|
| 209 | up->port.handle_irq(&up->port); | 
|---|
| 210 | mod_timer(timer: &up->timer, expires: jiffies + uart_poll_timeout(port: &up->port)); | 
|---|
| 211 | } | 
|---|
| 212 |  | 
|---|
| 213 | static void serial8250_backup_timeout(struct timer_list *t) | 
|---|
| 214 | { | 
|---|
| 215 | struct uart_8250_port *up = timer_container_of(up, t, timer); | 
|---|
| 216 | unsigned int iir, ier = 0, lsr; | 
|---|
| 217 | unsigned long flags; | 
|---|
| 218 |  | 
|---|
| 219 | uart_port_lock_irqsave(up: &up->port, flags: &flags); | 
|---|
| 220 |  | 
|---|
| 221 | /* | 
|---|
| 222 | * Must disable interrupts or else we risk racing with the interrupt | 
|---|
| 223 | * based handler. | 
|---|
| 224 | */ | 
|---|
| 225 | if (up->port.irq) { | 
|---|
| 226 | ier = serial_in(up, UART_IER); | 
|---|
| 227 | serial_out(up, UART_IER, value: 0); | 
|---|
| 228 | } | 
|---|
| 229 |  | 
|---|
| 230 | iir = serial_in(up, UART_IIR); | 
|---|
| 231 |  | 
|---|
| 232 | /* | 
|---|
| 233 | * This should be a safe test for anyone who doesn't trust the | 
|---|
| 234 | * IIR bits on their UART, but it's specifically designed for | 
|---|
| 235 | * the "Diva" UART used on the management processor on many HP | 
|---|
| 236 | * ia64 and parisc boxes. | 
|---|
| 237 | */ | 
|---|
| 238 | lsr = serial_lsr_in(up); | 
|---|
| 239 | if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) && | 
|---|
| 240 | (!kfifo_is_empty(&up->port.state->port.xmit_fifo) || | 
|---|
| 241 | up->port.x_char) && | 
|---|
| 242 | (lsr & UART_LSR_THRE)) { | 
|---|
| 243 | iir &= ~(UART_IIR_ID | UART_IIR_NO_INT); | 
|---|
| 244 | iir |= UART_IIR_THRI; | 
|---|
| 245 | } | 
|---|
| 246 |  | 
|---|
| 247 | if (!(iir & UART_IIR_NO_INT)) | 
|---|
| 248 | serial8250_tx_chars(up); | 
|---|
| 249 |  | 
|---|
| 250 | if (up->port.irq) | 
|---|
| 251 | serial_out(up, UART_IER, value: ier); | 
|---|
| 252 |  | 
|---|
| 253 | uart_port_unlock_irqrestore(up: &up->port, flags); | 
|---|
| 254 |  | 
|---|
| 255 | /* Standard timer interval plus 0.2s to keep the port running */ | 
|---|
| 256 | mod_timer(timer: &up->timer, | 
|---|
| 257 | expires: jiffies + uart_poll_timeout(port: &up->port) + HZ / 5); | 
|---|
| 258 | } | 
|---|
| 259 |  | 
|---|
| 260 | static void univ8250_setup_timer(struct uart_8250_port *up) | 
|---|
| 261 | { | 
|---|
| 262 | struct uart_port *port = &up->port; | 
|---|
| 263 |  | 
|---|
| 264 | /* | 
|---|
| 265 | * The above check will only give an accurate result the first time | 
|---|
| 266 | * the port is opened so this value needs to be preserved. | 
|---|
| 267 | */ | 
|---|
| 268 | if (up->bugs & UART_BUG_THRE) { | 
|---|
| 269 | pr_debug( "%s - using backup timer\n", port->name); | 
|---|
| 270 |  | 
|---|
| 271 | up->timer.function = serial8250_backup_timeout; | 
|---|
| 272 | mod_timer(timer: &up->timer, expires: jiffies + | 
|---|
| 273 | uart_poll_timeout(port) + HZ / 5); | 
|---|
| 274 | } | 
|---|
| 275 |  | 
|---|
| 276 | /* | 
|---|
| 277 | * If the "interrupt" for this port doesn't correspond with any | 
|---|
| 278 | * hardware interrupt, we use a timer-based system.  The original | 
|---|
| 279 | * driver used to do this with IRQ0. | 
|---|
| 280 | */ | 
|---|
| 281 | if (!port->irq) | 
|---|
| 282 | mod_timer(timer: &up->timer, expires: jiffies + uart_poll_timeout(port)); | 
|---|
| 283 | } | 
|---|
| 284 |  | 
|---|
| 285 | static int univ8250_setup_irq(struct uart_8250_port *up) | 
|---|
| 286 | { | 
|---|
| 287 | struct uart_port *port = &up->port; | 
|---|
| 288 |  | 
|---|
| 289 | if (port->irq) | 
|---|
| 290 | return serial_link_irq_chain(up); | 
|---|
| 291 |  | 
|---|
| 292 | return 0; | 
|---|
| 293 | } | 
|---|
| 294 |  | 
|---|
| 295 | static void univ8250_release_irq(struct uart_8250_port *up) | 
|---|
| 296 | { | 
|---|
| 297 | struct uart_port *port = &up->port; | 
|---|
| 298 |  | 
|---|
| 299 | timer_delete_sync(timer: &up->timer); | 
|---|
| 300 | up->timer.function = serial8250_timeout; | 
|---|
| 301 | if (port->irq) | 
|---|
| 302 | serial_unlink_irq_chain(up); | 
|---|
| 303 | } | 
|---|
| 304 |  | 
|---|
| 305 | const struct uart_ops *univ8250_port_base_ops; | 
|---|
| 306 | struct uart_ops univ8250_port_ops; | 
|---|
| 307 |  | 
|---|
| 308 | static const struct uart_8250_ops univ8250_driver_ops = { | 
|---|
| 309 | .setup_irq	= univ8250_setup_irq, | 
|---|
| 310 | .release_irq	= univ8250_release_irq, | 
|---|
| 311 | .setup_timer	= univ8250_setup_timer, | 
|---|
| 312 | }; | 
|---|
| 313 |  | 
|---|
| 314 | static struct uart_8250_port serial8250_ports[UART_NR]; | 
|---|
| 315 |  | 
|---|
| 316 | /** | 
|---|
| 317 | * serial8250_get_port - retrieve struct uart_8250_port | 
|---|
| 318 | * @line: serial line number | 
|---|
| 319 | * | 
|---|
| 320 | * This function retrieves struct uart_8250_port for the specific line. | 
|---|
| 321 | * This struct *must* *not* be used to perform a 8250 or serial core operation | 
|---|
| 322 | * which is not accessible otherwise. Its only purpose is to make the struct | 
|---|
| 323 | * accessible to the runtime-pm callbacks for context suspend/restore. | 
|---|
| 324 | * The lock assumption made here is none because runtime-pm suspend/resume | 
|---|
| 325 | * callbacks should not be invoked if there is any operation performed on the | 
|---|
| 326 | * port. | 
|---|
| 327 | */ | 
|---|
| 328 | struct uart_8250_port *serial8250_get_port(int line) | 
|---|
| 329 | { | 
|---|
| 330 | return &serial8250_ports[line]; | 
|---|
| 331 | } | 
|---|
| 332 | EXPORT_SYMBOL_GPL(serial8250_get_port); | 
|---|
| 333 |  | 
|---|
| 334 | static inline void serial8250_apply_quirks(struct uart_8250_port *up) | 
|---|
| 335 | { | 
|---|
| 336 | up->port.quirks |= skip_txen_test ? UPQ_NO_TXEN_TEST : 0; | 
|---|
| 337 | } | 
|---|
| 338 |  | 
|---|
| 339 | struct uart_8250_port *serial8250_setup_port(int index) | 
|---|
| 340 | { | 
|---|
| 341 | struct uart_8250_port *up; | 
|---|
| 342 |  | 
|---|
| 343 | if (index >= UART_NR) | 
|---|
| 344 | return NULL; | 
|---|
| 345 |  | 
|---|
| 346 | up = &serial8250_ports[index]; | 
|---|
| 347 | up->port.line = index; | 
|---|
| 348 | up->port.port_id = index; | 
|---|
| 349 |  | 
|---|
| 350 | serial8250_init_port(up); | 
|---|
| 351 | if (!univ8250_port_base_ops) | 
|---|
| 352 | univ8250_port_base_ops = up->port.ops; | 
|---|
| 353 | up->port.ops = &univ8250_port_ops; | 
|---|
| 354 |  | 
|---|
| 355 | timer_setup(&up->timer, serial8250_timeout, 0); | 
|---|
| 356 |  | 
|---|
| 357 | up->ops = &univ8250_driver_ops; | 
|---|
| 358 |  | 
|---|
| 359 | serial8250_set_defaults(up); | 
|---|
| 360 |  | 
|---|
| 361 | return up; | 
|---|
| 362 | } | 
|---|
| 363 |  | 
|---|
| 364 | void __init serial8250_register_ports(struct uart_driver *drv, struct device *dev) | 
|---|
| 365 | { | 
|---|
| 366 | int i; | 
|---|
| 367 |  | 
|---|
| 368 | for (i = 0; i < nr_uarts; i++) { | 
|---|
| 369 | struct uart_8250_port *up = &serial8250_ports[i]; | 
|---|
| 370 |  | 
|---|
| 371 | if (up->port.type == PORT_8250_CIR) | 
|---|
| 372 | continue; | 
|---|
| 373 |  | 
|---|
| 374 | if (up->port.dev) | 
|---|
| 375 | continue; | 
|---|
| 376 |  | 
|---|
| 377 | up->port.dev = dev; | 
|---|
| 378 |  | 
|---|
| 379 | if (uart_console_registered(port: &up->port)) | 
|---|
| 380 | pm_runtime_get_sync(dev: up->port.dev); | 
|---|
| 381 |  | 
|---|
| 382 | serial8250_apply_quirks(up); | 
|---|
| 383 | uart_add_one_port(reg: drv, port: &up->port); | 
|---|
| 384 | } | 
|---|
| 385 | } | 
|---|
| 386 |  | 
|---|
| 387 | #ifdef CONFIG_SERIAL_8250_CONSOLE | 
|---|
| 388 |  | 
|---|
| 389 | static void univ8250_console_write(struct console *co, const char *s, | 
|---|
| 390 | unsigned int count) | 
|---|
| 391 | { | 
|---|
| 392 | struct uart_8250_port *up = &serial8250_ports[co->index]; | 
|---|
| 393 |  | 
|---|
| 394 | serial8250_console_write(up, s, count); | 
|---|
| 395 | } | 
|---|
| 396 |  | 
|---|
| 397 | static int univ8250_console_setup(struct console *co, char *options) | 
|---|
| 398 | { | 
|---|
| 399 | struct uart_8250_port *up; | 
|---|
| 400 | struct uart_port *port; | 
|---|
| 401 | int retval, i; | 
|---|
| 402 |  | 
|---|
| 403 | /* | 
|---|
| 404 | * Check whether an invalid uart number has been specified, and | 
|---|
| 405 | * if so, search for the first available port that does have | 
|---|
| 406 | * console support. | 
|---|
| 407 | */ | 
|---|
| 408 | if (co->index < 0 || co->index >= UART_NR) | 
|---|
| 409 | co->index = 0; | 
|---|
| 410 |  | 
|---|
| 411 | /* | 
|---|
| 412 | * If the console is past the initial isa ports, init more ports up to | 
|---|
| 413 | * co->index as needed and increment nr_uarts accordingly. | 
|---|
| 414 | */ | 
|---|
| 415 | for (i = nr_uarts; i <= co->index; i++) { | 
|---|
| 416 | up = serial8250_setup_port(index: i); | 
|---|
| 417 | if (!up) | 
|---|
| 418 | return -ENODEV; | 
|---|
| 419 | nr_uarts++; | 
|---|
| 420 | } | 
|---|
| 421 |  | 
|---|
| 422 | port = &serial8250_ports[co->index].port; | 
|---|
| 423 | /* link port to console */ | 
|---|
| 424 | uart_port_set_cons(up: port, con: co); | 
|---|
| 425 |  | 
|---|
| 426 | retval = serial8250_console_setup(port, options, probe: false); | 
|---|
| 427 | if (retval != 0) | 
|---|
| 428 | uart_port_set_cons(up: port, NULL); | 
|---|
| 429 | return retval; | 
|---|
| 430 | } | 
|---|
| 431 |  | 
|---|
| 432 | static int univ8250_console_exit(struct console *co) | 
|---|
| 433 | { | 
|---|
| 434 | struct uart_port *port; | 
|---|
| 435 |  | 
|---|
| 436 | port = &serial8250_ports[co->index].port; | 
|---|
| 437 | return serial8250_console_exit(port); | 
|---|
| 438 | } | 
|---|
| 439 |  | 
|---|
| 440 | /** | 
|---|
| 441 | *	univ8250_console_match - non-standard console matching | 
|---|
| 442 | *	@co:	  registering console | 
|---|
| 443 | *	@name:	  name from console command line | 
|---|
| 444 | *	@idx:	  index from console command line | 
|---|
| 445 | *	@options: ptr to option string from console command line | 
|---|
| 446 | * | 
|---|
| 447 | *	Only attempts to match console command lines of the form: | 
|---|
| 448 | *	    console=uart[8250],io|mmio|mmio16|mmio32,<addr>[,<options>] | 
|---|
| 449 | *	    console=uart[8250],0x<addr>[,<options>] | 
|---|
| 450 | *	This form is used to register an initial earlycon boot console and | 
|---|
| 451 | *	replace it with the serial8250_console at 8250 driver init. | 
|---|
| 452 | * | 
|---|
| 453 | *	Performs console setup for a match (as required by interface) | 
|---|
| 454 | *	If no <options> are specified, then assume the h/w is already setup. | 
|---|
| 455 | * | 
|---|
| 456 | *	Returns 0 if console matches; otherwise non-zero to use default matching | 
|---|
| 457 | */ | 
|---|
| 458 | static int univ8250_console_match(struct console *co, char *name, int idx, | 
|---|
| 459 | char *options) | 
|---|
| 460 | { | 
|---|
| 461 | char match[] = "uart";	/* 8250-specific earlycon name */ | 
|---|
| 462 | enum uart_iotype iotype; | 
|---|
| 463 | resource_size_t addr; | 
|---|
| 464 | int i; | 
|---|
| 465 |  | 
|---|
| 466 | if (strncmp(name, match, 4) != 0) | 
|---|
| 467 | return -ENODEV; | 
|---|
| 468 |  | 
|---|
| 469 | if (uart_parse_earlycon(p: options, iotype: &iotype, addr: &addr, options: &options)) | 
|---|
| 470 | return -ENODEV; | 
|---|
| 471 |  | 
|---|
| 472 | /* try to match the port specified on the command line */ | 
|---|
| 473 | for (i = 0; i < nr_uarts; i++) { | 
|---|
| 474 | struct uart_port *port = &serial8250_ports[i].port; | 
|---|
| 475 |  | 
|---|
| 476 | if (port->iotype != iotype) | 
|---|
| 477 | continue; | 
|---|
| 478 | if ((iotype == UPIO_MEM || iotype == UPIO_MEM16 || | 
|---|
| 479 | iotype == UPIO_MEM32 || iotype == UPIO_MEM32BE) | 
|---|
| 480 | && (port->mapbase != addr)) | 
|---|
| 481 | continue; | 
|---|
| 482 | if (iotype == UPIO_PORT && port->iobase != addr) | 
|---|
| 483 | continue; | 
|---|
| 484 |  | 
|---|
| 485 | co->index = i; | 
|---|
| 486 | uart_port_set_cons(up: port, con: co); | 
|---|
| 487 | return serial8250_console_setup(port, options, probe: true); | 
|---|
| 488 | } | 
|---|
| 489 |  | 
|---|
| 490 | return -ENODEV; | 
|---|
| 491 | } | 
|---|
| 492 |  | 
|---|
| 493 | static struct console univ8250_console = { | 
|---|
| 494 | .name		= "ttyS", | 
|---|
| 495 | .write		= univ8250_console_write, | 
|---|
| 496 | .device		= uart_console_device, | 
|---|
| 497 | .setup		= univ8250_console_setup, | 
|---|
| 498 | .exit		= univ8250_console_exit, | 
|---|
| 499 | .match		= univ8250_console_match, | 
|---|
| 500 | .flags		= CON_PRINTBUFFER | CON_ANYTIME, | 
|---|
| 501 | .index		= -1, | 
|---|
| 502 | .data		= &serial8250_reg, | 
|---|
| 503 | }; | 
|---|
| 504 |  | 
|---|
| 505 | static int __init univ8250_console_init(void) | 
|---|
| 506 | { | 
|---|
| 507 | if (nr_uarts == 0) | 
|---|
| 508 | return -ENODEV; | 
|---|
| 509 |  | 
|---|
| 510 | serial8250_isa_init_ports(); | 
|---|
| 511 | register_console(&univ8250_console); | 
|---|
| 512 | return 0; | 
|---|
| 513 | } | 
|---|
| 514 | console_initcall(univ8250_console_init); | 
|---|
| 515 |  | 
|---|
| 516 | #define SERIAL8250_CONSOLE	(&univ8250_console) | 
|---|
| 517 | #else | 
|---|
| 518 | #define SERIAL8250_CONSOLE	NULL | 
|---|
| 519 | #endif | 
|---|
| 520 |  | 
|---|
| 521 | struct uart_driver serial8250_reg = { | 
|---|
| 522 | .owner			= THIS_MODULE, | 
|---|
| 523 | .driver_name		= "serial", | 
|---|
| 524 | .dev_name		= "ttyS", | 
|---|
| 525 | .major			= TTY_MAJOR, | 
|---|
| 526 | .minor			= 64, | 
|---|
| 527 | .cons			= SERIAL8250_CONSOLE, | 
|---|
| 528 | }; | 
|---|
| 529 |  | 
|---|
| 530 | /* | 
|---|
| 531 | * early_serial_setup - early registration for 8250 ports | 
|---|
| 532 | * | 
|---|
| 533 | * Setup an 8250 port structure prior to console initialisation.  Use | 
|---|
| 534 | * after console initialisation will cause undefined behaviour. | 
|---|
| 535 | */ | 
|---|
| 536 | int __init early_serial_setup(struct uart_port *port) | 
|---|
| 537 | { | 
|---|
| 538 | struct uart_port *p; | 
|---|
| 539 |  | 
|---|
| 540 | if (port->line >= ARRAY_SIZE(serial8250_ports) || nr_uarts == 0) | 
|---|
| 541 | return -ENODEV; | 
|---|
| 542 |  | 
|---|
| 543 | serial8250_isa_init_ports(); | 
|---|
| 544 | p = &serial8250_ports[port->line].port; | 
|---|
| 545 | p->iobase       = port->iobase; | 
|---|
| 546 | p->membase      = port->membase; | 
|---|
| 547 | p->irq          = port->irq; | 
|---|
| 548 | p->irqflags     = port->irqflags; | 
|---|
| 549 | p->uartclk      = port->uartclk; | 
|---|
| 550 | p->fifosize     = port->fifosize; | 
|---|
| 551 | p->regshift     = port->regshift; | 
|---|
| 552 | p->iotype       = port->iotype; | 
|---|
| 553 | p->flags        = port->flags; | 
|---|
| 554 | p->mapbase      = port->mapbase; | 
|---|
| 555 | p->mapsize      = port->mapsize; | 
|---|
| 556 | p->private_data = port->private_data; | 
|---|
| 557 | p->type		= port->type; | 
|---|
| 558 | p->line		= port->line; | 
|---|
| 559 |  | 
|---|
| 560 | serial8250_set_defaults(up: up_to_u8250p(up: p)); | 
|---|
| 561 |  | 
|---|
| 562 | if (port->serial_in) | 
|---|
| 563 | p->serial_in = port->serial_in; | 
|---|
| 564 | if (port->serial_out) | 
|---|
| 565 | p->serial_out = port->serial_out; | 
|---|
| 566 | if (port->handle_irq) | 
|---|
| 567 | p->handle_irq = port->handle_irq; | 
|---|
| 568 |  | 
|---|
| 569 | return 0; | 
|---|
| 570 | } | 
|---|
| 571 |  | 
|---|
| 572 | /** | 
|---|
| 573 | *	serial8250_suspend_port - suspend one serial port | 
|---|
| 574 | *	@line:  serial line number | 
|---|
| 575 | * | 
|---|
| 576 | *	Suspend one serial port. | 
|---|
| 577 | */ | 
|---|
| 578 | void serial8250_suspend_port(int line) | 
|---|
| 579 | { | 
|---|
| 580 | struct uart_8250_port *up = &serial8250_ports[line]; | 
|---|
| 581 | struct uart_port *port = &up->port; | 
|---|
| 582 |  | 
|---|
| 583 | if (!console_suspend_enabled && uart_console(port) && | 
|---|
| 584 | port->type != PORT_8250) { | 
|---|
| 585 | unsigned char canary = 0xa5; | 
|---|
| 586 |  | 
|---|
| 587 | serial_out(up, UART_SCR, value: canary); | 
|---|
| 588 | if (serial_in(up, UART_SCR) == canary) | 
|---|
| 589 | up->canary = canary; | 
|---|
| 590 | } | 
|---|
| 591 |  | 
|---|
| 592 | uart_suspend_port(reg: &serial8250_reg, port); | 
|---|
| 593 | } | 
|---|
| 594 | EXPORT_SYMBOL(serial8250_suspend_port); | 
|---|
| 595 |  | 
|---|
| 596 | /** | 
|---|
| 597 | *	serial8250_resume_port - resume one serial port | 
|---|
| 598 | *	@line:  serial line number | 
|---|
| 599 | * | 
|---|
| 600 | *	Resume one serial port. | 
|---|
| 601 | */ | 
|---|
| 602 | void serial8250_resume_port(int line) | 
|---|
| 603 | { | 
|---|
| 604 | struct uart_8250_port *up = &serial8250_ports[line]; | 
|---|
| 605 | struct uart_port *port = &up->port; | 
|---|
| 606 |  | 
|---|
| 607 | up->canary = 0; | 
|---|
| 608 |  | 
|---|
| 609 | if (up->capabilities & UART_NATSEMI) { | 
|---|
| 610 | /* Ensure it's still in high speed mode */ | 
|---|
| 611 | serial_port_out(up: port, UART_LCR, value: 0xE0); | 
|---|
| 612 |  | 
|---|
| 613 | ns16550a_goto_highspeed(up); | 
|---|
| 614 |  | 
|---|
| 615 | serial_port_out(up: port, UART_LCR, value: 0); | 
|---|
| 616 | port->uartclk = 921600*16; | 
|---|
| 617 | } | 
|---|
| 618 | uart_resume_port(reg: &serial8250_reg, port); | 
|---|
| 619 | } | 
|---|
| 620 | EXPORT_SYMBOL(serial8250_resume_port); | 
|---|
| 621 |  | 
|---|
| 622 | /* | 
|---|
| 623 | * serial8250_register_8250_port and serial8250_unregister_port allows for | 
|---|
| 624 | * 16x50 serial ports to be configured at run-time, to support PCMCIA | 
|---|
| 625 | * modems and PCI multiport cards. | 
|---|
| 626 | */ | 
|---|
| 627 | static DEFINE_MUTEX(serial_mutex); | 
|---|
| 628 |  | 
|---|
| 629 | static struct uart_8250_port *serial8250_find_match_or_unused(const struct uart_port *port) | 
|---|
| 630 | { | 
|---|
| 631 | int i; | 
|---|
| 632 |  | 
|---|
| 633 | /* | 
|---|
| 634 | * First, find a port entry which matches. | 
|---|
| 635 | */ | 
|---|
| 636 | for (i = 0; i < nr_uarts; i++) | 
|---|
| 637 | if (uart_match_port(port1: &serial8250_ports[i].port, port2: port)) | 
|---|
| 638 | return &serial8250_ports[i]; | 
|---|
| 639 |  | 
|---|
| 640 | /* try line number first if still available */ | 
|---|
| 641 | i = port->line; | 
|---|
| 642 | if (i < nr_uarts && serial8250_ports[i].port.type == PORT_UNKNOWN && | 
|---|
| 643 | serial8250_ports[i].port.iobase == 0) | 
|---|
| 644 | return &serial8250_ports[i]; | 
|---|
| 645 | /* | 
|---|
| 646 | * We didn't find a matching entry, so look for the first | 
|---|
| 647 | * free entry.  We look for one which hasn't been previously | 
|---|
| 648 | * used (indicated by zero iobase). | 
|---|
| 649 | */ | 
|---|
| 650 | for (i = 0; i < nr_uarts; i++) | 
|---|
| 651 | if (serial8250_ports[i].port.type == PORT_UNKNOWN && | 
|---|
| 652 | serial8250_ports[i].port.iobase == 0) | 
|---|
| 653 | return &serial8250_ports[i]; | 
|---|
| 654 |  | 
|---|
| 655 | /* | 
|---|
| 656 | * That also failed.  Last resort is to find any entry which | 
|---|
| 657 | * doesn't have a real port associated with it. | 
|---|
| 658 | */ | 
|---|
| 659 | for (i = 0; i < nr_uarts; i++) | 
|---|
| 660 | if (serial8250_ports[i].port.type == PORT_UNKNOWN) | 
|---|
| 661 | return &serial8250_ports[i]; | 
|---|
| 662 |  | 
|---|
| 663 | return NULL; | 
|---|
| 664 | } | 
|---|
| 665 |  | 
|---|
| 666 | static void serial_8250_overrun_backoff_work(struct work_struct *work) | 
|---|
| 667 | { | 
|---|
| 668 | struct uart_8250_port *up = container_of(to_delayed_work(work), struct uart_8250_port, | 
|---|
| 669 | overrun_backoff); | 
|---|
| 670 |  | 
|---|
| 671 | guard(uart_port_lock_irqsave)(l: &up->port); | 
|---|
| 672 | up->ier |= UART_IER_RLSI | UART_IER_RDI; | 
|---|
| 673 | serial_out(up, UART_IER, value: up->ier); | 
|---|
| 674 | } | 
|---|
| 675 |  | 
|---|
| 676 | /** | 
|---|
| 677 | *	serial8250_register_8250_port - register a serial port | 
|---|
| 678 | *	@up: serial port template | 
|---|
| 679 | * | 
|---|
| 680 | *	Configure the serial port specified by the request. If the | 
|---|
| 681 | *	port exists and is in use, it is hung up and unregistered | 
|---|
| 682 | *	first. | 
|---|
| 683 | * | 
|---|
| 684 | *	The port is then probed and if necessary the IRQ is autodetected | 
|---|
| 685 | *	If this fails an error is returned. | 
|---|
| 686 | * | 
|---|
| 687 | *	On success the port is ready to use and the line number is returned. | 
|---|
| 688 | */ | 
|---|
| 689 | int serial8250_register_8250_port(const struct uart_8250_port *up) | 
|---|
| 690 | { | 
|---|
| 691 | struct uart_8250_port *uart; | 
|---|
| 692 | int ret; | 
|---|
| 693 |  | 
|---|
| 694 | if (up->port.uartclk == 0) | 
|---|
| 695 | return -EINVAL; | 
|---|
| 696 |  | 
|---|
| 697 | guard(mutex)(T: &serial_mutex); | 
|---|
| 698 |  | 
|---|
| 699 | uart = serial8250_find_match_or_unused(port: &up->port); | 
|---|
| 700 | if (!uart) { | 
|---|
| 701 | /* | 
|---|
| 702 | * If the port is past the initial isa ports, initialize a new | 
|---|
| 703 | * port and increment nr_uarts accordingly. | 
|---|
| 704 | */ | 
|---|
| 705 | uart = serial8250_setup_port(index: nr_uarts); | 
|---|
| 706 | if (!uart) | 
|---|
| 707 | return -ENOSPC; | 
|---|
| 708 | nr_uarts++; | 
|---|
| 709 | } | 
|---|
| 710 |  | 
|---|
| 711 | /* Check if it is CIR already. We check this below again, see there why. */ | 
|---|
| 712 | if (uart->port.type == PORT_8250_CIR) | 
|---|
| 713 | return -ENODEV; | 
|---|
| 714 |  | 
|---|
| 715 | if (uart->port.dev) | 
|---|
| 716 | uart_remove_one_port(reg: &serial8250_reg, port: &uart->port); | 
|---|
| 717 |  | 
|---|
| 718 | uart->port.ctrl_id	= up->port.ctrl_id; | 
|---|
| 719 | uart->port.port_id	= up->port.port_id; | 
|---|
| 720 | uart->port.iobase       = up->port.iobase; | 
|---|
| 721 | uart->port.membase      = up->port.membase; | 
|---|
| 722 | uart->port.irq          = up->port.irq; | 
|---|
| 723 | uart->port.irqflags     = up->port.irqflags; | 
|---|
| 724 | uart->port.uartclk      = up->port.uartclk; | 
|---|
| 725 | uart->port.fifosize     = up->port.fifosize; | 
|---|
| 726 | uart->port.regshift     = up->port.regshift; | 
|---|
| 727 | uart->port.iotype       = up->port.iotype; | 
|---|
| 728 | uart->port.flags        = up->port.flags | UPF_BOOT_AUTOCONF; | 
|---|
| 729 | uart->bugs		= up->bugs; | 
|---|
| 730 | uart->port.mapbase      = up->port.mapbase; | 
|---|
| 731 | uart->port.mapsize      = up->port.mapsize; | 
|---|
| 732 | uart->port.private_data = up->port.private_data; | 
|---|
| 733 | uart->tx_loadsz		= up->tx_loadsz; | 
|---|
| 734 | uart->capabilities	= up->capabilities; | 
|---|
| 735 | uart->port.throttle	= up->port.throttle; | 
|---|
| 736 | uart->port.unthrottle	= up->port.unthrottle; | 
|---|
| 737 | uart->port.rs485_config	= up->port.rs485_config; | 
|---|
| 738 | uart->port.rs485_supported = up->port.rs485_supported; | 
|---|
| 739 | uart->port.rs485	= up->port.rs485; | 
|---|
| 740 | uart->rs485_start_tx	= up->rs485_start_tx; | 
|---|
| 741 | uart->rs485_stop_tx	= up->rs485_stop_tx; | 
|---|
| 742 | uart->lsr_save_mask	= up->lsr_save_mask; | 
|---|
| 743 | uart->dma		= up->dma; | 
|---|
| 744 |  | 
|---|
| 745 | /* Take tx_loadsz from fifosize if it wasn't set separately */ | 
|---|
| 746 | if (uart->port.fifosize && !uart->tx_loadsz) | 
|---|
| 747 | uart->tx_loadsz = uart->port.fifosize; | 
|---|
| 748 |  | 
|---|
| 749 | if (up->port.dev) { | 
|---|
| 750 | uart->port.dev = up->port.dev; | 
|---|
| 751 | ret = uart_get_rs485_mode(port: &uart->port); | 
|---|
| 752 | if (ret) | 
|---|
| 753 | goto err; | 
|---|
| 754 | } | 
|---|
| 755 |  | 
|---|
| 756 | if (up->port.flags & UPF_FIXED_TYPE) | 
|---|
| 757 | uart->port.type = up->port.type; | 
|---|
| 758 |  | 
|---|
| 759 | /* | 
|---|
| 760 | * Only call mctrl_gpio_init(), if the device has no ACPI | 
|---|
| 761 | * companion device | 
|---|
| 762 | */ | 
|---|
| 763 | if (!has_acpi_companion(dev: uart->port.dev)) { | 
|---|
| 764 | struct mctrl_gpios *gpios = mctrl_gpio_init(port: &uart->port, idx: 0); | 
|---|
| 765 | if (IS_ERR(ptr: gpios)) { | 
|---|
| 766 | ret = PTR_ERR(ptr: gpios); | 
|---|
| 767 | goto err; | 
|---|
| 768 | } else { | 
|---|
| 769 | uart->gpios = gpios; | 
|---|
| 770 | } | 
|---|
| 771 | } | 
|---|
| 772 |  | 
|---|
| 773 | serial8250_set_defaults(up: uart); | 
|---|
| 774 |  | 
|---|
| 775 | /* Possibly override default I/O functions.  */ | 
|---|
| 776 | if (up->port.serial_in) | 
|---|
| 777 | uart->port.serial_in = up->port.serial_in; | 
|---|
| 778 | if (up->port.serial_out) | 
|---|
| 779 | uart->port.serial_out = up->port.serial_out; | 
|---|
| 780 | if (up->port.handle_irq) | 
|---|
| 781 | uart->port.handle_irq = up->port.handle_irq; | 
|---|
| 782 | /*  Possibly override set_termios call */ | 
|---|
| 783 | if (up->port.set_termios) | 
|---|
| 784 | uart->port.set_termios = up->port.set_termios; | 
|---|
| 785 | if (up->port.set_ldisc) | 
|---|
| 786 | uart->port.set_ldisc = up->port.set_ldisc; | 
|---|
| 787 | if (up->port.get_mctrl) | 
|---|
| 788 | uart->port.get_mctrl = up->port.get_mctrl; | 
|---|
| 789 | if (up->port.set_mctrl) | 
|---|
| 790 | uart->port.set_mctrl = up->port.set_mctrl; | 
|---|
| 791 | if (up->port.get_divisor) | 
|---|
| 792 | uart->port.get_divisor = up->port.get_divisor; | 
|---|
| 793 | if (up->port.set_divisor) | 
|---|
| 794 | uart->port.set_divisor = up->port.set_divisor; | 
|---|
| 795 | if (up->port.startup) | 
|---|
| 796 | uart->port.startup = up->port.startup; | 
|---|
| 797 | if (up->port.shutdown) | 
|---|
| 798 | uart->port.shutdown = up->port.shutdown; | 
|---|
| 799 | if (up->port.pm) | 
|---|
| 800 | uart->port.pm = up->port.pm; | 
|---|
| 801 | if (up->port.handle_break) | 
|---|
| 802 | uart->port.handle_break = up->port.handle_break; | 
|---|
| 803 | if (up->dl_read) | 
|---|
| 804 | uart->dl_read = up->dl_read; | 
|---|
| 805 | if (up->dl_write) | 
|---|
| 806 | uart->dl_write = up->dl_write; | 
|---|
| 807 |  | 
|---|
| 808 | /* Check the type (again)! It might have changed by the port.type assignment above. */ | 
|---|
| 809 | if (uart->port.type != PORT_8250_CIR) { | 
|---|
| 810 | if (uart_console_registered(port: &uart->port)) | 
|---|
| 811 | pm_runtime_get_sync(dev: uart->port.dev); | 
|---|
| 812 |  | 
|---|
| 813 | if (serial8250_isa_config != NULL) | 
|---|
| 814 | serial8250_isa_config(0, &uart->port, | 
|---|
| 815 | &uart->capabilities); | 
|---|
| 816 |  | 
|---|
| 817 | serial8250_apply_quirks(up: uart); | 
|---|
| 818 | ret = uart_add_one_port(reg: &serial8250_reg, | 
|---|
| 819 | port: &uart->port); | 
|---|
| 820 | if (ret) | 
|---|
| 821 | goto err; | 
|---|
| 822 |  | 
|---|
| 823 | ret = uart->port.line; | 
|---|
| 824 | } else { | 
|---|
| 825 | dev_info(uart->port.dev, | 
|---|
| 826 | "skipping CIR port at 0x%lx / 0x%llx, IRQ %d\n", | 
|---|
| 827 | uart->port.iobase, | 
|---|
| 828 | (unsigned long long)uart->port.mapbase, | 
|---|
| 829 | uart->port.irq); | 
|---|
| 830 |  | 
|---|
| 831 | ret = 0; | 
|---|
| 832 | } | 
|---|
| 833 |  | 
|---|
| 834 | if (!uart->lsr_save_mask) | 
|---|
| 835 | uart->lsr_save_mask = LSR_SAVE_FLAGS;	/* Use default LSR mask */ | 
|---|
| 836 |  | 
|---|
| 837 | /* Initialise interrupt backoff work if required */ | 
|---|
| 838 | if (up->overrun_backoff_time_ms > 0) { | 
|---|
| 839 | uart->overrun_backoff_time_ms = | 
|---|
| 840 | up->overrun_backoff_time_ms; | 
|---|
| 841 | INIT_DELAYED_WORK(&uart->overrun_backoff, | 
|---|
| 842 | serial_8250_overrun_backoff_work); | 
|---|
| 843 | } else { | 
|---|
| 844 | uart->overrun_backoff_time_ms = 0; | 
|---|
| 845 | } | 
|---|
| 846 |  | 
|---|
| 847 | return ret; | 
|---|
| 848 |  | 
|---|
| 849 | err: | 
|---|
| 850 | uart->port.dev = NULL; | 
|---|
| 851 | return ret; | 
|---|
| 852 | } | 
|---|
| 853 | EXPORT_SYMBOL(serial8250_register_8250_port); | 
|---|
| 854 |  | 
|---|
| 855 | /** | 
|---|
| 856 | *	serial8250_unregister_port - remove a 16x50 serial port at runtime | 
|---|
| 857 | *	@line: serial line number | 
|---|
| 858 | * | 
|---|
| 859 | *	Remove one serial port.  This may not be called from interrupt | 
|---|
| 860 | *	context.  We hand the port back to the our control. | 
|---|
| 861 | */ | 
|---|
| 862 | void serial8250_unregister_port(int line) | 
|---|
| 863 | { | 
|---|
| 864 | struct uart_8250_port *uart = &serial8250_ports[line]; | 
|---|
| 865 |  | 
|---|
| 866 | guard(mutex)(T: &serial_mutex); | 
|---|
| 867 |  | 
|---|
| 868 | if (uart->em485) { | 
|---|
| 869 | guard(uart_port_lock_irqsave)(l: &uart->port); | 
|---|
| 870 | serial8250_em485_destroy(p: uart); | 
|---|
| 871 | } | 
|---|
| 872 |  | 
|---|
| 873 | uart_remove_one_port(reg: &serial8250_reg, port: &uart->port); | 
|---|
| 874 | if (serial8250_isa_devs) { | 
|---|
| 875 | uart->port.flags &= ~UPF_BOOT_AUTOCONF; | 
|---|
| 876 | uart->port.type = PORT_UNKNOWN; | 
|---|
| 877 | uart->port.dev = &serial8250_isa_devs->dev; | 
|---|
| 878 | uart->port.port_id = line; | 
|---|
| 879 | uart->capabilities = 0; | 
|---|
| 880 | serial8250_init_port(up: uart); | 
|---|
| 881 | serial8250_apply_quirks(up: uart); | 
|---|
| 882 | uart_add_one_port(reg: &serial8250_reg, port: &uart->port); | 
|---|
| 883 | } else { | 
|---|
| 884 | uart->port.dev = NULL; | 
|---|
| 885 | } | 
|---|
| 886 | } | 
|---|
| 887 | EXPORT_SYMBOL(serial8250_unregister_port); | 
|---|
| 888 |  | 
|---|
| 889 | MODULE_LICENSE( "GPL"); | 
|---|
| 890 | MODULE_DESCRIPTION( "Generic 8250/16x50 serial driver"); | 
|---|
| 891 |  | 
|---|