summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2005-11-23 17:57:25 +1100
committerPaul Mackerras <paulus@samba.org>2006-01-09 14:49:54 +1100
commit51d3082fe6e55aecfa17113dbe98077c749f724c (patch)
tree9a1e2355d5988d8cc1ca511d53c1bb24b0baa17f
parent463ce0e103f419f51b1769111e73fe8bb305d0ec (diff)
[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: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r--arch/powerpc/Kconfig2
-rw-r--r--arch/powerpc/kernel/Makefile7
-rw-r--r--arch/powerpc/kernel/btext.c130
-rw-r--r--arch/powerpc/kernel/head_32.S29
-rw-r--r--arch/powerpc/kernel/setup_32.c28
-rw-r--r--arch/powerpc/kernel/setup_64.c4
-rw-r--r--arch/powerpc/kernel/udbg.c8
-rw-r--r--arch/powerpc/kernel/udbg_16550.c4
-rw-r--r--arch/powerpc/mm/init_32.c5
-rw-r--r--arch/powerpc/platforms/powermac/Makefile1
-rw-r--r--arch/powerpc/platforms/powermac/feature.c68
-rw-r--r--arch/powerpc/platforms/powermac/low_i2c.c27
-rw-r--r--arch/powerpc/platforms/powermac/pic.c2
-rw-r--r--arch/powerpc/platforms/powermac/setup.c52
-rw-r--r--arch/powerpc/platforms/powermac/udbg_adb.c218
-rw-r--r--arch/powerpc/platforms/powermac/udbg_scc.c (renamed from arch/powerpc/kernel/udbg_scc.c)64
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c8
-rw-r--r--arch/powerpc/xmon/Makefile8
-rw-r--r--arch/powerpc/xmon/start.c (renamed from arch/powerpc/xmon/start_64.c)0
-rw-r--r--arch/powerpc/xmon/start_32.c441
-rw-r--r--arch/powerpc/xmon/start_8xx.c44
-rw-r--r--arch/ppc/kernel/setup.c3
-rw-r--r--drivers/i2c/busses/i2c-keywest.c25
-rw-r--r--drivers/macintosh/via-cuda.c48
-rw-r--r--drivers/macintosh/via-pmu.c87
-rw-r--r--include/asm-powerpc/btext.h19
-rw-r--r--include/asm-powerpc/udbg.h9
-rw-r--r--include/asm-ppc/btext.h2
-rw-r--r--include/asm-ppc/machdep.h4
29 files changed, 627 insertions, 720 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 39ca7b9da369..0e4617104f8c 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -50,7 +50,7 @@ config PPC
config EARLY_PRINTK
bool
- default y if PPC64
+ default y
config COMPAT
bool
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index bf3fd6f02249..89714929f444 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -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)
diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c
index bdfba92b2b38..893dd24a9f67 100644
--- a/arch/powerpc/kernel/btext.c
+++ b/arch/powerpc/kernel/btext.c
@@ -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,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;
@@ -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";
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index ccdf94731e30..fdd34dbd8797 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -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.
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 02baacf04366..79d434fc14d2 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -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
- 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
@@ -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)
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 0fc442ad1d26..65603e9af984 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -474,10 +474,6 @@ void __init setup_system(void)
*/
finish_device_tree();
-#ifdef CONFIG_BOOTX_TEXT
- init_boot_display();
-#endif
-
/*
* Initialize xmon
*/
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
index 2e372477d22a..cc2df5e61bb0 100644
--- a/arch/powerpc/kernel/udbg.c
+++ b/arch/powerpc/kernel/udbg.c
@@ -16,8 +16,8 @@
#include <linux/console.h>
#include <asm/processor.h>
-void (*udbg_putc)(unsigned char c);
-unsigned char (*udbg_getc)(void);
+void (*udbg_putc)(char c);
+char (*udbg_getc)(void);
int (*udbg_getc_poll)(void);
/* udbg library, used by xmon et al */
@@ -78,7 +78,7 @@ int udbg_read(char *buf, int buflen)
#define UDBG_BUFSIZE 256
void udbg_printf(const char *fmt, ...)
{
- unsigned char buf[UDBG_BUFSIZE];
+ char buf[UDBG_BUFSIZE];
va_list args;
va_start(args, fmt);
@@ -116,6 +116,8 @@ void __init disable_early_printk(void)
/* called by setup_system */
void register_early_udbg_console(void)
{
+ if (early_console_initialized)
+ return;
early_console_initialized = 1;
register_console(&udbg_console);
}
diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c
index 50fd376446c9..28a58da5592c 100644
--- a/arch/powerpc/kernel/udbg_16550.c
+++ b/arch/powerpc/kernel/udbg_16550.c
@@ -47,7 +47,7 @@ struct NS16550 {
static volatile struct NS16550 __iomem *udbg_comport;
-static void udbg_550_putc(unsigned char c)
+static void udbg_550_putc(char c)
{
if (udbg_comport) {
while ((in_8(&udbg_comport->lsr) & LSR_THRE) == 0)
@@ -69,7 +69,7 @@ static int udbg_550_getc_poll(void)
return -1;
}
-static unsigned char udbg_550_getc(void)
+static char udbg_550_getc(void)
{
if (udbg_comport) {
while ((in_8(&udbg_comport->lsr) & LSR_DR) == 0)
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index 7d4b8b5f0606..7d0d75c11848 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -188,6 +188,11 @@ void __init MMU_init(void)
if (ppc_md.progress)
ppc_md.progress("MMU:exit", 0x211);
+
+ /* From now on, btext is no longer BAT mapped if it was at all */
+#ifdef CONFIG_BOOTX_TEXT
+ btext_unmap();
+#endif
}
/* This is only called until mem_init is done. */
diff --git a/arch/powerpc/platforms/powermac/Makefile b/arch/powerpc/platforms/powermac/Makefile
index c9df44fcf571..3e5370eeb1b7 100644
--- a/arch/powerpc/platforms/powermac/Makefile
+++ b/arch/powerpc/platforms/powermac/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_NVRAM) += nvram.o
# ppc64 pmac doesn't define CONFIG_NVRAM but needs nvram stuff
obj-$(CONFIG_PPC64) += nvram.o
obj-$(CONFIG_SMP) += smp.o
+obj-$(CONFIG_PPC_MERGE) += udbg_scc.o udbg_adb.o
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c
index f6e22da2a5da..52a9d0c1b8b8 100644
--- a/arch/powerpc/platforms/powermac/feature.c
+++ b/arch/powerpc/platforms/powermac/feature.c
@@ -2607,6 +2607,8 @@ found:
*/
static void __init probe_uninorth(void)
{
+ u32 *addrp;
+ phys_addr_t address;
unsigned long actrl;
/* Locate core99 Uni-N */
@@ -2616,20 +2618,23 @@ static void __init probe_uninorth(void)
uninorth_node = of_find_node_by_name(NULL, "u3");
uninorth_u3 = 1;
}
- if (uninorth_node && uninorth_node->n_addrs > 0) {
- unsigned long address = uninorth_node->addrs[0].address;
- uninorth_base = ioremap(address, 0x40000);
- uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
- if (uninorth_u3)
- u3_ht = ioremap(address + U3_HT_CONFIG_BASE, 0x1000);
- } else
- uninorth_node = NULL;
-
- if (!uninorth_node)
+ if (uninorth_node == NULL)
return;
- printk(KERN_INFO "Found %s memory controller & host bridge, revision: %d\n",
- uninorth_u3 ? "U3" : "UniNorth", uninorth_rev);
+ addrp = (u32 *)get_property(uninorth_node, "reg", NULL);
+ if (addrp == NULL)
+ return;
+ address = of_translate_address(uninorth_node, addrp);
+ if (address == 0)
+ return;
+ uninorth_base = ioremap(address, 0x40000);
+ uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
+ if (uninorth_u3)
+ u3_ht = ioremap(address + U3_HT_CONFIG_BASE, 0x1000);
+
+ printk(KERN_INFO "Found %s memory controller & host bridge,"
+ " revision: %d\n", uninorth_u3 ? "U3" : "UniNorth",
+ uninorth_rev);
printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base);
/* Set the arbitrer QAck delay according to what Apple does
@@ -2653,18 +2658,17 @@ static void __init probe_one_macio(const char *name, const char *compat, int typ
{
struct device_node* node;
int i;
- volatile u32 __iomem * base;
- u32* revp;
+ volatile u32 __iomem *base;
+ u32 *addrp, *revp;
+ phys_addr_t addr;
+ u64 size;
- node = find_devices(name);
- if (!node || !node->n_addrs)
- return;
- if (compat)
- do {
- if (device_is_compatible(node, compat))
- break;
- node = node->next;
- } while (node);
+ for (node = NULL; (node = of_find_node_by_name(node, name)) != NULL;) {
+ if (!compat)
+ break;
+ if (device_is_compatible(node, compat))
+ break;
+ }
if (!node)
return;
for(i=0; i<MAX_MACIO_CHIPS; i++) {
@@ -2673,14 +2677,28 @@ static void __init probe_one_macio(const char *name, const char *compat, int typ
if (macio_chips[i].of_node == node)
return;
}
+
if (i >= MAX_MACIO_CHIPS) {
printk(KERN_ERR "pmac_feature: Please increase MAX_MACIO_CHIPS !\n");
printk(KERN_ERR "pmac_feature: %s skipped\n", node->full_name);
return;
}
- base = ioremap(node->addrs[0].address, node->addrs[0].size);
+ addrp = of_get_pci_address(node, 0, &size);
+ if (addrp == NULL) {
+ printk(KERN_ERR "pmac_feature: %s: can't find base !\n",
+ node->full_name);
+ return;
+ }
+ addr = of_translate_address(node, addrp);
+ if (addr == 0) {
+ printk(KERN_ERR "pmac_feature: %s, can't translate base !\n",
+ node->full_name);
+ return;
+ }
+ base = ioremap(addr, (unsigned long)size);
if (!base) {
- printk(KERN_ERR "pmac_feature: Can't map mac-io chip !\n");
+ printk(KERN_ERR "pmac_feature: %s, can't map mac-io chip !\n",
+ node->full_name);
return;
}
if (type == macio_keylargo) {
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index f3f39e8e337a..606e0ed13731 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -36,7 +36,7 @@
#ifdef DEBUG
#define DBG(x...) do {\
- printk(KERN_DEBUG "KW:" x); \
+ printk(KERN_DEBUG "low_i2c:" x); \
} while(0)
#else
#define DBG(x...)
@@ -342,7 +342,7 @@ static int keywest_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 subaddr,
static void keywest_low_i2c_add(struct device_node *np)
{
struct low_i2c_host *host = find_low_i2c_host(NULL);
- u32 *psteps, *prate, steps, aoffset = 0;
+ u32 *psteps, *prate, *addrp, steps;
struct device_node *parent;
if (host == NULL) {
@@ -352,6 +352,16 @@ static void keywest_low_i2c_add(struct device_node *np)
}
memset(host, 0, sizeof(*host));
+ /* Apple is kind enough to provide a valid AAPL,address property
+ * on all i2c keywest nodes so far ... we would have to fallback
+ * to macio parsing if that wasn't the case
+ */
+ addrp = (u32 *)get_property(np, "AAPL,address", NULL);
+ if (addrp == NULL) {
+ printk(KERN_ERR "low_i2c: Can't find address for %s\n",
+ np->full_name);
+ return;
+ }
init_MUTEX(&host->mutex);
host->np = of_node_get(np);
psteps = (u32 *)get_property(np, "AAPL,address-step", NULL);
@@ -360,12 +370,10 @@ static void keywest_low_i2c_add(struct device_node *np)
steps >>= 1;
parent = of_get_parent(np);
host->num_channels = 1;
- if (parent && parent->name[0] == 'u') {
+ if (parent && parent->name[0] == 'u')
host->num_channels = 2;
- aoffset = 3;
- }
/* Select interface rate */
- host->speed = KW_I2C_MODE_100KHZ;
+ host->speed = KW_I2C_MODE_25KHZ;
prate = (u32 *)get_property(np, "AAPL,i2c-rate", NULL);
if (prate) switch(*prate) {
case 100:
@@ -379,9 +387,12 @@ static void keywest_low_i2c_add(struct device_node *np)
break;
}
+ printk(KERN_INFO "low_i2c: Bus %s found at 0x%08x, %d channels,"
+ " speed = %d KHz\n",
+ np->full_name, *addrp, host->num_channels, prate ? *prate : 25);
+
host->mode = pmac_low_i2c_mode_std;
- host->base = ioremap(np->addrs[0].address + aoffset,
- np->addrs[0].size);
+ host->base = ioremap((*addrp), 0x1000);
host->func = keywest_low_i2c_func;
}
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index 90040c49494d..ff78eeac10f2 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -459,7 +459,7 @@ void __init pmac_pic_init(void)
mpic_setup_cascade(irqctrler2->intrs[0].line,
pmac_u3_cascade, mpic2);
}
-#if defined(CONFIG_XMON) && defined(CONFIG_PPC32)
+#ifdef CONFIG_XMON
{
struct device_node* pswitch;
int nmi_irq;
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 3b7a492d9b68..6ee620fe5195 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -77,6 +77,7 @@
#include <asm/pmc.h>
#include <asm/mpic.h>
#include <asm/lmb.h>
+#include <asm/udbg.h>
#include "pmac.h"
@@ -322,16 +323,6 @@ void __init pmac_setup_arch(void)
l2cr_init();
#endif /* CONFIG_PPC32 */
-#ifdef CONFIG_PPC64
- /* Probe motherboard chipset */
- /* this is done earlier in setup_arch for 32-bit */
- pmac_feature_init();
-
- /* We can NAP */
- powersave_nap = 1;
- printk(KERN_INFO "Using native/NAP idle loop\n");
-#endif
-
#ifdef CONFIG_KGDB
zs_kgdb_hook(0);
#endif
@@ -622,13 +613,26 @@ static void __init pmac_init_early(void)
* and call ioremap
*/
hpte_init_native();
+#endif
- /* Init SCC */
- if (strstr(cmd_line, "sccdbg")) {
- sccdbg = 1;
- udbg_init_scc(NULL);
+ /* Enable early btext debug if requested */
+ if (strstr(cmd_line, "btextdbg")) {
+ udbg_adb_init_early();
+ register_early_udbg_console();
}
+ /* Probe motherboard chipset */
+ pmac_feature_init();
+
+ /* We can NAP */
+ powersave_nap = 1;
+ printk(KERN_INFO "Using native/NAP idle loop\n");
+
+ /* Initialize debug stuff */
+ udbg_scc_init(!!strstr(cmd_line, "sccdbg"));
+ udbg_adb_init(!!strstr(cmd_line, "btextdbg"));
+
+#ifdef CONFIG_PPC64
/* Setup interrupt mapping options */
ppc64_interrupt_controller = IC_OPEN_PIC;
@@ -638,19 +642,8 @@ static void __init pmac_init_early(void)
static void __init pmac_progress(char *s, unsigned short hex)
{
-#ifdef CONFIG_PPC64
- if (sccdbg) {
- udbg_puts(s);
- udbg_puts("\n");
- return;
- }
-#endif
-#ifdef CONFIG_BOOTX_TEXT
- if (boot_text_mapped) {
- btext_drawstring(s);
- btext_drawchar('\n');
- }
-#endif /* CONFIG_BOOTX_TEXT */
+ udbg_puts(s);
+ udbg_puts("\n");
}
/*
@@ -735,7 +728,8 @@ static int __init pmac_probe(int platform)
}
#ifdef CONFIG_PPC64
-static int pmac_probe_mode(struct pci_bus *bus)
+/* Move that to pci.c */
+static int pmac_pci_probe_mode(struct pci_bus *bus)
{
struct device_node *node = bus->sysdata;
@@ -771,7 +765,7 @@ struct machdep_calls __initdata pmac_md = {
.check_legacy_ioport = pmac_check_legacy_ioport,
.progress = pmac_progress,
#ifdef CONFIG_PPC64
- .pci_probe_mode = pmac_probe_mode,
+ .pci_probe_mode = pmac_pci_probe_mode,
.idle_loop = native_idle,
.enable_pmcs = power4_enable_pmcs,
#ifdef CONFIG_KEXEC
diff --git a/arch/powerpc/platforms/powermac/udbg_adb.c b/arch/powerpc/platforms/powermac/udbg_adb.c
new file mode 100644
index 000000000000..e51de55b2d6e
--- /dev/null
+++ b/arch/powerpc/platforms/powermac/udbg_adb.c
@@ -0,0 +1,218 @@
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/bitops.h>
+#include <linux/ptrace.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <linux/cuda.h>
+#include <asm/machdep.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/xmon.h>
+#include <asm/prom.h>
+#include <asm/bootx.h>
+#include <asm/machdep.h>
+#include <asm/errno.h>
+#include <asm/pmac_feature.h>
+#include <asm/processor.h>
+#include <asm/delay.h>
+#include <asm/btext.h>
+#include <asm/time.h>
+#include <asm/udbg.h>
+
+/*
+ * This implementation is "special", it can "patch" the current
+ * udbg implementation and work on top of it. It must thus be
+ * initialized last
+ */
+
+static void (*udbg_adb_old_putc)(char c);
+static char (*udbg_adb_old_getc)(void);
+static int (*udbg_adb_old_getc_poll)(void);
+
+static enum {
+ input_adb_none,
+ input_adb_pmu,
+ input_adb_cuda,
+} input_type = input_adb_none;
+
+static int udbg_adb_use_btext;
+
+int xmon_wants_key, xmon_adb_keycode;
+
+static inline void udbg_adb_poll(void)
+{
+#ifdef CONFIG_ADB_PMU
+ if (input_type == input_adb_pmu)
+ pmu_poll_adb();
+#endif /* CONFIG_ADB_PMU */
+#ifdef CONFIG_ADB_CUDA
+ if (input_type == input_adb_cuda)
+ cuda_poll();
+#endif /* CONFIG_ADB_CUDA */
+}
+
+#ifdef CONFIG_BOOTX_TEXT
+static int xmon_adb_shiftstate;
+
+static unsigned char xmon_keytab[128] =
+ "asdfhgzxcv\000bqwer" /* 0x00 - 0x0f */
+ "yt123465=97-80]o" /* 0x10 - 0x1f */
+ "u[ip\rlj'k;\\,/nm." /* 0x20 - 0x2f */
+ "\t `\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */
+ "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
+ "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
+
+static unsigned char xmon_shift_keytab[128] =
+ "ASDFHGZXCV\000BQWER" /* 0x00 - 0x0f */
+ "YT!@#$^%+(&_*)}O" /* 0x10 - 0x1f */
+ "U{IP\rLJ\"K:|<?NM>" /* 0x20 - 0x2f */
+ "\t ~\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */