Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 51d3082f authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by Paul Mackerras
Browse files

[PATCH] powerpc: Unify udbg (#2)



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: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 463ce0e1
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ config PPC

config EARLY_PRINTK
	bool
	default y if PPC64
	default y

config COMPAT
	bool
+3 −4
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -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)

+93 −37
Original line number Diff line number Diff line
@@ -31,15 +31,18 @@ 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};

@@ -47,7 +50,7 @@ unsigned long disp_BAT[2] __initdata = {0, 0};

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
@@ -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;
@@ -95,11 +97,12 @@ 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,
void __init btext_setup_display(int width, int height, int depth, int pitch,
				unsigned long address)
{
	g_loc_X = 0;
@@ -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
 *
@@ -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;
@@ -175,8 +183,9 @@ 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;

@@ -184,7 +193,6 @@ int btext_initialize(struct device_node *np)
	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;
@@ -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; 
@@ -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)) {
@@ -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) */
@@ -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 */
@@ -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";
+29 −0
Original line number Diff line number Diff line
@@ -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
@@ -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.
+15 −13
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
#include <asm/xmon.h>
#include <asm/time.h>
#include <asm/serial.h>
#include <asm/udbg.h>

#include "setup.h"

@@ -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
	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
@@ -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)
Loading