0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/kernel.h>
0013 #include <linux/init.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/module.h>
0016 #include <linux/console.h>
0017 #include <linux/of.h>
0018 #include <linux/tty.h>
0019 #include <linux/tty_flip.h>
0020 #include <linux/serial.h>
0021 #include <linux/serial_core.h>
0022 #include <linux/platform_device.h>
0023 #include <linux/io.h>
0024 #include <linux/altera_jtaguart.h>
0025
0026 #define DRV_NAME "altera_jtaguart"
0027
0028
0029
0030
0031
0032
0033 #define ALTERA_JTAGUART_SIZE 8
0034
0035 #define ALTERA_JTAGUART_DATA_REG 0
0036
0037 #define ALTERA_JTAGUART_DATA_DATA_MSK 0x000000FF
0038 #define ALTERA_JTAGUART_DATA_RVALID_MSK 0x00008000
0039 #define ALTERA_JTAGUART_DATA_RAVAIL_MSK 0xFFFF0000
0040 #define ALTERA_JTAGUART_DATA_RAVAIL_OFF 16
0041
0042 #define ALTERA_JTAGUART_CONTROL_REG 4
0043
0044 #define ALTERA_JTAGUART_CONTROL_RE_MSK 0x00000001
0045 #define ALTERA_JTAGUART_CONTROL_WE_MSK 0x00000002
0046 #define ALTERA_JTAGUART_CONTROL_RI_MSK 0x00000100
0047 #define ALTERA_JTAGUART_CONTROL_RI_OFF 8
0048 #define ALTERA_JTAGUART_CONTROL_WI_MSK 0x00000200
0049 #define ALTERA_JTAGUART_CONTROL_AC_MSK 0x00000400
0050 #define ALTERA_JTAGUART_CONTROL_WSPACE_MSK 0xFFFF0000
0051 #define ALTERA_JTAGUART_CONTROL_WSPACE_OFF 16
0052
0053
0054
0055
0056 struct altera_jtaguart {
0057 struct uart_port port;
0058 unsigned int sigs;
0059 unsigned long imr;
0060 };
0061
0062 static unsigned int altera_jtaguart_tx_empty(struct uart_port *port)
0063 {
0064 return (readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) &
0065 ALTERA_JTAGUART_CONTROL_WSPACE_MSK) ? TIOCSER_TEMT : 0;
0066 }
0067
0068 static unsigned int altera_jtaguart_get_mctrl(struct uart_port *port)
0069 {
0070 return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
0071 }
0072
0073 static void altera_jtaguart_set_mctrl(struct uart_port *port, unsigned int sigs)
0074 {
0075 }
0076
0077 static void altera_jtaguart_start_tx(struct uart_port *port)
0078 {
0079 struct altera_jtaguart *pp =
0080 container_of(port, struct altera_jtaguart, port);
0081
0082 pp->imr |= ALTERA_JTAGUART_CONTROL_WE_MSK;
0083 writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG);
0084 }
0085
0086 static void altera_jtaguart_stop_tx(struct uart_port *port)
0087 {
0088 struct altera_jtaguart *pp =
0089 container_of(port, struct altera_jtaguart, port);
0090
0091 pp->imr &= ~ALTERA_JTAGUART_CONTROL_WE_MSK;
0092 writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG);
0093 }
0094
0095 static void altera_jtaguart_stop_rx(struct uart_port *port)
0096 {
0097 struct altera_jtaguart *pp =
0098 container_of(port, struct altera_jtaguart, port);
0099
0100 pp->imr &= ~ALTERA_JTAGUART_CONTROL_RE_MSK;
0101 writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG);
0102 }
0103
0104 static void altera_jtaguart_break_ctl(struct uart_port *port, int break_state)
0105 {
0106 }
0107
0108 static void altera_jtaguart_set_termios(struct uart_port *port,
0109 struct ktermios *termios,
0110 struct ktermios *old)
0111 {
0112
0113 if (old)
0114 tty_termios_copy_hw(termios, old);
0115 }
0116
0117 static void altera_jtaguart_rx_chars(struct altera_jtaguart *pp)
0118 {
0119 struct uart_port *port = &pp->port;
0120 unsigned char ch, flag;
0121 unsigned long status;
0122
0123 while ((status = readl(port->membase + ALTERA_JTAGUART_DATA_REG)) &
0124 ALTERA_JTAGUART_DATA_RVALID_MSK) {
0125 ch = status & ALTERA_JTAGUART_DATA_DATA_MSK;
0126 flag = TTY_NORMAL;
0127 port->icount.rx++;
0128
0129 if (uart_handle_sysrq_char(port, ch))
0130 continue;
0131 uart_insert_char(port, 0, 0, ch, flag);
0132 }
0133
0134 tty_flip_buffer_push(&port->state->port);
0135 }
0136
0137 static void altera_jtaguart_tx_chars(struct altera_jtaguart *pp)
0138 {
0139 struct uart_port *port = &pp->port;
0140 struct circ_buf *xmit = &port->state->xmit;
0141 unsigned int pending, count;
0142
0143 if (port->x_char) {
0144
0145 writel(port->x_char, port->membase + ALTERA_JTAGUART_DATA_REG);
0146 port->x_char = 0;
0147 port->icount.tx++;
0148 return;
0149 }
0150
0151 pending = uart_circ_chars_pending(xmit);
0152 if (pending > 0) {
0153 count = (readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) &
0154 ALTERA_JTAGUART_CONTROL_WSPACE_MSK) >>
0155 ALTERA_JTAGUART_CONTROL_WSPACE_OFF;
0156 if (count > pending)
0157 count = pending;
0158 if (count > 0) {
0159 pending -= count;
0160 while (count--) {
0161 writel(xmit->buf[xmit->tail],
0162 port->membase + ALTERA_JTAGUART_DATA_REG);
0163 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
0164 port->icount.tx++;
0165 }
0166 if (pending < WAKEUP_CHARS)
0167 uart_write_wakeup(port);
0168 }
0169 }
0170
0171 if (pending == 0)
0172 altera_jtaguart_stop_tx(port);
0173 }
0174
0175 static irqreturn_t altera_jtaguart_interrupt(int irq, void *data)
0176 {
0177 struct uart_port *port = data;
0178 struct altera_jtaguart *pp =
0179 container_of(port, struct altera_jtaguart, port);
0180 unsigned int isr;
0181
0182 isr = (readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) >>
0183 ALTERA_JTAGUART_CONTROL_RI_OFF) & pp->imr;
0184
0185 spin_lock(&port->lock);
0186
0187 if (isr & ALTERA_JTAGUART_CONTROL_RE_MSK)
0188 altera_jtaguart_rx_chars(pp);
0189 if (isr & ALTERA_JTAGUART_CONTROL_WE_MSK)
0190 altera_jtaguart_tx_chars(pp);
0191
0192 spin_unlock(&port->lock);
0193
0194 return IRQ_RETVAL(isr);
0195 }
0196
0197 static void altera_jtaguart_config_port(struct uart_port *port, int flags)
0198 {
0199 port->type = PORT_ALTERA_JTAGUART;
0200
0201
0202 writel(0, port->membase + ALTERA_JTAGUART_CONTROL_REG);
0203 }
0204
0205 static int altera_jtaguart_startup(struct uart_port *port)
0206 {
0207 struct altera_jtaguart *pp =
0208 container_of(port, struct altera_jtaguart, port);
0209 unsigned long flags;
0210 int ret;
0211
0212 ret = request_irq(port->irq, altera_jtaguart_interrupt, 0,
0213 DRV_NAME, port);
0214 if (ret) {
0215 pr_err(DRV_NAME ": unable to attach Altera JTAG UART %d "
0216 "interrupt vector=%d\n", port->line, port->irq);
0217 return ret;
0218 }
0219
0220 spin_lock_irqsave(&port->lock, flags);
0221
0222
0223 pp->imr = ALTERA_JTAGUART_CONTROL_RE_MSK;
0224 writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG);
0225
0226 spin_unlock_irqrestore(&port->lock, flags);
0227
0228 return 0;
0229 }
0230
0231 static void altera_jtaguart_shutdown(struct uart_port *port)
0232 {
0233 struct altera_jtaguart *pp =
0234 container_of(port, struct altera_jtaguart, port);
0235 unsigned long flags;
0236
0237 spin_lock_irqsave(&port->lock, flags);
0238
0239
0240 pp->imr = 0;
0241 writel(pp->imr, port->membase + ALTERA_JTAGUART_CONTROL_REG);
0242
0243 spin_unlock_irqrestore(&port->lock, flags);
0244
0245 free_irq(port->irq, port);
0246 }
0247
0248 static const char *altera_jtaguart_type(struct uart_port *port)
0249 {
0250 return (port->type == PORT_ALTERA_JTAGUART) ? "Altera JTAG UART" : NULL;
0251 }
0252
0253 static int altera_jtaguart_request_port(struct uart_port *port)
0254 {
0255
0256 return 0;
0257 }
0258
0259 static void altera_jtaguart_release_port(struct uart_port *port)
0260 {
0261
0262 }
0263
0264 static int altera_jtaguart_verify_port(struct uart_port *port,
0265 struct serial_struct *ser)
0266 {
0267 if (ser->type != PORT_UNKNOWN && ser->type != PORT_ALTERA_JTAGUART)
0268 return -EINVAL;
0269 return 0;
0270 }
0271
0272
0273
0274
0275 static const struct uart_ops altera_jtaguart_ops = {
0276 .tx_empty = altera_jtaguart_tx_empty,
0277 .get_mctrl = altera_jtaguart_get_mctrl,
0278 .set_mctrl = altera_jtaguart_set_mctrl,
0279 .start_tx = altera_jtaguart_start_tx,
0280 .stop_tx = altera_jtaguart_stop_tx,
0281 .stop_rx = altera_jtaguart_stop_rx,
0282 .break_ctl = altera_jtaguart_break_ctl,
0283 .startup = altera_jtaguart_startup,
0284 .shutdown = altera_jtaguart_shutdown,
0285 .set_termios = altera_jtaguart_set_termios,
0286 .type = altera_jtaguart_type,
0287 .request_port = altera_jtaguart_request_port,
0288 .release_port = altera_jtaguart_release_port,
0289 .config_port = altera_jtaguart_config_port,
0290 .verify_port = altera_jtaguart_verify_port,
0291 };
0292
0293 #define ALTERA_JTAGUART_MAXPORTS 1
0294 static struct altera_jtaguart altera_jtaguart_ports[ALTERA_JTAGUART_MAXPORTS];
0295
0296 #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE)
0297
0298 #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS)
0299 static void altera_jtaguart_console_putc(struct uart_port *port, unsigned char c)
0300 {
0301 unsigned long status;
0302 unsigned long flags;
0303
0304 spin_lock_irqsave(&port->lock, flags);
0305 while (((status = readl(port->membase + ALTERA_JTAGUART_CONTROL_REG)) &
0306 ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0) {
0307 if ((status & ALTERA_JTAGUART_CONTROL_AC_MSK) == 0) {
0308 spin_unlock_irqrestore(&port->lock, flags);
0309 return;
0310 }
0311 spin_unlock_irqrestore(&port->lock, flags);
0312 cpu_relax();
0313 spin_lock_irqsave(&port->lock, flags);
0314 }
0315 writel(c, port->membase + ALTERA_JTAGUART_DATA_REG);
0316 spin_unlock_irqrestore(&port->lock, flags);
0317 }
0318 #else
0319 static void altera_jtaguart_console_putc(struct uart_port *port, unsigned char c)
0320 {
0321 unsigned long flags;
0322
0323 spin_lock_irqsave(&port->lock, flags);
0324 while ((readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) &
0325 ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0) {
0326 spin_unlock_irqrestore(&port->lock, flags);
0327 cpu_relax();
0328 spin_lock_irqsave(&port->lock, flags);
0329 }
0330 writel(c, port->membase + ALTERA_JTAGUART_DATA_REG);
0331 spin_unlock_irqrestore(&port->lock, flags);
0332 }
0333 #endif
0334
0335 static void altera_jtaguart_console_write(struct console *co, const char *s,
0336 unsigned int count)
0337 {
0338 struct uart_port *port = &(altera_jtaguart_ports + co->index)->port;
0339
0340 uart_console_write(port, s, count, altera_jtaguart_console_putc);
0341 }
0342
0343 static int __init altera_jtaguart_console_setup(struct console *co,
0344 char *options)
0345 {
0346 struct uart_port *port;
0347
0348 if (co->index < 0 || co->index >= ALTERA_JTAGUART_MAXPORTS)
0349 return -EINVAL;
0350 port = &altera_jtaguart_ports[co->index].port;
0351 if (port->membase == NULL)
0352 return -ENODEV;
0353 return 0;
0354 }
0355
0356 static struct uart_driver altera_jtaguart_driver;
0357
0358 static struct console altera_jtaguart_console = {
0359 .name = "ttyJ",
0360 .write = altera_jtaguart_console_write,
0361 .device = uart_console_device,
0362 .setup = altera_jtaguart_console_setup,
0363 .flags = CON_PRINTBUFFER,
0364 .index = -1,
0365 .data = &altera_jtaguart_driver,
0366 };
0367
0368 static int __init altera_jtaguart_console_init(void)
0369 {
0370 register_console(&altera_jtaguart_console);
0371 return 0;
0372 }
0373
0374 console_initcall(altera_jtaguart_console_init);
0375
0376 #define ALTERA_JTAGUART_CONSOLE (&altera_jtaguart_console)
0377
0378 static void altera_jtaguart_earlycon_write(struct console *co, const char *s,
0379 unsigned int count)
0380 {
0381 struct earlycon_device *dev = co->data;
0382
0383 uart_console_write(&dev->port, s, count, altera_jtaguart_console_putc);
0384 }
0385
0386 static int __init altera_jtaguart_earlycon_setup(struct earlycon_device *dev,
0387 const char *options)
0388 {
0389 if (!dev->port.membase)
0390 return -ENODEV;
0391
0392 dev->con->write = altera_jtaguart_earlycon_write;
0393 return 0;
0394 }
0395
0396 OF_EARLYCON_DECLARE(juart, "altr,juart-1.0", altera_jtaguart_earlycon_setup);
0397
0398 #else
0399
0400 #define ALTERA_JTAGUART_CONSOLE NULL
0401
0402 #endif
0403
0404 static struct uart_driver altera_jtaguart_driver = {
0405 .owner = THIS_MODULE,
0406 .driver_name = "altera_jtaguart",
0407 .dev_name = "ttyJ",
0408 .major = ALTERA_JTAGUART_MAJOR,
0409 .minor = ALTERA_JTAGUART_MINOR,
0410 .nr = ALTERA_JTAGUART_MAXPORTS,
0411 .cons = ALTERA_JTAGUART_CONSOLE,
0412 };
0413
0414 static int altera_jtaguart_probe(struct platform_device *pdev)
0415 {
0416 struct altera_jtaguart_platform_uart *platp =
0417 dev_get_platdata(&pdev->dev);
0418 struct uart_port *port;
0419 struct resource *res_mem;
0420 int i = pdev->id;
0421 int irq;
0422
0423
0424 if (i == -1)
0425 i = 0;
0426
0427 if (i >= ALTERA_JTAGUART_MAXPORTS)
0428 return -EINVAL;
0429
0430 port = &altera_jtaguart_ports[i].port;
0431
0432 res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0433 if (res_mem)
0434 port->mapbase = res_mem->start;
0435 else if (platp)
0436 port->mapbase = platp->mapbase;
0437 else
0438 return -ENODEV;
0439
0440 irq = platform_get_irq_optional(pdev, 0);
0441 if (irq < 0 && irq != -ENXIO)
0442 return irq;
0443 if (irq > 0)
0444 port->irq = irq;
0445 else if (platp)
0446 port->irq = platp->irq;
0447 else
0448 return -ENODEV;
0449
0450 port->membase = ioremap(port->mapbase, ALTERA_JTAGUART_SIZE);
0451 if (!port->membase)
0452 return -ENOMEM;
0453
0454 port->line = i;
0455 port->type = PORT_ALTERA_JTAGUART;
0456 port->iotype = SERIAL_IO_MEM;
0457 port->ops = &altera_jtaguart_ops;
0458 port->flags = UPF_BOOT_AUTOCONF;
0459 port->dev = &pdev->dev;
0460
0461 uart_add_one_port(&altera_jtaguart_driver, port);
0462
0463 return 0;
0464 }
0465
0466 static int altera_jtaguart_remove(struct platform_device *pdev)
0467 {
0468 struct uart_port *port;
0469 int i = pdev->id;
0470
0471 if (i == -1)
0472 i = 0;
0473
0474 port = &altera_jtaguart_ports[i].port;
0475 uart_remove_one_port(&altera_jtaguart_driver, port);
0476 iounmap(port->membase);
0477
0478 return 0;
0479 }
0480
0481 #ifdef CONFIG_OF
0482 static const struct of_device_id altera_jtaguart_match[] = {
0483 { .compatible = "ALTR,juart-1.0", },
0484 { .compatible = "altr,juart-1.0", },
0485 {},
0486 };
0487 MODULE_DEVICE_TABLE(of, altera_jtaguart_match);
0488 #endif
0489
0490 static struct platform_driver altera_jtaguart_platform_driver = {
0491 .probe = altera_jtaguart_probe,
0492 .remove = altera_jtaguart_remove,
0493 .driver = {
0494 .name = DRV_NAME,
0495 .of_match_table = of_match_ptr(altera_jtaguart_match),
0496 },
0497 };
0498
0499 static int __init altera_jtaguart_init(void)
0500 {
0501 int rc;
0502
0503 rc = uart_register_driver(&altera_jtaguart_driver);
0504 if (rc)
0505 return rc;
0506 rc = platform_driver_register(&altera_jtaguart_platform_driver);
0507 if (rc)
0508 uart_unregister_driver(&altera_jtaguart_driver);
0509 return rc;
0510 }
0511
0512 static void __exit altera_jtaguart_exit(void)
0513 {
0514 platform_driver_unregister(&altera_jtaguart_platform_driver);
0515 uart_unregister_driver(&altera_jtaguart_driver);
0516 }
0517
0518 module_init(altera_jtaguart_init);
0519 module_exit(altera_jtaguart_exit);
0520
0521 MODULE_DESCRIPTION("Altera JTAG UART driver");
0522 MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
0523 MODULE_LICENSE("GPL");
0524 MODULE_ALIAS("platform:" DRV_NAME);