^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * vio driver interface to hvc_console.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This code was moved here to allow the remaining code to be reused as a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * generic polling mode with semi-reliable transport driver core to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * console and tty subsystems.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Copyright (C) 2001 Paul Mackerras <paulus@au.ibm.com>, IBM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Copyright (C) 2004 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Copyright (C) 2004 IBM Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Additional Author(s):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Ryan S. Arnold <rsa@us.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * TODO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * - handle error in sending hvsi protocol packets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * - retry nego on subsequent sends ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #undef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/console.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <asm/hvconsole.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <asm/vio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <asm/prom.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <asm/hvsi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <asm/udbg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <asm/machdep.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include "hvc_console.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static const char hvc_driver_name[] = "hvc_console";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static const struct vio_device_id hvc_driver_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {"serial", "hvterm1"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #ifndef HVC_OLD_HVSI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {"serial", "hvterm-protocol"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) { "", "" }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) typedef enum hv_protocol {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) HV_PROTOCOL_RAW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) HV_PROTOCOL_HVSI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) } hv_protocol_t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct hvterm_priv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) u32 termno; /* HV term number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) hv_protocol_t proto; /* Raw data or HVSI packets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct hvsi_priv hvsi; /* HVSI specific data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) spinlock_t buf_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) char buf[SIZE_VIO_GET_CHARS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) int left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static struct hvterm_priv *hvterm_privs[MAX_NR_HVC_CONSOLES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /* For early boot console */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static struct hvterm_priv hvterm_priv0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static int hvterm_raw_get_chars(uint32_t vtermno, char *buf, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct hvterm_priv *pv = hvterm_privs[vtermno];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) unsigned long i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) int got;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (WARN_ON(!pv))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) spin_lock_irqsave(&pv->buf_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (pv->left == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) pv->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) pv->left = hvc_get_chars(pv->termno, pv->buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * Work around a HV bug where it gives us a null
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * after every \r. -- paulus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) for (i = 1; i < pv->left; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (pv->buf[i] == 0 && pv->buf[i-1] == '\r') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) --pv->left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (i < pv->left) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) memmove(&pv->buf[i], &pv->buf[i+1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) pv->left - i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) got = min(count, pv->left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) memcpy(buf, &pv->buf[pv->offset], got);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) pv->offset += got;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) pv->left -= got;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) spin_unlock_irqrestore(&pv->buf_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return got;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * hvterm_raw_put_chars: send characters to firmware for given vterm adapter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * @vtermno: The virtual terminal number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * @buf: The characters to send. Because of the underlying hypercall in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * hvc_put_chars(), this buffer must be at least 16 bytes long, even if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * you are sending fewer chars.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * @count: number of chars to send.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static int hvterm_raw_put_chars(uint32_t vtermno, const char *buf, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct hvterm_priv *pv = hvterm_privs[vtermno];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (WARN_ON(!pv))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return hvc_put_chars(pv->termno, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static const struct hv_ops hvterm_raw_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) .get_chars = hvterm_raw_get_chars,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) .put_chars = hvterm_raw_put_chars,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) .notifier_add = notifier_add_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) .notifier_del = notifier_del_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) .notifier_hangup = notifier_hangup_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static int hvterm_hvsi_get_chars(uint32_t vtermno, char *buf, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) struct hvterm_priv *pv = hvterm_privs[vtermno];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (WARN_ON(!pv))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return hvsilib_get_chars(&pv->hvsi, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static int hvterm_hvsi_put_chars(uint32_t vtermno, const char *buf, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct hvterm_priv *pv = hvterm_privs[vtermno];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (WARN_ON(!pv))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return hvsilib_put_chars(&pv->hvsi, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static int hvterm_hvsi_open(struct hvc_struct *hp, int data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct hvterm_priv *pv = hvterm_privs[hp->vtermno];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) pr_devel("HVSI@%x: open !\n", pv->termno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) rc = notifier_add_irq(hp, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return hvsilib_open(&pv->hvsi, hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static void hvterm_hvsi_close(struct hvc_struct *hp, int data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) struct hvterm_priv *pv = hvterm_privs[hp->vtermno];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) pr_devel("HVSI@%x: do close !\n", pv->termno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) hvsilib_close(&pv->hvsi, hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) notifier_del_irq(hp, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) void hvterm_hvsi_hangup(struct hvc_struct *hp, int data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) struct hvterm_priv *pv = hvterm_privs[hp->vtermno];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) pr_devel("HVSI@%x: do hangup !\n", pv->termno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) hvsilib_close(&pv->hvsi, hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) notifier_hangup_irq(hp, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static int hvterm_hvsi_tiocmget(struct hvc_struct *hp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct hvterm_priv *pv = hvterm_privs[hp->vtermno];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (!pv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return pv->hvsi.mctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static int hvterm_hvsi_tiocmset(struct hvc_struct *hp, unsigned int set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) unsigned int clear)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) struct hvterm_priv *pv = hvterm_privs[hp->vtermno];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) pr_devel("HVSI@%x: Set modem control, set=%x,clr=%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) pv->termno, set, clear);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (set & TIOCM_DTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) hvsilib_write_mctrl(&pv->hvsi, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) else if (clear & TIOCM_DTR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) hvsilib_write_mctrl(&pv->hvsi, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static const struct hv_ops hvterm_hvsi_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) .get_chars = hvterm_hvsi_get_chars,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) .put_chars = hvterm_hvsi_put_chars,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) .notifier_add = hvterm_hvsi_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) .notifier_del = hvterm_hvsi_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) .notifier_hangup = hvterm_hvsi_hangup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) .tiocmget = hvterm_hvsi_tiocmget,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) .tiocmset = hvterm_hvsi_tiocmset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static void udbg_hvc_putc(char c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) int count = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) unsigned char bounce_buffer[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (!hvterm_privs[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (c == '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) udbg_hvc_putc('\r');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) switch(hvterm_privs[0]->proto) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) case HV_PROTOCOL_RAW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * hvterm_raw_put_chars requires at least a 16-byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * buffer, so go via the bounce buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) bounce_buffer[0] = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) count = hvterm_raw_put_chars(0, bounce_buffer, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) case HV_PROTOCOL_HVSI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) count = hvterm_hvsi_put_chars(0, &c, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) } while(count == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) static int udbg_hvc_getc_poll(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) char c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (!hvterm_privs[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) switch(hvterm_privs[0]->proto) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) case HV_PROTOCOL_RAW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) rc = hvterm_raw_get_chars(0, &c, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) case HV_PROTOCOL_HVSI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) rc = hvterm_hvsi_get_chars(0, &c, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) static int udbg_hvc_getc(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) int ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (!hvterm_privs[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) ch = udbg_hvc_getc_poll();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (ch == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) /* This shouldn't be needed...but... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) volatile unsigned long delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) for (delay=0; delay < 2000000; delay++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) static int hvc_vio_probe(struct vio_dev *vdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) const struct vio_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) const struct hv_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) struct hvc_struct *hp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) struct hvterm_priv *pv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) hv_protocol_t proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) int i, termno = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) /* probed with invalid parameters. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (!vdev || !id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (of_device_is_compatible(vdev->dev.of_node, "hvterm1")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) proto = HV_PROTOCOL_RAW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) ops = &hvterm_raw_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) } else if (of_device_is_compatible(vdev->dev.of_node, "hvterm-protocol")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) proto = HV_PROTOCOL_HVSI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) ops = &hvterm_hvsi_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) pr_err("hvc_vio: Unknown protocol for %pOF\n", vdev->dev.of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) pr_devel("hvc_vio_probe() device %pOF, using %s protocol\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) vdev->dev.of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) proto == HV_PROTOCOL_RAW ? "raw" : "hvsi");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) /* Is it our boot one ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (hvterm_privs[0] == &hvterm_priv0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) vdev->unit_address == hvterm_priv0.termno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) pv = hvterm_privs[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) termno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) pr_devel("->boot console, using termno 0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) /* nope, allocate a new one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) for (i = 0; i < MAX_NR_HVC_CONSOLES && termno < 0; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (!hvterm_privs[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) termno = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) pr_devel("->non-boot console, using termno %d\n", termno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (termno < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) pv = kzalloc(sizeof(struct hvterm_priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (!pv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) pv->termno = vdev->unit_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) pv->proto = proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) spin_lock_init(&pv->buf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) hvterm_privs[termno] = pv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) hvsilib_init(&pv->hvsi, hvc_get_chars, hvc_put_chars,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) pv->termno, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) hp = hvc_alloc(termno, vdev->irq, ops, MAX_VIO_PUT_CHARS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (IS_ERR(hp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) return PTR_ERR(hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) dev_set_drvdata(&vdev->dev, hp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) /* register udbg if it's not there already for console 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (hp->index == 0 && !udbg_putc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) udbg_putc = udbg_hvc_putc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) udbg_getc = udbg_hvc_getc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) udbg_getc_poll = udbg_hvc_getc_poll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) static struct vio_driver hvc_vio_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) .id_table = hvc_driver_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) .probe = hvc_vio_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) .name = hvc_driver_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) .suppress_bind_attrs = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) static int __init hvc_vio_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) /* Register as a vio device to receive callbacks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) rc = vio_register_driver(&hvc_vio_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) device_initcall(hvc_vio_init); /* after drivers/tty/hvc/hvc_console.c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) void __init hvc_vio_init_early(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) const __be32 *termno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) const struct hv_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) /* find the boot console from /chosen/stdout */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) /* Check if it's a virtual terminal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) if (!of_node_name_prefix(of_stdout, "vty"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) termno = of_get_property(of_stdout, "reg", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (termno == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) hvterm_priv0.termno = of_read_number(termno, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) spin_lock_init(&hvterm_priv0.buf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) hvterm_privs[0] = &hvterm_priv0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) /* Check the protocol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (of_device_is_compatible(of_stdout, "hvterm1")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) hvterm_priv0.proto = HV_PROTOCOL_RAW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) ops = &hvterm_raw_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) else if (of_device_is_compatible(of_stdout, "hvterm-protocol")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) hvterm_priv0.proto = HV_PROTOCOL_HVSI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) ops = &hvterm_hvsi_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) hvsilib_init(&hvterm_priv0.hvsi, hvc_get_chars, hvc_put_chars,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) hvterm_priv0.termno, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) /* HVSI, perform the handshake now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) hvsilib_establish(&hvterm_priv0.hvsi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) udbg_putc = udbg_hvc_putc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) udbg_getc = udbg_hvc_getc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) udbg_getc_poll = udbg_hvc_getc_poll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) #ifdef HVC_OLD_HVSI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) /* When using the old HVSI driver don't register the HVC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) * backend for HVSI, only do udbg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (hvterm_priv0.proto == HV_PROTOCOL_HVSI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) /* Check whether the user has requested a different console. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (!strstr(boot_command_line, "console="))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) add_preferred_console("hvc", 0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) hvc_instantiate(0, 0, ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) /* call this from early_init() for a working debug console on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) * vterm capable LPAR machines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) #ifdef CONFIG_PPC_EARLY_DEBUG_LPAR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) void __init udbg_init_debug_lpar(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) * If we're running as a hypervisor then we definitely can't call the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) * hypervisor to print debug output (we *are* the hypervisor), so don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) * register if we detect that MSR_HV=1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if (mfmsr() & MSR_HV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) hvterm_privs[0] = &hvterm_priv0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) hvterm_priv0.termno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) hvterm_priv0.proto = HV_PROTOCOL_RAW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) spin_lock_init(&hvterm_priv0.buf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) udbg_putc = udbg_hvc_putc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) udbg_getc = udbg_hvc_getc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) udbg_getc_poll = udbg_hvc_getc_poll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) #endif /* CONFIG_PPC_EARLY_DEBUG_LPAR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) #ifdef CONFIG_PPC_EARLY_DEBUG_LPAR_HVSI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) void __init udbg_init_debug_lpar_hvsi(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) /* See comment above in udbg_init_debug_lpar() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (mfmsr() & MSR_HV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) hvterm_privs[0] = &hvterm_priv0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) hvterm_priv0.termno = CONFIG_PPC_EARLY_DEBUG_HVSI_VTERMNO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) hvterm_priv0.proto = HV_PROTOCOL_HVSI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) spin_lock_init(&hvterm_priv0.buf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) udbg_putc = udbg_hvc_putc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) udbg_getc = udbg_hvc_getc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) udbg_getc_poll = udbg_hvc_getc_poll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) hvsilib_init(&hvterm_priv0.hvsi, hvc_get_chars, hvc_put_chars,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) hvterm_priv0.termno, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) hvsilib_establish(&hvterm_priv0.hvsi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) #endif /* CONFIG_PPC_EARLY_DEBUG_LPAR_HVSI */