diff options
Diffstat (limited to 'drivers/tty/serial/sccnxp.c')
-rw-r--r-- | drivers/tty/serial/sccnxp.c | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c index c0a68eee4479..68a24a14f6b7 100644 --- a/drivers/tty/serial/sccnxp.c +++ b/drivers/tty/serial/sccnxp.c | |||
@@ -48,7 +48,6 @@ | |||
48 | # define MR2_STOP1 (7 << 0) | 48 | # define MR2_STOP1 (7 << 0) |
49 | # define MR2_STOP2 (0xf << 0) | 49 | # define MR2_STOP2 (0xf << 0) |
50 | #define SCCNXP_SR_REG (0x01) | 50 | #define SCCNXP_SR_REG (0x01) |
51 | #define SCCNXP_CSR_REG SCCNXP_SR_REG | ||
52 | # define SR_RXRDY (1 << 0) | 51 | # define SR_RXRDY (1 << 0) |
53 | # define SR_FULL (1 << 1) | 52 | # define SR_FULL (1 << 1) |
54 | # define SR_TXRDY (1 << 2) | 53 | # define SR_TXRDY (1 << 2) |
@@ -57,6 +56,8 @@ | |||
57 | # define SR_PE (1 << 5) | 56 | # define SR_PE (1 << 5) |
58 | # define SR_FE (1 << 6) | 57 | # define SR_FE (1 << 6) |
59 | # define SR_BRK (1 << 7) | 58 | # define SR_BRK (1 << 7) |
59 | #define SCCNXP_CSR_REG (SCCNXP_SR_REG) | ||
60 | # define CSR_TIMER_MODE (0x0d) | ||
60 | #define SCCNXP_CR_REG (0x02) | 61 | #define SCCNXP_CR_REG (0x02) |
61 | # define CR_RX_ENABLE (1 << 0) | 62 | # define CR_RX_ENABLE (1 << 0) |
62 | # define CR_RX_DISABLE (1 << 1) | 63 | # define CR_RX_DISABLE (1 << 1) |
@@ -83,9 +84,12 @@ | |||
83 | # define IMR_RXRDY (1 << 1) | 84 | # define IMR_RXRDY (1 << 1) |
84 | # define ISR_TXRDY(x) (1 << ((x * 4) + 0)) | 85 | # define ISR_TXRDY(x) (1 << ((x * 4) + 0)) |
85 | # define ISR_RXRDY(x) (1 << ((x * 4) + 1)) | 86 | # define ISR_RXRDY(x) (1 << ((x * 4) + 1)) |
87 | #define SCCNXP_CTPU_REG (0x06) | ||
88 | #define SCCNXP_CTPL_REG (0x07) | ||
86 | #define SCCNXP_IPR_REG (0x0d) | 89 | #define SCCNXP_IPR_REG (0x0d) |
87 | #define SCCNXP_OPCR_REG SCCNXP_IPR_REG | 90 | #define SCCNXP_OPCR_REG SCCNXP_IPR_REG |
88 | #define SCCNXP_SOP_REG (0x0e) | 91 | #define SCCNXP_SOP_REG (0x0e) |
92 | #define SCCNXP_START_COUNTER_REG SCCNXP_SOP_REG | ||
89 | #define SCCNXP_ROP_REG (0x0f) | 93 | #define SCCNXP_ROP_REG (0x0f) |
90 | 94 | ||
91 | /* Route helpers */ | 95 | /* Route helpers */ |
@@ -255,7 +259,7 @@ static int sccnxp_update_best_err(int a, int b, int *besterr) | |||
255 | { | 259 | { |
256 | int err = abs(a - b); | 260 | int err = abs(a - b); |
257 | 261 | ||
258 | if ((*besterr < 0) || (*besterr > err)) { | 262 | if (*besterr > err) { |
259 | *besterr = err; | 263 | *besterr = err; |
260 | return 0; | 264 | return 0; |
261 | } | 265 | } |
@@ -303,10 +307,22 @@ static const struct { | |||
303 | static int sccnxp_set_baud(struct uart_port *port, int baud) | 307 | static int sccnxp_set_baud(struct uart_port *port, int baud) |
304 | { | 308 | { |
305 | struct sccnxp_port *s = dev_get_drvdata(port->dev); | 309 | struct sccnxp_port *s = dev_get_drvdata(port->dev); |
306 | int div_std, tmp_baud, bestbaud = baud, besterr = -1; | 310 | int div_std, tmp_baud, bestbaud = INT_MAX, besterr = INT_MAX; |
307 | struct sccnxp_chip *chip = s->chip; | 311 | struct sccnxp_chip *chip = s->chip; |
308 | u8 i, acr = 0, csr = 0, mr0 = 0; | 312 | u8 i, acr = 0, csr = 0, mr0 = 0; |
309 | 313 | ||
314 | /* Find divisor to load to the timer preset registers */ | ||
315 | div_std = DIV_ROUND_CLOSEST(port->uartclk, 2 * 16 * baud); | ||
316 | if ((div_std >= 2) && (div_std <= 0xffff)) { | ||
317 | bestbaud = DIV_ROUND_CLOSEST(port->uartclk, 2 * 16 * div_std); | ||
318 | sccnxp_update_best_err(baud, bestbaud, &besterr); | ||
319 | csr = CSR_TIMER_MODE; | ||
320 | sccnxp_port_write(port, SCCNXP_CTPU_REG, div_std >> 8); | ||
321 | sccnxp_port_write(port, SCCNXP_CTPL_REG, div_std); | ||
322 | /* Issue start timer/counter command */ | ||
323 | sccnxp_port_read(port, SCCNXP_START_COUNTER_REG); | ||
324 | } | ||
325 | |||
310 | /* Find best baud from table */ | 326 | /* Find best baud from table */ |
311 | for (i = 0; baud_std[i].baud && besterr; i++) { | 327 | for (i = 0; baud_std[i].baud && besterr; i++) { |
312 | if (baud_std[i].mr0 && !(chip->flags & SCCNXP_HAVE_MR0)) | 328 | if (baud_std[i].mr0 && !(chip->flags & SCCNXP_HAVE_MR0)) |