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