Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
altera_jtaguart.c
Go to the documentation of this file.
1 /*
2  * altera_jtaguart.c -- Altera JTAG UART driver
3  *
4  * Based on mcf.c -- Freescale ColdFire UART driver
5  *
6  * (C) Copyright 2003-2007, Greg Ungerer <[email protected]>
7  * (C) Copyright 2008, Thomas Chou <[email protected]>
8  * (C) Copyright 2010, Tobias Klauser <[email protected]>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  */
15 
16 #include <linux/kernel.h>
17 #include <linux/init.h>
18 #include <linux/interrupt.h>
19 #include <linux/module.h>
20 #include <linux/console.h>
21 #include <linux/of.h>
22 #include <linux/tty.h>
23 #include <linux/tty_flip.h>
24 #include <linux/serial.h>
25 #include <linux/serial_core.h>
26 #include <linux/platform_device.h>
27 #include <linux/io.h>
28 #include <linux/altera_jtaguart.h>
29 
30 #define DRV_NAME "altera_jtaguart"
31 
32 /*
33  * Altera JTAG UART register definitions according to the Altera JTAG UART
34  * datasheet: http://www.altera.com/literature/hb/nios2/n2cpu_nii51009.pdf
35  */
36 
37 #define ALTERA_JTAGUART_SIZE 8
38 
39 #define ALTERA_JTAGUART_DATA_REG 0
40 
41 #define ALTERA_JTAGUART_DATA_DATA_MSK 0x000000FF
42 #define ALTERA_JTAGUART_DATA_RVALID_MSK 0x00008000
43 #define ALTERA_JTAGUART_DATA_RAVAIL_MSK 0xFFFF0000
44 #define ALTERA_JTAGUART_DATA_RAVAIL_OFF 16
45 
46 #define ALTERA_JTAGUART_CONTROL_REG 4
47 
48 #define ALTERA_JTAGUART_CONTROL_RE_MSK 0x00000001
49 #define ALTERA_JTAGUART_CONTROL_WE_MSK 0x00000002
50 #define ALTERA_JTAGUART_CONTROL_RI_MSK 0x00000100
51 #define ALTERA_JTAGUART_CONTROL_RI_OFF 8
52 #define ALTERA_JTAGUART_CONTROL_WI_MSK 0x00000200
53 #define ALTERA_JTAGUART_CONTROL_AC_MSK 0x00000400
54 #define ALTERA_JTAGUART_CONTROL_WSPACE_MSK 0xFFFF0000
55 #define ALTERA_JTAGUART_CONTROL_WSPACE_OFF 16
56 
57 /*
58  * Local per-uart structure.
59  */
61  struct uart_port port;
62  unsigned int sigs; /* Local copy of line sigs */
63  unsigned long imr; /* Local IMR mirror */
64 };
65 
66 static unsigned int altera_jtaguart_tx_empty(struct uart_port *port)
67 {
68  return (readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) &
70 }
71 
72 static unsigned int altera_jtaguart_get_mctrl(struct uart_port *port)
73 {
74  return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
75 }
76 
77 static void altera_jtaguart_set_mctrl(struct uart_port *port, unsigned int sigs)
78 {
79 }
80 
81 static void altera_jtaguart_start_tx(struct uart_port *port)
82 {
83  struct altera_jtaguart *pp =
84  container_of(port, struct altera_jtaguart, port);
85 
88 }
89 
90 static void altera_jtaguart_stop_tx(struct uart_port *port)
91 {
92  struct altera_jtaguart *pp =
93  container_of(port, struct altera_jtaguart, port);
94 
97 }
98 
99 static void altera_jtaguart_stop_rx(struct uart_port *port)
100 {
101  struct altera_jtaguart *pp =
102  container_of(port, struct altera_jtaguart, port);
103 
106 }
107 
108 static void altera_jtaguart_break_ctl(struct uart_port *port, int break_state)
109 {
110 }
111 
112 static void altera_jtaguart_enable_ms(struct uart_port *port)
113 {
114 }
115 
116 static void altera_jtaguart_set_termios(struct uart_port *port,
117  struct ktermios *termios,
118  struct ktermios *old)
119 {
120  /* Just copy the old termios settings back */
121  if (old)
122  tty_termios_copy_hw(termios, old);
123 }
124 
125 static void altera_jtaguart_rx_chars(struct altera_jtaguart *pp)
126 {
127  struct uart_port *port = &pp->port;
128  unsigned char ch, flag;
129  unsigned long status;
130 
131  while ((status = readl(port->membase + ALTERA_JTAGUART_DATA_REG)) &
133  ch = status & ALTERA_JTAGUART_DATA_DATA_MSK;
134  flag = TTY_NORMAL;
135  port->icount.rx++;
136 
137  if (uart_handle_sysrq_char(port, ch))
138  continue;
139  uart_insert_char(port, 0, 0, ch, flag);
140  }
141 
142  tty_flip_buffer_push(port->state->port.tty);
143 }
144 
145 static void altera_jtaguart_tx_chars(struct altera_jtaguart *pp)
146 {
147  struct uart_port *port = &pp->port;
148  struct circ_buf *xmit = &port->state->xmit;
149  unsigned int pending, count;
150 
151  if (port->x_char) {
152  /* Send special char - probably flow control */
154  port->x_char = 0;
155  port->icount.tx++;
156  return;
157  }
158 
159  pending = uart_circ_chars_pending(xmit);
160  if (pending > 0) {
161  count = (readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) &
164  if (count > pending)
165  count = pending;
166  if (count > 0) {
167  pending -= count;
168  while (count--) {
169  writel(xmit->buf[xmit->tail],
171  xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
172  port->icount.tx++;
173  }
174  if (pending < WAKEUP_CHARS)
175  uart_write_wakeup(port);
176  }
177  }
178 
179  if (pending == 0) {
182  }
183 }
184 
185 static irqreturn_t altera_jtaguart_interrupt(int irq, void *data)
186 {
187  struct uart_port *port = data;
188  struct altera_jtaguart *pp =
189  container_of(port, struct altera_jtaguart, port);
190  unsigned int isr;
191 
192  isr = (readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) >>
194 
195  spin_lock(&port->lock);
196 
198  altera_jtaguart_rx_chars(pp);
200  altera_jtaguart_tx_chars(pp);
201 
202  spin_unlock(&port->lock);
203 
204  return IRQ_RETVAL(isr);
205 }
206 
207 static void altera_jtaguart_config_port(struct uart_port *port, int flags)
208 {
209  port->type = PORT_ALTERA_JTAGUART;
210 
211  /* Clear mask, so no surprise interrupts. */
213 }
214 
215 static int altera_jtaguart_startup(struct uart_port *port)
216 {
217  struct altera_jtaguart *pp =
218  container_of(port, struct altera_jtaguart, port);
219  unsigned long flags;
220  int ret;
221 
222  ret = request_irq(port->irq, altera_jtaguart_interrupt, 0,
223  DRV_NAME, port);
224  if (ret) {
225  pr_err(DRV_NAME ": unable to attach Altera JTAG UART %d "
226  "interrupt vector=%d\n", port->line, port->irq);
227  return ret;
228  }
229 
230  spin_lock_irqsave(&port->lock, flags);
231 
232  /* Enable RX interrupts now */
235 
236  spin_unlock_irqrestore(&port->lock, flags);
237 
238  return 0;
239 }
240 
241 static void altera_jtaguart_shutdown(struct uart_port *port)
242 {
243  struct altera_jtaguart *pp =
244  container_of(port, struct altera_jtaguart, port);
245  unsigned long flags;
246 
247  spin_lock_irqsave(&port->lock, flags);
248 
249  /* Disable all interrupts now */
250  pp->imr = 0;
252 
253  spin_unlock_irqrestore(&port->lock, flags);
254 
255  free_irq(port->irq, port);
256 }
257 
258 static const char *altera_jtaguart_type(struct uart_port *port)
259 {
260  return (port->type == PORT_ALTERA_JTAGUART) ? "Altera JTAG UART" : NULL;
261 }
262 
263 static int altera_jtaguart_request_port(struct uart_port *port)
264 {
265  /* UARTs always present */
266  return 0;
267 }
268 
269 static void altera_jtaguart_release_port(struct uart_port *port)
270 {
271  /* Nothing to release... */
272 }
273 
274 static int altera_jtaguart_verify_port(struct uart_port *port,
275  struct serial_struct *ser)
276 {
277  if (ser->type != PORT_UNKNOWN && ser->type != PORT_ALTERA_JTAGUART)
278  return -EINVAL;
279  return 0;
280 }
281 
282 /*
283  * Define the basic serial functions we support.
284  */
285 static struct uart_ops altera_jtaguart_ops = {
286  .tx_empty = altera_jtaguart_tx_empty,
287  .get_mctrl = altera_jtaguart_get_mctrl,
288  .set_mctrl = altera_jtaguart_set_mctrl,
289  .start_tx = altera_jtaguart_start_tx,
290  .stop_tx = altera_jtaguart_stop_tx,
291  .stop_rx = altera_jtaguart_stop_rx,
292  .enable_ms = altera_jtaguart_enable_ms,
293  .break_ctl = altera_jtaguart_break_ctl,
294  .startup = altera_jtaguart_startup,
295  .shutdown = altera_jtaguart_shutdown,
296  .set_termios = altera_jtaguart_set_termios,
297  .type = altera_jtaguart_type,
298  .request_port = altera_jtaguart_request_port,
299  .release_port = altera_jtaguart_release_port,
300  .config_port = altera_jtaguart_config_port,
301  .verify_port = altera_jtaguart_verify_port,
302 };
303 
304 #define ALTERA_JTAGUART_MAXPORTS 1
305 static struct altera_jtaguart altera_jtaguart_ports[ALTERA_JTAGUART_MAXPORTS];
306 
307 #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE)
308 
309 #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS)
310 static void altera_jtaguart_console_putc(struct console *co, const char c)
311 {
312  struct uart_port *port = &(altera_jtaguart_ports + co->index)->port;
313  unsigned long status;
314  unsigned long flags;
315 
316  spin_lock_irqsave(&port->lock, flags);
317  while (((status = readl(port->membase + ALTERA_JTAGUART_CONTROL_REG)) &
319  if ((status & ALTERA_JTAGUART_CONTROL_AC_MSK) == 0) {
320  spin_unlock_irqrestore(&port->lock, flags);
321  return; /* no connection activity */
322  }
323  spin_unlock_irqrestore(&port->lock, flags);
324  cpu_relax();
325  spin_lock_irqsave(&port->lock, flags);
326  }
328  spin_unlock_irqrestore(&port->lock, flags);
329 }
330 #else
331 static void altera_jtaguart_console_putc(struct console *co, const char c)
332 {
333  struct uart_port *port = &(altera_jtaguart_ports + co->index)->port;
334  unsigned long flags;
335 
336  spin_lock_irqsave(&port->lock, flags);
337  while ((readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) &
338  ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0) {
339  spin_unlock_irqrestore(&port->lock, flags);
340  cpu_relax();
341  spin_lock_irqsave(&port->lock, flags);
342  }
344  spin_unlock_irqrestore(&port->lock, flags);
345 }
346 #endif
347 
348 static void altera_jtaguart_console_write(struct console *co, const char *s,
349  unsigned int count)
350 {
351  for (; count; count--, s++) {
352  altera_jtaguart_console_putc(co, *s);
353  if (*s == '\n')
354  altera_jtaguart_console_putc(co, '\r');
355  }
356 }
357 
358 static int __init altera_jtaguart_console_setup(struct console *co,
359  char *options)
360 {
361  struct uart_port *port;
362 
363  if (co->index < 0 || co->index >= ALTERA_JTAGUART_MAXPORTS)
364  return -EINVAL;
365  port = &altera_jtaguart_ports[co->index].port;
366  if (port->membase == NULL)
367  return -ENODEV;
368  return 0;
369 }
370 
371 static struct uart_driver altera_jtaguart_driver;
372 
373 static struct console altera_jtaguart_console = {
374  .name = "ttyJ",
375  .write = altera_jtaguart_console_write,
376  .device = uart_console_device,
377  .setup = altera_jtaguart_console_setup,
378  .flags = CON_PRINTBUFFER,
379  .index = -1,
380  .data = &altera_jtaguart_driver,
381 };
382 
383 static int __init altera_jtaguart_console_init(void)
384 {
385  register_console(&altera_jtaguart_console);
386  return 0;
387 }
388 
389 console_initcall(altera_jtaguart_console_init);
390 
391 #define ALTERA_JTAGUART_CONSOLE (&altera_jtaguart_console)
392 
393 #else
394 
395 #define ALTERA_JTAGUART_CONSOLE NULL
396 
397 #endif /* CONFIG_ALTERA_JTAGUART_CONSOLE */
398 
399 static struct uart_driver altera_jtaguart_driver = {
400  .owner = THIS_MODULE,
401  .driver_name = "altera_jtaguart",
402  .dev_name = "ttyJ",
403  .major = ALTERA_JTAGUART_MAJOR,
404  .minor = ALTERA_JTAGUART_MINOR,
406  .cons = ALTERA_JTAGUART_CONSOLE,
407 };
408 
409 static int __devinit altera_jtaguart_probe(struct platform_device *pdev)
410 {
411  struct altera_jtaguart_platform_uart *platp = pdev->dev.platform_data;
412  struct uart_port *port;
413  struct resource *res_irq, *res_mem;
414  int i = pdev->id;
415 
416  /* -1 emphasizes that the platform must have one port, no .N suffix */
417  if (i == -1)
418  i = 0;
419 
420  if (i >= ALTERA_JTAGUART_MAXPORTS)
421  return -EINVAL;
422 
423  port = &altera_jtaguart_ports[i].port;
424 
425  res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
426  if (res_mem)
427  port->mapbase = res_mem->start;
428  else if (platp)
429  port->mapbase = platp->mapbase;
430  else
431  return -ENODEV;
432 
433  res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
434  if (res_irq)
435  port->irq = res_irq->start;
436  else if (platp)
437  port->irq = platp->irq;
438  else
439  return -ENODEV;
440 
442  if (!port->membase)
443  return -ENOMEM;
444 
445  port->line = i;
446  port->type = PORT_ALTERA_JTAGUART;
447  port->iotype = SERIAL_IO_MEM;
448  port->ops = &altera_jtaguart_ops;
449  port->flags = UPF_BOOT_AUTOCONF;
450 
451  uart_add_one_port(&altera_jtaguart_driver, port);
452 
453  return 0;
454 }
455 
456 static int __devexit altera_jtaguart_remove(struct platform_device *pdev)
457 {
458  struct uart_port *port;
459  int i = pdev->id;
460 
461  if (i == -1)
462  i = 0;
463 
464  port = &altera_jtaguart_ports[i].port;
465  uart_remove_one_port(&altera_jtaguart_driver, port);
466 
467  return 0;
468 }
469 
470 #ifdef CONFIG_OF
471 static struct of_device_id altera_jtaguart_match[] = {
472  { .compatible = "ALTR,juart-1.0", },
473  {},
474 };
475 MODULE_DEVICE_TABLE(of, altera_jtaguart_match);
476 #endif /* CONFIG_OF */
477 
478 static struct platform_driver altera_jtaguart_platform_driver = {
479  .probe = altera_jtaguart_probe,
480  .remove = __devexit_p(altera_jtaguart_remove),
481  .driver = {
482  .name = DRV_NAME,
483  .owner = THIS_MODULE,
484  .of_match_table = of_match_ptr(altera_jtaguart_match),
485  },
486 };
487 
488 static int __init altera_jtaguart_init(void)
489 {
490  int rc;
491 
492  rc = uart_register_driver(&altera_jtaguart_driver);
493  if (rc)
494  return rc;
495  rc = platform_driver_register(&altera_jtaguart_platform_driver);
496  if (rc) {
497  uart_unregister_driver(&altera_jtaguart_driver);
498  return rc;
499  }
500  return 0;
501 }
502 
503 static void __exit altera_jtaguart_exit(void)
504 {
505  platform_driver_unregister(&altera_jtaguart_platform_driver);
506  uart_unregister_driver(&altera_jtaguart_driver);
507 }
508 
509 module_init(altera_jtaguart_init);
510 module_exit(altera_jtaguart_exit);
511 
512 MODULE_DESCRIPTION("Altera JTAG UART driver");
513 MODULE_AUTHOR("Thomas Chou <[email protected]>");
514 MODULE_LICENSE("GPL");
515 MODULE_ALIAS("platform:" DRV_NAME);