aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/Kconfig.debug15
-rw-r--r--arch/powerpc/include/asm/udbg.h1
-rw-r--r--arch/powerpc/kernel/udbg.c3
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c189
-rw-r--r--arch/powerpc/platforms/pseries/pseries.h3
-rw-r--r--arch/powerpc/platforms/pseries/setup.c5
6 files changed, 24 insertions, 192 deletions
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index e72dcf6a421d..067cb8480747 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -167,6 +167,13 @@ config PPC_EARLY_DEBUG_LPAR
167 Select this to enable early debugging for a machine with a HVC 167 Select this to enable early debugging for a machine with a HVC
168 console on vterm 0. 168 console on vterm 0.
169 169
170config PPC_EARLY_DEBUG_LPAR_HVSI
171 bool "LPAR HVSI Console"
172 depends on PPC_PSERIES
173 help
174 Select this to enable early debugging for a machine with a HVSI
175 console on a specified vterm.
176
170config PPC_EARLY_DEBUG_G5 177config PPC_EARLY_DEBUG_G5
171 bool "Apple G5" 178 bool "Apple G5"
172 depends on PPC_PMAC64 179 depends on PPC_PMAC64
@@ -253,6 +260,14 @@ config PPC_EARLY_DEBUG_WSP
253 260
254endchoice 261endchoice
255 262
263config PPC_EARLY_DEBUG_HVSI_VTERMNO
264 hex "vterm number to use with early debug HVSI"
265 depends on PPC_EARLY_DEBUG_LPAR_HVSI
266 default "0x30000000"
267 help
268 You probably want 0x30000000 for your first serial port and
269 0x30000001 for your second one
270
256config PPC_EARLY_DEBUG_44x_PHYSLOW 271config PPC_EARLY_DEBUG_44x_PHYSLOW
257 hex "Low 32 bits of early debug UART physical address" 272 hex "Low 32 bits of early debug UART physical address"
258 depends on PPC_EARLY_DEBUG_44x 273 depends on PPC_EARLY_DEBUG_44x
diff --git a/arch/powerpc/include/asm/udbg.h b/arch/powerpc/include/asm/udbg.h
index 58580e94a2bb..93e05d1b34b2 100644
--- a/arch/powerpc/include/asm/udbg.h
+++ b/arch/powerpc/include/asm/udbg.h
@@ -40,6 +40,7 @@ extern void udbg_adb_init_early(void);
40 40
41extern void __init udbg_early_init(void); 41extern void __init udbg_early_init(void);
42extern void __init udbg_init_debug_lpar(void); 42extern void __init udbg_init_debug_lpar(void);
43extern void __init udbg_init_debug_lpar_hvsi(void);
43extern void __init udbg_init_pmac_realmode(void); 44extern void __init udbg_init_pmac_realmode(void);
44extern void __init udbg_init_maple_realmode(void); 45extern void __init udbg_init_maple_realmode(void);
45extern void __init udbg_init_pas_realmode(void); 46extern void __init udbg_init_pas_realmode(void);
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
index a57e61ea0558..faa82c1f3f68 100644
--- a/arch/powerpc/kernel/udbg.c
+++ b/arch/powerpc/kernel/udbg.c
@@ -31,6 +31,9 @@ void __init udbg_early_init(void)
31#if defined(CONFIG_PPC_EARLY_DEBUG_LPAR) 31#if defined(CONFIG_PPC_EARLY_DEBUG_LPAR)
32 /* For LPAR machines that have an HVC console on vterm 0 */ 32 /* For LPAR machines that have an HVC console on vterm 0 */
33 udbg_init_debug_lpar(); 33 udbg_init_debug_lpar();
34#elif defined(CONFIG_PPC_EARLY_DEBUG_LPAR_HVSI)
35 /* For LPAR machines that have an HVSI console on vterm 0 */
36 udbg_init_debug_lpar_hvsi();
34#elif defined(CONFIG_PPC_EARLY_DEBUG_G5) 37#elif defined(CONFIG_PPC_EARLY_DEBUG_G5)
35 /* For use on Apple G5 machines */ 38 /* For use on Apple G5 machines */
36 udbg_init_pmac_realmode(); 39 udbg_init_pmac_realmode();
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index e3a96c4348ab..f7205d344efd 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -52,195 +52,6 @@ EXPORT_SYMBOL(plpar_hcall_norets);
52 52
53extern void pSeries_find_serial_port(void); 53extern void pSeries_find_serial_port(void);
54 54
55
56static int vtermno; /* virtual terminal# for udbg */
57
58#define __ALIGNED__ __attribute__((__aligned__(sizeof(long))))
59static void udbg_hvsi_putc(char c)
60{
61 /* packet's seqno isn't used anyways */
62 uint8_t packet[] __ALIGNED__ = { 0xff, 5, 0, 0, c };
63 int rc;
64
65 if (c == '\n')
66 udbg_hvsi_putc('\r');
67
68 do {
69 rc = plpar_put_term_char(vtermno, sizeof(packet), packet);
70 } while (rc == H_BUSY);
71}
72
73static long hvsi_udbg_buf_len;
74static uint8_t hvsi_udbg_buf[256];
75
76static int udbg_hvsi_getc_poll(void)
77{
78 unsigned char ch;
79 int rc, i;
80
81 if (hvsi_udbg_buf_len == 0) {
82 rc = plpar_get_term_char(vtermno, &hvsi_udbg_buf_len, hvsi_udbg_buf);
83 if (rc != H_SUCCESS || hvsi_udbg_buf[0] != 0xff) {
84 /* bad read or non-data packet */
85 hvsi_udbg_buf_len = 0;
86 } else {
87 /* remove the packet header */
88 for (i = 4; i < hvsi_udbg_buf_len; i++)
89 hvsi_udbg_buf[i-4] = hvsi_udbg_buf[i];
90 hvsi_udbg_buf_len -= 4;
91 }
92 }
93
94 if (hvsi_udbg_buf_len <= 0 || hvsi_udbg_buf_len > 256) {
95 /* no data ready */
96 hvsi_udbg_buf_len = 0;
97 return -1;
98 }
99
100 ch = hvsi_udbg_buf[0];
101 /* shift remaining data down */
102 for (i = 1; i < hvsi_udbg_buf_len; i++) {
103 hvsi_udbg_buf[i-1] = hvsi_udbg_buf[i];
104 }
105 hvsi_udbg_buf_len--;
106
107 return ch;
108}
109
110static int udbg_hvsi_getc(void)
111{
112 int ch;
113 for (;;) {
114 ch = udbg_hvsi_getc_poll();
115 if (ch == -1) {
116 /* This shouldn't be needed...but... */
117 volatile unsigned long delay;
118 for (delay=0; delay < 2000000; delay++)
119 ;
120 } else {
121 return ch;
122 }
123 }
124}
125
126static void udbg_putcLP(char c)
127{
128 char buf[16];
129 unsigned long rc;
130
131 if (c == '\n')
132 udbg_putcLP('\r');
133
134 buf[0] = c;
135 do {
136 rc = plpar_put_term_char(vtermno, 1, buf);
137 } while(rc == H_BUSY);
138}
139
140/* Buffered chars getc */
141static long inbuflen;
142static long inbuf[2]; /* must be 2 longs */
143
144static int udbg_getc_pollLP(void)
145{
146 /* The interface is tricky because it may return up to 16 chars.
147 * We save them statically for future calls to udbg_getc().
148 */
149 char ch, *buf = (char *)inbuf;
150 int i;
151 long rc;
152 if (inbuflen == 0) {
153 /* get some more chars. */
154 inbuflen = 0;
155 rc = plpar_get_term_char(vtermno, &inbuflen, buf);
156 if (rc != H_SUCCESS)
157 inbuflen = 0; /* otherwise inbuflen is garbage */
158 }
159 if (inbuflen <= 0 || inbuflen > 16) {
160 /* Catch error case as well as other oddities (corruption) */
161 inbuflen = 0;
162 return -1;
163 }
164 ch = buf[0];
165 for (i = 1; i < inbuflen; i++) /* shuffle them down. */
166 buf[i-1] = buf[i];
167 inbuflen--;
168 return ch;
169}
170
171static int udbg_getcLP(void)
172{
173 int ch;
174 for (;;) {
175 ch = udbg_getc_pollLP();
176 if (ch == -1) {
177 /* This shouldn't be needed...but... */
178 volatile unsigned long delay;
179 for (delay=0; delay < 2000000; delay++)
180 ;
181 } else {
182 return ch;
183 }
184 }
185}
186
187/* call this from early_init() for a working debug console on
188 * vterm capable LPAR machines
189 */
190void __init udbg_init_debug_lpar(void)
191{
192 vtermno = 0;
193 udbg_putc = udbg_putcLP;
194 udbg_getc = udbg_getcLP;
195 udbg_getc_poll = udbg_getc_pollLP;
196}
197
198/* returns 0 if couldn't find or use /chosen/stdout as console */
199void __init find_udbg_vterm(void)
200{
201 struct device_node *stdout_node;
202 const u32 *termno;
203 const char *name;
204
205 /* find the boot console from /chosen/stdout */
206 if (!of_chosen)
207 return;
208 name = of_get_property(of_chosen, "linux,stdout-path", NULL);
209 if (name == NULL)
210 return;
211 stdout_node = of_find_node_by_path(name);
212 if (!stdout_node)
213 return;
214 name = of_get_property(stdout_node, "name", NULL);
215 if (!name) {
216 printk(KERN_WARNING "stdout node missing 'name' property!\n");
217 goto out;
218 }
219
220 /* Check if it's a virtual terminal */
221 if (strncmp(name, "vty", 3) != 0)
222 goto out;
223 termno = of_get_property(stdout_node, "reg", NULL);
224 if (termno == NULL)
225 goto out;
226 vtermno = termno[0];
227
228 if (of_device_is_compatible(stdout_node, "hvterm1")) {
229 udbg_putc = udbg_putcLP;
230 udbg_getc = udbg_getcLP;
231 udbg_getc_poll = udbg_getc_pollLP;
232 add_preferred_console("hvc", termno[0] & 0xff, NULL);
233 } else if (of_device_is_compatible(stdout_node, "hvterm-protocol")) {
234 vtermno = termno[0];
235 udbg_putc = udbg_hvsi_putc;
236 udbg_getc = udbg_hvsi_getc;
237 udbg_getc_poll = udbg_hvsi_getc_poll;
238 add_preferred_console("hvsi", termno[0] & 0xff, NULL);
239 }
240out:
241 of_node_put(stdout_node);
242}
243
244void vpa_init(int cpu) 55void vpa_init(int cpu)
245{ 56{
246 int hwcpu = get_hard_smp_processor_id(cpu); 57 int hwcpu = get_hard_smp_processor_id(cpu);
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h
index e9f6d2859c3c..24c7162f11d9 100644
--- a/arch/powerpc/platforms/pseries/pseries.h
+++ b/arch/powerpc/platforms/pseries/pseries.h
@@ -47,7 +47,8 @@ extern void pSeries_final_fixup(void);
47/* Poweron flag used for enabling auto ups restart */ 47/* Poweron flag used for enabling auto ups restart */
48extern unsigned long rtas_poweron_auto; 48extern unsigned long rtas_poweron_auto;
49 49
50extern void find_udbg_vterm(void); 50/* Provided by HVC VIO */
51extern void hvc_vio_init_early(void);
51 52
52/* Dynamic logical Partitioning/Mobility */ 53/* Dynamic logical Partitioning/Mobility */
53extern void dlpar_free_cc_nodes(struct device_node *); 54extern void dlpar_free_cc_nodes(struct device_node *);
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 593acceeff96..d00e52926b71 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -512,9 +512,10 @@ static void __init pSeries_init_early(void)
512{ 512{
513 pr_debug(" -> pSeries_init_early()\n"); 513 pr_debug(" -> pSeries_init_early()\n");
514 514
515#ifdef CONFIG_HVC_CONSOLE
515 if (firmware_has_feature(FW_FEATURE_LPAR)) 516 if (firmware_has_feature(FW_FEATURE_LPAR))
516 find_udbg_vterm(); 517 hvc_vio_init_early();
517 518#endif
518 if (firmware_has_feature(FW_FEATURE_DABR)) 519 if (firmware_has_feature(FW_FEATURE_DABR))
519 ppc_md.set_dabr = pseries_set_dabr; 520 ppc_md.set_dabr = pseries_set_dabr;
520 else if (firmware_has_feature(FW_FEATURE_XDABR)) 521 else if (firmware_has_feature(FW_FEATURE_XDABR))