diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-07 12:02:26 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-07 12:02:26 -0500 |
commit | 37969581301e50872a1ae84dc73962b5f7ee6b76 (patch) | |
tree | 35bbd6a07f903f248f4bd209b8d194a922415fe0 /drivers/serial | |
parent | 80ff8a805113850a3ffafcc8e6eaa1fdd51b02f3 (diff) | |
parent | 24f1a849614ba1805e26a05da7cc8c6bd67490ea (diff) |
Merge branch 'for-2.6.25' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'for-2.6.25' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (69 commits)
[POWERPC] Add SPE registers to core dumps
[POWERPC] Use regset code for compat PTRACE_*REGS* calls
[POWERPC] Use generic compat_sys_ptrace
[POWERPC] Use generic compat_ptrace_request
[POWERPC] Use generic ptrace peekdata/pokedata
[POWERPC] Use regset code for PTRACE_*REGS* requests
[POWERPC] Switch to generic compat_binfmt_elf code
[POWERPC] Switch to using user_regset-based core dumps
[POWERPC] Add user_regset compat support
[POWERPC] Add user_regset_view definitions
[POWERPC] Use user_regset accessors for GPRs
[POWERPC] ptrace accessors for special regs MSR and TRAP
[POWERPC] Use user_regset accessors for SPE regs
[POWERPC] Use user_regset accessors for altivec regs
[POWERPC] Use user_regset accessors for FP regs
[POWERPC] mpc52xx: fix compile error introduce when rebasing patch
[POWERPC] 4xx: PCIe indirect DCR spinlock fix.
[POWERPC] Add missing native dcr dcr_ind_lock spinlock
[POWERPC] 4xx: Fix offset value on Warp board
[POWERPC] 4xx: Add 440EPx Sequoia ehci dts entry
...
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/Kconfig | 12 | ||||
-rw-r--r-- | drivers/serial/mpc52xx_uart.c | 424 | ||||
-rw-r--r-- | drivers/serial/uartlite.c | 53 |
3 files changed, 374 insertions, 115 deletions
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 50d6e2214ddf..84a054d7e986 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -1142,17 +1142,17 @@ config SERIAL_SGI_L1_CONSOLE | |||
1142 | say Y. Otherwise, say N. | 1142 | say Y. Otherwise, say N. |
1143 | 1143 | ||
1144 | config SERIAL_MPC52xx | 1144 | config SERIAL_MPC52xx |
1145 | tristate "Freescale MPC52xx family PSC serial support" | 1145 | tristate "Freescale MPC52xx/MPC512x family PSC serial support" |
1146 | depends on PPC_MPC52xx | 1146 | depends on PPC_MPC52xx || PPC_MPC512x |
1147 | select SERIAL_CORE | 1147 | select SERIAL_CORE |
1148 | help | 1148 | help |
1149 | This drivers support the MPC52xx PSC serial ports. If you would | 1149 | This driver supports MPC52xx and MPC512x PSC serial ports. If you would |
1150 | like to use them, you must answer Y or M to this option. Not that | 1150 | like to use them, you must answer Y or M to this option. Note that |
1151 | for use as console, it must be included in kernel and not as a | 1151 | for use as console, it must be included in kernel and not as a |
1152 | module. | 1152 | module. |
1153 | 1153 | ||
1154 | config SERIAL_MPC52xx_CONSOLE | 1154 | config SERIAL_MPC52xx_CONSOLE |
1155 | bool "Console on a Freescale MPC52xx family PSC serial port" | 1155 | bool "Console on a Freescale MPC52xx/MPC512x family PSC serial port" |
1156 | depends on SERIAL_MPC52xx=y | 1156 | depends on SERIAL_MPC52xx=y |
1157 | select SERIAL_CORE_CONSOLE | 1157 | select SERIAL_CORE_CONSOLE |
1158 | help | 1158 | help |
@@ -1160,7 +1160,7 @@ config SERIAL_MPC52xx_CONSOLE | |||
1160 | of the Freescale MPC52xx family as a console. | 1160 | of the Freescale MPC52xx family as a console. |
1161 | 1161 | ||
1162 | config SERIAL_MPC52xx_CONSOLE_BAUD | 1162 | config SERIAL_MPC52xx_CONSOLE_BAUD |
1163 | int "Freescale MPC52xx family PSC serial port baud" | 1163 | int "Freescale MPC52xx/MPC512x family PSC serial port baud" |
1164 | depends on SERIAL_MPC52xx_CONSOLE=y | 1164 | depends on SERIAL_MPC52xx_CONSOLE=y |
1165 | default "9600" | 1165 | default "9600" |
1166 | help | 1166 | help |
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 3c4d29e59b2c..a638f23c6c61 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c | |||
@@ -16,6 +16,9 @@ | |||
16 | * Some of the code has been inspired/copied from the 2.4 code written | 16 | * Some of the code has been inspired/copied from the 2.4 code written |
17 | * by Dale Farnsworth <dfarnsworth@mvista.com>. | 17 | * by Dale Farnsworth <dfarnsworth@mvista.com>. |
18 | * | 18 | * |
19 | * Copyright (C) 2008 Freescale Semiconductor Inc. | ||
20 | * John Rigby <jrigby@gmail.com> | ||
21 | * Added support for MPC5121 | ||
19 | * Copyright (C) 2006 Secret Lab Technologies Ltd. | 22 | * Copyright (C) 2006 Secret Lab Technologies Ltd. |
20 | * Grant Likely <grant.likely@secretlab.ca> | 23 | * Grant Likely <grant.likely@secretlab.ca> |
21 | * Copyright (C) 2004-2006 Sylvain Munaut <tnt@246tNt.com> | 24 | * Copyright (C) 2004-2006 Sylvain Munaut <tnt@246tNt.com> |
@@ -67,7 +70,6 @@ | |||
67 | #include <linux/serial.h> | 70 | #include <linux/serial.h> |
68 | #include <linux/sysrq.h> | 71 | #include <linux/sysrq.h> |
69 | #include <linux/console.h> | 72 | #include <linux/console.h> |
70 | |||
71 | #include <linux/delay.h> | 73 | #include <linux/delay.h> |
72 | #include <linux/io.h> | 74 | #include <linux/io.h> |
73 | 75 | ||
@@ -79,6 +81,7 @@ | |||
79 | #endif | 81 | #endif |
80 | 82 | ||
81 | #include <asm/mpc52xx.h> | 83 | #include <asm/mpc52xx.h> |
84 | #include <asm/mpc512x.h> | ||
82 | #include <asm/mpc52xx_psc.h> | 85 | #include <asm/mpc52xx_psc.h> |
83 | 86 | ||
84 | #if defined(CONFIG_SERIAL_MPC52xx_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) | 87 | #if defined(CONFIG_SERIAL_MPC52xx_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) |
@@ -111,8 +114,8 @@ static struct device_node *mpc52xx_uart_nodes[MPC52xx_PSC_MAXNUM]; | |||
111 | static void mpc52xx_uart_of_enumerate(void); | 114 | static void mpc52xx_uart_of_enumerate(void); |
112 | #endif | 115 | #endif |
113 | 116 | ||
117 | |||
114 | #define PSC(port) ((struct mpc52xx_psc __iomem *)((port)->membase)) | 118 | #define PSC(port) ((struct mpc52xx_psc __iomem *)((port)->membase)) |
115 | #define FIFO(port) ((struct mpc52xx_psc_fifo __iomem *)(PSC(port)+1)) | ||
116 | 119 | ||
117 | 120 | ||
118 | /* Forward declaration of the interruption handling routine */ | 121 | /* Forward declaration of the interruption handling routine */ |
@@ -128,15 +131,301 @@ static irqreturn_t mpc52xx_uart_int(int irq, void *dev_id); | |||
128 | #define uart_console(port) (0) | 131 | #define uart_console(port) (0) |
129 | #endif | 132 | #endif |
130 | 133 | ||
134 | /* ======================================================================== */ | ||
135 | /* PSC fifo operations for isolating differences between 52xx and 512x */ | ||
136 | /* ======================================================================== */ | ||
137 | |||
138 | struct psc_ops { | ||
139 | void (*fifo_init)(struct uart_port *port); | ||
140 | int (*raw_rx_rdy)(struct uart_port *port); | ||
141 | int (*raw_tx_rdy)(struct uart_port *port); | ||
142 | int (*rx_rdy)(struct uart_port *port); | ||
143 | int (*tx_rdy)(struct uart_port *port); | ||
144 | int (*tx_empty)(struct uart_port *port); | ||
145 | void (*stop_rx)(struct uart_port *port); | ||
146 | void (*start_tx)(struct uart_port *port); | ||
147 | void (*stop_tx)(struct uart_port *port); | ||
148 | void (*rx_clr_irq)(struct uart_port *port); | ||
149 | void (*tx_clr_irq)(struct uart_port *port); | ||
150 | void (*write_char)(struct uart_port *port, unsigned char c); | ||
151 | unsigned char (*read_char)(struct uart_port *port); | ||
152 | void (*cw_disable_ints)(struct uart_port *port); | ||
153 | void (*cw_restore_ints)(struct uart_port *port); | ||
154 | unsigned long (*getuartclk)(void *p); | ||
155 | }; | ||
156 | |||
157 | #ifdef CONFIG_PPC_MPC52xx | ||
158 | #define FIFO_52xx(port) ((struct mpc52xx_psc_fifo __iomem *)(PSC(port)+1)) | ||
159 | static void mpc52xx_psc_fifo_init(struct uart_port *port) | ||
160 | { | ||
161 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
162 | struct mpc52xx_psc_fifo __iomem *fifo = FIFO_52xx(port); | ||
163 | |||
164 | /* /32 prescaler */ | ||
165 | out_be16(&psc->mpc52xx_psc_clock_select, 0xdd00); | ||
166 | |||
167 | out_8(&fifo->rfcntl, 0x00); | ||
168 | out_be16(&fifo->rfalarm, 0x1ff); | ||
169 | out_8(&fifo->tfcntl, 0x07); | ||
170 | out_be16(&fifo->tfalarm, 0x80); | ||
171 | |||
172 | port->read_status_mask |= MPC52xx_PSC_IMR_RXRDY | MPC52xx_PSC_IMR_TXRDY; | ||
173 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | ||
174 | } | ||
175 | |||
176 | static int mpc52xx_psc_raw_rx_rdy(struct uart_port *port) | ||
177 | { | ||
178 | return in_be16(&PSC(port)->mpc52xx_psc_status) | ||
179 | & MPC52xx_PSC_SR_RXRDY; | ||
180 | } | ||
181 | |||
182 | static int mpc52xx_psc_raw_tx_rdy(struct uart_port *port) | ||
183 | { | ||
184 | return in_be16(&PSC(port)->mpc52xx_psc_status) | ||
185 | & MPC52xx_PSC_SR_TXRDY; | ||
186 | } | ||
187 | |||
188 | |||
189 | static int mpc52xx_psc_rx_rdy(struct uart_port *port) | ||
190 | { | ||
191 | return in_be16(&PSC(port)->mpc52xx_psc_isr) | ||
192 | & port->read_status_mask | ||
193 | & MPC52xx_PSC_IMR_RXRDY; | ||
194 | } | ||
195 | |||
196 | static int mpc52xx_psc_tx_rdy(struct uart_port *port) | ||
197 | { | ||
198 | return in_be16(&PSC(port)->mpc52xx_psc_isr) | ||
199 | & port->read_status_mask | ||
200 | & MPC52xx_PSC_IMR_TXRDY; | ||
201 | } | ||
202 | |||
203 | static int mpc52xx_psc_tx_empty(struct uart_port *port) | ||
204 | { | ||
205 | return in_be16(&PSC(port)->mpc52xx_psc_status) | ||
206 | & MPC52xx_PSC_SR_TXEMP; | ||
207 | } | ||
208 | |||
209 | static void mpc52xx_psc_start_tx(struct uart_port *port) | ||
210 | { | ||
211 | port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY; | ||
212 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
213 | } | ||
214 | |||
215 | static void mpc52xx_psc_stop_tx(struct uart_port *port) | ||
216 | { | ||
217 | port->read_status_mask &= ~MPC52xx_PSC_IMR_TXRDY; | ||
218 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
219 | } | ||
220 | |||
221 | static void mpc52xx_psc_stop_rx(struct uart_port *port) | ||
222 | { | ||
223 | port->read_status_mask &= ~MPC52xx_PSC_IMR_RXRDY; | ||
224 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
225 | } | ||
226 | |||
227 | static void mpc52xx_psc_rx_clr_irq(struct uart_port *port) | ||
228 | { | ||
229 | } | ||
230 | |||
231 | static void mpc52xx_psc_tx_clr_irq(struct uart_port *port) | ||
232 | { | ||
233 | } | ||
234 | |||
235 | static void mpc52xx_psc_write_char(struct uart_port *port, unsigned char c) | ||
236 | { | ||
237 | out_8(&PSC(port)->mpc52xx_psc_buffer_8, c); | ||
238 | } | ||
239 | |||
240 | static unsigned char mpc52xx_psc_read_char(struct uart_port *port) | ||
241 | { | ||
242 | return in_8(&PSC(port)->mpc52xx_psc_buffer_8); | ||
243 | } | ||
244 | |||
245 | static void mpc52xx_psc_cw_disable_ints(struct uart_port *port) | ||
246 | { | ||
247 | out_be16(&PSC(port)->mpc52xx_psc_imr, 0); | ||
248 | } | ||
249 | |||
250 | static void mpc52xx_psc_cw_restore_ints(struct uart_port *port) | ||
251 | { | ||
252 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
253 | } | ||
254 | |||
255 | /* Search for bus-frequency property in this node or a parent */ | ||
256 | static unsigned long mpc52xx_getuartclk(void *p) | ||
257 | { | ||
131 | #if defined(CONFIG_PPC_MERGE) | 258 | #if defined(CONFIG_PPC_MERGE) |
132 | static struct of_device_id mpc52xx_uart_of_match[] = { | 259 | /* |
133 | { .type = "serial", .compatible = "fsl,mpc5200-psc-uart", }, | 260 | * 5200 UARTs have a / 32 prescaler |
134 | { .type = "serial", .compatible = "mpc5200-psc-uart", }, /* lite5200 */ | 261 | * but the generic serial code assumes 16 |
135 | { .type = "serial", .compatible = "mpc5200-serial", }, /* efika */ | 262 | * so return ipb freq / 2 |
136 | {}, | 263 | */ |
264 | return mpc52xx_find_ipb_freq(p) / 2; | ||
265 | #else | ||
266 | pr_debug("unexpected call to mpc52xx_getuartclk with arch/ppc\n"); | ||
267 | return NULL; | ||
268 | #endif | ||
269 | } | ||
270 | |||
271 | static struct psc_ops mpc52xx_psc_ops = { | ||
272 | .fifo_init = mpc52xx_psc_fifo_init, | ||
273 | .raw_rx_rdy = mpc52xx_psc_raw_rx_rdy, | ||
274 | .raw_tx_rdy = mpc52xx_psc_raw_tx_rdy, | ||
275 | .rx_rdy = mpc52xx_psc_rx_rdy, | ||
276 | .tx_rdy = mpc52xx_psc_tx_rdy, | ||
277 | .tx_empty = mpc52xx_psc_tx_empty, | ||
278 | .stop_rx = mpc52xx_psc_stop_rx, | ||
279 | .start_tx = mpc52xx_psc_start_tx, | ||
280 | .stop_tx = mpc52xx_psc_stop_tx, | ||
281 | .rx_clr_irq = mpc52xx_psc_rx_clr_irq, | ||
282 | .tx_clr_irq = mpc52xx_psc_tx_clr_irq, | ||
283 | .write_char = mpc52xx_psc_write_char, | ||
284 | .read_char = mpc52xx_psc_read_char, | ||
285 | .cw_disable_ints = mpc52xx_psc_cw_disable_ints, | ||
286 | .cw_restore_ints = mpc52xx_psc_cw_restore_ints, | ||
287 | .getuartclk = mpc52xx_getuartclk, | ||
288 | }; | ||
289 | |||
290 | #endif /* CONFIG_MPC52xx */ | ||
291 | |||
292 | #ifdef CONFIG_PPC_MPC512x | ||
293 | #define FIFO_512x(port) ((struct mpc512x_psc_fifo __iomem *)(PSC(port)+1)) | ||
294 | static void mpc512x_psc_fifo_init(struct uart_port *port) | ||
295 | { | ||
296 | out_be32(&FIFO_512x(port)->txcmd, MPC512x_PSC_FIFO_RESET_SLICE); | ||
297 | out_be32(&FIFO_512x(port)->txcmd, MPC512x_PSC_FIFO_ENABLE_SLICE); | ||
298 | out_be32(&FIFO_512x(port)->txalarm, 1); | ||
299 | out_be32(&FIFO_512x(port)->tximr, 0); | ||
300 | |||
301 | out_be32(&FIFO_512x(port)->rxcmd, MPC512x_PSC_FIFO_RESET_SLICE); | ||
302 | out_be32(&FIFO_512x(port)->rxcmd, MPC512x_PSC_FIFO_ENABLE_SLICE); | ||
303 | out_be32(&FIFO_512x(port)->rxalarm, 1); | ||
304 | out_be32(&FIFO_512x(port)->rximr, 0); | ||
305 | |||
306 | out_be32(&FIFO_512x(port)->tximr, MPC512x_PSC_FIFO_ALARM); | ||
307 | out_be32(&FIFO_512x(port)->rximr, MPC512x_PSC_FIFO_ALARM); | ||
308 | } | ||
309 | |||
310 | static int mpc512x_psc_raw_rx_rdy(struct uart_port *port) | ||
311 | { | ||
312 | return !(in_be32(&FIFO_512x(port)->rxsr) & MPC512x_PSC_FIFO_EMPTY); | ||
313 | } | ||
314 | |||
315 | static int mpc512x_psc_raw_tx_rdy(struct uart_port *port) | ||
316 | { | ||
317 | return !(in_be32(&FIFO_512x(port)->txsr) & MPC512x_PSC_FIFO_FULL); | ||
318 | } | ||
319 | |||
320 | static int mpc512x_psc_rx_rdy(struct uart_port *port) | ||
321 | { | ||
322 | return in_be32(&FIFO_512x(port)->rxsr) | ||
323 | & in_be32(&FIFO_512x(port)->rximr) | ||
324 | & MPC512x_PSC_FIFO_ALARM; | ||
325 | } | ||
326 | |||
327 | static int mpc512x_psc_tx_rdy(struct uart_port *port) | ||
328 | { | ||
329 | return in_be32(&FIFO_512x(port)->txsr) | ||
330 | & in_be32(&FIFO_512x(port)->tximr) | ||
331 | & MPC512x_PSC_FIFO_ALARM; | ||
332 | } | ||
333 | |||
334 | static int mpc512x_psc_tx_empty(struct uart_port *port) | ||
335 | { | ||
336 | return in_be32(&FIFO_512x(port)->txsr) | ||
337 | & MPC512x_PSC_FIFO_EMPTY; | ||
338 | } | ||
339 | |||
340 | static void mpc512x_psc_stop_rx(struct uart_port *port) | ||
341 | { | ||
342 | unsigned long rx_fifo_imr; | ||
343 | |||
344 | rx_fifo_imr = in_be32(&FIFO_512x(port)->rximr); | ||
345 | rx_fifo_imr &= ~MPC512x_PSC_FIFO_ALARM; | ||
346 | out_be32(&FIFO_512x(port)->rximr, rx_fifo_imr); | ||
347 | } | ||
348 | |||
349 | static void mpc512x_psc_start_tx(struct uart_port *port) | ||
350 | { | ||
351 | unsigned long tx_fifo_imr; | ||
352 | |||
353 | tx_fifo_imr = in_be32(&FIFO_512x(port)->tximr); | ||
354 | tx_fifo_imr |= MPC512x_PSC_FIFO_ALARM; | ||
355 | out_be32(&FIFO_512x(port)->tximr, tx_fifo_imr); | ||
356 | } | ||
357 | |||
358 | static void mpc512x_psc_stop_tx(struct uart_port *port) | ||
359 | { | ||
360 | unsigned long tx_fifo_imr; | ||
361 | |||
362 | tx_fifo_imr = in_be32(&FIFO_512x(port)->tximr); | ||
363 | tx_fifo_imr &= ~MPC512x_PSC_FIFO_ALARM; | ||
364 | out_be32(&FIFO_512x(port)->tximr, tx_fifo_imr); | ||
365 | } | ||
366 | |||
367 | static void mpc512x_psc_rx_clr_irq(struct uart_port *port) | ||
368 | { | ||
369 | out_be32(&FIFO_512x(port)->rxisr, in_be32(&FIFO_512x(port)->rxisr)); | ||
370 | } | ||
371 | |||
372 | static void mpc512x_psc_tx_clr_irq(struct uart_port *port) | ||
373 | { | ||
374 | out_be32(&FIFO_512x(port)->txisr, in_be32(&FIFO_512x(port)->txisr)); | ||
375 | } | ||
376 | |||
377 | static void mpc512x_psc_write_char(struct uart_port *port, unsigned char c) | ||
378 | { | ||
379 | out_8(&FIFO_512x(port)->txdata_8, c); | ||
380 | } | ||
381 | |||
382 | static unsigned char mpc512x_psc_read_char(struct uart_port *port) | ||
383 | { | ||
384 | return in_8(&FIFO_512x(port)->rxdata_8); | ||
385 | } | ||
386 | |||
387 | static void mpc512x_psc_cw_disable_ints(struct uart_port *port) | ||
388 | { | ||
389 | port->read_status_mask = | ||
390 | in_be32(&FIFO_512x(port)->tximr) << 16 | | ||
391 | in_be32(&FIFO_512x(port)->rximr); | ||
392 | out_be32(&FIFO_512x(port)->tximr, 0); | ||
393 | out_be32(&FIFO_512x(port)->rximr, 0); | ||
394 | } | ||
395 | |||
396 | static void mpc512x_psc_cw_restore_ints(struct uart_port *port) | ||
397 | { | ||
398 | out_be32(&FIFO_512x(port)->tximr, | ||
399 | (port->read_status_mask >> 16) & 0x7f); | ||
400 | out_be32(&FIFO_512x(port)->rximr, port->read_status_mask & 0x7f); | ||
401 | } | ||
402 | |||
403 | static unsigned long mpc512x_getuartclk(void *p) | ||
404 | { | ||
405 | return mpc512x_find_ips_freq(p); | ||
406 | } | ||
407 | |||
408 | static struct psc_ops mpc512x_psc_ops = { | ||
409 | .fifo_init = mpc512x_psc_fifo_init, | ||
410 | .raw_rx_rdy = mpc512x_psc_raw_rx_rdy, | ||
411 | .raw_tx_rdy = mpc512x_psc_raw_tx_rdy, | ||
412 | .rx_rdy = mpc512x_psc_rx_rdy, | ||
413 | .tx_rdy = mpc512x_psc_tx_rdy, | ||
414 | .tx_empty = mpc512x_psc_tx_empty, | ||
415 | .stop_rx = mpc512x_psc_stop_rx, | ||
416 | .start_tx = mpc512x_psc_start_tx, | ||
417 | .stop_tx = mpc512x_psc_stop_tx, | ||
418 | .rx_clr_irq = mpc512x_psc_rx_clr_irq, | ||
419 | .tx_clr_irq = mpc512x_psc_tx_clr_irq, | ||
420 | .write_char = mpc512x_psc_write_char, | ||
421 | .read_char = mpc512x_psc_read_char, | ||
422 | .cw_disable_ints = mpc512x_psc_cw_disable_ints, | ||
423 | .cw_restore_ints = mpc512x_psc_cw_restore_ints, | ||
424 | .getuartclk = mpc512x_getuartclk, | ||
137 | }; | 425 | }; |
138 | #endif | 426 | #endif |
139 | 427 | ||
428 | static struct psc_ops *psc_ops; | ||
140 | 429 | ||
141 | /* ======================================================================== */ | 430 | /* ======================================================================== */ |
142 | /* UART operations */ | 431 | /* UART operations */ |
@@ -145,8 +434,7 @@ static struct of_device_id mpc52xx_uart_of_match[] = { | |||
145 | static unsigned int | 434 | static unsigned int |
146 | mpc52xx_uart_tx_empty(struct uart_port *port) | 435 | mpc52xx_uart_tx_empty(struct uart_port *port) |
147 | { | 436 | { |
148 | int status = in_be16(&PSC(port)->mpc52xx_psc_status); | 437 | return psc_ops->tx_empty(port) ? TIOCSER_TEMT : 0; |
149 | return (status & MPC52xx_PSC_SR_TXEMP) ? TIOCSER_TEMT : 0; | ||
150 | } | 438 | } |
151 | 439 | ||
152 | static void | 440 | static void |
@@ -166,16 +454,14 @@ static void | |||
166 | mpc52xx_uart_stop_tx(struct uart_port *port) | 454 | mpc52xx_uart_stop_tx(struct uart_port *port) |
167 | { | 455 | { |
168 | /* port->lock taken by caller */ | 456 | /* port->lock taken by caller */ |
169 | port->read_status_mask &= ~MPC52xx_PSC_IMR_TXRDY; | 457 | psc_ops->stop_tx(port); |
170 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
171 | } | 458 | } |
172 | 459 | ||
173 | static void | 460 | static void |
174 | mpc52xx_uart_start_tx(struct uart_port *port) | 461 | mpc52xx_uart_start_tx(struct uart_port *port) |
175 | { | 462 | { |
176 | /* port->lock taken by caller */ | 463 | /* port->lock taken by caller */ |
177 | port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY; | 464 | psc_ops->start_tx(port); |
178 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
179 | } | 465 | } |
180 | 466 | ||
181 | static void | 467 | static void |
@@ -188,8 +474,7 @@ mpc52xx_uart_send_xchar(struct uart_port *port, char ch) | |||
188 | if (ch) { | 474 | if (ch) { |
189 | /* Make sure tx interrupts are on */ | 475 | /* Make sure tx interrupts are on */ |
190 | /* Truly necessary ??? They should be anyway */ | 476 | /* Truly necessary ??? They should be anyway */ |
191 | port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY; | 477 | psc_ops->start_tx(port); |
192 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
193 | } | 478 | } |
194 | 479 | ||
195 | spin_unlock_irqrestore(&port->lock, flags); | 480 | spin_unlock_irqrestore(&port->lock, flags); |
@@ -199,8 +484,7 @@ static void | |||
199 | mpc52xx_uart_stop_rx(struct uart_port *port) | 484 | mpc52xx_uart_stop_rx(struct uart_port *port) |
200 | { | 485 | { |
201 | /* port->lock taken by caller */ | 486 | /* port->lock taken by caller */ |
202 | port->read_status_mask &= ~MPC52xx_PSC_IMR_RXRDY; | 487 | psc_ops->stop_rx(port); |
203 | out_be16(&PSC(port)->mpc52xx_psc_imr, port->read_status_mask); | ||
204 | } | 488 | } |
205 | 489 | ||
206 | static void | 490 | static void |
@@ -227,12 +511,12 @@ static int | |||
227 | mpc52xx_uart_startup(struct uart_port *port) | 511 | mpc52xx_uart_startup(struct uart_port *port) |
228 | { | 512 | { |
229 | struct mpc52xx_psc __iomem *psc = PSC(port); | 513 | struct mpc52xx_psc __iomem *psc = PSC(port); |
230 | struct mpc52xx_psc_fifo __iomem *fifo = FIFO(port); | ||
231 | int ret; | 514 | int ret; |
232 | 515 | ||
233 | /* Request IRQ */ | 516 | /* Request IRQ */ |
234 | ret = request_irq(port->irq, mpc52xx_uart_int, | 517 | ret = request_irq(port->irq, mpc52xx_uart_int, |
235 | IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "mpc52xx_psc_uart", port); | 518 | IRQF_DISABLED | IRQF_SAMPLE_RANDOM | IRQF_SHARED, |
519 | "mpc52xx_psc_uart", port); | ||
236 | if (ret) | 520 | if (ret) |
237 | return ret; | 521 | return ret; |
238 | 522 | ||
@@ -242,15 +526,7 @@ mpc52xx_uart_startup(struct uart_port *port) | |||
242 | 526 | ||
243 | out_be32(&psc->sicr, 0); /* UART mode DCD ignored */ | 527 | out_be32(&psc->sicr, 0); /* UART mode DCD ignored */ |
244 | 528 | ||
245 | out_be16(&psc->mpc52xx_psc_clock_select, 0xdd00); /* /16 prescaler on */ | 529 | psc_ops->fifo_init(port); |
246 | |||
247 | out_8(&fifo->rfcntl, 0x00); | ||
248 | out_be16(&fifo->rfalarm, 0x1ff); | ||
249 | out_8(&fifo->tfcntl, 0x07); | ||
250 | out_be16(&fifo->tfalarm, 0x80); | ||
251 | |||
252 | port->read_status_mask |= MPC52xx_PSC_IMR_RXRDY | MPC52xx_PSC_IMR_TXRDY; | ||
253 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | ||
254 | 530 | ||
255 | out_8(&psc->command, MPC52xx_PSC_TX_ENABLE); | 531 | out_8(&psc->command, MPC52xx_PSC_TX_ENABLE); |
256 | out_8(&psc->command, MPC52xx_PSC_RX_ENABLE); | 532 | out_8(&psc->command, MPC52xx_PSC_RX_ENABLE); |
@@ -333,8 +609,7 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, | |||
333 | * boot for the console, all stuff is not yet ready to receive at that | 609 | * boot for the console, all stuff is not yet ready to receive at that |
334 | * time and that just makes the kernel oops */ | 610 | * time and that just makes the kernel oops */ |
335 | /* while (j-- && mpc52xx_uart_int_rx_chars(port)); */ | 611 | /* while (j-- && mpc52xx_uart_int_rx_chars(port)); */ |
336 | while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) && | 612 | while (!mpc52xx_uart_tx_empty(port) && --j) |
337 | --j) | ||
338 | udelay(1); | 613 | udelay(1); |
339 | 614 | ||
340 | if (!j) | 615 | if (!j) |
@@ -462,11 +737,9 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port) | |||
462 | unsigned short status; | 737 | unsigned short status; |
463 | 738 | ||
464 | /* While we can read, do so ! */ | 739 | /* While we can read, do so ! */ |
465 | while ((status = in_be16(&PSC(port)->mpc52xx_psc_status)) & | 740 | while (psc_ops->raw_rx_rdy(port)) { |
466 | MPC52xx_PSC_SR_RXRDY) { | ||
467 | |||
468 | /* Get the char */ | 741 | /* Get the char */ |
469 | ch = in_8(&PSC(port)->mpc52xx_psc_buffer_8); | 742 | ch = psc_ops->read_char(port); |
470 | 743 | ||
471 | /* Handle sysreq char */ | 744 | /* Handle sysreq char */ |
472 | #ifdef SUPPORT_SYSRQ | 745 | #ifdef SUPPORT_SYSRQ |
@@ -481,6 +754,8 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port) | |||
481 | flag = TTY_NORMAL; | 754 | flag = TTY_NORMAL; |
482 | port->icount.rx++; | 755 | port->icount.rx++; |
483 | 756 | ||
757 | status = in_be16(&PSC(port)->mpc52xx_psc_status); | ||
758 | |||
484 | if (status & (MPC52xx_PSC_SR_PE | | 759 | if (status & (MPC52xx_PSC_SR_PE | |
485 | MPC52xx_PSC_SR_FE | | 760 | MPC52xx_PSC_SR_FE | |
486 | MPC52xx_PSC_SR_RB)) { | 761 | MPC52xx_PSC_SR_RB)) { |
@@ -510,7 +785,7 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port) | |||
510 | 785 | ||
511 | tty_flip_buffer_push(tty); | 786 | tty_flip_buffer_push(tty); |
512 | 787 | ||
513 | return in_be16(&PSC(port)->mpc52xx_psc_status) & MPC52xx_PSC_SR_RXRDY; | 788 | return psc_ops->raw_rx_rdy(port); |
514 | } | 789 | } |
515 | 790 | ||
516 | static inline int | 791 | static inline int |
@@ -520,7 +795,7 @@ mpc52xx_uart_int_tx_chars(struct uart_port *port) | |||
520 | 795 | ||
521 | /* Process out of band chars */ | 796 | /* Process out of band chars */ |
522 | if (port->x_char) { | 797 | if (port->x_char) { |
523 | out_8(&PSC(port)->mpc52xx_psc_buffer_8, port->x_char); | 798 | psc_ops->write_char(port, port->x_char); |
524 | port->icount.tx++; | 799 | port->icount.tx++; |
525 | port->x_char = 0; | 800 | port->x_char = 0; |
526 | return 1; | 801 | return 1; |
@@ -533,8 +808,8 @@ mpc52xx_uart_int_tx_chars(struct uart_port *port) | |||
533 | } | 808 | } |
534 | 809 | ||
535 | /* Send chars */ | 810 | /* Send chars */ |
536 | while (in_be16(&PSC(port)->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXRDY) { | 811 | while (psc_ops->raw_tx_rdy(port)) { |
537 | out_8(&PSC(port)->mpc52xx_psc_buffer_8, xmit->buf[xmit->tail]); | 812 | psc_ops->write_char(port, xmit->buf[xmit->tail]); |
538 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | 813 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); |
539 | port->icount.tx++; | 814 | port->icount.tx++; |
540 | if (uart_circ_empty(xmit)) | 815 | if (uart_circ_empty(xmit)) |
@@ -560,7 +835,6 @@ mpc52xx_uart_int(int irq, void *dev_id) | |||
560 | struct uart_port *port = dev_id; | 835 | struct uart_port *port = dev_id; |
561 | unsigned long pass = ISR_PASS_LIMIT; | 836 | unsigned long pass = ISR_PASS_LIMIT; |
562 | unsigned int keepgoing; | 837 | unsigned int keepgoing; |
563 | unsigned short status; | ||
564 | 838 | ||
565 | spin_lock(&port->lock); | 839 | spin_lock(&port->lock); |
566 | 840 | ||
@@ -569,18 +843,12 @@ mpc52xx_uart_int(int irq, void *dev_id) | |||
569 | /* If we don't find anything to do, we stop */ | 843 | /* If we don't find anything to do, we stop */ |
570 | keepgoing = 0; | 844 | keepgoing = 0; |
571 | 845 | ||
572 | /* Read status */ | 846 | psc_ops->rx_clr_irq(port); |
573 | status = in_be16(&PSC(port)->mpc52xx_psc_isr); | 847 | if (psc_ops->rx_rdy(port)) |
574 | status &= port->read_status_mask; | ||
575 | |||
576 | /* Do we need to receive chars ? */ | ||
577 | /* For this RX interrupts must be on and some chars waiting */ | ||
578 | if (status & MPC52xx_PSC_IMR_RXRDY) | ||
579 | keepgoing |= mpc52xx_uart_int_rx_chars(port); | 848 | keepgoing |= mpc52xx_uart_int_rx_chars(port); |
580 | 849 | ||
581 | /* Do we need to send chars ? */ | 850 | psc_ops->tx_clr_irq(port); |
582 | /* For this, TX must be ready and TX interrupt enabled */ | 851 | if (psc_ops->tx_rdy(port)) |
583 | if (status & MPC52xx_PSC_IMR_TXRDY) | ||
584 | keepgoing |= mpc52xx_uart_int_tx_chars(port); | 852 | keepgoing |= mpc52xx_uart_int_tx_chars(port); |
585 | 853 | ||
586 | /* Limit number of iteration */ | 854 | /* Limit number of iteration */ |
@@ -647,36 +915,33 @@ static void | |||
647 | mpc52xx_console_write(struct console *co, const char *s, unsigned int count) | 915 | mpc52xx_console_write(struct console *co, const char *s, unsigned int count) |
648 | { | 916 | { |
649 | struct uart_port *port = &mpc52xx_uart_ports[co->index]; | 917 | struct uart_port *port = &mpc52xx_uart_ports[co->index]; |
650 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
651 | unsigned int i, j; | 918 | unsigned int i, j; |
652 | 919 | ||
653 | /* Disable interrupts */ | 920 | /* Disable interrupts */ |
654 | out_be16(&psc->mpc52xx_psc_imr, 0); | 921 | psc_ops->cw_disable_ints(port); |
655 | 922 | ||
656 | /* Wait the TX buffer to be empty */ | 923 | /* Wait the TX buffer to be empty */ |
657 | j = 5000000; /* Maximum wait */ | 924 | j = 5000000; /* Maximum wait */ |
658 | while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) && | 925 | while (!mpc52xx_uart_tx_empty(port) && --j) |
659 | --j) | ||
660 | udelay(1); | 926 | udelay(1); |
661 | 927 | ||
662 | /* Write all the chars */ | 928 | /* Write all the chars */ |
663 | for (i = 0; i < count; i++, s++) { | 929 | for (i = 0; i < count; i++, s++) { |
664 | /* Line return handling */ | 930 | /* Line return handling */ |
665 | if (*s == '\n') | 931 | if (*s == '\n') |
666 | out_8(&psc->mpc52xx_psc_buffer_8, '\r'); | 932 | psc_ops->write_char(port, '\r'); |
667 | 933 | ||
668 | /* Send the char */ | 934 | /* Send the char */ |
669 | out_8(&psc->mpc52xx_psc_buffer_8, *s); | 935 | psc_ops->write_char(port, *s); |
670 | 936 | ||
671 | /* Wait the TX buffer to be empty */ | 937 | /* Wait the TX buffer to be empty */ |
672 | j = 20000; /* Maximum wait */ | 938 | j = 20000; /* Maximum wait */ |
673 | while (!(in_be16(&psc->mpc52xx_psc_status) & | 939 | while (!mpc52xx_uart_tx_empty(port) && --j) |
674 | MPC52xx_PSC_SR_TXEMP) && --j) | ||
675 | udelay(1); | 940 | udelay(1); |
676 | } | 941 | } |
677 | 942 | ||
678 | /* Restore interrupt state */ | 943 | /* Restore interrupt state */ |
679 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | 944 | psc_ops->cw_restore_ints(port); |
680 | } | 945 | } |
681 | 946 | ||
682 | #if !defined(CONFIG_PPC_MERGE) | 947 | #if !defined(CONFIG_PPC_MERGE) |
@@ -721,7 +986,7 @@ mpc52xx_console_setup(struct console *co, char *options) | |||
721 | { | 986 | { |
722 | struct uart_port *port = &mpc52xx_uart_ports[co->index]; | 987 | struct uart_port *port = &mpc52xx_uart_ports[co->index]; |
723 | struct device_node *np = mpc52xx_uart_nodes[co->index]; | 988 | struct device_node *np = mpc52xx_uart_nodes[co->index]; |
724 | unsigned int ipb_freq; | 989 | unsigned int uartclk; |
725 | struct resource res; | 990 | struct resource res; |
726 | int ret; | 991 | int ret; |
727 | 992 | ||
@@ -753,17 +1018,16 @@ mpc52xx_console_setup(struct console *co, char *options) | |||
753 | return ret; | 1018 | return ret; |
754 | } | 1019 | } |
755 | 1020 | ||
756 | /* Search for bus-frequency property in this node or a parent */ | 1021 | uartclk = psc_ops->getuartclk(np); |
757 | ipb_freq = mpc52xx_find_ipb_freq(np); | 1022 | if (uartclk == 0) { |
758 | if (ipb_freq == 0) { | 1023 | pr_debug("Could not find uart clock frequency!\n"); |
759 | pr_debug("Could not find IPB bus frequency!\n"); | ||
760 | return -EINVAL; | 1024 | return -EINVAL; |
761 | } | 1025 | } |
762 | 1026 | ||
763 | /* Basic port init. Needed since we use some uart_??? func before | 1027 | /* Basic port init. Needed since we use some uart_??? func before |
764 | * real init for early access */ | 1028 | * real init for early access */ |
765 | spin_lock_init(&port->lock); | 1029 | spin_lock_init(&port->lock); |
766 | port->uartclk = ipb_freq / 2; | 1030 | port->uartclk = uartclk; |
767 | port->ops = &mpc52xx_uart_ops; | 1031 | port->ops = &mpc52xx_uart_ops; |
768 | port->mapbase = res.start; | 1032 | port->mapbase = res.start; |
769 | port->membase = ioremap(res.start, sizeof(struct mpc52xx_psc)); | 1033 | port->membase = ioremap(res.start, sizeof(struct mpc52xx_psc)); |
@@ -945,11 +1209,25 @@ static struct platform_driver mpc52xx_uart_platform_driver = { | |||
945 | /* OF Platform Driver */ | 1209 | /* OF Platform Driver */ |
946 | /* ======================================================================== */ | 1210 | /* ======================================================================== */ |
947 | 1211 | ||
1212 | static struct of_device_id mpc52xx_uart_of_match[] = { | ||
1213 | #ifdef CONFIG_PPC_MPC52xx | ||
1214 | { .compatible = "fsl,mpc5200-psc-uart", .data = &mpc52xx_psc_ops, }, | ||
1215 | /* binding used by old lite5200 device trees: */ | ||
1216 | { .compatible = "mpc5200-psc-uart", .data = &mpc52xx_psc_ops, }, | ||
1217 | /* binding used by efika: */ | ||
1218 | { .compatible = "mpc5200-serial", .data = &mpc52xx_psc_ops, }, | ||
1219 | #endif | ||
1220 | #ifdef CONFIG_PPC_MPC512x | ||
1221 | { .compatible = "fsl,mpc5121-psc-uart", .data = &mpc512x_psc_ops, }, | ||
1222 | {}, | ||
1223 | #endif | ||
1224 | }; | ||
1225 | |||
948 | static int __devinit | 1226 | static int __devinit |
949 | mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) | 1227 | mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) |
950 | { | 1228 | { |
951 | int idx = -1; | 1229 | int idx = -1; |
952 | unsigned int ipb_freq; | 1230 | unsigned int uartclk; |
953 | struct uart_port *port = NULL; | 1231 | struct uart_port *port = NULL; |
954 | struct resource res; | 1232 | struct resource res; |
955 | int ret; | 1233 | int ret; |
@@ -965,10 +1243,9 @@ mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) | |||
965 | pr_debug("Found %s assigned to ttyPSC%x\n", | 1243 | pr_debug("Found %s assigned to ttyPSC%x\n", |
966 | mpc52xx_uart_nodes[idx]->full_name, idx); | 1244 | mpc52xx_uart_nodes[idx]->full_name, idx); |
967 | 1245 | ||
968 | /* Search for bus-frequency property in this node or a parent */ | 1246 | uartclk = psc_ops->getuartclk(op->node); |
969 | ipb_freq = mpc52xx_find_ipb_freq(op->node); | 1247 | if (uartclk == 0) { |
970 | if (ipb_freq == 0) { | 1248 | dev_dbg(&op->dev, "Could not find uart clock frequency!\n"); |
971 | dev_dbg(&op->dev, "Could not find IPB bus frequency!\n"); | ||
972 | return -EINVAL; | 1249 | return -EINVAL; |
973 | } | 1250 | } |
974 | 1251 | ||
@@ -976,7 +1253,7 @@ mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) | |||
976 | port = &mpc52xx_uart_ports[idx]; | 1253 | port = &mpc52xx_uart_ports[idx]; |
977 | 1254 | ||
978 | spin_lock_init(&port->lock); | 1255 | spin_lock_init(&port->lock); |
979 | port->uartclk = ipb_freq / 2; | 1256 | port->uartclk = uartclk; |
980 | port->fifosize = 512; | 1257 | port->fifosize = 512; |
981 | port->iotype = UPIO_MEM; | 1258 | port->iotype = UPIO_MEM; |
982 | port->flags = UPF_BOOT_AUTOCONF | | 1259 | port->flags = UPF_BOOT_AUTOCONF | |
@@ -1080,15 +1357,19 @@ mpc52xx_uart_of_enumerate(void) | |||
1080 | static int enum_done; | 1357 | static int enum_done; |
1081 | struct device_node *np; | 1358 | struct device_node *np; |
1082 | const unsigned int *devno; | 1359 | const unsigned int *devno; |
1360 | const struct of_device_id *match; | ||
1083 | int i; | 1361 | int i; |
1084 | 1362 | ||
1085 | if (enum_done) | 1363 | if (enum_done) |
1086 | return; | 1364 | return; |
1087 | 1365 | ||
1088 | for_each_node_by_type(np, "serial") { | 1366 | for_each_node_by_type(np, "serial") { |
1089 | if (!of_match_node(mpc52xx_uart_of_match, np)) | 1367 | match = of_match_node(mpc52xx_uart_of_match, np); |
1368 | if (!match) | ||
1090 | continue; | 1369 | continue; |
1091 | 1370 | ||
1371 | psc_ops = match->data; | ||
1372 | |||
1092 | /* Is a particular device number requested? */ | 1373 | /* Is a particular device number requested? */ |
1093 | devno = of_get_property(np, "port-number", NULL); | 1374 | devno = of_get_property(np, "port-number", NULL); |
1094 | mpc52xx_uart_of_assign(np, devno ? *devno : -1); | 1375 | mpc52xx_uart_of_assign(np, devno ? *devno : -1); |
@@ -1149,6 +1430,7 @@ mpc52xx_uart_init(void) | |||
1149 | return ret; | 1430 | return ret; |
1150 | } | 1431 | } |
1151 | #else | 1432 | #else |
1433 | psc_ops = &mpc52xx_psc_ops; | ||
1152 | ret = platform_driver_register(&mpc52xx_uart_platform_driver); | 1434 | ret = platform_driver_register(&mpc52xx_uart_platform_driver); |
1153 | if (ret) { | 1435 | if (ret) { |
1154 | printk(KERN_ERR "%s: platform_driver_register failed (%i)\n", | 1436 | printk(KERN_ERR "%s: platform_driver_register failed (%i)\n", |
diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c index bacf68dca01a..4e06ab6bcb6e 100644 --- a/drivers/serial/uartlite.c +++ b/drivers/serial/uartlite.c | |||
@@ -17,10 +17,21 @@ | |||
17 | #include <linux/tty.h> | 17 | #include <linux/tty.h> |
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | #include <linux/init.h> | ||
20 | #include <asm/io.h> | 21 | #include <asm/io.h> |
21 | #if defined(CONFIG_OF) | 22 | #if defined(CONFIG_OF) |
23 | #include <linux/of.h> | ||
22 | #include <linux/of_device.h> | 24 | #include <linux/of_device.h> |
23 | #include <linux/of_platform.h> | 25 | #include <linux/of_platform.h> |
26 | |||
27 | /* Match table for of_platform binding */ | ||
28 | static struct of_device_id ulite_of_match[] __devinitdata = { | ||
29 | { .compatible = "xlnx,opb-uartlite-1.00.b", }, | ||
30 | { .compatible = "xlnx,xps-uartlite-1.00.a", }, | ||
31 | {} | ||
32 | }; | ||
33 | MODULE_DEVICE_TABLE(of, ulite_of_match); | ||
34 | |||
24 | #endif | 35 | #endif |
25 | 36 | ||
26 | #define ULITE_NAME "ttyUL" | 37 | #define ULITE_NAME "ttyUL" |
@@ -275,6 +286,9 @@ static void ulite_release_port(struct uart_port *port) | |||
275 | 286 | ||
276 | static int ulite_request_port(struct uart_port *port) | 287 | static int ulite_request_port(struct uart_port *port) |
277 | { | 288 | { |
289 | pr_debug("ulite console: port=%p; port->mapbase=%x\n", | ||
290 | port, port->mapbase); | ||
291 | |||
278 | if (!request_mem_region(port->mapbase, ULITE_REGION, "uartlite")) { | 292 | if (!request_mem_region(port->mapbase, ULITE_REGION, "uartlite")) { |
279 | dev_err(port->dev, "Memory region busy\n"); | 293 | dev_err(port->dev, "Memory region busy\n"); |
280 | return -EBUSY; | 294 | return -EBUSY; |
@@ -375,32 +389,6 @@ static void ulite_console_write(struct console *co, const char *s, | |||
375 | spin_unlock_irqrestore(&port->lock, flags); | 389 | spin_unlock_irqrestore(&port->lock, flags); |
376 | } | 390 | } |
377 | 391 | ||
378 | #if defined(CONFIG_OF) | ||
379 | static inline void __init ulite_console_of_find_device(int id) | ||
380 | { | ||
381 | struct device_node *np; | ||
382 | struct resource res; | ||
383 | const unsigned int *of_id; | ||
384 | int rc; | ||
385 | |||
386 | for_each_compatible_node(np, NULL, "xilinx,uartlite") { | ||
387 | of_id = of_get_property(np, "port-number", NULL); | ||
388 | if ((!of_id) || (*of_id != id)) | ||
389 | continue; | ||
390 | |||
391 | rc = of_address_to_resource(np, 0, &res); | ||
392 | if (rc) | ||
393 | continue; | ||
394 | |||
395 | ulite_ports[id].mapbase = res.start; | ||
396 | of_node_put(np); | ||
397 | return; | ||
398 | } | ||
399 | } | ||
400 | #else /* CONFIG_OF */ | ||
401 | static inline void __init ulite_console_of_find_device(int id) { /* do nothing */ } | ||
402 | #endif /* CONFIG_OF */ | ||
403 | |||
404 | static int __init ulite_console_setup(struct console *co, char *options) | 392 | static int __init ulite_console_setup(struct console *co, char *options) |
405 | { | 393 | { |
406 | struct uart_port *port; | 394 | struct uart_port *port; |
@@ -414,11 +402,7 @@ static int __init ulite_console_setup(struct console *co, char *options) | |||
414 | 402 | ||
415 | port = &ulite_ports[co->index]; | 403 | port = &ulite_ports[co->index]; |
416 | 404 | ||
417 | /* Check if it is an OF device */ | 405 | /* Has the device been initialized yet? */ |
418 | if (!port->mapbase) | ||
419 | ulite_console_of_find_device(co->index); | ||
420 | |||
421 | /* Do we have a device now? */ | ||
422 | if (!port->mapbase) { | 406 | if (!port->mapbase) { |
423 | pr_debug("console on ttyUL%i not present\n", co->index); | 407 | pr_debug("console on ttyUL%i not present\n", co->index); |
424 | return -ENODEV; | 408 | return -ENODEV; |
@@ -617,13 +601,6 @@ static int __devexit ulite_of_remove(struct of_device *op) | |||
617 | return ulite_release(&op->dev); | 601 | return ulite_release(&op->dev); |
618 | } | 602 | } |
619 | 603 | ||
620 | /* Match table for of_platform binding */ | ||
621 | static struct of_device_id __devinit ulite_of_match[] = { | ||
622 | { .type = "serial", .compatible = "xilinx,uartlite", }, | ||
623 | {}, | ||
624 | }; | ||
625 | MODULE_DEVICE_TABLE(of, ulite_of_match); | ||
626 | |||
627 | static struct of_platform_driver ulite_of_driver = { | 604 | static struct of_platform_driver ulite_of_driver = { |
628 | .owner = THIS_MODULE, | 605 | .owner = THIS_MODULE, |
629 | .name = "uartlite", | 606 | .name = "uartlite", |