24 #include <linux/types.h>
27 #include <linux/slab.h>
31 #include <linux/export.h>
42 static const char hvc_opal_name[] =
"hvc_opal";
45 { .name =
"serial", .compatible =
"ibm,opal-console-raw" },
46 { .name =
"serial", .compatible =
"ibm,opal-console-hvsi" },
63 static u32 hvc_opal_boot_termno;
65 static const struct hv_ops hvc_opal_raw_ops = {
83 static int hvc_opal_hvsi_put_chars(
uint32_t vtermno,
const char *buf,
int count)
107 static void hvc_opal_hvsi_close(
struct hvc_struct *hp,
int data)
129 static int hvc_opal_hvsi_tiocmget(
struct hvc_struct *hp)
135 return pv->
hvsi.mctrl;
138 static int hvc_opal_hvsi_tiocmset(
struct hvc_struct *hp,
unsigned int set,
143 pr_devel(
"HVSI@%x: Set modem control, set=%x,clr=%x\n",
154 static const struct hv_ops hvc_opal_hvsi_ops = {
155 .get_chars = hvc_opal_hvsi_get_chars,
156 .put_chars = hvc_opal_hvsi_put_chars,
157 .notifier_add = hvc_opal_hvsi_open,
158 .notifier_del = hvc_opal_hvsi_close,
160 .tiocmget = hvc_opal_hvsi_tiocmget,
161 .tiocmset = hvc_opal_hvsi_tiocmset,
170 unsigned int termno, boot = 0;
175 ops = &hvc_opal_raw_ops;
177 "ibm,opal-console-hvsi")) {
179 ops = &hvc_opal_hvsi_ops;
181 pr_err(
"hvc_opal: Unkown protocol for %s\n",
182 dev->
dev.of_node->full_name);
190 if (hvc_opal_privs[termno] == &hvc_opal_boot_priv) {
191 pv = hvc_opal_privs[termno];
193 }
else if (hvc_opal_privs[termno] ==
NULL) {
198 hvc_opal_privs[termno] =
pv;
206 pr_err(
"hvc_opal: Device %s has duplicate terminal number #%d\n",
207 dev->
dev.of_node->full_name, termno);
211 pr_info(
"hvc%d: %s protocol on %s%s\n", termno,
213 dev->
dev.of_node->full_name,
214 boot ?
" (boot console)" :
"");
217 hp =
hvc_alloc(termno, 0, ops, MAX_VIO_PUT_CHARS);
233 if (hvc_opal_privs[termno] != &hvc_opal_boot_priv)
234 kfree(hvc_opal_privs[termno]);
235 hvc_opal_privs[termno] =
NULL;
241 .probe = hvc_opal_probe,
244 .name = hvc_opal_name,
246 .of_match_table = hvc_opal_match,
250 static int __init hvc_opal_init(
void)
252 if (!firmware_has_feature(FW_FEATURE_OPAL))
260 static void __exit hvc_opal_exit(
void)
266 static void udbg_opal_putc(
char c)
268 unsigned int termno = hvc_opal_boot_termno;
272 udbg_opal_putc(
'\r');
275 switch(hvc_opal_boot_priv.proto) {
280 count = hvc_opal_hvsi_put_chars(termno, &c, 1);
283 }
while(count == 0 || count == -
EAGAIN);
286 static int udbg_opal_getc_poll(
void)
288 unsigned int termno = hvc_opal_boot_termno;
292 switch(hvc_opal_boot_priv.proto) {
297 rc = hvc_opal_hvsi_get_chars(termno, &c, 1);
305 static int udbg_opal_getc(
void)
309 ch = udbg_opal_getc_poll();
312 volatile unsigned long delay;
313 for (delay=0; delay < 2000000; delay++)
321 static void udbg_init_opal_common(
void)
343 pr_err(
"hvc_opal: Failed to locate default console!\n");
354 pr_devel(
"hvc_opal: Found consoles in new location\n");
359 "Found consoles in old location\n");
374 index = termno ? *termno : 0;
377 hvc_opal_privs[
index] = &hvc_opal_boot_priv;
382 ops = &hvc_opal_raw_ops;
383 pr_devel(
"hvc_opal: Found RAW console\n");
387 ops = &hvc_opal_hvsi_ops;
392 pr_devel(
"hvc_opal: Found HVSI console\n");
395 hvc_opal_boot_termno =
index;
396 udbg_init_opal_common();
400 of_node_put(stdout_node);
403 #ifdef CONFIG_PPC_EARLY_DEBUG_OPAL_RAW
404 void __init udbg_init_debug_opal_raw(
void)
406 u32 index = CONFIG_PPC_EARLY_DEBUG_OPAL_VTERMNO;
407 hvc_opal_privs[
index] = &hvc_opal_boot_priv;
409 hvc_opal_boot_termno =
index;
410 udbg_init_opal_common();
414 #ifdef CONFIG_PPC_EARLY_DEBUG_OPAL_HVSI
415 void __init udbg_init_debug_opal_hvsi(
void)
417 u32 index = CONFIG_PPC_EARLY_DEBUG_OPAL_VTERMNO;
418 hvc_opal_privs[
index] = &hvc_opal_boot_priv;
419 hvc_opal_boot_termno =
index;
420 udbg_init_opal_common();