Lines Matching +full:byte +full:- +full:len
1 // SPDX-License-Identifier: GPL-2.0
2 /* ePAPR hypervisor byte channel device driver
4 * Copyright 2009-2011 Freescale Semiconductor, Inc.
9 * ePAPR hypervisor byte channels.
11 * 1) An early-console (udbg) driver. This provides early console output
12 * through a byte channel. The byte channel handle must be specified in a
15 * 2) A normal console driver. Output is sent to the byte channel designated
19 * 3) A tty driver, which is used to handle user-space input and output. The
20 * byte channel used for the console is designated as the default tty.
43 /* Per-byte channel private data */
59 /* Array of byte channel objects */
62 /* Byte channel handle for stdout (and stdin), taken from device tree */
65 /* Virtual IRQ for the byte channel handle for stdin, taken from device tree */
73 * Unlike a serial device, byte channels have no mechanism for disabling their
81 * 1. The tty layer makes two back-to-back calls to ehv_bc_tty_write()
88 if (!bc->tx_irq_enabled) { in enable_tx_interrupt()
89 enable_irq(bc->tx_irq); in enable_tx_interrupt()
90 bc->tx_irq_enabled = 1; in enable_tx_interrupt()
96 if (bc->tx_irq_enabled) { in disable_tx_interrupt()
97 disable_irq_nosync(bc->tx_irq); in disable_tx_interrupt()
98 bc->tx_irq_enabled = 0; in disable_tx_interrupt()
103 * find the byte channel handle to use for the console
105 * The byte channel to be used for the console is specified via a "stdout"
114 * care if it's compatible with "epapr,hv-byte-channel", because that in find_console_handle()
115 * indicates that it's a byte channel node. in find_console_handle()
117 if (!np || !of_device_is_compatible(np, "epapr,hv-byte-channel")) in find_console_handle()
122 pr_err("ehv-bc: no 'interrupts' property in %pOF node\n", np); in find_console_handle()
127 * The 'hv-handle' property contains the handle for this byte channel. in find_console_handle()
129 iprop = of_get_property(np, "hv-handle", NULL); in find_console_handle()
131 pr_err("ehv-bc: no 'hv-handle' property in %pOFn node\n", in find_console_handle()
162 * send a byte to a byte channel, wait if necessary
164 * This function sends a byte to a byte channel, and it waits and
165 * retries if the byte channel is full. It returns if the character
198 * byte channel handle for stdout.
208 /* Verify the byte channel handle */ in udbg_init_ehv_bc()
217 udbg_printf("ehv-bc: early console using byte channel handle %u\n", in udbg_init_ehv_bc()
228 * Byte channel console sending worker function.
236 unsigned int len; in ehv_bc_console_byte_channel_send() local
240 len = min_t(unsigned int, count, EV_BYTE_CHANNEL_MAX_BYTES); in ehv_bc_console_byte_channel_send()
242 ret = local_ev_byte_channel_send(handle, &len, s); in ehv_bc_console_byte_channel_send()
244 count -= len; in ehv_bc_console_byte_channel_send()
245 s += len; in ehv_bc_console_byte_channel_send()
275 if (j >= (EV_BYTE_CHANNEL_MAX_BYTES - 1)) { in ehv_bc_console_write()
288 * for one with ->device and then calls that method. On success, it expects
289 * the passed-in int* to contain the minor number to use.
293 *index = co->index; in ehv_bc_console_device()
309 * available, so here is where we determine the byte channel handle and IRQ for
316 pr_debug("ehv-bc: stdout is not a byte channel\n"); in ehv_bc_console_init()
317 return -ENODEV; in ehv_bc_console_init()
321 /* Print a friendly warning if the user chose the wrong byte channel in ehv_bc_console_init()
325 pr_warn("ehv-bc: udbg handle %u is not the stdout handle\n", in ehv_bc_console_init()
331 byte channels here, either, since we only care about one. */ in ehv_bc_console_init()
336 pr_info("ehv-bc: registered console driver for byte channel %u\n", in ehv_bc_console_init()
346 * byte channel receive interrupt handler
348 * This ISR is called whenever data is available on a byte channel.
353 unsigned int rx_count, tx_count, len; in ehv_bc_tty_rx_isr() local
359 * if it can handle that much. We want to ensure that every byte we in ehv_bc_tty_rx_isr()
360 * read from the byte channel will be accepted by the TTY layer. in ehv_bc_tty_rx_isr()
362 ev_byte_channel_poll(bc->handle, &rx_count, &tx_count); in ehv_bc_tty_rx_isr()
363 count = tty_buffer_request_room(&bc->port, rx_count); in ehv_bc_tty_rx_isr()
372 len = min_t(unsigned int, count, sizeof(buffer)); in ehv_bc_tty_rx_isr()
374 /* Read some data from the byte channel. This function will in ehv_bc_tty_rx_isr()
377 ev_byte_channel_receive(bc->handle, &len, buffer); in ehv_bc_tty_rx_isr()
379 /* 'len' is now the amount of data that's been received. 'len' in ehv_bc_tty_rx_isr()
384 ret = tty_insert_flip_string(&bc->port, buffer, len); in ehv_bc_tty_rx_isr()
387 * If it's not equal to 'len', then it means the buffer is in ehv_bc_tty_rx_isr()
389 * exit gracefully, but we drop the last 'len - ret' characters in ehv_bc_tty_rx_isr()
390 * that we read from the byte channel. in ehv_bc_tty_rx_isr()
392 if (ret != len) in ehv_bc_tty_rx_isr()
395 count -= len; in ehv_bc_tty_rx_isr()
399 tty_flip_buffer_push(&bc->port); in ehv_bc_tty_rx_isr()
408 * data as possible from the transmit buffer to the byte channel.
413 unsigned int len, ret; in ehv_bc_tx_dequeue() local
417 spin_lock_irqsave(&bc->lock, flags); in ehv_bc_tx_dequeue()
418 len = min_t(unsigned int, in ehv_bc_tx_dequeue()
419 CIRC_CNT_TO_END(bc->head, bc->tail, BUF_SIZE), in ehv_bc_tx_dequeue()
422 ret = local_ev_byte_channel_send(bc->handle, &len, bc->buf + bc->tail); in ehv_bc_tx_dequeue()
424 /* 'len' is valid only if the return code is 0 or EV_EAGAIN */ in ehv_bc_tx_dequeue()
426 bc->tail = (bc->tail + len) & (BUF_SIZE - 1); in ehv_bc_tx_dequeue()
428 count = CIRC_CNT(bc->head, bc->tail, BUF_SIZE); in ehv_bc_tx_dequeue()
429 spin_unlock_irqrestore(&bc->lock, flags); in ehv_bc_tx_dequeue()
432 spin_lock_irqsave(&bc->lock, flags); in ehv_bc_tx_dequeue()
433 if (CIRC_CNT(bc->head, bc->tail, BUF_SIZE)) in ehv_bc_tx_dequeue()
442 spin_unlock_irqrestore(&bc->lock, flags); in ehv_bc_tx_dequeue()
446 * byte channel transmit interrupt handler
449 * characters on a byte channel.
456 tty_port_tty_wakeup(&bc->port); in ehv_bc_tty_tx_isr()
475 struct ehv_bc_data *bc = ttys->driver_data; in ehv_bc_tty_write()
477 size_t len, written = 0; in ehv_bc_tty_write() local
480 spin_lock_irqsave(&bc->lock, flags); in ehv_bc_tty_write()
481 len = CIRC_SPACE_TO_END(bc->head, bc->tail, BUF_SIZE); in ehv_bc_tty_write()
482 if (count < len) in ehv_bc_tty_write()
483 len = count; in ehv_bc_tty_write()
484 if (len) { in ehv_bc_tty_write()
485 memcpy(bc->buf + bc->head, s, len); in ehv_bc_tty_write()
486 bc->head = (bc->head + len) & (BUF_SIZE - 1); in ehv_bc_tty_write()
488 spin_unlock_irqrestore(&bc->lock, flags); in ehv_bc_tty_write()
489 if (!len) in ehv_bc_tty_write()
492 s += len; in ehv_bc_tty_write()
493 count -= len; in ehv_bc_tty_write()
494 written += len; in ehv_bc_tty_write()
504 * why we initialize bc->ttys in ehv_bc_tty_port_activate() instead.
513 struct ehv_bc_data *bc = &bcs[ttys->index]; in ehv_bc_tty_open()
515 if (!bc->dev) in ehv_bc_tty_open()
516 return -ENODEV; in ehv_bc_tty_open()
518 return tty_port_open(&bc->port, ttys, filp); in ehv_bc_tty_open()
528 struct ehv_bc_data *bc = &bcs[ttys->index]; in ehv_bc_tty_close()
530 if (bc->dev) in ehv_bc_tty_close()
531 tty_port_close(&bc->port, ttys, filp); in ehv_bc_tty_close()
543 struct ehv_bc_data *bc = ttys->driver_data; in ehv_bc_tty_write_room()
547 spin_lock_irqsave(&bc->lock, flags); in ehv_bc_tty_write_room()
548 count = CIRC_SPACE(bc->head, bc->tail, BUF_SIZE); in ehv_bc_tty_write_room()
549 spin_unlock_irqrestore(&bc->lock, flags); in ehv_bc_tty_write_room()
568 struct ehv_bc_data *bc = ttys->driver_data; in ehv_bc_tty_throttle()
570 disable_irq(bc->rx_irq); in ehv_bc_tty_throttle()
582 struct ehv_bc_data *bc = ttys->driver_data; in ehv_bc_tty_unthrottle()
587 enable_irq(bc->rx_irq); in ehv_bc_tty_unthrottle()
592 struct ehv_bc_data *bc = ttys->driver_data; in ehv_bc_tty_hangup()
595 tty_port_hangup(&bc->port); in ehv_bc_tty_hangup()
620 * why we initialize tty_struct-related variables here.
628 ttys->driver_data = bc; in ehv_bc_tty_port_activate()
630 ret = request_irq(bc->rx_irq, ehv_bc_tty_rx_isr, 0, "ehv-bc", bc); in ehv_bc_tty_port_activate()
632 dev_err(bc->dev, "could not request rx irq %u (ret=%i)\n", in ehv_bc_tty_port_activate()
633 bc->rx_irq, ret); in ehv_bc_tty_port_activate()
638 bc->tx_irq_enabled = 1; in ehv_bc_tty_port_activate()
640 ret = request_irq(bc->tx_irq, ehv_bc_tty_tx_isr, 0, "ehv-bc", bc); in ehv_bc_tty_port_activate()
642 dev_err(bc->dev, "could not request tx irq %u (ret=%i)\n", in ehv_bc_tty_port_activate()
643 bc->tx_irq, ret); in ehv_bc_tty_port_activate()
644 free_irq(bc->rx_irq, bc); in ehv_bc_tty_port_activate()
649 * byte channel at once, so by default it's disabled. in ehv_bc_tty_port_activate()
660 free_irq(bc->tx_irq, bc); in ehv_bc_tty_port_shutdown()
661 free_irq(bc->rx_irq, bc); in ehv_bc_tty_port_shutdown()
671 struct device_node *np = pdev->dev.of_node; in ehv_bc_tty_probe()
679 iprop = of_get_property(np, "hv-handle", NULL); in ehv_bc_tty_probe()
681 dev_err(&pdev->dev, "no 'hv-handle' property in %pOFn node\n", in ehv_bc_tty_probe()
683 return -ENODEV; in ehv_bc_tty_probe()
688 * we probe the console byte channel node. in ehv_bc_tty_probe()
694 bc->handle = handle; in ehv_bc_tty_probe()
695 bc->head = 0; in ehv_bc_tty_probe()
696 bc->tail = 0; in ehv_bc_tty_probe()
697 spin_lock_init(&bc->lock); in ehv_bc_tty_probe()
699 bc->rx_irq = irq_of_parse_and_map(np, 0); in ehv_bc_tty_probe()
700 bc->tx_irq = irq_of_parse_and_map(np, 1); in ehv_bc_tty_probe()
701 if (!bc->rx_irq || !bc->tx_irq) { in ehv_bc_tty_probe()
702 dev_err(&pdev->dev, "no 'interrupts' property in %pOFn node\n", in ehv_bc_tty_probe()
704 ret = -ENODEV; in ehv_bc_tty_probe()
708 tty_port_init(&bc->port); in ehv_bc_tty_probe()
709 bc->port.ops = &ehv_bc_tty_port_ops; in ehv_bc_tty_probe()
711 bc->dev = tty_port_register_device(&bc->port, ehv_bc_driver, i, in ehv_bc_tty_probe()
712 &pdev->dev); in ehv_bc_tty_probe()
713 if (IS_ERR(bc->dev)) { in ehv_bc_tty_probe()
714 ret = PTR_ERR(bc->dev); in ehv_bc_tty_probe()
715 dev_err(&pdev->dev, "could not register tty (ret=%i)\n", ret); in ehv_bc_tty_probe()
719 dev_set_drvdata(&pdev->dev, bc); in ehv_bc_tty_probe()
721 dev_info(&pdev->dev, "registered /dev/%s%u for byte channel %u\n", in ehv_bc_tty_probe()
722 ehv_bc_driver->name, i, bc->handle); in ehv_bc_tty_probe()
727 tty_port_destroy(&bc->port); in ehv_bc_tty_probe()
728 irq_dispose_mapping(bc->tx_irq); in ehv_bc_tty_probe()
729 irq_dispose_mapping(bc->rx_irq); in ehv_bc_tty_probe()
736 { .compatible = "epapr,hv-byte-channel" },
742 .name = "ehv-bc",
750 * ehv_bc_init - ePAPR hypervisor byte channel driver initialization
761 pr_info("ePAPR hypervisor byte channel driver\n"); in ehv_bc_init()
763 /* Count the number of byte channels */ in ehv_bc_init()
764 for_each_compatible_node(np, NULL, "epapr,hv-byte-channel") in ehv_bc_init()
768 return -ENODEV; in ehv_bc_init()
772 * array, then you can use pointer math (e.g. "bc - bcs") to get its in ehv_bc_init()
777 return -ENOMEM; in ehv_bc_init()
786 driver->driver_name = "ehv-bc"; in ehv_bc_init()
787 driver->name = ehv_bc_console.name; in ehv_bc_init()
788 driver->type = TTY_DRIVER_TYPE_CONSOLE; in ehv_bc_init()
789 driver->subtype = SYSTEM_TYPE_CONSOLE; in ehv_bc_init()
790 driver->init_termios = tty_std_termios; in ehv_bc_init()
795 pr_err("ehv-bc: could not register tty driver (ret=%i)\n", ret); in ehv_bc_init()
803 pr_err("ehv-bc: could not register platform driver (ret=%i)\n", in ehv_bc_init()