diff options
Diffstat (limited to 'drivers/tty/serial/8250')
-rw-r--r-- | drivers/tty/serial/8250/8250.c | 312 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250.h | 16 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_em.c | 186 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_pci.c | 63 | ||||
-rw-r--r-- | drivers/tty/serial/8250/Kconfig | 8 | ||||
-rw-r--r-- | drivers/tty/serial/8250/Makefile | 1 |
6 files changed, 424 insertions, 162 deletions
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index 5c27f7e6c9f1..47d061b9ad4d 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c | |||
@@ -284,7 +284,20 @@ static const struct serial8250_config uart_config[] = { | |||
284 | }, | 284 | }, |
285 | }; | 285 | }; |
286 | 286 | ||
287 | #if defined(CONFIG_MIPS_ALCHEMY) | 287 | /* Uart divisor latch read */ |
288 | static int default_serial_dl_read(struct uart_8250_port *up) | ||
289 | { | ||
290 | return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8; | ||
291 | } | ||
292 | |||
293 | /* Uart divisor latch write */ | ||
294 | static void default_serial_dl_write(struct uart_8250_port *up, int value) | ||
295 | { | ||
296 | serial_out(up, UART_DLL, value & 0xff); | ||
297 | serial_out(up, UART_DLM, value >> 8 & 0xff); | ||
298 | } | ||
299 | |||
300 | #ifdef CONFIG_MIPS_ALCHEMY | ||
288 | 301 | ||
289 | /* Au1x00 UART hardware has a weird register layout */ | 302 | /* Au1x00 UART hardware has a weird register layout */ |
290 | static const u8 au_io_in_map[] = { | 303 | static const u8 au_io_in_map[] = { |
@@ -305,22 +318,32 @@ static const u8 au_io_out_map[] = { | |||
305 | [UART_MCR] = 6, | 318 | [UART_MCR] = 6, |
306 | }; | 319 | }; |
307 | 320 | ||
308 | /* sane hardware needs no mapping */ | 321 | static unsigned int au_serial_in(struct uart_port *p, int offset) |
309 | static inline int map_8250_in_reg(struct uart_port *p, int offset) | 322 | { |
323 | offset = au_io_in_map[offset] << p->regshift; | ||
324 | return __raw_readl(p->membase + offset); | ||
325 | } | ||
326 | |||
327 | static void au_serial_out(struct uart_port *p, int offset, int value) | ||
328 | { | ||
329 | offset = au_io_out_map[offset] << p->regshift; | ||
330 | __raw_writel(value, p->membase + offset); | ||
331 | } | ||
332 | |||
333 | /* Au1x00 haven't got a standard divisor latch */ | ||
334 | static int au_serial_dl_read(struct uart_8250_port *up) | ||
310 | { | 335 | { |
311 | if (p->iotype != UPIO_AU) | 336 | return __raw_readl(up->port.membase + 0x28); |
312 | return offset; | ||
313 | return au_io_in_map[offset]; | ||
314 | } | 337 | } |
315 | 338 | ||
316 | static inline int map_8250_out_reg(struct uart_port *p, int offset) | 339 | static void au_serial_dl_write(struct uart_8250_port *up, int value) |
317 | { | 340 | { |
318 | if (p->iotype != UPIO_AU) | 341 | __raw_writel(value, up->port.membase + 0x28); |
319 | return offset; | ||
320 | return au_io_out_map[offset]; | ||
321 | } | 342 | } |
322 | 343 | ||
323 | #elif defined(CONFIG_SERIAL_8250_RM9K) | 344 | #endif |
345 | |||
346 | #ifdef CONFIG_SERIAL_8250_RM9K | ||
324 | 347 | ||
325 | static const u8 | 348 | static const u8 |
326 | regmap_in[8] = { | 349 | regmap_in[8] = { |
@@ -344,87 +367,79 @@ static const u8 | |||
344 | [UART_SCR] = 0x2c | 367 | [UART_SCR] = 0x2c |
345 | }; | 368 | }; |
346 | 369 | ||
347 | static inline int map_8250_in_reg(struct uart_port *p, int offset) | 370 | static unsigned int rm9k_serial_in(struct uart_port *p, int offset) |
348 | { | 371 | { |
349 | if (p->iotype != UPIO_RM9000) | 372 | offset = regmap_in[offset] << p->regshift; |
350 | return offset; | 373 | return readl(p->membase + offset); |
351 | return regmap_in[offset]; | ||
352 | } | 374 | } |
353 | 375 | ||
354 | static inline int map_8250_out_reg(struct uart_port *p, int offset) | 376 | static void rm9k_serial_out(struct uart_port *p, int offset, int value) |
355 | { | 377 | { |
356 | if (p->iotype != UPIO_RM9000) | 378 | offset = regmap_out[offset] << p->regshift; |
357 | return offset; | 379 | writel(value, p->membase + offset); |
358 | return regmap_out[offset]; | ||
359 | } | 380 | } |
360 | 381 | ||
361 | #else | 382 | static int rm9k_serial_dl_read(struct uart_8250_port *up) |
383 | { | ||
384 | return ((__raw_readl(up->port.membase + 0x10) << 8) | | ||
385 | (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff; | ||
386 | } | ||
362 | 387 | ||
363 | /* sane hardware needs no mapping */ | 388 | static void rm9k_serial_dl_write(struct uart_8250_port *up, int value) |
364 | #define map_8250_in_reg(up, offset) (offset) | 389 | { |
365 | #define map_8250_out_reg(up, offset) (offset) | 390 | __raw_writel(value, up->port.membase + 0x08); |
391 | __raw_writel(value >> 8, up->port.membase + 0x10); | ||
392 | } | ||
366 | 393 | ||
367 | #endif | 394 | #endif |
368 | 395 | ||
369 | static unsigned int hub6_serial_in(struct uart_port *p, int offset) | 396 | static unsigned int hub6_serial_in(struct uart_port *p, int offset) |
370 | { | 397 | { |
371 | offset = map_8250_in_reg(p, offset) << p->regshift; | 398 | offset = offset << p->regshift; |
372 | outb(p->hub6 - 1 + offset, p->iobase); | 399 | outb(p->hub6 - 1 + offset, p->iobase); |
373 | return inb(p->iobase + 1); | 400 | return inb(p->iobase + 1); |
374 | } | 401 | } |
375 | 402 | ||
376 | static void hub6_serial_out(struct uart_port *p, int offset, int value) | 403 | static void hub6_serial_out(struct uart_port *p, int offset, int value) |
377 | { | 404 | { |
378 | offset = map_8250_out_reg(p, offset) << p->regshift; | 405 | offset = offset << p->regshift; |
379 | outb(p->hub6 - 1 + offset, p->iobase); | 406 | outb(p->hub6 - 1 + offset, p->iobase); |
380 | outb(value, p->iobase + 1); | 407 | outb(value, p->iobase + 1); |
381 | } | 408 | } |
382 | 409 | ||
383 | static unsigned int mem_serial_in(struct uart_port *p, int offset) | 410 | static unsigned int mem_serial_in(struct uart_port *p, int offset) |
384 | { | 411 | { |
385 | offset = map_8250_in_reg(p, offset) << p->regshift; | 412 | offset = offset << p->regshift; |
386 | return readb(p->membase + offset); | 413 | return readb(p->membase + offset); |
387 | } | 414 | } |
388 | 415 | ||
389 | static void mem_serial_out(struct uart_port *p, int offset, int value) | 416 | static void mem_serial_out(struct uart_port *p, int offset, int value) |
390 | { | 417 | { |
391 | offset = map_8250_out_reg(p, offset) << p->regshift; | 418 | offset = offset << p->regshift; |
392 | writeb(value, p->membase + offset); | 419 | writeb(value, p->membase + offset); |
393 | } | 420 | } |
394 | 421 | ||
395 | static void mem32_serial_out(struct uart_port *p, int offset, int value) | 422 | static void mem32_serial_out(struct uart_port *p, int offset, int value) |
396 | { | 423 | { |
397 | offset = map_8250_out_reg(p, offset) << p->regshift; | 424 | offset = offset << p->regshift; |
398 | writel(value, p->membase + offset); | 425 | writel(value, p->membase + offset); |
399 | } | 426 | } |
400 | 427 | ||
401 | static unsigned int mem32_serial_in(struct uart_port *p, int offset) | 428 | static unsigned int mem32_serial_in(struct uart_port *p, int offset) |
402 | { | 429 | { |
403 | offset = map_8250_in_reg(p, offset) << p->regshift; | 430 | offset = offset << p->regshift; |
404 | return readl(p->membase + offset); | 431 | return readl(p->membase + offset); |
405 | } | 432 | } |
406 | 433 | ||
407 | static unsigned int au_serial_in(struct uart_port *p, int offset) | ||
408 | { | ||
409 | offset = map_8250_in_reg(p, offset) << p->regshift; | ||
410 | return __raw_readl(p->membase + offset); | ||
411 | } | ||
412 | |||
413 | static void au_serial_out(struct uart_port *p, int offset, int value) | ||
414 | { | ||
415 | offset = map_8250_out_reg(p, offset) << p->regshift; | ||
416 | __raw_writel(value, p->membase + offset); | ||
417 | } | ||
418 | |||
419 | static unsigned int io_serial_in(struct uart_port *p, int offset) | 434 | static unsigned int io_serial_in(struct uart_port *p, int offset) |
420 | { | 435 | { |
421 | offset = map_8250_in_reg(p, offset) << p->regshift; | 436 | offset = offset << p->regshift; |
422 | return inb(p->iobase + offset); | 437 | return inb(p->iobase + offset); |
423 | } | 438 | } |
424 | 439 | ||
425 | static void io_serial_out(struct uart_port *p, int offset, int value) | 440 | static void io_serial_out(struct uart_port *p, int offset, int value) |
426 | { | 441 | { |
427 | offset = map_8250_out_reg(p, offset) << p->regshift; | 442 | offset = offset << p->regshift; |
428 | outb(value, p->iobase + offset); | 443 | outb(value, p->iobase + offset); |
429 | } | 444 | } |
430 | 445 | ||
@@ -434,6 +449,10 @@ static void set_io_from_upio(struct uart_port *p) | |||
434 | { | 449 | { |
435 | struct uart_8250_port *up = | 450 | struct uart_8250_port *up = |
436 | container_of(p, struct uart_8250_port, port); | 451 | container_of(p, struct uart_8250_port, port); |
452 | |||
453 | up->dl_read = default_serial_dl_read; | ||
454 | up->dl_write = default_serial_dl_write; | ||
455 | |||
437 | switch (p->iotype) { | 456 | switch (p->iotype) { |
438 | case UPIO_HUB6: | 457 | case UPIO_HUB6: |
439 | p->serial_in = hub6_serial_in; | 458 | p->serial_in = hub6_serial_in; |
@@ -445,16 +464,28 @@ static void set_io_from_upio(struct uart_port *p) | |||
445 | p->serial_out = mem_serial_out; | 464 | p->serial_out = mem_serial_out; |
446 | break; | 465 | break; |
447 | 466 | ||
448 | case UPIO_RM9000: | ||
449 | case UPIO_MEM32: | 467 | case UPIO_MEM32: |
450 | p->serial_in = mem32_serial_in; | 468 | p->serial_in = mem32_serial_in; |
451 | p->serial_out = mem32_serial_out; | 469 | p->serial_out = mem32_serial_out; |
452 | break; | 470 | break; |
453 | 471 | ||
472 | #ifdef CONFIG_SERIAL_8250_RM9K | ||
473 | case UPIO_RM9000: | ||
474 | p->serial_in = rm9k_serial_in; | ||
475 | p->serial_out = rm9k_serial_out; | ||
476 | up->dl_read = rm9k_serial_dl_read; | ||
477 | up->dl_write = rm9k_serial_dl_write; | ||
478 | break; | ||
479 | #endif | ||
480 | |||
481 | #ifdef CONFIG_MIPS_ALCHEMY | ||
454 | case UPIO_AU: | 482 | case UPIO_AU: |
455 | p->serial_in = au_serial_in; | 483 | p->serial_in = au_serial_in; |
456 | p->serial_out = au_serial_out; | 484 | p->serial_out = au_serial_out; |
485 | up->dl_read = au_serial_dl_read; | ||
486 | up->dl_write = au_serial_dl_write; | ||
457 | break; | 487 | break; |
488 | #endif | ||
458 | 489 | ||
459 | default: | 490 | default: |
460 | p->serial_in = io_serial_in; | 491 | p->serial_in = io_serial_in; |
@@ -481,59 +512,6 @@ serial_port_out_sync(struct uart_port *p, int offset, int value) | |||
481 | } | 512 | } |
482 | } | 513 | } |
483 | 514 | ||
484 | /* Uart divisor latch read */ | ||
485 | static inline int _serial_dl_read(struct uart_8250_port *up) | ||
486 | { | ||
487 | return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8; | ||
488 | } | ||
489 | |||
490 | /* Uart divisor latch write */ | ||
491 | static inline void _serial_dl_write(struct uart_8250_port *up, int value) | ||
492 | { | ||
493 | serial_out(up, UART_DLL, value & 0xff); | ||
494 | serial_out(up, UART_DLM, value >> 8 & 0xff); | ||
495 | } | ||
496 | |||
497 | #if defined(CONFIG_MIPS_ALCHEMY) | ||
498 | /* Au1x00 haven't got a standard divisor latch */ | ||
499 | static int serial_dl_read(struct uart_8250_port *up) | ||
500 | { | ||
501 | if (up->port.iotype == UPIO_AU) | ||
502 | return __raw_readl(up->port.membase + 0x28); | ||
503 | else | ||
504 | return _serial_dl_read(up); | ||
505 | } | ||
506 | |||
507 | static void serial_dl_write(struct uart_8250_port *up, int value) | ||
508 | { | ||
509 | if (up->port.iotype == UPIO_AU) | ||
510 | __raw_writel(value, up->port.membase + 0x28); | ||
511 | else | ||
512 | _serial_dl_write(up, value); | ||
513 | } | ||
514 | #elif defined(CONFIG_SERIAL_8250_RM9K) | ||
515 | static int serial_dl_read(struct uart_8250_port *up) | ||
516 | { | ||
517 | return (up->port.iotype == UPIO_RM9000) ? | ||
518 | (((__raw_readl(up->port.membase + 0x10) << 8) | | ||
519 | (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff) : | ||
520 | _serial_dl_read(up); | ||
521 | } | ||
522 | |||
523 | static void serial_dl_write(struct uart_8250_port *up, int value) | ||
524 | { | ||
525 | if (up->port.iotype == UPIO_RM9000) { | ||
526 | __raw_writel(value, up->port.membase + 0x08); | ||
527 | __raw_writel(value >> 8, up->port.membase + 0x10); | ||
528 | } else { | ||
529 | _serial_dl_write(up, value); | ||
530 | } | ||
531 | } | ||
532 | #else | ||
533 | #define serial_dl_read(up) _serial_dl_read(up) | ||
534 | #define serial_dl_write(up, value) _serial_dl_write(up, value) | ||
535 | #endif | ||
536 | |||
537 | /* | 515 | /* |
538 | * For the 16C950 | 516 | * For the 16C950 |
539 | */ | 517 | */ |
@@ -568,6 +546,16 @@ static void serial8250_clear_fifos(struct uart_8250_port *p) | |||
568 | } | 546 | } |
569 | } | 547 | } |
570 | 548 | ||
549 | void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p) | ||
550 | { | ||
551 | unsigned char fcr; | ||
552 | |||
553 | serial8250_clear_fifos(p); | ||
554 | fcr = uart_config[p->port.type].fcr; | ||
555 | serial_out(p, UART_FCR, fcr); | ||
556 | } | ||
557 | EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos); | ||
558 | |||
571 | /* | 559 | /* |
572 | * IER sleep support. UARTs which have EFRs need the "extended | 560 | * IER sleep support. UARTs which have EFRs need the "extended |
573 | * capability" bit enabled. Note that on XR16C850s, we need to | 561 | * capability" bit enabled. Note that on XR16C850s, we need to |
@@ -1332,27 +1320,6 @@ static void serial8250_enable_ms(struct uart_port *port) | |||
1332 | } | 1320 | } |
1333 | 1321 | ||
1334 | /* | 1322 | /* |
1335 | * Clear the Tegra rx fifo after a break | ||
1336 | * | ||
1337 | * FIXME: This needs to become a port specific callback once we have a | ||
1338 | * framework for this | ||
1339 | */ | ||
1340 | static void clear_rx_fifo(struct uart_8250_port *up) | ||
1341 | { | ||
1342 | unsigned int status, tmout = 10000; | ||
1343 | do { | ||
1344 | status = serial_in(up, UART_LSR); | ||
1345 | if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS)) | ||
1346 | status = serial_in(up, UART_RX); | ||
1347 | else | ||
1348 | break; | ||
1349 | if (--tmout == 0) | ||
1350 | break; | ||
1351 | udelay(1); | ||
1352 | } while (1); | ||
1353 | } | ||
1354 | |||
1355 | /* | ||
1356 | * serial8250_rx_chars: processes according to the passed in LSR | 1323 | * serial8250_rx_chars: processes according to the passed in LSR |
1357 | * value, and returns the remaining LSR bits not handled | 1324 | * value, and returns the remaining LSR bits not handled |
1358 | * by this Rx routine. | 1325 | * by this Rx routine. |
@@ -1386,20 +1353,10 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) | |||
1386 | up->lsr_saved_flags = 0; | 1353 | up->lsr_saved_flags = 0; |
1387 | 1354 | ||
1388 | if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) { | 1355 | if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) { |
1389 | /* | ||
1390 | * For statistics only | ||
1391 | */ | ||
1392 | if (lsr & UART_LSR_BI) { | 1356 | if (lsr & UART_LSR_BI) { |
1393 | lsr &= ~(UART_LSR_FE | UART_LSR_PE); | 1357 | lsr &= ~(UART_LSR_FE | UART_LSR_PE); |
1394 | port->icount.brk++; | 1358 | port->icount.brk++; |
1395 | /* | 1359 | /* |
1396 | * If tegra port then clear the rx fifo to | ||
1397 | * accept another break/character. | ||
1398 | */ | ||
1399 | if (port->type == PORT_TEGRA) | ||
1400 | clear_rx_fifo(up); | ||
1401 | |||
1402 | /* | ||
1403 | * We do the SysRQ and SAK checking | 1360 | * We do the SysRQ and SAK checking |
1404 | * here because otherwise the break | 1361 | * here because otherwise the break |
1405 | * may get masked by ignore_status_mask | 1362 | * may get masked by ignore_status_mask |
@@ -2280,10 +2237,11 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, | |||
2280 | quot++; | 2237 | quot++; |
2281 | 2238 | ||
2282 | if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) { | 2239 | if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) { |
2283 | if (baud < 2400) | 2240 | fcr = uart_config[port->type].fcr; |
2284 | fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; | 2241 | if (baud < 2400) { |
2285 | else | 2242 | fcr &= ~UART_FCR_TRIGGER_MASK; |
2286 | fcr = uart_config[port->type].fcr; | 2243 | fcr |= UART_FCR_TRIGGER_1; |
2244 | } | ||
2287 | } | 2245 | } |
2288 | 2246 | ||
2289 | /* | 2247 | /* |
@@ -3037,6 +2995,7 @@ static int __devinit serial8250_probe(struct platform_device *dev) | |||
3037 | port.serial_in = p->serial_in; | 2995 | port.serial_in = p->serial_in; |
3038 | port.serial_out = p->serial_out; | 2996 | port.serial_out = p->serial_out; |
3039 | port.handle_irq = p->handle_irq; | 2997 | port.handle_irq = p->handle_irq; |
2998 | port.handle_break = p->handle_break; | ||
3040 | port.set_termios = p->set_termios; | 2999 | port.set_termios = p->set_termios; |
3041 | port.pm = p->pm; | 3000 | port.pm = p->pm; |
3042 | port.dev = &dev->dev; | 3001 | port.dev = &dev->dev; |
@@ -3153,7 +3112,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port * | |||
3153 | } | 3112 | } |
3154 | 3113 | ||
3155 | /** | 3114 | /** |
3156 | * serial8250_register_port - register a serial port | 3115 | * serial8250_register_8250_port - register a serial port |
3157 | * @port: serial port template | 3116 | * @port: serial port template |
3158 | * | 3117 | * |
3159 | * Configure the serial port specified by the request. If the | 3118 | * Configure the serial port specified by the request. If the |
@@ -3165,50 +3124,56 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port * | |||
3165 | * | 3124 | * |
3166 | * On success the port is ready to use and the line number is returned. | 3125 | * On success the port is ready to use and the line number is returned. |
3167 | */ | 3126 | */ |
3168 | int serial8250_register_port(struct uart_port *port) | 3127 | int serial8250_register_8250_port(struct uart_8250_port *up) |
3169 | { | 3128 | { |
3170 | struct uart_8250_port *uart; | 3129 | struct uart_8250_port *uart; |
3171 | int ret = -ENOSPC; | 3130 | int ret = -ENOSPC; |
3172 | 3131 | ||
3173 | if (port->uartclk == 0) | 3132 | if (up->port.uartclk == 0) |
3174 | return -EINVAL; | 3133 | return -EINVAL; |
3175 | 3134 | ||
3176 | mutex_lock(&serial_mutex); | 3135 | mutex_lock(&serial_mutex); |
3177 | 3136 | ||
3178 | uart = serial8250_find_match_or_unused(port); | 3137 | uart = serial8250_find_match_or_unused(&up->port); |
3179 | if (uart) { | 3138 | if (uart) { |
3180 | uart_remove_one_port(&serial8250_reg, &uart->port); | 3139 | uart_remove_one_port(&serial8250_reg, &uart->port); |
3181 | 3140 | ||
3182 | uart->port.iobase = port->iobase; | 3141 | uart->port.iobase = up->port.iobase; |
3183 | uart->port.membase = port->membase; | 3142 | uart->port.membase = up->port.membase; |
3184 | uart->port.irq = port->irq; | 3143 | uart->port.irq = up->port.irq; |
3185 | uart->port.irqflags = port->irqflags; | 3144 | uart->port.irqflags = up->port.irqflags; |
3186 | uart->port.uartclk = port->uartclk; | 3145 | uart->port.uartclk = up->port.uartclk; |
3187 | uart->port.fifosize = port->fifosize; | 3146 | uart->port.fifosize = up->port.fifosize; |
3188 | uart->port.regshift = port->regshift; | 3147 | uart->port.regshift = up->port.regshift; |
3189 | uart->port.iotype = port->iotype; | 3148 | uart->port.iotype = up->port.iotype; |
3190 | uart->port.flags = port->flags | UPF_BOOT_AUTOCONF; | 3149 | uart->port.flags = up->port.flags | UPF_BOOT_AUTOCONF; |
3191 | uart->port.mapbase = port->mapbase; | 3150 | uart->port.mapbase = up->port.mapbase; |
3192 | uart->port.private_data = port->private_data; | 3151 | uart->port.private_data = up->port.private_data; |
3193 | if (port->dev) | 3152 | if (up->port.dev) |
3194 | uart->port.dev = port->dev; | 3153 | uart->port.dev = up->port.dev; |
3195 | 3154 | ||
3196 | if (port->flags & UPF_FIXED_TYPE) | 3155 | if (up->port.flags & UPF_FIXED_TYPE) |
3197 | serial8250_init_fixed_type_port(uart, port->type); | 3156 | serial8250_init_fixed_type_port(uart, up->port.type); |
3198 | 3157 | ||
3199 | set_io_from_upio(&uart->port); | 3158 | set_io_from_upio(&uart->port); |
3200 | /* Possibly override default I/O functions. */ | 3159 | /* Possibly override default I/O functions. */ |
3201 | if (port->serial_in) | 3160 | if (up->port.serial_in) |
3202 | uart->port.serial_in = port->serial_in; | 3161 | uart->port.serial_in = up->port.serial_in; |
3203 | if (port->serial_out) | 3162 | if (up->port.serial_out) |
3204 | uart->port.serial_out = port->serial_out; | 3163 | uart->port.serial_out = up->port.serial_out; |
3205 | if (port->handle_irq) | 3164 | if (up->port.handle_irq) |
3206 | uart->port.handle_irq = port->handle_irq; | 3165 | uart->port.handle_irq = up->port.handle_irq; |
3207 | /* Possibly override set_termios call */ | 3166 | /* Possibly override set_termios call */ |
3208 | if (port->set_termios) | 3167 | if (up->port.set_termios) |
3209 | uart->port.set_termios = port->set_termios; | 3168 | uart->port.set_termios = up->port.set_termios; |
3210 | if (port->pm) | 3169 | if (up->port.pm) |
3211 | uart->port.pm = port->pm; | 3170 | uart->port.pm = up->port.pm; |
3171 | if (up->port.handle_break) | ||
3172 | uart->port.handle_break = up->port.handle_break; | ||
3173 | if (up->dl_read) | ||
3174 | uart->dl_read = up->dl_read; | ||
3175 | if (up->dl_write) | ||
3176 | uart->dl_write = up->dl_write; | ||
3212 | 3177 | ||
3213 | if (serial8250_isa_config != NULL) | 3178 | if (serial8250_isa_config != NULL) |
3214 | serial8250_isa_config(0, &uart->port, | 3179 | serial8250_isa_config(0, &uart->port, |
@@ -3222,6 +3187,29 @@ int serial8250_register_port(struct uart_port *port) | |||
3222 | 3187 | ||
3223 | return ret; | 3188 | return ret; |
3224 | } | 3189 | } |
3190 | EXPORT_SYMBOL(serial8250_register_8250_port); | ||
3191 | |||
3192 | /** | ||
3193 | * serial8250_register_port - register a serial port | ||
3194 | * @port: serial port template | ||
3195 | * | ||
3196 | * Configure the serial port specified by the request. If the | ||
3197 | * port exists and is in use, it is hung up and unregistered | ||
3198 | * first. | ||
3199 | * | ||
3200 | * The port is then probed and if necessary the IRQ is autodetected | ||
3201 | * If this fails an error is returned. | ||
3202 | * | ||
3203 | * On success the port is ready to use and the line number is returned. | ||
3204 | */ | ||
3205 | int serial8250_register_port(struct uart_port *port) | ||
3206 | { | ||
3207 | struct uart_8250_port up; | ||
3208 | |||
3209 | memset(&up, 0, sizeof(up)); | ||
3210 | memcpy(&up.port, port, sizeof(*port)); | ||
3211 | return serial8250_register_8250_port(&up); | ||
3212 | } | ||
3225 | EXPORT_SYMBOL(serial8250_register_port); | 3213 | EXPORT_SYMBOL(serial8250_register_port); |
3226 | 3214 | ||
3227 | /** | 3215 | /** |
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index 2868a1da254d..f9719d167c8d 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h | |||
@@ -37,6 +37,10 @@ struct uart_8250_port { | |||
37 | unsigned char lsr_saved_flags; | 37 | unsigned char lsr_saved_flags; |
38 | #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA | 38 | #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA |
39 | unsigned char msr_saved_flags; | 39 | unsigned char msr_saved_flags; |
40 | |||
41 | /* 8250 specific callbacks */ | ||
42 | int (*dl_read)(struct uart_8250_port *); | ||
43 | void (*dl_write)(struct uart_8250_port *, int); | ||
40 | }; | 44 | }; |
41 | 45 | ||
42 | struct old_serial_port { | 46 | struct old_serial_port { |
@@ -96,6 +100,18 @@ static inline void serial_out(struct uart_8250_port *up, int offset, int value) | |||
96 | up->port.serial_out(&up->port, offset, value); | 100 | up->port.serial_out(&up->port, offset, value); |
97 | } | 101 | } |
98 | 102 | ||
103 | void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p); | ||
104 | |||
105 | static inline int serial_dl_read(struct uart_8250_port *up) | ||
106 | { | ||
107 | return up->dl_read(up); | ||
108 | } | ||
109 | |||
110 | static inline void serial_dl_write(struct uart_8250_port *up, int value) | ||
111 | { | ||
112 | up->dl_write(up, value); | ||
113 | } | ||
114 | |||
99 | #if defined(__alpha__) && !defined(CONFIG_PCI) | 115 | #if defined(__alpha__) && !defined(CONFIG_PCI) |
100 | /* | 116 | /* |
101 | * Digital did something really horribly wrong with the OUT1 and OUT2 | 117 | * Digital did something really horribly wrong with the OUT1 and OUT2 |
diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c new file mode 100644 index 000000000000..3a0363e7f3a7 --- /dev/null +++ b/drivers/tty/serial/8250/8250_em.c | |||
@@ -0,0 +1,186 @@ | |||
1 | /* | ||
2 | * Renesas Emma Mobile 8250 driver | ||
3 | * | ||
4 | * Copyright (C) 2012 Magnus Damm | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | #include <linux/device.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/io.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/serial_8250.h> | ||
25 | #include <linux/serial_core.h> | ||
26 | #include <linux/serial_reg.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | #include <linux/clk.h> | ||
29 | #include <linux/slab.h> | ||
30 | |||
31 | #include "8250.h" | ||
32 | |||
33 | #define UART_DLL_EM 9 | ||
34 | #define UART_DLM_EM 10 | ||
35 | |||
36 | struct serial8250_em_priv { | ||
37 | struct clk *sclk; | ||
38 | int line; | ||
39 | }; | ||
40 | |||
41 | static void serial8250_em_serial_out(struct uart_port *p, int offset, int value) | ||
42 | { | ||
43 | switch (offset) { | ||
44 | case UART_TX: /* TX @ 0x00 */ | ||
45 | writeb(value, p->membase); | ||
46 | break; | ||
47 | case UART_FCR: /* FCR @ 0x0c (+1) */ | ||
48 | case UART_LCR: /* LCR @ 0x10 (+1) */ | ||
49 | case UART_MCR: /* MCR @ 0x14 (+1) */ | ||
50 | case UART_SCR: /* SCR @ 0x20 (+1) */ | ||
51 | writel(value, p->membase + ((offset + 1) << 2)); | ||
52 | break; | ||
53 | case UART_IER: /* IER @ 0x04 */ | ||
54 | value &= 0x0f; /* only 4 valid bits - not Xscale */ | ||
55 | /* fall-through */ | ||
56 | case UART_DLL_EM: /* DLL @ 0x24 (+9) */ | ||
57 | case UART_DLM_EM: /* DLM @ 0x28 (+9) */ | ||
58 | writel(value, p->membase + (offset << 2)); | ||
59 | } | ||
60 | } | ||
61 | |||
62 | static unsigned int serial8250_em_serial_in(struct uart_port *p, int offset) | ||
63 | { | ||
64 | switch (offset) { | ||
65 | case UART_RX: /* RX @ 0x00 */ | ||
66 | return readb(p->membase); | ||
67 | case UART_MCR: /* MCR @ 0x14 (+1) */ | ||
68 | case UART_LSR: /* LSR @ 0x18 (+1) */ | ||
69 | case UART_MSR: /* MSR @ 0x1c (+1) */ | ||
70 | case UART_SCR: /* SCR @ 0x20 (+1) */ | ||
71 | return readl(p->membase + ((offset + 1) << 2)); | ||
72 | case UART_IER: /* IER @ 0x04 */ | ||
73 | case UART_IIR: /* IIR @ 0x08 */ | ||
74 | case UART_DLL_EM: /* DLL @ 0x24 (+9) */ | ||
75 | case UART_DLM_EM: /* DLM @ 0x28 (+9) */ | ||
76 | return readl(p->membase + (offset << 2)); | ||
77 | } | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | static int serial8250_em_serial_dl_read(struct uart_8250_port *up) | ||
82 | { | ||
83 | return serial_in(up, UART_DLL_EM) | serial_in(up, UART_DLM_EM) << 8; | ||
84 | } | ||
85 | |||
86 | static void serial8250_em_serial_dl_write(struct uart_8250_port *up, int value) | ||
87 | { | ||
88 | serial_out(up, UART_DLL_EM, value & 0xff); | ||
89 | serial_out(up, UART_DLM_EM, value >> 8 & 0xff); | ||
90 | } | ||
91 | |||
92 | static int __devinit serial8250_em_probe(struct platform_device *pdev) | ||
93 | { | ||
94 | struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
95 | struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
96 | struct serial8250_em_priv *priv; | ||
97 | struct uart_8250_port up; | ||
98 | int ret = -EINVAL; | ||
99 | |||
100 | if (!regs || !irq) { | ||
101 | dev_err(&pdev->dev, "missing registers or irq\n"); | ||
102 | goto err0; | ||
103 | } | ||
104 | |||
105 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
106 | if (!priv) { | ||
107 | dev_err(&pdev->dev, "unable to allocate private data\n"); | ||
108 | ret = -ENOMEM; | ||
109 | goto err0; | ||
110 | } | ||
111 | |||
112 | priv->sclk = clk_get(&pdev->dev, "sclk"); | ||
113 | if (IS_ERR(priv->sclk)) { | ||
114 | dev_err(&pdev->dev, "unable to get clock\n"); | ||
115 | ret = PTR_ERR(priv->sclk); | ||
116 | goto err1; | ||
117 | } | ||
118 | |||
119 | memset(&up, 0, sizeof(up)); | ||
120 | up.port.mapbase = regs->start; | ||
121 | up.port.irq = irq->start; | ||
122 | up.port.type = PORT_UNKNOWN; | ||
123 | up.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP; | ||
124 | up.port.dev = &pdev->dev; | ||
125 | up.port.private_data = priv; | ||
126 | |||
127 | clk_enable(priv->sclk); | ||
128 | up.port.uartclk = clk_get_rate(priv->sclk); | ||
129 | |||
130 | up.port.iotype = UPIO_MEM32; | ||
131 | up.port.serial_in = serial8250_em_serial_in; | ||
132 | up.port.serial_out = serial8250_em_serial_out; | ||
133 | up.dl_read = serial8250_em_serial_dl_read; | ||
134 | up.dl_write = serial8250_em_serial_dl_write; | ||
135 | |||
136 | ret = serial8250_register_8250_port(&up); | ||
137 | if (ret < 0) { | ||
138 | dev_err(&pdev->dev, "unable to register 8250 port\n"); | ||
139 | goto err2; | ||
140 | } | ||
141 | |||
142 | priv->line = ret; | ||
143 | platform_set_drvdata(pdev, priv); | ||
144 | return 0; | ||
145 | |||
146 | err2: | ||
147 | clk_disable(priv->sclk); | ||
148 | clk_put(priv->sclk); | ||
149 | err1: | ||
150 | kfree(priv); | ||
151 | err0: | ||
152 | return ret; | ||
153 | } | ||
154 | |||
155 | static int __devexit serial8250_em_remove(struct platform_device *pdev) | ||
156 | { | ||
157 | struct serial8250_em_priv *priv = platform_get_drvdata(pdev); | ||
158 | |||
159 | serial8250_unregister_port(priv->line); | ||
160 | clk_disable(priv->sclk); | ||
161 | clk_put(priv->sclk); | ||
162 | kfree(priv); | ||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | static const struct of_device_id serial8250_em_dt_ids[] __devinitconst = { | ||
167 | { .compatible = "renesas,em-uart", }, | ||
168 | {}, | ||
169 | }; | ||
170 | MODULE_DEVICE_TABLE(of, serial8250_em_dt_ids); | ||
171 | |||
172 | static struct platform_driver serial8250_em_platform_driver = { | ||
173 | .driver = { | ||
174 | .name = "serial8250-em", | ||
175 | .of_match_table = serial8250_em_dt_ids, | ||
176 | .owner = THIS_MODULE, | ||
177 | }, | ||
178 | .probe = serial8250_em_probe, | ||
179 | .remove = __devexit_p(serial8250_em_remove), | ||
180 | }; | ||
181 | |||
182 | module_platform_driver(serial8250_em_platform_driver); | ||
183 | |||
184 | MODULE_AUTHOR("Magnus Damm"); | ||
185 | MODULE_DESCRIPTION("Renesas Emma Mobile 8250 Driver"); | ||
186 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 858dca865d6a..28e7c7cce893 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <linux/tty.h> | 19 | #include <linux/tty.h> |
20 | #include <linux/serial_reg.h> | ||
20 | #include <linux/serial_core.h> | 21 | #include <linux/serial_core.h> |
21 | #include <linux/8250_pci.h> | 22 | #include <linux/8250_pci.h> |
22 | #include <linux/bitops.h> | 23 | #include <linux/bitops.h> |
@@ -1092,11 +1093,49 @@ static int skip_tx_en_setup(struct serial_private *priv, | |||
1092 | return pci_default_setup(priv, board, port, idx); | 1093 | return pci_default_setup(priv, board, port, idx); |
1093 | } | 1094 | } |
1094 | 1095 | ||
1096 | static void kt_handle_break(struct uart_port *p) | ||
1097 | { | ||
1098 | struct uart_8250_port *up = | ||
1099 | container_of(p, struct uart_8250_port, port); | ||
1100 | /* | ||
1101 | * On receipt of a BI, serial device in Intel ME (Intel | ||
1102 | * management engine) needs to have its fifos cleared for sane | ||
1103 | * SOL (Serial Over Lan) output. | ||
1104 | */ | ||
1105 | serial8250_clear_and_reinit_fifos(up); | ||
1106 | } | ||
1107 | |||
1108 | static unsigned int kt_serial_in(struct uart_port *p, int offset) | ||
1109 | { | ||
1110 | struct uart_8250_port *up = | ||
1111 | container_of(p, struct uart_8250_port, port); | ||
1112 | unsigned int val; | ||
1113 | |||
1114 | /* | ||
1115 | * When the Intel ME (management engine) gets reset its serial | ||
1116 | * port registers could return 0 momentarily. Functions like | ||
1117 | * serial8250_console_write, read and save the IER, perform | ||
1118 | * some operation and then restore it. In order to avoid | ||
1119 | * setting IER register inadvertently to 0, if the value read | ||
1120 | * is 0, double check with ier value in uart_8250_port and use | ||
1121 | * that instead. up->ier should be the same value as what is | ||
1122 | * currently configured. | ||
1123 | */ | ||
1124 | val = inb(p->iobase + offset); | ||
1125 | if (offset == UART_IER) { | ||
1126 | if (val == 0) | ||
1127 | val = up->ier; | ||
1128 | } | ||
1129 | return val; | ||
1130 | } | ||
1131 | |||
1095 | static int kt_serial_setup(struct serial_private *priv, | 1132 | static int kt_serial_setup(struct serial_private *priv, |
1096 | const struct pciserial_board *board, | 1133 | const struct pciserial_board *board, |
1097 | struct uart_port *port, int idx) | 1134 | struct uart_port *port, int idx) |
1098 | { | 1135 | { |
1099 | port->flags |= UPF_BUG_THRE; | 1136 | port->flags |= UPF_BUG_THRE; |
1137 | port->serial_in = kt_serial_in; | ||
1138 | port->handle_break = kt_handle_break; | ||
1100 | return skip_tx_en_setup(priv, board, port, idx); | 1139 | return skip_tx_en_setup(priv, board, port, idx); |
1101 | } | 1140 | } |
1102 | 1141 | ||
@@ -1609,54 +1648,72 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { | |||
1609 | { | 1648 | { |
1610 | .vendor = PCI_VENDOR_ID_INTEL, | 1649 | .vendor = PCI_VENDOR_ID_INTEL, |
1611 | .device = 0x8811, | 1650 | .device = 0x8811, |
1651 | .subvendor = PCI_ANY_ID, | ||
1652 | .subdevice = PCI_ANY_ID, | ||
1612 | .init = pci_eg20t_init, | 1653 | .init = pci_eg20t_init, |
1613 | .setup = pci_default_setup, | 1654 | .setup = pci_default_setup, |
1614 | }, | 1655 | }, |
1615 | { | 1656 | { |
1616 | .vendor = PCI_VENDOR_ID_INTEL, | 1657 | .vendor = PCI_VENDOR_ID_INTEL, |
1617 | .device = 0x8812, | 1658 | .device = 0x8812, |
1659 | .subvendor = PCI_ANY_ID, | ||
1660 | .subdevice = PCI_ANY_ID, | ||
1618 | .init = pci_eg20t_init, | 1661 | .init = pci_eg20t_init, |
1619 | .setup = pci_default_setup, | 1662 | .setup = pci_default_setup, |
1620 | }, | 1663 | }, |
1621 | { | 1664 | { |
1622 | .vendor = PCI_VENDOR_ID_INTEL, | 1665 | .vendor = PCI_VENDOR_ID_INTEL, |
1623 | .device = 0x8813, | 1666 | .device = 0x8813, |
1667 | .subvendor = PCI_ANY_ID, | ||
1668 | .subdevice = PCI_ANY_ID, | ||
1624 | .init = pci_eg20t_init, | 1669 | .init = pci_eg20t_init, |
1625 | .setup = pci_default_setup, | 1670 | .setup = pci_default_setup, |
1626 | }, | 1671 | }, |
1627 | { | 1672 | { |
1628 | .vendor = PCI_VENDOR_ID_INTEL, | 1673 | .vendor = PCI_VENDOR_ID_INTEL, |
1629 | .device = 0x8814, | 1674 | .device = 0x8814, |
1675 | .subvendor = PCI_ANY_ID, | ||
1676 | .subdevice = PCI_ANY_ID, | ||
1630 | .init = pci_eg20t_init, | 1677 | .init = pci_eg20t_init, |
1631 | .setup = pci_default_setup, | 1678 | .setup = pci_default_setup, |
1632 | }, | 1679 | }, |
1633 | { | 1680 | { |
1634 | .vendor = 0x10DB, | 1681 | .vendor = 0x10DB, |
1635 | .device = 0x8027, | 1682 | .device = 0x8027, |
1683 | .subvendor = PCI_ANY_ID, | ||
1684 | .subdevice = PCI_ANY_ID, | ||
1636 | .init = pci_eg20t_init, | 1685 | .init = pci_eg20t_init, |
1637 | .setup = pci_default_setup, | 1686 | .setup = pci_default_setup, |
1638 | }, | 1687 | }, |
1639 | { | 1688 | { |
1640 | .vendor = 0x10DB, | 1689 | .vendor = 0x10DB, |
1641 | .device = 0x8028, | 1690 | .device = 0x8028, |
1691 | .subvendor = PCI_ANY_ID, | ||
1692 | .subdevice = PCI_ANY_ID, | ||
1642 | .init = pci_eg20t_init, | 1693 | .init = pci_eg20t_init, |
1643 | .setup = pci_default_setup, | 1694 | .setup = pci_default_setup, |
1644 | }, | 1695 | }, |
1645 | { | 1696 | { |
1646 | .vendor = 0x10DB, | 1697 | .vendor = 0x10DB, |
1647 | .device = 0x8029, | 1698 | .device = 0x8029, |
1699 | .subvendor = PCI_ANY_ID, | ||
1700 | .subdevice = PCI_ANY_ID, | ||
1648 | .init = pci_eg20t_init, | 1701 | .init = pci_eg20t_init, |
1649 | .setup = pci_default_setup, | 1702 | .setup = pci_default_setup, |
1650 | }, | 1703 | }, |
1651 | { | 1704 | { |
1652 | .vendor = 0x10DB, | 1705 | .vendor = 0x10DB, |
1653 | .device = 0x800C, | 1706 | .device = 0x800C, |
1707 | .subvendor = PCI_ANY_ID, | ||
1708 | .subdevice = PCI_ANY_ID, | ||
1654 | .init = pci_eg20t_init, | 1709 | .init = pci_eg20t_init, |
1655 | .setup = pci_default_setup, | 1710 | .setup = pci_default_setup, |
1656 | }, | 1711 | }, |
1657 | { | 1712 | { |
1658 | .vendor = 0x10DB, | 1713 | .vendor = 0x10DB, |
1659 | .device = 0x800D, | 1714 | .device = 0x800D, |
1715 | .subvendor = PCI_ANY_ID, | ||
1716 | .subdevice = PCI_ANY_ID, | ||
1660 | .init = pci_eg20t_init, | 1717 | .init = pci_eg20t_init, |
1661 | .setup = pci_default_setup, | 1718 | .setup = pci_default_setup, |
1662 | }, | 1719 | }, |
@@ -2775,6 +2832,12 @@ void pciserial_suspend_ports(struct serial_private *priv) | |||
2775 | for (i = 0; i < priv->nr; i++) | 2832 | for (i = 0; i < priv->nr; i++) |
2776 | if (priv->line[i] >= 0) | 2833 | if (priv->line[i] >= 0) |
2777 | serial8250_suspend_port(priv->line[i]); | 2834 | serial8250_suspend_port(priv->line[i]); |
2835 | |||
2836 | /* | ||
2837 | * Ensure that every init quirk is properly torn down | ||
2838 | */ | ||
2839 | if (priv->quirk->exit) | ||
2840 | priv->quirk->exit(priv->dev); | ||
2778 | } | 2841 | } |
2779 | EXPORT_SYMBOL_GPL(pciserial_suspend_ports); | 2842 | EXPORT_SYMBOL_GPL(pciserial_suspend_ports); |
2780 | 2843 | ||
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 591f8018e7dd..8bc7ecbf6bea 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig | |||
@@ -278,3 +278,11 @@ config SERIAL_8250_DW | |||
278 | help | 278 | help |
279 | Selecting this option will enable handling of the extra features | 279 | Selecting this option will enable handling of the extra features |
280 | present in the Synopsys DesignWare APB UART. | 280 | present in the Synopsys DesignWare APB UART. |
281 | |||
282 | config SERIAL_8250_EM | ||
283 | tristate "Support for Emma Mobile intergrated serial port" | ||
284 | depends on SERIAL_8250 && ARM && HAVE_CLK | ||
285 | help | ||
286 | Selecting this option will add support for the integrated serial | ||
287 | port hardware found on the Emma Mobile line of processors. | ||
288 | If unsure, say N. | ||
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index 867bba738908..3f35eacdf673 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile | |||
@@ -18,3 +18,4 @@ obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o | |||
18 | obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o | 18 | obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o |
19 | obj-$(CONFIG_SERIAL_8250_FSL) += 8250_fsl.o | 19 | obj-$(CONFIG_SERIAL_8250_FSL) += 8250_fsl.o |
20 | obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o | 20 | obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o |
21 | obj-$(CONFIG_SERIAL_8250_EM) += 8250_em.o | ||