Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  *  Driver for CLPS711x serial ports
0004  *
0005  *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
0006  *
0007  *  Copyright 1999 ARM Limited
0008  *  Copyright (C) 2000 Deep Blue Solutions Ltd.
0009  */
0010 
0011 #include <linux/module.h>
0012 #include <linux/device.h>
0013 #include <linux/console.h>
0014 #include <linux/serial_core.h>
0015 #include <linux/serial.h>
0016 #include <linux/clk.h>
0017 #include <linux/io.h>
0018 #include <linux/tty.h>
0019 #include <linux/tty_flip.h>
0020 #include <linux/ioport.h>
0021 #include <linux/of.h>
0022 #include <linux/platform_device.h>
0023 #include <linux/regmap.h>
0024 
0025 #include <linux/mfd/syscon.h>
0026 #include <linux/mfd/syscon/clps711x.h>
0027 
0028 #include "serial_mctrl_gpio.h"
0029 
0030 #define UART_CLPS711X_DEVNAME   "ttyCL"
0031 #define UART_CLPS711X_NR    2
0032 #define UART_CLPS711X_MAJOR 204
0033 #define UART_CLPS711X_MINOR 40
0034 
0035 #define UARTDR_OFFSET       (0x00)
0036 #define UBRLCR_OFFSET       (0x40)
0037 
0038 #define UARTDR_FRMERR       (1 << 8)
0039 #define UARTDR_PARERR       (1 << 9)
0040 #define UARTDR_OVERR        (1 << 10)
0041 
0042 #define UBRLCR_BAUD_MASK    ((1 << 12) - 1)
0043 #define UBRLCR_BREAK        (1 << 12)
0044 #define UBRLCR_PRTEN        (1 << 13)
0045 #define UBRLCR_EVENPRT      (1 << 14)
0046 #define UBRLCR_XSTOP        (1 << 15)
0047 #define UBRLCR_FIFOEN       (1 << 16)
0048 #define UBRLCR_WRDLEN5      (0 << 17)
0049 #define UBRLCR_WRDLEN6      (1 << 17)
0050 #define UBRLCR_WRDLEN7      (2 << 17)
0051 #define UBRLCR_WRDLEN8      (3 << 17)
0052 #define UBRLCR_WRDLEN_MASK  (3 << 17)
0053 
0054 struct clps711x_port {
0055     struct uart_port    port;
0056     unsigned int        tx_enabled;
0057     int         rx_irq;
0058     struct regmap       *syscon;
0059     struct mctrl_gpios  *gpios;
0060 };
0061 
0062 static struct uart_driver clps711x_uart = {
0063     .owner      = THIS_MODULE,
0064     .driver_name    = UART_CLPS711X_DEVNAME,
0065     .dev_name   = UART_CLPS711X_DEVNAME,
0066     .major      = UART_CLPS711X_MAJOR,
0067     .minor      = UART_CLPS711X_MINOR,
0068     .nr     = UART_CLPS711X_NR,
0069 };
0070 
0071 static void uart_clps711x_stop_tx(struct uart_port *port)
0072 {
0073     struct clps711x_port *s = dev_get_drvdata(port->dev);
0074 
0075     if (s->tx_enabled) {
0076         disable_irq(port->irq);
0077         s->tx_enabled = 0;
0078     }
0079 }
0080 
0081 static void uart_clps711x_start_tx(struct uart_port *port)
0082 {
0083     struct clps711x_port *s = dev_get_drvdata(port->dev);
0084 
0085     if (!s->tx_enabled) {
0086         s->tx_enabled = 1;
0087         enable_irq(port->irq);
0088     }
0089 }
0090 
0091 static irqreturn_t uart_clps711x_int_rx(int irq, void *dev_id)
0092 {
0093     struct uart_port *port = dev_id;
0094     struct clps711x_port *s = dev_get_drvdata(port->dev);
0095     unsigned int status, flg;
0096     u16 ch;
0097 
0098     for (;;) {
0099         u32 sysflg = 0;
0100 
0101         regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg);
0102         if (sysflg & SYSFLG_URXFE)
0103             break;
0104 
0105         ch = readw(port->membase + UARTDR_OFFSET);
0106         status = ch & (UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR);
0107         ch &= 0xff;
0108 
0109         port->icount.rx++;
0110         flg = TTY_NORMAL;
0111 
0112         if (unlikely(status)) {
0113             if (status & UARTDR_PARERR)
0114                 port->icount.parity++;
0115             else if (status & UARTDR_FRMERR)
0116                 port->icount.frame++;
0117             else if (status & UARTDR_OVERR)
0118                 port->icount.overrun++;
0119 
0120             status &= port->read_status_mask;
0121 
0122             if (status & UARTDR_PARERR)
0123                 flg = TTY_PARITY;
0124             else if (status & UARTDR_FRMERR)
0125                 flg = TTY_FRAME;
0126             else if (status & UARTDR_OVERR)
0127                 flg = TTY_OVERRUN;
0128         }
0129 
0130         if (uart_handle_sysrq_char(port, ch))
0131             continue;
0132 
0133         if (status & port->ignore_status_mask)
0134             continue;
0135 
0136         uart_insert_char(port, status, UARTDR_OVERR, ch, flg);
0137     }
0138 
0139     tty_flip_buffer_push(&port->state->port);
0140 
0141     return IRQ_HANDLED;
0142 }
0143 
0144 static irqreturn_t uart_clps711x_int_tx(int irq, void *dev_id)
0145 {
0146     struct uart_port *port = dev_id;
0147     struct clps711x_port *s = dev_get_drvdata(port->dev);
0148     struct circ_buf *xmit = &port->state->xmit;
0149 
0150     if (port->x_char) {
0151         writew(port->x_char, port->membase + UARTDR_OFFSET);
0152         port->icount.tx++;
0153         port->x_char = 0;
0154         return IRQ_HANDLED;
0155     }
0156 
0157     if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
0158         if (s->tx_enabled) {
0159             disable_irq_nosync(port->irq);
0160             s->tx_enabled = 0;
0161         }
0162         return IRQ_HANDLED;
0163     }
0164 
0165     while (!uart_circ_empty(xmit)) {
0166         u32 sysflg = 0;
0167 
0168         writew(xmit->buf[xmit->tail], port->membase + UARTDR_OFFSET);
0169         xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
0170         port->icount.tx++;
0171 
0172         regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg);
0173         if (sysflg & SYSFLG_UTXFF)
0174             break;
0175     }
0176 
0177     if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
0178         uart_write_wakeup(port);
0179 
0180     return IRQ_HANDLED;
0181 }
0182 
0183 static unsigned int uart_clps711x_tx_empty(struct uart_port *port)
0184 {
0185     struct clps711x_port *s = dev_get_drvdata(port->dev);
0186     u32 sysflg = 0;
0187 
0188     regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg);
0189 
0190     return (sysflg & SYSFLG_UBUSY) ? 0 : TIOCSER_TEMT;
0191 }
0192 
0193 static unsigned int uart_clps711x_get_mctrl(struct uart_port *port)
0194 {
0195     unsigned int result = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR;
0196     struct clps711x_port *s = dev_get_drvdata(port->dev);
0197 
0198     return mctrl_gpio_get(s->gpios, &result);
0199 }
0200 
0201 static void uart_clps711x_set_mctrl(struct uart_port *port, unsigned int mctrl)
0202 {
0203     struct clps711x_port *s = dev_get_drvdata(port->dev);
0204 
0205     mctrl_gpio_set(s->gpios, mctrl);
0206 }
0207 
0208 static void uart_clps711x_break_ctl(struct uart_port *port, int break_state)
0209 {
0210     unsigned int ubrlcr;
0211 
0212     ubrlcr = readl(port->membase + UBRLCR_OFFSET);
0213     if (break_state)
0214         ubrlcr |= UBRLCR_BREAK;
0215     else
0216         ubrlcr &= ~UBRLCR_BREAK;
0217     writel(ubrlcr, port->membase + UBRLCR_OFFSET);
0218 }
0219 
0220 static void uart_clps711x_set_ldisc(struct uart_port *port,
0221                     struct ktermios *termios)
0222 {
0223     if (!port->line) {
0224         struct clps711x_port *s = dev_get_drvdata(port->dev);
0225 
0226         regmap_update_bits(s->syscon, SYSCON_OFFSET, SYSCON1_SIREN,
0227                    (termios->c_line == N_IRDA) ? SYSCON1_SIREN : 0);
0228     }
0229 }
0230 
0231 static int uart_clps711x_startup(struct uart_port *port)
0232 {
0233     struct clps711x_port *s = dev_get_drvdata(port->dev);
0234 
0235     /* Disable break */
0236     writel(readl(port->membase + UBRLCR_OFFSET) & ~UBRLCR_BREAK,
0237            port->membase + UBRLCR_OFFSET);
0238 
0239     /* Enable the port */
0240     return regmap_update_bits(s->syscon, SYSCON_OFFSET,
0241                   SYSCON_UARTEN, SYSCON_UARTEN);
0242 }
0243 
0244 static void uart_clps711x_shutdown(struct uart_port *port)
0245 {
0246     struct clps711x_port *s = dev_get_drvdata(port->dev);
0247 
0248     /* Disable the port */
0249     regmap_update_bits(s->syscon, SYSCON_OFFSET, SYSCON_UARTEN, 0);
0250 }
0251 
0252 static void uart_clps711x_set_termios(struct uart_port *port,
0253                       struct ktermios *termios,
0254                       struct ktermios *old)
0255 {
0256     u32 ubrlcr;
0257     unsigned int baud, quot;
0258 
0259     /* Mask termios capabilities we don't support */
0260     termios->c_cflag &= ~CMSPAR;
0261     termios->c_iflag &= ~(BRKINT | IGNBRK);
0262 
0263     /* Ask the core to calculate the divisor for us */
0264     baud = uart_get_baud_rate(port, termios, old, port->uartclk / 4096,
0265                               port->uartclk / 16);
0266     quot = uart_get_divisor(port, baud);
0267 
0268     switch (termios->c_cflag & CSIZE) {
0269     case CS5:
0270         ubrlcr = UBRLCR_WRDLEN5;
0271         break;
0272     case CS6:
0273         ubrlcr = UBRLCR_WRDLEN6;
0274         break;
0275     case CS7:
0276         ubrlcr = UBRLCR_WRDLEN7;
0277         break;
0278     case CS8:
0279     default:
0280         ubrlcr = UBRLCR_WRDLEN8;
0281         break;
0282     }
0283 
0284     if (termios->c_cflag & CSTOPB)
0285         ubrlcr |= UBRLCR_XSTOP;
0286 
0287     if (termios->c_cflag & PARENB) {
0288         ubrlcr |= UBRLCR_PRTEN;
0289         if (!(termios->c_cflag & PARODD))
0290             ubrlcr |= UBRLCR_EVENPRT;
0291     }
0292 
0293     /* Enable FIFO */
0294     ubrlcr |= UBRLCR_FIFOEN;
0295 
0296     /* Set read status mask */
0297     port->read_status_mask = UARTDR_OVERR;
0298     if (termios->c_iflag & INPCK)
0299         port->read_status_mask |= UARTDR_PARERR | UARTDR_FRMERR;
0300 
0301     /* Set status ignore mask */
0302     port->ignore_status_mask = 0;
0303     if (!(termios->c_cflag & CREAD))
0304         port->ignore_status_mask |= UARTDR_OVERR | UARTDR_PARERR |
0305                         UARTDR_FRMERR;
0306 
0307     uart_update_timeout(port, termios->c_cflag, baud);
0308 
0309     writel(ubrlcr | (quot - 1), port->membase + UBRLCR_OFFSET);
0310 }
0311 
0312 static const char *uart_clps711x_type(struct uart_port *port)
0313 {
0314     return (port->type == PORT_CLPS711X) ? "CLPS711X" : NULL;
0315 }
0316 
0317 static void uart_clps711x_config_port(struct uart_port *port, int flags)
0318 {
0319     if (flags & UART_CONFIG_TYPE)
0320         port->type = PORT_CLPS711X;
0321 }
0322 
0323 static void uart_clps711x_nop_void(struct uart_port *port)
0324 {
0325 }
0326 
0327 static int uart_clps711x_nop_int(struct uart_port *port)
0328 {
0329     return 0;
0330 }
0331 
0332 static const struct uart_ops uart_clps711x_ops = {
0333     .tx_empty   = uart_clps711x_tx_empty,
0334     .set_mctrl  = uart_clps711x_set_mctrl,
0335     .get_mctrl  = uart_clps711x_get_mctrl,
0336     .stop_tx    = uart_clps711x_stop_tx,
0337     .start_tx   = uart_clps711x_start_tx,
0338     .stop_rx    = uart_clps711x_nop_void,
0339     .break_ctl  = uart_clps711x_break_ctl,
0340     .set_ldisc  = uart_clps711x_set_ldisc,
0341     .startup    = uart_clps711x_startup,
0342     .shutdown   = uart_clps711x_shutdown,
0343     .set_termios    = uart_clps711x_set_termios,
0344     .type       = uart_clps711x_type,
0345     .config_port    = uart_clps711x_config_port,
0346     .release_port   = uart_clps711x_nop_void,
0347     .request_port   = uart_clps711x_nop_int,
0348 };
0349 
0350 #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
0351 static void uart_clps711x_console_putchar(struct uart_port *port, unsigned char ch)
0352 {
0353     struct clps711x_port *s = dev_get_drvdata(port->dev);
0354     u32 sysflg = 0;
0355 
0356     /* Wait for FIFO is not full */
0357     do {
0358         regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg);
0359     } while (sysflg & SYSFLG_UTXFF);
0360 
0361     writew(ch, port->membase + UARTDR_OFFSET);
0362 }
0363 
0364 static void uart_clps711x_console_write(struct console *co, const char *c,
0365                     unsigned n)
0366 {
0367     struct uart_port *port = clps711x_uart.state[co->index].uart_port;
0368     struct clps711x_port *s = dev_get_drvdata(port->dev);
0369     u32 sysflg = 0;
0370 
0371     uart_console_write(port, c, n, uart_clps711x_console_putchar);
0372 
0373     /* Wait for transmitter to become empty */
0374     do {
0375         regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg);
0376     } while (sysflg & SYSFLG_UBUSY);
0377 }
0378 
0379 static int uart_clps711x_console_setup(struct console *co, char *options)
0380 {
0381     int baud = 38400, bits = 8, parity = 'n', flow = 'n';
0382     int ret, index = co->index;
0383     struct clps711x_port *s;
0384     struct uart_port *port;
0385     unsigned int quot;
0386     u32 ubrlcr;
0387 
0388     if (index < 0 || index >= UART_CLPS711X_NR)
0389         return -EINVAL;
0390 
0391     port = clps711x_uart.state[index].uart_port;
0392     if (!port)
0393         return -ENODEV;
0394 
0395     s = dev_get_drvdata(port->dev);
0396 
0397     if (!options) {
0398         u32 syscon = 0;
0399 
0400         regmap_read(s->syscon, SYSCON_OFFSET, &syscon);
0401         if (syscon & SYSCON_UARTEN) {
0402             ubrlcr = readl(port->membase + UBRLCR_OFFSET);
0403 
0404             if (ubrlcr & UBRLCR_PRTEN) {
0405                 if (ubrlcr & UBRLCR_EVENPRT)
0406                     parity = 'e';
0407                 else
0408                     parity = 'o';
0409             }
0410 
0411             if ((ubrlcr & UBRLCR_WRDLEN_MASK) == UBRLCR_WRDLEN7)
0412                 bits = 7;
0413 
0414             quot = ubrlcr & UBRLCR_BAUD_MASK;
0415             baud = port->uartclk / (16 * (quot + 1));
0416         }
0417     } else
0418         uart_parse_options(options, &baud, &parity, &bits, &flow);
0419 
0420     ret = uart_set_options(port, co, baud, parity, bits, flow);
0421     if (ret)
0422         return ret;
0423 
0424     return regmap_update_bits(s->syscon, SYSCON_OFFSET,
0425                   SYSCON_UARTEN, SYSCON_UARTEN);
0426 }
0427 
0428 static struct console clps711x_console = {
0429     .name   = UART_CLPS711X_DEVNAME,
0430     .device = uart_console_device,
0431     .write  = uart_clps711x_console_write,
0432     .setup  = uart_clps711x_console_setup,
0433     .flags  = CON_PRINTBUFFER,
0434     .index  = -1,
0435 };
0436 #endif
0437 
0438 static int uart_clps711x_probe(struct platform_device *pdev)
0439 {
0440     struct device_node *np = pdev->dev.of_node;
0441     struct clps711x_port *s;
0442     struct resource *res;
0443     struct clk *uart_clk;
0444     int irq, ret;
0445 
0446     s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL);
0447     if (!s)
0448         return -ENOMEM;
0449 
0450     uart_clk = devm_clk_get(&pdev->dev, NULL);
0451     if (IS_ERR(uart_clk))
0452         return PTR_ERR(uart_clk);
0453 
0454     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0455     s->port.membase = devm_ioremap_resource(&pdev->dev, res);
0456     if (IS_ERR(s->port.membase))
0457         return PTR_ERR(s->port.membase);
0458 
0459     irq = platform_get_irq(pdev, 0);
0460     if (irq < 0)
0461         return irq;
0462     s->port.irq = irq;
0463 
0464     s->rx_irq = platform_get_irq(pdev, 1);
0465     if (s->rx_irq < 0)
0466         return s->rx_irq;
0467 
0468     s->syscon = syscon_regmap_lookup_by_phandle(np, "syscon");
0469     if (IS_ERR(s->syscon))
0470         return PTR_ERR(s->syscon);
0471 
0472     s->port.line        = of_alias_get_id(np, "serial");
0473     s->port.dev     = &pdev->dev;
0474     s->port.iotype      = UPIO_MEM32;
0475     s->port.mapbase     = res->start;
0476     s->port.type        = PORT_CLPS711X;
0477     s->port.fifosize    = 16;
0478     s->port.has_sysrq   = IS_ENABLED(CONFIG_SERIAL_CLPS711X_CONSOLE);
0479     s->port.flags       = UPF_SKIP_TEST | UPF_FIXED_TYPE;
0480     s->port.uartclk     = clk_get_rate(uart_clk);
0481     s->port.ops     = &uart_clps711x_ops;
0482 
0483     platform_set_drvdata(pdev, s);
0484 
0485     s->gpios = mctrl_gpio_init_noauto(&pdev->dev, 0);
0486     if (IS_ERR(s->gpios))
0487         return PTR_ERR(s->gpios);
0488 
0489     ret = uart_add_one_port(&clps711x_uart, &s->port);
0490     if (ret)
0491         return ret;
0492 
0493     /* Disable port */
0494     if (!uart_console(&s->port))
0495         regmap_update_bits(s->syscon, SYSCON_OFFSET, SYSCON_UARTEN, 0);
0496 
0497     s->tx_enabled = 1;
0498 
0499     ret = devm_request_irq(&pdev->dev, s->port.irq, uart_clps711x_int_tx, 0,
0500                    dev_name(&pdev->dev), &s->port);
0501     if (ret) {
0502         uart_remove_one_port(&clps711x_uart, &s->port);
0503         return ret;
0504     }
0505 
0506     ret = devm_request_irq(&pdev->dev, s->rx_irq, uart_clps711x_int_rx, 0,
0507                    dev_name(&pdev->dev), &s->port);
0508     if (ret)
0509         uart_remove_one_port(&clps711x_uart, &s->port);
0510 
0511     return ret;
0512 }
0513 
0514 static int uart_clps711x_remove(struct platform_device *pdev)
0515 {
0516     struct clps711x_port *s = platform_get_drvdata(pdev);
0517 
0518     return uart_remove_one_port(&clps711x_uart, &s->port);
0519 }
0520 
0521 static const struct of_device_id __maybe_unused clps711x_uart_dt_ids[] = {
0522     { .compatible = "cirrus,ep7209-uart", },
0523     { }
0524 };
0525 MODULE_DEVICE_TABLE(of, clps711x_uart_dt_ids);
0526 
0527 static struct platform_driver clps711x_uart_platform = {
0528     .driver = {
0529         .name       = "clps711x-uart",
0530         .of_match_table = of_match_ptr(clps711x_uart_dt_ids),
0531     },
0532     .probe  = uart_clps711x_probe,
0533     .remove = uart_clps711x_remove,
0534 };
0535 
0536 static int __init uart_clps711x_init(void)
0537 {
0538     int ret;
0539 
0540 #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
0541     clps711x_uart.cons = &clps711x_console;
0542     clps711x_console.data = &clps711x_uart;
0543 #endif
0544 
0545     ret = uart_register_driver(&clps711x_uart);
0546     if (ret)
0547         return ret;
0548 
0549     return platform_driver_register(&clps711x_uart_platform);
0550 }
0551 module_init(uart_clps711x_init);
0552 
0553 static void __exit uart_clps711x_exit(void)
0554 {
0555     platform_driver_unregister(&clps711x_uart_platform);
0556     uart_unregister_driver(&clps711x_uart);
0557 }
0558 module_exit(uart_clps711x_exit);
0559 
0560 MODULE_AUTHOR("Deep Blue Solutions Ltd");
0561 MODULE_DESCRIPTION("CLPS711X serial driver");
0562 MODULE_LICENSE("GPL");