Commit | Line | Data |
---|---|---|
656ad58e OH |
1 | /* |
2 | * Copyright (c) 2016 IBM Corporation. | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or | |
5 | * modify it under the terms of the GNU General Public License | |
6 | * as published by the Free Software Foundation; either version | |
7 | * 2 of the License, or (at your option) any later version. | |
8 | */ | |
9 | ||
10 | #include "ops.h" | |
11 | #include "stdio.h" | |
12 | #include "io.h" | |
13 | #include <libfdt.h> | |
14 | #include "../include/asm/opal-api.h" | |
15 | ||
16 | #ifdef __powerpc64__ | |
17 | ||
18 | /* Global OPAL struct used by opal-call.S */ | |
19 | struct opal { | |
20 | u64 base; | |
21 | u64 entry; | |
22 | } opal; | |
23 | ||
24 | static u32 opal_con_id; | |
25 | ||
26 | int64_t opal_console_write(int64_t term_number, u64 *length, const u8 *buffer); | |
27 | int64_t opal_console_read(int64_t term_number, uint64_t *length, u8 *buffer); | |
28 | int64_t opal_console_write_buffer_space(uint64_t term_number, uint64_t *length); | |
29 | int64_t opal_console_flush(uint64_t term_number); | |
30 | int64_t opal_poll_events(uint64_t *outstanding_event_mask); | |
31 | ||
32 | static int opal_con_open(void) | |
33 | { | |
34 | return 0; | |
35 | } | |
36 | ||
37 | static void opal_con_putc(unsigned char c) | |
38 | { | |
39 | int64_t rc; | |
40 | uint64_t olen, len; | |
41 | ||
42 | do { | |
43 | rc = opal_console_write_buffer_space(opal_con_id, &olen); | |
44 | len = be64_to_cpu(olen); | |
45 | if (rc) | |
46 | return; | |
47 | opal_poll_events(NULL); | |
48 | } while (len < 1); | |
49 | ||
50 | ||
51 | olen = cpu_to_be64(1); | |
52 | opal_console_write(opal_con_id, &olen, &c); | |
53 | } | |
54 | ||
55 | static void opal_con_close(void) | |
56 | { | |
57 | opal_console_flush(opal_con_id); | |
58 | } | |
59 | ||
60 | static void opal_init(void) | |
61 | { | |
62 | void *opal_node; | |
63 | ||
64 | opal_node = finddevice("/ibm,opal"); | |
65 | if (!opal_node) | |
66 | return; | |
67 | if (getprop(opal_node, "opal-base-address", &opal.base, sizeof(u64)) < 0) | |
68 | return; | |
69 | opal.base = be64_to_cpu(opal.base); | |
70 | if (getprop(opal_node, "opal-entry-address", &opal.entry, sizeof(u64)) < 0) | |
71 | return; | |
72 | opal.entry = be64_to_cpu(opal.entry); | |
73 | } | |
74 | ||
75 | int opal_console_init(void *devp, struct serial_console_data *scdp) | |
76 | { | |
77 | opal_init(); | |
78 | ||
79 | if (devp) { | |
80 | int n = getprop(devp, "reg", &opal_con_id, sizeof(u32)); | |
81 | if (n != sizeof(u32)) | |
82 | return -1; | |
83 | opal_con_id = be32_to_cpu(opal_con_id); | |
84 | } else | |
85 | opal_con_id = 0; | |
86 | ||
87 | scdp->open = opal_con_open; | |
88 | scdp->putc = opal_con_putc; | |
89 | scdp->close = opal_con_close; | |
90 | ||
91 | return 0; | |
92 | } | |
93 | #else | |
94 | int opal_console_init(void *devp, struct serial_console_data *scdp) | |
95 | { | |
96 | return -1; | |
97 | } | |
98 | #endif /* __powerpc64__ */ |