aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial/mpc52xx_uart.c
diff options
context:
space:
mode:
authorJohn Rigby <jrigby@freescale.com>2008-01-28 12:28:56 -0500
committerGrant Likely <grant.likely@secretlab.ca>2008-02-06 16:05:40 -0500
commit25ae3a0739c69425a911925b43213895a9802b98 (patch)
tree250695da67fc1414080f96e55cd68b4d92d6da43 /drivers/serial/mpc52xx_uart.c
parent599f030cc596cd41a0f966afd4cee2e2fc48ee86 (diff)
[POWERPC] mpc512x: Add MPC512x PSC support to MPC52xx psc driver
Add 512x support using the psc_ops framework established with the previous patch. All 512x PSCs share the same interrupt so add IRQF_SHARED to irq flags. Signed-off-by: John Rigby <jrigby@freescale.com> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/serial/mpc52xx_uart.c')
-rw-r--r--drivers/serial/mpc52xx_uart.c177
1 files changed, 171 insertions, 6 deletions
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 7ab73fa4a80f..821facd10bbc 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -16,6 +16,9 @@
16 * Some of the code has been inspired/copied from the 2.4 code written 16 * Some of the code has been inspired/copied from the 2.4 code written
17 * by Dale Farnsworth <dfarnsworth@mvista.com>. 17 * by Dale Farnsworth <dfarnsworth@mvista.com>.
18 * 18 *
19 * Copyright (C) 2008 Freescale Semiconductor Inc.
20 * John Rigby <jrigby@gmail.com>
21 * Added support for MPC5121
19 * Copyright (C) 2006 Secret Lab Technologies Ltd. 22 * Copyright (C) 2006 Secret Lab Technologies Ltd.
20 * Grant Likely <grant.likely@secretlab.ca> 23 * Grant Likely <grant.likely@secretlab.ca>
21 * Copyright (C) 2004-2006 Sylvain Munaut <tnt@246tNt.com> 24 * Copyright (C) 2004-2006 Sylvain Munaut <tnt@246tNt.com>
@@ -78,6 +81,7 @@
78#endif 81#endif
79 82
80#include <asm/mpc52xx.h> 83#include <asm/mpc52xx.h>
84#include <asm/mpc512x.h>
81#include <asm/mpc52xx_psc.h> 85#include <asm/mpc52xx_psc.h>
82 86
83#if defined(CONFIG_SERIAL_MPC52xx_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) 87#if defined(CONFIG_SERIAL_MPC52xx_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
@@ -129,13 +133,29 @@ static irqreturn_t mpc52xx_uart_int(int irq, void *dev_id);
129 133
130#if defined(CONFIG_PPC_MERGE) 134#if defined(CONFIG_PPC_MERGE)
131static struct of_device_id mpc52xx_uart_of_match[] = { 135static struct of_device_id mpc52xx_uart_of_match[] = {
132 { .type = "serial", .compatible = "fsl,mpc5200-psc-uart", }, 136#ifdef CONFIG_PPC_MPC52xx
133 { .type = "serial", .compatible = "mpc5200-psc-uart", }, /* lite5200 */ 137 { .compatible = "fsl,mpc5200-psc-uart", .data = &mpc52xx_psc_ops, },
134 { .type = "serial", .compatible = "mpc5200-serial", }, /* efika */ 138 /* binding used by old lite5200 device trees: */
139 { .compatible = "mpc5200-psc-uart", .data = &mpc52xx_psc_ops, },
140 /* binding used by efika: */
141 { .compatible = "mpc5200-serial", .data = &mpc52xx_psc_ops, },
142#endif
143#ifdef CONFIG_PPC_MPC512x
144 { .compatible = "fsl,mpc5121-psc-uart", .data = &mpc512x_psc_ops, },
145 {},
146#endif
147};
148#if defined(CONFIG_PPC_MERGE)
149static const struct of_device_id mpc52xx_uart_of_match[] = {
150 {.type = "serial",
151 .compatible = "mpc5200-psc-uart",
152#endif
135 {}, 153 {},
136}; 154};
137#endif 155#endif
138 156
157#endif
158
139/* ======================================================================== */ 159/* ======================================================================== */
140/* PSC fifo operations for isolating differences between 52xx and 512x */ 160/* PSC fifo operations for isolating differences between 52xx and 512x */
141/* ======================================================================== */ 161/* ======================================================================== */
@@ -159,6 +179,7 @@ struct psc_ops {
159 unsigned long (*getuartclk)(void *p); 179 unsigned long (*getuartclk)(void *p);
160}; 180};
161 181
182#ifdef CONFIG_PPC_MPC52xx
162#define FIFO_52xx(port) ((struct mpc52xx_psc_fifo __iomem *)(PSC(port)+1)) 183#define FIFO_52xx(port) ((struct mpc52xx_psc_fifo __iomem *)(PSC(port)+1))
163static void mpc52xx_psc_fifo_init(struct uart_port *port) 184static void mpc52xx_psc_fifo_init(struct uart_port *port)
164{ 185{
@@ -291,7 +312,145 @@ static struct psc_ops mpc52xx_psc_ops = {
291 .getuartclk = mpc52xx_getuartclk, 312 .getuartclk = mpc52xx_getuartclk,
292}; 313};
293 314
294static struct psc_ops *psc_ops = &mpc52xx_psc_ops; 315#endif /* CONFIG_MPC52xx */
316
317#ifdef CONFIG_PPC_MPC512x
318#define FIFO_512x(port) ((struct mpc512x_psc_fifo __iomem *)(PSC(port)+1))
319static void mpc512x_psc_fifo_init(struct uart_port *port)
320{
321 out_be32(&FIFO_512x(port)->txcmd, MPC512x_PSC_FIFO_RESET_SLICE);
322 out_be32(&FIFO_512x(port)->txcmd, MPC512x_PSC_FIFO_ENABLE_SLICE);
323 out_be32(&FIFO_512x(port)->txalarm, 1);
324 out_be32(&FIFO_512x(port)->tximr, 0);
325
326 out_be32(&FIFO_512x(port)->rxcmd, MPC512x_PSC_FIFO_RESET_SLICE);
327 out_be32(&FIFO_512x(port)->rxcmd, MPC512x_PSC_FIFO_ENABLE_SLICE);
328 out_be32(&FIFO_512x(port)->rxalarm, 1);
329 out_be32(&FIFO_512x(port)->rximr, 0);
330
331 out_be32(&FIFO_512x(port)->tximr, MPC512x_PSC_FIFO_ALARM);
332 out_be32(&FIFO_512x(port)->rximr, MPC512x_PSC_FIFO_ALARM);
333}
334
335static int mpc512x_psc_raw_rx_rdy(struct uart_port *port)
336{
337 return !(in_be32(&FIFO_512x(port)->rxsr) & MPC512x_PSC_FIFO_EMPTY);
338}
339
340static int mpc512x_psc_raw_tx_rdy(struct uart_port *port)
341{
342 return !(in_be32(&FIFO_512x(port)->txsr) & MPC512x_PSC_FIFO_FULL);
343}
344
345static int mpc512x_psc_rx_rdy(struct uart_port *port)
346{
347 return in_be32(&FIFO_512x(port)->rxsr)
348 & in_be32(&FIFO_512x(port)->rximr)
349 & MPC512x_PSC_FIFO_ALARM;
350}
351
352static int mpc512x_psc_tx_rdy(struct uart_port *port)
353{
354 return in_be32(&FIFO_512x(port)->txsr)
355 & in_be32(&FIFO_512x(port)->tximr)
356 & MPC512x_PSC_FIFO_ALARM;
357}
358
359static int mpc512x_psc_tx_empty(struct uart_port *port)
360{
361 return in_be32(&FIFO_512x(port)->txsr)
362 & MPC512x_PSC_FIFO_EMPTY;
363}
364
365static void mpc512x_psc_stop_rx(struct uart_port *port)
366{
367 unsigned long rx_fifo_imr;
368
369 rx_fifo_imr = in_be32(&FIFO_512x(port)->rximr);
370 rx_fifo_imr &= ~MPC512x_PSC_FIFO_ALARM;
371 out_be32(&FIFO_512x(port)->rximr, rx_fifo_imr);
372}
373
374static void mpc512x_psc_start_tx(struct uart_port *port)
375{
376 unsigned long tx_fifo_imr;
377
378 tx_fifo_imr = in_be32(&FIFO_512x(port)->tximr);
379 tx_fifo_imr |= MPC512x_PSC_FIFO_ALARM;
380 out_be32(&FIFO_512x(port)->tximr, tx_fifo_imr);
381}
382
383static void mpc512x_psc_stop_tx(struct uart_port *port)
384{
385 unsigned long tx_fifo_imr;
386
387 tx_fifo_imr = in_be32(&FIFO_512x(port)->tximr);
388 tx_fifo_imr &= ~MPC512x_PSC_FIFO_ALARM;
389 out_be32(&FIFO_512x(port)->tximr, tx_fifo_imr);
390}
391
392static void mpc512x_psc_rx_clr_irq(struct uart_port *port)
393{
394 out_be32(&FIFO_512x(port)->rxisr, in_be32(&FIFO_512x(port)->rxisr));
395}
396
397static void mpc512x_psc_tx_clr_irq(struct uart_port *port)
398{
399 out_be32(&FIFO_512x(port)->txisr, in_be32(&FIFO_512x(port)->txisr));
400}
401
402static void mpc512x_psc_write_char(struct uart_port *port, unsigned char c)
403{
404 out_8(&FIFO_512x(port)->txdata_8, c);
405}
406
407static unsigned char mpc512x_psc_read_char(struct uart_port *port)
408{
409 return in_8(&FIFO_512x(port)->rxdata_8);
410}
411
412static void mpc512x_psc_cw_disable_ints(struct uart_port *port)
413{
414 port->read_status_mask =
415 in_be32(&FIFO_512x(port)->tximr) << 16 |
416 in_be32(&FIFO_512x(port)->rximr);
417 out_be32(&FIFO_512x(port)->tximr, 0);
418 out_be32(&FIFO_512x(port)->rximr, 0);
419}
420
421static void mpc512x_psc_cw_restore_ints(struct uart_port *port)
422{
423 out_be32(&FIFO_512x(port)->tximr,
424 (port->read_status_mask >> 16) & 0x7f);
425 out_be32(&FIFO_512x(port)->rximr, port->read_status_mask & 0x7f);
426}
427
428static unsigned long mpc512x_getuartclk(void *p)
429{
430 return mpc512x_find_ips_freq(p);
431}
432
433static struct psc_ops mpc512x_psc_ops = {
434 .fifo_init = mpc512x_psc_fifo_init,
435 .raw_rx_rdy = mpc512x_psc_raw_rx_rdy,
436 .raw_tx_rdy = mpc512x_psc_raw_tx_rdy,
437 .rx_rdy = mpc512x_psc_rx_rdy,
438 .tx_rdy = mpc512x_psc_tx_rdy,
439 .tx_empty = mpc512x_psc_tx_empty,
440 .stop_rx = mpc512x_psc_stop_rx,
441 .start_tx = mpc512x_psc_start_tx,
442 .stop_tx = mpc512x_psc_stop_tx,
443 .rx_clr_irq = mpc512x_psc_rx_clr_irq,
444 .tx_clr_irq = mpc512x_psc_tx_clr_irq,
445 .write_char = mpc512x_psc_write_char,
446 .read_char = mpc512x_psc_read_char,
447 .cw_disable_ints = mpc512x_psc_cw_disable_ints,
448 .cw_restore_ints = mpc512x_psc_cw_restore_ints,
449 .getuartclk = mpc512x_getuartclk,
450};
451#endif
452
453static struct psc_ops *psc_ops;
295 454
296/* ======================================================================== */ 455/* ======================================================================== */
297/* UART operations */ 456/* UART operations */
@@ -381,7 +540,8 @@ mpc52xx_uart_startup(struct uart_port *port)
381 540
382 /* Request IRQ */ 541 /* Request IRQ */
383 ret = request_irq(port->irq, mpc52xx_uart_int, 542 ret = request_irq(port->irq, mpc52xx_uart_int,
384 IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "mpc52xx_psc_uart", port); 543 IRQF_DISABLED | IRQF_SAMPLE_RANDOM | IRQF_SHARED,
544 "mpc52xx_psc_uart", port);
385 if (ret) 545 if (ret)
386 return ret; 546 return ret;
387 547
@@ -1208,15 +1368,19 @@ mpc52xx_uart_of_enumerate(void)
1208 static int enum_done; 1368 static int enum_done;
1209 struct device_node *np; 1369 struct device_node *np;
1210 const unsigned int *devno; 1370 const unsigned int *devno;
1371 const struct of_device_id *match;
1211 int i; 1372 int i;
1212 1373
1213 if (enum_done) 1374 if (enum_done)
1214 return; 1375 return;
1215 1376
1216 for_each_node_by_type(np, "serial") { 1377 for_each_node_by_type(np, "serial") {
1217 if (!of_match_node(mpc52xx_uart_of_match, np)) 1378 match = of_match_node(mpc52xx_uart_of_match, np);
1379 if (!match)
1218 continue; 1380 continue;
1219 1381
1382 psc_ops = match->data;
1383
1220 /* Is a particular device number requested? */ 1384 /* Is a particular device number requested? */
1221 devno = of_get_property(np, "port-number", NULL); 1385 devno = of_get_property(np, "port-number", NULL);
1222 mpc52xx_uart_of_assign(np, devno ? *devno : -1); 1386 mpc52xx_uart_of_assign(np, devno ? *devno : -1);
@@ -1277,6 +1441,7 @@ mpc52xx_uart_init(void)
1277 return ret; 1441 return ret;
1278 } 1442 }
1279#else 1443#else
1444 psc_ops = &mpc52xx_psc_ops;
1280 ret = platform_driver_register(&mpc52xx_uart_platform_driver); 1445 ret = platform_driver_register(&mpc52xx_uart_platform_driver);
1281 if (ret) { 1446 if (ret) {
1282 printk(KERN_ERR "%s: platform_driver_register failed (%i)\n", 1447 printk(KERN_ERR "%s: platform_driver_register failed (%i)\n",