Skip to content

Commit

Permalink
[PATCH] powerpc: Unify udbg (#2)
Browse files Browse the repository at this point in the history
This patch unifies udbg for both ppc32 and ppc64 when building the
merged achitecture. xmon now has a single "back end". The powermac udbg
stuff gets enriched with some ADB capabilities and btext output. In
addition, the early_init callback is now called on ppc32 as well,
approx. in the same order as ppc64 regarding device-tree manipulations.
The init sequences of ppc32 and ppc64 are getting closer, I'll unify
them in a later patch.

For now, you can force udbg to the scc using "sccdbg" or to btext using
"btextdbg" on powermacs. I'll implement a cleaner way of forcing udbg
output to something else than the autodetected OF output device in a
later patch.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
  • Loading branch information
ozbenh authored and paulusmack committed Jan 9, 2006
1 parent 463ce0e commit 51d3082
Show file tree
Hide file tree
Showing 29 changed files with 627 additions and 720 deletions.
2 changes: 1 addition & 1 deletion arch/powerpc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ config PPC

config EARLY_PRINTK
bool
default y if PPC64
default y

config COMPAT
bool
Expand Down
7 changes: 3 additions & 4 deletions arch/powerpc/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ obj-y += vdso32/
obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \
signal_64.o ptrace32.o systbl.o \
paca.o ioctl32.o cpu_setup_power4.o \
firmware.o sysfs.o udbg.o idle_64.o
firmware.o sysfs.o idle_64.o
obj-$(CONFIG_PPC64) += vdso64/
obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
obj-$(CONFIG_POWER4) += idle_power4.o
Expand Down Expand Up @@ -46,7 +46,7 @@ extra-$(CONFIG_8xx) := head_8xx.o
extra-y += vmlinux.lds

obj-y += process.o init_task.o time.o \
prom.o traps.o setup-common.o
prom.o traps.o setup-common.o udbg.o
obj-$(CONFIG_PPC32) += entry_32.o setup_32.o misc_32.o systbl.o
obj-$(CONFIG_PPC64) += misc_64.o dma_64.o iommu.o
obj-$(CONFIG_PPC_OF) += prom_init.o
Expand All @@ -56,8 +56,7 @@ obj-$(CONFIG_6xx) += idle_6xx.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_KPROBES) += kprobes.o
obj-$(CONFIG_PPC_MULTIPLATFORM) += legacy_serial.o
obj64-$(CONFIG_PPC_MULTIPLATFORM) += udbg_16550.o
obj64-$(CONFIG_PPC_PMAC) += udbg_scc.o
obj-$(CONFIG_PPC_MULTIPLATFORM) += udbg_16550.o
module-$(CONFIG_PPC64) += module_64.o
obj-$(CONFIG_MODULES) += $(module-y)

Expand Down
130 changes: 93 additions & 37 deletions arch/powerpc/kernel/btext.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,26 @@ static void draw_byte_32(unsigned char *bits, unsigned int *base, int rb);
static void draw_byte_16(unsigned char *bits, unsigned int *base, int rb);
static void draw_byte_8(unsigned char *bits, unsigned int *base, int rb);

static int g_loc_X;
static int g_loc_Y;
static int g_max_loc_X;
static int g_max_loc_Y;
#define __force_data __attribute__((__section__(".data")))

static int dispDeviceRowBytes;
static int dispDeviceDepth;
static int dispDeviceRect[4];
static unsigned char *dispDeviceBase, *logicalDisplayBase;
static int g_loc_X __force_data;
static int g_loc_Y __force_data;
static int g_max_loc_X __force_data;
static int g_max_loc_Y __force_data;

static int dispDeviceRowBytes __force_data;
static int dispDeviceDepth __force_data;
static int dispDeviceRect[4] __force_data;
static unsigned char *dispDeviceBase __force_data;
static unsigned char *logicalDisplayBase __force_data;

unsigned long disp_BAT[2] __initdata = {0, 0};

#define cmapsz (16*256)

static unsigned char vga_font[cmapsz];

int boot_text_mapped;
int boot_text_mapped __force_data = 0;
int force_printk_to_btext = 0;

#ifdef CONFIG_PPC32
Expand All @@ -66,8 +69,7 @@ int force_printk_to_btext = 0;
* is really badly aligned, but I didn't encounter this case
* yet.
*/
void __init
btext_prepare_BAT(void)
void __init btext_prepare_BAT(void)
{
unsigned long vaddr = KERNELBASE + 0x10000000;
unsigned long addr;
Expand Down Expand Up @@ -95,12 +97,13 @@ btext_prepare_BAT(void)
}
#endif

