aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/serial/Kconfig12
-rw-r--r--drivers/serial/mpc52xx_uart.c177
-rw-r--r--include/asm-powerpc/mpc52xx_psc.h48
3 files changed, 225 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",
diff --git a/include/asm-powerpc/mpc52xx_psc.h b/include/asm-powerpc/mpc52xx_psc.h
index bea42b95390f..710c5d36efaa 100644
--- a/include/asm-powerpc/mpc52xx_psc.h
+++ b/include/asm-powerpc/mpc52xx_psc.h
@@ -190,5 +190,53 @@ struct mpc52xx_psc_fifo {
190 u16 tflwfptr; /* PSC + 0x9e */ 190 u16 tflwfptr; /* PSC + 0x9e */
191}; 191};
192 192
193#define MPC512x_PSC_FIFO_RESET_SLICE 0x80
194#define MPC512x_PSC_FIFO_ENABLE_SLICE 0x01
195#define MPC512x_PSC_FIFO_ENABLE_DMA 0x04
196
197#define MPC512x_PSC_FIFO_EMPTY 0x1
198#define MPC512x_PSC_FIFO_FULL 0x2
199#define MPC512x_PSC_FIFO_ALARM 0x4
200#define MPC512x_PSC_FIFO_URERR 0x8
201#define MPC512x_PSC_FIFO_ORERR 0x01
202#define MPC512x_PSC_FIFO_MEMERROR 0x02
203
204struct mpc512x_psc_fifo {
205 u32 reserved1[10];
206 u32 txcmd; /* PSC + 0x80 */
207 u32 txalarm; /* PSC + 0x84 */
208 u32 txsr; /* PSC + 0x88 */
209 u32 txisr; /* PSC + 0x8c */
210 u32 tximr; /* PSC + 0x90 */
211 u32 txcnt; /* PSC + 0x94 */
212 u32 txptr; /* PSC + 0x98 */
213 u32 txsz; /* PSC + 0x9c */
214 u32 reserved2[7];
215 union {
216 u8 txdata_8;
217 u16 txdata_16;
218 u32 txdata_32;
219 } txdata; /* PSC + 0xbc */
220#define txdata_8 txdata.txdata_8
221#define txdata_16 txdata.txdata_16
222#define txdata_32 txdata.txdata_32
223 u32 rxcmd; /* PSC + 0xc0 */
224 u32 rxalarm; /* PSC + 0xc4 */
225 u32 rxsr; /* PSC + 0xc8 */
226 u32 rxisr; /* PSC + 0xcc */
227 u32 rximr; /* PSC + 0xd0 */
228 u32 rxcnt; /* PSC + 0xd4 */
229 u32 rxptr; /* PSC + 0xd8 */
230 u32 rxsz; /* PSC + 0xdc */
231 u32 reserved3[7];
232 union {
233 u8 rxdata_8;
234 u16 rxdata_16;
235 u32 rxdata_32;
236 } rxdata; /* PSC + 0xfc */
237#define rxdata_8 rxdata.rxdata_8
238#define rxdata_16 rxdata.rxdata_16
239#define rxdata_32 rxdata.rxdata_32
240};
193 241
194#endif /* __ASM_MPC52xx_PSC_H__ */ 242#endif /* __ASM_MPC52xx_PSC_H__ */