aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorJerzy Kasenberg <jerzy.kasenberg@tieto.com>2010-06-02 12:14:04 +0200
committerJohn Rigby <john.rigby@linaro.org>2010-09-02 22:45:32 -0600
commitf344d5b7119e8729bcab6f7aed8541276f82759e (patch)
treeea186630230fe0b76243f4574b261f7dcd1c04ec /drivers
parent2a2861e26d41b9a096726a94217e4e72311d9013 (diff)
ARM: pl011 baudrate precision fix
Settings of baudrate divisor registers (IBRD, FBRD) were always rounded down. Now they can be rounded up if it could make better precision. This patch also fixes white spaces. ST-Ericsson ID: ER260310 Signed-off-by: Marcin Mielczarczyk <marcin.mielczarczyk@tieto.com> Signed-off-by: Jerzy Kasenberg <jerzy.kasenberg@tieto.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/725 Reviewed-by: Marcus COOPER <marcus.xm.cooper@stericsson.com> Tested-by: Marcus COOPER <marcus.xm.cooper@stericsson.com> Reviewed-by: Linus WALLEIJ <linus.walleij@stericsson.com> Signed-off-by: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> Change-Id: I1d3107ea3e033712b3d9be77f9f716d106241aaa Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/2389 Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/serial/amba-pl011.c31
1 files changed, 27 insertions, 4 deletions
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index e351e7adb89..58b2768296b 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -70,12 +70,13 @@
struct uart_amba_port {
struct uart_port port;
struct clk *clk;
- unsigned int im; /* interrupt mask */
+ unsigned int im; /* interrupt mask */
unsigned int old_status;
- unsigned int ifls; /* vendor-specific */
+ unsigned int ifls; /* vendor-specific */
bool autorts;
unsigned int lcrh_tx; /* vendor-specific */
unsigned int lcrh_rx; /* vendor-specific */
+ bool oversampling; /* vendor-specific */
};
/* There is by now at least one vendor with differing details, so handle it */
@@ -84,6 +85,7 @@ struct vendor_data {
unsigned int fifosize;
unsigned int lcrh_tx;
unsigned int lcrh_rx;
+ bool oversampling;
};
static struct vendor_data vendor_arm = {
@@ -91,6 +93,7 @@ static struct vendor_data vendor_arm = {
.fifosize = 16,
.lcrh_tx = UART011_LCRH,
.lcrh_rx = UART011_LCRH,
+ .oversampling = false,
};
static struct vendor_data vendor_st = {
@@ -98,6 +101,7 @@ static struct vendor_data vendor_st = {
.fifosize = 64,
.lcrh_tx = ST_UART011_LCRH_TX,
.lcrh_rx = ST_UART011_LCRH_RX,
+ .oversampling = true,
};
static void pl011_stop_tx(struct uart_port *port)
@@ -516,8 +520,13 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
/*
* Ask the core to calculate the divisor for us.
*/
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
- quot = port->uartclk * 4 / baud;
+ baud = uart_get_baud_rate(port, termios, old, 0,
+ port->uartclk/(uap->oversampling?8:16));
+
+ if (baud > port->uartclk/16)
+ quot = DIV_ROUND_CLOSEST(port->uartclk * 8, baud);
+ else
+ quot = DIV_ROUND_CLOSEST(port->uartclk * 4, baud);
switch (termios->c_cflag & CSIZE) {
case CS5:
@@ -596,6 +605,13 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
uap->autorts = false;
}
+ if (uap->oversampling) {
+ if (baud > port->uartclk/16)
+ old_cr |= ST_UART011_CR_OVSFACT;
+ else
+ old_cr &= ~ST_UART011_CR_OVSFACT;
+ }
+
/* Set baud rate */
writew(quot & 0x3f, port->membase + UART011_FBRD);
writew(quot >> 6, port->membase + UART011_IBRD);
@@ -763,6 +779,12 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud,
fbrd = readw(uap->port.membase + UART011_FBRD);
*baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd);
+
+ if (uap->oversampling) {
+ if (readw(uap->port.membase + UART011_CR)
+ & ST_UART011_CR_OVSFACT)
+ *baud *= 2;
+ }
}
}
@@ -866,6 +888,7 @@ static int pl011_probe(struct amba_device *dev, struct amba_id *id)
uap->ifls = vendor->ifls;
uap->lcrh_rx = vendor->lcrh_rx;
uap->lcrh_tx = vendor->lcrh_tx;
+ uap->oversampling = vendor->oversampling;
uap->port.dev = &dev->dev;
uap->port.mapbase = dev->res.start;
uap->port.membase = base;