/* This function will enable the early boot text when doing OF booting. This
* way, xmon output should work too

/* This function can be used to enable the early boot text when doing
* OF booting or within bootx init. It must be followed by a btext_unmap()
* call before the logical address becomes unuseable
*/
void __init
btext_setup_display(int width, int height, int depth, int pitch,
unsigned long address)
void __init btext_setup_display(int width, int height, int depth, int pitch,
unsigned long address)
{
g_loc_X = 0;
g_loc_Y = 0;
Expand All @@ -116,6 +119,11 @@ btext_setup_display(int width, int height, int depth, int pitch,
boot_text_mapped = 1;
}

void __init btext_unmap(void)
{
boot_text_mapped = 0;
}

/* Here's a small text engine to use during early boot
* or for debugging purposes
*
Expand All @@ -127,7 +135,7 @@ btext_setup_display(int width, int height, int depth, int pitch,
* changes.
*/

void map_boot_text(void)
static void map_boot_text(void)
{
unsigned long base, offset, size;
unsigned char *vbase;
Expand Down Expand Up @@ -175,16 +183,16 @@ int btext_initialize(struct device_node *np)
if (prop)
address = *prop;

/* FIXME: Add support for PCI reg properties */

/* FIXME: Add support for PCI reg properties. Right now, only
* reliable on macs
*/
if (address == 0)
return -EINVAL;

g_loc_X = 0;
g_loc_Y = 0;
g_max_loc_X = width / 8;
g_max_loc_Y = height / 16;
logicalDisplayBase = (unsigned char *)address;
dispDeviceBase = (unsigned char *)address;
dispDeviceRowBytes = pitch;
dispDeviceDepth = depth;
Expand All @@ -197,7 +205,7 @@ int btext_initialize(struct device_node *np)
return 0;
}

void __init init_boot_display(void)
int __init btext_find_display(int allow_nonstdout)
{
char *name;
struct device_node *np = NULL;
Expand All @@ -218,8 +226,8 @@ void __init init_boot_display(void)
}
if (np)
rc = btext_initialize(np);
if (rc == 0)
return;
if (rc == 0 || !allow_nonstdout)
return rc;

for (np = NULL; (np = of_find_node_by_type(np, "display"));) {
if (get_property(np, "linux,opened", NULL)) {
Expand All @@ -228,8 +236,9 @@ void __init init_boot_display(void)
printk("result: %d\n", rc);
}
if (rc == 0)
return;
break;
}
return rc;
}

/* Calc the base address of a given point (x,y) */
Expand Down Expand Up @@ -277,44 +286,83 @@ EXPORT_SYMBOL(btext_update_display);

void btext_clearscreen(void)
{
unsigned long *base = (unsigned long *)calc_base(0, 0);
unsigned int *base = (unsigned int *)calc_base(0, 0);
unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) *
(dispDeviceDepth >> 3)) >> 3;
(dispDeviceDepth >> 3)) >> 2;
int i,j;

for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1]); i++)
{
unsigned long *ptr = base;
unsigned int *ptr = base;
for(j=width; j; --j)
*(ptr++) = 0;
base += (dispDeviceRowBytes >> 3);
base += (dispDeviceRowBytes >> 2);
}
}

void btext_flushscreen(void)
{
unsigned int *base = (unsigned int *)calc_base(0, 0);
unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) *
(dispDeviceDepth >> 3)) >> 2;
int i,j;

for (i=0; i < (dispDeviceRect[3] - dispDeviceRect[1]); i++)
{
unsigned int *ptr = base;
for(j = width; j > 0; j -= 8) {
__asm__ __volatile__ ("dcbst 0,%0" :: "r" (ptr));
ptr += 8;
}
base += (dispDeviceRowBytes >> 2);
}
__asm__ __volatile__ ("sync" ::: "memory");
}

void btext_flushline(void)
{
unsigned int *base = (unsigned int *)calc_base(0, g_loc_Y << 4);
unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) *
(dispDeviceDepth >> 3)) >> 2;
int i,j;

for (i=0; i < 16; i++)
{
unsigned int *ptr = base;
for(j = width; j > 0; j -= 8) {
__asm__ __volatile__ ("dcbst 0,%0" :: "r" (ptr));
ptr += 8;
}
base += (dispDeviceRowBytes >> 2);
}
__asm__ __volatile__ ("sync" ::: "memory");
}


#ifndef NO_SCROLL
static void scrollscreen(void)
{
unsigned long *src = (unsigned long *)calc_base(0,16);
unsigned long *dst = (unsigned long *)calc_base(0,0);
unsigned int *src = (unsigned int *)calc_base(0,16);
unsigned int *dst = (unsigned int *)calc_base(0,0);
unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) *
(dispDeviceDepth >> 3)) >> 3;
(dispDeviceDepth >> 3)) >> 2;
int i,j;

