diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-12-22 12:48:26 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-01-05 11:58:44 -0500 |
commit | c19f12b5ef3adf3c139eabbe3d3d0201838b77b1 (patch) | |
tree | 8e4feb43846bb02a50132dc97d3a8d8cac8346ee /drivers/serial | |
parent | 5063e2c567ee569cccfc01ebf80c898cb4e6833a (diff) |
ARM: PL011: Allow better handling of vendor data
Rather than copying all vendor data into the port structure, copy
just that which is frequently used, and keep a pointer to the
remaining vendor data structure. This makes it easier to add
vendor quirks in the future.
Acked-by: Linus Walleij <linus.walleij@stericsson.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/amba-pl011.c | 51 |
1 files changed, 27 insertions, 24 deletions
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index c77b3eb5142d..6afdd9b39720 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c | |||
@@ -63,22 +63,6 @@ | |||
63 | #define UART_DR_ERROR (UART011_DR_OE|UART011_DR_BE|UART011_DR_PE|UART011_DR_FE) | 63 | #define UART_DR_ERROR (UART011_DR_OE|UART011_DR_BE|UART011_DR_PE|UART011_DR_FE) |
64 | #define UART_DUMMY_DR_RX (1 << 16) | 64 | #define UART_DUMMY_DR_RX (1 << 16) |
65 | 65 | ||
66 | /* | ||
67 | * We wrap our port structure around the generic uart_port. | ||
68 | */ | ||
69 | struct uart_amba_port { | ||
70 | struct uart_port port; | ||
71 | struct clk *clk; | ||
72 | unsigned int im; /* interrupt mask */ | ||
73 | unsigned int old_status; | ||
74 | unsigned int ifls; /* vendor-specific */ | ||
75 | unsigned int lcrh_tx; /* vendor-specific */ | ||
76 | unsigned int lcrh_rx; /* vendor-specific */ | ||
77 | bool oversampling; /* vendor-specific */ | ||
78 | bool autorts; | ||
79 | char type[12]; | ||
80 | }; | ||
81 | |||
82 | /* There is by now at least one vendor with differing details, so handle it */ | 66 | /* There is by now at least one vendor with differing details, so handle it */ |
83 | struct vendor_data { | 67 | struct vendor_data { |
84 | unsigned int ifls; | 68 | unsigned int ifls; |
@@ -104,6 +88,21 @@ static struct vendor_data vendor_st = { | |||
104 | .oversampling = true, | 88 | .oversampling = true, |
105 | }; | 89 | }; |
106 | 90 | ||
91 | /* | ||
92 | * We wrap our port structure around the generic uart_port. | ||
93 | */ | ||
94 | struct uart_amba_port { | ||
95 | struct uart_port port; | ||
96 | struct clk *clk; | ||
97 | const struct vendor_data *vendor; | ||
98 | unsigned int im; /* interrupt mask */ | ||
99 | unsigned int old_status; | ||
100 | unsigned int lcrh_tx; /* vendor-specific */ | ||
101 | unsigned int lcrh_rx; /* vendor-specific */ | ||
102 | bool autorts; | ||
103 | char type[12]; | ||
104 | }; | ||
105 | |||
107 | static void pl011_stop_tx(struct uart_port *port) | 106 | static void pl011_stop_tx(struct uart_port *port) |
108 | { | 107 | { |
109 | struct uart_amba_port *uap = (struct uart_amba_port *)port; | 108 | struct uart_amba_port *uap = (struct uart_amba_port *)port; |
@@ -397,7 +396,7 @@ static int pl011_startup(struct uart_port *port) | |||
397 | if (retval) | 396 | if (retval) |
398 | goto clk_dis; | 397 | goto clk_dis; |
399 | 398 | ||
400 | writew(uap->ifls, uap->port.membase + UART011_IFLS); | 399 | writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS); |
401 | 400 | ||
402 | /* | 401 | /* |
403 | * Provoke TX FIFO interrupt into asserting. | 402 | * Provoke TX FIFO interrupt into asserting. |
@@ -503,13 +502,18 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, | |||
503 | struct uart_amba_port *uap = (struct uart_amba_port *)port; | 502 | struct uart_amba_port *uap = (struct uart_amba_port *)port; |
504 | unsigned int lcr_h, old_cr; | 503 | unsigned int lcr_h, old_cr; |
505 | unsigned long flags; | 504 | unsigned long flags; |
506 | unsigned int baud, quot; | 505 | unsigned int baud, quot, clkdiv; |
506 | |||
507 | if (uap->vendor->oversampling) | ||
508 | clkdiv = 8; | ||
509 | else | ||
510 | clkdiv = 16; | ||
507 | 511 | ||
508 | /* | 512 | /* |
509 | * Ask the core to calculate the divisor for us. | 513 | * Ask the core to calculate the divisor for us. |
510 | */ | 514 | */ |
511 | baud = uart_get_baud_rate(port, termios, old, 0, | 515 | baud = uart_get_baud_rate(port, termios, old, 0, |
512 | port->uartclk/(uap->oversampling ? 8 : 16)); | 516 | port->uartclk / clkdiv); |
513 | 517 | ||
514 | if (baud > port->uartclk/16) | 518 | if (baud > port->uartclk/16) |
515 | quot = DIV_ROUND_CLOSEST(port->uartclk * 8, baud); | 519 | quot = DIV_ROUND_CLOSEST(port->uartclk * 8, baud); |
@@ -593,8 +597,8 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, | |||
593 | uap->autorts = false; | 597 | uap->autorts = false; |
594 | } | 598 | } |
595 | 599 | ||
596 | if (uap->oversampling) { | 600 | if (uap->vendor->oversampling) { |
597 | if (baud > port->uartclk/16) | 601 | if (baud > port->uartclk / 16) |
598 | old_cr |= ST_UART011_CR_OVSFACT; | 602 | old_cr |= ST_UART011_CR_OVSFACT; |
599 | else | 603 | else |
600 | old_cr &= ~ST_UART011_CR_OVSFACT; | 604 | old_cr &= ~ST_UART011_CR_OVSFACT; |
@@ -767,7 +771,7 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud, | |||
767 | 771 | ||
768 | *baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd); | 772 | *baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd); |
769 | 773 | ||
770 | if (uap->oversampling) { | 774 | if (uap->vendor->oversampling) { |
771 | if (readw(uap->port.membase + UART011_CR) | 775 | if (readw(uap->port.membase + UART011_CR) |
772 | & ST_UART011_CR_OVSFACT) | 776 | & ST_UART011_CR_OVSFACT) |
773 | *baud *= 2; | 777 | *baud *= 2; |
@@ -864,10 +868,9 @@ static int pl011_probe(struct amba_device *dev, struct amba_id *id) | |||
864 | goto unmap; | 868 | goto unmap; |
865 | } | 869 | } |
866 | 870 | ||
867 | uap->ifls = vendor->ifls; | 871 | uap->vendor = vendor; |
868 | uap->lcrh_rx = vendor->lcrh_rx; | 872 | uap->lcrh_rx = vendor->lcrh_rx; |
869 | uap->lcrh_tx = vendor->lcrh_tx; | 873 | uap->lcrh_tx = vendor->lcrh_tx; |
870 | uap->oversampling = vendor->oversampling; | ||
871 | uap->port.dev = &dev->dev; | 874 | uap->port.dev = &dev->dev; |
872 | uap->port.mapbase = dev->res.start; | 875 | uap->port.mapbase = dev->res.start; |
873 | uap->port.membase = base; | 876 | uap->port.membase = base; |