162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* ePAPR hypervisor byte channel device driver 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright 2009-2011 Freescale Semiconductor, Inc. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Author: Timur Tabi <timur@freescale.com> 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * This driver support three distinct interfaces, all of which are related to 962306a36Sopenharmony_ci * ePAPR hypervisor byte channels. 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * 1) An early-console (udbg) driver. This provides early console output 1262306a36Sopenharmony_ci * through a byte channel. The byte channel handle must be specified in a 1362306a36Sopenharmony_ci * Kconfig option. 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * 2) A normal console driver. Output is sent to the byte channel designated 1662306a36Sopenharmony_ci * for stdout in the device tree. The console driver is for handling kernel 1762306a36Sopenharmony_ci * printk calls. 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * 3) A tty driver, which is used to handle user-space input and output. The 2062306a36Sopenharmony_ci * byte channel used for the console is designated as the default tty. 2162306a36Sopenharmony_ci */ 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#include <linux/init.h> 2462306a36Sopenharmony_ci#include <linux/slab.h> 2562306a36Sopenharmony_ci#include <linux/err.h> 2662306a36Sopenharmony_ci#include <linux/interrupt.h> 2762306a36Sopenharmony_ci#include <linux/fs.h> 2862306a36Sopenharmony_ci#include <linux/poll.h> 2962306a36Sopenharmony_ci#include <asm/epapr_hcalls.h> 3062306a36Sopenharmony_ci#include <linux/of.h> 3162306a36Sopenharmony_ci#include <linux/of_irq.h> 3262306a36Sopenharmony_ci#include <linux/platform_device.h> 3362306a36Sopenharmony_ci#include <linux/cdev.h> 3462306a36Sopenharmony_ci#include <linux/console.h> 3562306a36Sopenharmony_ci#include <linux/tty.h> 3662306a36Sopenharmony_ci#include <linux/tty_flip.h> 3762306a36Sopenharmony_ci#include <linux/circ_buf.h> 3862306a36Sopenharmony_ci#include <asm/udbg.h> 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci/* The size of the transmit circular buffer. This must be a power of two. */ 4162306a36Sopenharmony_ci#define BUF_SIZE 2048 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci/* Per-byte channel private data */ 4462306a36Sopenharmony_cistruct ehv_bc_data { 4562306a36Sopenharmony_ci struct device *dev; 4662306a36Sopenharmony_ci struct tty_port port; 4762306a36Sopenharmony_ci uint32_t handle; 4862306a36Sopenharmony_ci unsigned int rx_irq; 4962306a36Sopenharmony_ci unsigned int tx_irq; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci spinlock_t lock; /* lock for transmit buffer */ 5262306a36Sopenharmony_ci unsigned char buf[BUF_SIZE]; /* transmit circular buffer */ 5362306a36Sopenharmony_ci unsigned int head; /* circular buffer head */ 5462306a36Sopenharmony_ci unsigned int tail; /* circular buffer tail */ 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci int tx_irq_enabled; /* true == TX interrupt is enabled */ 5762306a36Sopenharmony_ci}; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci/* Array of byte channel objects */ 6062306a36Sopenharmony_cistatic struct ehv_bc_data *bcs; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci/* Byte channel handle for stdout (and stdin), taken from device tree */ 6362306a36Sopenharmony_cistatic unsigned int stdout_bc; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci/* Virtual IRQ for the byte channel handle for stdin, taken from device tree */ 6662306a36Sopenharmony_cistatic unsigned int stdout_irq; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci/**************************** SUPPORT FUNCTIONS ****************************/ 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci/* 7162306a36Sopenharmony_ci * Enable the transmit interrupt 7262306a36Sopenharmony_ci * 7362306a36Sopenharmony_ci * Unlike a serial device, byte channels have no mechanism for disabling their 7462306a36Sopenharmony_ci * own receive or transmit interrupts. To emulate that feature, we toggle 7562306a36Sopenharmony_ci * the IRQ in the kernel. 7662306a36Sopenharmony_ci * 7762306a36Sopenharmony_ci * We cannot just blindly call enable_irq() or disable_irq(), because these 7862306a36Sopenharmony_ci * calls are reference counted. This means that we cannot call enable_irq() 7962306a36Sopenharmony_ci * if interrupts are already enabled. This can happen in two situations: 8062306a36Sopenharmony_ci * 8162306a36Sopenharmony_ci * 1. The tty layer makes two back-to-back calls to ehv_bc_tty_write() 8262306a36Sopenharmony_ci * 2. A transmit interrupt occurs while executing ehv_bc_tx_dequeue() 8362306a36Sopenharmony_ci * 8462306a36Sopenharmony_ci * To work around this, we keep a flag to tell us if the IRQ is enabled or not. 8562306a36Sopenharmony_ci */ 8662306a36Sopenharmony_cistatic void enable_tx_interrupt(struct ehv_bc_data *bc) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci if (!bc->tx_irq_enabled) { 8962306a36Sopenharmony_ci enable_irq(bc->tx_irq); 9062306a36Sopenharmony_ci bc->tx_irq_enabled = 1; 9162306a36Sopenharmony_ci } 9262306a36Sopenharmony_ci} 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_cistatic void disable_tx_interrupt(struct ehv_bc_data *bc) 9562306a36Sopenharmony_ci{ 9662306a36Sopenharmony_ci if (bc->tx_irq_enabled) { 9762306a36Sopenharmony_ci disable_irq_nosync(bc->tx_irq); 9862306a36Sopenharmony_ci bc->tx_irq_enabled = 0; 9962306a36Sopenharmony_ci } 10062306a36Sopenharmony_ci} 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci/* 10362306a36Sopenharmony_ci * find the byte channel handle to use for the console 10462306a36Sopenharmony_ci * 10562306a36Sopenharmony_ci * The byte channel to be used for the console is specified via a "stdout" 10662306a36Sopenharmony_ci * property in the /chosen node. 10762306a36Sopenharmony_ci */ 10862306a36Sopenharmony_cistatic int find_console_handle(void) 10962306a36Sopenharmony_ci{ 11062306a36Sopenharmony_ci struct device_node *np = of_stdout; 11162306a36Sopenharmony_ci const uint32_t *iprop; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci /* We don't care what the aliased node is actually called. We only 11462306a36Sopenharmony_ci * care if it's compatible with "epapr,hv-byte-channel", because that 11562306a36Sopenharmony_ci * indicates that it's a byte channel node. 11662306a36Sopenharmony_ci */ 11762306a36Sopenharmony_ci if (!np || !of_device_is_compatible(np, "epapr,hv-byte-channel")) 11862306a36Sopenharmony_ci return 0; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci stdout_irq = irq_of_parse_and_map(np, 0); 12162306a36Sopenharmony_ci if (!stdout_irq) { 12262306a36Sopenharmony_ci pr_err("ehv-bc: no 'interrupts' property in %pOF node\n", np); 12362306a36Sopenharmony_ci return 0; 12462306a36Sopenharmony_ci } 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci /* 12762306a36Sopenharmony_ci * The 'hv-handle' property contains the handle for this byte channel. 12862306a36Sopenharmony_ci */ 12962306a36Sopenharmony_ci iprop = of_get_property(np, "hv-handle", NULL); 13062306a36Sopenharmony_ci if (!iprop) { 13162306a36Sopenharmony_ci pr_err("ehv-bc: no 'hv-handle' property in %pOFn node\n", 13262306a36Sopenharmony_ci np); 13362306a36Sopenharmony_ci return 0; 13462306a36Sopenharmony_ci } 13562306a36Sopenharmony_ci stdout_bc = be32_to_cpu(*iprop); 13662306a36Sopenharmony_ci return 1; 13762306a36Sopenharmony_ci} 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_cistatic unsigned int local_ev_byte_channel_send(unsigned int handle, 14062306a36Sopenharmony_ci unsigned int *count, 14162306a36Sopenharmony_ci const char *p) 14262306a36Sopenharmony_ci{ 14362306a36Sopenharmony_ci char buffer[EV_BYTE_CHANNEL_MAX_BYTES]; 14462306a36Sopenharmony_ci unsigned int c = *count; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci if (c < sizeof(buffer)) { 14762306a36Sopenharmony_ci memcpy(buffer, p, c); 14862306a36Sopenharmony_ci memset(&buffer[c], 0, sizeof(buffer) - c); 14962306a36Sopenharmony_ci p = buffer; 15062306a36Sopenharmony_ci } 15162306a36Sopenharmony_ci return ev_byte_channel_send(handle, count, p); 15262306a36Sopenharmony_ci} 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci/*************************** EARLY CONSOLE DRIVER ***************************/ 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci#ifdef CONFIG_PPC_EARLY_DEBUG_EHV_BC 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci/* 15962306a36Sopenharmony_ci * send a byte to a byte channel, wait if necessary 16062306a36Sopenharmony_ci * 16162306a36Sopenharmony_ci * This function sends a byte to a byte channel, and it waits and 16262306a36Sopenharmony_ci * retries if the byte channel is full. It returns if the character 16362306a36Sopenharmony_ci * has been sent, or if some error has occurred. 16462306a36Sopenharmony_ci * 16562306a36Sopenharmony_ci */ 16662306a36Sopenharmony_cistatic void byte_channel_spin_send(const char data) 16762306a36Sopenharmony_ci{ 16862306a36Sopenharmony_ci int ret, count; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci do { 17162306a36Sopenharmony_ci count = 1; 17262306a36Sopenharmony_ci ret = local_ev_byte_channel_send(CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE, 17362306a36Sopenharmony_ci &count, &data); 17462306a36Sopenharmony_ci } while (ret == EV_EAGAIN); 17562306a36Sopenharmony_ci} 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci/* 17862306a36Sopenharmony_ci * The udbg subsystem calls this function to display a single character. 17962306a36Sopenharmony_ci * We convert CR to a CR/LF. 18062306a36Sopenharmony_ci */ 18162306a36Sopenharmony_cistatic void ehv_bc_udbg_putc(char c) 18262306a36Sopenharmony_ci{ 18362306a36Sopenharmony_ci if (c == '\n') 18462306a36Sopenharmony_ci byte_channel_spin_send('\r'); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci byte_channel_spin_send(c); 18762306a36Sopenharmony_ci} 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci/* 19062306a36Sopenharmony_ci * early console initialization 19162306a36Sopenharmony_ci * 19262306a36Sopenharmony_ci * PowerPC kernels support an early printk console, also known as udbg. 19362306a36Sopenharmony_ci * This function must be called via the ppc_md.init_early function pointer. 19462306a36Sopenharmony_ci * At this point, the device tree has been unflattened, so we can obtain the 19562306a36Sopenharmony_ci * byte channel handle for stdout. 19662306a36Sopenharmony_ci * 19762306a36Sopenharmony_ci * We only support displaying of characters (putc). We do not support 19862306a36Sopenharmony_ci * keyboard input. 19962306a36Sopenharmony_ci */ 20062306a36Sopenharmony_civoid __init udbg_init_ehv_bc(void) 20162306a36Sopenharmony_ci{ 20262306a36Sopenharmony_ci unsigned int rx_count, tx_count; 20362306a36Sopenharmony_ci unsigned int ret; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci /* Verify the byte channel handle */ 20662306a36Sopenharmony_ci ret = ev_byte_channel_poll(CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE, 20762306a36Sopenharmony_ci &rx_count, &tx_count); 20862306a36Sopenharmony_ci if (ret) 20962306a36Sopenharmony_ci return; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci udbg_putc = ehv_bc_udbg_putc; 21262306a36Sopenharmony_ci register_early_udbg_console(); 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci udbg_printf("ehv-bc: early console using byte channel handle %u\n", 21562306a36Sopenharmony_ci CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE); 21662306a36Sopenharmony_ci} 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci#endif 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci/****************************** CONSOLE DRIVER ******************************/ 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_cistatic struct tty_driver *ehv_bc_driver; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci/* 22562306a36Sopenharmony_ci * Byte channel console sending worker function. 22662306a36Sopenharmony_ci * 22762306a36Sopenharmony_ci * For consoles, if the output buffer is full, we should just spin until it 22862306a36Sopenharmony_ci * clears. 22962306a36Sopenharmony_ci */ 23062306a36Sopenharmony_cistatic int ehv_bc_console_byte_channel_send(unsigned int handle, const char *s, 23162306a36Sopenharmony_ci unsigned int count) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci unsigned int len; 23462306a36Sopenharmony_ci int ret = 0; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci while (count) { 23762306a36Sopenharmony_ci len = min_t(unsigned int, count, EV_BYTE_CHANNEL_MAX_BYTES); 23862306a36Sopenharmony_ci do { 23962306a36Sopenharmony_ci ret = local_ev_byte_channel_send(handle, &len, s); 24062306a36Sopenharmony_ci } while (ret == EV_EAGAIN); 24162306a36Sopenharmony_ci count -= len; 24262306a36Sopenharmony_ci s += len; 24362306a36Sopenharmony_ci } 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci return ret; 24662306a36Sopenharmony_ci} 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci/* 24962306a36Sopenharmony_ci * write a string to the console 25062306a36Sopenharmony_ci * 25162306a36Sopenharmony_ci * This function gets called to write a string from the kernel, typically from 25262306a36Sopenharmony_ci * a printk(). This function spins until all data is written. 25362306a36Sopenharmony_ci * 25462306a36Sopenharmony_ci * We copy the data to a temporary buffer because we need to insert a \r in 25562306a36Sopenharmony_ci * front of every \n. It's more efficient to copy the data to the buffer than 25662306a36Sopenharmony_ci * it is to make multiple hcalls for each character or each newline. 25762306a36Sopenharmony_ci */ 25862306a36Sopenharmony_cistatic void ehv_bc_console_write(struct console *co, const char *s, 25962306a36Sopenharmony_ci unsigned int count) 26062306a36Sopenharmony_ci{ 26162306a36Sopenharmony_ci char s2[EV_BYTE_CHANNEL_MAX_BYTES]; 26262306a36Sopenharmony_ci unsigned int i, j = 0; 26362306a36Sopenharmony_ci char c; 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci for (i = 0; i < count; i++) { 26662306a36Sopenharmony_ci c = *s++; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci if (c == '\n') 26962306a36Sopenharmony_ci s2[j++] = '\r'; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci s2[j++] = c; 27262306a36Sopenharmony_ci if (j >= (EV_BYTE_CHANNEL_MAX_BYTES - 1)) { 27362306a36Sopenharmony_ci if (ehv_bc_console_byte_channel_send(stdout_bc, s2, j)) 27462306a36Sopenharmony_ci return; 27562306a36Sopenharmony_ci j = 0; 27662306a36Sopenharmony_ci } 27762306a36Sopenharmony_ci } 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci if (j) 28062306a36Sopenharmony_ci ehv_bc_console_byte_channel_send(stdout_bc, s2, j); 28162306a36Sopenharmony_ci} 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci/* 28462306a36Sopenharmony_ci * When /dev/console is opened, the kernel iterates the console list looking 28562306a36Sopenharmony_ci * for one with ->device and then calls that method. On success, it expects 28662306a36Sopenharmony_ci * the passed-in int* to contain the minor number to use. 28762306a36Sopenharmony_ci */ 28862306a36Sopenharmony_cistatic struct tty_driver *ehv_bc_console_device(struct console *co, int *index) 28962306a36Sopenharmony_ci{ 29062306a36Sopenharmony_ci *index = co->index; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci return ehv_bc_driver; 29362306a36Sopenharmony_ci} 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_cistatic struct console ehv_bc_console = { 29662306a36Sopenharmony_ci .name = "ttyEHV", 29762306a36Sopenharmony_ci .write = ehv_bc_console_write, 29862306a36Sopenharmony_ci .device = ehv_bc_console_device, 29962306a36Sopenharmony_ci .flags = CON_PRINTBUFFER | CON_ENABLED, 30062306a36Sopenharmony_ci}; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci/* 30362306a36Sopenharmony_ci * Console initialization 30462306a36Sopenharmony_ci * 30562306a36Sopenharmony_ci * This is the first function that is called after the device tree is 30662306a36Sopenharmony_ci * available, so here is where we determine the byte channel handle and IRQ for 30762306a36Sopenharmony_ci * stdout/stdin, even though that information is used by the tty and character 30862306a36Sopenharmony_ci * drivers. 30962306a36Sopenharmony_ci */ 31062306a36Sopenharmony_cistatic int __init ehv_bc_console_init(void) 31162306a36Sopenharmony_ci{ 31262306a36Sopenharmony_ci if (!find_console_handle()) { 31362306a36Sopenharmony_ci pr_debug("ehv-bc: stdout is not a byte channel\n"); 31462306a36Sopenharmony_ci return -ENODEV; 31562306a36Sopenharmony_ci } 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci#ifdef CONFIG_PPC_EARLY_DEBUG_EHV_BC 31862306a36Sopenharmony_ci /* Print a friendly warning if the user chose the wrong byte channel 31962306a36Sopenharmony_ci * handle for udbg. 32062306a36Sopenharmony_ci */ 32162306a36Sopenharmony_ci if (stdout_bc != CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE) 32262306a36Sopenharmony_ci pr_warn("ehv-bc: udbg handle %u is not the stdout handle\n", 32362306a36Sopenharmony_ci CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE); 32462306a36Sopenharmony_ci#endif 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci /* add_preferred_console() must be called before register_console(), 32762306a36Sopenharmony_ci otherwise it won't work. However, we don't want to enumerate all the 32862306a36Sopenharmony_ci byte channels here, either, since we only care about one. */ 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci add_preferred_console(ehv_bc_console.name, ehv_bc_console.index, NULL); 33162306a36Sopenharmony_ci register_console(&ehv_bc_console); 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci pr_info("ehv-bc: registered console driver for byte channel %u\n", 33462306a36Sopenharmony_ci stdout_bc); 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci return 0; 33762306a36Sopenharmony_ci} 33862306a36Sopenharmony_ciconsole_initcall(ehv_bc_console_init); 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci/******************************** TTY DRIVER ********************************/ 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci/* 34362306a36Sopenharmony_ci * byte channel receive interrupt handler 34462306a36Sopenharmony_ci * 34562306a36Sopenharmony_ci * This ISR is called whenever data is available on a byte channel. 34662306a36Sopenharmony_ci */ 34762306a36Sopenharmony_cistatic irqreturn_t ehv_bc_tty_rx_isr(int irq, void *data) 34862306a36Sopenharmony_ci{ 34962306a36Sopenharmony_ci struct ehv_bc_data *bc = data; 35062306a36Sopenharmony_ci unsigned int rx_count, tx_count, len; 35162306a36Sopenharmony_ci int count; 35262306a36Sopenharmony_ci char buffer[EV_BYTE_CHANNEL_MAX_BYTES]; 35362306a36Sopenharmony_ci int ret; 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci /* Find out how much data needs to be read, and then ask the TTY layer 35662306a36Sopenharmony_ci * if it can handle that much. We want to ensure that every byte we 35762306a36Sopenharmony_ci * read from the byte channel will be accepted by the TTY layer. 35862306a36Sopenharmony_ci */ 35962306a36Sopenharmony_ci ev_byte_channel_poll(bc->handle, &rx_count, &tx_count); 36062306a36Sopenharmony_ci count = tty_buffer_request_room(&bc->port, rx_count); 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci /* 'count' is the maximum amount of data the TTY layer can accept at 36362306a36Sopenharmony_ci * this time. However, during testing, I was never able to get 'count' 36462306a36Sopenharmony_ci * to be less than 'rx_count'. I'm not sure whether I'm calling it 36562306a36Sopenharmony_ci * correctly. 36662306a36Sopenharmony_ci */ 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci while (count > 0) { 36962306a36Sopenharmony_ci len = min_t(unsigned int, count, sizeof(buffer)); 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci /* Read some data from the byte channel. This function will 37262306a36Sopenharmony_ci * never return more than EV_BYTE_CHANNEL_MAX_BYTES bytes. 37362306a36Sopenharmony_ci */ 37462306a36Sopenharmony_ci ev_byte_channel_receive(bc->handle, &len, buffer); 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci /* 'len' is now the amount of data that's been received. 'len' 37762306a36Sopenharmony_ci * can't be zero, and most likely it's equal to one. 37862306a36Sopenharmony_ci */ 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci /* Pass the received data to the tty layer. */ 38162306a36Sopenharmony_ci ret = tty_insert_flip_string(&bc->port, buffer, len); 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci /* 'ret' is the number of bytes that the TTY layer accepted. 38462306a36Sopenharmony_ci * If it's not equal to 'len', then it means the buffer is 38562306a36Sopenharmony_ci * full, which should never happen. If it does happen, we can 38662306a36Sopenharmony_ci * exit gracefully, but we drop the last 'len - ret' characters 38762306a36Sopenharmony_ci * that we read from the byte channel. 38862306a36Sopenharmony_ci */ 38962306a36Sopenharmony_ci if (ret != len) 39062306a36Sopenharmony_ci break; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci count -= len; 39362306a36Sopenharmony_ci } 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci /* Tell the tty layer that we're done. */ 39662306a36Sopenharmony_ci tty_flip_buffer_push(&bc->port); 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci return IRQ_HANDLED; 39962306a36Sopenharmony_ci} 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci/* 40262306a36Sopenharmony_ci * dequeue the transmit buffer to the hypervisor 40362306a36Sopenharmony_ci * 40462306a36Sopenharmony_ci * This function, which can be called in interrupt context, dequeues as much 40562306a36Sopenharmony_ci * data as possible from the transmit buffer to the byte channel. 40662306a36Sopenharmony_ci */ 40762306a36Sopenharmony_cistatic void ehv_bc_tx_dequeue(struct ehv_bc_data *bc) 40862306a36Sopenharmony_ci{ 40962306a36Sopenharmony_ci unsigned int count; 41062306a36Sopenharmony_ci unsigned int len, ret; 41162306a36Sopenharmony_ci unsigned long flags; 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci do { 41462306a36Sopenharmony_ci spin_lock_irqsave(&bc->lock, flags); 41562306a36Sopenharmony_ci len = min_t(unsigned int, 41662306a36Sopenharmony_ci CIRC_CNT_TO_END(bc->head, bc->tail, BUF_SIZE), 41762306a36Sopenharmony_ci EV_BYTE_CHANNEL_MAX_BYTES); 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci ret = local_ev_byte_channel_send(bc->handle, &len, bc->buf + bc->tail); 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci /* 'len' is valid only if the return code is 0 or EV_EAGAIN */ 42262306a36Sopenharmony_ci if (!ret || (ret == EV_EAGAIN)) 42362306a36Sopenharmony_ci bc->tail = (bc->tail + len) & (BUF_SIZE - 1); 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci count = CIRC_CNT(bc->head, bc->tail, BUF_SIZE); 42662306a36Sopenharmony_ci spin_unlock_irqrestore(&bc->lock, flags); 42762306a36Sopenharmony_ci } while (count && !ret); 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci spin_lock_irqsave(&bc->lock, flags); 43062306a36Sopenharmony_ci if (CIRC_CNT(bc->head, bc->tail, BUF_SIZE)) 43162306a36Sopenharmony_ci /* 43262306a36Sopenharmony_ci * If we haven't emptied the buffer, then enable the TX IRQ. 43362306a36Sopenharmony_ci * We'll get an interrupt when there's more room in the 43462306a36Sopenharmony_ci * hypervisor's output buffer. 43562306a36Sopenharmony_ci */ 43662306a36Sopenharmony_ci enable_tx_interrupt(bc); 43762306a36Sopenharmony_ci else 43862306a36Sopenharmony_ci disable_tx_interrupt(bc); 43962306a36Sopenharmony_ci spin_unlock_irqrestore(&bc->lock, flags); 44062306a36Sopenharmony_ci} 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci/* 44362306a36Sopenharmony_ci * byte channel transmit interrupt handler 44462306a36Sopenharmony_ci * 44562306a36Sopenharmony_ci * This ISR is called whenever space becomes available for transmitting 44662306a36Sopenharmony_ci * characters on a byte channel. 44762306a36Sopenharmony_ci */ 44862306a36Sopenharmony_cistatic irqreturn_t ehv_bc_tty_tx_isr(int irq, void *data) 44962306a36Sopenharmony_ci{ 45062306a36Sopenharmony_ci struct ehv_bc_data *bc = data; 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci ehv_bc_tx_dequeue(bc); 45362306a36Sopenharmony_ci tty_port_tty_wakeup(&bc->port); 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci return IRQ_HANDLED; 45662306a36Sopenharmony_ci} 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci/* 45962306a36Sopenharmony_ci * This function is called when the tty layer has data for us send. We store 46062306a36Sopenharmony_ci * the data first in a circular buffer, and then dequeue as much of that data 46162306a36Sopenharmony_ci * as possible. 46262306a36Sopenharmony_ci * 46362306a36Sopenharmony_ci * We don't need to worry about whether there is enough room in the buffer for 46462306a36Sopenharmony_ci * all the data. The purpose of ehv_bc_tty_write_room() is to tell the tty 46562306a36Sopenharmony_ci * layer how much data it can safely send to us. We guarantee that 46662306a36Sopenharmony_ci * ehv_bc_tty_write_room() will never lie, so the tty layer will never send us 46762306a36Sopenharmony_ci * too much data. 46862306a36Sopenharmony_ci */ 46962306a36Sopenharmony_cistatic ssize_t ehv_bc_tty_write(struct tty_struct *ttys, const u8 *s, 47062306a36Sopenharmony_ci size_t count) 47162306a36Sopenharmony_ci{ 47262306a36Sopenharmony_ci struct ehv_bc_data *bc = ttys->driver_data; 47362306a36Sopenharmony_ci unsigned long flags; 47462306a36Sopenharmony_ci unsigned int len; 47562306a36Sopenharmony_ci unsigned int written = 0; 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci while (1) { 47862306a36Sopenharmony_ci spin_lock_irqsave(&bc->lock, flags); 47962306a36Sopenharmony_ci len = CIRC_SPACE_TO_END(bc->head, bc->tail, BUF_SIZE); 48062306a36Sopenharmony_ci if (count < len) 48162306a36Sopenharmony_ci len = count; 48262306a36Sopenharmony_ci if (len) { 48362306a36Sopenharmony_ci memcpy(bc->buf + bc->head, s, len); 48462306a36Sopenharmony_ci bc->head = (bc->head + len) & (BUF_SIZE - 1); 48562306a36Sopenharmony_ci } 48662306a36Sopenharmony_ci spin_unlock_irqrestore(&bc->lock, flags); 48762306a36Sopenharmony_ci if (!len) 48862306a36Sopenharmony_ci break; 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci s += len; 49162306a36Sopenharmony_ci count -= len; 49262306a36Sopenharmony_ci written += len; 49362306a36Sopenharmony_ci } 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci ehv_bc_tx_dequeue(bc); 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci return written; 49862306a36Sopenharmony_ci} 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci/* 50162306a36Sopenharmony_ci * This function can be called multiple times for a given tty_struct, which is 50262306a36Sopenharmony_ci * why we initialize bc->ttys in ehv_bc_tty_port_activate() instead. 50362306a36Sopenharmony_ci * 50462306a36Sopenharmony_ci * The tty layer will still call this function even if the device was not 50562306a36Sopenharmony_ci * registered (i.e. tty_register_device() was not called). This happens 50662306a36Sopenharmony_ci * because tty_register_device() is optional and some legacy drivers don't 50762306a36Sopenharmony_ci * use it. So we need to check for that. 50862306a36Sopenharmony_ci */ 50962306a36Sopenharmony_cistatic int ehv_bc_tty_open(struct tty_struct *ttys, struct file *filp) 51062306a36Sopenharmony_ci{ 51162306a36Sopenharmony_ci struct ehv_bc_data *bc = &bcs[ttys->index]; 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci if (!bc->dev) 51462306a36Sopenharmony_ci return -ENODEV; 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci return tty_port_open(&bc->port, ttys, filp); 51762306a36Sopenharmony_ci} 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci/* 52062306a36Sopenharmony_ci * Amazingly, if ehv_bc_tty_open() returns an error code, the tty layer will 52162306a36Sopenharmony_ci * still call this function to close the tty device. So we can't assume that 52262306a36Sopenharmony_ci * the tty port has been initialized. 52362306a36Sopenharmony_ci */ 52462306a36Sopenharmony_cistatic void ehv_bc_tty_close(struct tty_struct *ttys, struct file *filp) 52562306a36Sopenharmony_ci{ 52662306a36Sopenharmony_ci struct ehv_bc_data *bc = &bcs[ttys->index]; 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci if (bc->dev) 52962306a36Sopenharmony_ci tty_port_close(&bc->port, ttys, filp); 53062306a36Sopenharmony_ci} 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci/* 53362306a36Sopenharmony_ci * Return the amount of space in the output buffer 53462306a36Sopenharmony_ci * 53562306a36Sopenharmony_ci * This is actually a contract between the driver and the tty layer outlining 53662306a36Sopenharmony_ci * how much write room the driver can guarantee will be sent OR BUFFERED. This 53762306a36Sopenharmony_ci * driver MUST honor the return value. 53862306a36Sopenharmony_ci */ 53962306a36Sopenharmony_cistatic unsigned int ehv_bc_tty_write_room(struct tty_struct *ttys) 54062306a36Sopenharmony_ci{ 54162306a36Sopenharmony_ci struct ehv_bc_data *bc = ttys->driver_data; 54262306a36Sopenharmony_ci unsigned long flags; 54362306a36Sopenharmony_ci unsigned int count; 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci spin_lock_irqsave(&bc->lock, flags); 54662306a36Sopenharmony_ci count = CIRC_SPACE(bc->head, bc->tail, BUF_SIZE); 54762306a36Sopenharmony_ci spin_unlock_irqrestore(&bc->lock, flags); 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci return count; 55062306a36Sopenharmony_ci} 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci/* 55362306a36Sopenharmony_ci * Stop sending data to the tty layer 55462306a36Sopenharmony_ci * 55562306a36Sopenharmony_ci * This function is called when the tty layer's input buffers are getting full, 55662306a36Sopenharmony_ci * so the driver should stop sending it data. The easiest way to do this is to 55762306a36Sopenharmony_ci * disable the RX IRQ, which will prevent ehv_bc_tty_rx_isr() from being 55862306a36Sopenharmony_ci * called. 55962306a36Sopenharmony_ci * 56062306a36Sopenharmony_ci * The hypervisor will continue to queue up any incoming data. If there is any 56162306a36Sopenharmony_ci * data in the queue when the RX interrupt is enabled, we'll immediately get an 56262306a36Sopenharmony_ci * RX interrupt. 56362306a36Sopenharmony_ci */ 56462306a36Sopenharmony_cistatic void ehv_bc_tty_throttle(struct tty_struct *ttys) 56562306a36Sopenharmony_ci{ 56662306a36Sopenharmony_ci struct ehv_bc_data *bc = ttys->driver_data; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci disable_irq(bc->rx_irq); 56962306a36Sopenharmony_ci} 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci/* 57262306a36Sopenharmony_ci * Resume sending data to the tty layer 57362306a36Sopenharmony_ci * 57462306a36Sopenharmony_ci * This function is called after previously calling ehv_bc_tty_throttle(). The 57562306a36Sopenharmony_ci * tty layer's input buffers now have more room, so the driver can resume 57662306a36Sopenharmony_ci * sending it data. 57762306a36Sopenharmony_ci */ 57862306a36Sopenharmony_cistatic void ehv_bc_tty_unthrottle(struct tty_struct *ttys) 57962306a36Sopenharmony_ci{ 58062306a36Sopenharmony_ci struct ehv_bc_data *bc = ttys->driver_data; 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci /* If there is any data in the queue when the RX interrupt is enabled, 58362306a36Sopenharmony_ci * we'll immediately get an RX interrupt. 58462306a36Sopenharmony_ci */ 58562306a36Sopenharmony_ci enable_irq(bc->rx_irq); 58662306a36Sopenharmony_ci} 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_cistatic void ehv_bc_tty_hangup(struct tty_struct *ttys) 58962306a36Sopenharmony_ci{ 59062306a36Sopenharmony_ci struct ehv_bc_data *bc = ttys->driver_data; 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci ehv_bc_tx_dequeue(bc); 59362306a36Sopenharmony_ci tty_port_hangup(&bc->port); 59462306a36Sopenharmony_ci} 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci/* 59762306a36Sopenharmony_ci * TTY driver operations 59862306a36Sopenharmony_ci * 59962306a36Sopenharmony_ci * If we could ask the hypervisor how much data is still in the TX buffer, or 60062306a36Sopenharmony_ci * at least how big the TX buffers are, then we could implement the 60162306a36Sopenharmony_ci * .wait_until_sent and .chars_in_buffer functions. 60262306a36Sopenharmony_ci */ 60362306a36Sopenharmony_cistatic const struct tty_operations ehv_bc_ops = { 60462306a36Sopenharmony_ci .open = ehv_bc_tty_open, 60562306a36Sopenharmony_ci .close = ehv_bc_tty_close, 60662306a36Sopenharmony_ci .write = ehv_bc_tty_write, 60762306a36Sopenharmony_ci .write_room = ehv_bc_tty_write_room, 60862306a36Sopenharmony_ci .throttle = ehv_bc_tty_throttle, 60962306a36Sopenharmony_ci .unthrottle = ehv_bc_tty_unthrottle, 61062306a36Sopenharmony_ci .hangup = ehv_bc_tty_hangup, 61162306a36Sopenharmony_ci}; 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci/* 61462306a36Sopenharmony_ci * initialize the TTY port 61562306a36Sopenharmony_ci * 61662306a36Sopenharmony_ci * This function will only be called once, no matter how many times 61762306a36Sopenharmony_ci * ehv_bc_tty_open() is called. That's why we register the ISR here, and also 61862306a36Sopenharmony_ci * why we initialize tty_struct-related variables here. 61962306a36Sopenharmony_ci */ 62062306a36Sopenharmony_cistatic int ehv_bc_tty_port_activate(struct tty_port *port, 62162306a36Sopenharmony_ci struct tty_struct *ttys) 62262306a36Sopenharmony_ci{ 62362306a36Sopenharmony_ci struct ehv_bc_data *bc = container_of(port, struct ehv_bc_data, port); 62462306a36Sopenharmony_ci int ret; 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci ttys->driver_data = bc; 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci ret = request_irq(bc->rx_irq, ehv_bc_tty_rx_isr, 0, "ehv-bc", bc); 62962306a36Sopenharmony_ci if (ret < 0) { 63062306a36Sopenharmony_ci dev_err(bc->dev, "could not request rx irq %u (ret=%i)\n", 63162306a36Sopenharmony_ci bc->rx_irq, ret); 63262306a36Sopenharmony_ci return ret; 63362306a36Sopenharmony_ci } 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci /* request_irq also enables the IRQ */ 63662306a36Sopenharmony_ci bc->tx_irq_enabled = 1; 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci ret = request_irq(bc->tx_irq, ehv_bc_tty_tx_isr, 0, "ehv-bc", bc); 63962306a36Sopenharmony_ci if (ret < 0) { 64062306a36Sopenharmony_ci dev_err(bc->dev, "could not request tx irq %u (ret=%i)\n", 64162306a36Sopenharmony_ci bc->tx_irq, ret); 64262306a36Sopenharmony_ci free_irq(bc->rx_irq, bc); 64362306a36Sopenharmony_ci return ret; 64462306a36Sopenharmony_ci } 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci /* The TX IRQ is enabled only when we can't write all the data to the 64762306a36Sopenharmony_ci * byte channel at once, so by default it's disabled. 64862306a36Sopenharmony_ci */ 64962306a36Sopenharmony_ci disable_tx_interrupt(bc); 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci return 0; 65262306a36Sopenharmony_ci} 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_cistatic void ehv_bc_tty_port_shutdown(struct tty_port *port) 65562306a36Sopenharmony_ci{ 65662306a36Sopenharmony_ci struct ehv_bc_data *bc = container_of(port, struct ehv_bc_data, port); 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci free_irq(bc->tx_irq, bc); 65962306a36Sopenharmony_ci free_irq(bc->rx_irq, bc); 66062306a36Sopenharmony_ci} 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_cistatic const struct tty_port_operations ehv_bc_tty_port_ops = { 66362306a36Sopenharmony_ci .activate = ehv_bc_tty_port_activate, 66462306a36Sopenharmony_ci .shutdown = ehv_bc_tty_port_shutdown, 66562306a36Sopenharmony_ci}; 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_cistatic int ehv_bc_tty_probe(struct platform_device *pdev) 66862306a36Sopenharmony_ci{ 66962306a36Sopenharmony_ci struct device_node *np = pdev->dev.of_node; 67062306a36Sopenharmony_ci struct ehv_bc_data *bc; 67162306a36Sopenharmony_ci const uint32_t *iprop; 67262306a36Sopenharmony_ci unsigned int handle; 67362306a36Sopenharmony_ci int ret; 67462306a36Sopenharmony_ci static unsigned int index = 1; 67562306a36Sopenharmony_ci unsigned int i; 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci iprop = of_get_property(np, "hv-handle", NULL); 67862306a36Sopenharmony_ci if (!iprop) { 67962306a36Sopenharmony_ci dev_err(&pdev->dev, "no 'hv-handle' property in %pOFn node\n", 68062306a36Sopenharmony_ci np); 68162306a36Sopenharmony_ci return -ENODEV; 68262306a36Sopenharmony_ci } 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci /* We already told the console layer that the index for the console 68562306a36Sopenharmony_ci * device is zero, so we need to make sure that we use that index when 68662306a36Sopenharmony_ci * we probe the console byte channel node. 68762306a36Sopenharmony_ci */ 68862306a36Sopenharmony_ci handle = be32_to_cpu(*iprop); 68962306a36Sopenharmony_ci i = (handle == stdout_bc) ? 0 : index++; 69062306a36Sopenharmony_ci bc = &bcs[i]; 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci bc->handle = handle; 69362306a36Sopenharmony_ci bc->head = 0; 69462306a36Sopenharmony_ci bc->tail = 0; 69562306a36Sopenharmony_ci spin_lock_init(&bc->lock); 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci bc->rx_irq = irq_of_parse_and_map(np, 0); 69862306a36Sopenharmony_ci bc->tx_irq = irq_of_parse_and_map(np, 1); 69962306a36Sopenharmony_ci if (!bc->rx_irq || !bc->tx_irq) { 70062306a36Sopenharmony_ci dev_err(&pdev->dev, "no 'interrupts' property in %pOFn node\n", 70162306a36Sopenharmony_ci np); 70262306a36Sopenharmony_ci ret = -ENODEV; 70362306a36Sopenharmony_ci goto error; 70462306a36Sopenharmony_ci } 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci tty_port_init(&bc->port); 70762306a36Sopenharmony_ci bc->port.ops = &ehv_bc_tty_port_ops; 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci bc->dev = tty_port_register_device(&bc->port, ehv_bc_driver, i, 71062306a36Sopenharmony_ci &pdev->dev); 71162306a36Sopenharmony_ci if (IS_ERR(bc->dev)) { 71262306a36Sopenharmony_ci ret = PTR_ERR(bc->dev); 71362306a36Sopenharmony_ci dev_err(&pdev->dev, "could not register tty (ret=%i)\n", ret); 71462306a36Sopenharmony_ci goto error; 71562306a36Sopenharmony_ci } 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci dev_set_drvdata(&pdev->dev, bc); 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci dev_info(&pdev->dev, "registered /dev/%s%u for byte channel %u\n", 72062306a36Sopenharmony_ci ehv_bc_driver->name, i, bc->handle); 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci return 0; 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_cierror: 72562306a36Sopenharmony_ci tty_port_destroy(&bc->port); 72662306a36Sopenharmony_ci irq_dispose_mapping(bc->tx_irq); 72762306a36Sopenharmony_ci irq_dispose_mapping(bc->rx_irq); 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci memset(bc, 0, sizeof(struct ehv_bc_data)); 73062306a36Sopenharmony_ci return ret; 73162306a36Sopenharmony_ci} 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_cistatic const struct of_device_id ehv_bc_tty_of_ids[] = { 73462306a36Sopenharmony_ci { .compatible = "epapr,hv-byte-channel" }, 73562306a36Sopenharmony_ci {} 73662306a36Sopenharmony_ci}; 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_cistatic struct platform_driver ehv_bc_tty_driver = { 73962306a36Sopenharmony_ci .driver = { 74062306a36Sopenharmony_ci .name = "ehv-bc", 74162306a36Sopenharmony_ci .of_match_table = ehv_bc_tty_of_ids, 74262306a36Sopenharmony_ci .suppress_bind_attrs = true, 74362306a36Sopenharmony_ci }, 74462306a36Sopenharmony_ci .probe = ehv_bc_tty_probe, 74562306a36Sopenharmony_ci}; 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci/** 74862306a36Sopenharmony_ci * ehv_bc_init - ePAPR hypervisor byte channel driver initialization 74962306a36Sopenharmony_ci * 75062306a36Sopenharmony_ci * This function is called when this driver is loaded. 75162306a36Sopenharmony_ci */ 75262306a36Sopenharmony_cistatic int __init ehv_bc_init(void) 75362306a36Sopenharmony_ci{ 75462306a36Sopenharmony_ci struct tty_driver *driver; 75562306a36Sopenharmony_ci struct device_node *np; 75662306a36Sopenharmony_ci unsigned int count = 0; /* Number of elements in bcs[] */ 75762306a36Sopenharmony_ci int ret; 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci pr_info("ePAPR hypervisor byte channel driver\n"); 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci /* Count the number of byte channels */ 76262306a36Sopenharmony_ci for_each_compatible_node(np, NULL, "epapr,hv-byte-channel") 76362306a36Sopenharmony_ci count++; 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci if (!count) 76662306a36Sopenharmony_ci return -ENODEV; 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci /* The array index of an element in bcs[] is the same as the tty index 76962306a36Sopenharmony_ci * for that element. If you know the address of an element in the 77062306a36Sopenharmony_ci * array, then you can use pointer math (e.g. "bc - bcs") to get its 77162306a36Sopenharmony_ci * tty index. 77262306a36Sopenharmony_ci */ 77362306a36Sopenharmony_ci bcs = kcalloc(count, sizeof(struct ehv_bc_data), GFP_KERNEL); 77462306a36Sopenharmony_ci if (!bcs) 77562306a36Sopenharmony_ci return -ENOMEM; 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci driver = tty_alloc_driver(count, TTY_DRIVER_REAL_RAW | 77862306a36Sopenharmony_ci TTY_DRIVER_DYNAMIC_DEV); 77962306a36Sopenharmony_ci if (IS_ERR(driver)) { 78062306a36Sopenharmony_ci ret = PTR_ERR(driver); 78162306a36Sopenharmony_ci goto err_free_bcs; 78262306a36Sopenharmony_ci } 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_ci driver->driver_name = "ehv-bc"; 78562306a36Sopenharmony_ci driver->name = ehv_bc_console.name; 78662306a36Sopenharmony_ci driver->type = TTY_DRIVER_TYPE_CONSOLE; 78762306a36Sopenharmony_ci driver->subtype = SYSTEM_TYPE_CONSOLE; 78862306a36Sopenharmony_ci driver->init_termios = tty_std_termios; 78962306a36Sopenharmony_ci tty_set_operations(driver, &ehv_bc_ops); 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci ret = tty_register_driver(driver); 79262306a36Sopenharmony_ci if (ret) { 79362306a36Sopenharmony_ci pr_err("ehv-bc: could not register tty driver (ret=%i)\n", ret); 79462306a36Sopenharmony_ci goto err_tty_driver_kref_put; 79562306a36Sopenharmony_ci } 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci ehv_bc_driver = driver; 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci ret = platform_driver_register(&ehv_bc_tty_driver); 80062306a36Sopenharmony_ci if (ret) { 80162306a36Sopenharmony_ci pr_err("ehv-bc: could not register platform driver (ret=%i)\n", 80262306a36Sopenharmony_ci ret); 80362306a36Sopenharmony_ci goto err_deregister_tty_driver; 80462306a36Sopenharmony_ci } 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci return 0; 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_cierr_deregister_tty_driver: 80962306a36Sopenharmony_ci ehv_bc_driver = NULL; 81062306a36Sopenharmony_ci tty_unregister_driver(driver); 81162306a36Sopenharmony_cierr_tty_driver_kref_put: 81262306a36Sopenharmony_ci tty_driver_kref_put(driver); 81362306a36Sopenharmony_cierr_free_bcs: 81462306a36Sopenharmony_ci kfree(bcs); 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci return ret; 81762306a36Sopenharmony_ci} 81862306a36Sopenharmony_cidevice_initcall(ehv_bc_init); 819