for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1] - 16); i++)
{
unsigned long *src_ptr = src;
unsigned long *dst_ptr = dst;
unsigned int *src_ptr = src;
unsigned int *dst_ptr = dst;
for(j=width; j; --j)
*(dst_ptr++) = *(src_ptr++);
src += (dispDeviceRowBytes >> 3);
dst += (dispDeviceRowBytes >> 3);
src += (dispDeviceRowBytes >> 2);
dst += (dispDeviceRowBytes >> 2);
}
for (i=0; i<16; i++)
{
unsigned long *dst_ptr = dst;
unsigned int *dst_ptr = dst;
for(j=width; j; --j)
*(dst_ptr++) = 0;
dst += (dispDeviceRowBytes >> 3);
dst += (dispDeviceRowBytes >> 2);
}
}
#endif /* ndef NO_SCROLL */
Expand Down Expand Up @@ -377,6 +425,14 @@ void btext_drawstring(const char *c)
btext_drawchar(*c++);
}

void btext_drawtext(const char *c, unsigned int len)
{
if (!boot_text_mapped)
return;
while (len--)
btext_drawchar(*c++);
}

void btext_drawhex(unsigned long v)
{
char *hex_table = "0123456789abcdef";
Expand Down
29 changes: 29 additions & 0 deletions arch/powerpc/kernel/head_32.S
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ __after_mmu_off:
bl flush_tlbs

bl initial_bats
#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
bl setup_disp_bat
#endif

/*
* Call setup_cpu for CPU 0 and initialize 6xx Idle
Expand Down Expand Up @@ -1306,6 +1309,32 @@ initial_bats:
blr


#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
setup_disp_bat:
/*
* setup the display bat prepared for us in prom.c
*/
mflr r8
bl reloc_offset
mtlr r8
addis r8,r3,disp_BAT@ha
addi r8,r8,disp_BAT@l
cmpwi cr0,r8,0
beqlr
lwz r11,0(r8)
lwz r8,4(r8)
mfspr r9,SPRN_PVR
rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */
cmpwi 0,r9,1
beq 1f
mtspr SPRN_DBAT3L,r8
mtspr SPRN_DBAT3U,r11
blr
1: mtspr SPRN_IBAT3L,r8
mtspr SPRN_IBAT3U,r11
blr
#endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */

#ifdef CONFIG_8260
/* Jump into the system reset for the rom.
* We first disable the MMU, and then jump to the ROM reset address.
Expand Down
28 changes: 15 additions & 13 deletions arch/powerpc/kernel/setup_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include <asm/xmon.h>
#include <asm/time.h>
#include <asm/serial.h>
#include <asm/udbg.h>

#include "setup.h"

Expand Down Expand Up @@ -173,12 +174,23 @@ void __init platform_init(void)
*/
void __init machine_init(unsigned long dt_ptr, unsigned long phys)
{
/* If btext is enabled, we might have a BAT setup for early display,
* thus we do enable some very basic udbg output
*/
#ifdef CONFIG_BOOTX_TEXT
udbg_putc = btext_drawchar;
#endif

/* Do some early initialization based on the flat device tree */
early_init_devtree(__va(dt_ptr));

/* Check default command line */
#ifdef CONFIG_CMDLINE
strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
if (cmd_line[0] == 0)
strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
#endif /* CONFIG_CMDLINE */

/* Base init based on machine type */
platform_init();

#ifdef CONFIG_6xx
Expand Down Expand Up @@ -294,21 +306,11 @@ void __init setup_arch(char **cmdline_p)

smp_setup_cpu_maps();

#ifdef CONFIG_BOOTX_TEXT
init_boot_display();
#endif

#ifdef CONFIG_PPC_PMAC
/* This could be called "early setup arch", it must be done
* now because xmon need it
*/
if (_machine == _MACH_Pmac)
pmac_feature_init(); /* New cool way */
#endif

#ifdef CONFIG_XMON_DEFAULT
xmon_init(1);
#endif
/* Register early console */
register_early_udbg_console();

#if defined(CONFIG_KGDB)
if (ppc_md.kgdb_map_scc)
Expand Down
4 changes: 0 additions & 4 deletions arch/powerpc/kernel/setup_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -474,10 +474,6 @@ void __init setup_system(void)
*/
finish_device_tree();

#ifdef CONFIG_BOOTX_TEXT
init_boot_display();
#endif

/*
* Initialize xmon
*/
Expand Down
Loading

0 comments on commit 51d3082

Please sign in to comment.