aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial/mpc52xx_uart.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-08-05 12:03:46 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-05 12:03:46 -0400
commitcdd854bc42b5e6c79bbbc40c6600d995ffe6e747 (patch)
tree18c4dcc07bbb8aeb2b23bc812cd60cc293f36cd8 /drivers/serial/mpc52xx_uart.c
parentbbc4fd12a635492ad9d12bb418124fa2d5f0d734 (diff)
parent42a0ae2282b512d1a8f6f020327f5f7b8f31a5ea (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (79 commits) powerpc/8xx: Add support for the MPC8xx based boards from TQC powerpc/85xx: Introduce support for the Freescale P1022DS reference board powerpc/85xx: Adding DTS for the STx GP3-SSA MPC8555 board powerpc/85xx: Change deprecated binding for 85xx-based boards powerpc/tqm85xx: add a quirk for ti1520 PCMCIA bridge powerpc/tqm85xx: update PCI interrupt-map attribute powerpc/mpc8308rdb: support for MPC8308RDB board from Freescale powerpc/fsl_pci: add quirk for mpc8308 pcie bridge powerpc/85xx: Cleanup QE initialization for MPC85xxMDS boards powerpc/85xx: Fix booting for P1021MDS boards powerpc/85xx: Fix SWIOTLB initalization for MPC85xxMDS boards powerpc/85xx: kexec for SMP 85xx BookE systems powerpc/5200/i2c: improve i2c bus error recovery of/xilinxfb: update tft compatible versions powerpc/fsl-diu-fb: Support setting display mode using EDID powerpc/5121: doc/dts-bindings: update doc of FSL DIU bindings powerpc/5121: shared DIU framebuffer support powerpc/5121: move fsl-diu-fb.h to include/linux powerpc/5121: fsl-diu-fb: fix issue with re-enabling DIU area descriptor powerpc/512x: add clock structure for Video-IN (VIU) unit ...
Diffstat (limited to 'drivers/serial/mpc52xx_uart.c')
-rw-r--r--drivers/serial/mpc52xx_uart.c145
1 files changed, 116 insertions, 29 deletions
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 84a35f699016..1a88b363005c 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -113,7 +113,9 @@ struct psc_ops {
113 unsigned char (*read_char)(struct uart_port *port); 113 unsigned char (*read_char)(struct uart_port *port);
114 void (*cw_disable_ints)(struct uart_port *port); 114 void (*cw_disable_ints)(struct uart_port *port);
115 void (*cw_restore_ints)(struct uart_port *port); 115 void (*cw_restore_ints)(struct uart_port *port);
116 unsigned long (*getuartclk)(void *p); 116 unsigned int (*set_baudrate)(struct uart_port *port,
117 struct ktermios *new,
118 struct ktermios *old);
117 int (*clock)(struct uart_port *port, int enable); 119 int (*clock)(struct uart_port *port, int enable);
118 int (*fifoc_init)(void); 120 int (*fifoc_init)(void);
119 void (*fifoc_uninit)(void); 121 void (*fifoc_uninit)(void);
@@ -121,6 +123,16 @@ struct psc_ops {
121 irqreturn_t (*handle_irq)(struct uart_port *port); 123 irqreturn_t (*handle_irq)(struct uart_port *port);
122}; 124};
123 125
126/* setting the prescaler and divisor reg is common for all chips */
127static inline void mpc52xx_set_divisor(struct mpc52xx_psc __iomem *psc,
128 u16 prescaler, unsigned int divisor)
129{
130 /* select prescaler */
131 out_be16(&psc->mpc52xx_psc_clock_select, prescaler);
132 out_8(&psc->ctur, divisor >> 8);
133 out_8(&psc->ctlr, divisor & 0xff);
134}
135
124#ifdef CONFIG_PPC_MPC52xx 136#ifdef CONFIG_PPC_MPC52xx
125#define FIFO_52xx(port) ((struct mpc52xx_psc_fifo __iomem *)(PSC(port)+1)) 137#define FIFO_52xx(port) ((struct mpc52xx_psc_fifo __iomem *)(PSC(port)+1))
126static void mpc52xx_psc_fifo_init(struct uart_port *port) 138static void mpc52xx_psc_fifo_init(struct uart_port *port)
@@ -128,9 +140,6 @@ static void mpc52xx_psc_fifo_init(struct uart_port *port)
128 struct mpc52xx_psc __iomem *psc = PSC(port); 140 struct mpc52xx_psc __iomem *psc = PSC(port);
129 struct mpc52xx_psc_fifo __iomem *fifo = FIFO_52xx(port); 141 struct mpc52xx_psc_fifo __iomem *fifo = FIFO_52xx(port);
130 142
131 /* /32 prescaler */
132 out_be16(&psc->mpc52xx_psc_clock_select, 0xdd00);
133
134 out_8(&fifo->rfcntl, 0x00); 143 out_8(&fifo->rfcntl, 0x00);
135 out_be16(&fifo->rfalarm, 0x1ff); 144 out_be16(&fifo->rfalarm, 0x1ff);
136 out_8(&fifo->tfcntl, 0x07); 145 out_8(&fifo->tfcntl, 0x07);
@@ -219,15 +228,47 @@ static void mpc52xx_psc_cw_restore_ints(struct uart_port *port)
219 out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); 228 out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask);
220} 229}
221 230
222/* Search for bus-frequency property in this node or a parent */ 231static unsigned int mpc5200_psc_set_baudrate(struct uart_port *port,
223static unsigned long mpc52xx_getuartclk(void *p) 232 struct ktermios *new,
233 struct ktermios *old)
224{ 234{
225 /* 235 unsigned int baud;
226 * 5200 UARTs have a / 32 prescaler 236 unsigned int divisor;
227 * but the generic serial code assumes 16 237
228 * so return ipb freq / 2 238 /* The 5200 has a fixed /32 prescaler, uartclk contains the ipb freq */
229 */ 239 baud = uart_get_baud_rate(port, new, old,
230 return mpc5xxx_get_bus_frequency(p) / 2; 240 port->uartclk / (32 * 0xffff) + 1,
241 port->uartclk / 32);
242 divisor = (port->uartclk + 16 * baud) / (32 * baud);
243
244 /* enable the /32 prescaler and set the divisor */
245 mpc52xx_set_divisor(PSC(port), 0xdd00, divisor);
246 return baud;
247}
248
249static unsigned int mpc5200b_psc_set_baudrate(struct uart_port *port,
250 struct ktermios *new,
251 struct ktermios *old)
252{
253 unsigned int baud;
254 unsigned int divisor;
255 u16 prescaler;
256
257 /* The 5200B has a selectable /4 or /32 prescaler, uartclk contains the
258 * ipb freq */
259 baud = uart_get_baud_rate(port, new, old,
260 port->uartclk / (32 * 0xffff) + 1,
261 port->uartclk / 4);
262 divisor = (port->uartclk + 2 * baud) / (4 * baud);
263
264 /* select the proper prescaler and set the divisor */
265 if (divisor > 0xffff) {
266 divisor = (divisor + 4) / 8;
267 prescaler = 0xdd00; /* /32 */
268 } else
269 prescaler = 0xff00; /* /4 */
270 mpc52xx_set_divisor(PSC(port), prescaler, divisor);
271 return baud;
231} 272}
232 273
233static void mpc52xx_psc_get_irq(struct uart_port *port, struct device_node *np) 274static void mpc52xx_psc_get_irq(struct uart_port *port, struct device_node *np)
@@ -258,7 +299,28 @@ static struct psc_ops mpc52xx_psc_ops = {
258 .read_char = mpc52xx_psc_read_char, 299 .read_char = mpc52xx_psc_read_char,
259 .cw_disable_ints = mpc52xx_psc_cw_disable_ints, 300 .cw_disable_ints = mpc52xx_psc_cw_disable_ints,
260 .cw_restore_ints = mpc52xx_psc_cw_restore_ints, 301 .cw_restore_ints = mpc52xx_psc_cw_restore_ints,
261 .getuartclk = mpc52xx_getuartclk, 302 .set_baudrate = mpc5200_psc_set_baudrate,
303 .get_irq = mpc52xx_psc_get_irq,
304 .handle_irq = mpc52xx_psc_handle_irq,
305};
306
307static struct psc_ops mpc5200b_psc_ops = {
308 .fifo_init = mpc52xx_psc_fifo_init,
309 .raw_rx_rdy = mpc52xx_psc_raw_rx_rdy,
310 .raw_tx_rdy = mpc52xx_psc_raw_tx_rdy,
311 .rx_rdy = mpc52xx_psc_rx_rdy,
312 .tx_rdy = mpc52xx_psc_tx_rdy,
313 .tx_empty = mpc52xx_psc_tx_empty,
314 .stop_rx = mpc52xx_psc_stop_rx,
315 .start_tx = mpc52xx_psc_start_tx,
316 .stop_tx = mpc52xx_psc_stop_tx,
317 .rx_clr_irq = mpc52xx_psc_rx_clr_irq,
318 .tx_clr_irq = mpc52xx_psc_tx_clr_irq,
319 .write_char = mpc52xx_psc_write_char,
320 .read_char = mpc52xx_psc_read_char,
321 .cw_disable_ints = mpc52xx_psc_cw_disable_ints,
322 .cw_restore_ints = mpc52xx_psc_cw_restore_ints,
323 .set_baudrate = mpc5200b_psc_set_baudrate,
262 .get_irq = mpc52xx_psc_get_irq, 324 .get_irq = mpc52xx_psc_get_irq,
263 .handle_irq = mpc52xx_psc_handle_irq, 325 .handle_irq = mpc52xx_psc_handle_irq,
264}; 326};
@@ -392,9 +454,35 @@ static void mpc512x_psc_cw_restore_ints(struct uart_port *port)
392 out_be32(&FIFO_512x(port)->rximr, port->read_status_mask & 0x7f); 454 out_be32(&FIFO_512x(port)->rximr, port->read_status_mask & 0x7f);
393} 455}
394 456
395static unsigned long mpc512x_getuartclk(void *p) 457static unsigned int mpc512x_psc_set_baudrate(struct uart_port *port,
458 struct ktermios *new,
459 struct ktermios *old)
396{ 460{
397 return mpc5xxx_get_bus_frequency(p); 461 unsigned int baud;
462 unsigned int divisor;
463
464 /*
465 * The "MPC5121e Microcontroller Reference Manual, Rev. 3" says on
466 * pg. 30-10 that the chip supports a /32 and a /10 prescaler.
467 * Furthermore, it states that "After reset, the prescaler by 10
468 * for the UART mode is selected", but the reset register value is
469 * 0x0000 which means a /32 prescaler. This is wrong.
470 *
471 * In reality using /32 prescaler doesn't work, as it is not supported!
472 * Use /16 or /10 prescaler, see "MPC5121e Hardware Design Guide",
473 * Chapter 4.1 PSC in UART Mode.
474 * Calculate with a /16 prescaler here.
475 */
476
477 /* uartclk contains the ips freq */
478 baud = uart_get_baud_rate(port, new, old,
479 port->uartclk / (16 * 0xffff) + 1,
480 port->uartclk / 16);
481 divisor = (port->uartclk + 8 * baud) / (16 * baud);
482
483 /* enable the /16 prescaler and set the divisor */
484 mpc52xx_set_divisor(PSC(port), 0xdd00, divisor);
485 return baud;
398} 486}
399 487
400/* Init PSC FIFO Controller */ 488/* Init PSC FIFO Controller */
@@ -498,7 +586,7 @@ static struct psc_ops mpc512x_psc_ops = {
498 .read_char = mpc512x_psc_read_char, 586 .read_char = mpc512x_psc_read_char,
499 .cw_disable_ints = mpc512x_psc_cw_disable_ints, 587 .cw_disable_ints = mpc512x_psc_cw_disable_ints,
500 .cw_restore_ints = mpc512x_psc_cw_restore_ints, 588 .cw_restore_ints = mpc512x_psc_cw_restore_ints,
501 .getuartclk = mpc512x_getuartclk, 589 .set_baudrate = mpc512x_psc_set_baudrate,
502 .clock = mpc512x_psc_clock, 590 .clock = mpc512x_psc_clock,
503 .fifoc_init = mpc512x_psc_fifoc_init, 591 .fifoc_init = mpc512x_psc_fifoc_init,
504 .fifoc_uninit = mpc512x_psc_fifoc_uninit, 592 .fifoc_uninit = mpc512x_psc_fifoc_uninit,
@@ -666,8 +754,8 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new,
666 struct mpc52xx_psc __iomem *psc = PSC(port); 754 struct mpc52xx_psc __iomem *psc = PSC(port);
667 unsigned long flags; 755 unsigned long flags;
668 unsigned char mr1, mr2; 756 unsigned char mr1, mr2;
669 unsigned short ctr; 757 unsigned int j;
670 unsigned int j, baud, quot; 758 unsigned int baud;
671 759
672 /* Prepare what we're gonna write */ 760 /* Prepare what we're gonna write */
673 mr1 = 0; 761 mr1 = 0;
@@ -704,16 +792,9 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new,
704 mr2 |= MPC52xx_PSC_MODE_TXCTS; 792 mr2 |= MPC52xx_PSC_MODE_TXCTS;
705 } 793 }
706 794
707 baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16);
708 quot = uart_get_divisor(port, baud);
709 ctr = quot & 0xffff;
710
711 /* Get the lock */ 795 /* Get the lock */
712 spin_lock_irqsave(&port->lock, flags); 796 spin_lock_irqsave(&port->lock, flags);
713 797
714 /* Update the per-port timeout */
715 uart_update_timeout(port, new->c_cflag, baud);
716
717 /* Do our best to flush TX & RX, so we don't lose anything */ 798 /* Do our best to flush TX & RX, so we don't lose anything */
718 /* But we don't wait indefinitely ! */ 799 /* But we don't wait indefinitely ! */
719 j = 5000000; /* Maximum wait */ 800 j = 5000000; /* Maximum wait */
@@ -737,8 +818,10 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new,
737 out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1); 818 out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1);
738 out_8(&psc->mode, mr1); 819 out_8(&psc->mode, mr1);
739 out_8(&psc->mode, mr2); 820 out_8(&psc->mode, mr2);
740 out_8(&psc->ctur, ctr >> 8); 821 baud = psc_ops->set_baudrate(port, new, old);
741 out_8(&psc->ctlr, ctr & 0xff); 822
823 /* Update the per-port timeout */
824 uart_update_timeout(port, new->c_cflag, baud);
742 825
743 if (UART_ENABLE_MS(port, new->c_cflag)) 826 if (UART_ENABLE_MS(port, new->c_cflag))
744 mpc52xx_uart_enable_ms(port); 827 mpc52xx_uart_enable_ms(port);
@@ -1118,7 +1201,7 @@ mpc52xx_console_setup(struct console *co, char *options)
1118 return ret; 1201 return ret;
1119 } 1202 }
1120 1203
1121 uartclk = psc_ops->getuartclk(np); 1204 uartclk = mpc5xxx_get_bus_frequency(np);
1122 if (uartclk == 0) { 1205 if (uartclk == 0) {
1123 pr_debug("Could not find uart clock frequency!\n"); 1206 pr_debug("Could not find uart clock frequency!\n");
1124 return -EINVAL; 1207 return -EINVAL;
@@ -1201,6 +1284,7 @@ static struct uart_driver mpc52xx_uart_driver = {
1201 1284
1202static struct of_device_id mpc52xx_uart_of_match[] = { 1285static struct of_device_id mpc52xx_uart_of_match[] = {
1203#ifdef CONFIG_PPC_MPC52xx 1286#ifdef CONFIG_PPC_MPC52xx
1287 { .compatible = "fsl,mpc5200b-psc-uart", .data = &mpc5200b_psc_ops, },
1204 { .compatible = "fsl,mpc5200-psc-uart", .data = &mpc52xx_psc_ops, }, 1288 { .compatible = "fsl,mpc5200-psc-uart", .data = &mpc52xx_psc_ops, },
1205 /* binding used by old lite5200 device trees: */ 1289 /* binding used by old lite5200 device trees: */
1206 { .compatible = "mpc5200-psc-uart", .data = &mpc52xx_psc_ops, }, 1290 { .compatible = "mpc5200-psc-uart", .data = &mpc52xx_psc_ops, },
@@ -1233,7 +1317,10 @@ mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match)
1233 pr_debug("Found %s assigned to ttyPSC%x\n", 1317 pr_debug("Found %s assigned to ttyPSC%x\n",
1234 mpc52xx_uart_nodes[idx]->full_name, idx); 1318 mpc52xx_uart_nodes[idx]->full_name, idx);
1235 1319
1236 uartclk = psc_ops->getuartclk(op->dev.of_node); 1320 /* set the uart clock to the input clock of the psc, the different
1321 * prescalers are taken into account in the set_baudrate() methods
1322 * of the respective chip */
1323 uartclk = mpc5xxx_get_bus_frequency(op->dev.of_node);
1237 if (uartclk == 0) { 1324 if (uartclk == 0) {
1238 dev_dbg(&op->dev, "Could not find uart clock frequency!\n"); 1325 dev_dbg(&op->dev, "Could not find uart clock frequency!\n");
1239 return -EINVAL; 1326 return -EINVAL;