diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2011-01-13 15:10:18 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-01-13 15:10:18 -0500 |
commit | ab4382d27412e7e3e7c936e8d50d8888dfac3df8 (patch) | |
tree | 51d96dea2431140358784b6b426715f37f74fd53 /drivers/tty/serial/mpc52xx_uart.c | |
parent | 728674a7e466628df2aeec6d11a2ae1ef968fb67 (diff) |
tty: move drivers/serial/ to drivers/tty/serial/
The serial drivers are really just tty drivers, so move them to
drivers/tty/ to make things a bit neater overall.
This is part of the tty/serial driver movement proceedure as proposed by
Arnd Bergmann and approved by everyone involved a number of months ago.
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Rogier Wolff <R.E.Wolff@bitwizard.nl>
Cc: Michael H. Warfield <mhw@wittsend.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/tty/serial/mpc52xx_uart.c')
-rw-r--r-- | drivers/tty/serial/mpc52xx_uart.c | 1527 |
1 files changed, 1527 insertions, 0 deletions
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c new file mode 100644 index 000000000000..126ec7f568ec --- /dev/null +++ b/drivers/tty/serial/mpc52xx_uart.c | |||
@@ -0,0 +1,1527 @@ | |||
1 | /* | ||
2 | * 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> | ||
15 | * | ||
16 | * Some of the code has been inspired/copied from the 2.4 code written | ||
17 | * by Dale Farnsworth <dfarnsworth@mvista.com>. | ||
18 | * | ||
19 | * Copyright (C) 2008 Freescale Semiconductor Inc. | ||
20 | * John Rigby <jrigby@gmail.com> | ||
21 | * Added support for MPC5121 | ||
22 | * Copyright (C) 2006 Secret Lab Technologies Ltd. | ||
23 | * Grant Likely <grant.likely@secretlab.ca> | ||
24 | * Copyright (C) 2004-2006 Sylvain Munaut <tnt@246tNt.com> | ||
25 | * Copyright (C) 2003 MontaVista, Software, Inc. | ||
26 | * | ||
27 | * 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 | */ | ||
31 | |||
32 | #undef DEBUG | ||
33 | |||
34 | #include <linux/device.h> | ||
35 | #include <linux/module.h> | ||
36 | #include <linux/tty.h> | ||
37 | #include <linux/serial.h> | ||
38 | #include <linux/sysrq.h> | ||
39 | #include <linux/console.h> | ||
40 | #include <linux/delay.h> | ||
41 | #include <linux/io.h> | ||
42 | #include <linux/of.h> | ||
43 | #include <linux/of_platform.h> | ||
44 | #include <linux/clk.h> | ||
45 | |||
46 | #include <asm/mpc52xx.h> | ||
47 | #include <asm/mpc52xx_psc.h> | ||
48 | |||
49 | #if defined(CONFIG_SERIAL_MPC52xx_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) | ||
50 | #define SUPPORT_SYSRQ | ||
51 | #endif | ||
52 | |||
53 | #include <linux/serial_core.h> | ||
54 | |||
55 | |||
56 | /* We've been assigned a range on the "Low-density serial ports" major */ | ||
57 | #define SERIAL_PSC_MAJOR 204 | ||
58 | #define SERIAL_PSC_MINOR 148 | ||
59 | |||
60 | |||
61 | #define ISR_PASS_LIMIT 256 /* Max number of iteration in the interrupt */ | ||
62 | |||
63 | |||
64 | static struct uart_port mpc52xx_uart_ports[MPC52xx_PSC_MAXNUM]; | ||
65 | /* Rem: - We use the read_status_mask as a shadow of | ||
66 | * psc->mpc52xx_psc_imr | ||
67 | * - It's important that is array is all zero on start as we | ||
68 | * use it to know if it's initialized or not ! If it's not sure | ||
69 | * it's cleared, then a memset(...,0,...) should be added to | ||
70 | * the console_init | ||
71 | */ | ||
72 | |||
73 | /* lookup table for matching device nodes to index numbers */ | ||
74 | static struct device_node *mpc52xx_uart_nodes[MPC52xx_PSC_MAXNUM]; | ||
75 | |||
76 | static void mpc52xx_uart_of_enumerate(void); | ||
77 | |||
78 | |||
79 | #define PSC(port) ((struct mpc52xx_psc __iomem *)((port)->membase)) | ||
80 | |||
81 | |||
82 | /* Forward declaration of the interruption handling routine */ | ||
83 | static irqreturn_t mpc52xx_uart_int(int irq, void *dev_id); | ||
84 | static irqreturn_t mpc5xxx_uart_process_int(struct uart_port *port); | ||
85 | |||
86 | |||
87 | /* Simple macro to test if a port is console or not. This one is taken | ||
88 | * for serial_core.c and maybe should be moved to serial_core.h ? */ | ||
89 | #ifdef CONFIG_SERIAL_CORE_CONSOLE | ||
90 | #define uart_console(port) \ | ||
91 | ((port)->cons && (port)->cons->index == (port)->line) | ||
92 | #else | ||
93 | #define uart_console(port) (0) | ||
94 | #endif | ||
95 | |||
96 | /* ======================================================================== */ | ||
97 | /* PSC fifo operations for isolating differences between 52xx and 512x */ | ||
98 | /* ======================================================================== */ | ||
99 | |||
100 | struct psc_ops { | ||
101 | void (*fifo_init)(struct uart_port *port); | ||
102 | int (*raw_rx_rdy)(struct uart_port *port); | ||
103 | int (*raw_tx_rdy)(struct uart_port *port); | ||
104 | int (*rx_rdy)(struct uart_port *port); | ||
105 | int (*tx_rdy)(struct uart_port *port); | ||
106 | int (*tx_empty)(struct uart_port *port); | ||
107 | void (*stop_rx)(struct uart_port *port); | ||
108 | void (*start_tx)(struct uart_port *port); | ||
109 | void (*stop_tx)(struct uart_port *port); | ||
110 | void (*rx_clr_irq)(struct uart_port *port); | ||
111 | void (*tx_clr_irq)(struct uart_port *port); | ||
112 | void (*write_char)(struct uart_port *port, unsigned char c); | ||
113 | unsigned char (*read_char)(struct uart_port *port); | ||
114 | void (*cw_disable_ints)(struct uart_port *port); | ||
115 | void (*cw_restore_ints)(struct uart_port *port); | ||
116 | unsigned int (*set_baudrate)(struct uart_port *port, | ||
117 | struct ktermios *new, | ||
118 | struct ktermios *old); | ||
119 | int (*clock)(struct uart_port *port, int enable); | ||
120 | int (*fifoc_init)(void); | ||
121 | void (*fifoc_uninit)(void); | ||
122 | void (*get_irq)(struct uart_port *, struct device_node *); | ||
123 | irqreturn_t (*handle_irq)(struct uart_port *port); | ||
124 | }; | ||
125 | |||
126 | /* setting the prescaler and divisor reg is common for all chips */ | ||
127 | static inline void mpc52xx_set_divisor(struct mpc52xx_psc __iomem *psc, | ||
128 | u16 prescaler, unsigned int divisor) | ||
129 | { | ||
130 | /* select prescaler */ | ||
131 | out_be16(&psc->mpc52xx_psc_clock_select, prescaler); | ||
132 | out_8(&psc->ctur, divisor >> 8); | ||
133 | out_8(&psc->ctlr, divisor & 0xff); | ||
134 | } | ||
135 | |||
136 | #ifdef CONFIG_PPC_MPC52xx | ||
137 | #define FIFO_52xx(port) ((struct mpc52xx_psc_fifo __iomem *)(PSC(port)+1)) | ||
138 | static void mpc52xx_psc_fifo_init(struct uart_port *port) | ||
139 | { | ||
140 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
141 | struct mpc52xx_psc_fifo __iomem *fifo = FIFO_52xx(port); | ||
142 | |||
143 | out_8(&fifo->rfcntl, 0x00); | ||
144 | out_be16(&fifo->rfalarm, 0x1ff); | ||
145 | out_8(&fifo->tfcntl, 0x07); | ||
146 | out_be16(&fifo->tfalarm, 0x80); | ||
147 | |||
148 | port->read_status_mask |= MPC52xx_PSC_IMR_RXRDY | MPC52xx_PSC_IMR_TXRDY; | ||
149 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | ||
150 | } | ||
151 | |||
152 | static int mpc52xx_psc_raw_rx_rdy(struct uart_port *port) | ||
153 | { | ||
154 | return in_be16(&PSC(port)->mpc52xx_psc_status) | ||
155 | & MPC52xx_PSC_SR_RXRDY; | ||
156 | } | ||
157 | |||
158 | static int mpc52xx_psc_raw_tx_rdy(struct uart_port *port) | ||
159 | { | ||
160 | return in_be16(&PSC(port)->mpc52xx_psc_status) | ||
161 | & MPC52xx_PSC_SR_TXRDY; | ||
162 | } | ||
163 | |||
164 | |||
165 | static int mpc52xx_psc_rx_rdy(struct uart_port *port) | ||
166 | { | ||
167 | return in_be16(&PSC(port)->mpc52xx_psc_isr) | ||
168 | & port->read_status_mask | ||
169 | & MPC52xx_PSC_IMR_RXRDY; | ||
170 | } | ||
171 | |||
172 | static int mpc52xx_psc_tx_rdy(struct uart_port *port) | ||
173 | { | ||
174 | return in_be16(&PSC(port)->mpc52xx_psc_isr) | ||
175 | & port->read_status_mask | ||
176 | & MPC52xx_PSC_IMR_TXRDY; | ||
177 | } | ||
178 | |||
179 | static int mpc52xx_psc_tx_empty(struct uart_port *port) | ||
180 | { | ||
181 | return in_be16(&PSC(port)->mpc52xx_psc_status) | ||
182 | & MPC52xx_PSC_SR_TXEMP; | ||
183 | } | ||
184 | |||
185 | static void mpc52xx_psc_start_tx(struct uart_port *port) | ||
186 | { | ||
187 | port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY; | ||
188 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
189 | } | ||
190 | |||
191 | static void mpc52xx_psc_stop_tx(struct uart_port *port) | ||
192 | { | ||
193 | port->read_status_mask &= ~MPC52xx_PSC_IMR_TXRDY; | ||
194 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
195 | } | ||
196 | |||
197 | static void mpc52xx_psc_stop_rx(struct uart_port *port) | ||
198 | { | ||
199 | port->read_status_mask &= ~MPC52xx_PSC_IMR_RXRDY; | ||
200 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
201 | } | ||
202 | |||
203 | static void mpc52xx_psc_rx_clr_irq(struct uart_port *port) | ||
204 | { | ||
205 | } | ||
206 | |||
207 | static void mpc52xx_psc_tx_clr_irq(struct uart_port *port) | ||
208 | { | ||
209 | } | ||
210 | |||
211 | static void mpc52xx_psc_write_char(struct uart_port *port, unsigned char c) | ||
212 | { | ||
213 | out_8(&PSC(port)->mpc52xx_psc_buffer_8, c); | ||
214 | } | ||
215 | |||
216 | static unsigned char mpc52xx_psc_read_char(struct uart_port *port) | ||
217 | { | ||
218 | return in_8(&PSC(port)->mpc52xx_psc_buffer_8); | ||
219 | } | ||
220 | |||
221 | static void mpc52xx_psc_cw_disable_ints(struct uart_port *port) | ||
222 | { | ||
223 | out_be16(&PSC(port)->mpc52xx_psc_imr, 0); | ||
224 | } | ||
225 | |||
226 | static void mpc52xx_psc_cw_restore_ints(struct uart_port *port) | ||
227 | { | ||
228 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
229 | } | ||
230 | |||
231 | static unsigned int mpc5200_psc_set_baudrate(struct uart_port *port, | ||
232 | struct ktermios *new, | ||
233 | struct ktermios *old) | ||
234 | { | ||
235 | unsigned int baud; | ||
236 | unsigned int divisor; | ||
237 | |||
238 | /* The 5200 has a fixed /32 prescaler, uartclk contains the ipb freq */ | ||
239 | baud = uart_get_baud_rate(port, new, old, | ||
240 | port->uartclk / (32 * 0xffff) + 1, | ||
241 | port->uartclk / 32); | ||
242 | divisor = (port->uartclk + 16 * baud) / (32 * baud); | ||
243 | |||
244 | /* enable the /32 prescaler and set the divisor */ | ||
245 | mpc52xx_set_divisor(PSC(port), 0xdd00, divisor); | ||
246 | return baud; | ||
247 | } | ||
248 | |||
249 | static unsigned int mpc5200b_psc_set_baudrate(struct uart_port *port, | ||
250 | struct ktermios *new, | ||
251 | struct ktermios *old) | ||
252 | { | ||
253 | unsigned int baud; | ||
254 | unsigned int divisor; | ||
255 | u16 prescaler; | ||
256 | |||
257 | /* The 5200B has a selectable /4 or /32 prescaler, uartclk contains the | ||
258 | * ipb freq */ | ||
259 | baud = uart_get_baud_rate(port, new, old, | ||
260 | port->uartclk / (32 * 0xffff) + 1, | ||
261 | port->uartclk / 4); | ||
262 | divisor = (port->uartclk + 2 * baud) / (4 * baud); | ||
263 | |||
264 | /* select the proper prescaler and set the divisor */ | ||
265 | if (divisor > 0xffff) { | ||
266 | divisor = (divisor + 4) / 8; | ||
267 | prescaler = 0xdd00; /* /32 */ | ||
268 | } else | ||
269 | prescaler = 0xff00; /* /4 */ | ||
270 | mpc52xx_set_divisor(PSC(port), prescaler, divisor); | ||
271 | return baud; | ||
272 | } | ||
273 | |||
274 | static void mpc52xx_psc_get_irq(struct uart_port *port, struct device_node *np) | ||
275 | { | ||
276 | port->irqflags = IRQF_DISABLED; | ||
277 | port->irq = irq_of_parse_and_map(np, 0); | ||
278 | } | ||
279 | |||
280 | /* 52xx specific interrupt handler. The caller holds the port lock */ | ||
281 | static irqreturn_t mpc52xx_psc_handle_irq(struct uart_port *port) | ||
282 | { | ||
283 | return mpc5xxx_uart_process_int(port); | ||
284 | } | ||
285 | |||
286 | static struct psc_ops mpc52xx_psc_ops = { | ||
287 | .fifo_init = mpc52xx_psc_fifo_init, | ||
288 | .raw_rx_rdy = mpc52xx_psc_raw_rx_rdy, | ||
289 | .raw_tx_rdy = mpc52xx_psc_raw_tx_rdy, | ||
290 | .rx_rdy = mpc52xx_psc_rx_rdy, | ||
291 | .tx_rdy = mpc52xx_psc_tx_rdy, | ||
292 | .tx_empty = mpc52xx_psc_tx_empty, | ||
293 | .stop_rx = mpc52xx_psc_stop_rx, | ||
294 | .start_tx = mpc52xx_psc_start_tx, | ||
295 | .stop_tx = mpc52xx_psc_stop_tx, | ||
296 | .rx_clr_irq = mpc52xx_psc_rx_clr_irq, | ||
297 | .tx_clr_irq = mpc52xx_psc_tx_clr_irq, | ||
298 | .write_char = mpc52xx_psc_write_char, | ||
299 | .read_char = mpc52xx_psc_read_char, | ||
300 | .cw_disable_ints = mpc52xx_psc_cw_disable_ints, | ||
301 | .cw_restore_ints = mpc52xx_psc_cw_restore_ints, | ||
302 | .set_baudrate = mpc5200_psc_set_baudrate, | ||
303 | .get_irq = mpc52xx_psc_get_irq, | ||
304 | .handle_irq = mpc52xx_psc_handle_irq, | ||
305 | }; | ||
306 | |||
307 | static struct psc_ops mpc5200b_psc_ops = { | ||
308 | .fifo_init = mpc52xx_psc_fifo_init, | ||
309 | .raw_rx_rdy = mpc52xx_psc_raw_rx_rdy, | ||
310 | .raw_tx_rdy = mpc52xx_psc_raw_tx_rdy, | ||
311 | .rx_rdy = mpc52xx_psc_rx_rdy, | ||
312 | .tx_rdy = mpc52xx_psc_tx_rdy, | ||
313 | .tx_empty = mpc52xx_psc_tx_empty, | ||
314 | .stop_rx = mpc52xx_psc_stop_rx, | ||
315 | .start_tx = mpc52xx_psc_start_tx, | ||
316 | .stop_tx = mpc52xx_psc_stop_tx, | ||
317 | .rx_clr_irq = mpc52xx_psc_rx_clr_irq, | ||
318 | .tx_clr_irq = mpc52xx_psc_tx_clr_irq, | ||
319 | .write_char = mpc52xx_psc_write_char, | ||
320 | .read_char = mpc52xx_psc_read_char, | ||
321 | .cw_disable_ints = mpc52xx_psc_cw_disable_ints, | ||
322 | .cw_restore_ints = mpc52xx_psc_cw_restore_ints, | ||
323 | .set_baudrate = mpc5200b_psc_set_baudrate, | ||
324 | .get_irq = mpc52xx_psc_get_irq, | ||
325 | .handle_irq = mpc52xx_psc_handle_irq, | ||
326 | }; | ||
327 | |||
328 | #endif /* CONFIG_MPC52xx */ | ||
329 | |||
330 | #ifdef CONFIG_PPC_MPC512x | ||
331 | #define FIFO_512x(port) ((struct mpc512x_psc_fifo __iomem *)(PSC(port)+1)) | ||
332 | |||
333 | /* PSC FIFO Controller for mpc512x */ | ||
334 | struct psc_fifoc { | ||
335 | u32 fifoc_cmd; | ||
336 | u32 fifoc_int; | ||
337 | u32 fifoc_dma; | ||
338 | u32 fifoc_axe; | ||
339 | u32 fifoc_debug; | ||
340 | }; | ||
341 | |||
342 | static struct psc_fifoc __iomem *psc_fifoc; | ||
343 | static unsigned int psc_fifoc_irq; | ||
344 | |||
345 | static void mpc512x_psc_fifo_init(struct uart_port *port) | ||
346 | { | ||
347 | /* /32 prescaler */ | ||
348 | out_be16(&PSC(port)->mpc52xx_psc_clock_select, 0xdd00); | ||
349 | |||
350 | out_be32(&FIFO_512x(port)->txcmd, MPC512x_PSC_FIFO_RESET_SLICE); | ||
351 | out_be32(&FIFO_512x(port)->txcmd, MPC512x_PSC_FIFO_ENABLE_SLICE); | ||
352 | out_be32(&FIFO_512x(port)->txalarm, 1); | ||
353 | out_be32(&FIFO_512x(port)->tximr, 0); | ||
354 | |||
355 | out_be32(&FIFO_512x(port)->rxcmd, MPC512x_PSC_FIFO_RESET_SLICE); | ||
356 | out_be32(&FIFO_512x(port)->rxcmd, MPC512x_PSC_FIFO_ENABLE_SLICE); | ||
357 | out_be32(&FIFO_512x(port)->rxalarm, 1); | ||
358 | out_be32(&FIFO_512x(port)->rximr, 0); | ||
359 | |||
360 | out_be32(&FIFO_512x(port)->tximr, MPC512x_PSC_FIFO_ALARM); | ||
361 | out_be32(&FIFO_512x(port)->rximr, MPC512x_PSC_FIFO_ALARM); | ||
362 | } | ||
363 | |||
364 | static int mpc512x_psc_raw_rx_rdy(struct uart_port *port) | ||
365 | { | ||
366 | return !(in_be32(&FIFO_512x(port)->rxsr) & MPC512x_PSC_FIFO_EMPTY); | ||
367 | } | ||
368 | |||
369 | static int mpc512x_psc_raw_tx_rdy(struct uart_port *port) | ||
370 | { | ||
371 | return !(in_be32(&FIFO_512x(port)->txsr) & MPC512x_PSC_FIFO_FULL); | ||
372 | } | ||
373 | |||
374 | static int mpc512x_psc_rx_rdy(struct uart_port *port) | ||
375 | { | ||
376 | return in_be32(&FIFO_512x(port)->rxsr) | ||
377 | & in_be32(&FIFO_512x(port)->rximr) | ||
378 | & MPC512x_PSC_FIFO_ALARM; | ||
379 | } | ||
380 | |||
381 | static int mpc512x_psc_tx_rdy(struct uart_port *port) | ||
382 | { | ||
383 | return in_be32(&FIFO_512x(port)->txsr) | ||
384 | & in_be32(&FIFO_512x(port)->tximr) | ||
385 | & MPC512x_PSC_FIFO_ALARM; | ||
386 | } | ||
387 | |||
388 | static int mpc512x_psc_tx_empty(struct uart_port *port) | ||
389 | { | ||
390 | return in_be32(&FIFO_512x(port)->txsr) | ||
391 | & MPC512x_PSC_FIFO_EMPTY; | ||
392 | } | ||
393 | |||
394 | static void mpc512x_psc_stop_rx(struct uart_port *port) | ||
395 | { | ||
396 | unsigned long rx_fifo_imr; | ||
397 | |||
398 | rx_fifo_imr = in_be32(&FIFO_512x(port)->rximr); | ||
399 | rx_fifo_imr &= ~MPC512x_PSC_FIFO_ALARM; | ||
400 | out_be32(&FIFO_512x(port)->rximr, rx_fifo_imr); | ||
401 | } | ||
402 | |||
403 | static void mpc512x_psc_start_tx(struct uart_port *port) | ||
404 | { | ||
405 | unsigned long tx_fifo_imr; | ||
406 | |||
407 | tx_fifo_imr = in_be32(&FIFO_512x(port)->tximr); | ||
408 | tx_fifo_imr |= MPC512x_PSC_FIFO_ALARM; | ||
409 | out_be32(&FIFO_512x(port)->tximr, tx_fifo_imr); | ||
410 | } | ||
411 | |||
412 | static void mpc512x_psc_stop_tx(struct uart_port *port) | ||
413 | { | ||
414 | unsigned long tx_fifo_imr; | ||
415 | |||
416 | tx_fifo_imr = in_be32(&FIFO_512x(port)->tximr); | ||
417 | tx_fifo_imr &= ~MPC512x_PSC_FIFO_ALARM; | ||
418 | out_be32(&FIFO_512x(port)->tximr, tx_fifo_imr); | ||
419 | } | ||
420 | |||
421 | static void mpc512x_psc_rx_clr_irq(struct uart_port *port) | ||
422 | { | ||
423 | out_be32(&FIFO_512x(port)->rxisr, in_be32(&FIFO_512x(port)->rxisr)); | ||
424 | } | ||
425 | |||
426 | static void mpc512x_psc_tx_clr_irq(struct uart_port *port) | ||
427 | { | ||
428 | out_be32(&FIFO_512x(port)->txisr, in_be32(&FIFO_512x(port)->txisr)); | ||
429 | } | ||
430 | |||
431 | static void mpc512x_psc_write_char(struct uart_port *port, unsigned char c) | ||
432 | { | ||
433 | out_8(&FIFO_512x(port)->txdata_8, c); | ||
434 | } | ||
435 | |||
436 | static unsigned char mpc512x_psc_read_char(struct uart_port *port) | ||
437 | { | ||
438 | return in_8(&FIFO_512x(port)->rxdata_8); | ||
439 | } | ||
440 | |||
441 | static void mpc512x_psc_cw_disable_ints(struct uart_port *port) | ||
442 | { | ||
443 | port->read_status_mask = | ||
444 | in_be32(&FIFO_512x(port)->tximr) << 16 | | ||
445 | in_be32(&FIFO_512x(port)->rximr); | ||
446 | out_be32(&FIFO_512x(port)->tximr, 0); | ||
447 | out_be32(&FIFO_512x(port)->rximr, 0); | ||
448 | } | ||
449 | |||
450 | static void mpc512x_psc_cw_restore_ints(struct uart_port *port) | ||
451 | { | ||
452 | out_be32(&FIFO_512x(port)->tximr, | ||
453 | (port->read_status_mask >> 16) & 0x7f); | ||
454 | out_be32(&FIFO_512x(port)->rximr, port->read_status_mask & 0x7f); | ||
455 | } | ||
456 | |||
457 | static unsigned int mpc512x_psc_set_baudrate(struct uart_port *port, | ||
458 | struct ktermios *new, | ||
459 | struct ktermios *old) | ||
460 | { | ||
461 | unsigned int baud; | ||
462 | unsigned int divisor; | ||
463 | |||
464 | /* | ||
465 | * The "MPC5121e Microcontroller Reference Manual, Rev. 3" says on | ||
466 | * pg. 30-10 that the chip supports a /32 and a /10 prescaler. | ||
467 | * Furthermore, it states that "After reset, the prescaler by 10 | ||
468 | * for the UART mode is selected", but the reset register value is | ||
469 | * 0x0000 which means a /32 prescaler. This is wrong. | ||
470 | * | ||
471 | * In reality using /32 prescaler doesn't work, as it is not supported! | ||
472 | * Use /16 or /10 prescaler, see "MPC5121e Hardware Design Guide", | ||
473 | * Chapter 4.1 PSC in UART Mode. | ||
474 | * Calculate with a /16 prescaler here. | ||
475 | */ | ||
476 | |||
477 | /* uartclk contains the ips freq */ | ||
478 | baud = uart_get_baud_rate(port, new, old, | ||
479 | port->uartclk / (16 * 0xffff) + 1, | ||
480 | port->uartclk / 16); | ||
481 | divisor = (port->uartclk + 8 * baud) / (16 * baud); | ||
482 | |||
483 | /* enable the /16 prescaler and set the divisor */ | ||
484 | mpc52xx_set_divisor(PSC(port), 0xdd00, divisor); | ||
485 | return baud; | ||
486 | } | ||
487 | |||
488 | /* Init PSC FIFO Controller */ | ||
489 | static int __init mpc512x_psc_fifoc_init(void) | ||
490 | { | ||
491 | struct device_node *np; | ||
492 | |||
493 | np = of_find_compatible_node(NULL, NULL, | ||
494 | "fsl,mpc5121-psc-fifo"); | ||
495 | if (!np) { | ||
496 | pr_err("%s: Can't find FIFOC node\n", __func__); | ||
497 | return -ENODEV; | ||
498 | } | ||
499 | |||
500 | psc_fifoc = of_iomap(np, 0); | ||
501 | if (!psc_fifoc) { | ||
502 | pr_err("%s: Can't map FIFOC\n", __func__); | ||
503 | of_node_put(np); | ||
504 | return -ENODEV; | ||
505 | } | ||
506 | |||
507 | psc_fifoc_irq = irq_of_parse_and_map(np, 0); | ||
508 | of_node_put(np); | ||
509 | if (psc_fifoc_irq == NO_IRQ) { | ||
510 | pr_err("%s: Can't get FIFOC irq\n", __func__); | ||
511 | iounmap(psc_fifoc); | ||
512 | return -ENODEV; | ||
513 | } | ||
514 | |||
515 | return 0; | ||
516 | } | ||
517 | |||
518 | static void __exit mpc512x_psc_fifoc_uninit(void) | ||
519 | { | ||
520 | iounmap(psc_fifoc); | ||
521 | } | ||
522 | |||
523 | /* 512x specific interrupt handler. The caller holds the port lock */ | ||
524 | static irqreturn_t mpc512x_psc_handle_irq(struct uart_port *port) | ||
525 | { | ||
526 | unsigned long fifoc_int; | ||
527 | int psc_num; | ||
528 | |||
529 | /* Read pending PSC FIFOC interrupts */ | ||
530 | fifoc_int = in_be32(&psc_fifoc->fifoc_int); | ||
531 | |||
532 | /* Check if it is an interrupt for this port */ | ||
533 | psc_num = (port->mapbase & 0xf00) >> 8; | ||
534 | if (test_bit(psc_num, &fifoc_int) || | ||
535 | test_bit(psc_num + 16, &fifoc_int)) | ||
536 | return mpc5xxx_uart_process_int(port); | ||
537 | |||
538 | return IRQ_NONE; | ||
539 | } | ||
540 | |||
541 | static int mpc512x_psc_clock(struct uart_port *port, int enable) | ||
542 | { | ||
543 | struct clk *psc_clk; | ||
544 | int psc_num; | ||
545 | char clk_name[10]; | ||
546 | |||
547 | if (uart_console(port)) | ||
548 | return 0; | ||
549 | |||
550 | psc_num = (port->mapbase & 0xf00) >> 8; | ||
551 | snprintf(clk_name, sizeof(clk_name), "psc%d_clk", psc_num); | ||
552 | psc_clk = clk_get(port->dev, clk_name); | ||
553 | if (IS_ERR(psc_clk)) { | ||
554 | dev_err(port->dev, "Failed to get PSC clock entry!\n"); | ||
555 | return -ENODEV; | ||
556 | } | ||
557 | |||
558 | dev_dbg(port->dev, "%s %sable\n", clk_name, enable ? "en" : "dis"); | ||
559 | |||
560 | if (enable) | ||
561 | clk_enable(psc_clk); | ||
562 | else | ||
563 | clk_disable(psc_clk); | ||
564 | |||
565 | return 0; | ||
566 | } | ||
567 | |||
568 | static void mpc512x_psc_get_irq(struct uart_port *port, struct device_node *np) | ||
569 | { | ||
570 | port->irqflags = IRQF_SHARED; | ||
571 | port->irq = psc_fifoc_irq; | ||
572 | } | ||
573 | |||
574 | static struct psc_ops mpc512x_psc_ops = { | ||
575 | .fifo_init = mpc512x_psc_fifo_init, | ||
576 | .raw_rx_rdy = mpc512x_psc_raw_rx_rdy, | ||
577 | .raw_tx_rdy = mpc512x_psc_raw_tx_rdy, | ||
578 | .rx_rdy = mpc512x_psc_rx_rdy, | ||
579 | .tx_rdy = mpc512x_psc_tx_rdy, | ||
580 | .tx_empty = mpc512x_psc_tx_empty, | ||
581 | .stop_rx = mpc512x_psc_stop_rx, | ||
582 | .start_tx = mpc512x_psc_start_tx, | ||
583 | .stop_tx = mpc512x_psc_stop_tx, | ||
584 | .rx_clr_irq = mpc512x_psc_rx_clr_irq, | ||
585 | .tx_clr_irq = mpc512x_psc_tx_clr_irq, | ||
586 | .write_char = mpc512x_psc_write_char, | ||
587 | .read_char = mpc512x_psc_read_char, | ||
588 | .cw_disable_ints = mpc512x_psc_cw_disable_ints, | ||
589 | .cw_restore_ints = mpc512x_psc_cw_restore_ints, | ||
590 | .set_baudrate = mpc512x_psc_set_baudrate, | ||
591 | .clock = mpc512x_psc_clock, | ||
592 | .fifoc_init = mpc512x_psc_fifoc_init, | ||
593 | .fifoc_uninit = mpc512x_psc_fifoc_uninit, | ||
594 | .get_irq = mpc512x_psc_get_irq, | ||
595 | .handle_irq = mpc512x_psc_handle_irq, | ||
596 | }; | ||
597 | #endif | ||
598 | |||
599 | static struct psc_ops *psc_ops; | ||
600 | |||
601 | /* ======================================================================== */ | ||
602 | /* UART operations */ | ||
603 | /* ======================================================================== */ | ||
604 | |||
605 | static unsigned int | ||
606 | mpc52xx_uart_tx_empty(struct uart_port *port) | ||
607 | { | ||
608 | return psc_ops->tx_empty(port) ? TIOCSER_TEMT : 0; | ||
609 | } | ||
610 | |||
611 | static void | ||
612 | mpc52xx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) | ||
613 | { | ||
614 | if (mctrl & TIOCM_RTS) | ||
615 | out_8(&PSC(port)->op1, MPC52xx_PSC_OP_RTS); | ||
616 | else | ||
617 | out_8(&PSC(port)->op0, MPC52xx_PSC_OP_RTS); | ||
618 | } | ||
619 | |||
620 | static unsigned int | ||
621 | mpc52xx_uart_get_mctrl(struct uart_port *port) | ||
622 | { | ||
623 | unsigned int ret = TIOCM_DSR; | ||
624 | u8 status = in_8(&PSC(port)->mpc52xx_psc_ipcr); | ||
625 | |||
626 | if (!(status & MPC52xx_PSC_CTS)) | ||
627 | ret |= TIOCM_CTS; | ||
628 | if (!(status & MPC52xx_PSC_DCD)) | ||
629 | ret |= TIOCM_CAR; | ||
630 | |||
631 | return ret; | ||
632 | } | ||
633 | |||
634 | static void | ||
635 | mpc52xx_uart_stop_tx(struct uart_port *port) | ||
636 | { | ||
637 | /* port->lock taken by caller */ | ||
638 | psc_ops->stop_tx(port); | ||
639 | } | ||
640 | |||
641 | static void | ||
642 | mpc52xx_uart_start_tx(struct uart_port *port) | ||
643 | { | ||
644 | /* port->lock taken by caller */ | ||
645 | psc_ops->start_tx(port); | ||
646 | } | ||
647 | |||
648 | static void | ||
649 | mpc52xx_uart_send_xchar(struct uart_port *port, char ch) | ||
650 | { | ||
651 | unsigned long flags; | ||
652 | spin_lock_irqsave(&port->lock, flags); | ||
653 | |||
654 | port->x_char = ch; | ||
655 | if (ch) { | ||
656 | /* Make sure tx interrupts are on */ | ||
657 | /* Truly necessary ??? They should be anyway */ | ||
658 | psc_ops->start_tx(port); | ||
659 | } | ||
660 | |||
661 | spin_unlock_irqrestore(&port->lock, flags); | ||
662 | } | ||
663 | |||
664 | static void | ||
665 | mpc52xx_uart_stop_rx(struct uart_port *port) | ||
666 | { | ||
667 | /* port->lock taken by caller */ | ||
668 | psc_ops->stop_rx(port); | ||
669 | } | ||
670 | |||
671 | static void | ||
672 | mpc52xx_uart_enable_ms(struct uart_port *port) | ||
673 | { | ||
674 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
675 | |||
676 | /* clear D_*-bits by reading them */ | ||
677 | in_8(&psc->mpc52xx_psc_ipcr); | ||
678 | /* enable CTS and DCD as IPC interrupts */ | ||
679 | out_8(&psc->mpc52xx_psc_acr, MPC52xx_PSC_IEC_CTS | MPC52xx_PSC_IEC_DCD); | ||
680 | |||
681 | port->read_status_mask |= MPC52xx_PSC_IMR_IPC; | ||
682 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | ||
683 | } | ||
684 | |||
685 | static void | ||
686 | mpc52xx_uart_break_ctl(struct uart_port *port, int ctl) | ||
687 | { | ||
688 | unsigned long flags; | ||
689 | spin_lock_irqsave(&port->lock, flags); | ||
690 | |||
691 | if (ctl == -1) | ||
692 | out_8(&PSC(port)->command, MPC52xx_PSC_START_BRK); | ||
693 | else | ||
694 | out_8(&PSC(port)->command, MPC52xx_PSC_STOP_BRK); | ||
695 | |||
696 | spin_unlock_irqrestore(&port->lock, flags); | ||
697 | } | ||
698 | |||
699 | static int | ||
700 | mpc52xx_uart_startup(struct uart_port *port) | ||
701 | { | ||
702 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
703 | int ret; | ||
704 | |||
705 | if (psc_ops->clock) { | ||
706 | ret = psc_ops->clock(port, 1); | ||
707 | if (ret) | ||
708 | return ret; | ||
709 | } | ||
710 | |||
711 | /* Request IRQ */ | ||
712 | ret = request_irq(port->irq, mpc52xx_uart_int, | ||
713 | port->irqflags, "mpc52xx_psc_uart", port); | ||
714 | if (ret) | ||
715 | return ret; | ||
716 | |||
717 | /* Reset/activate the port, clear and enable interrupts */ | ||
718 | out_8(&psc->command, MPC52xx_PSC_RST_RX); | ||
719 | out_8(&psc->command, MPC52xx_PSC_RST_TX); | ||
720 | |||
721 | out_be32(&psc->sicr, 0); /* UART mode DCD ignored */ | ||
722 | |||
723 | psc_ops->fifo_init(port); | ||
724 | |||
725 | out_8(&psc->command, MPC52xx_PSC_TX_ENABLE); | ||
726 | out_8(&psc->command, MPC52xx_PSC_RX_ENABLE); | ||
727 | |||
728 | return 0; | ||
729 | } | ||
730 | |||
731 | static void | ||
732 | mpc52xx_uart_shutdown(struct uart_port *port) | ||
733 | { | ||
734 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
735 | |||
736 | /* Shut down the port. Leave TX active if on a console port */ | ||
737 | out_8(&psc->command, MPC52xx_PSC_RST_RX); | ||
738 | if (!uart_console(port)) | ||
739 | out_8(&psc->command, MPC52xx_PSC_RST_TX); | ||
740 | |||
741 | port->read_status_mask = 0; | ||
742 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | ||
743 | |||
744 | if (psc_ops->clock) | ||
745 | psc_ops->clock(port, 0); | ||
746 | |||
747 | /* Release interrupt */ | ||
748 | free_irq(port->irq, port); | ||
749 | } | ||
750 | |||
751 | static void | ||
752 | mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, | ||
753 | struct ktermios *old) | ||
754 | { | ||
755 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
756 | unsigned long flags; | ||
757 | unsigned char mr1, mr2; | ||
758 | unsigned int j; | ||
759 | unsigned int baud; | ||
760 | |||
761 | /* Prepare what we're gonna write */ | ||
762 | mr1 = 0; | ||
763 | |||
764 | switch (new->c_cflag & CSIZE) { | ||
765 | case CS5: mr1 |= MPC52xx_PSC_MODE_5_BITS; | ||
766 | break; | ||
767 | case CS6: mr1 |= MPC52xx_PSC_MODE_6_BITS; | ||
768 | break; | ||
769 | case CS7: mr1 |= MPC52xx_PSC_MODE_7_BITS; | ||
770 | break; | ||
771 | case CS8: | ||
772 | default: mr1 |= MPC52xx_PSC_MODE_8_BITS; | ||
773 | } | ||
774 | |||
775 | if (new->c_cflag & PARENB) { | ||
776 | mr1 |= (new->c_cflag & PARODD) ? | ||
777 | MPC52xx_PSC_MODE_PARODD : MPC52xx_PSC_MODE_PAREVEN; | ||
778 | } else | ||
779 | mr1 |= MPC52xx_PSC_MODE_PARNONE; | ||
780 | |||
781 | |||
782 | mr2 = 0; | ||
783 | |||
784 | if (new->c_cflag & CSTOPB) | ||
785 | mr2 |= MPC52xx_PSC_MODE_TWO_STOP; | ||
786 | else | ||
787 | mr2 |= ((new->c_cflag & CSIZE) == CS5) ? | ||
788 | MPC52xx_PSC_MODE_ONE_STOP_5_BITS : | ||
789 | MPC52xx_PSC_MODE_ONE_STOP; | ||
790 | |||
791 | if (new->c_cflag & CRTSCTS) { | ||
792 | mr1 |= MPC52xx_PSC_MODE_RXRTS; | ||
793 | mr2 |= MPC52xx_PSC_MODE_TXCTS; | ||
794 | } | ||
795 | |||
796 | /* Get the lock */ | ||
797 | spin_lock_irqsave(&port->lock, flags); | ||
798 | |||
799 | /* Do our best to flush TX & RX, so we don't lose anything */ | ||
800 | /* But we don't wait indefinitely ! */ | ||
801 | j = 5000000; /* Maximum wait */ | ||
802 | /* FIXME Can't receive chars since set_termios might be called at early | ||
803 | * boot for the console, all stuff is not yet ready to receive at that | ||
804 | * time and that just makes the kernel oops */ | ||
805 | /* while (j-- && mpc52xx_uart_int_rx_chars(port)); */ | ||
806 | while (!mpc52xx_uart_tx_empty(port) && --j) | ||
807 | udelay(1); | ||
808 | |||
809 | if (!j) | ||
810 | printk(KERN_ERR "mpc52xx_uart.c: " | ||
811 | "Unable to flush RX & TX fifos in-time in set_termios." | ||
812 | "Some chars may have been lost.\n"); | ||
813 | |||
814 | /* Reset the TX & RX */ | ||
815 | out_8(&psc->command, MPC52xx_PSC_RST_RX); | ||
816 | out_8(&psc->command, MPC52xx_PSC_RST_TX); | ||
817 | |||
818 | /* Send new mode settings */ | ||
819 | out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1); | ||
820 | out_8(&psc->mode, mr1); | ||
821 | out_8(&psc->mode, mr2); | ||
822 | baud = psc_ops->set_baudrate(port, new, old); | ||
823 | |||
824 | /* Update the per-port timeout */ | ||
825 | uart_update_timeout(port, new->c_cflag, baud); | ||
826 | |||
827 | if (UART_ENABLE_MS(port, new->c_cflag)) | ||
828 | mpc52xx_uart_enable_ms(port); | ||
829 | |||
830 | /* Reenable TX & RX */ | ||
831 | out_8(&psc->command, MPC52xx_PSC_TX_ENABLE); | ||
832 | out_8(&psc->command, MPC52xx_PSC_RX_ENABLE); | ||
833 | |||
834 | /* We're all set, release the lock */ | ||
835 | spin_unlock_irqrestore(&port->lock, flags); | ||
836 | } | ||
837 | |||
838 | static const char * | ||
839 | mpc52xx_uart_type(struct uart_port *port) | ||
840 | { | ||
841 | /* | ||
842 | * We keep using PORT_MPC52xx for historic reasons although it applies | ||
843 | * for MPC512x, too, but print "MPC5xxx" to not irritate users | ||
844 | */ | ||
845 | return port->type == PORT_MPC52xx ? "MPC5xxx PSC" : NULL; | ||
846 | } | ||
847 | |||
848 | static void | ||
849 | mpc52xx_uart_release_port(struct uart_port *port) | ||
850 | { | ||
851 | /* remapped by us ? */ | ||
852 | if (port->flags & UPF_IOREMAP) { | ||
853 | iounmap(port->membase); | ||
854 | port->membase = NULL; | ||
855 | } | ||
856 | |||
857 | release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc)); | ||
858 | } | ||
859 | |||
860 | static int | ||
861 | mpc52xx_uart_request_port(struct uart_port *port) | ||
862 | { | ||
863 | int err; | ||
864 | |||
865 | if (port->flags & UPF_IOREMAP) /* Need to remap ? */ | ||
866 | port->membase = ioremap(port->mapbase, | ||
867 | sizeof(struct mpc52xx_psc)); | ||
868 | |||
869 | if (!port->membase) | ||
870 | return -EINVAL; | ||
871 | |||
872 | err = request_mem_region(port->mapbase, sizeof(struct mpc52xx_psc), | ||
873 | "mpc52xx_psc_uart") != NULL ? 0 : -EBUSY; | ||
874 | |||
875 | if (err && (port->flags & UPF_IOREMAP)) { | ||
876 | iounmap(port->membase); | ||
877 | port->membase = NULL; | ||
878 | } | ||
879 | |||
880 | return err; | ||
881 | } | ||
882 | |||
883 | static void | ||
884 | mpc52xx_uart_config_port(struct uart_port *port, int flags) | ||
885 | { | ||
886 | if ((flags & UART_CONFIG_TYPE) | ||
887 | && (mpc52xx_uart_request_port(port) == 0)) | ||
888 | port->type = PORT_MPC52xx; | ||
889 | } | ||
890 | |||
891 | static int | ||
892 | mpc52xx_uart_verify_port(struct uart_port *port, struct serial_struct *ser) | ||
893 | { | ||
894 | if (ser->type != PORT_UNKNOWN && ser->type != PORT_MPC52xx) | ||
895 | return -EINVAL; | ||
896 | |||
897 | if ((ser->irq != port->irq) || | ||
898 | (ser->io_type != UPIO_MEM) || | ||
899 | (ser->baud_base != port->uartclk) || | ||
900 | (ser->iomem_base != (void *)port->mapbase) || | ||
901 | (ser->hub6 != 0)) | ||
902 | return -EINVAL; | ||
903 | |||
904 | return 0; | ||
905 | } | ||
906 | |||
907 | |||
908 | static struct uart_ops mpc52xx_uart_ops = { | ||
909 | .tx_empty = mpc52xx_uart_tx_empty, | ||
910 | .set_mctrl = mpc52xx_uart_set_mctrl, | ||
911 | .get_mctrl = mpc52xx_uart_get_mctrl, | ||
912 | .stop_tx = mpc52xx_uart_stop_tx, | ||
913 | .start_tx = mpc52xx_uart_start_tx, | ||
914 | .send_xchar = mpc52xx_uart_send_xchar, | ||
915 | .stop_rx = mpc52xx_uart_stop_rx, | ||
916 | .enable_ms = mpc52xx_uart_enable_ms, | ||
917 | .break_ctl = mpc52xx_uart_break_ctl, | ||
918 | .startup = mpc52xx_uart_startup, | ||
919 | .shutdown = mpc52xx_uart_shutdown, | ||
920 | .set_termios = mpc52xx_uart_set_termios, | ||
921 | /* .pm = mpc52xx_uart_pm, Not supported yet */ | ||
922 | /* .set_wake = mpc52xx_uart_set_wake, Not supported yet */ | ||
923 | .type = mpc52xx_uart_type, | ||
924 | .release_port = mpc52xx_uart_release_port, | ||
925 | .request_port = mpc52xx_uart_request_port, | ||
926 | .config_port = mpc52xx_uart_config_port, | ||
927 | .verify_port = mpc52xx_uart_verify_port | ||
928 | }; | ||
929 | |||
930 | |||
931 | /* ======================================================================== */ | ||
932 | /* Interrupt handling */ | ||
933 | /* ======================================================================== */ | ||
934 | |||
935 | static inline int | ||
936 | mpc52xx_uart_int_rx_chars(struct uart_port *port) | ||
937 | { | ||
938 | struct tty_struct *tty = port->state->port.tty; | ||
939 | unsigned char ch, flag; | ||
940 | unsigned short status; | ||
941 | |||
942 | /* While we can read, do so ! */ | ||
943 | while (psc_ops->raw_rx_rdy(port)) { | ||
944 | /* Get the char */ | ||
945 | ch = psc_ops->read_char(port); | ||
946 | |||
947 | /* Handle sysreq char */ | ||
948 | #ifdef SUPPORT_SYSRQ | ||
949 | if (uart_handle_sysrq_char(port, ch)) { | ||
950 | port->sysrq = 0; | ||
951 | continue; | ||
952 | } | ||
953 | #endif | ||
954 | |||
955 | /* Store it */ | ||
956 | |||
957 | flag = TTY_NORMAL; | ||
958 | port->icount.rx++; | ||
959 | |||
960 | status = in_be16(&PSC(port)->mpc52xx_psc_status); | ||
961 | |||
962 | if (status & (MPC52xx_PSC_SR_PE | | ||
963 | MPC52xx_PSC_SR_FE | | ||
964 | MPC52xx_PSC_SR_RB)) { | ||
965 | |||
966 | if (status & MPC52xx_PSC_SR_RB) { | ||
967 | flag = TTY_BREAK; | ||
968 | uart_handle_break(port); | ||
969 | port->icount.brk++; | ||
970 | } else if (status & MPC52xx_PSC_SR_PE) { | ||
971 | flag = TTY_PARITY; | ||
972 | port->icount.parity++; | ||
973 | } | ||
974 | else if (status & MPC52xx_PSC_SR_FE) { | ||
975 | flag = TTY_FRAME; | ||
976 | port->icount.frame++; | ||
977 | } | ||
978 | |||
979 | /* Clear error condition */ | ||
980 | out_8(&PSC(port)->command, MPC52xx_PSC_RST_ERR_STAT); | ||
981 | |||
982 | } | ||
983 | tty_insert_flip_char(tty, ch, flag); | ||
984 | if (status & MPC52xx_PSC_SR_OE) { | ||
985 | /* | ||
986 | * Overrun is special, since it's | ||
987 | * reported immediately, and doesn't | ||
988 | * affect the current character | ||
989 | */ | ||
990 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | ||
991 | port->icount.overrun++; | ||
992 | } | ||
993 | } | ||
994 | |||
995 | spin_unlock(&port->lock); | ||
996 | tty_flip_buffer_push(tty); | ||
997 | spin_lock(&port->lock); | ||
998 | |||
999 | return psc_ops->raw_rx_rdy(port); | ||
1000 | } | ||
1001 | |||
1002 | static inline int | ||
1003 | mpc52xx_uart_int_tx_chars(struct uart_port *port) | ||
1004 | { | ||
1005 | struct circ_buf *xmit = &port->state->xmit; | ||
1006 | |||
1007 | /* Process out of band chars */ | ||
1008 | if (port->x_char) { | ||
1009 | psc_ops->write_char(port, port->x_char); | ||
1010 | port->icount.tx++; | ||
1011 | port->x_char = 0; | ||
1012 | return 1; | ||
1013 | } | ||
1014 | |||
1015 | /* Nothing to do ? */ | ||
1016 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { | ||
1017 | mpc52xx_uart_stop_tx(port); | ||
1018 | return 0; | ||
1019 | } | ||
1020 | |||
1021 | /* Send chars */ | ||
1022 | while (psc_ops->raw_tx_rdy(port)) { | ||
1023 | psc_ops->write_char(port, xmit->buf[xmit->tail]); | ||
1024 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
1025 | port->icount.tx++; | ||
1026 | if (uart_circ_empty(xmit)) | ||
1027 | break; | ||
1028 | } | ||
1029 | |||
1030 | /* Wake up */ | ||
1031 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
1032 | uart_write_wakeup(port); | ||
1033 | |||
1034 | /* Maybe we're done after all */ | ||
1035 | if (uart_circ_empty(xmit)) { | ||
1036 | mpc52xx_uart_stop_tx(port); | ||
1037 | return 0; | ||
1038 | } | ||
1039 | |||
1040 | return 1; | ||
1041 | } | ||
1042 | |||
1043 | static irqreturn_t | ||
1044 | mpc5xxx_uart_process_int(struct uart_port *port) | ||
1045 | { | ||
1046 | unsigned long pass = ISR_PASS_LIMIT; | ||
1047 | unsigned int keepgoing; | ||
1048 | u8 status; | ||
1049 | |||
1050 | /* While we have stuff to do, we continue */ | ||
1051 | do { | ||
1052 | /* If we don't find anything to do, we stop */ | ||
1053 | keepgoing = 0; | ||
1054 | |||
1055 | psc_ops->rx_clr_irq(port); | ||
1056 | if (psc_ops->rx_rdy(port)) | ||
1057 | keepgoing |= mpc52xx_uart_int_rx_chars(port); | ||
1058 | |||
1059 | psc_ops->tx_clr_irq(port); | ||
1060 | if (psc_ops->tx_rdy(port)) | ||
1061 | keepgoing |= mpc52xx_uart_int_tx_chars(port); | ||
1062 | |||
1063 | status = in_8(&PSC(port)->mpc52xx_psc_ipcr); | ||
1064 | if (status & MPC52xx_PSC_D_DCD) | ||
1065 | uart_handle_dcd_change(port, !(status & MPC52xx_PSC_DCD)); | ||
1066 | |||
1067 | if (status & MPC52xx_PSC_D_CTS) | ||
1068 | uart_handle_cts_change(port, !(status & MPC52xx_PSC_CTS)); | ||
1069 | |||
1070 | /* Limit number of iteration */ | ||
1071 | if (!(--pass)) | ||
1072 | keepgoing = 0; | ||
1073 | |||
1074 | } while (keepgoing); | ||
1075 | |||
1076 | return IRQ_HANDLED; | ||
1077 | } | ||
1078 | |||
1079 | static irqreturn_t | ||
1080 | mpc52xx_uart_int(int irq, void *dev_id) | ||
1081 | { | ||
1082 | struct uart_port *port = dev_id; | ||
1083 | irqreturn_t ret; | ||
1084 | |||
1085 | spin_lock(&port->lock); | ||
1086 | |||
1087 | ret = psc_ops->handle_irq(port); | ||
1088 | |||
1089 | spin_unlock(&port->lock); | ||
1090 | |||
1091 | return ret; | ||
1092 | } | ||
1093 | |||
1094 | /* ======================================================================== */ | ||
1095 | /* Console ( if applicable ) */ | ||
1096 | /* ======================================================================== */ | ||
1097 | |||
1098 | #ifdef CONFIG_SERIAL_MPC52xx_CONSOLE | ||
1099 | |||
1100 | static void __init | ||
1101 | mpc52xx_console_get_options(struct uart_port *port, | ||
1102 | int *baud, int *parity, int *bits, int *flow) | ||
1103 | { | ||
1104 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
1105 | unsigned char mr1; | ||
1106 | |||
1107 | pr_debug("mpc52xx_console_get_options(port=%p)\n", port); | ||
1108 | |||
1109 | /* Read the mode registers */ | ||
1110 | out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1); | ||
1111 | mr1 = in_8(&psc->mode); | ||
1112 | |||
1113 | /* CT{U,L}R are write-only ! */ | ||
1114 | *baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD; | ||
1115 | |||
1116 | /* Parse them */ | ||
1117 | switch (mr1 & MPC52xx_PSC_MODE_BITS_MASK) { | ||
1118 | case MPC52xx_PSC_MODE_5_BITS: | ||
1119 | *bits = 5; | ||
1120 | break; | ||
1121 | case MPC52xx_PSC_MODE_6_BITS: | ||
1122 | *bits = 6; | ||
1123 | break; | ||
1124 | case MPC52xx_PSC_MODE_7_BITS: | ||
1125 | *bits = 7; | ||
1126 | break; | ||
1127 | case MPC52xx_PSC_MODE_8_BITS: | ||
1128 | default: | ||
1129 | *bits = 8; | ||
1130 | } | ||
1131 | |||
1132 | if (mr1 & MPC52xx_PSC_MODE_PARNONE) | ||
1133 | *parity = 'n'; | ||
1134 | else | ||
1135 | *parity = mr1 & MPC52xx_PSC_MODE_PARODD ? 'o' : 'e'; | ||
1136 | } | ||
1137 | |||
1138 | static void | ||
1139 | mpc52xx_console_write(struct console *co, const char *s, unsigned int count) | ||
1140 | { | ||
1141 | struct uart_port *port = &mpc52xx_uart_ports[co->index]; | ||
1142 | unsigned int i, j; | ||
1143 | |||
1144 | /* Disable interrupts */ | ||
1145 | psc_ops->cw_disable_ints(port); | ||
1146 | |||
1147 | /* Wait the TX buffer to be empty */ | ||
1148 | j = 5000000; /* Maximum wait */ | ||
1149 | while (!mpc52xx_uart_tx_empty(port) && --j) | ||
1150 | udelay(1); | ||
1151 | |||
1152 | /* Write all the chars */ | ||
1153 | for (i = 0; i < count; i++, s++) { | ||
1154 | /* Line return handling */ | ||
1155 | if (*s == '\n') | ||
1156 | psc_ops->write_char(port, '\r'); | ||
1157 | |||
1158 | /* Send the char */ | ||
1159 | psc_ops->write_char(port, *s); | ||
1160 | |||
1161 | /* Wait the TX buffer to be empty */ | ||
1162 | j = 20000; /* Maximum wait */ | ||
1163 | while (!mpc52xx_uart_tx_empty(port) && --j) | ||
1164 | udelay(1); | ||
1165 | } | ||
1166 | |||
1167 | /* Restore interrupt state */ | ||
1168 | psc_ops->cw_restore_ints(port); | ||
1169 | } | ||
1170 | |||
1171 | |||
1172 | static int __init | ||
1173 | mpc52xx_console_setup(struct console *co, char *options) | ||
1174 | { | ||
1175 | struct uart_port *port = &mpc52xx_uart_ports[co->index]; | ||
1176 | struct device_node *np = mpc52xx_uart_nodes[co->index]; | ||
1177 | unsigned int uartclk; | ||
1178 | struct resource res; | ||
1179 | int ret; | ||
1180 | |||
1181 | int baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD; | ||
1182 | int bits = 8; | ||
1183 | int parity = 'n'; | ||
1184 | int flow = 'n'; | ||
1185 | |||
1186 | pr_debug("mpc52xx_console_setup co=%p, co->index=%i, options=%s\n", | ||
1187 | co, co->index, options); | ||
1188 | |||
1189 | if ((co->index < 0) || (co->index >= MPC52xx_PSC_MAXNUM)) { | ||
1190 | pr_debug("PSC%x out of range\n", co->index); | ||
1191 | return -EINVAL; | ||
1192 | } | ||
1193 | |||
1194 | if (!np) { | ||
1195 | pr_debug("PSC%x not found in device tree\n", co->index); | ||
1196 | return -EINVAL; | ||
1197 | } | ||
1198 | |||
1199 | pr_debug("Console on ttyPSC%x is %s\n", | ||
1200 | co->index, mpc52xx_uart_nodes[co->index]->full_name); | ||
1201 | |||
1202 | /* Fetch register locations */ | ||
1203 | ret = of_address_to_resource(np, 0, &res); | ||
1204 | if (ret) { | ||
1205 | pr_debug("Could not get resources for PSC%x\n", co->index); | ||
1206 | return ret; | ||
1207 | } | ||
1208 | |||
1209 | uartclk = mpc5xxx_get_bus_frequency(np); | ||
1210 | if (uartclk == 0) { | ||
1211 | pr_debug("Could not find uart clock frequency!\n"); | ||
1212 | return -EINVAL; | ||
1213 | } | ||
1214 | |||
1215 | /* Basic port init. Needed since we use some uart_??? func before | ||
1216 | * real init for early access */ | ||
1217 | spin_lock_init(&port->lock); | ||
1218 | port->uartclk = uartclk; | ||
1219 | port->ops = &mpc52xx_uart_ops; | ||
1220 | port->mapbase = res.start; | ||
1221 | port->membase = ioremap(res.start, sizeof(struct mpc52xx_psc)); | ||
1222 | port->irq = irq_of_parse_and_map(np, 0); | ||
1223 | |||
1224 | if (port->membase == NULL) | ||
1225 | return -EINVAL; | ||
1226 | |||
1227 | pr_debug("mpc52xx-psc uart at %p, mapped to %p, irq=%x, freq=%i\n", | ||
1228 | (void *)port->mapbase, port->membase, | ||
1229 | port->irq, port->uartclk); | ||
1230 | |||
1231 | /* Setup the port parameters accoding to options */ | ||
1232 | if (options) | ||
1233 | uart_parse_options(options, &baud, &parity, &bits, &flow); | ||
1234 | else | ||
1235 | mpc52xx_console_get_options(port, &baud, &parity, &bits, &flow); | ||
1236 | |||
1237 | pr_debug("Setting console parameters: %i %i%c1 flow=%c\n", | ||
1238 | baud, bits, parity, flow); | ||
1239 | |||
1240 | return uart_set_options(port, co, baud, parity, bits, flow); | ||
1241 | } | ||
1242 | |||
1243 | |||
1244 | static struct uart_driver mpc52xx_uart_driver; | ||
1245 | |||
1246 | static struct console mpc52xx_console = { | ||
1247 | .name = "ttyPSC", | ||
1248 | .write = mpc52xx_console_write, | ||
1249 | .device = uart_console_device, | ||
1250 | .setup = mpc52xx_console_setup, | ||
1251 | .flags = CON_PRINTBUFFER, | ||
1252 | .index = -1, /* Specified on the cmdline (e.g. console=ttyPSC0) */ | ||
1253 | .data = &mpc52xx_uart_driver, | ||
1254 | }; | ||
1255 | |||
1256 | |||
1257 | static int __init | ||
1258 | mpc52xx_console_init(void) | ||
1259 | { | ||
1260 | mpc52xx_uart_of_enumerate(); | ||
1261 | register_console(&mpc52xx_console); | ||
1262 | return 0; | ||
1263 | } | ||
1264 | |||
1265 | console_initcall(mpc52xx_console_init); | ||
1266 | |||
1267 | #define MPC52xx_PSC_CONSOLE &mpc52xx_console | ||
1268 | #else | ||
1269 | #define MPC52xx_PSC_CONSOLE NULL | ||
1270 | #endif | ||
1271 | |||
1272 | |||
1273 | /* ======================================================================== */ | ||
1274 | /* UART Driver */ | ||
1275 | /* ======================================================================== */ | ||
1276 | |||
1277 | static struct uart_driver mpc52xx_uart_driver = { | ||
1278 | .driver_name = "mpc52xx_psc_uart", | ||
1279 | .dev_name = "ttyPSC", | ||
1280 | .major = SERIAL_PSC_MAJOR, | ||
1281 | .minor = SERIAL_PSC_MINOR, | ||
1282 | .nr = MPC52xx_PSC_MAXNUM, | ||
1283 | .cons = MPC52xx_PSC_CONSOLE, | ||
1284 | }; | ||
1285 | |||
1286 | /* ======================================================================== */ | ||
1287 | /* OF Platform Driver */ | ||
1288 | /* ======================================================================== */ | ||
1289 | |||
1290 | static struct of_device_id mpc52xx_uart_of_match[] = { | ||
1291 | #ifdef CONFIG_PPC_MPC52xx | ||
1292 | { .compatible = "fsl,mpc5200b-psc-uart", .data = &mpc5200b_psc_ops, }, | ||
1293 | { .compatible = "fsl,mpc5200-psc-uart", .data = &mpc52xx_psc_ops, }, | ||
1294 | /* binding used by old lite5200 device trees: */ | ||
1295 | { .compatible = "mpc5200-psc-uart", .data = &mpc52xx_psc_ops, }, | ||
1296 | /* binding used by efika: */ | ||
1297 | { .compatible = "mpc5200-serial", .data = &mpc52xx_psc_ops, }, | ||
1298 | #endif | ||
1299 | #ifdef CONFIG_PPC_MPC512x | ||
1300 | { .compatible = "fsl,mpc5121-psc-uart", .data = &mpc512x_psc_ops, }, | ||
1301 | #endif | ||
1302 | {}, | ||
1303 | }; | ||
1304 | |||
1305 | static int __devinit | ||
1306 | mpc52xx_uart_of_probe(struct platform_device *op, const struct of_device_id *match) | ||
1307 | { | ||
1308 | int idx = -1; | ||
1309 | unsigned int uartclk; | ||
1310 | struct uart_port *port = NULL; | ||
1311 | struct resource res; | ||
1312 | int ret; | ||
1313 | |||
1314 | dev_dbg(&op->dev, "mpc52xx_uart_probe(op=%p, match=%p)\n", op, match); | ||
1315 | |||
1316 | /* Check validity & presence */ | ||
1317 | for (idx = 0; idx < MPC52xx_PSC_MAXNUM; idx++) | ||
1318 | if (mpc52xx_uart_nodes[idx] == op->dev.of_node) | ||
1319 | break; | ||
1320 | if (idx >= MPC52xx_PSC_MAXNUM) | ||
1321 | return -EINVAL; | ||
1322 | pr_debug("Found %s assigned to ttyPSC%x\n", | ||
1323 | mpc52xx_uart_nodes[idx]->full_name, idx); | ||
1324 | |||
1325 | /* set the uart clock to the input clock of the psc, the different | ||
1326 | * prescalers are taken into account in the set_baudrate() methods | ||
1327 | * of the respective chip */ | ||
1328 | uartclk = mpc5xxx_get_bus_frequency(op->dev.of_node); | ||
1329 | if (uartclk == 0) { | ||
1330 | dev_dbg(&op->dev, "Could not find uart clock frequency!\n"); | ||
1331 | return -EINVAL; | ||
1332 | } | ||
1333 | |||
1334 | /* Init the port structure */ | ||
1335 | port = &mpc52xx_uart_ports[idx]; | ||
1336 | |||
1337 | spin_lock_init(&port->lock); | ||
1338 | port->uartclk = uartclk; | ||
1339 | port->fifosize = 512; | ||
1340 | port->iotype = UPIO_MEM; | ||
1341 | port->flags = UPF_BOOT_AUTOCONF | | ||
1342 | (uart_console(port) ? 0 : UPF_IOREMAP); | ||
1343 | port->line = idx; | ||
1344 | port->ops = &mpc52xx_uart_ops; | ||
1345 | port->dev = &op->dev; | ||
1346 | |||
1347 | /* Search for IRQ and mapbase */ | ||
1348 | ret = of_address_to_resource(op->dev.of_node, 0, &res); | ||
1349 | if (ret) | ||
1350 | return ret; | ||
1351 | |||
1352 | port->mapbase = res.start; | ||
1353 | if (!port->mapbase) { | ||
1354 | dev_dbg(&op->dev, "Could not allocate resources for PSC\n"); | ||
1355 | return -EINVAL; | ||
1356 | } | ||
1357 | |||
1358 | psc_ops->get_irq(port, op->dev.of_node); | ||
1359 | if (port->irq == NO_IRQ) { | ||
1360 | dev_dbg(&op->dev, "Could not get irq\n"); | ||
1361 | return -EINVAL; | ||
1362 | } | ||
1363 | |||
1364 | dev_dbg(&op->dev, "mpc52xx-psc uart at %p, irq=%x, freq=%i\n", | ||
1365 | (void *)port->mapbase, port->irq, port->uartclk); | ||
1366 | |||
1367 | /* Add the port to the uart sub-system */ | ||
1368 | ret = uart_add_one_port(&mpc52xx_uart_driver, port); | ||
1369 | if (ret) | ||
1370 | return ret; | ||
1371 | |||
1372 | dev_set_drvdata(&op->dev, (void *)port); | ||
1373 | return 0; | ||
1374 | } | ||
1375 | |||
1376 | static int | ||
1377 | mpc52xx_uart_of_remove(struct platform_device *op) | ||
1378 | { | ||
1379 | struct uart_port *port = dev_get_drvdata(&op->dev); | ||
1380 | dev_set_drvdata(&op->dev, NULL); | ||
1381 | |||
1382 | if (port) | ||
1383 | uart_remove_one_port(&mpc52xx_uart_driver, port); | ||
1384 | |||
1385 | return 0; | ||
1386 | } | ||
1387 | |||
1388 | #ifdef CONFIG_PM | ||
1389 | static int | ||
1390 | mpc52xx_uart_of_suspend(struct platform_device *op, pm_message_t state) | ||
1391 | { | ||
1392 | struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev); | ||
1393 | |||
1394 | if (port) | ||
1395 | uart_suspend_port(&mpc52xx_uart_driver, port); | ||
1396 | |||
1397 | return 0; | ||
1398 | } | ||
1399 | |||
1400 | static int | ||
1401 | mpc52xx_uart_of_resume(struct platform_device *op) | ||
1402 | { | ||
1403 | struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev); | ||
1404 | |||
1405 | if (port) | ||
1406 | uart_resume_port(&mpc52xx_uart_driver, port); | ||
1407 | |||
1408 | return 0; | ||
1409 | } | ||
1410 | #endif | ||
1411 | |||
1412 | static void | ||
1413 | mpc52xx_uart_of_assign(struct device_node *np) | ||
1414 | { | ||
1415 | int i; | ||
1416 | |||
1417 | /* Find the first free PSC number */ | ||
1418 | for (i = 0; i < MPC52xx_PSC_MAXNUM; i++) { | ||
1419 | if (mpc52xx_uart_nodes[i] == NULL) { | ||
1420 | of_node_get(np); | ||
1421 | mpc52xx_uart_nodes[i] = np; | ||
1422 | return; | ||
1423 | } | ||
1424 | } | ||
1425 | } | ||
1426 | |||
1427 | static void | ||
1428 | mpc52xx_uart_of_enumerate(void) | ||
1429 | { | ||
1430 | static int enum_done; | ||
1431 | struct device_node *np; | ||
1432 | const struct of_device_id *match; | ||
1433 | int i; | ||
1434 | |||
1435 | if (enum_done) | ||
1436 | return; | ||
1437 | |||
1438 | /* Assign index to each PSC in device tree */ | ||
1439 | for_each_matching_node(np, mpc52xx_uart_of_match) { | ||
1440 | match = of_match_node(mpc52xx_uart_of_match, np); | ||
1441 | psc_ops = match->data; | ||
1442 | mpc52xx_uart_of_assign(np); | ||
1443 | } | ||
1444 | |||
1445 | enum_done = 1; | ||
1446 | |||
1447 | for (i = 0; i < MPC52xx_PSC_MAXNUM; i++) { | ||
1448 | if (mpc52xx_uart_nodes[i]) | ||
1449 | pr_debug("%s assigned to ttyPSC%x\n", | ||
1450 | mpc52xx_uart_nodes[i]->full_name, i); | ||
1451 | } | ||
1452 | } | ||
1453 | |||
1454 | MODULE_DEVICE_TABLE(of, mpc52xx_uart_of_match); | ||
1455 | |||
1456 | static struct of_platform_driver mpc52xx_uart_of_driver = { | ||
1457 | .probe = mpc52xx_uart_of_probe, | ||
1458 | .remove = mpc52xx_uart_of_remove, | ||
1459 | #ifdef CONFIG_PM | ||
1460 | .suspend = mpc52xx_uart_of_suspend, | ||
1461 | .resume = mpc52xx_uart_of_resume, | ||
1462 | #endif | ||
1463 | .driver = { | ||
1464 | .name = "mpc52xx-psc-uart", | ||
1465 | .owner = THIS_MODULE, | ||
1466 | .of_match_table = mpc52xx_uart_of_match, | ||
1467 | }, | ||
1468 | }; | ||
1469 | |||
1470 | |||
1471 | /* ======================================================================== */ | ||
1472 | /* Module */ | ||
1473 | /* ======================================================================== */ | ||
1474 | |||
1475 | static int __init | ||
1476 | mpc52xx_uart_init(void) | ||
1477 | { | ||
1478 | int ret; | ||
1479 | |||
1480 | printk(KERN_INFO "Serial: MPC52xx PSC UART driver\n"); | ||
1481 | |||
1482 | ret = uart_register_driver(&mpc52xx_uart_driver); | ||
1483 | if (ret) { | ||
1484 | printk(KERN_ERR "%s: uart_register_driver failed (%i)\n", | ||
1485 | __FILE__, ret); | ||
1486 | return ret; | ||
1487 | } | ||
1488 | |||
1489 | mpc52xx_uart_of_enumerate(); | ||
1490 | |||
1491 | /* | ||
1492 | * Map the PSC FIFO Controller and init if on MPC512x. | ||
1493 | */ | ||
1494 | if (psc_ops && psc_ops->fifoc_init) { | ||
1495 | ret = psc_ops->fifoc_init(); | ||
1496 | if (ret) | ||
1497 | return ret; | ||
1498 | } | ||
1499 | |||
1500 | ret = of_register_platform_driver(&mpc52xx_uart_of_driver); | ||
1501 | if (ret) { | ||
1502 | printk(KERN_ERR "%s: of_register_platform_driver failed (%i)\n", | ||
1503 | __FILE__, ret); | ||
1504 | uart_unregister_driver(&mpc52xx_uart_driver); | ||
1505 | return ret; | ||
1506 | } | ||
1507 | |||
1508 | return 0; | ||
1509 | } | ||
1510 | |||
1511 | static void __exit | ||
1512 | mpc52xx_uart_exit(void) | ||
1513 | { | ||
1514 | if (psc_ops->fifoc_uninit) | ||
1515 | psc_ops->fifoc_uninit(); | ||
1516 | |||
1517 | of_unregister_platform_driver(&mpc52xx_uart_of_driver); | ||
1518 | uart_unregister_driver(&mpc52xx_uart_driver); | ||
1519 | } | ||
1520 | |||
1521 | |||
1522 | module_init(mpc52xx_uart_init); | ||
1523 | module_exit(mpc52xx_uart_exit); | ||
1524 | |||
1525 | MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>"); | ||
1526 | MODULE_DESCRIPTION("Freescale MPC52xx PSC UART"); | ||
1527 | MODULE_LICENSE("GPL"); | ||