aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-07-24 22:12:32 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-08-14 00:57:40 -0400
commit7191b615759ec10cab9eea43be5ecc42cda82364 (patch)
tree48e96713113f5c8a54a7021d0dd5bc6b31d32f15
parent1a85d66bcc90e2cbdf04f70d6586b82532142e85 (diff)
powerpc/pmac: Early debug output on screen on 64-bit macs
We have a bunch of CONFIG_PPC_EARLY_DEBUG_* options that are intended for bringup/debug only. They hard wire a machine specific udbg backend very early on (before we even probe the platform), and use whatever tricks are available on each machine/cpu to be able to get some kind of output out there early on. So far, on powermac with no serial ports, we have CONFIG_PPC_EARLY_DEBUG_BOOTX to use the low-level btext engine on the screen, but it doesn't do much, at least on 64-bit. It only really gets enabled after the platform has been probed and the MMU enabled. This adds a way to enable it much earlier. From prom_init.c (while still running with Open Firmware), we grab the screen details and set things up using the physical address of the frame buffer. Then btext itself uses the "rm_ci" feature of the 970 processor (Real Mode Cache Inhibited) to access it while in real mode. We need to do a little bit of reorg of the btext code to inline things better, in order to limit how much we touch memory while in this mode as the consequences might be ... interesting. This successfully allowed me to debug problems early on with the G5 (related to gold being broken vs. ppc64 kernels). Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--arch/powerpc/include/asm/btext.h1
-rw-r--r--arch/powerpc/kernel/btext.c254
-rw-r--r--arch/powerpc/kernel/misc_64.S31
-rw-r--r--arch/powerpc/kernel/prom_init.c16
-rw-r--r--arch/powerpc/kernel/prom_init_check.sh3
-rw-r--r--arch/powerpc/kernel/setup_64.c14
6 files changed, 202 insertions, 117 deletions
diff --git a/arch/powerpc/include/asm/btext.h b/arch/powerpc/include/asm/btext.h
index 906f46e31006..89fc382648bc 100644
--- a/arch/powerpc/include/asm/btext.h
+++ b/arch/powerpc/include/asm/btext.h
@@ -13,6 +13,7 @@ extern void btext_update_display(unsigned long phys, int width, int height,
13extern void btext_setup_display(int width, int height, int depth, int pitch, 13extern void btext_setup_display(int width, int height, int depth, int pitch,
14 unsigned long address); 14 unsigned long address);
15extern void btext_prepare_BAT(void); 15extern void btext_prepare_BAT(void);
16extern void btext_map(void);
16extern void btext_unmap(void); 17extern void btext_unmap(void);
17 18
18extern void btext_drawchar(char c); 19extern void btext_drawchar(char c);
diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c
index ac8f52732fde..0428992fdb4b 100644
--- a/arch/powerpc/kernel/btext.c
+++ b/arch/powerpc/kernel/btext.c
@@ -25,11 +25,6 @@
25static void scrollscreen(void); 25static void scrollscreen(void);
26#endif 26#endif
27 27
28static void draw_byte(unsigned char c, long locX, long locY);
29static void draw_byte_32(unsigned char *bits, unsigned int *base, int rb);
30static void draw_byte_16(unsigned char *bits, unsigned int *base, int rb);
31static void draw_byte_8(unsigned char *bits, unsigned int *base, int rb);
32
33#define __force_data __attribute__((__section__(".data"))) 28#define __force_data __attribute__((__section__(".data")))
34 29
35static int g_loc_X __force_data; 30static int g_loc_X __force_data;
@@ -52,6 +47,26 @@ static unsigned char vga_font[cmapsz];
52int boot_text_mapped __force_data = 0; 47int boot_text_mapped __force_data = 0;
53int force_printk_to_btext = 0; 48int force_printk_to_btext = 0;
54 49
50extern void rmci_on(void);
51extern void rmci_off(void);
52
53static inline void rmci_maybe_on(void)
54{
55#ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX
56 if (!(mfmsr() & MSR_DR))
57 rmci_on();
58#endif
59}
60
61static inline void rmci_maybe_off(void)
62{
63#ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX
64 if (!(mfmsr() & MSR_DR))
65 rmci_off();
66#endif
67}
68
69
55#ifdef CONFIG_PPC32 70#ifdef CONFIG_PPC32
56/* Calc BAT values for mapping the display and store them 71/* Calc BAT values for mapping the display and store them
57 * in disp_BAT. Those values are then used from head.S to map 72 * in disp_BAT. Those values are then used from head.S to map
@@ -134,7 +149,7 @@ void __init btext_unmap(void)
134 * changes. 149 * changes.
135 */ 150 */
136 151
137static void map_boot_text(void) 152void btext_map(void)
138{ 153{
139 unsigned long base, offset, size; 154 unsigned long base, offset, size;
140 unsigned char *vbase; 155 unsigned char *vbase;
@@ -209,7 +224,7 @@ int btext_initialize(struct device_node *np)
209 dispDeviceRect[2] = width; 224 dispDeviceRect[2] = width;
210 dispDeviceRect[3] = height; 225 dispDeviceRect[3] = height;
211 226
212 map_boot_text(); 227 btext_map();
213 228
214 return 0; 229 return 0;
215} 230}
@@ -283,7 +298,7 @@ void btext_update_display(unsigned long phys, int width, int height,
283 iounmap(logicalDisplayBase); 298 iounmap(logicalDisplayBase);
284 boot_text_mapped = 0; 299 boot_text_mapped = 0;
285 } 300 }
286 map_boot_text(); 301 btext_map();
287 g_loc_X = 0; 302 g_loc_X = 0;
288 g_loc_Y = 0; 303 g_loc_Y = 0;
289 g_max_loc_X = width / 8; 304 g_max_loc_X = width / 8;
@@ -298,6 +313,7 @@ void btext_clearscreen(void)
298 (dispDeviceDepth >> 3)) >> 2; 313 (dispDeviceDepth >> 3)) >> 2;
299 int i,j; 314 int i,j;
300 315
316 rmci_maybe_on();
301 for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1]); i++) 317 for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1]); i++)
302 { 318 {
303 unsigned int *ptr = base; 319 unsigned int *ptr = base;
@@ -305,6 +321,7 @@ void btext_clearscreen(void)
305 *(ptr++) = 0; 321 *(ptr++) = 0;
306 base += (dispDeviceRowBytes >> 2); 322 base += (dispDeviceRowBytes >> 2);
307 } 323 }
324 rmci_maybe_off();
308} 325}
309 326
310void btext_flushscreen(void) 327void btext_flushscreen(void)
@@ -355,6 +372,8 @@ static void scrollscreen(void)
355 (dispDeviceDepth >> 3)) >> 2; 372 (dispDeviceDepth >> 3)) >> 2;
356 int i,j; 373 int i,j;
357 374
375 rmci_maybe_on();
376
358 for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1] - 16); i++) 377 for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1] - 16); i++)
359 { 378 {
360 unsigned int *src_ptr = src; 379 unsigned int *src_ptr = src;
@@ -371,9 +390,116 @@ static void scrollscreen(void)
371 *(dst_ptr++) = 0; 390 *(dst_ptr++) = 0;
372 dst += (dispDeviceRowBytes >> 2); 391 dst += (dispDeviceRowBytes >> 2);
373 } 392 }
393
394 rmci_maybe_off();
374} 395}
375#endif /* ndef NO_SCROLL */ 396#endif /* ndef NO_SCROLL */
376 397
398static unsigned int expand_bits_8[16] = {
399 0x00000000,
400 0x000000ff,
401 0x0000ff00,
402 0x0000ffff,
403 0x00ff0000,
404 0x00ff00ff,
405 0x00ffff00,
406 0x00ffffff,
407 0xff000000,
408 0xff0000ff,
409 0xff00ff00,
410 0xff00ffff,
411 0xffff0000,
412 0xffff00ff,
413 0xffffff00,
414 0xffffffff
415};
416
417static unsigned int expand_bits_16[4] = {
418 0x00000000,
419 0x0000ffff,
420 0xffff0000,
421 0xffffffff
422};
423
424
425static void draw_byte_32(unsigned char *font, unsigned int *base, int rb)
426{
427 int l, bits;
428 int fg = 0xFFFFFFFFUL;
429 int bg = 0x00000000UL;
430
431 for (l = 0; l < 16; ++l)
432 {
433 bits = *font++;
434 base[0] = (-(bits >> 7) & fg) ^ bg;
435 base[1] = (-((bits >> 6) & 1) & fg) ^ bg;
436 base[2] = (-((bits >> 5) & 1) & fg) ^ bg;
437 base[3] = (-((bits >> 4) & 1) & fg) ^ bg;
438 base[4] = (-((bits >> 3) & 1) & fg) ^ bg;
439 base[5] = (-((bits >> 2) & 1) & fg) ^ bg;
440 base[6] = (-((bits >> 1) & 1) & fg) ^ bg;
441 base[7] = (-(bits & 1) & fg) ^ bg;
442 base = (unsigned int *) ((char *)base + rb);
443 }
444}
445
446static inline void draw_byte_16(unsigned char *font, unsigned int *base, int rb)
447{
448</