root/drivers/tty/serial/21285.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. serial21285_stop_tx
  2. serial21285_start_tx
  3. serial21285_stop_rx
  4. serial21285_rx_chars
  5. serial21285_tx_chars
  6. serial21285_tx_empty
  7. serial21285_get_mctrl
  8. serial21285_set_mctrl
  9. serial21285_break_ctl
  10. serial21285_startup
  11. serial21285_shutdown
  12. serial21285_set_termios
  13. serial21285_type
  14. serial21285_release_port
  15. serial21285_request_port
  16. serial21285_config_port
  17. serial21285_verify_port
  18. serial21285_setup_ports
  19. serial21285_console_putchar
  20. serial21285_console_write
  21. serial21285_get_options
  22. serial21285_console_setup
  23. rs285_console_init
  24. serial21285_init
  25. serial21285_exit

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Driver for the serial port on the 21285 StrongArm-110 core logic chip.
   4  *
   5  * Based on drivers/char/serial.c
   6  */
   7 #include <linux/module.h>
   8 #include <linux/tty.h>
   9 #include <linux/ioport.h>
  10 #include <linux/init.h>
  11 #include <linux/console.h>
  12 #include <linux/device.h>
  13 #include <linux/tty_flip.h>
  14 #include <linux/serial_core.h>
  15 #include <linux/serial.h>
  16 #include <linux/io.h>
  17 
  18 #include <asm/irq.h>
  19 #include <asm/mach-types.h>
  20 #include <asm/system_info.h>
  21 #include <asm/hardware/dec21285.h>
  22 #include <mach/hardware.h>
  23 
  24 #define BAUD_BASE               (mem_fclk_21285/64)
  25 
  26 #define SERIAL_21285_NAME       "ttyFB"
  27 #define SERIAL_21285_MAJOR      204
  28 #define SERIAL_21285_MINOR      4
  29 
  30 #define RXSTAT_DUMMY_READ       0x80000000
  31 #define RXSTAT_FRAME            (1 << 0)
  32 #define RXSTAT_PARITY           (1 << 1)
  33 #define RXSTAT_OVERRUN          (1 << 2)
  34 #define RXSTAT_ANYERR           (RXSTAT_FRAME|RXSTAT_PARITY|RXSTAT_OVERRUN)
  35 
  36 #define H_UBRLCR_BREAK          (1 << 0)
  37 #define H_UBRLCR_PARENB         (1 << 1)
  38 #define H_UBRLCR_PAREVN         (1 << 2)
  39 #define H_UBRLCR_STOPB          (1 << 3)
  40 #define H_UBRLCR_FIFO           (1 << 4)
  41 
  42 static const char serial21285_name[] = "Footbridge UART";
  43 
  44 #define tx_enabled(port)        ((port)->unused[0])
  45 #define rx_enabled(port)        ((port)->unused[1])
  46 
  47 /*
  48  * The documented expression for selecting the divisor is:
  49  *  BAUD_BASE / baud - 1
  50  * However, typically BAUD_BASE is not divisible by baud, so
  51  * we want to select the divisor that gives us the minimum
  52  * error.  Therefore, we want:
  53  *  int(BAUD_BASE / baud - 0.5) ->
  54  *  int(BAUD_BASE / baud - (baud >> 1) / baud) ->
  55  *  int((BAUD_BASE - (baud >> 1)) / baud)
  56  */
  57 
  58 static void serial21285_stop_tx(struct uart_port *port)
  59 {
  60         if (tx_enabled(port)) {
  61                 disable_irq_nosync(IRQ_CONTX);
  62                 tx_enabled(port) = 0;
  63         }
  64 }
  65 
  66 static void serial21285_start_tx(struct uart_port *port)
  67 {
  68         if (!tx_enabled(port)) {
  69                 enable_irq(IRQ_CONTX);
  70                 tx_enabled(port) = 1;
  71         }
  72 }
  73 
  74 static void serial21285_stop_rx(struct uart_port *port)
  75 {
  76         if (rx_enabled(port)) {
  77                 disable_irq_nosync(IRQ_CONRX);
  78                 rx_enabled(port) = 0;
  79         }
  80 }
  81 
  82 static irqreturn_t serial21285_rx_chars(int irq, void *dev_id)
  83 {
  84         struct uart_port *port = dev_id;
  85         unsigned int status, ch, flag, rxs, max_count = 256;
  86 
  87         status = *CSR_UARTFLG;
  88         while (!(status & 0x10) && max_count--) {
  89                 ch = *CSR_UARTDR;
  90                 flag = TTY_NORMAL;
  91                 port->icount.rx++;
  92 
  93                 rxs = *CSR_RXSTAT | RXSTAT_DUMMY_READ;
  94                 if (unlikely(rxs & RXSTAT_ANYERR)) {
  95                         if (rxs & RXSTAT_PARITY)
  96                                 port->icount.parity++;
  97                         else if (rxs & RXSTAT_FRAME)
  98                                 port->icount.frame++;
  99                         if (rxs & RXSTAT_OVERRUN)
 100                                 port->icount.overrun++;
 101 
 102                         rxs &= port->read_status_mask;
 103 
 104                         if (rxs & RXSTAT_PARITY)
 105                                 flag = TTY_PARITY;
 106                         else if (rxs & RXSTAT_FRAME)
 107                                 flag = TTY_FRAME;
 108                 }
 109 
 110                 uart_insert_char(port, rxs, RXSTAT_OVERRUN, ch, flag);
 111 
 112                 status = *CSR_UARTFLG;
 113         }
 114         tty_flip_buffer_push(&port->state->port);
 115 
 116         return IRQ_HANDLED;
 117 }
 118 
 119 static irqreturn_t serial21285_tx_chars(int irq, void *dev_id)
 120 {
 121         struct uart_port *port = dev_id;
 122         struct circ_buf *xmit = &port->state->xmit;
 123         int count = 256;
 124 
 125         if (port->x_char) {
 126                 *CSR_UARTDR = port->x_char;
 127                 port->icount.tx++;
 128                 port->x_char = 0;
 129                 goto out;
 130         }
 131         if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
 132                 serial21285_stop_tx(port);
 133                 goto out;
 134         }
 135 
 136         do {
 137                 *CSR_UARTDR = xmit->buf[xmit->tail];
 138                 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
 139                 port->icount.tx++;
 140                 if (uart_circ_empty(xmit))
 141                         break;
 142         } while (--count > 0 && !(*CSR_UARTFLG & 0x20));
 143 
 144         if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 145                 uart_write_wakeup(port);
 146 
 147         if (uart_circ_empty(xmit))
 148                 serial21285_stop_tx(port);
 149 
 150  out:
 151         return IRQ_HANDLED;
 152 }
 153 
 154 static unsigned int serial21285_tx_empty(struct uart_port *port)
 155 {
 156         return (*CSR_UARTFLG & 8) ? 0 : TIOCSER_TEMT;
 157 }
 158 
 159 /* no modem control lines */
 160 static unsigned int serial21285_get_mctrl(struct uart_port *port)
 161 {
 162         return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
 163 }
 164 
 165 static void serial21285_set_mctrl(struct uart_port *port, unsigned int mctrl)
 166 {
 167 }
 168 
 169 static void serial21285_break_ctl(struct uart_port *port, int break_state)
 170 {
 171         unsigned long flags;
 172         unsigned int h_lcr;
 173 
 174         spin_lock_irqsave(&port->lock, flags);
 175         h_lcr = *CSR_H_UBRLCR;
 176         if (break_state)
 177                 h_lcr |= H_UBRLCR_BREAK;
 178         else
 179                 h_lcr &= ~H_UBRLCR_BREAK;
 180         *CSR_H_UBRLCR = h_lcr;
 181         spin_unlock_irqrestore(&port->lock, flags);
 182 }
 183 
 184 static int serial21285_startup(struct uart_port *port)
 185 {
 186         int ret;
 187 
 188         tx_enabled(port) = 1;
 189         rx_enabled(port) = 1;
 190 
 191         ret = request_irq(IRQ_CONRX, serial21285_rx_chars, 0,
 192                           serial21285_name, port);
 193         if (ret == 0) {
 194                 ret = request_irq(IRQ_CONTX, serial21285_tx_chars, 0,
 195                                   serial21285_name, port);
 196                 if (ret)
 197                         free_irq(IRQ_CONRX, port);
 198         }
 199 
 200         return ret;
 201 }
 202 
 203 static void serial21285_shutdown(struct uart_port *port)
 204 {
 205         free_irq(IRQ_CONTX, port);
 206         free_irq(IRQ_CONRX, port);
 207 }
 208 
 209 static void
 210 serial21285_set_termios(struct uart_port *port, struct ktermios *termios,
 211                         struct ktermios *old)
 212 {
 213         unsigned long flags;
 214         unsigned int baud, quot, h_lcr, b;
 215 
 216         /*
 217          * We don't support modem control lines.
 218          */
 219         termios->c_cflag &= ~(HUPCL | CRTSCTS | CMSPAR);
 220         termios->c_cflag |= CLOCAL;
 221 
 222         /*
 223          * We don't support BREAK character recognition.
 224          */
 225         termios->c_iflag &= ~(IGNBRK | BRKINT);
 226 
 227         /*
 228          * Ask the core to calculate the divisor for us.
 229          */
 230         baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 
 231         quot = uart_get_divisor(port, baud);
 232         b = port->uartclk / (16 * quot);
 233         tty_termios_encode_baud_rate(termios, b, b);
 234 
 235         switch (termios->c_cflag & CSIZE) {
 236         case CS5:
 237                 h_lcr = 0x00;
 238                 break;
 239         case CS6:
 240                 h_lcr = 0x20;
 241                 break;
 242         case CS7:
 243                 h_lcr = 0x40;
 244                 break;
 245         default: /* CS8 */
 246                 h_lcr = 0x60;
 247                 break;
 248         }
 249 
 250         if (termios->c_cflag & CSTOPB)
 251                 h_lcr |= H_UBRLCR_STOPB;
 252         if (termios->c_cflag & PARENB) {
 253                 h_lcr |= H_UBRLCR_PARENB;
 254                 if (!(termios->c_cflag & PARODD))
 255                         h_lcr |= H_UBRLCR_PAREVN;
 256         }
 257 
 258         if (port->fifosize)
 259                 h_lcr |= H_UBRLCR_FIFO;
 260 
 261         spin_lock_irqsave(&port->lock, flags);
 262 
 263         /*
 264          * Update the per-port timeout.
 265          */
 266         uart_update_timeout(port, termios->c_cflag, baud);
 267 
 268         /*
 269          * Which character status flags are we interested in?
 270          */
 271         port->read_status_mask = RXSTAT_OVERRUN;
 272         if (termios->c_iflag & INPCK)
 273                 port->read_status_mask |= RXSTAT_FRAME | RXSTAT_PARITY;
 274 
 275         /*
 276          * Which character status flags should we ignore?
 277          */
 278         port->ignore_status_mask = 0;
 279         if (termios->c_iflag & IGNPAR)
 280                 port->ignore_status_mask |= RXSTAT_FRAME | RXSTAT_PARITY;
 281         if (termios->c_iflag & IGNBRK && termios->c_iflag & IGNPAR)
 282                 port->ignore_status_mask |= RXSTAT_OVERRUN;
 283 
 284         /*
 285          * Ignore all characters if CREAD is not set.
 286          */
 287         if ((termios->c_cflag & CREAD) == 0)
 288                 port->ignore_status_mask |= RXSTAT_DUMMY_READ;
 289 
 290         quot -= 1;
 291 
 292         *CSR_UARTCON = 0;
 293         *CSR_L_UBRLCR = quot & 0xff;
 294         *CSR_M_UBRLCR = (quot >> 8) & 0x0f;
 295         *CSR_H_UBRLCR = h_lcr;
 296         *CSR_UARTCON = 1;
 297 
 298         spin_unlock_irqrestore(&port->lock, flags);
 299 }
 300 
 301 static const char *serial21285_type(struct uart_port *port)
 302 {
 303         return port->type == PORT_21285 ? "DC21285" : NULL;
 304 }
 305 
 306 static void serial21285_release_port(struct uart_port *port)
 307 {
 308         release_mem_region(port->mapbase, 32);
 309 }
 310 
 311 static int serial21285_request_port(struct uart_port *port)
 312 {
 313         return request_mem_region(port->mapbase, 32, serial21285_name)
 314                          != NULL ? 0 : -EBUSY;
 315 }
 316 
 317 static void serial21285_config_port(struct uart_port *port, int flags)
 318 {
 319         if (flags & UART_CONFIG_TYPE && serial21285_request_port(port) == 0)
 320                 port->type = PORT_21285;
 321 }
 322 
 323 /*
 324  * verify the new serial_struct (for TIOCSSERIAL).
 325  */
 326 static int serial21285_verify_port(struct uart_port *port, struct serial_struct *ser)
 327 {
 328         int ret = 0;
 329         if (ser->type != PORT_UNKNOWN && ser->type != PORT_21285)
 330                 ret = -EINVAL;
 331         if (ser->irq <= 0)
 332                 ret = -EINVAL;
 333         if (ser->baud_base != port->uartclk / 16)
 334                 ret = -EINVAL;
 335         return ret;
 336 }
 337 
 338 static const struct uart_ops serial21285_ops = {
 339         .tx_empty       = serial21285_tx_empty,
 340         .get_mctrl      = serial21285_get_mctrl,
 341         .set_mctrl      = serial21285_set_mctrl,
 342         .stop_tx        = serial21285_stop_tx,
 343         .start_tx       = serial21285_start_tx,
 344         .stop_rx        = serial21285_stop_rx,
 345         .break_ctl      = serial21285_break_ctl,
 346         .startup        = serial21285_startup,
 347         .shutdown       = serial21285_shutdown,
 348         .set_termios    = serial21285_set_termios,
 349         .type           = serial21285_type,
 350         .release_port   = serial21285_release_port,
 351         .request_port   = serial21285_request_port,
 352         .config_port    = serial21285_config_port,
 353         .verify_port    = serial21285_verify_port,
 354 };
 355 
 356 static struct uart_port serial21285_port = {
 357         .mapbase        = 0x42000160,
 358         .iotype         = UPIO_MEM,
 359         .irq            = 0,
 360         .fifosize       = 16,
 361         .ops            = &serial21285_ops,
 362         .flags          = UPF_BOOT_AUTOCONF,
 363 };
 364 
 365 static void serial21285_setup_ports(void)
 366 {
 367         serial21285_port.uartclk = mem_fclk_21285 / 4;
 368 }
 369 
 370 #ifdef CONFIG_SERIAL_21285_CONSOLE
 371 static void serial21285_console_putchar(struct uart_port *port, int ch)
 372 {
 373         while (*CSR_UARTFLG & 0x20)
 374                 barrier();
 375         *CSR_UARTDR = ch;
 376 }
 377 
 378 static void
 379 serial21285_console_write(struct console *co, const char *s,
 380                           unsigned int count)
 381 {
 382         uart_console_write(&serial21285_port, s, count, serial21285_console_putchar);
 383 }
 384 
 385 static void __init
 386 serial21285_get_options(struct uart_port *port, int *baud,
 387                         int *parity, int *bits)
 388 {
 389         if (*CSR_UARTCON == 1) {
 390                 unsigned int tmp;
 391 
 392                 tmp = *CSR_H_UBRLCR;
 393                 switch (tmp & 0x60) {
 394                 case 0x00:
 395                         *bits = 5;
 396                         break;
 397                 case 0x20:
 398                         *bits = 6;
 399                         break;
 400                 case 0x40:
 401                         *bits = 7;
 402                         break;
 403                 default:
 404                 case 0x60:
 405                         *bits = 8;
 406                         break;
 407                 }
 408 
 409                 if (tmp & H_UBRLCR_PARENB) {
 410                         *parity = 'o';
 411                         if (tmp & H_UBRLCR_PAREVN)
 412                                 *parity = 'e';
 413                 }
 414 
 415                 tmp = *CSR_L_UBRLCR | (*CSR_M_UBRLCR << 8);
 416 
 417                 *baud = port->uartclk / (16 * (tmp + 1));
 418         }
 419 }
 420 
 421 static int __init serial21285_console_setup(struct console *co, char *options)
 422 {
 423         struct uart_port *port = &serial21285_port;
 424         int baud = 9600;
 425         int bits = 8;
 426         int parity = 'n';
 427         int flow = 'n';
 428 
 429         if (machine_is_personal_server())
 430                 baud = 57600;
 431 
 432         /*
 433          * Check whether an invalid uart number has been specified, and
 434          * if so, search for the first available port that does have
 435          * console support.
 436          */
 437         if (options)
 438                 uart_parse_options(options, &baud, &parity, &bits, &flow);
 439         else
 440                 serial21285_get_options(port, &baud, &parity, &bits);
 441 
 442         return uart_set_options(port, co, baud, parity, bits, flow);
 443 }
 444 
 445 static struct uart_driver serial21285_reg;
 446 
 447 static struct console serial21285_console =
 448 {
 449         .name           = SERIAL_21285_NAME,
 450         .write          = serial21285_console_write,
 451         .device         = uart_console_device,
 452         .setup          = serial21285_console_setup,
 453         .flags          = CON_PRINTBUFFER,
 454         .index          = -1,
 455         .data           = &serial21285_reg,
 456 };
 457 
 458 static int __init rs285_console_init(void)
 459 {
 460         serial21285_setup_ports();
 461         register_console(&serial21285_console);
 462         return 0;
 463 }
 464 console_initcall(rs285_console_init);
 465 
 466 #define SERIAL_21285_CONSOLE    &serial21285_console
 467 #else
 468 #define SERIAL_21285_CONSOLE    NULL
 469 #endif
 470 
 471 static struct uart_driver serial21285_reg = {
 472         .owner                  = THIS_MODULE,
 473         .driver_name            = "ttyFB",
 474         .dev_name               = "ttyFB",
 475         .major                  = SERIAL_21285_MAJOR,
 476         .minor                  = SERIAL_21285_MINOR,
 477         .nr                     = 1,
 478         .cons                   = SERIAL_21285_CONSOLE,
 479 };
 480 
 481 static int __init serial21285_init(void)
 482 {
 483         int ret;
 484 
 485         printk(KERN_INFO "Serial: 21285 driver\n");
 486 
 487         serial21285_setup_ports();
 488 
 489         ret = uart_register_driver(&serial21285_reg);
 490         if (ret == 0)
 491                 uart_add_one_port(&serial21285_reg, &serial21285_port);
 492 
 493         return ret;
 494 }
 495 
 496 static void __exit serial21285_exit(void)
 497 {
 498         uart_remove_one_port(&serial21285_reg, &serial21285_port);
 499         uart_unregister_driver(&serial21285_reg);
 500 }
 501 
 502 module_init(serial21285_init);
 503 module_exit(serial21285_exit);
 504 
 505 MODULE_LICENSE("GPL");
 506 MODULE_DESCRIPTION("Intel Footbridge (21285) serial driver");
 507 MODULE_ALIAS_CHARDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR);

/* [<][>][^][v][top][bottom][index][help] */