Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * altera_jtaguart.c -- Altera JTAG UART driver
0004  *
0005  * Based on mcf.c -- Freescale ColdFire UART driver
0006  *
0007  * (C) Copyright 2003-2007, Greg Ungerer <gerg@snapgear.com>
0008  * (C) Copyright 2008, Thomas Chou <thomas@wytron.com.tw>
0009  * (C) Copyright 2010, Tobias Klauser <tklauser@distanz.ch>
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  * Altera JTAG UART register definitions according to the Altera JTAG UART
0030  * datasheet: https://www.altera.com/literature/hb/nios2/n2cpu_nii51009.pdf
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  * Local per-uart structure.
0055  */
0056 struct altera_jtaguart {
0057     struct uart_port port;
0058     unsigned int sigs;  /* Local copy of line sigs */
0059     unsigned long imr;  /* Local IMR mirror */
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     /* Just copy the old termios settings back */
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         /* Send special char - probably flow control */
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     /* Clear mask, so no surprise interrupts. */
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     /* Enable RX interrupts now */
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     /* Disable all interrupts now */
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     /* UARTs always present */
0256     return 0;
0257 }
0258 
0259 static void altera_jtaguart_release_port(struct uart_port *port)
0260 {
0261     /* Nothing to release... */
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  *  Define the basic serial functions we support.
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; /* no connection activity */
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 /* CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE */
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     /* -1 emphasizes that the platform must have one port, no .N suffix */
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 /* CONFIG_OF */
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);