root/drivers/tty/serial/sunhv.c

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

DEFINITIONS

This source file includes following definitions.
  1. transmit_chars_putchar
  2. transmit_chars_write
  3. receive_chars_getchar
  4. receive_chars_read
  5. receive_chars
  6. transmit_chars
  7. sunhv_interrupt
  8. sunhv_tx_empty
  9. sunhv_set_mctrl
  10. sunhv_get_mctrl
  11. sunhv_stop_tx
  12. sunhv_start_tx
  13. sunhv_send_xchar
  14. sunhv_stop_rx
  15. sunhv_break_ctl
  16. sunhv_startup
  17. sunhv_shutdown
  18. sunhv_set_termios
  19. sunhv_type
  20. sunhv_release_port
  21. sunhv_request_port
  22. sunhv_config_port
  23. sunhv_verify_port
  24. sunhv_migrate_hvcons_irq
  25. fill_con_write_page
  26. sunhv_console_write_paged
  27. sunhv_console_putchar
  28. sunhv_console_write_bychar
  29. hv_probe
  30. hv_remove
  31. sunhv_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 /* sunhv.c: Serial driver for SUN4V hypervisor console.
   3  *
   4  * Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net)
   5  */
   6 
   7 #include <linux/kernel.h>
   8 #include <linux/errno.h>
   9 #include <linux/tty.h>
  10 #include <linux/tty_flip.h>
  11 #include <linux/major.h>
  12 #include <linux/circ_buf.h>
  13 #include <linux/serial.h>
  14 #include <linux/sysrq.h>
  15 #include <linux/console.h>
  16 #include <linux/spinlock.h>
  17 #include <linux/slab.h>
  18 #include <linux/delay.h>
  19 #include <linux/init.h>
  20 #include <linux/of_device.h>
  21 
  22 #include <asm/hypervisor.h>
  23 #include <asm/spitfire.h>
  24 #include <asm/prom.h>
  25 #include <asm/irq.h>
  26 #include <asm/setup.h>
  27 
  28 #if defined(CONFIG_MAGIC_SYSRQ)
  29 #define SUPPORT_SYSRQ
  30 #endif
  31 
  32 #include <linux/serial_core.h>
  33 #include <linux/sunserialcore.h>
  34 
  35 #define CON_BREAK       ((long)-1)
  36 #define CON_HUP         ((long)-2)
  37 
  38 #define IGNORE_BREAK    0x1
  39 #define IGNORE_ALL      0x2
  40 
  41 static char *con_write_page;
  42 static char *con_read_page;
  43 
  44 static int hung_up = 0;
  45 
  46 static void transmit_chars_putchar(struct uart_port *port, struct circ_buf *xmit)
  47 {
  48         while (!uart_circ_empty(xmit)) {
  49                 long status = sun4v_con_putchar(xmit->buf[xmit->tail]);
  50 
  51                 if (status != HV_EOK)
  52                         break;
  53 
  54                 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
  55                 port->icount.tx++;
  56         }
  57 }
  58 
  59 static void transmit_chars_write(struct uart_port *port, struct circ_buf *xmit)
  60 {
  61         while (!uart_circ_empty(xmit)) {
  62                 unsigned long ra = __pa(xmit->buf + xmit->tail);
  63                 unsigned long len, status, sent;
  64 
  65                 len = CIRC_CNT_TO_END(xmit->head, xmit->tail,
  66                                       UART_XMIT_SIZE);
  67                 status = sun4v_con_write(ra, len, &sent);
  68                 if (status != HV_EOK)
  69                         break;
  70                 xmit->tail = (xmit->tail + sent) & (UART_XMIT_SIZE - 1);
  71                 port->icount.tx += sent;
  72         }
  73 }
  74 
  75 static int receive_chars_getchar(struct uart_port *port)
  76 {
  77         int saw_console_brk = 0;
  78         int limit = 10000;
  79 
  80         while (limit-- > 0) {
  81                 long status;
  82                 long c = sun4v_con_getchar(&status);
  83 
  84                 if (status == HV_EWOULDBLOCK)
  85                         break;
  86 
  87                 if (c == CON_BREAK) {
  88                         if (uart_handle_break(port))
  89                                 continue;
  90                         saw_console_brk = 1;
  91                         c = 0;
  92                 }
  93 
  94                 if (c == CON_HUP) {
  95                         hung_up = 1;
  96                         uart_handle_dcd_change(port, 0);
  97                 } else if (hung_up) {
  98                         hung_up = 0;
  99                         uart_handle_dcd_change(port, 1);
 100                 }
 101 
 102                 if (port->state == NULL) {
 103                         uart_handle_sysrq_char(port, c);
 104                         continue;
 105                 }
 106 
 107                 port->icount.rx++;
 108 
 109                 if (uart_handle_sysrq_char(port, c))
 110                         continue;
 111 
 112                 tty_insert_flip_char(&port->state->port, c, TTY_NORMAL);
 113         }
 114 
 115         return saw_console_brk;
 116 }
 117 
 118 static int receive_chars_read(struct uart_port *port)
 119 {
 120         static int saw_console_brk;
 121         int limit = 10000;
 122 
 123         while (limit-- > 0) {
 124                 unsigned long ra = __pa(con_read_page);
 125                 unsigned long bytes_read, i;
 126                 long stat = sun4v_con_read(ra, PAGE_SIZE, &bytes_read);
 127 
 128                 if (stat != HV_EOK) {
 129                         bytes_read = 0;
 130 
 131                         if (stat == CON_BREAK) {
 132                                 if (saw_console_brk)
 133                                         sun_do_break();
 134 
 135                                 if (uart_handle_break(port))
 136                                         continue;
 137                                 saw_console_brk = 1;
 138                                 *con_read_page = 0;
 139                                 bytes_read = 1;
 140                         } else if (stat == CON_HUP) {
 141                                 hung_up = 1;
 142                                 uart_handle_dcd_change(port, 0);
 143                                 continue;
 144                         } else {
 145                                 /* HV_EWOULDBLOCK, etc.  */
 146                                 break;
 147                         }
 148                 }
 149 
 150                 if (hung_up) {
 151                         hung_up = 0;
 152                         uart_handle_dcd_change(port, 1);
 153                 }
 154 
 155                 if (port->sysrq != 0 &&  *con_read_page) {
 156                         for (i = 0; i < bytes_read; i++)
 157                                 uart_handle_sysrq_char(port, con_read_page[i]);
 158                         saw_console_brk = 0;
 159                 }
 160 
 161                 if (port->state == NULL)
 162                         continue;
 163 
 164                 port->icount.rx += bytes_read;
 165 
 166                 tty_insert_flip_string(&port->state->port, con_read_page,
 167                                 bytes_read);
 168         }
 169 
 170         return saw_console_brk;
 171 }
 172 
 173 struct sunhv_ops {
 174         void (*transmit_chars)(struct uart_port *port, struct circ_buf *xmit);
 175         int (*receive_chars)(struct uart_port *port);
 176 };
 177 
 178 static const struct sunhv_ops bychar_ops = {
 179         .transmit_chars = transmit_chars_putchar,
 180         .receive_chars = receive_chars_getchar,
 181 };
 182 
 183 static const struct sunhv_ops bywrite_ops = {
 184         .transmit_chars = transmit_chars_write,
 185         .receive_chars = receive_chars_read,
 186 };
 187 
 188 static const struct sunhv_ops *sunhv_ops = &bychar_ops;
 189 
 190 static struct tty_port *receive_chars(struct uart_port *port)
 191 {
 192         struct tty_port *tport = NULL;
 193 
 194         if (port->state != NULL)                /* Unopened serial console */
 195                 tport = &port->state->port;
 196 
 197         if (sunhv_ops->receive_chars(port))
 198                 sun_do_break();
 199 
 200         return tport;
 201 }
 202 
 203 static void transmit_chars(struct uart_port *port)
 204 {
 205         struct circ_buf *xmit;
 206 
 207         if (!port->state)
 208                 return;
 209 
 210         xmit = &port->state->xmit;
 211         if (uart_circ_empty(xmit) || uart_tx_stopped(port))
 212                 return;
 213 
 214         sunhv_ops->transmit_chars(port, xmit);
 215 
 216         if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
 217                 uart_write_wakeup(port);
 218 }
 219 
 220 static irqreturn_t sunhv_interrupt(int irq, void *dev_id)
 221 {
 222         struct uart_port *port = dev_id;
 223         struct tty_port *tport;
 224         unsigned long flags;
 225 
 226         spin_lock_irqsave(&port->lock, flags);
 227         tport = receive_chars(port);
 228         transmit_chars(port);
 229         spin_unlock_irqrestore(&port->lock, flags);
 230 
 231         if (tport)
 232                 tty_flip_buffer_push(tport);
 233 
 234         return IRQ_HANDLED;
 235 }
 236 
 237 /* port->lock is not held.  */
 238 static unsigned int sunhv_tx_empty(struct uart_port *port)
 239 {
 240         /* Transmitter is always empty for us.  If the circ buffer
 241          * is non-empty or there is an x_char pending, our caller
 242          * will do the right thing and ignore what we return here.
 243          */
 244         return TIOCSER_TEMT;
 245 }
 246 
 247 /* port->lock held by caller.  */
 248 static void sunhv_set_mctrl(struct uart_port *port, unsigned int mctrl)
 249 {
 250         return;
 251 }
 252 
 253 /* port->lock is held by caller and interrupts are disabled.  */
 254 static unsigned int sunhv_get_mctrl(struct uart_port *port)
 255 {
 256         return TIOCM_DSR | TIOCM_CAR | TIOCM_CTS;
 257 }
 258 
 259 /* port->lock held by caller.  */
 260 static void sunhv_stop_tx(struct uart_port *port)
 261 {
 262         return;
 263 }
 264 
 265 /* port->lock held by caller.  */
 266 static void sunhv_start_tx(struct uart_port *port)
 267 {
 268         transmit_chars(port);
 269 }
 270 
 271 /* port->lock is not held.  */
 272 static void sunhv_send_xchar(struct uart_port *port, char ch)
 273 {
 274         unsigned long flags;
 275         int limit = 10000;
 276 
 277         if (ch == __DISABLED_CHAR)
 278                 return;
 279 
 280         spin_lock_irqsave(&port->lock, flags);
 281 
 282         while (limit-- > 0) {
 283                 long status = sun4v_con_putchar(ch);
 284                 if (status == HV_EOK)
 285                         break;
 286                 udelay(1);
 287         }
 288 
 289         spin_unlock_irqrestore(&port->lock, flags);
 290 }
 291 
 292 /* port->lock held by caller.  */
 293 static void sunhv_stop_rx(struct uart_port *port)
 294 {
 295 }
 296 
 297 /* port->lock is not held.  */
 298 static void sunhv_break_ctl(struct uart_port *port, int break_state)
 299 {
 300         if (break_state) {
 301                 unsigned long flags;
 302                 int limit = 10000;
 303 
 304                 spin_lock_irqsave(&port->lock, flags);
 305 
 306                 while (limit-- > 0) {
 307                         long status = sun4v_con_putchar(CON_BREAK);
 308                         if (status == HV_EOK)
 309                                 break;
 310                         udelay(1);
 311                 }
 312 
 313                 spin_unlock_irqrestore(&port->lock, flags);
 314         }
 315 }
 316 
 317 /* port->lock is not held.  */
 318 static int sunhv_startup(struct uart_port *port)
 319 {
 320         return 0;
 321 }
 322 
 323 /* port->lock is not held.  */
 324 static void sunhv_shutdown(struct uart_port *port)
 325 {
 326 }
 327 
 328 /* port->lock is not held.  */
 329 static void sunhv_set_termios(struct uart_port *port, struct ktermios *termios,
 330                               struct ktermios *old)
 331 {
 332         unsigned int baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
 333         unsigned int quot = uart_get_divisor(port, baud);
 334         unsigned int iflag, cflag;
 335         unsigned long flags;
 336 
 337         spin_lock_irqsave(&port->lock, flags);
 338 
 339         iflag = termios->c_iflag;
 340         cflag = termios->c_cflag;
 341 
 342         port->ignore_status_mask = 0;
 343         if (iflag & IGNBRK)
 344                 port->ignore_status_mask |= IGNORE_BREAK;
 345         if ((cflag & CREAD) == 0)
 346                 port->ignore_status_mask |= IGNORE_ALL;
 347 
 348         /* XXX */
 349         uart_update_timeout(port, cflag,
 350                             (port->uartclk / (16 * quot)));
 351 
 352         spin_unlock_irqrestore(&port->lock, flags);
 353 }
 354 
 355 static const char *sunhv_type(struct uart_port *port)
 356 {
 357         return "SUN4V HCONS";
 358 }
 359 
 360 static void sunhv_release_port(struct uart_port *port)
 361 {
 362 }
 363 
 364 static int sunhv_request_port(struct uart_port *port)
 365 {
 366         return 0;
 367 }
 368 
 369 static void sunhv_config_port(struct uart_port *port, int flags)
 370 {
 371 }
 372 
 373 static int sunhv_verify_port(struct uart_port *port, struct serial_struct *ser)
 374 {
 375         return -EINVAL;
 376 }
 377 
 378 static const struct uart_ops sunhv_pops = {
 379         .tx_empty       = sunhv_tx_empty,
 380         .set_mctrl      = sunhv_set_mctrl,
 381         .get_mctrl      = sunhv_get_mctrl,
 382         .stop_tx        = sunhv_stop_tx,
 383         .start_tx       = sunhv_start_tx,
 384         .send_xchar     = sunhv_send_xchar,
 385         .stop_rx        = sunhv_stop_rx,
 386         .break_ctl      = sunhv_break_ctl,
 387         .startup        = sunhv_startup,
 388         .shutdown       = sunhv_shutdown,
 389         .set_termios    = sunhv_set_termios,
 390         .type           = sunhv_type,
 391         .release_port   = sunhv_release_port,
 392         .request_port   = sunhv_request_port,
 393         .config_port    = sunhv_config_port,
 394         .verify_port    = sunhv_verify_port,
 395 };
 396 
 397 static struct uart_driver sunhv_reg = {
 398         .owner                  = THIS_MODULE,
 399         .driver_name            = "sunhv",
 400         .dev_name               = "ttyHV",
 401         .major                  = TTY_MAJOR,
 402 };
 403 
 404 static struct uart_port *sunhv_port;
 405 
 406 void sunhv_migrate_hvcons_irq(int cpu)
 407 {
 408         /* Migrate hvcons irq to param cpu */
 409         irq_force_affinity(sunhv_port->irq, cpumask_of(cpu));
 410 }
 411 
 412 /* Copy 's' into the con_write_page, decoding "\n" into
 413  * "\r\n" along the way.  We have to return two lengths
 414  * because the caller needs to know how much to advance
 415  * 's' and also how many bytes to output via con_write_page.
 416  */
 417 static int fill_con_write_page(const char *s, unsigned int n,
 418                                unsigned long *page_bytes)
 419 {
 420         const char *orig_s = s;
 421         char *p = con_write_page;
 422         int left = PAGE_SIZE;
 423 
 424         while (n--) {
 425                 if (*s == '\n') {
 426                         if (left < 2)
 427                                 break;
 428                         *p++ = '\r';
 429                         left--;
 430                 } else if (left < 1)
 431                         break;
 432                 *p++ = *s++;
 433                 left--;
 434         }
 435         *page_bytes = p - con_write_page;
 436         return s - orig_s;
 437 }
 438 
 439 static void sunhv_console_write_paged(struct console *con, const char *s, unsigned n)
 440 {
 441         struct uart_port *port = sunhv_port;
 442         unsigned long flags;
 443         int locked = 1;
 444 
 445         if (port->sysrq || oops_in_progress)
 446                 locked = spin_trylock_irqsave(&port->lock, flags);
 447         else
 448                 spin_lock_irqsave(&port->lock, flags);
 449 
 450         while (n > 0) {
 451                 unsigned long ra = __pa(con_write_page);
 452                 unsigned long page_bytes;
 453                 unsigned int cpy = fill_con_write_page(s, n,
 454                                                        &page_bytes);
 455 
 456                 n -= cpy;
 457                 s += cpy;
 458                 while (page_bytes > 0) {
 459                         unsigned long written;
 460                         int limit = 1000000;
 461 
 462                         while (limit--) {
 463                                 unsigned long stat;
 464 
 465                                 stat = sun4v_con_write(ra, page_bytes,
 466                                                        &written);
 467                                 if (stat == HV_EOK)
 468                                         break;
 469                                 udelay(1);
 470                         }
 471                         if (limit < 0)
 472                                 break;
 473                         page_bytes -= written;
 474                         ra += written;
 475                 }
 476         }
 477 
 478         if (locked)
 479                 spin_unlock_irqrestore(&port->lock, flags);
 480 }
 481 
 482 static inline void sunhv_console_putchar(struct uart_port *port, char c)
 483 {
 484         int limit = 1000000;
 485 
 486         while (limit-- > 0) {
 487                 long status = sun4v_con_putchar(c);
 488                 if (status == HV_EOK)
 489                         break;
 490                 udelay(1);
 491         }
 492 }
 493 
 494 static void sunhv_console_write_bychar(struct console *con, const char *s, unsigned n)
 495 {
 496         struct uart_port *port = sunhv_port;
 497         unsigned long flags;
 498         int i, locked = 1;
 499 
 500         if (port->sysrq || oops_in_progress)
 501                 locked = spin_trylock_irqsave(&port->lock, flags);
 502         else
 503                 spin_lock_irqsave(&port->lock, flags);
 504 
 505         for (i = 0; i < n; i++) {
 506                 if (*s == '\n')
 507                         sunhv_console_putchar(port, '\r');
 508                 sunhv_console_putchar(port, *s++);
 509         }
 510 
 511         if (locked)
 512                 spin_unlock_irqrestore(&port->lock, flags);
 513 }
 514 
 515 static struct console sunhv_console = {
 516         .name   =       "ttyHV",
 517         .write  =       sunhv_console_write_bychar,
 518         .device =       uart_console_device,
 519         .flags  =       CON_PRINTBUFFER,
 520         .index  =       -1,
 521         .data   =       &sunhv_reg,
 522 };
 523 
 524 static int hv_probe(struct platform_device *op)
 525 {
 526         struct uart_port *port;
 527         unsigned long minor;
 528         int err;
 529 
 530         if (op->archdata.irqs[0] == 0xffffffff)
 531                 return -ENODEV;
 532 
 533         port = kzalloc(sizeof(struct uart_port), GFP_KERNEL);
 534         if (unlikely(!port))
 535                 return -ENOMEM;
 536 
 537         minor = 1;
 538         if (sun4v_hvapi_register(HV_GRP_CORE, 1, &minor) == 0 &&
 539             minor >= 1) {
 540                 err = -ENOMEM;
 541                 con_write_page = kzalloc(PAGE_SIZE, GFP_KERNEL);
 542                 if (!con_write_page)
 543                         goto out_free_port;
 544 
 545                 con_read_page = kzalloc(PAGE_SIZE, GFP_KERNEL);
 546                 if (!con_read_page)
 547                         goto out_free_con_write_page;
 548 
 549                 sunhv_console.write = sunhv_console_write_paged;
 550                 sunhv_ops = &bywrite_ops;
 551         }
 552 
 553         sunhv_port = port;
 554 
 555         port->line = 0;
 556         port->ops = &sunhv_pops;
 557         port->type = PORT_SUNHV;
 558         port->uartclk = ( 29491200 / 16 ); /* arbitrary */
 559 
 560         port->membase = (unsigned char __iomem *) __pa(port);
 561 
 562         port->irq = op->archdata.irqs[0];
 563 
 564         port->dev = &op->dev;
 565 
 566         err = sunserial_register_minors(&sunhv_reg, 1);
 567         if (err)
 568                 goto out_free_con_read_page;
 569 
 570         sunserial_console_match(&sunhv_console, op->dev.of_node,
 571                                 &sunhv_reg, port->line, false);
 572 
 573         err = uart_add_one_port(&sunhv_reg, port);
 574         if (err)
 575                 goto out_unregister_driver;
 576 
 577         err = request_irq(port->irq, sunhv_interrupt, 0, "hvcons", port);
 578         if (err)
 579                 goto out_remove_port;
 580 
 581         platform_set_drvdata(op, port);
 582 
 583         return 0;
 584 
 585 out_remove_port:
 586         uart_remove_one_port(&sunhv_reg, port);
 587 
 588 out_unregister_driver:
 589         sunserial_unregister_minors(&sunhv_reg, 1);
 590 
 591 out_free_con_read_page:
 592         kfree(con_read_page);
 593 
 594 out_free_con_write_page:
 595         kfree(con_write_page);
 596 
 597 out_free_port:
 598         kfree(port);
 599         sunhv_port = NULL;
 600         return err;
 601 }
 602 
 603 static int hv_remove(struct platform_device *dev)
 604 {
 605         struct uart_port *port = platform_get_drvdata(dev);
 606 
 607         free_irq(port->irq, port);
 608 
 609         uart_remove_one_port(&sunhv_reg, port);
 610 
 611         sunserial_unregister_minors(&sunhv_reg, 1);
 612         kfree(con_read_page);
 613         kfree(con_write_page);
 614         kfree(port);
 615         sunhv_port = NULL;
 616 
 617         return 0;
 618 }
 619 
 620 static const struct of_device_id hv_match[] = {
 621         {
 622                 .name = "console",
 623                 .compatible = "qcn",
 624         },
 625         {
 626                 .name = "console",
 627                 .compatible = "SUNW,sun4v-console",
 628         },
 629         {},
 630 };
 631 
 632 static struct platform_driver hv_driver = {
 633         .driver = {
 634                 .name = "hv",
 635                 .of_match_table = hv_match,
 636         },
 637         .probe          = hv_probe,
 638         .remove         = hv_remove,
 639 };
 640 
 641 static int __init sunhv_init(void)
 642 {
 643         if (tlb_type != hypervisor)
 644                 return -ENODEV;
 645 
 646         return platform_driver_register(&hv_driver);
 647 }
 648 device_initcall(sunhv_init);
 649 
 650 #if 0 /* ...def MODULE ; never supported as such */
 651 MODULE_AUTHOR("David S. Miller");
 652 MODULE_DESCRIPTION("SUN4V Hypervisor console driver");
 653 MODULE_VERSION("2.0");
 654 MODULE_LICENSE("GPL");
 655 #endif

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