diff options
| author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2013-07-24 22:12:32 -0400 |
|---|---|---|
| committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2013-08-14 00:57:40 -0400 |
| commit | 7191b615759ec10cab9eea43be5ecc42cda82364 (patch) | |
| tree | 48e96713113f5c8a54a7021d0dd5bc6b31d32f15 | |
| parent | 1a85d66bcc90e2cbdf04f70d6586b82532142e85 (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.h | 1 | ||||
| -rw-r--r-- | arch/powerpc/kernel/btext.c | 254 | ||||
| -rw-r--r-- | arch/powerpc/kernel/misc_64.S | 31 | ||||
| -rw-r--r-- | arch/powerpc/kernel/prom_init.c | 16 | ||||
| -rw-r--r-- | arch/powerpc/kernel/prom_init_check.sh | 3 | ||||
| -rw-r--r-- | arch/powerpc/kernel/setup_64.c | 14 |
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, | |||
| 13 | extern void btext_setup_display(int width, int height, int depth, int pitch, | 13 | extern void btext_setup_display(int width, int height, int depth, int pitch, |
| 14 | unsigned long address); | 14 | unsigned long address); |
| 15 | extern void btext_prepare_BAT(void); | 15 | extern void btext_prepare_BAT(void); |
| 16 | extern void btext_map(void); | ||
| 16 | extern void btext_unmap(void); | 17 | extern void btext_unmap(void); |
| 17 | 18 | ||
| 18 | extern void btext_drawchar(char c); | 19 | extern 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 @@ | |||
| 25 | static void scrollscreen(void); | 25 | static void scrollscreen(void); |
| 26 | #endif | 26 | #endif |
| 27 | 27 | ||
| 28 | static void draw_byte(unsigned char c, long locX, long locY); | ||
| 29 | static void draw_byte_32(unsigned char *bits, unsigned int *base, int rb); | ||
| 30 | static void draw_byte_16(unsigned char *bits, unsigned int *base, int rb); | ||
| 31 | static 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 | ||
| 35 | static int g_loc_X __force_data; | 30 | static int g_loc_X __force_data; |
| @@ -52,6 +47,26 @@ static unsigned char vga_font[cmapsz]; | |||
| 52 | int boot_text_mapped __force_data = 0; | 47 | int boot_text_mapped __force_data = 0; |
| 53 | int force_printk_to_btext = 0; | 48 | int force_printk_to_btext = 0; |
| 54 | 49 | ||
| 50 | extern void rmci_on(void); | ||
| 51 | extern void rmci_off(void); | ||
| 52 | |||
| 53 | static 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 | |||
| 61 | static 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 | ||
| 137 | static void map_boot_text(void) | 152 | void 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 | ||
| 310 | void btext_flushscreen(void) | 327 | void 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 | ||
| 398 | static 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 | |||
| 417 | static unsigned int expand_bits_16[4] = { | ||
| 418 | 0x00000000, | ||
| 419 | 0x0000ffff, | ||
| 420 | 0xffff0000, | ||
| 421 | 0xffffffff | ||
| 422 | }; | ||
| 423 | |||
| 424 | |||
| 425 | static 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 | |||
| 446 | static inline void draw_byte_16(unsigned char *font, unsigned int *base, int rb) | ||
| 447 | { | ||
| 448 | |||
