diff options
author | Philippe Langlais <philippe.langlais@stericsson.com> | 2010-07-29 11:13:57 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-10 16:47:46 -0400 |
commit | 235dae5d094c415fcf0fc79fa637f1901bc8afe2 (patch) | |
tree | 947ea700996f68c0a601cb2a0204d475ca131f32 /drivers/serial | |
parent | bf9c1fca9ae9a79ed209e7ab2c10b3862f3f6f72 (diff) |
U6715 16550A serial driver support
UART Features extract from STEricsson U6715 data-sheet (arm926 SoC for mobile phone):
* Fully compatible with industry standard 16C550 and 16C450 from various
manufacturers
* RX and TX 64 byte FIFO reduces CPU interrupts
* Full double buffering
* Modem control signals include CTS, RTS, (and DSR, DTR on UART1 only)
* Automatic baud rate selection
* Manual or automatic RTS/CTS smart hardware flow control
* Programmable serial characteristics:
– Baud rate generation (50 to 3.25M baud)
– 5, 6, 7 or 8-bit characters
– Even, odd or no-parity bit generation and detection
– 1, 1.5 or 2 stop bit generation
* Independent control of transmit, receive, line status, data set interrupts and FIFOs
* Full status-reporting capabilities
* Separate DMA signaling for RX and TX
* Timed interrupt to spread receive interrupt on known duration
* DMA time-out interrupt to allow detection of end of reception
* Carkit pulse coding and decoding compliant with USB carkit control interface [40]
In 16550A auto-configuration, if the fifo size is 64 then it's an U6 16550A port
Add set_termios hook & export serial8250_do_set_termios to change uart
clock following baudrate
Signed-off-by: Philippe Langlais <philippe.langlais@stericsson.com>
Acked-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/8250.c | 37 |
1 files changed, 34 insertions, 3 deletions
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 355148dc085e..24110f6f61e0 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -300,6 +300,13 @@ static const struct serial8250_config uart_config[] = { | |||
300 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00, | 300 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00, |
301 | .flags = UART_CAP_FIFO | UART_CAP_AFE, | 301 | .flags = UART_CAP_FIFO | UART_CAP_AFE, |
302 | }, | 302 | }, |
303 | [PORT_U6_16550A] = { | ||
304 | .name = "U6_16550A", | ||
305 | .fifo_size = 64, | ||
306 | .tx_loadsz = 64, | ||
307 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, | ||
308 | .flags = UART_CAP_FIFO | UART_CAP_AFE, | ||
309 | }, | ||
303 | }; | 310 | }; |
304 | 311 | ||
305 | #if defined(CONFIG_MIPS_ALCHEMY) | 312 | #if defined(CONFIG_MIPS_ALCHEMY) |
@@ -1070,6 +1077,15 @@ static void autoconfig_16550a(struct uart_8250_port *up) | |||
1070 | DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 "); | 1077 | DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 "); |
1071 | } | 1078 | } |
1072 | serial_outp(up, UART_IER, iersave); | 1079 | serial_outp(up, UART_IER, iersave); |
1080 | |||
1081 | /* | ||
1082 | * We distinguish between 16550A and U6 16550A by counting | ||
1083 | * how many bytes are in the FIFO. | ||
1084 | */ | ||
1085 | if (up->port.type == PORT_16550A && size_fifo(up) == 64) { | ||
1086 | up->port.type = PORT_U6_16550A; | ||
1087 | up->capabilities |= UART_CAP_AFE; | ||
1088 | } | ||
1073 | } | 1089 | } |
1074 | 1090 | ||
1075 | /* | 1091 | /* |
@@ -2224,9 +2240,9 @@ static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int | |||
2224 | return quot; | 2240 | return quot; |
2225 | } | 2241 | } |
2226 | 2242 | ||
2227 | static void | 2243 | void |
2228 | serial8250_set_termios(struct uart_port *port, struct ktermios *termios, | 2244 | serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, |
2229 | struct ktermios *old) | 2245 | struct ktermios *old) |
2230 | { | 2246 | { |
2231 | struct uart_8250_port *up = (struct uart_8250_port *)port; | 2247 | struct uart_8250_port *up = (struct uart_8250_port *)port; |
2232 | unsigned char cval, fcr = 0; | 2248 | unsigned char cval, fcr = 0; |
@@ -2402,6 +2418,17 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, | |||
2402 | if (tty_termios_baud_rate(termios)) | 2418 | if (tty_termios_baud_rate(termios)) |
2403 | tty_termios_encode_baud_rate(termios, baud, baud); | 2419 | tty_termios_encode_baud_rate(termios, baud, baud); |
2404 | } | 2420 | } |
2421 | EXPORT_SYMBOL(serial8250_do_set_termios); | ||
2422 | |||
2423 | static void | ||
2424 | serial8250_set_termios(struct uart_port *port, struct ktermios *termios, | ||
2425 | struct ktermios *old) | ||
2426 | { | ||
2427 | if (port->set_termios) | ||
2428 | port->set_termios(port, termios, old); | ||
2429 | else | ||
2430 | serial8250_do_set_termios(port, termios, old); | ||
2431 | } | ||
2405 | 2432 | ||
2406 | static void | 2433 | static void |
2407 | serial8250_set_ldisc(struct uart_port *port, int new) | 2434 | serial8250_set_ldisc(struct uart_port *port, int new) |
@@ -2982,6 +3009,7 @@ static int __devinit serial8250_probe(struct platform_device *dev) | |||
2982 | port.type = p->type; | 3009 | port.type = p->type; |
2983 | port.serial_in = p->serial_in; | 3010 | port.serial_in = p->serial_in; |
2984 | port.serial_out = p->serial_out; | 3011 | port.serial_out = p->serial_out; |
3012 | port.set_termios = p->set_termios; | ||
2985 | port.dev = &dev->dev; | 3013 | port.dev = &dev->dev; |
2986 | port.irqflags |= irqflag; | 3014 | port.irqflags |= irqflag; |
2987 | ret = serial8250_register_port(&port); | 3015 | ret = serial8250_register_port(&port); |
@@ -3145,6 +3173,9 @@ int serial8250_register_port(struct uart_port *port) | |||
3145 | uart->port.serial_in = port->serial_in; | 3173 | uart->port.serial_in = port->serial_in; |
3146 | if (port->serial_out) | 3174 | if (port->serial_out) |
3147 | uart->port.serial_out = port->serial_out; | 3175 | uart->port.serial_out = port->serial_out; |
3176 | /* Possibly override set_termios call */ | ||
3177 | if (port->set_termios) | ||
3178 | uart->port.set_termios = port->set_termios; | ||
3148 | 3179 | ||
3149 | ret = uart_add_one_port(&serial8250_reg, &uart->port); | 3180 | ret = uart_add_one_port(&serial8250_reg, &uart->port); |
3150 | if (ret == 0) | 3181 | if (ret == 0) |