aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial
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
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')
-rw-r--r--drivers/serial/Kconfig12
-rw-r--r--drivers/serial/mpc52xx_uart.c177
2 files changed, 177 insertions, 12 deletions
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index d962b74e3114..d9d7673b712b 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -1114,17 +1114,17 @@ config SERIAL_SGI_L1_CONSOLE
1114 say Y. Otherwise, say N. 1114 say Y. Otherwise, say N.
1115 1115
1116config SERIAL_MPC52xx 1116config SERIAL_MPC52xx
1117 tristate "Freescale MPC52xx family PSC serial support" 1117 tristate "Freescale MPC52xx/MPC512x family PSC serial support"
1118 depends on PPC_MPC52xx 1118 depends on PPC_MPC52xx || PPC_MPC512x
1119 select SERIAL_CORE 1119 select SERIAL_CORE
1120 help 1120 help
1121 This drivers support the MPC52xx PSC serial ports. If you would 1121 This driver supports MPC52xx and MPC512x PSC serial ports. If you would
1122 like to use them, you must answer Y or M to this option. Not that 1122 like to use them, you must answer Y or M to this option. Note that
1123 for use as console, it must be included in kernel and not as a 1123 for use as console, it must be included in kernel and not as a
1124 module. 1124 module.
1125 1125
1126config SERIAL_MPC52xx_CONSOLE 1126config SERIAL_MPC52xx_CONSOLE
1127 bool "Console on a Freescale MPC52xx family PSC serial port" 1127 bool "Console on a Freescale MPC52xx/MPC512x family PSC serial port"
1128 depends on SERIAL_MPC52xx=y 1128 depends on SERIAL_MPC52xx=y
1129 select SERIAL_CORE_CONSOLE 1129 select SERIAL_CORE_CONSOLE
1130 help 1130 help
@@ -1132,7 +1132,7 @@ config SERIAL_MPC52xx_CONSOLE
1132 of the Freescale MPC52xx family as a console. 1132 of the Freescale MPC52xx family as a console.
1133 1133
1134config SERIAL_MPC52xx_CONSOLE_BAUD 1134config SERIAL_MPC52xx_CONSOLE_BAUD
1135 int "Freescale MPC52xx family PSC serial port baud" 1135 int "Freescale MPC52xx/MPC512x family PSC serial port baud"
1136 depends on SERIAL_MPC52xx_CONSOLE=y 1136 depends on SERIAL_MPC52xx_CONSOLE=y
1137 default "9600" 1137 default "9600"
1138 help 1138 help
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",