aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/sccnxp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/sccnxp.c')
-rw-r--r--drivers/tty/serial/sccnxp.c22
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 {
303static int sccnxp_set_baud(struct uart_port *port, int baud) 307static 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))