blob: 5be1df39f9f5f6b8fe0671bba23ba8f566e685f4 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 * Driver for the PSC of the Freescale MPC52xx PSCs configured as UARTs.
3 *
4 * FIXME According to the usermanual the status bits in the status register
5 * are only updated when the peripherals access the FIFO and not when the
6 * CPU access them. So since we use this bits to know when we stop writing
7 * and reading, they may not be updated in-time and a race condition may
8 * exists. But I haven't be able to prove this and I don't care. But if
9 * any problem arises, it might worth checking. The TX/RX FIFO Stats
10 * registers should be used in addition.
11 * Update: Actually, they seem updated ... At least the bits we use.
12 *
13 *
14 * Maintainer : Sylvain Munaut <tnt@246tNt.com>
Grant Likely9b9129e2006-11-27 14:21:01 -070015 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070016 * Some of the code has been inspired/copied from the 2.4 code written
17 * by Dale Farnsworth <dfarnsworth@mvista.com>.
Grant Likely9b9129e2006-11-27 14:21:01 -070018 *
John Rigby25ae3a02008-01-29 04:28:56 +110019 * Copyright (C) 2008 Freescale Semiconductor Inc.
20 * John Rigby <jrigby@gmail.com>
21 * Added support for MPC5121
Grant Likelyb9272df2006-11-27 14:21:02 -070022 * Copyright (C) 2006 Secret Lab Technologies Ltd.
23 * Grant Likely <grant.likely@secretlab.ca>
24 * Copyright (C) 2004-2006 Sylvain Munaut <tnt@246tNt.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025 * Copyright (C) 2003 MontaVista, Software, Inc.
Grant Likely9b9129e2006-11-27 14:21:01 -070026 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070027 * This file is licensed under the terms of the GNU General Public License
28 * version 2. This program is licensed "as is" without any warranty of any
29 * kind, whether express or implied.
30 */
Grant Likely9b9129e2006-11-27 14:21:01 -070031
Grant Likelyb9272df2006-11-27 14:21:02 -070032#undef DEBUG
33
34#include <linux/device.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/module.h>
36#include <linux/tty.h>
Jiri Slabyee160a32011-09-01 16:20:57 +020037#include <linux/tty_flip.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070038#include <linux/serial.h>
39#include <linux/sysrq.h>
40#include <linux/console.h>
John Rigby406b7d42008-01-17 08:37:25 +110041#include <linux/delay.h>
42#include <linux/io.h>
Grant Likely283029d2008-01-09 06:20:40 +110043#include <linux/of.h>
44#include <linux/of_platform.h>
Anatolij Gustschin6acc6832010-02-16 22:30:03 -070045#include <linux/clk.h>
Grant Likelyb9272df2006-11-27 14:21:02 -070046
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include <asm/mpc52xx.h>
48#include <asm/mpc52xx_psc.h>
49
50#if defined(CONFIG_SERIAL_MPC52xx_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
51#define SUPPORT_SYSRQ
52#endif
53
54#include <linux/serial_core.h>
55
56
Sylvain Munautd62de3a2006-01-06 00:11:32 -080057/* We've been assigned a range on the "Low-density serial ports" major */
58#define SERIAL_PSC_MAJOR 204
59#define SERIAL_PSC_MINOR 148
60
Linus Torvalds1da177e2005-04-16 15:20:36 -070061
62#define ISR_PASS_LIMIT 256 /* Max number of iteration in the interrupt */
63
64
65static struct uart_port mpc52xx_uart_ports[MPC52xx_PSC_MAXNUM];
66 /* Rem: - We use the read_status_mask as a shadow of
67 * psc->mpc52xx_psc_imr
68 * - It's important that is array is all zero on start as we
69 * use it to know if it's initialized or not ! If it's not sure
70 * it's cleared, then a memset(...,0,...) should be added to
71 * the console_init
72 */
Kumar Gala8d1fb8c2008-08-01 11:09:34 -050073
Grant Likelyb9272df2006-11-27 14:21:02 -070074/* lookup table for matching device nodes to index numbers */
75static struct device_node *mpc52xx_uart_nodes[MPC52xx_PSC_MAXNUM];
76
77static void mpc52xx_uart_of_enumerate(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
John Rigby599f0302008-01-29 04:28:55 +110079
Linus Torvalds1da177e2005-04-16 15:20:36 -070080#define PSC(port) ((struct mpc52xx_psc __iomem *)((port)->membase))
81
82
83/* Forward declaration of the interruption handling routine */
John Rigby406b7d42008-01-17 08:37:25 +110084static irqreturn_t mpc52xx_uart_int(int irq, void *dev_id);
Anatolij Gustschin6acc6832010-02-16 22:30:03 -070085static irqreturn_t mpc5xxx_uart_process_int(struct uart_port *port);
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
John Rigby599f0302008-01-29 04:28:55 +110087/* ======================================================================== */
88/* PSC fifo operations for isolating differences between 52xx and 512x */
89/* ======================================================================== */
90
91struct psc_ops {
92 void (*fifo_init)(struct uart_port *port);
93 int (*raw_rx_rdy)(struct uart_port *port);
94 int (*raw_tx_rdy)(struct uart_port *port);
95 int (*rx_rdy)(struct uart_port *port);
96 int (*tx_rdy)(struct uart_port *port);
97 int (*tx_empty)(struct uart_port *port);
98 void (*stop_rx)(struct uart_port *port);
99 void (*start_tx)(struct uart_port *port);
100 void (*stop_tx)(struct uart_port *port);
101 void (*rx_clr_irq)(struct uart_port *port);
102 void (*tx_clr_irq)(struct uart_port *port);
103 void (*write_char)(struct uart_port *port, unsigned char c);
104 unsigned char (*read_char)(struct uart_port *port);
105 void (*cw_disable_ints)(struct uart_port *port);
106 void (*cw_restore_ints)(struct uart_port *port);
Albrecht Dreß0d1f22e2010-04-26 11:18:12 +0000107 unsigned int (*set_baudrate)(struct uart_port *port,
108 struct ktermios *new,
109 struct ktermios *old);
Gerhard Sittig2d30cca2013-08-06 22:43:42 +0200110 int (*clock_alloc)(struct uart_port *port);
111 void (*clock_relse)(struct uart_port *port);
Anatolij Gustschin6acc6832010-02-16 22:30:03 -0700112 int (*clock)(struct uart_port *port, int enable);
113 int (*fifoc_init)(void);
114 void (*fifoc_uninit)(void);
115 void (*get_irq)(struct uart_port *, struct device_node *);
116 irqreturn_t (*handle_irq)(struct uart_port *port);
Matteo Facchinetti2574b272013-05-24 20:24:58 +0200117 u16 (*get_status)(struct uart_port *port);
118 u8 (*get_ipcr)(struct uart_port *port);
119 void (*command)(struct uart_port *port, u8 cmd);
120 void (*set_mode)(struct uart_port *port, u8 mr1, u8 mr2);
121 void (*set_rts)(struct uart_port *port, int state);
122 void (*enable_ms)(struct uart_port *port);
123 void (*set_sicr)(struct uart_port *port, u32 val);
124 void (*set_imr)(struct uart_port *port, u16 val);
125 u8 (*get_mr1)(struct uart_port *port);
John Rigby599f0302008-01-29 04:28:55 +1100126};
127
Albrecht Dreß0d1f22e2010-04-26 11:18:12 +0000128/* setting the prescaler and divisor reg is common for all chips */
129static inline void mpc52xx_set_divisor(struct mpc52xx_psc __iomem *psc,
130 u16 prescaler, unsigned int divisor)
131{
132 /* select prescaler */
133 out_be16(&psc->mpc52xx_psc_clock_select, prescaler);
134 out_8(&psc->ctur, divisor >> 8);
135 out_8(&psc->ctlr, divisor & 0xff);
136}
137
Matteo Facchinetti2574b272013-05-24 20:24:58 +0200138static u16 mpc52xx_psc_get_status(struct uart_port *port)
139{
140 return in_be16(&PSC(port)->mpc52xx_psc_status);
141}
142
143static u8 mpc52xx_psc_get_ipcr(struct uart_port *port)
144{
145 return in_8(&PSC(port)->mpc52xx_psc_ipcr);
146}
147
148static void mpc52xx_psc_command(struct uart_port *port, u8 cmd)
149{
150 out_8(&PSC(port)->command, cmd);
151}
152
153static void mpc52xx_psc_set_mode(struct uart_port *port, u8 mr1, u8 mr2)
154{
155 out_8(&PSC(port)->command, MPC52xx_PSC_SEL_MODE_REG_1);
156 out_8(&PSC(port)->mode, mr1);
157 out_8(&PSC(port)->mode, mr2);
158}
159
160static void mpc52xx_psc_set_rts(struct uart_port *port, int state)
161{
162 if (state)
163 out_8(&PSC(port)->op1, MPC52xx_PSC_OP_RTS);
164 else
165 out_8(&PSC(port)->op0, MPC52xx_PSC_OP_RTS);
166}
167
168static void mpc52xx_psc_enable_ms(struct uart_port *port)
169{
170 struct mpc52xx_psc __iomem *psc = PSC(port);
171
172 /* clear D_*-bits by reading them */
173 in_8(&psc->mpc52xx_psc_ipcr);
174 /* enable CTS and DCD as IPC interrupts */
175 out_8(&psc->mpc52xx_psc_acr, MPC52xx_PSC_IEC_CTS | MPC52xx_PSC_IEC_DCD);
176
177 port->read_status_mask |= MPC52xx_PSC_IMR_IPC;
178 out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask);
179}
180
181static void mpc52xx_psc_set_sicr(struct uart_port *port, u32 val)
182{
183 out_be32(&PSC(port)->sicr, val);
184}
185
186static void mpc52xx_psc_set_imr(struct uart_port *port, u16 val)
187{
188 out_be16(&PSC(port)->mpc52xx_psc_imr, val);
189}
190
191static u8 mpc52xx_psc_get_mr1(struct uart_port *port)
192{
193 out_8(&PSC(port)->command, MPC52xx_PSC_SEL_MODE_REG_1);
194 return in_8(&PSC(port)->mode);
195}
196
John Rigby25ae3a02008-01-29 04:28:56 +1100197#ifdef CONFIG_PPC_MPC52xx
John Rigby599f0302008-01-29 04:28:55 +1100198#define FIFO_52xx(port) ((struct mpc52xx_psc_fifo __iomem *)(PSC(port)+1))
199static void mpc52xx_psc_fifo_init(struct uart_port *port)
200{
201 struct mpc52xx_psc __iomem *psc = PSC(port);
202 struct mpc52xx_psc_fifo __iomem *fifo = FIFO_52xx(port);
203
John Rigby599f0302008-01-29 04:28:55 +1100204 out_8(&fifo->rfcntl, 0x00);
205 out_be16(&fifo->rfalarm, 0x1ff);
206 out_8(&fifo->tfcntl, 0x07);
207 out_be16(&fifo->tfalarm, 0x80);
208
209 port->read_status_mask |= MPC52xx_PSC_IMR_RXRDY | MPC52xx_PSC_IMR_TXRDY;
210 out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask);
211}
212
213static int mpc52xx_psc_raw_rx_rdy(struct uart_port *port)
214{
215 return in_be16(&PSC(port)->mpc52xx_psc_status)
216 & MPC52xx_PSC_SR_RXRDY;
217}
218
219static int mpc52xx_psc_raw_tx_rdy(struct uart_port *port)
220{
221 return in_be16(&PSC(port)->mpc52xx_psc_status)
222 & MPC52xx_PSC_SR_TXRDY;
223}
224
225
226static int mpc52xx_psc_rx_rdy(struct uart_port *port)
227{
228 return in_be16(&PSC(port)->mpc52xx_psc_isr)
229 & port->read_status_mask
230 & MPC52xx_PSC_IMR_RXRDY;
231}
232
233static int mpc52xx_psc_tx_rdy(struct uart_port *port)
234{
235 return in_be16(&PSC(port)->mpc52xx_psc_isr)
236 & port->read_status_mask
237 & MPC52xx_PSC_IMR_TXRDY;
238}
239
240static int mpc52xx_psc_tx_empty(struct uart_port *port)
241{
242 return in_be16(&PSC(port)->mpc52xx_psc_status)
243 & MPC52xx_PSC_SR_TXEMP;
244}
245
246static void mpc52xx_psc_start_tx(struct uart_port *port)
247{
248 port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY;
249 out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask);
250}
251
252static void mpc52xx_psc_stop_tx(struct uart_port *port)
253{
254 port->read_status_mask &= ~MPC52xx_PSC_IMR_TXRDY;
255 out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask);
256}
257
258static void mpc52xx_psc_stop_rx(struct uart_port *port)
259{
260 port->read_status_mask &= ~MPC52xx_PSC_IMR_RXRDY;
261 out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask);
262}
263
264static void mpc52xx_psc_rx_clr_irq(struct uart_port *port)
265{
266}
267
268static void mpc52xx_psc_tx_clr_irq(struct uart_port *port)
269{
270}
271
272static void mpc52xx_psc_write_char(struct uart_port *port, unsigned char c)
273{
274 out_8(&PSC(port)->mpc52xx_psc_buffer_8, c);
275}
276
277static unsigned char mpc52xx_psc_read_char(struct uart_port *port)
278{
279 return in_8(&PSC(port)->mpc52xx_psc_buffer_8);
280}
281
282static void mpc52xx_psc_cw_disable_ints(struct uart_port *port)
283{
284 out_be16(&PSC(port)->mpc52xx_psc_imr, 0);
285}
286
287static void mpc52xx_psc_cw_restore_ints(struct uart_port *port)
288{
289 out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask);
290}
291
Albrecht Dreß0d1f22e2010-04-26 11:18:12 +0000292static unsigned int mpc5200_psc_set_baudrate(struct uart_port *port,
293 struct ktermios *new,
294 struct ktermios *old)
John Rigby599f0302008-01-29 04:28:55 +1100295{
Albrecht Dreß0d1f22e2010-04-26 11:18:12 +0000296 unsigned int baud;
297 unsigned int divisor;
298
299 /* The 5200 has a fixed /32 prescaler, uartclk contains the ipb freq */
300 baud = uart_get_baud_rate(port, new, old,
301 port->uartclk / (32 * 0xffff) + 1,
302 port->uartclk / 32);
303 divisor = (port->uartclk + 16 * baud) / (32 * baud);
304
305 /* enable the /32 prescaler and set the divisor */
306 mpc52xx_set_divisor(PSC(port), 0xdd00, divisor);
307 return baud;
308}
309
310static unsigned int mpc5200b_psc_set_baudrate(struct uart_port *port,
311 struct ktermios *new,
312 struct ktermios *old)
313{
314 unsigned int baud;
315 unsigned int divisor;
316 u16 prescaler;
317
318 /* The 5200B has a selectable /4 or /32 prescaler, uartclk contains the
319 * ipb freq */
320 baud = uart_get_baud_rate(port, new, old,
321 port->uartclk / (32 * 0xffff) + 1,
322 port->uartclk / 4);
323 divisor = (port->uartclk + 2 * baud) / (4 * baud);
324
Frank Benkerte0955ac2012-03-05 16:14:29 +0100325 /* select the proper prescaler and set the divisor
326 * prefer high prescaler for more tolerance on low baudrates */
327 if (divisor > 0xffff || baud <= 115200) {
Albrecht Dreß0d1f22e2010-04-26 11:18:12 +0000328 divisor = (divisor + 4) / 8;
329 prescaler = 0xdd00; /* /32 */
330 } else
331 prescaler = 0xff00; /* /4 */
332 mpc52xx_set_divisor(PSC(port), prescaler, divisor);
333 return baud;
John Rigby599f0302008-01-29 04:28:55 +1100334}
335
Anatolij Gustschin6acc6832010-02-16 22:30:03 -0700336static void mpc52xx_psc_get_irq(struct uart_port *port, struct device_node *np)
337{
Yong Zhang9cfb5c02011-09-22 16:59:15 +0800338 port->irqflags = 0;
Anatolij Gustschin6acc6832010-02-16 22:30:03 -0700339 port->irq = irq_of_parse_and_map(np, 0);
340}
341
342/* 52xx specific interrupt handler. The caller holds the port lock */
343static irqreturn_t mpc52xx_psc_handle_irq(struct uart_port *port)
344{
345 return mpc5xxx_uart_process_int(port);
346}
347
John Rigby599f0302008-01-29 04:28:55 +1100348static struct psc_ops mpc52xx_psc_ops = {
349 .fifo_init = mpc52xx_psc_fifo_init,
350 .raw_rx_rdy = mpc52xx_psc_raw_rx_rdy,
351 .raw_tx_rdy = mpc52xx_psc_raw_tx_rdy,
352 .rx_rdy = mpc52xx_psc_rx_rdy,
353 .tx_rdy = mpc52xx_psc_tx_rdy,
354 .tx_empty = mpc52xx_psc_tx_empty,
355 .stop_rx = mpc52xx_psc_stop_rx,
356 .start_tx = mpc52xx_psc_start_tx,
357 .stop_tx = mpc52xx_psc_stop_tx,
358 .rx_clr_irq = mpc52xx_psc_rx_clr_irq,
359 .tx_clr_irq = mpc52xx_psc_tx_clr_irq,
360 .write_char = mpc52xx_psc_write_char,
361 .read_char = mpc52xx_psc_read_char,
362 .cw_disable_ints = mpc52xx_psc_cw_disable_ints,
363 .cw_restore_ints = mpc52xx_psc_cw_restore_ints,
Albrecht Dreß0d1f22e2010-04-26 11:18:12 +0000364 .set_baudrate = mpc5200_psc_set_baudrate,
365 .get_irq = mpc52xx_psc_get_irq,
366 .handle_irq = mpc52xx_psc_handle_irq,
Matteo Facchinetti2574b272013-05-24 20:24:58 +0200367 .get_status = mpc52xx_psc_get_status,
368 .get_ipcr = mpc52xx_psc_get_ipcr,
369 .command = mpc52xx_psc_command,
370 .set_mode = mpc52xx_psc_set_mode,
371 .set_rts = mpc52xx_psc_set_rts,
372 .enable_ms = mpc52xx_psc_enable_ms,
373 .set_sicr = mpc52xx_psc_set_sicr,
374 .set_imr = mpc52xx_psc_set_imr,
375 .get_mr1 = mpc52xx_psc_get_mr1,
Albrecht Dreß0d1f22e2010-04-26 11:18:12 +0000376};
377
378static struct psc_ops mpc5200b_psc_ops = {
379 .fifo_init = mpc52xx_psc_fifo_init,
380 .raw_rx_rdy = mpc52xx_psc_raw_rx_rdy,
381 .raw_tx_rdy = mpc52xx_psc_raw_tx_rdy,
382 .rx_rdy = mpc52xx_psc_rx_rdy,
383 .tx_rdy = mpc52xx_psc_tx_rdy,
384 .tx_empty = mpc52xx_psc_tx_empty,
385 .stop_rx = mpc52xx_psc_stop_rx,
386 .start_tx = mpc52xx_psc_start_tx,
387 .stop_tx = mpc52xx_psc_stop_tx,
388 .rx_clr_irq = mpc52xx_psc_rx_clr_irq,
389 .tx_clr_irq = mpc52xx_psc_tx_clr_irq,
390 .write_char = mpc52xx_psc_write_char,
391 .read_char = mpc52xx_psc_read_char,
392 .cw_disable_ints = mpc52xx_psc_cw_disable_ints,
393 .cw_restore_ints = mpc52xx_psc_cw_restore_ints,
394 .set_baudrate = mpc5200b_psc_set_baudrate,
Anatolij Gustschin6acc6832010-02-16 22:30:03 -0700395 .get_irq = mpc52xx_psc_get_irq,
396 .handle_irq = mpc52xx_psc_handle_irq,
Matteo Facchinetti2574b272013-05-24 20:24:58 +0200397 .get_status = mpc52xx_psc_get_status,
398 .get_ipcr = mpc52xx_psc_get_ipcr,
399 .command = mpc52xx_psc_command,
400 .set_mode = mpc52xx_psc_set_mode,
401 .set_rts = mpc52xx_psc_set_rts,
402 .enable_ms = mpc52xx_psc_enable_ms,
403 .set_sicr = mpc52xx_psc_set_sicr,
404 .set_imr = mpc52xx_psc_set_imr,
405 .get_mr1 = mpc52xx_psc_get_mr1,
John Rigby599f0302008-01-29 04:28:55 +1100406};
407
John Rigby25ae3a02008-01-29 04:28:56 +1100408#endif /* CONFIG_MPC52xx */
409
410#ifdef CONFIG_PPC_MPC512x
411#define FIFO_512x(port) ((struct mpc512x_psc_fifo __iomem *)(PSC(port)+1))
Anatolij Gustschin6acc6832010-02-16 22:30:03 -0700412
413/* PSC FIFO Controller for mpc512x */
414struct psc_fifoc {
415 u32 fifoc_cmd;
416 u32 fifoc_int;
417 u32 fifoc_dma;
418 u32 fifoc_axe;
419 u32 fifoc_debug;
420};
421
422static struct psc_fifoc __iomem *psc_fifoc;
423static unsigned int psc_fifoc_irq;
424
John Rigby25ae3a02008-01-29 04:28:56 +1100425static void mpc512x_psc_fifo_init(struct uart_port *port)
426{
Anatolij Gustschin6acc6832010-02-16 22:30:03 -0700427 /* /32 prescaler */
428 out_be16(&PSC(port)->mpc52xx_psc_clock_select, 0xdd00);
429
John Rigby25ae3a02008-01-29 04:28:56 +1100430 out_be32(&FIFO_512x(port)->txcmd, MPC512x_PSC_FIFO_RESET_SLICE);
431 out_be32(&FIFO_512x(port)->txcmd, MPC512x_PSC_FIFO_ENABLE_SLICE);
432 out_be32(&FIFO_512x(port)->txalarm, 1);
433 out_be32(&FIFO_512x(port)->tximr, 0);
434
435 out_be32(&FIFO_512x(port)->rxcmd, MPC512x_PSC_FIFO_RESET_SLICE);
436 out_be32(&FIFO_512x(port)->rxcmd, MPC512x_PSC_FIFO_ENABLE_SLICE);
437 out_be32(&FIFO_512x(port)->rxalarm, 1);
438 out_be32(&FIFO_512x(port)->rximr, 0);
439
440 out_be32(&FIFO_512x(port)->tximr, MPC512x_PSC_FIFO_ALARM);
441 out_be32(&FIFO_512x(port)->rximr, MPC512x_PSC_FIFO_ALARM);
442}
443
444static int mpc512x_psc_raw_rx_rdy(struct uart_port *port)
445{
446 return !(in_be32(&FIFO_512x(port)->rxsr) & MPC512x_PSC_FIFO_EMPTY);
447}
448
449static int mpc512x_psc_raw_tx_rdy(struct uart_port *port)
450{
451 return !(in_be32(&FIFO_512x(port)->txsr) & MPC512x_PSC_FIFO_FULL);
452}
453
454static int mpc512x_psc_rx_rdy(struct uart_port *port)
455{
456 return in_be32(&FIFO_512x(port)->rxsr)
457 & in_be32(&FIFO_512x(port)->rximr)
458 & MPC512x_PSC_FIFO_ALARM;
459}
460
461static int mpc512x_psc_tx_rdy(struct uart_port *port)
462{
463 return in_be32(&FIFO_512x(port)->txsr)
464 & in_be32(&FIFO_512x(port)->tximr)
465 & MPC512x_PSC_FIFO_ALARM;
466}
467
468static int mpc512x_psc_tx_empty(struct uart_port *port)
469{
470 return in_be32(&FIFO_512x(port)->txsr)
471 & MPC512x_PSC_FIFO_EMPTY;
472}
473
474static void mpc512x_psc_stop_rx(struct uart_port *port)
475{
476 unsigned long rx_fifo_imr;
477
478 rx_fifo_imr = in_be32(&FIFO_512x(port)->rximr);
479 rx_fifo_imr &= ~MPC512x_PSC_FIFO_ALARM;
480 out_be32(&FIFO_512x(port)->rximr, rx_fifo_imr);
481}
482
483static void mpc512x_psc_start_tx(struct uart_port *port)
484{
485 unsigned long tx_fifo_imr;
486
487 tx_fifo_imr = in_be32(&FIFO_512x(port)->tximr);
488 tx_fifo_imr |= MPC512x_PSC_FIFO_ALARM;
489 out_be32(&FIFO_512x(port)->tximr, tx_fifo_imr);
490}
491
492static void mpc512x_psc_stop_tx(struct uart_port *port)
493{
494 unsigned long tx_fifo_imr;
495
496 tx_fifo_imr = in_be32(&FIFO_512x(port)->tximr);
497 tx_fifo_imr &= ~MPC512x_PSC_FIFO_ALARM;
498 out_be32(&FIFO_512x(port)->tximr, tx_fifo_imr);
499}
500
501static void mpc512x_psc_rx_clr_irq(struct uart_port *port)
502{
503 out_be32(&FIFO_512x(port)->rxisr, in_be32(&FIFO_512x(port)->rxisr));
504}
505
506static void mpc512x_psc_tx_clr_irq(struct uart_port *port)
507{
508 out_be32(&FIFO_512x(port)->txisr, in_be32(&FIFO_512x(port)->txisr));
509}
510
511static void mpc512x_psc_write_char(struct uart_port *port, unsigned char c)
512{
513 out_8(&FIFO_512x(port)->txdata_8, c);
514}
515
516static unsigned char mpc512x_psc_read_char(struct uart_port *port)
517{
518 return in_8(&FIFO_512x(port)->rxdata_8);
519}
520
521static void mpc512x_psc_cw_disable_ints(struct uart_port *port)
522{
523 port->read_status_mask =
524 in_be32(&FIFO_512x(port)->tximr) << 16 |
525 in_be32(&FIFO_512x(port)->rximr);
526 out_be32(&FIFO_512x(port)->tximr, 0);
527 out_be32(&FIFO_512x(port)->rximr, 0);
528}
529
530static void mpc512x_psc_cw_restore_ints(struct uart_port *port)
531{
532 out_be32(&FIFO_512x(port)->tximr,
533 (port->read_status_mask >> 16) & 0x7f);
534 out_be32(&FIFO_512x(port)->rximr, port->read_status_mask & 0x7f);
535}
536
Albrecht Dreß0d1f22e2010-04-26 11:18:12 +0000537static unsigned int mpc512x_psc_set_baudrate(struct uart_port *port,
538 struct ktermios *new,
539 struct ktermios *old)
John Rigby25ae3a02008-01-29 04:28:56 +1100540{
Albrecht Dreß0d1f22e2010-04-26 11:18:12 +0000541 unsigned int baud;
542 unsigned int divisor;
543
544 /*
545 * The "MPC5121e Microcontroller Reference Manual, Rev. 3" says on
546 * pg. 30-10 that the chip supports a /32 and a /10 prescaler.
547 * Furthermore, it states that "After reset, the prescaler by 10
548 * for the UART mode is selected", but the reset register value is
549 * 0x0000 which means a /32 prescaler. This is wrong.
550 *
551 * In reality using /32 prescaler doesn't work, as it is not supported!
552 * Use /16 or /10 prescaler, see "MPC5121e Hardware Design Guide",
553 * Chapter 4.1 PSC in UART Mode.
554 * Calculate with a /16 prescaler here.
555 */
556
557 /* uartclk contains the ips freq */
558 baud = uart_get_baud_rate(port, new, old,
559 port->uartclk / (16 * 0xffff) + 1,
560 port->uartclk / 16);
561 divisor = (port->uartclk + 8 * baud) / (16 * baud);
562
563 /* enable the /16 prescaler and set the divisor */
564 mpc52xx_set_divisor(PSC(port), 0xdd00, divisor);
565 return baud;
John Rigby25ae3a02008-01-29 04:28:56 +1100566}
567
Anatolij Gustschin6acc6832010-02-16 22:30:03 -0700568/* Init PSC FIFO Controller */
569static int __init mpc512x_psc_fifoc_init(void)
570{
571 struct device_node *np;
Anatolij Gustschin6acc6832010-02-16 22:30:03 -0700572
573 np = of_find_compatible_node(NULL, NULL,
574 "fsl,mpc5121-psc-fifo");
575 if (!np) {
576 pr_err("%s: Can't find FIFOC node\n", __func__);
577 return -ENODEV;
578 }
579
580 psc_fifoc = of_iomap(np, 0);
581 if (!psc_fifoc) {
582 pr_err("%s: Can't map FIFOC\n", __func__);
Julia Lawall05f25ab2010-08-29 11:52:41 +0200583 of_node_put(np);
Anatolij Gustschin6acc6832010-02-16 22:30:03 -0700584 return -ENODEV;
585 }
586
587 psc_fifoc_irq = irq_of_parse_and_map(np, 0);
588 of_node_put(np);
Alan Coxd4e33fa2012-01-26 17:44:09 +0000589 if (psc_fifoc_irq == 0) {
Anatolij Gustschin6acc6832010-02-16 22:30:03 -0700590 pr_err("%s: Can't get FIFOC irq\n", __func__);
591 iounmap(psc_fifoc);
592 return -ENODEV;
593 }
594
Anatolij Gustschin6acc6832010-02-16 22:30:03 -0700595 return 0;
596}
597
598static void __exit mpc512x_psc_fifoc_uninit(void)
599{
600 iounmap(psc_fifoc);
601}
602
603/* 512x specific interrupt handler. The caller holds the port lock */
604static irqreturn_t mpc512x_psc_handle_irq(struct uart_port *port)
605{
606 unsigned long fifoc_int;
607 int psc_num;
608
609 /* Read pending PSC FIFOC interrupts */
610 fifoc_int = in_be32(&psc_fifoc->fifoc_int);
611
612 /* Check if it is an interrupt for this port */
613 psc_num = (port->mapbase & 0xf00) >> 8;
614 if (test_bit(psc_num, &fifoc_int) ||
615 test_bit(psc_num + 16, &fifoc_int))
616 return mpc5xxx_uart_process_int(port);
617
618 return IRQ_NONE;
619}
620
Gerhard Sittig2d30cca2013-08-06 22:43:42 +0200621static struct clk *psc_mclk_clk[MPC52xx_PSC_MAXNUM];
622
623/* called from within the .request_port() callback (allocation) */
624static int mpc512x_psc_alloc_clock(struct uart_port *port)
Anatolij Gustschin6acc6832010-02-16 22:30:03 -0700625{
Anatolij Gustschin6acc6832010-02-16 22:30:03 -0700626 int psc_num;
Gerhard Sittig2d30cca2013-08-06 22:43:42 +0200627 char clk_name[16];
628 struct clk *clk;
629 int err;
630
631 psc_num = (port->mapbase & 0xf00) >> 8;
632 snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
633 clk = devm_clk_get(port->dev, clk_name);
634 if (IS_ERR(clk)) {
635 dev_err(port->dev, "Failed to get MCLK!\n");
636 return PTR_ERR(clk);
637 }
638 err = clk_prepare_enable(clk);
639 if (err) {
640 dev_err(port->dev, "Failed to enable MCLK!\n");
641 return err;
642 }
643 psc_mclk_clk[psc_num] = clk;
644 return 0;
645}
646
647/* called from within the .release_port() callback (release) */
648static void mpc512x_psc_relse_clock(struct uart_port *port)
649{
650 int psc_num;
651 struct clk *clk;
652
653 psc_num = (port->mapbase & 0xf00) >> 8;
654 clk = psc_mclk_clk[psc_num];
655 if (clk) {
656 clk_disable_unprepare(clk);
657 psc_mclk_clk[psc_num] = NULL;
658 }
659}
660
661/* implementation of the .clock() callback (enable/disable) */
662static int mpc512x_psc_endis_clock(struct uart_port *port, int enable)
663{
664 int psc_num;
665 struct clk *psc_clk;
666 int ret;
Anatolij Gustschin6acc6832010-02-16 22:30:03 -0700667
668 if (uart_console(port))
669 return 0;
670
671 psc_num = (port->mapbase & 0xf00) >> 8;
Gerhard Sittig2d30cca2013-08-06 22:43:42 +0200672 psc_clk = psc_mclk_clk[psc_num];
673 if (!psc_clk) {
Anatolij Gustschin6acc6832010-02-16 22:30:03 -0700674 dev_err(port->dev, "Failed to get PSC clock entry!\n");
675 return -ENODEV;
676 }
677
Gerhard Sittig2d30cca2013-08-06 22:43:42 +0200678 dev_dbg(port->dev, "mclk %sable\n", enable ? "en" : "dis");
679 if (enable) {
680 ret = clk_enable(psc_clk);
681 if (ret)
682 dev_err(port->dev, "Failed to enable MCLK!\n");
683 return ret;
684 } else {
Anatolij Gustschin6acc6832010-02-16 22:30:03 -0700685 clk_disable(psc_clk);
Gerhard Sittig2d30cca2013-08-06 22:43:42 +0200686 return 0;
687 }
Anatolij Gustschin6acc6832010-02-16 22:30:03 -0700688}
689
690static void mpc512x_psc_get_irq(struct uart_port *port, struct device_node *np)
691{
692 port->irqflags = IRQF_SHARED;
693 port->irq = psc_fifoc_irq;
694}
Matteo Facchinetti1f48c492013-05-24 20:24:59 +0200695#endif
696
697#ifdef CONFIG_PPC_MPC512x
698
699#define PSC_5125(port) ((struct mpc5125_psc __iomem *)((port)->membase))
700#define FIFO_5125(port) ((struct mpc512x_psc_fifo __iomem *)(PSC_5125(port)+1))
701
702static void mpc5125_psc_fifo_init(struct uart_port *port)
703{
704 /* /32 prescaler */
705 out_8(&PSC_5125(port)->mpc52xx_psc_clock_select, 0xdd);
706
707 out_be32(&FIFO_5125(port)->txcmd, MPC512x_PSC_FIFO_RESET_SLICE);
708 out_be32(&FIFO_5125(port)->txcmd, MPC512x_PSC_FIFO_ENABLE_SLICE);
709 out_be32(&FIFO_5125(port)->txalarm, 1);
710 out_be32(&FIFO_5125(port)->tximr, 0);
711
712 out_be32(&FIFO_5125(port)->rxcmd, MPC512x_PSC_FIFO_RESET_SLICE);
713 out_be32(&FIFO_5125(port)->rxcmd, MPC512x_PSC_FIFO_ENABLE_SLICE);
714 out_be32(&FIFO_5125(port)->rxalarm, 1);
715 out_be32(&FIFO_5125(port)->rximr, 0);
716
717 out_be32(&FIFO_5125(port)->tximr, MPC512x_PSC_FIFO_ALARM);
718 out_be32(&FIFO_5125(port)->rximr, MPC512x_PSC_FIFO_ALARM);
719}
720
721static int mpc5125_psc_raw_rx_rdy(struct uart_port *port)
722{
723 return !(in_be32(&FIFO_5125(port)->rxsr) & MPC512x_PSC_FIFO_EMPTY);
724}
725
726static int mpc5125_psc_raw_tx_rdy(struct uart_port *port)
727{
728 return !(in_be32(&FIFO_5125(port)->txsr) & MPC512x_PSC_FIFO_FULL);
729}
730
731static int mpc5125_psc_rx_rdy(struct uart_port *port)
732{
733 return in_be32(&FIFO_5125(port)->rxsr) &
734 in_be32(&FIFO_5125(port)->rximr) & MPC512x_PSC_FIFO_ALARM;
735}
736
737static int mpc5125_psc_tx_rdy(struct uart_port *port)
738{
739 return in_be32(&FIFO_5125(port)->txsr) &
740 in_be32(&FIFO_5125(port)->tximr) & MPC512x_PSC_FIFO_ALARM;
741}
742
743static int mpc5125_psc_tx_empty(struct uart_port *port)
744{
745 return in_be32(&FIFO_5125(port)->txsr) & MPC512x_PSC_FIFO_EMPTY;
746}
747
748static void mpc5125_psc_stop_rx(struct uart_port *port)
749{
750 unsigned long rx_fifo_imr;
751
752 rx_fifo_imr = in_be32(&FIFO_5125(port)->rximr);
753 rx_fifo_imr &= ~MPC512x_PSC_FIFO_ALARM;
754 out_be32(&FIFO_5125(port)->rximr, rx_fifo_imr);
755}
756
757static void mpc5125_psc_start_tx(struct uart_port *port)
758{
759 unsigned long tx_fifo_imr;
760
761 tx_fifo_imr = in_be32(&FIFO_5125(port)->tximr);
762 tx_fifo_imr |= MPC512x_PSC_FIFO_ALARM;
763 out_be32(&FIFO_5125(port)->tximr, tx_fifo_imr);
764}
765
766static void mpc5125_psc_stop_tx(struct uart_port *port)
767{
768 unsigned long tx_fifo_imr;
769
770 tx_fifo_imr = in_be32(&FIFO_5125(port)->tximr);
771 tx_fifo_imr &= ~MPC512x_PSC_FIFO_ALARM;
772 out_be32(&FIFO_5125(port)->tximr, tx_fifo_imr);
773}
774
775static void mpc5125_psc_rx_clr_irq(struct uart_port *port)
776{
777 out_be32(&FIFO_5125(port)->rxisr, in_be32(&FIFO_5125(port)->rxisr));
778}
779
780static void mpc5125_psc_tx_clr_irq(struct uart_port *port)
781{
782 out_be32(&FIFO_5125(port)->txisr, in_be32(&FIFO_5125(port)->txisr));
783}
784
785static void mpc5125_psc_write_char(struct uart_port *port, unsigned char c)
786{
787 out_8(&FIFO_5125(port)->txdata_8, c);
788}
789
790static unsigned char mpc5125_psc_read_char(struct uart_port *port)
791{
792 return in_8(&FIFO_5125(port)->rxdata_8);
793}
794
795static void mpc5125_psc_cw_disable_ints(struct uart_port *port)
796{
797 port->read_status_mask =
798 in_be32(&FIFO_5125(port)->tximr) << 16 |
799 in_be32(&FIFO_5125(port)->rximr);
800 out_be32(&FIFO_5125(port)->tximr, 0);
801 out_be32(&FIFO_5125(port)->rximr, 0);
802}
803
804static void mpc5125_psc_cw_restore_ints(struct uart_port *port)
805{
806 out_be32(&FIFO_5125(port)->tximr,
807 (port->read_status_mask >> 16) & 0x7f);
808 out_be32(&FIFO_5125(port)->rximr, port->read_status_mask & 0x7f);
809}
810
811static inline void mpc5125_set_divisor(struct mpc5125_psc __iomem *psc,
812 u8 prescaler, unsigned int divisor)
813{
814 /* select prescaler */
815 out_8(&psc->mpc52xx_psc_clock_select, prescaler);
816 out_8(&psc->ctur, divisor >> 8);
817 out_8(&psc->ctlr, divisor & 0xff);
818}
819
820static unsigned int mpc5125_psc_set_baudrate(struct uart_port *port,
821 struct ktermios *new,
822 struct ktermios *old)
823{
824 unsigned int baud;
825 unsigned int divisor;
826
827 /*
828 * Calculate with a /16 prescaler here.
829 */
830
831 /* uartclk contains the ips freq */
832 baud = uart_get_baud_rate(port, new, old,
833 port->uartclk / (16 * 0xffff) + 1,
834 port->uartclk / 16);
835 divisor = (port->uartclk + 8 * baud) / (16 * baud);
836
837 /* enable the /16 prescaler and set the divisor */
838 mpc5125_set_divisor(PSC_5125(port), 0xdd, divisor);
839 return baud;
840}
841
842/*
843 * MPC5125 have compatible PSC FIFO Controller.
844 * Special init not needed.
845 */
846static u16 mpc5125_psc_get_status(struct uart_port *port)
847{
848 return in_be16(&PSC_5125(port)->mpc52xx_psc_status);
849}
850
851static u8 mpc5125_psc_get_ipcr(struct uart_port *port)
852{
853 return in_8(&PSC_5125(port)->mpc52xx_psc_ipcr);
854}
855
856static void mpc5125_psc_command(struct uart_port *port, u8 cmd)
857{
858 out_8(&PSC_5125(port)->command, cmd);
859}
860
861static void mpc5125_psc_set_mode(struct uart_port *port, u8 mr1, u8 mr2)
862{
863 out_8(&PSC_5125(port)->mr1, mr1);
864 out_8(&PSC_5125(port)->mr2, mr2);
865}
866
867static void mpc5125_psc_set_rts(struct uart_port *port, int state)
868{
869 if (state & TIOCM_RTS)
870 out_8(&PSC_5125(port)->op1, MPC52xx_PSC_OP_RTS);
871 else
872 out_8(&PSC_5125(port)->op0, MPC52xx_PSC_OP_RTS);
873}
874
875static void mpc5125_psc_enable_ms(struct uart_port *port)
876{
877 struct mpc5125_psc __iomem *psc = PSC_5125(port);
878
879 /* clear D_*-bits by reading them */
880 in_8(&psc->mpc52xx_psc_ipcr);
881 /* enable CTS and DCD as IPC interrupts */
882 out_8(&psc->mpc52xx_psc_acr, MPC52xx_PSC_IEC_CTS | MPC52xx_PSC_IEC_DCD);
883
884 port->read_status_mask |= MPC52xx_PSC_IMR_IPC;
885 out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask);
886}
887
888static void mpc5125_psc_set_sicr(struct uart_port *port, u32 val)
889{
890 out_be32(&PSC_5125(port)->sicr, val);
891}
892
893static void mpc5125_psc_set_imr(struct uart_port *port, u16 val)
894{
895 out_be16(&PSC_5125(port)->mpc52xx_psc_imr, val);
896}
897
898static u8 mpc5125_psc_get_mr1(struct uart_port *port)
899{
900 return in_8(&PSC_5125(port)->mr1);
901}
902
903static struct psc_ops mpc5125_psc_ops = {
904 .fifo_init = mpc5125_psc_fifo_init,
905 .raw_rx_rdy = mpc5125_psc_raw_rx_rdy,
906 .raw_tx_rdy = mpc5125_psc_raw_tx_rdy,
907 .rx_rdy = mpc5125_psc_rx_rdy,
908 .tx_rdy = mpc5125_psc_tx_rdy,
909 .tx_empty = mpc5125_psc_tx_empty,
910 .stop_rx = mpc5125_psc_stop_rx,
911 .start_tx = mpc5125_psc_start_tx,
912 .stop_tx = mpc5125_psc_stop_tx,
913 .rx_clr_irq = mpc5125_psc_rx_clr_irq,
914 .tx_clr_irq = mpc5125_psc_tx_clr_irq,
915 .write_char = mpc5125_psc_write_char,
916 .read_char = mpc5125_psc_read_char,
917 .cw_disable_ints = mpc5125_psc_cw_disable_ints,
918 .cw_restore_ints = mpc5125_psc_cw_restore_ints,
919 .set_baudrate = mpc5125_psc_set_baudrate,
Gerhard Sittig2d30cca2013-08-06 22:43:42 +0200920 .clock_alloc = mpc512x_psc_alloc_clock,
921 .clock_relse = mpc512x_psc_relse_clock,
922 .clock = mpc512x_psc_endis_clock,
Matteo Facchinetti1f48c492013-05-24 20:24:59 +0200923 .fifoc_init = mpc512x_psc_fifoc_init,
924 .fifoc_uninit = mpc512x_psc_fifoc_uninit,
925 .get_irq = mpc512x_psc_get_irq,
926 .handle_irq = mpc512x_psc_handle_irq,
927 .get_status = mpc5125_psc_get_status,
928 .get_ipcr = mpc5125_psc_get_ipcr,
929 .command = mpc5125_psc_command,
930 .set_mode = mpc5125_psc_set_mode,
931 .set_rts = mpc5125_psc_set_rts,
932 .enable_ms = mpc5125_psc_enable_ms,
933 .set_sicr = mpc5125_psc_set_sicr,
934 .set_imr = mpc5125_psc_set_imr,
935 .get_mr1 = mpc5125_psc_get_mr1,
936};
Anatolij Gustschin6acc6832010-02-16 22:30:03 -0700937
John Rigby25ae3a02008-01-29 04:28:56 +1100938static struct psc_ops mpc512x_psc_ops = {
939 .fifo_init = mpc512x_psc_fifo_init,
940 .raw_rx_rdy = mpc512x_psc_raw_rx_rdy,
941 .raw_tx_rdy = mpc512x_psc_raw_tx_rdy,
942 .rx_rdy = mpc512x_psc_rx_rdy,
943 .tx_rdy = mpc512x_psc_tx_rdy,
944 .tx_empty = mpc512x_psc_tx_empty,
945 .stop_rx = mpc512x_psc_stop_rx,
946 .start_tx = mpc512x_psc_start_tx,
947 .stop_tx = mpc512x_psc_stop_tx,
948 .rx_clr_irq = mpc512x_psc_rx_clr_irq,
949 .tx_clr_irq = mpc512x_psc_tx_clr_irq,
950 .write_char = mpc512x_psc_write_char,
951 .read_char = mpc512x_psc_read_char,
952 .cw_disable_ints = mpc512x_psc_cw_disable_ints,
953 .cw_restore_ints = mpc512x_psc_cw_restore_ints,
Albrecht Dreß0d1f22e2010-04-26 11:18:12 +0000954 .set_baudrate = mpc512x_psc_set_baudrate,
Gerhard Sittig2d30cca2013-08-06 22:43:42 +0200955 .clock_alloc = mpc512x_psc_alloc_clock,
956 .clock_relse = mpc512x_psc_relse_clock,
957 .clock = mpc512x_psc_endis_clock,
Anatolij Gustschin6acc6832010-02-16 22:30:03 -0700958 .fifoc_init = mpc512x_psc_fifoc_init,
959 .fifoc_uninit = mpc512x_psc_fifoc_uninit,
960 .get_irq = mpc512x_psc_get_irq,
961 .handle_irq = mpc512x_psc_handle_irq,
Matteo Facchinetti2574b272013-05-24 20:24:58 +0200962 .get_status = mpc52xx_psc_get_status,
963 .get_ipcr = mpc52xx_psc_get_ipcr,
964 .command = mpc52xx_psc_command,
965 .set_mode = mpc52xx_psc_set_mode,
966 .set_rts = mpc52xx_psc_set_rts,
967 .enable_ms = mpc52xx_psc_enable_ms,
968 .set_sicr = mpc52xx_psc_set_sicr,
969 .set_imr = mpc52xx_psc_set_imr,
970 .get_mr1 = mpc52xx_psc_get_mr1,
John Rigby25ae3a02008-01-29 04:28:56 +1100971};
Matteo Facchinetti2574b272013-05-24 20:24:58 +0200972#endif /* CONFIG_PPC_MPC512x */
973
John Rigby25ae3a02008-01-29 04:28:56 +1100974
Uwe Kleine-König76d28e42012-05-21 21:57:39 +0200975static const struct psc_ops *psc_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976
977/* ======================================================================== */
978/* UART operations */
979/* ======================================================================== */
980
Grant Likely9b9129e2006-11-27 14:21:01 -0700981static unsigned int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982mpc52xx_uart_tx_empty(struct uart_port *port)
983{
John Rigby599f0302008-01-29 04:28:55 +1100984 return psc_ops->tx_empty(port) ? TIOCSER_TEMT : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985}
986
Grant Likely9b9129e2006-11-27 14:21:01 -0700987static void
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988mpc52xx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
989{
Matteo Facchinetti2574b272013-05-24 20:24:58 +0200990 psc_ops->set_rts(port, mctrl & TIOCM_RTS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991}
992
Grant Likely9b9129e2006-11-27 14:21:01 -0700993static unsigned int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994mpc52xx_uart_get_mctrl(struct uart_port *port)
995{
Wolfram Sangaec739e2008-12-21 02:54:32 -0700996 unsigned int ret = TIOCM_DSR;
Matteo Facchinetti2574b272013-05-24 20:24:58 +0200997 u8 status = psc_ops->get_ipcr(port);
Wolfram Sangaec739e2008-12-21 02:54:32 -0700998
999 if (!(status & MPC52xx_PSC_CTS))
1000 ret |= TIOCM_CTS;
1001 if (!(status & MPC52xx_PSC_DCD))
1002 ret |= TIOCM_CAR;
1003
1004 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005}
1006
Grant Likely9b9129e2006-11-27 14:21:01 -07001007static void
Russell Kingb129a8c2005-08-31 10:12:14 +01001008mpc52xx_uart_stop_tx(struct uart_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009{
1010 /* port->lock taken by caller */
John Rigby599f0302008-01-29 04:28:55 +11001011 psc_ops->stop_tx(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012}
1013
Grant Likely9b9129e2006-11-27 14:21:01 -07001014static void
Russell Kingb129a8c2005-08-31 10:12:14 +01001015mpc52xx_uart_start_tx(struct uart_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016{
1017 /* port->lock taken by caller */
John Rigby599f0302008-01-29 04:28:55 +11001018 psc_ops->start_tx(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019}
1020
Grant Likely9b9129e2006-11-27 14:21:01 -07001021static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022mpc52xx_uart_send_xchar(struct uart_port *port, char ch)
1023{
1024 unsigned long flags;
1025 spin_lock_irqsave(&port->lock, flags);
Grant Likely9b9129e2006-11-27 14:21:01 -07001026
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 port->x_char = ch;
1028 if (ch) {
1029 /* Make sure tx interrupts are on */
1030 /* Truly necessary ??? They should be anyway */
John Rigby599f0302008-01-29 04:28:55 +11001031 psc_ops->start_tx(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 }
Grant Likely9b9129e2006-11-27 14:21:01 -07001033
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 spin_unlock_irqrestore(&port->lock, flags);
1035}
1036
1037static void
1038mpc52xx_uart_stop_rx(struct uart_port *port)
1039{
1040 /* port->lock taken by caller */
John Rigby599f0302008-01-29 04:28:55 +11001041 psc_ops->stop_rx(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042}
1043
1044static void
1045mpc52xx_uart_enable_ms(struct uart_port *port)
1046{
Matteo Facchinetti2574b272013-05-24 20:24:58 +02001047 psc_ops->enable_ms(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048}
1049
1050static void
1051mpc52xx_uart_break_ctl(struct uart_port *port, int ctl)
1052{
1053 unsigned long flags;
1054 spin_lock_irqsave(&port->lock, flags);
1055
John Rigby406b7d42008-01-17 08:37:25 +11001056 if (ctl == -1)
Matteo Facchinetti2574b272013-05-24 20:24:58 +02001057 psc_ops->command(port, MPC52xx_PSC_START_BRK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 else
Matteo Facchinetti2574b272013-05-24 20:24:58 +02001059 psc_ops->command(port, MPC52xx_PSC_STOP_BRK);
Grant Likely9b9129e2006-11-27 14:21:01 -07001060
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 spin_unlock_irqrestore(&port->lock, flags);
1062}
1063
1064static int
1065mpc52xx_uart_startup(struct uart_port *port)
1066{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 int ret;
1068
Anatolij Gustschin6acc6832010-02-16 22:30:03 -07001069 if (psc_ops->clock) {
1070 ret = psc_ops->clock(port, 1);
1071 if (ret)
1072 return ret;
1073 }
1074
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 /* Request IRQ */
1076 ret = request_irq(port->irq, mpc52xx_uart_int,
Anatolij Gustschin6acc6832010-02-16 22:30:03 -07001077 port->irqflags, "mpc52xx_psc_uart", port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 if (ret)
1079 return ret;
1080
1081 /* Reset/activate the port, clear and enable interrupts */
Matteo Facchinetti2574b272013-05-24 20:24:58 +02001082 psc_ops->command(port, MPC52xx_PSC_RST_RX);
1083 psc_ops->command(port, MPC52xx_PSC_RST_TX);
Grant Likely9b9129e2006-11-27 14:21:01 -07001084
Matteo Facchinetti2574b272013-05-24 20:24:58 +02001085 psc_ops->set_sicr(port, 0); /* UART mode DCD ignored */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086
John Rigby599f0302008-01-29 04:28:55 +11001087 psc_ops->fifo_init(port);
Grant Likely9b9129e2006-11-27 14:21:01 -07001088
Matteo Facchinetti2574b272013-05-24 20:24:58 +02001089 psc_ops->command(port, MPC52xx_PSC_TX_ENABLE);
1090 psc_ops->command(port, MPC52xx_PSC_RX_ENABLE);
Grant Likely9b9129e2006-11-27 14:21:01 -07001091
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 return 0;
1093}
1094
1095static void
1096mpc52xx_uart_shutdown(struct uart_port *port)
1097{
Grant Likelya3481192007-05-07 01:38:51 +10001098 /* Shut down the port. Leave TX active if on a console port */
Matteo Facchinetti2574b272013-05-24 20:24:58 +02001099 psc_ops->command(port, MPC52xx_PSC_RST_RX);
Grant Likelya3481192007-05-07 01:38:51 +10001100 if (!uart_console(port))
Matteo Facchinetti2574b272013-05-24 20:24:58 +02001101 psc_ops->command(port, MPC52xx_PSC_RST_TX);
Grant Likely9b9129e2006-11-27 14:21:01 -07001102
1103 port->read_status_mask = 0;
Matteo Facchinetti2574b272013-05-24 20:24:58 +02001104 psc_ops->set_imr(port, port->read_status_mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105
Anatolij Gustschin6acc6832010-02-16 22:30:03 -07001106 if (psc_ops->clock)
1107 psc_ops->clock(port, 0);
1108
Matteo Facchinetti8a29dfb2013-06-12 09:21:42 +02001109 /* Disable interrupt */
1110 psc_ops->cw_disable_ints(port);
1111
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 /* Release interrupt */
1113 free_irq(port->irq, port);
1114}
1115
Grant Likely9b9129e2006-11-27 14:21:01 -07001116static void
Alan Cox606d0992006-12-08 02:38:45 -08001117mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new,
John Rigby406b7d42008-01-17 08:37:25 +11001118 struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 unsigned long flags;
1121 unsigned char mr1, mr2;
Albrecht Dreß0d1f22e2010-04-26 11:18:12 +00001122 unsigned int j;
1123 unsigned int baud;
Grant Likely9b9129e2006-11-27 14:21:01 -07001124
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 /* Prepare what we're gonna write */
1126 mr1 = 0;
Grant Likely9b9129e2006-11-27 14:21:01 -07001127
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 switch (new->c_cflag & CSIZE) {
John Rigby406b7d42008-01-17 08:37:25 +11001129 case CS5: mr1 |= MPC52xx_PSC_MODE_5_BITS;
1130 break;
1131 case CS6: mr1 |= MPC52xx_PSC_MODE_6_BITS;
1132 break;
1133 case CS7: mr1 |= MPC52xx_PSC_MODE_7_BITS;
1134 break;
1135 case CS8:
1136 default: mr1 |= MPC52xx_PSC_MODE_8_BITS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 }
1138
1139 if (new->c_cflag & PARENB) {
Wolfram Sangd3dec962012-08-27 16:03:14 +02001140 if (new->c_cflag & CMSPAR)
1141 mr1 |= MPC52xx_PSC_MODE_PARFORCE;
1142
1143 /* With CMSPAR, PARODD also means high parity (same as termios) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 mr1 |= (new->c_cflag & PARODD) ?
1145 MPC52xx_PSC_MODE_PARODD : MPC52xx_PSC_MODE_PAREVEN;
Wolfram Sangd3dec962012-08-27 16:03:14 +02001146 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 mr1 |= MPC52xx_PSC_MODE_PARNONE;
Wolfram Sangd3dec962012-08-27 16:03:14 +02001148 }
Grant Likely9b9129e2006-11-27 14:21:01 -07001149
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 mr2 = 0;
1151
1152 if (new->c_cflag & CSTOPB)
1153 mr2 |= MPC52xx_PSC_MODE_TWO_STOP;
1154 else
1155 mr2 |= ((new->c_cflag & CSIZE) == CS5) ?
1156 MPC52xx_PSC_MODE_ONE_STOP_5_BITS :
1157 MPC52xx_PSC_MODE_ONE_STOP;
1158
Wolfram Sangaec739e2008-12-21 02:54:32 -07001159 if (new->c_cflag & CRTSCTS) {
1160 mr1 |= MPC52xx_PSC_MODE_RXRTS;
1161 mr2 |= MPC52xx_PSC_MODE_TXCTS;
1162 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 /* Get the lock */
1165 spin_lock_irqsave(&port->lock, flags);
1166
Nick Andrewc4f01242008-12-05 16:34:46 +00001167 /* Do our best to flush TX & RX, so we don't lose anything */
1168 /* But we don't wait indefinitely ! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 j = 5000000; /* Maximum wait */
1170 /* FIXME Can't receive chars since set_termios might be called at early
1171 * boot for the console, all stuff is not yet ready to receive at that
1172 * time and that just makes the kernel oops */
1173 /* while (j-- && mpc52xx_uart_int_rx_chars(port)); */
John Rigby599f0302008-01-29 04:28:55 +11001174 while (!mpc52xx_uart_tx_empty(port) && --j)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 udelay(1);
1176
1177 if (!j)
John Rigby406b7d42008-01-17 08:37:25 +11001178 printk(KERN_ERR "mpc52xx_uart.c: "
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 "Unable to flush RX & TX fifos in-time in set_termios."
John Rigby406b7d42008-01-17 08:37:25 +11001180 "Some chars may have been lost.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181
1182 /* Reset the TX & RX */
Matteo Facchinetti2574b272013-05-24 20:24:58 +02001183 psc_ops->command(port, MPC52xx_PSC_RST_RX);
1184 psc_ops->command(port, MPC52xx_PSC_RST_TX);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185
1186 /* Send new mode settings */
Matteo Facchinetti2574b272013-05-24 20:24:58 +02001187 psc_ops->set_mode(port, mr1, mr2);
Albrecht Dreß0d1f22e2010-04-26 11:18:12 +00001188 baud = psc_ops->set_baudrate(port, new, old);
1189
1190 /* Update the per-port timeout */
1191 uart_update_timeout(port, new->c_cflag, baud);
Grant Likely9b9129e2006-11-27 14:21:01 -07001192
Wolfram Sangaec739e2008-12-21 02:54:32 -07001193 if (UART_ENABLE_MS(port, new->c_cflag))
1194 mpc52xx_uart_enable_ms(port);
1195
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 /* Reenable TX & RX */
Matteo Facchinetti2574b272013-05-24 20:24:58 +02001197 psc_ops->command(port, MPC52xx_PSC_TX_ENABLE);
1198 psc_ops->command(port, MPC52xx_PSC_RX_ENABLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199
1200 /* We're all set, release the lock */
1201 spin_unlock_irqrestore(&port->lock, flags);
1202}
1203
1204static const char *
1205mpc52xx_uart_type(struct uart_port *port)
1206{
Wolfram Sange44dcb62010-11-12 19:47:47 +01001207 /*
1208 * We keep using PORT_MPC52xx for historic reasons although it applies
1209 * for MPC512x, too, but print "MPC5xxx" to not irritate users
1210 */
1211 return port->type == PORT_MPC52xx ? "MPC5xxx PSC" : NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212}
1213
1214static void
1215mpc52xx_uart_release_port(struct uart_port *port)
1216{
Gerhard Sittig2d30cca2013-08-06 22:43:42 +02001217 if (psc_ops->clock_relse)
1218 psc_ops->clock_relse(port);
1219
John Rigby406b7d42008-01-17 08:37:25 +11001220 /* remapped by us ? */
1221 if (port->flags & UPF_IOREMAP) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 iounmap(port->membase);
1223 port->membase = NULL;
1224 }
1225
Grant Likelyb9272df2006-11-27 14:21:02 -07001226 release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227}
1228
1229static int
1230mpc52xx_uart_request_port(struct uart_port *port)
1231{
Amol Ladbe618f52006-09-30 23:29:23 -07001232 int err;
1233
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 if (port->flags & UPF_IOREMAP) /* Need to remap ? */
Grant Likelyb9272df2006-11-27 14:21:02 -07001235 port->membase = ioremap(port->mapbase,
John Rigby406b7d42008-01-17 08:37:25 +11001236 sizeof(struct mpc52xx_psc));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237
1238 if (!port->membase)
1239 return -EINVAL;
1240
Grant Likelyb9272df2006-11-27 14:21:02 -07001241 err = request_mem_region(port->mapbase, sizeof(struct mpc52xx_psc),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 "mpc52xx_psc_uart") != NULL ? 0 : -EBUSY;
Amol Ladbe618f52006-09-30 23:29:23 -07001243
Gerhard Sittig2d30cca2013-08-06 22:43:42 +02001244 if (err)
1245 goto out_membase;
1246
1247 if (psc_ops->clock_alloc) {
1248 err = psc_ops->clock_alloc(port);
1249 if (err)
1250 goto out_mapregion;
1251 }
1252
1253 return 0;
1254
1255out_mapregion:
1256 release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
1257out_membase:
1258 if (port->flags & UPF_IOREMAP) {
Amol Ladbe618f52006-09-30 23:29:23 -07001259 iounmap(port->membase);
1260 port->membase = NULL;
1261 }
Amol Ladbe618f52006-09-30 23:29:23 -07001262 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263}
1264
1265static void
1266mpc52xx_uart_config_port(struct uart_port *port, int flags)
1267{
John Rigby406b7d42008-01-17 08:37:25 +11001268 if ((flags & UART_CONFIG_TYPE)
1269 && (mpc52xx_uart_request_port(port) == 0))
1270 port->type = PORT_MPC52xx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271}
1272
1273static int
1274mpc52xx_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
1275{
John Rigby406b7d42008-01-17 08:37:25 +11001276 if (ser->type != PORT_UNKNOWN && ser->type != PORT_MPC52xx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 return -EINVAL;
1278
John Rigby406b7d42008-01-17 08:37:25 +11001279 if ((ser->irq != port->irq) ||
Julia Lawallb7a82122009-10-15 09:58:28 -06001280 (ser->io_type != UPIO_MEM) ||
John Rigby406b7d42008-01-17 08:37:25 +11001281 (ser->baud_base != port->uartclk) ||
1282 (ser->iomem_base != (void *)port->mapbase) ||
1283 (ser->hub6 != 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 return -EINVAL;
1285
1286 return 0;
1287}
1288
1289
1290static struct uart_ops mpc52xx_uart_ops = {
1291 .tx_empty = mpc52xx_uart_tx_empty,
1292 .set_mctrl = mpc52xx_uart_set_mctrl,
1293 .get_mctrl = mpc52xx_uart_get_mctrl,
1294 .stop_tx = mpc52xx_uart_stop_tx,
1295 .start_tx = mpc52xx_uart_start_tx,
1296 .send_xchar = mpc52xx_uart_send_xchar,
1297 .stop_rx = mpc52xx_uart_stop_rx,
1298 .enable_ms = mpc52xx_uart_enable_ms,
1299 .break_ctl = mpc52xx_uart_break_ctl,
1300 .startup = mpc52xx_uart_startup,
1301 .shutdown = mpc52xx_uart_shutdown,
1302 .set_termios = mpc52xx_uart_set_termios,
1303/* .pm = mpc52xx_uart_pm, Not supported yet */
1304/* .set_wake = mpc52xx_uart_set_wake, Not supported yet */
1305 .type = mpc52xx_uart_type,
1306 .release_port = mpc52xx_uart_release_port,
1307 .request_port = mpc52xx_uart_request_port,
1308 .config_port = mpc52xx_uart_config_port,
1309 .verify_port = mpc52xx_uart_verify_port
1310};
1311
Grant Likely9b9129e2006-11-27 14:21:01 -07001312
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313/* ======================================================================== */
1314/* Interrupt handling */
1315/* ======================================================================== */
Grant Likely9b9129e2006-11-27 14:21:01 -07001316
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317static inline int
David Howells7d12e782006-10-05 14:55:46 +01001318mpc52xx_uart_int_rx_chars(struct uart_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319{
Jiri Slaby92a19f92013-01-03 15:53:03 +01001320 struct tty_port *tport = &port->state->port;
Alan Cox33f0f882006-01-09 20:54:13 -08001321 unsigned char ch, flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 unsigned short status;
1323
1324 /* While we can read, do so ! */
John Rigby599f0302008-01-29 04:28:55 +11001325 while (psc_ops->raw_rx_rdy(port)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 /* Get the char */
John Rigby599f0302008-01-29 04:28:55 +11001327 ch = psc_ops->read_char(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328
1329 /* Handle sysreq char */
1330#ifdef SUPPORT_SYSRQ
David Howells7d12e782006-10-05 14:55:46 +01001331 if (uart_handle_sysrq_char(port, ch)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 port->sysrq = 0;
1333 continue;
1334 }
1335#endif
1336
1337 /* Store it */
Alan Cox33f0f882006-01-09 20:54:13 -08001338
1339 flag = TTY_NORMAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 port->icount.rx++;
Grant Likely9b9129e2006-11-27 14:21:01 -07001341
Matteo Facchinetti2574b272013-05-24 20:24:58 +02001342 status = psc_ops->get_status(port);
John Rigby599f0302008-01-29 04:28:55 +11001343
John Rigby406b7d42008-01-17 08:37:25 +11001344 if (status & (MPC52xx_PSC_SR_PE |
1345 MPC52xx_PSC_SR_FE |
1346 MPC52xx_PSC_SR_RB)) {
Grant Likely9b9129e2006-11-27 14:21:01 -07001347
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 if (status & MPC52xx_PSC_SR_RB) {
Alan Cox33f0f882006-01-09 20:54:13 -08001349 flag = TTY_BREAK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350 uart_handle_break(port);
René Bürgelb6514982008-12-21 02:54:31 -07001351 port->icount.brk++;
1352 } else if (status & MPC52xx_PSC_SR_PE) {
Alan Cox33f0f882006-01-09 20:54:13 -08001353 flag = TTY_PARITY;
René Bürgelb6514982008-12-21 02:54:31 -07001354 port->icount.parity++;
1355 }
1356 else if (status & MPC52xx_PSC_SR_FE) {
Alan Cox33f0f882006-01-09 20:54:13 -08001357 flag = TTY_FRAME;
René Bürgelb6514982008-12-21 02:54:31 -07001358 port->icount.frame++;
1359 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360
1361 /* Clear error condition */
Matteo Facchinetti2574b272013-05-24 20:24:58 +02001362 psc_ops->command(port, MPC52xx_PSC_RST_ERR_STAT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363
1364 }
Jiri Slaby92a19f92013-01-03 15:53:03 +01001365 tty_insert_flip_char(tport, ch, flag);
Alan Cox33f0f882006-01-09 20:54:13 -08001366 if (status & MPC52xx_PSC_SR_OE) {
1367 /*
1368 * Overrun is special, since it's
1369 * reported immediately, and doesn't
1370 * affect the current character
1371 */
Jiri Slaby92a19f92013-01-03 15:53:03 +01001372 tty_insert_flip_char(tport, 0, TTY_OVERRUN);
René Bürgelb6514982008-12-21 02:54:31 -07001373 port->icount.overrun++;
Alan Cox33f0f882006-01-09 20:54:13 -08001374 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 }
1376
Andrew Liufbe543b2008-04-29 17:36:25 +10001377 spin_unlock(&port->lock);
Jiri Slaby2e124b42013-01-03 15:53:06 +01001378 tty_flip_buffer_push(tport);
Andrew Liufbe543b2008-04-29 17:36:25 +10001379 spin_lock(&port->lock);
Grant Likely9b9129e2006-11-27 14:21:01 -07001380
John Rigby599f0302008-01-29 04:28:55 +11001381 return psc_ops->raw_rx_rdy(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382}
1383
1384static inline int
1385mpc52xx_uart_int_tx_chars(struct uart_port *port)
1386{
Alan Coxebd2c8f2009-09-19 13:13:28 -07001387 struct circ_buf *xmit = &port->state->xmit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388
1389 /* Process out of band chars */
1390 if (port->x_char) {
John Rigby599f0302008-01-29 04:28:55 +11001391 psc_ops->write_char(port, port->x_char);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 port->icount.tx++;
1393 port->x_char = 0;
1394 return 1;
1395 }
1396
1397 /* Nothing to do ? */
1398 if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
Russell Kingb129a8c2005-08-31 10:12:14 +01001399 mpc52xx_uart_stop_tx(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400 return 0;
1401 }
1402
1403 /* Send chars */
John Rigby599f0302008-01-29 04:28:55 +11001404 while (psc_ops->raw_tx_rdy(port)) {
1405 psc_ops->write_char(port, xmit->buf[xmit->tail]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
1407 port->icount.tx++;
1408 if (uart_circ_empty(xmit))
1409 break;
1410 }
1411
1412 /* Wake up */
1413 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
1414 uart_write_wakeup(port);
1415
1416 /* Maybe we're done after all */
1417 if (uart_circ_empty(xmit)) {
Russell Kingb129a8c2005-08-31 10:12:14 +01001418 mpc52xx_uart_stop_tx(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419 return 0;
1420 }
1421
1422 return 1;
1423}
1424
Grant Likely9b9129e2006-11-27 14:21:01 -07001425static irqreturn_t
Anatolij Gustschin6acc6832010-02-16 22:30:03 -07001426mpc5xxx_uart_process_int(struct uart_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 unsigned long pass = ISR_PASS_LIMIT;
1429 unsigned int keepgoing;
Wolfram Sangaec739e2008-12-21 02:54:32 -07001430 u8 status;
Grant Likely9b9129e2006-11-27 14:21:01 -07001431
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432 /* While we have stuff to do, we continue */
1433 do {
1434 /* If we don't find anything to do, we stop */
Grant Likely9b9129e2006-11-27 14:21:01 -07001435 keepgoing = 0;
1436
John Rigby599f0302008-01-29 04:28:55 +11001437 psc_ops->rx_clr_irq(port);
1438 if (psc_ops->rx_rdy(port))
David Howells7d12e782006-10-05 14:55:46 +01001439 keepgoing |= mpc52xx_uart_int_rx_chars(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440
John Rigby599f0302008-01-29 04:28:55 +11001441 psc_ops->tx_clr_irq(port);
1442 if (psc_ops->tx_rdy(port))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 keepgoing |= mpc52xx_uart_int_tx_chars(port);
Grant Likely9b9129e2006-11-27 14:21:01 -07001444
Matteo Facchinetti2574b272013-05-24 20:24:58 +02001445 status = psc_ops->get_ipcr(port);
Wolfram Sangaec739e2008-12-21 02:54:32 -07001446 if (status & MPC52xx_PSC_D_DCD)
1447 uart_handle_dcd_change(port, !(status & MPC52xx_PSC_DCD));
1448
1449 if (status & MPC52xx_PSC_D_CTS)
1450 uart_handle_cts_change(port, !(status & MPC52xx_PSC_CTS));
1451
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 /* Limit number of iteration */
John Rigby406b7d42008-01-17 08:37:25 +11001453 if (!(--pass))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 keepgoing = 0;
1455
1456 } while (keepgoing);
Grant Likely9b9129e2006-11-27 14:21:01 -07001457
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458 return IRQ_HANDLED;
1459}
1460
Anatolij Gustschin6acc6832010-02-16 22:30:03 -07001461static irqreturn_t
1462mpc52xx_uart_int(int irq, void *dev_id)
1463{
1464 struct uart_port *port = dev_id;
1465 irqreturn_t ret;
1466
1467 spin_lock(&port->lock);
1468
1469 ret = psc_ops->handle_irq(port);
1470
1471 spin_unlock(&port->lock);
1472
1473 return ret;
1474}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475
1476/* ======================================================================== */
1477/* Console ( if applicable ) */
1478/* ======================================================================== */
1479
1480#ifdef CONFIG_SERIAL_MPC52xx_CONSOLE
1481
1482static void __init
1483mpc52xx_console_get_options(struct uart_port *port,
John Rigby406b7d42008-01-17 08:37:25 +11001484 int *baud, int *parity, int *bits, int *flow)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486 unsigned char mr1;
1487
Grant Likelyb9272df2006-11-27 14:21:02 -07001488 pr_debug("mpc52xx_console_get_options(port=%p)\n", port);
1489
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 /* Read the mode registers */
Matteo Facchinetti2574b272013-05-24 20:24:58 +02001491 mr1 = psc_ops->get_mr1(port);
Grant Likely9b9129e2006-11-27 14:21:01 -07001492
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 /* CT{U,L}R are write-only ! */
Grant Likelyb9272df2006-11-27 14:21:02 -07001494 *baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495
1496 /* Parse them */
1497 switch (mr1 & MPC52xx_PSC_MODE_BITS_MASK) {
John Rigby406b7d42008-01-17 08:37:25 +11001498 case MPC52xx_PSC_MODE_5_BITS:
1499 *bits = 5;
1500 break;
1501 case MPC52xx_PSC_MODE_6_BITS:
1502 *bits = 6;
1503 break;
1504 case MPC52xx_PSC_MODE_7_BITS:
1505 *bits = 7;
1506 break;
1507 case MPC52xx_PSC_MODE_8_BITS:
1508 default:
1509 *bits = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 }
Grant Likely9b9129e2006-11-27 14:21:01 -07001511
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512 if (mr1 & MPC52xx_PSC_MODE_PARNONE)
1513 *parity = 'n';
1514 else
1515 *parity = mr1 & MPC52xx_PSC_MODE_PARODD ? 'o' : 'e';
1516}
1517
Grant Likely9b9129e2006-11-27 14:21:01 -07001518static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519mpc52xx_console_write(struct console *co, const char *s, unsigned int count)
1520{
1521 struct uart_port *port = &mpc52xx_uart_ports[co->index];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 unsigned int i, j;
Grant Likely9b9129e2006-11-27 14:21:01 -07001523
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 /* Disable interrupts */
John Rigby599f0302008-01-29 04:28:55 +11001525 psc_ops->cw_disable_ints(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526
1527 /* Wait the TX buffer to be empty */
Grant Likely9b9129e2006-11-27 14:21:01 -07001528 j = 5000000; /* Maximum wait */
John Rigby599f0302008-01-29 04:28:55 +11001529 while (!mpc52xx_uart_tx_empty(port) && --j)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 udelay(1);
1531
1532 /* Write all the chars */
Russell Kingd3587882006-03-20 20:00:09 +00001533 for (i = 0; i < count; i++, s++) {
1534 /* Line return handling */
1535 if (*s == '\n')
John Rigby599f0302008-01-29 04:28:55 +11001536 psc_ops->write_char(port, '\r');
Grant Likely9b9129e2006-11-27 14:21:01 -07001537
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538 /* Send the char */
John Rigby599f0302008-01-29 04:28:55 +11001539 psc_ops->write_char(port, *s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 /* Wait the TX buffer to be empty */
Grant Likely9b9129e2006-11-27 14:21:01 -07001542 j = 20000; /* Maximum wait */
John Rigby599f0302008-01-29 04:28:55 +11001543 while (!mpc52xx_uart_tx_empty(port) && --j)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544 udelay(1);
1545 }
1546
1547 /* Restore interrupt state */
John Rigby599f0302008-01-29 04:28:55 +11001548 psc_ops->cw_restore_ints(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549}
1550
Grant Likelyb9272df2006-11-27 14:21:02 -07001551
1552static int __init
1553mpc52xx_console_setup(struct console *co, char *options)
1554{
1555 struct uart_port *port = &mpc52xx_uart_ports[co->index];
1556 struct device_node *np = mpc52xx_uart_nodes[co->index];
John Rigby599f0302008-01-29 04:28:55 +11001557 unsigned int uartclk;
Grant Likelyb9272df2006-11-27 14:21:02 -07001558 struct resource res;
1559 int ret;
1560
1561 int baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;
1562 int bits = 8;
1563 int parity = 'n';
1564 int flow = 'n';
1565
1566 pr_debug("mpc52xx_console_setup co=%p, co->index=%i, options=%s\n",
1567 co, co->index, options);
1568
Roel Kluinb898f4f2009-05-28 14:34:29 -07001569 if ((co->index < 0) || (co->index >= MPC52xx_PSC_MAXNUM)) {
Grant Likelyb9272df2006-11-27 14:21:02 -07001570 pr_debug("PSC%x out of range\n", co->index);
1571 return -EINVAL;
1572 }
1573
1574 if (!np) {
1575 pr_debug("PSC%x not found in device tree\n", co->index);
1576 return -EINVAL;
1577 }
1578
1579 pr_debug("Console on ttyPSC%x is %s\n",
John Rigby406b7d42008-01-17 08:37:25 +11001580 co->index, mpc52xx_uart_nodes[co->index]->full_name);
Grant Likelyb9272df2006-11-27 14:21:02 -07001581
1582 /* Fetch register locations */
John Rigby406b7d42008-01-17 08:37:25 +11001583 ret = of_address_to_resource(np, 0, &res);
1584 if (ret) {
Grant Likelyb9272df2006-11-27 14:21:02 -07001585 pr_debug("Could not get resources for PSC%x\n", co->index);
1586 return ret;
1587 }
1588
Albrecht Dreß0d1f22e2010-04-26 11:18:12 +00001589 uartclk = mpc5xxx_get_bus_frequency(np);
John Rigby599f0302008-01-29 04:28:55 +11001590 if (uartclk == 0) {
1591 pr_debug("Could not find uart clock frequency!\n");
Grant Likelyb9272df2006-11-27 14:21:02 -07001592 return -EINVAL;
1593 }
1594
1595 /* Basic port init. Needed since we use some uart_??? func before
1596 * real init for early access */
1597 spin_lock_init(&port->lock);
John Rigby599f0302008-01-29 04:28:55 +11001598 port->uartclk = uartclk;
Grant Likelyb9272df2006-11-27 14:21:02 -07001599 port->ops = &mpc52xx_uart_ops;
1600 port->mapbase = res.start;
1601 port->membase = ioremap(res.start, sizeof(struct mpc52xx_psc));
1602 port->irq = irq_of_parse_and_map(np, 0);
1603
1604 if (port->membase == NULL)
1605 return -EINVAL;
1606
Grant Likely5dd80d52007-10-13 22:37:02 -06001607 pr_debug("mpc52xx-psc uart at %p, mapped to %p, irq=%x, freq=%i\n",
John Rigby406b7d42008-01-17 08:37:25 +11001608 (void *)port->mapbase, port->membase,
1609 port->irq, port->uartclk);
Grant Likelyb9272df2006-11-27 14:21:02 -07001610
1611 /* Setup the port parameters accoding to options */
1612 if (options)
1613 uart_parse_options(options, &baud, &parity, &bits, &flow);
1614 else
1615 mpc52xx_console_get_options(port, &baud, &parity, &bits, &flow);
1616
1617 pr_debug("Setting console parameters: %i %i%c1 flow=%c\n",
John Rigby406b7d42008-01-17 08:37:25 +11001618 baud, bits, parity, flow);
Grant Likelyb9272df2006-11-27 14:21:02 -07001619
1620 return uart_set_options(port, co, baud, parity, bits, flow);
1621}
Grant Likelyb9272df2006-11-27 14:21:02 -07001622
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623
Sylvain Munaut2d8179c2006-01-06 00:11:31 -08001624static struct uart_driver mpc52xx_uart_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625
1626static struct console mpc52xx_console = {
Sylvain Munautd62de3a2006-01-06 00:11:32 -08001627 .name = "ttyPSC",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628 .write = mpc52xx_console_write,
1629 .device = uart_console_device,
1630 .setup = mpc52xx_console_setup,
1631 .flags = CON_PRINTBUFFER,
John Rigby406b7d42008-01-17 08:37:25 +11001632 .index = -1, /* Specified on the cmdline (e.g. console=ttyPSC0) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633 .data = &mpc52xx_uart_driver,
1634};
1635
Grant Likely9b9129e2006-11-27 14:21:01 -07001636
1637static int __init
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638mpc52xx_console_init(void)
1639{
Grant Likelyb9272df2006-11-27 14:21:02 -07001640 mpc52xx_uart_of_enumerate();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641 register_console(&mpc52xx_console);
1642 return 0;
1643}
1644
1645console_initcall(mpc52xx_console_init);
1646
1647#define MPC52xx_PSC_CONSOLE &mpc52xx_console
1648#else
1649#define MPC52xx_PSC_CONSOLE NULL
1650#endif
1651
1652
1653/* ======================================================================== */
1654/* UART Driver */
1655/* ======================================================================== */
1656
1657static struct uart_driver mpc52xx_uart_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658 .driver_name = "mpc52xx_psc_uart",
Sylvain Munautd62de3a2006-01-06 00:11:32 -08001659 .dev_name = "ttyPSC",
Sylvain Munautd62de3a2006-01-06 00:11:32 -08001660 .major = SERIAL_PSC_MAJOR,
1661 .minor = SERIAL_PSC_MINOR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 .nr = MPC52xx_PSC_MAXNUM,
1663 .cons = MPC52xx_PSC_CONSOLE,
1664};
1665
Grant Likelyb9272df2006-11-27 14:21:02 -07001666/* ======================================================================== */
1667/* OF Platform Driver */
1668/* ======================================================================== */
1669
Grant Likely52b80482008-02-06 22:29:25 -07001670static struct of_device_id mpc52xx_uart_of_match[] = {
1671#ifdef CONFIG_PPC_MPC52xx
Albrecht Dreß0d1f22e2010-04-26 11:18:12 +00001672 { .compatible = "fsl,mpc5200b-psc-uart", .data = &mpc5200b_psc_ops, },
Grant Likely52b80482008-02-06 22:29:25 -07001673 { .compatible = "fsl,mpc5200-psc-uart", .data = &mpc52xx_psc_ops, },
1674 /* binding used by old lite5200 device trees: */
1675 { .compatible = "mpc5200-psc-uart", .data = &mpc52xx_psc_ops, },
1676 /* binding used by efika: */
1677 { .compatible = "mpc5200-serial", .data = &mpc52xx_psc_ops, },
1678#endif
1679#ifdef CONFIG_PPC_MPC512x
1680 { .compatible = "fsl,mpc5121-psc-uart", .data = &mpc512x_psc_ops, },
Matteo Facchinetti1f48c492013-05-24 20:24:59 +02001681 { .compatible = "fsl,mpc5125-psc-uart", .data = &mpc5125_psc_ops, },
Grant Likely52b80482008-02-06 22:29:25 -07001682#endif
Grant Likelybc775ea2008-04-29 06:40:37 -06001683 {},
Grant Likely52b80482008-02-06 22:29:25 -07001684};
1685
Bill Pemberton9671f092012-11-19 13:21:50 -05001686static int mpc52xx_uart_of_probe(struct platform_device *op)
Grant Likelyb9272df2006-11-27 14:21:02 -07001687{
1688 int idx = -1;
John Rigby599f0302008-01-29 04:28:55 +11001689 unsigned int uartclk;
Grant Likelyb9272df2006-11-27 14:21:02 -07001690 struct uart_port *port = NULL;
1691 struct resource res;
1692 int ret;
1693
Grant Likelyb9272df2006-11-27 14:21:02 -07001694 /* Check validity & presence */
1695 for (idx = 0; idx < MPC52xx_PSC_MAXNUM; idx++)
Grant Likely61c7a082010-04-13 16:12:29 -07001696 if (mpc52xx_uart_nodes[idx] == op->dev.of_node)
Grant Likelyb9272df2006-11-27 14:21:02 -07001697 break;
1698 if (idx >= MPC52xx_PSC_MAXNUM)
1699 return -EINVAL;
1700 pr_debug("Found %s assigned to ttyPSC%x\n",
John Rigby406b7d42008-01-17 08:37:25 +11001701 mpc52xx_uart_nodes[idx]->full_name, idx);
Grant Likelyb9272df2006-11-27 14:21:02 -07001702
Albrecht Dreß0d1f22e2010-04-26 11:18:12 +00001703 /* set the uart clock to the input clock of the psc, the different
1704 * prescalers are taken into account in the set_baudrate() methods
1705 * of the respective chip */
1706 uartclk = mpc5xxx_get_bus_frequency(op->dev.of_node);
John Rigby599f0302008-01-29 04:28:55 +11001707 if (uartclk == 0) {
1708 dev_dbg(&op->dev, "Could not find uart clock frequency!\n");
Grant Likelyb9272df2006-11-27 14:21:02 -07001709 return -EINVAL;
1710 }
1711
1712 /* Init the port structure */
1713 port = &mpc52xx_uart_ports[idx];
1714
1715 spin_lock_init(&port->lock);
John Rigby599f0302008-01-29 04:28:55 +11001716 port->uartclk = uartclk;
Grant Likelyb9272df2006-11-27 14:21:02 -07001717 port->fifosize = 512;
1718 port->iotype = UPIO_MEM;
1719 port->flags = UPF_BOOT_AUTOCONF |
John Rigby406b7d42008-01-17 08:37:25 +11001720 (uart_console(port) ? 0 : UPF_IOREMAP);
Grant Likelyb9272df2006-11-27 14:21:02 -07001721 port->line = idx;
1722 port->ops = &mpc52xx_uart_ops;
1723 port->dev = &op->dev;
1724
1725 /* Search for IRQ and mapbase */
Grant Likely61c7a082010-04-13 16:12:29 -07001726 ret = of_address_to_resource(op->dev.of_node, 0, &res);
John Rigby406b7d42008-01-17 08:37:25 +11001727 if (ret)
Grant Likelyb9272df2006-11-27 14:21:02 -07001728 return ret;
1729
1730 port->mapbase = res.start;
Wolfram Sang418441d92008-12-21 02:54:32 -07001731 if (!port->mapbase) {
1732 dev_dbg(&op->dev, "Could not allocate resources for PSC\n");
1733 return -EINVAL;
1734 }
1735
Grant Likely61c7a082010-04-13 16:12:29 -07001736 psc_ops->get_irq(port, op->dev.of_node);
Alan Coxd4e33fa2012-01-26 17:44:09 +00001737 if (port->irq == 0) {
Wolfram Sang418441d92008-12-21 02:54:32 -07001738 dev_dbg(&op->dev, "Could not get irq\n");
1739 return -EINVAL;
1740 }
Grant Likelyb9272df2006-11-27 14:21:02 -07001741
Grant Likely5dd80d52007-10-13 22:37:02 -06001742 dev_dbg(&op->dev, "mpc52xx-psc uart at %p, irq=%x, freq=%i\n",
John Rigby406b7d42008-01-17 08:37:25 +11001743 (void *)port->mapbase, port->irq, port->uartclk);
Grant Likelyb9272df2006-11-27 14:21:02 -07001744
Grant Likelyb9272df2006-11-27 14:21:02 -07001745 /* Add the port to the uart sub-system */
1746 ret = uart_add_one_port(&mpc52xx_uart_driver, port);
Anatolij Gustschin6acc6832010-02-16 22:30:03 -07001747 if (ret)
Wolfram Sang418441d92008-12-21 02:54:32 -07001748 return ret;
Grant Likelyb9272df2006-11-27 14:21:02 -07001749
Jingoo Han696faed2013-05-23 19:39:36 +09001750 platform_set_drvdata(op, (void *)port);
Wolfram Sang418441d92008-12-21 02:54:32 -07001751 return 0;
Grant Likelyb9272df2006-11-27 14:21:02 -07001752}
1753
1754static int
Grant Likely2dc11582010-08-06 09:25:50 -06001755mpc52xx_uart_of_remove(struct platform_device *op)
Grant Likelyb9272df2006-11-27 14:21:02 -07001756{
Jingoo Han696faed2013-05-23 19:39:36 +09001757 struct uart_port *port = platform_get_drvdata(op);
Grant Likelyb9272df2006-11-27 14:21:02 -07001758
Anatolij Gustschin6acc6832010-02-16 22:30:03 -07001759 if (port)
Grant Likelyb9272df2006-11-27 14:21:02 -07001760 uart_remove_one_port(&mpc52xx_uart_driver, port);
1761
1762 return 0;
1763}
1764
1765#ifdef CONFIG_PM
1766static int
Grant Likely2dc11582010-08-06 09:25:50 -06001767mpc52xx_uart_of_suspend(struct platform_device *op, pm_message_t state)
Grant Likelyb9272df2006-11-27 14:21:02 -07001768{
Jingoo Han696faed2013-05-23 19:39:36 +09001769 struct uart_port *port = (struct uart_port *) platform_get_drvdata(op);
Grant Likelyb9272df2006-11-27 14:21:02 -07001770
1771 if (port)
1772 uart_suspend_port(&mpc52xx_uart_driver, port);
1773
1774 return 0;
1775}
1776
1777static int
Grant Likely2dc11582010-08-06 09:25:50 -06001778mpc52xx_uart_of_resume(struct platform_device *op)
Grant Likelyb9272df2006-11-27 14:21:02 -07001779{
Jingoo Han696faed2013-05-23 19:39:36 +09001780 struct uart_port *port = (struct uart_port *) platform_get_drvdata(op);
Grant Likelyb9272df2006-11-27 14:21:02 -07001781
1782 if (port)
1783 uart_resume_port(&mpc52xx_uart_driver, port);
1784
1785 return 0;
1786}
1787#endif
1788
1789static void
Grant Likely3b5ebf82009-02-03 12:30:25 -07001790mpc52xx_uart_of_assign(struct device_node *np)
Grant Likelyb9272df2006-11-27 14:21:02 -07001791{
Grant Likelyb9272df2006-11-27 14:21:02 -07001792 int i;
1793
Grant Likely3b5ebf82009-02-03 12:30:25 -07001794 /* Find the first free PSC number */
Grant Likelyb9272df2006-11-27 14:21:02 -07001795 for (i = 0; i < MPC52xx_PSC_MAXNUM; i++) {
1796 if (mpc52xx_uart_nodes[i] == NULL) {
Grant Likely3b5ebf82009-02-03 12:30:25 -07001797 of_node_get(np);
1798 mpc52xx_uart_nodes[i] = np;
1799 return;
Grant Likelyb9272df2006-11-27 14:21:02 -07001800 }
1801 }
Grant Likelyb9272df2006-11-27 14:21:02 -07001802}
1803
1804static void
1805mpc52xx_uart_of_enumerate(void)
1806{
John Rigby406b7d42008-01-17 08:37:25 +11001807 static int enum_done;
Grant Likelyb9272df2006-11-27 14:21:02 -07001808 struct device_node *np;
John Rigby25ae3a02008-01-29 04:28:56 +11001809 const struct of_device_id *match;
Grant Likelyb9272df2006-11-27 14:21:02 -07001810 int i;
1811
1812 if (enum_done)
1813 return;
1814
Grant Likely3b5ebf82009-02-03 12:30:25 -07001815 /* Assign index to each PSC in device tree */
1816 for_each_matching_node(np, mpc52xx_uart_of_match) {
John Rigby25ae3a02008-01-29 04:28:56 +11001817 match = of_match_node(mpc52xx_uart_of_match, np);
John Rigby25ae3a02008-01-29 04:28:56 +11001818 psc_ops = match->data;
Grant Likely3b5ebf82009-02-03 12:30:25 -07001819 mpc52xx_uart_of_assign(np);
Grant Likelyb9272df2006-11-27 14:21:02 -07001820 }
1821
1822 enum_done = 1;
1823
1824 for (i = 0; i < MPC52xx_PSC_MAXNUM; i++) {
1825 if (mpc52xx_uart_nodes[i])
1826 pr_debug("%s assigned to ttyPSC%x\n",
John Rigby406b7d42008-01-17 08:37:25 +11001827 mpc52xx_uart_nodes[i]->full_name, i);
Grant Likelyb9272df2006-11-27 14:21:02 -07001828 }
1829}
1830
1831MODULE_DEVICE_TABLE(of, mpc52xx_uart_of_match);
1832
Grant Likely793218d2011-02-22 21:10:26 -07001833static struct platform_driver mpc52xx_uart_of_driver = {
Grant Likelyb9272df2006-11-27 14:21:02 -07001834 .probe = mpc52xx_uart_of_probe,
1835 .remove = mpc52xx_uart_of_remove,
1836#ifdef CONFIG_PM
1837 .suspend = mpc52xx_uart_of_suspend,
1838 .resume = mpc52xx_uart_of_resume,
1839#endif
Grant Likely40182942010-04-13 16:13:02 -07001840 .driver = {
1841 .name = "mpc52xx-psc-uart",
1842 .owner = THIS_MODULE,
1843 .of_match_table = mpc52xx_uart_of_match,
Grant Likelyb9272df2006-11-27 14:21:02 -07001844 },
1845};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846
1847
1848/* ======================================================================== */
1849/* Module */
1850/* ======================================================================== */
1851
1852static int __init
1853mpc52xx_uart_init(void)
1854{
1855 int ret;
1856
Grant Likelyb9272df2006-11-27 14:21:02 -07001857 printk(KERN_INFO "Serial: MPC52xx PSC UART driver\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858
John Rigby406b7d42008-01-17 08:37:25 +11001859 ret = uart_register_driver(&mpc52xx_uart_driver);
1860 if (ret) {
Grant Likelyb9272df2006-11-27 14:21:02 -07001861 printk(KERN_ERR "%s: uart_register_driver failed (%i)\n",
1862 __FILE__, ret);
1863 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 }
1865
Grant Likelyb9272df2006-11-27 14:21:02 -07001866 mpc52xx_uart_of_enumerate();
1867
Anatolij Gustschin6acc6832010-02-16 22:30:03 -07001868 /*
1869 * Map the PSC FIFO Controller and init if on MPC512x.
1870 */
Anatolij Gustschine6114fa2010-05-05 00:18:59 +02001871 if (psc_ops && psc_ops->fifoc_init) {
Anatolij Gustschin6acc6832010-02-16 22:30:03 -07001872 ret = psc_ops->fifoc_init();
1873 if (ret)
Wei Yongjun9bcc3272013-04-25 15:34:27 +08001874 goto err_init;
Anatolij Gustschin6acc6832010-02-16 22:30:03 -07001875 }
1876
Grant Likely793218d2011-02-22 21:10:26 -07001877 ret = platform_driver_register(&mpc52xx_uart_of_driver);
Grant Likelyb9272df2006-11-27 14:21:02 -07001878 if (ret) {
Grant Likely793218d2011-02-22 21:10:26 -07001879 printk(KERN_ERR "%s: platform_driver_register failed (%i)\n",
Grant Likelyb9272df2006-11-27 14:21:02 -07001880 __FILE__, ret);
Wei Yongjun9bcc3272013-04-25 15:34:27 +08001881 goto err_reg;
Grant Likelyb9272df2006-11-27 14:21:02 -07001882 }
Grant Likelyb9272df2006-11-27 14:21:02 -07001883
1884 return 0;
Wei Yongjun9bcc3272013-04-25 15:34:27 +08001885err_reg:
1886 if (psc_ops && psc_ops->fifoc_uninit)
1887 psc_ops->fifoc_uninit();
1888err_init:
1889 uart_unregister_driver(&mpc52xx_uart_driver);
1890 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891}
1892
1893static void __exit
1894mpc52xx_uart_exit(void)
1895{
Anatolij Gustschin6acc6832010-02-16 22:30:03 -07001896 if (psc_ops->fifoc_uninit)
1897 psc_ops->fifoc_uninit();
1898
Grant Likely793218d2011-02-22 21:10:26 -07001899 platform_driver_unregister(&mpc52xx_uart_of_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 uart_unregister_driver(&mpc52xx_uart_driver);
1901}
1902
1903
1904module_init(mpc52xx_uart_init);
1905module_exit(mpc52xx_uart_exit);
1906
1907MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");
1908MODULE_DESCRIPTION("Freescale MPC52xx PSC UART");
1909MODULE_LICENSE("GPL");