Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Driver for the serial port on the 21285 StrongArm-110 core logic chip.
0004  *
0005  * Based on drivers/char/serial.c
0006  */
0007 #include <linux/module.h>
0008 #include <linux/tty.h>
0009 #include <linux/ioport.h>
0010 #include <linux/init.h>
0011 #include <linux/console.h>
0012 #include <linux/device.h>
0013 #include <linux/tty_flip.h>
0014 #include <linux/serial_core.h>
0015 #include <linux/serial.h>
0016 #include <linux/io.h>
0017 
0018 #include <asm/irq.h>
0019 #include <asm/mach-types.h>
0020 #include <asm/system_info.h>
0021 #include <asm/hardware/dec21285.h>
0022 #include <mach/hardware.h>
0023 
0024 #define BAUD_BASE       (mem_fclk_21285/64)
0025 
0026 #define SERIAL_21285_NAME   "ttyFB"
0027 #define SERIAL_21285_MAJOR  204
0028 #define SERIAL_21285_MINOR  4
0029 
0030 #define RXSTAT_DUMMY_READ   0x80000000
0031 #define RXSTAT_FRAME        (1 << 0)
0032 #define RXSTAT_PARITY       (1 << 1)
0033 #define RXSTAT_OVERRUN      (1 << 2)
0034 #define RXSTAT_ANYERR       (RXSTAT_FRAME|RXSTAT_PARITY|RXSTAT_OVERRUN)
0035 
0036 #define H_UBRLCR_BREAK      (1 << 0)
0037 #define H_UBRLCR_PARENB     (1 << 1)
0038 #define H_UBRLCR_PAREVN     (1 << 2)
0039 #define H_UBRLCR_STOPB      (1 << 3)
0040 #define H_UBRLCR_FIFO       (1 << 4)
0041 
0042 static const char serial21285_name[] = "Footbridge UART";
0043 
0044 /*
0045  * We only need 2 bits of data, so instead of creating a whole structure for
0046  * this, use bits of the private_data pointer of the uart port structure.
0047  */
0048 #define tx_enabled_bit  0
0049 #define rx_enabled_bit  1
0050 
0051 static bool is_enabled(struct uart_port *port, int bit)
0052 {
0053     unsigned long *private_data = (unsigned long *)&port->private_data;
0054 
0055     if (test_bit(bit, private_data))
0056         return true;
0057     return false;
0058 }
0059 
0060 static void enable(struct uart_port *port, int bit)
0061 {
0062     unsigned long *private_data = (unsigned long *)&port->private_data;
0063 
0064     set_bit(bit, private_data);
0065 }
0066 
0067 static void disable(struct uart_port *port, int bit)
0068 {
0069     unsigned long *private_data = (unsigned long *)&port->private_data;
0070 
0071     clear_bit(bit, private_data);
0072 }
0073 
0074 #define is_tx_enabled(port) is_enabled(port, tx_enabled_bit)
0075 #define tx_enable(port)     enable(port, tx_enabled_bit)
0076 #define tx_disable(port)    disable(port, tx_enabled_bit)
0077 
0078 #define is_rx_enabled(port) is_enabled(port, rx_enabled_bit)
0079 #define rx_enable(port)     enable(port, rx_enabled_bit)
0080 #define rx_disable(port)    disable(port, rx_enabled_bit)
0081 
0082 /*
0083  * The documented expression for selecting the divisor is:
0084  *  BAUD_BASE / baud - 1
0085  * However, typically BAUD_BASE is not divisible by baud, so
0086  * we want to select the divisor that gives us the minimum
0087  * error.  Therefore, we want:
0088  *  int(BAUD_BASE / baud - 0.5) ->
0089  *  int(BAUD_BASE / baud - (baud >> 1) / baud) ->
0090  *  int((BAUD_BASE - (baud >> 1)) / baud)
0091  */
0092 
0093 static void serial21285_stop_tx(struct uart_port *port)
0094 {
0095     if (is_tx_enabled(port)) {
0096         disable_irq_nosync(IRQ_CONTX);
0097         tx_disable(port);
0098     }
0099 }
0100 
0101 static void serial21285_start_tx(struct uart_port *port)
0102 {
0103     if (!is_tx_enabled(port)) {
0104         enable_irq(IRQ_CONTX);
0105         tx_enable(port);
0106     }
0107 }
0108 
0109 static void serial21285_stop_rx(struct uart_port *port)
0110 {
0111     if (is_rx_enabled(port)) {
0112         disable_irq_nosync(IRQ_CONRX);
0113         rx_disable(port);
0114     }
0115 }
0116 
0117 static irqreturn_t serial21285_rx_chars(int irq, void *dev_id)
0118 {
0119     struct uart_port *port = dev_id;
0120     unsigned int status, ch, flag, rxs, max_count = 256;
0121 
0122     status = *CSR_UARTFLG;
0123     while (!(status & 0x10) && max_count--) {
0124         ch = *CSR_UARTDR;
0125         flag = TTY_NORMAL;
0126         port->icount.rx++;
0127 
0128         rxs = *CSR_RXSTAT | RXSTAT_DUMMY_READ;
0129         if (unlikely(rxs & RXSTAT_ANYERR)) {
0130             if (rxs & RXSTAT_PARITY)
0131                 port->icount.parity++;
0132             else if (rxs & RXSTAT_FRAME)
0133                 port->icount.frame++;
0134             if (rxs & RXSTAT_OVERRUN)
0135                 port->icount.overrun++;
0136 
0137             rxs &= port->read_status_mask;
0138 
0139             if (rxs & RXSTAT_PARITY)
0140                 flag = TTY_PARITY;
0141             else if (rxs & RXSTAT_FRAME)
0142                 flag = TTY_FRAME;
0143         }
0144 
0145         uart_insert_char(port, rxs, RXSTAT_OVERRUN, ch, flag);
0146 
0147         status = *CSR_UARTFLG;
0148     }
0149     tty_flip_buffer_push(&port->state->port);
0150 
0151     return IRQ_HANDLED;
0152 }
0153 
0154 static irqreturn_t serial21285_tx_chars(int irq, void *dev_id)
0155 {
0156     struct uart_port *port = dev_id;
0157     struct circ_buf *xmit = &port->state->xmit;
0158     int count = 256;
0159 
0160     if (port->x_char) {
0161         *CSR_UARTDR = port->x_char;
0162         port->icount.tx++;
0163         port->x_char = 0;
0164         goto out;
0165     }
0166     if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
0167         serial21285_stop_tx(port);
0168         goto out;
0169     }
0170 
0171     do {
0172         *CSR_UARTDR = xmit->buf[xmit->tail];
0173         xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
0174         port->icount.tx++;
0175         if (uart_circ_empty(xmit))
0176             break;
0177     } while (--count > 0 && !(*CSR_UARTFLG & 0x20));
0178 
0179     if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
0180         uart_write_wakeup(port);
0181 
0182     if (uart_circ_empty(xmit))
0183         serial21285_stop_tx(port);
0184 
0185  out:
0186     return IRQ_HANDLED;
0187 }
0188 
0189 static unsigned int serial21285_tx_empty(struct uart_port *port)
0190 {
0191     return (*CSR_UARTFLG & 8) ? 0 : TIOCSER_TEMT;
0192 }
0193 
0194 /* no modem control lines */
0195 static unsigned int serial21285_get_mctrl(struct uart_port *port)
0196 {
0197     return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
0198 }
0199 
0200 static void serial21285_set_mctrl(struct uart_port *port, unsigned int mctrl)
0201 {
0202 }
0203 
0204 static void serial21285_break_ctl(struct uart_port *port, int break_state)
0205 {
0206     unsigned long flags;
0207     unsigned int h_lcr;
0208 
0209     spin_lock_irqsave(&port->lock, flags);
0210     h_lcr = *CSR_H_UBRLCR;
0211     if (break_state)
0212         h_lcr |= H_UBRLCR_BREAK;
0213     else
0214         h_lcr &= ~H_UBRLCR_BREAK;
0215     *CSR_H_UBRLCR = h_lcr;
0216     spin_unlock_irqrestore(&port->lock, flags);
0217 }
0218 
0219 static int serial21285_startup(struct uart_port *port)
0220 {
0221     int ret;
0222 
0223     tx_enable(port);
0224     rx_enable(port);
0225 
0226     ret = request_irq(IRQ_CONRX, serial21285_rx_chars, 0,
0227               serial21285_name, port);
0228     if (ret == 0) {
0229         ret = request_irq(IRQ_CONTX, serial21285_tx_chars, 0,
0230                   serial21285_name, port);
0231         if (ret)
0232             free_irq(IRQ_CONRX, port);
0233     }
0234 
0235     return ret;
0236 }
0237 
0238 static void serial21285_shutdown(struct uart_port *port)
0239 {
0240     free_irq(IRQ_CONTX, port);
0241     free_irq(IRQ_CONRX, port);
0242 }
0243 
0244 static void
0245 serial21285_set_termios(struct uart_port *port, struct ktermios *termios,
0246             struct ktermios *old)
0247 {
0248     unsigned long flags;
0249     unsigned int baud, quot, h_lcr, b;
0250 
0251     /*
0252      * We don't support modem control lines.
0253      */
0254     termios->c_cflag &= ~(HUPCL | CRTSCTS | CMSPAR);
0255     termios->c_cflag |= CLOCAL;
0256 
0257     /*
0258      * We don't support BREAK character recognition.
0259      */
0260     termios->c_iflag &= ~(IGNBRK | BRKINT);
0261 
0262     /*
0263      * Ask the core to calculate the divisor for us.
0264      */
0265     baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 
0266     quot = uart_get_divisor(port, baud);
0267     b = port->uartclk / (16 * quot);
0268     tty_termios_encode_baud_rate(termios, b, b);
0269 
0270     switch (termios->c_cflag & CSIZE) {
0271     case CS5:
0272         h_lcr = 0x00;
0273         break;
0274     case CS6:
0275         h_lcr = 0x20;
0276         break;
0277     case CS7:
0278         h_lcr = 0x40;
0279         break;
0280     default: /* CS8 */
0281         h_lcr = 0x60;
0282         break;
0283     }
0284 
0285     if (termios->c_cflag & CSTOPB)
0286         h_lcr |= H_UBRLCR_STOPB;
0287     if (termios->c_cflag & PARENB) {
0288         h_lcr |= H_UBRLCR_PARENB;
0289         if (!(termios->c_cflag & PARODD))
0290             h_lcr |= H_UBRLCR_PAREVN;
0291     }
0292 
0293     if (port->fifosize)
0294         h_lcr |= H_UBRLCR_FIFO;
0295 
0296     spin_lock_irqsave(&port->lock, flags);
0297 
0298     /*
0299      * Update the per-port timeout.
0300      */
0301     uart_update_timeout(port, termios->c_cflag, baud);
0302 
0303     /*
0304      * Which character status flags are we interested in?
0305      */
0306     port->read_status_mask = RXSTAT_OVERRUN;
0307     if (termios->c_iflag & INPCK)
0308         port->read_status_mask |= RXSTAT_FRAME | RXSTAT_PARITY;
0309 
0310     /*
0311      * Which character status flags should we ignore?
0312      */
0313     port->ignore_status_mask = 0;
0314     if (termios->c_iflag & IGNPAR)
0315         port->ignore_status_mask |= RXSTAT_FRAME | RXSTAT_PARITY;
0316     if (termios->c_iflag & IGNBRK && termios->c_iflag & IGNPAR)
0317         port->ignore_status_mask |= RXSTAT_OVERRUN;
0318 
0319     /*
0320      * Ignore all characters if CREAD is not set.
0321      */
0322     if ((termios->c_cflag & CREAD) == 0)
0323         port->ignore_status_mask |= RXSTAT_DUMMY_READ;
0324 
0325     quot -= 1;
0326 
0327     *CSR_UARTCON = 0;
0328     *CSR_L_UBRLCR = quot & 0xff;
0329     *CSR_M_UBRLCR = (quot >> 8) & 0x0f;
0330     *CSR_H_UBRLCR = h_lcr;
0331     *CSR_UARTCON = 1;
0332 
0333     spin_unlock_irqrestore(&port->lock, flags);
0334 }
0335 
0336 static const char *serial21285_type(struct uart_port *port)
0337 {
0338     return port->type == PORT_21285 ? "DC21285" : NULL;
0339 }
0340 
0341 static void serial21285_release_port(struct uart_port *port)
0342 {
0343     release_mem_region(port->mapbase, 32);
0344 }
0345 
0346 static int serial21285_request_port(struct uart_port *port)
0347 {
0348     return request_mem_region(port->mapbase, 32, serial21285_name)
0349              != NULL ? 0 : -EBUSY;
0350 }
0351 
0352 static void serial21285_config_port(struct uart_port *port, int flags)
0353 {
0354     if (flags & UART_CONFIG_TYPE && serial21285_request_port(port) == 0)
0355         port->type = PORT_21285;
0356 }
0357 
0358 /*
0359  * verify the new serial_struct (for TIOCSSERIAL).
0360  */
0361 static int serial21285_verify_port(struct uart_port *port, struct serial_struct *ser)
0362 {
0363     int ret = 0;
0364     if (ser->type != PORT_UNKNOWN && ser->type != PORT_21285)
0365         ret = -EINVAL;
0366     if (ser->irq <= 0)
0367         ret = -EINVAL;
0368     if (ser->baud_base != port->uartclk / 16)
0369         ret = -EINVAL;
0370     return ret;
0371 }
0372 
0373 static const struct uart_ops serial21285_ops = {
0374     .tx_empty   = serial21285_tx_empty,
0375     .get_mctrl  = serial21285_get_mctrl,
0376     .set_mctrl  = serial21285_set_mctrl,
0377     .stop_tx    = serial21285_stop_tx,
0378     .start_tx   = serial21285_start_tx,
0379     .stop_rx    = serial21285_stop_rx,
0380     .break_ctl  = serial21285_break_ctl,
0381     .startup    = serial21285_startup,
0382     .shutdown   = serial21285_shutdown,
0383     .set_termios    = serial21285_set_termios,
0384     .type       = serial21285_type,
0385     .release_port   = serial21285_release_port,
0386     .request_port   = serial21285_request_port,
0387     .config_port    = serial21285_config_port,
0388     .verify_port    = serial21285_verify_port,
0389 };
0390 
0391 static struct uart_port serial21285_port = {
0392     .mapbase    = 0x42000160,
0393     .iotype     = UPIO_MEM,
0394     .irq        = 0,
0395     .fifosize   = 16,
0396     .ops        = &serial21285_ops,
0397     .flags      = UPF_BOOT_AUTOCONF,
0398 };
0399 
0400 static void serial21285_setup_ports(void)
0401 {
0402     serial21285_port.uartclk = mem_fclk_21285 / 4;
0403 }
0404 
0405 #ifdef CONFIG_SERIAL_21285_CONSOLE
0406 static void serial21285_console_putchar(struct uart_port *port, unsigned char ch)
0407 {
0408     while (*CSR_UARTFLG & 0x20)
0409         barrier();
0410     *CSR_UARTDR = ch;
0411 }
0412 
0413 static void
0414 serial21285_console_write(struct console *co, const char *s,
0415               unsigned int count)
0416 {
0417     uart_console_write(&serial21285_port, s, count, serial21285_console_putchar);
0418 }
0419 
0420 static void __init
0421 serial21285_get_options(struct uart_port *port, int *baud,
0422             int *parity, int *bits)
0423 {
0424     if (*CSR_UARTCON == 1) {
0425         unsigned int tmp;
0426 
0427         tmp = *CSR_H_UBRLCR;
0428         switch (tmp & 0x60) {
0429         case 0x00:
0430             *bits = 5;
0431             break;
0432         case 0x20:
0433             *bits = 6;
0434             break;
0435         case 0x40:
0436             *bits = 7;
0437             break;
0438         default:
0439         case 0x60:
0440             *bits = 8;
0441             break;
0442         }
0443 
0444         if (tmp & H_UBRLCR_PARENB) {
0445             *parity = 'o';
0446             if (tmp & H_UBRLCR_PAREVN)
0447                 *parity = 'e';
0448         }
0449 
0450         tmp = *CSR_L_UBRLCR | (*CSR_M_UBRLCR << 8);
0451 
0452         *baud = port->uartclk / (16 * (tmp + 1));
0453     }
0454 }
0455 
0456 static int __init serial21285_console_setup(struct console *co, char *options)
0457 {
0458     struct uart_port *port = &serial21285_port;
0459     int baud = 9600;
0460     int bits = 8;
0461     int parity = 'n';
0462     int flow = 'n';
0463 
0464     if (machine_is_personal_server())
0465         baud = 57600;
0466 
0467     /*
0468      * Check whether an invalid uart number has been specified, and
0469      * if so, search for the first available port that does have
0470      * console support.
0471      */
0472     if (options)
0473         uart_parse_options(options, &baud, &parity, &bits, &flow);
0474     else
0475         serial21285_get_options(port, &baud, &parity, &bits);
0476 
0477     return uart_set_options(port, co, baud, parity, bits, flow);
0478 }
0479 
0480 static struct uart_driver serial21285_reg;
0481 
0482 static struct console serial21285_console =
0483 {
0484     .name       = SERIAL_21285_NAME,
0485     .write      = serial21285_console_write,
0486     .device     = uart_console_device,
0487     .setup      = serial21285_console_setup,
0488     .flags      = CON_PRINTBUFFER,
0489     .index      = -1,
0490     .data       = &serial21285_reg,
0491 };
0492 
0493 static int __init rs285_console_init(void)
0494 {
0495     serial21285_setup_ports();
0496     register_console(&serial21285_console);
0497     return 0;
0498 }
0499 console_initcall(rs285_console_init);
0500 
0501 #define SERIAL_21285_CONSOLE    &serial21285_console
0502 #else
0503 #define SERIAL_21285_CONSOLE    NULL
0504 #endif
0505 
0506 static struct uart_driver serial21285_reg = {
0507     .owner          = THIS_MODULE,
0508     .driver_name        = "ttyFB",
0509     .dev_name       = "ttyFB",
0510     .major          = SERIAL_21285_MAJOR,
0511     .minor          = SERIAL_21285_MINOR,
0512     .nr         = 1,
0513     .cons           = SERIAL_21285_CONSOLE,
0514 };
0515 
0516 static int __init serial21285_init(void)
0517 {
0518     int ret;
0519 
0520     printk(KERN_INFO "Serial: 21285 driver\n");
0521 
0522     serial21285_setup_ports();
0523 
0524     ret = uart_register_driver(&serial21285_reg);
0525     if (ret == 0)
0526         uart_add_one_port(&serial21285_reg, &serial21285_port);
0527 
0528     return ret;
0529 }
0530 
0531 static void __exit serial21285_exit(void)
0532 {
0533     uart_remove_one_port(&serial21285_reg, &serial21285_port);
0534     uart_unregister_driver(&serial21285_reg);
0535 }
0536 
0537 module_init(serial21285_init);
0538 module_exit(serial21285_exit);
0539 
0540 MODULE_LICENSE("GPL");
0541 MODULE_DESCRIPTION("Intel Footbridge (21285) serial driver");
0542 MODULE_ALIAS_CHARDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR);