1e3b3d0f5SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0+ 2728674a7SGreg Kroah-Hartman /* 3728674a7SGreg Kroah-Hartman * IBM RTAS driver interface to hvc_console.c 4728674a7SGreg Kroah-Hartman * 5728674a7SGreg Kroah-Hartman * (C) Copyright IBM Corporation 2001-2005 6728674a7SGreg Kroah-Hartman * (C) Copyright Red Hat, Inc. 2005 7728674a7SGreg Kroah-Hartman * 8728674a7SGreg Kroah-Hartman * Author(s): Maximino Augilar <IBM STI Design Center> 9728674a7SGreg Kroah-Hartman * : Ryan S. Arnold <rsa@us.ibm.com> 10728674a7SGreg Kroah-Hartman * : Utz Bacher <utz.bacher@de.ibm.com> 11728674a7SGreg Kroah-Hartman * : David Woodhouse <dwmw2@infradead.org> 12728674a7SGreg Kroah-Hartman * 13728674a7SGreg Kroah-Hartman * inspired by drivers/char/hvc_console.c 14728674a7SGreg Kroah-Hartman * written by Anton Blanchard and Paul Mackerras 15728674a7SGreg Kroah-Hartman * 16728674a7SGreg Kroah-Hartman * This program is free software; you can redistribute it and/or modify 17728674a7SGreg Kroah-Hartman * it under the terms of the GNU General Public License as published by 18728674a7SGreg Kroah-Hartman * the Free Software Foundation; either version 2 of the License, or 19728674a7SGreg Kroah-Hartman * (at your option) any later version. 20728674a7SGreg Kroah-Hartman * 21728674a7SGreg Kroah-Hartman * This program is distributed in the hope that it will be useful, 22728674a7SGreg Kroah-Hartman * but WITHOUT ANY WARRANTY; without even the implied warranty of 23728674a7SGreg Kroah-Hartman * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24728674a7SGreg Kroah-Hartman * GNU General Public License for more details. 25728674a7SGreg Kroah-Hartman * 26728674a7SGreg Kroah-Hartman * You should have received a copy of the GNU General Public License 27728674a7SGreg Kroah-Hartman * along with this program; if not, write to the Free Software 28728674a7SGreg Kroah-Hartman * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 29728674a7SGreg Kroah-Hartman */ 30728674a7SGreg Kroah-Hartman 31728674a7SGreg Kroah-Hartman #include <linux/console.h> 32728674a7SGreg Kroah-Hartman #include <linux/delay.h> 33728674a7SGreg Kroah-Hartman #include <linux/err.h> 34728674a7SGreg Kroah-Hartman #include <linux/init.h> 35728674a7SGreg Kroah-Hartman #include <linux/moduleparam.h> 36728674a7SGreg Kroah-Hartman #include <linux/types.h> 37728674a7SGreg Kroah-Hartman 38728674a7SGreg Kroah-Hartman #include <asm/irq.h> 39728674a7SGreg Kroah-Hartman #include <asm/rtas.h> 40728674a7SGreg Kroah-Hartman #include "hvc_console.h" 41728674a7SGreg Kroah-Hartman 42728674a7SGreg Kroah-Hartman #define hvc_rtas_cookie 0x67781e15 43728674a7SGreg Kroah-Hartman struct hvc_struct *hvc_rtas_dev; 44728674a7SGreg Kroah-Hartman 45728674a7SGreg Kroah-Hartman static int rtascons_put_char_token = RTAS_UNKNOWN_SERVICE; 46728674a7SGreg Kroah-Hartman static int rtascons_get_char_token = RTAS_UNKNOWN_SERVICE; 47728674a7SGreg Kroah-Hartman 48728674a7SGreg Kroah-Hartman static inline int hvc_rtas_write_console(uint32_t vtermno, const char *buf, 49728674a7SGreg Kroah-Hartman int count) 50728674a7SGreg Kroah-Hartman { 51728674a7SGreg Kroah-Hartman int i; 52728674a7SGreg Kroah-Hartman 53728674a7SGreg Kroah-Hartman for (i = 0; i < count; i++) { 54728674a7SGreg Kroah-Hartman if (rtas_call(rtascons_put_char_token, 1, 1, NULL, buf[i])) 55728674a7SGreg Kroah-Hartman break; 56728674a7SGreg Kroah-Hartman } 57728674a7SGreg Kroah-Hartman 58728674a7SGreg Kroah-Hartman return i; 59728674a7SGreg Kroah-Hartman } 60728674a7SGreg Kroah-Hartman 61728674a7SGreg Kroah-Hartman static int hvc_rtas_read_console(uint32_t vtermno, char *buf, int count) 62728674a7SGreg Kroah-Hartman { 63728674a7SGreg Kroah-Hartman int i, c; 64728674a7SGreg Kroah-Hartman 65728674a7SGreg Kroah-Hartman for (i = 0; i < count; i++) { 66728674a7SGreg Kroah-Hartman if (rtas_call(rtascons_get_char_token, 0, 2, &c)) 67728674a7SGreg Kroah-Hartman break; 68728674a7SGreg Kroah-Hartman 69728674a7SGreg Kroah-Hartman buf[i] = c; 70728674a7SGreg Kroah-Hartman } 71728674a7SGreg Kroah-Hartman 72728674a7SGreg Kroah-Hartman return i; 73728674a7SGreg Kroah-Hartman } 74728674a7SGreg Kroah-Hartman 75728674a7SGreg Kroah-Hartman static const struct hv_ops hvc_rtas_get_put_ops = { 76728674a7SGreg Kroah-Hartman .get_chars = hvc_rtas_read_console, 77728674a7SGreg Kroah-Hartman .put_chars = hvc_rtas_write_console, 78728674a7SGreg Kroah-Hartman }; 79728674a7SGreg Kroah-Hartman 80728674a7SGreg Kroah-Hartman static int __init hvc_rtas_init(void) 81728674a7SGreg Kroah-Hartman { 82728674a7SGreg Kroah-Hartman struct hvc_struct *hp; 83728674a7SGreg Kroah-Hartman 84728674a7SGreg Kroah-Hartman if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE) 85728674a7SGreg Kroah-Hartman rtascons_put_char_token = rtas_token("put-term-char"); 86728674a7SGreg Kroah-Hartman if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE) 87728674a7SGreg Kroah-Hartman return -EIO; 88728674a7SGreg Kroah-Hartman 89728674a7SGreg Kroah-Hartman if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE) 90728674a7SGreg Kroah-Hartman rtascons_get_char_token = rtas_token("get-term-char"); 91728674a7SGreg Kroah-Hartman if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE) 92728674a7SGreg Kroah-Hartman return -EIO; 93728674a7SGreg Kroah-Hartman 94728674a7SGreg Kroah-Hartman BUG_ON(hvc_rtas_dev); 95728674a7SGreg Kroah-Hartman 96728674a7SGreg Kroah-Hartman /* Allocate an hvc_struct for the console device we instantiated 97728674a7SGreg Kroah-Hartman * earlier. Save off hp so that we can return it on exit */ 98d4e33facSAlan Cox hp = hvc_alloc(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops, 16); 99728674a7SGreg Kroah-Hartman if (IS_ERR(hp)) 100728674a7SGreg Kroah-Hartman return PTR_ERR(hp); 101728674a7SGreg Kroah-Hartman 102728674a7SGreg Kroah-Hartman hvc_rtas_dev = hp; 103728674a7SGreg Kroah-Hartman 104728674a7SGreg Kroah-Hartman return 0; 105728674a7SGreg Kroah-Hartman } 1064fedd0bfSPaul Gortmaker device_initcall(hvc_rtas_init); 107728674a7SGreg Kroah-Hartman 108728674a7SGreg Kroah-Hartman /* This will happen prior to module init. There is no tty at this time? */ 109728674a7SGreg Kroah-Hartman static int __init hvc_rtas_console_init(void) 110728674a7SGreg Kroah-Hartman { 111728674a7SGreg Kroah-Hartman rtascons_put_char_token = rtas_token("put-term-char"); 112728674a7SGreg Kroah-Hartman if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE) 113728674a7SGreg Kroah-Hartman return -EIO; 114728674a7SGreg Kroah-Hartman 115728674a7SGreg Kroah-Hartman rtascons_get_char_token = rtas_token("get-term-char"); 116728674a7SGreg Kroah-Hartman if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE) 117728674a7SGreg Kroah-Hartman return -EIO; 118728674a7SGreg Kroah-Hartman 119728674a7SGreg Kroah-Hartman hvc_instantiate(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops); 120728674a7SGreg Kroah-Hartman add_preferred_console("hvc", 0, NULL); 121728674a7SGreg Kroah-Hartman 122728674a7SGreg Kroah-Hartman return 0; 123728674a7SGreg Kroah-Hartman } 124728674a7SGreg Kroah-Hartman console_initcall(hvc_rtas_console_init); 125