Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

8250: Serial driver changes to support future Cavium OCTEON serial patches.

In order to use Cavium OCTEON specific serial i/o drivers, we first
patch the 8250 driver to use replaceable I/O functions. Compatible
I/O functions are added for existing iotypeS.

An added benefit of this change is that it makes it easy to factor
some of the existing special cases out to board/SOC specific support
code.

The alternative is to load up 8250.c with a bunch of OCTEON specific
iotype code and bug work-arounds.

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Signed-off-by: Tomaso Paoletti <tpaoletti@caviumnetworks.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

David Daney and committed by
Linus Torvalds
7d6a07d1 b430428a

+149 -67
+145 -67
drivers/serial/8250.c
··· 303 303 }; 304 304 305 305 /* sane hardware needs no mapping */ 306 - static inline int map_8250_in_reg(struct uart_8250_port *up, int offset) 306 + static inline int map_8250_in_reg(struct uart_port *p, int offset) 307 307 { 308 - if (up->port.iotype != UPIO_AU) 308 + if (p->iotype != UPIO_AU) 309 309 return offset; 310 310 return au_io_in_map[offset]; 311 311 } 312 312 313 - static inline int map_8250_out_reg(struct uart_8250_port *up, int offset) 313 + static inline int map_8250_out_reg(struct uart_port *p, int offset) 314 314 { 315 - if (up->port.iotype != UPIO_AU) 315 + if (p->iotype != UPIO_AU) 316 316 return offset; 317 317 return au_io_out_map[offset]; 318 318 } ··· 341 341 [UART_SCR] = 0x2c 342 342 }; 343 343 344 - static inline int map_8250_in_reg(struct uart_8250_port *up, int offset) 344 + static inline int map_8250_in_reg(struct uart_port *p, int offset) 345 345 { 346 - if (up->port.iotype != UPIO_RM9000) 346 + if (p->iotype != UPIO_RM9000) 347 347 return offset; 348 348 return regmap_in[offset]; 349 349 } 350 350 351 - static inline int map_8250_out_reg(struct uart_8250_port *up, int offset) 351 + static inline int map_8250_out_reg(struct uart_port *p, int offset) 352 352 { 353 - if (up->port.iotype != UPIO_RM9000) 353 + if (p->iotype != UPIO_RM9000) 354 354 return offset; 355 355 return regmap_out[offset]; 356 356 } ··· 363 363 364 364 #endif 365 365 366 - static unsigned int serial_in(struct uart_8250_port *up, int offset) 366 + static unsigned int hub6_serial_in(struct uart_port *p, int offset) 367 367 { 368 - unsigned int tmp; 369 - offset = map_8250_in_reg(up, offset) << up->port.regshift; 370 - 371 - switch (up->port.iotype) { 372 - case UPIO_HUB6: 373 - outb(up->port.hub6 - 1 + offset, up->port.iobase); 374 - return inb(up->port.iobase + 1); 375 - 376 - case UPIO_MEM: 377 - case UPIO_DWAPB: 378 - return readb(up->port.membase + offset); 379 - 380 - case UPIO_RM9000: 381 - case UPIO_MEM32: 382 - return readl(up->port.membase + offset); 383 - 384 - #ifdef CONFIG_SERIAL_8250_AU1X00 385 - case UPIO_AU: 386 - return __raw_readl(up->port.membase + offset); 387 - #endif 388 - 389 - case UPIO_TSI: 390 - if (offset == UART_IIR) { 391 - tmp = readl(up->port.membase + (UART_IIR & ~3)); 392 - return (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */ 393 - } else 394 - return readb(up->port.membase + offset); 395 - 396 - default: 397 - return inb(up->port.iobase + offset); 398 - } 368 + offset = map_8250_in_reg(p, offset) << p->regshift; 369 + outb(p->hub6 - 1 + offset, p->iobase); 370 + return inb(p->iobase + 1); 399 371 } 400 372 401 - static void 402 - serial_out(struct uart_8250_port *up, int offset, int value) 373 + static void hub6_serial_out(struct uart_port *p, int offset, int value) 403 374 { 404 - /* Save the offset before it's remapped */ 405 - int save_offset = offset; 406 - offset = map_8250_out_reg(up, offset) << up->port.regshift; 375 + offset = map_8250_out_reg(p, offset) << p->regshift; 376 + outb(p->hub6 - 1 + offset, p->iobase); 377 + outb(value, p->iobase + 1); 378 + } 407 379 408 - switch (up->port.iotype) { 380 + static unsigned int mem_serial_in(struct uart_port *p, int offset) 381 + { 382 + offset = map_8250_in_reg(p, offset) << p->regshift; 383 + return readb(p->membase + offset); 384 + } 385 + 386 + static void mem_serial_out(struct uart_port *p, int offset, int value) 387 + { 388 + offset = map_8250_out_reg(p, offset) << p->regshift; 389 + writeb(value, p->membase + offset); 390 + } 391 + 392 + static void mem32_serial_out(struct uart_port *p, int offset, int value) 393 + { 394 + offset = map_8250_out_reg(p, offset) << p->regshift; 395 + writel(value, p->membase + offset); 396 + } 397 + 398 + static unsigned int mem32_serial_in(struct uart_port *p, int offset) 399 + { 400 + offset = map_8250_in_reg(p, offset) << p->regshift; 401 + return readl(p->membase + offset); 402 + } 403 + 404 + #ifdef CONFIG_SERIAL_8250_AU1X00 405 + static unsigned int au_serial_in(struct uart_port *p, int offset) 406 + { 407 + offset = map_8250_in_reg(p, offset) << p->regshift; 408 + return __raw_readl(p->membase + offset); 409 + } 410 + 411 + static void au_serial_out(struct uart_port *p, int offset, int value) 412 + { 413 + offset = map_8250_out_reg(p, offset) << p->regshift; 414 + __raw_writel(value, p->membase + offset); 415 + } 416 + #endif 417 + 418 + static unsigned int tsi_serial_in(struct uart_port *p, int offset) 419 + { 420 + unsigned int tmp; 421 + offset = map_8250_in_reg(p, offset) << p->regshift; 422 + if (offset == UART_IIR) { 423 + tmp = readl(p->membase + (UART_IIR & ~3)); 424 + return (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */ 425 + } else 426 + return readb(p->membase + offset); 427 + } 428 + 429 + static void tsi_serial_out(struct uart_port *p, int offset, int value) 430 + { 431 + offset = map_8250_out_reg(p, offset) << p->regshift; 432 + if (!((offset == UART_IER) && (value & UART_IER_UUE))) 433 + writeb(value, p->membase + offset); 434 + } 435 + 436 + static void dwapb_serial_out(struct uart_port *p, int offset, int value) 437 + { 438 + int save_offset = offset; 439 + offset = map_8250_out_reg(p, offset) << p->regshift; 440 + /* Save the LCR value so it can be re-written when a 441 + * Busy Detect interrupt occurs. */ 442 + if (save_offset == UART_LCR) { 443 + struct uart_8250_port *up = (struct uart_8250_port *)p; 444 + up->lcr = value; 445 + } 446 + writeb(value, p->membase + offset); 447 + /* Read the IER to ensure any interrupt is cleared before 448 + * returning from ISR. */ 449 + if (save_offset == UART_TX || save_offset == UART_IER) 450 + value = p->serial_in(p, UART_IER); 451 + } 452 + 453 + static unsigned int io_serial_in(struct uart_port *p, int offset) 454 + { 455 + offset = map_8250_in_reg(p, offset) << p->regshift; 456 + return inb(p->iobase + offset); 457 + } 458 + 459 + static void io_serial_out(struct uart_port *p, int offset, int value) 460 + { 461 + offset = map_8250_out_reg(p, offset) << p->regshift; 462 + outb(value, p->iobase + offset); 463 + } 464 + 465 + static void set_io_from_upio(struct uart_port *p) 466 + { 467 + switch (p->iotype) { 409 468 case UPIO_HUB6: 410 - outb(up->port.hub6 - 1 + offset, up->port.iobase); 411 - outb(value, up->port.iobase + 1); 469 + p->serial_in = hub6_serial_in; 470 + p->serial_out = hub6_serial_out; 412 471 break; 413 472 414 473 case UPIO_MEM: 415 - writeb(value, up->port.membase + offset); 474 + p->serial_in = mem_serial_in; 475 + p->serial_out = mem_serial_out; 416 476 break; 417 477 418 478 case UPIO_RM9000: 419 479 case UPIO_MEM32: 420 - writel(value, up->port.membase + offset); 480 + p->serial_in = mem32_serial_in; 481 + p->serial_out = mem32_serial_out; 421 482 break; 422 483 423 484 #ifdef CONFIG_SERIAL_8250_AU1X00 424 485 case UPIO_AU: 425 - __raw_writel(value, up->port.membase + offset); 486 + p->serial_in = au_serial_in; 487 + p->serial_out = au_serial_out; 426 488 break; 427 489 #endif 428 490 case UPIO_TSI: 429 - if (!((offset == UART_IER) && (value & UART_IER_UUE))) 430 - writeb(value, up->port.membase + offset); 491 + p->serial_in = tsi_serial_in; 492 + p->serial_out = tsi_serial_out; 431 493 break; 432 494 433 495 case UPIO_DWAPB: 434 - /* Save the LCR value so it can be re-written when a 435 - * Busy Detect interrupt occurs. */ 436 - if (save_offset == UART_LCR) 437 - up->lcr = value; 438 - writeb(value, up->port.membase + offset); 439 - /* Read the IER to ensure any interrupt is cleared before 440 - * returning from ISR. */ 441 - if (save_offset == UART_TX || save_offset == UART_IER) 442 - value = serial_in(up, UART_IER); 496 + p->serial_in = mem_serial_in; 497 + p->serial_out = dwapb_serial_out; 443 498 break; 444 499 445 500 default: 446 - outb(value, up->port.iobase + offset); 501 + p->serial_in = io_serial_in; 502 + p->serial_out = io_serial_out; 503 + break; 447 504 } 448 505 } 449 506 450 507 static void 451 508 serial_out_sync(struct uart_8250_port *up, int offset, int value) 452 509 { 453 - switch (up->port.iotype) { 510 + struct uart_port *p = &up->port; 511 + switch (p->iotype) { 454 512 case UPIO_MEM: 455 513 case UPIO_MEM32: 456 514 #ifdef CONFIG_SERIAL_8250_AU1X00 457 515 case UPIO_AU: 458 516 #endif 459 517 case UPIO_DWAPB: 460 - serial_out(up, offset, value); 461 - serial_in(up, UART_LCR); /* safe, no side-effects */ 518 + p->serial_out(p, offset, value); 519 + p->serial_in(p, UART_LCR); /* safe, no side-effects */ 462 520 break; 463 521 default: 464 - serial_out(up, offset, value); 522 + p->serial_out(p, offset, value); 465 523 } 466 524 } 467 525 526 + #define serial_in(up, offset) \ 527 + (up->port.serial_in(&(up)->port, (offset))) 528 + #define serial_out(up, offset, value) \ 529 + (up->port.serial_out(&(up)->port, (offset), (value))) 468 530 /* 469 531 * We used to support using pause I/O for certain machines. We 470 532 * haven't supported this for a while, but just in case it's badly ··· 2638 2576 up->port.membase = old_serial_port[i].iomem_base; 2639 2577 up->port.iotype = old_serial_port[i].io_type; 2640 2578 up->port.regshift = old_serial_port[i].iomem_reg_shift; 2579 + set_io_from_upio(&up->port); 2641 2580 if (share_irqs) 2642 2581 up->port.flags |= UPF_SHARE_IRQ; 2643 2582 } ··· 2832 2769 p->flags = port->flags; 2833 2770 p->mapbase = port->mapbase; 2834 2771 p->private_data = port->private_data; 2772 + 2773 + set_io_from_upio(p); 2774 + if (port->serial_in) 2775 + p->serial_in = port->serial_in; 2776 + if (port->serial_out) 2777 + p->serial_out = port->serial_out; 2778 + 2835 2779 return 0; 2836 2780 } 2837 2781 ··· 2903 2833 port.mapbase = p->mapbase; 2904 2834 port.hub6 = p->hub6; 2905 2835 port.private_data = p->private_data; 2836 + port.serial_in = p->serial_in; 2837 + port.serial_out = p->serial_out; 2906 2838 port.dev = &dev->dev; 2907 2839 if (share_irqs) 2908 2840 port.flags |= UPF_SHARE_IRQ; ··· 3058 2986 uart->port.private_data = port->private_data; 3059 2987 if (port->dev) 3060 2988 uart->port.dev = port->dev; 2989 + set_io_from_upio(&uart->port); 2990 + /* Possibly override default I/O functions. */ 2991 + if (port->serial_in) 2992 + uart->port.serial_in = port->serial_in; 2993 + if (port->serial_out) 2994 + uart->port.serial_out = port->serial_out; 3061 2995 3062 2996 ret = uart_add_one_port(&serial8250_reg, &uart->port); 3063 2997 if (ret == 0)
+2
include/linux/serial_8250.h
··· 28 28 unsigned char iotype; /* UPIO_* */ 29 29 unsigned char hub6; 30 30 upf_t flags; /* UPF_* flags */ 31 + unsigned int (*serial_in)(struct uart_port *, int); 32 + void (*serial_out)(struct uart_port *, int, int); 31 33 }; 32 34 33 35 /*
+2
include/linux/serial_core.h
··· 248 248 spinlock_t lock; /* port lock */ 249 249 unsigned long iobase; /* in/out[bwl] */ 250 250 unsigned char __iomem *membase; /* read/write[bwl] */ 251 + unsigned int (*serial_in)(struct uart_port *, int); 252 + void (*serial_out)(struct uart_port *, int, int); 251 253 unsigned int irq; /* irq number */ 252 254 unsigned int uartclk; /* base uart clock */ 253 255 unsigned int fifosize; /* tx fifo size */