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

[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
...@@ -50,7 +50,7 @@ config PPC ...@@ -50,7 +50,7 @@ config PPC
config EARLY_PRINTK config EARLY_PRINTK
bool bool
default y if PPC64 default y
config COMPAT config COMPAT
bool bool
......
...@@ -18,7 +18,7 @@ obj-y += vdso32/ ...@@ -18,7 +18,7 @@ obj-y += vdso32/
obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \
signal_64.o ptrace32.o systbl.o \ signal_64.o ptrace32.o systbl.o \
paca.o ioctl32.o cpu_setup_power4.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_PPC64) += vdso64/
obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
obj-$(CONFIG_POWER4) += idle_power4.o obj-$(CONFIG_POWER4) += idle_power4.o
...@@ -46,7 +46,7 @@ extra-$(CONFIG_8xx) := head_8xx.o ...@@ -46,7 +46,7 @@ extra-$(CONFIG_8xx) := head_8xx.o
extra-y += vmlinux.lds extra-y += vmlinux.lds
obj-y += process.o init_task.o time.o \ 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_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_PPC64) += misc_64.o dma_64.o iommu.o
obj-$(CONFIG_PPC_OF) += prom_init.o obj-$(CONFIG_PPC_OF) += prom_init.o
...@@ -56,8 +56,7 @@ obj-$(CONFIG_6xx) += idle_6xx.o ...@@ -56,8 +56,7 @@ obj-$(CONFIG_6xx) += idle_6xx.o
obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_KPROBES) += kprobes.o
obj-$(CONFIG_PPC_MULTIPLATFORM) += legacy_serial.o obj-$(CONFIG_PPC_MULTIPLATFORM) += legacy_serial.o
obj64-$(CONFIG_PPC_MULTIPLATFORM) += udbg_16550.o obj-$(CONFIG_PPC_MULTIPLATFORM) += udbg_16550.o
obj64-$(CONFIG_PPC_PMAC) += udbg_scc.o
module-$(CONFIG_PPC64) += module_64.o module-$(CONFIG_PPC64) += module_64.o
obj-$(CONFIG_MODULES) += $(module-y) obj-$(CONFIG_MODULES) += $(module-y)
......
...@@ -31,15 +31,18 @@ static void draw_byte_32(unsigned char *bits, unsigned int *base, int rb); ...@@ -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_16(unsigned char *bits, unsigned int *base, int rb);
static void draw_byte_8(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; #define __force_data __attribute__((__section__(".data")))
static int g_loc_Y;
static int g_max_loc_X;
static int g_max_loc_Y;
static int dispDeviceRowBytes; static int g_loc_X __force_data;
static int dispDeviceDepth; static int g_loc_Y __force_data;
static int dispDeviceRect[4]; static int g_max_loc_X __force_data;
static unsigned char *dispDeviceBase, *logicalDisplayBase; 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}; unsigned long disp_BAT[2] __initdata = {0, 0};
...@@ -47,7 +50,7 @@ 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]; static unsigned char vga_font[cmapsz];
int boot_text_mapped; int boot_text_mapped __force_data = 0;
int force_printk_to_btext = 0; int force_printk_to_btext = 0;
#ifdef CONFIG_PPC32 #ifdef CONFIG_PPC32
...@@ -66,8 +69,7 @@ int force_printk_to_btext = 0; ...@@ -66,8 +69,7 @@ int force_printk_to_btext = 0;
* is really badly aligned, but I didn't encounter this case * is really badly aligned, but I didn't encounter this case
* yet. * yet.
*/ */
void __init void __init btext_prepare_BAT(void)
btext_prepare_BAT(void)
{ {
unsigned long vaddr = KERNELBASE + 0x10000000; unsigned long vaddr = KERNELBASE + 0x10000000;
unsigned long addr; unsigned long addr;
...@@ -95,11 +97,12 @@ btext_prepare_BAT(void) ...@@ -95,11 +97,12 @@ btext_prepare_BAT(void)
} }
#endif #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 void __init btext_setup_display(int width, int height, int depth, int pitch,
btext_setup_display(int width, int height, int depth, int pitch,
unsigned long address) unsigned long address)
{ {
g_loc_X = 0; g_loc_X = 0;
...@@ -116,6 +119,11 @@ btext_setup_display(int width, int height, int depth, int pitch, ...@@ -116,6 +119,11 @@ btext_setup_display(int width, int height, int depth, int pitch,
boot_text_mapped = 1; boot_text_mapped = 1;
} }
void __init btext_unmap(void)
{
boot_text_mapped = 0;
}
/* Here's a small text engine to use during early boot /* Here's a small text engine to use during early boot
* or for debugging purposes * or for debugging purposes
* *
...@@ -127,7 +135,7 @@ btext_setup_display(int width, int height, int depth, int pitch, ...@@ -127,7 +135,7 @@ btext_setup_display(int width, int height, int depth, int pitch,
* changes. * changes.
*/ */
void map_boot_text(void) static void map_boot_text(void)
{ {
unsigned long base, offset, size; unsigned long base, offset, size;
unsigned char *vbase; unsigned char *vbase;
...@@ -175,8 +183,9 @@ int btext_initialize(struct device_node *np) ...@@ -175,8 +183,9 @@ int btext_initialize(struct device_node *np)
if (prop) if (prop)
address = *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) if (address == 0)
return -EINVAL; return -EINVAL;
...@@ -184,7 +193,6 @@ int btext_initialize(struct device_node *np) ...@@ -184,7 +193,6 @@ int btext_initialize(struct device_node *np)
g_loc_Y = 0; g_loc_Y = 0;
g_max_loc_X = width / 8; g_max_loc_X = width / 8;
g_max_loc_Y = height / 16; g_max_loc_Y = height / 16;
logicalDisplayBase = (unsigned char *)address;
dispDeviceBase = (unsigned char *)address; dispDeviceBase = (unsigned char *)address;
dispDeviceRowBytes = pitch; dispDeviceRowBytes = pitch;
dispDeviceDepth = depth; dispDeviceDepth = depth;
...@@ -197,7 +205,7 @@ int btext_initialize(struct device_node *np) ...@@ -197,7 +205,7 @@ int btext_initialize(struct device_node *np)
return 0; return 0;
} }
void __init init_boot_display(void) int __init btext_find_display(int allow_nonstdout)
{ {
char *name; char *name;
struct device_node *np = NULL; struct device_node *np = NULL;
...@@ -218,8 +226,8 @@ void __init init_boot_display(void) ...@@ -218,8 +226,8 @@ void __init init_boot_display(void)
} }
if (np) if (np)
rc = btext_initialize(np); rc = btext_initialize(np);
if (rc == 0) if (rc == 0 || !allow_nonstdout)
return; return rc;
for (np = NULL; (np = of_find_node_by_type(np, "display"));) { for (np = NULL; (np = of_find_node_by_type(np, "display"));) {
if (get_property(np, "linux,opened", NULL)) { if (get_property(np, "linux,opened", NULL)) {
...@@ -228,8 +236,9 @@ void __init init_boot_display(void) ...@@ -228,8 +236,9 @@ void __init init_boot_display(void)
printk("result: %d\n", rc); printk("result: %d\n", rc);
} }
if (rc == 0) if (rc == 0)
return; break;
} }
return rc;
} }
/* Calc the base address of a given point (x,y) */ /* Calc the base address of a given point (x,y) */
...@@ -277,44 +286,83 @@ EXPORT_SYMBOL(btext_update_display); ...@@ -277,44 +286,83 @@ EXPORT_SYMBOL(btext_update_display);
void btext_clearscreen(void) 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]) * unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) *
(dispDeviceDepth >> 3)) >> 3; (dispDeviceDepth >> 3)) >> 2;
int i,j; int i,j;
for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1]); i++) for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1]); i++)
{ {
unsigned long *ptr = base; unsigned int *ptr = base;
for(j=width; j; --j) for(j=width; j; --j)
*(ptr++) = 0; *(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 #ifndef NO_SCROLL
static void scrollscreen(void) static void scrollscreen(void)
{ {
unsigned long *src = (unsigned long *)calc_base(0,16); unsigned int *src = (unsigned int *)calc_base(0,16);
unsigned long *dst = (unsigned long *)calc_base(0,0); unsigned int *dst = (unsigned int *)calc_base(0,0);
unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) * unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) *
(dispDeviceDepth >> 3)) >> 3; (dispDeviceDepth >> 3)) >> 2;
int i,j; int i,j;
for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1] - 16); i++) for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1] - 16); i++)
{ {
unsigned long *src_ptr = src; unsigned int *src_ptr = src;
unsigned long *dst_ptr = dst; unsigned int *dst_ptr = dst;
for(j=width; j; --j) for(j=width; j; --j)
*(dst_ptr++) = *(src_ptr++); *(dst_ptr++) = *(src_ptr++);
src += (dispDeviceRowBytes >> 3); src += (dispDeviceRowBytes >> 2);
dst += (dispDeviceRowBytes >> 3); dst += (dispDeviceRowBytes >> 2);
} }
for (i=0; i<16; i++) for (i=0; i<16; i++)
{ {
unsigned long *dst_ptr = dst; unsigned int *dst_ptr = dst;
for(j=width; j; --j) for(j=width; j; --j)
*(dst_ptr++) = 0; *(dst_ptr++) = 0;
dst += (dispDeviceRowBytes >> 3); dst += (dispDeviceRowBytes >> 2);
} }
} }
#endif /* ndef NO_SCROLL */ #endif /* ndef NO_SCROLL */
...@@ -377,6 +425,14 @@ void btext_drawstring(const char *c) ...@@ -377,6 +425,14 @@ void btext_drawstring(const char *c)
btext_drawchar(*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) void btext_drawhex(unsigned long v)
{ {
char *hex_table = "0123456789abcdef"; char *hex_table = "0123456789abcdef";
......
...@@ -153,6 +153,9 @@ __after_mmu_off: ...@@ -153,6 +153,9 @@ __after_mmu_off:
bl flush_tlbs bl flush_tlbs
bl initial_bats 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 * Call setup_cpu for CPU 0 and initialize 6xx Idle
...@@ -1306,6 +1309,32 @@ initial_bats: ...@@ -1306,6 +1309,32 @@ initial_bats:
blr 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 #ifdef CONFIG_8260
/* Jump into the system reset for the rom. /* Jump into the system reset for the rom.
* We first disable the MMU, and then jump to the ROM reset address. * We first disable the MMU, and then jump to the ROM reset address.
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include <asm/xmon.h> #include <asm/xmon.h>
#include <asm/time.h> #include <asm/time.h>
#include <asm/serial.h> #include <asm/serial.h>
#include <asm/udbg.h>
#include "setup.h" #include "setup.h"
...@@ -173,12 +174,23 @@ void __init platform_init(void) ...@@ -173,12 +174,23 @@ void __init platform_init(void)
*/ */
void __init machine_init(unsigned long dt_ptr, unsigned long phys) 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)); early_init_devtree(__va(dt_ptr));
/* Check default command line */
#ifdef CONFIG_CMDLINE #ifdef CONFIG_CMDLINE
if (cmd_line[0] == 0)
strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line)); strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
#endif /* CONFIG_CMDLINE */ #endif /* CONFIG_CMDLINE */
/* Base init based on machine type */
platform_init(); platform_init();
#ifdef CONFIG_6xx #ifdef CONFIG_6xx
...@@ -294,21 +306,11 @@ void __init setup_arch(char **cmdline_p) ...@@ -294,21 +306,11 @@ void __init setup_arch(char **cmdline_p)
smp_setup_cpu_maps(); 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 #ifdef CONFIG_XMON_DEFAULT
xmon_init(1); xmon_init(1);
#endif #endif
/* Register early console */
register_early_udbg_console();
#if defined(CONFIG_KGDB) #if defined(CONFIG_KGDB)
if (ppc_md.kgdb_map_scc) if (ppc_md.kgdb_map_scc)
......
...@@ -474,10 +474,6 @@ void __init setup_system(void) ...@@ -474,10 +474,6 @@ void __init setup_system(void)
*/ */
finish_device_tree(); finish_device_tree();
#ifdef CONFIG_BOOTX_TEXT
init_boot_display();
#endif
/* /*
* Initialize xmon * Initialize xmon
*/ */
......
...@@ -16,8 +16,8 @@ ...@@ -16,8 +16,8 @@
#include <linux/console.h> #include <linux/console.h>
#include <asm/processor.h> #include <asm/processor.h>
void (*udbg_putc)(unsigned char c); void (*udbg_putc)(char c);
unsigned char (*udbg_getc)(void); char (*udbg_getc)(void);
int (*udbg_getc_poll)(void); int (*udbg_getc_poll)(void);
/* udbg library, used by xmon et al */ /* udbg library, used by xmon et al */
...@@ -78,7 +78,7 @@ int udbg_read(char *buf, int buflen) ...@@ -78,7 +78,7 @@ int udbg_read(char *buf, int buflen)
#define UDBG_BUFSIZE 256 #define UDBG_BUFSIZE 256
void udbg_printf(const char *fmt, ...) void udbg_printf(const char *fmt, ...)
{ {
unsigned char buf[UDBG_BUFSIZE]; char buf[UDBG_BUFSIZE];
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
...@@ -116,6 +116,8 @@ void __init disable_early_printk(void) ...@@ -116,6 +116,8 @@ void __init disable_early_printk(void)
/* called by setup_system */ /* called by setup_system */
void register_early_udbg_console(void) void register_early_udbg_console(void)
{ {
if (early_console_initialized)
return;
early_console_initialized = 1; early_console_initialized = 1;
register_console(&udbg_console); register_console(&udbg_console);
} }
......
...@@ -47,7 +47,7 @@ struct NS16550 { ...@@ -47,7 +47,7 @@ struct NS16550 {
static volatile struct NS16550 __iomem *udbg_comport; 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) { if (udbg_comport) {
while ((in_8(&udbg_comport->lsr) & LSR_THRE) == 0) while ((in_8(&udbg_comport->lsr) & LSR_THRE) == 0)
...@@ -69,7 +69,7 @@ static int udbg_550_getc_poll(void) ...@@ -69,7 +69,7 @@ static int udbg_550_getc_poll(void)
return -1; return -1;
} }
static unsigned char udbg_550_getc(void) static char udbg_550_getc(void)
{ {
if (udbg_comport) { if (udbg_comport) {
while ((in_8(&udbg_comport->lsr) & LSR_DR) == 0) while ((in_8(&udbg_comport->lsr) & LSR_DR) == 0)
......
...@@ -188,6 +188,11 @@ void __init MMU_init(void) ...@@ -188,6 +188,11 @@ void __init MMU_init(void)
if (ppc_md.progress) if (ppc_md.progress)
ppc_md.progress("MMU:exit", 0x211); 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. */ /* This is only called until mem_init is done. */
......
...@@ -7,3 +7,4 @@ obj-$(CONFIG_NVRAM) += nvram.o ...@@ -7,3 +7,4 @@ obj-$(CONFIG_NVRAM) += nvram.o
# ppc64 pmac doesn't define CONFIG_NVRAM but needs nvram stuff # ppc64 pmac doesn't define CONFIG_NVRAM but needs nvram stuff
obj-$(CONFIG_PPC64) += nvram.o obj-$(CONFIG_PPC64) += nvram.o
obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_PPC_MERGE) += udbg_scc.o udbg_adb.o
...@@ -2607,6 +2607,8 @@ static int __init probe_motherboard(void) ...@@ -2607,6 +2607,8 @@ static int __init probe_motherboard(void)
*/ */
static void __init probe_uninorth(void) static void __init probe_uninorth(void)
{ {
u32 *addrp;
phys_addr_t address;
unsigned long actrl; unsigned long actrl;
/* Locate core99 Uni-N */ /* Locate core99 Uni-N */
...@@ -2616,20 +2618,23 @@ static void __init probe_uninorth(void) ...@@ -2616,20 +2618,23 @@ static void __init probe_uninorth(void)
uninorth_node = of_find_node_by_name(NULL, "u3"); uninorth_node = of_find_node_by_name(NULL, "u3");
uninorth_u3 = 1; uninorth_u3 = 1;
} }
if (uninorth_node && uninorth_node->n_addrs > 0) { if (uninorth_node == NULL)
unsigned long address = uninorth_node->addrs[0].address; return;
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_base = ioremap(address, 0x40000);
uninorth_rev = in_be32(UN_REG(UNI_N_VERSION)); uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
if (uninorth_u3) if (uninorth_u3)
u3_ht = ioremap(address + U3_HT_CONFIG_BASE, 0x1000); u3_ht = ioremap(address + U3_HT_CONFIG_BASE, 0x1000);
} else
uninorth_node = NULL;
if (!uninorth_node)
return;
printk(KERN_INFO "Found %s memory controller & host bridge, revision: %d\n", printk(KERN_INFO "Found %s memory controller & host bridge,"
uninorth_u3 ? "U3" : "UniNorth", uninorth_rev); " revision: %d\n", uninorth_u3 ? "U3" : "UniNorth",
uninorth_rev);
printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base); printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base);
/* Set the arbitrer QAck delay according to what Apple does /* 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 ...@@ -2653,18 +2658,17 @@ static void __init probe_one_macio(const char *name, const char *compat, int typ
{ {
struct device_node* node; struct device_node* node;
int i; int i;
volatile u32 __iomem * base; volatile u32 __iomem *base;
u32* revp; u32 *addrp, *revp;
phys_addr_t addr;
u64 size;
node = find_devices(name); for (node = NULL; (node = of_find_node_by_name(node, name)) != NULL;) {
if (!node || !node->n_addrs) if (!compat)
return; break;
if (compat)
do {
if (device_is_compatible(node, compat)) if (device_is_compatible(node, compat))
break; break;
node = node->next; }
} while (node);
if (!node) if (!node)
return; return;
for(i=0; i<MAX_MACIO_CHIPS; i++) { 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 ...@@ -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) if (macio_chips[i].of_node == node)
return; return;
} }
if (i >= MAX_MACIO_CHIPS) { if (i >= MAX_MACIO_CHIPS) {
printk(KERN_ERR "pmac_feature: Please increase MAX_MACIO_CHIPS !\n"); printk(KERN_ERR "pmac_feature: Please increase MAX_MACIO_CHIPS !\n");
printk(KERN_ERR "pmac_feature: %s skipped\n", node->full_name); printk(KERN_ERR "pmac_feature: %s skipped\n", node->full_name);
return; 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) { 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; return;
} }
if (type == macio_keylargo) { if (type == macio_keylargo) {
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
#ifdef DEBUG #ifdef DEBUG
#define DBG(x...) do {\ #define DBG(x...) do {\
printk(KERN_DEBUG "KW:" x); \ printk(KERN_DEBUG "low_i2c:" x); \
} while(0) } while(0)
#else #else
#define DBG(x...) #define DBG(x...)
...@@ -342,7 +342,7 @@ static int keywest_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 subaddr, ...@@ -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) static void keywest_low_i2c_add(struct device_node *np)
{ {
struct low_i2c_host *host = find_low_i2c_host(NULL); 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; struct device_node *parent;
if (host == NULL) { if (host == NULL) {
...@@ -352,6 +352,16 @@ static void keywest_low_i2c_add(struct device_node *np) ...@@ -352,6 +352,16 @@ static void keywest_low_i2c_add(struct device_node *np)
} }
memset(host, 0, sizeof(*host)); 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); init_MUTEX(&host->mutex);
host->np = of_node_get(np); host->np = of_node_get(np);
psteps = (u32 *)get_property(np, "AAPL,address-step", NULL); psteps = (u32 *)get_property(np, "AAPL,address-step", NULL);
...@@ -360,12 +370,10 @@ static void keywest_low_i2c_add(struct device_node *np) ...@@ -360,12 +370,10 @@ static void keywest_low_i2c_add(struct device_node *np)
steps >>= 1; steps >>= 1;
parent = of_get_parent(np); parent = of_get_parent(np);
host->num_channels = 1; host->num_channels = 1;
if (parent && parent->name[0] == 'u') { if (parent && parent->name[0] == 'u')
host->num_channels = 2; host->num_channels = 2;
aoffset = 3;
}
/* Select interface rate */ /* Select interface rate */
host->speed = KW_I2C_MODE_100KHZ; host->speed = KW_I2C_MODE_25KHZ;
prate = (u32 *)get_property(np, "AAPL,i2c-rate", NULL); prate = (u32 *)get_property(np, "AAPL,i2c-rate", NULL);
if (prate) switch(*prate) { if (prate) switch(*prate) {
case 100: case 100:
...@@ -379,9 +387,12 @@ static void keywest_low_i2c_add(struct device_node *np) ...@@ -379,9 +387,12 @@ static void keywest_low_i2c_add(struct device_node *np)
break; 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->mode = pmac_low_i2c_mode_std;
host->base = ioremap(np->addrs[0].address + aoffset, host->base = ioremap((*addrp), 0x1000);
np->addrs[0].size);
host->func = keywest_low_i2c_func; host->func = keywest_low_i2c_func;
} }
......
...@@ -459,7 +459,7 @@ void __init pmac_pic_init(void) ...@@ -459,7 +459,7 @@ void __init pmac_pic_init(void)
mpic_setup_cascade(irqctrler2->intrs[0].line, mpic_setup_cascade(irqctrler2->intrs[0].line,
pmac_u3_cascade, mpic2); pmac_u3_cascade, mpic2);
} }
#if defined(CONFIG_XMON) && defined(CONFIG_PPC32) #ifdef CONFIG_XMON
{ {
struct device_node* pswitch; struct device_node* pswitch;
int nmi_irq; int nmi_irq;
......
...@@ -77,6 +77,7 @@ ...@@ -77,6 +77,7 @@
#include <asm/pmc.h> #include <asm/pmc.h>
#include <asm/mpic.h> #include <asm/mpic.h>
#include <asm/lmb.h> #include <asm/lmb.h>
#include <asm/udbg.h>
#include "pmac.h" #include "pmac.h"
...@@ -322,16 +323,6 @@ void __init pmac_setup_arch(void) ...@@ -322,16 +323,6 @@ void __init pmac_setup_arch(void)
l2cr_init(); l2cr_init();
#endif /* CONFIG_PPC32 */ #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 #ifdef CONFIG_KGDB
zs_kgdb_hook(0); zs_kgdb_hook(0);
#endif #endif
...@@ -622,13 +613,26 @@ static void __init pmac_init_early(void) ...@@ -622,13 +613,26 @@ static void __init pmac_init_early(void)
* and call ioremap * and call ioremap
*/ */
hpte_init_native(); hpte_init_native();
#endif
/* Init SCC */ /* Enable early btext debug if requested */
if (strstr(cmd_line, "sccdbg")) { if (strstr(cmd_line, "btextdbg")) {
sccdbg = 1; udbg_adb_init_early();
udbg_init_scc(NULL); 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 */ /* Setup interrupt mapping options */
ppc64_interrupt_controller = IC_OPEN_PIC; ppc64_interrupt_controller = IC_OPEN_PIC;
...@@ -638,19 +642,8 @@ static void __init pmac_init_early(void) ...@@ -638,19 +642,8 @@ static void __init pmac_init_early(void)
static void __init pmac_progress(char *s, unsigned short hex) static void __init pmac_progress(char *s, unsigned short hex)
{ {
#ifdef CONFIG_PPC64
if (sccdbg) {
udbg_puts(s); udbg_puts(s);
udbg_puts("\n"); udbg_puts("\n");
return;
}
#endif
#ifdef CONFIG_BOOTX_TEXT
if (boot_text_mapped) {
btext_drawstring(s);
btext_drawchar('\n');
}
#endif /* CONFIG_BOOTX_TEXT */
} }
/* /*
...@@ -735,7 +728,8 @@ static int __init pmac_probe(int platform) ...@@ -735,7 +728,8 @@ static int __init pmac_probe(int platform)
} }
#ifdef CONFIG_PPC64 #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; struct device_node *node = bus->sysdata;
...@@ -771,7 +765,7 @@ struct machdep_calls __initdata pmac_md = { ...@@ -771,7 +765,7 @@ struct machdep_calls __initdata pmac_md = {
.check_legacy_ioport = pmac_check_legacy_ioport, .check_legacy_ioport = pmac_check_legacy_ioport,
.progress = pmac_progress, .progress = pmac_progress,
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
.pci_probe_mode = pmac_probe_mode, .pci_probe_mode = pmac_pci_probe_mode,
.idle_loop = native_idle, .idle_loop = native_idle,
.enable_pmcs = power4_enable_pmcs, .enable_pmcs = power4_enable_pmcs,
#ifdef CONFIG_KEXEC #ifdef CONFIG_KEXEC
......
#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 */
"\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
"\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
static char udbg_adb_local_getc(void)
{
int k, t, on;
xmon_wants_key = 1;
for (;;) {
xmon_adb_keycode = -1;
t = 0;
on = 0;
k = -1;
do {
if (--t < 0) {
on = 1 - on;
btext_drawchar(on? 0xdb: 0x20);
btext_drawchar('\b');
t = 200000;
}
udbg_adb_poll();
if (udbg_adb_old_getc_poll)
k = udbg_adb_old_getc_poll();
} while (k == -1 && xmon_adb_keycode == -1);
if (on)
btext_drawstring(" \b");
if (k != -1)
return k;
k = xmon_adb_keycode;
/* test for shift keys */
if ((k & 0x7f) == 0x38 || (k & 0x7f) == 0x7b) {
xmon_adb_shiftstate = (k & 0x80) == 0;
continue;
}
if (k >= 0x80)
continue; /* ignore up transitions */
k = (xmon_adb_shiftstate? xmon_shift_keytab: xmon_keytab)[k];
if (k != 0)
break;
}
xmon_wants_key = 0;
return k;
}
#endif /* CONFIG_BOOTX_TEXT */
static char udbg_adb_getc(void)
{
#ifdef CONFIG_BOOTX_TEXT
if (udbg_adb_use_btext && input_type != input_adb_none)
return udbg_adb_local_getc();
#endif
if (udbg_adb_old_getc)
return udbg_adb_old_getc();
return -1;
}
/* getc_poll() is not really used, unless you have the xmon-over modem
* hack that doesn't quite concern us here, thus we just poll the low level
* ADB driver to prevent it from timing out and call back the original poll
* routine.
*/
static int udbg_adb_getc_poll(void)
{
udbg_adb_poll();
if (udbg_adb_old_getc_poll)
return udbg_adb_old_getc_poll();
return -1;
}
static void udbg_adb_putc(char c)
{
#ifdef CONFIG_BOOTX_TEXT
if (udbg_adb_use_btext)
btext_drawchar(c);
#endif
if (udbg_adb_old_putc)
return udbg_adb_old_putc(c);
}
void udbg_adb_init_early(void)
{
#ifdef CONFIG_BOOTX_TEXT
if (btext_find_display(1) == 0) {
udbg_adb_use_btext = 1;
udbg_putc = udbg_adb_putc;
}
#endif
}
int udbg_adb_init(int force_btext)
{
struct device_node *np;
/* Capture existing callbacks */
udbg_adb_old_putc = udbg_putc;
udbg_adb_old_getc = udbg_getc;
udbg_adb_old_getc_poll = udbg_getc_poll;
/* Check if our early init was already called */
if (udbg_adb_old_putc == udbg_adb_putc ||
udbg_adb_old_putc == btext_drawchar)
udbg_adb_old_putc = NULL;
/* Set ours as output */
udbg_putc = udbg_adb_putc;
udbg_getc = udbg_adb_getc;
udbg_getc_poll = udbg_adb_getc_poll;
#ifdef CONFIG_BOOTX_TEXT
/* Check if we should use btext output */
if (btext_find_display(force_btext) == 0)
udbg_adb_use_btext = 1;
#endif
/* See if there is a keyboard in the device tree with a parent
* of type "adb". If not, we return a failure, but we keep the
* bext output set for now
*/
for (np = NULL; (np = of_find_node_by_name(np, "keyboard")) != NULL;) {
struct device_node *parent = of_get_parent(np);
int found = (parent && !strcmp(parent->type, "adb") == 0);
of_node_put(parent);
if (found)
break;
}
if (np == NULL)
return -ENODEV;
of_node_put(np);
#ifdef CONFIG_ADB_PMU
if (find_via_pmu())
input_type = input_adb_pmu;
#endif
#ifdef CONFIG_ADB_CUDA
if (find_via_cuda())
input_type = input_adb_cuda;
#endif
/* Same as above: nothing found, keep btext set for output */
if (input_type == input_adb_none)
return -ENODEV;
return 0;
}
...@@ -25,7 +25,7 @@ extern void real_writeb(u8 data, volatile u8 __iomem *addr); ...@@ -25,7 +25,7 @@ extern void real_writeb(u8 data, volatile u8 __iomem *addr);
static volatile u8 __iomem *sccc; static volatile u8 __iomem *sccc;
static volatile u8 __iomem *sccd; static volatile u8 __iomem *sccd;
static void udbg_scc_putc(unsigned char c) static void udbg_scc_putc(char c)
{ {
if (sccc) { if (sccc) {
while ((in_8(sccc) & SCC_TXRDY) == 0) while ((in_8(sccc) & SCC_TXRDY) == 0)
...@@ -47,7 +47,7 @@ static int udbg_scc_getc_poll(void) ...@@ -47,7 +47,7 @@ static int udbg_scc_getc_poll(void)
return -1; return -1;
} }
static unsigned char udbg_scc_getc(void) static char udbg_scc_getc(void)
{ {
if (sccc) { if (sccc) {
while ((in_8(sccc) & SCC_RXRDY) == 0) while ((in_8(sccc) & SCC_RXRDY) == 0)
...@@ -67,38 +67,59 @@ static unsigned char scc_inittab[] = { ...@@ -67,38 +67,59 @@ static unsigned char scc_inittab[] = {
3, 0xc1, /* rx enable, 8 bits */ 3, 0xc1, /* rx enable, 8 bits */
}; };
void udbg_init_scc(struct device_node *np) void udbg_scc_init(int force_scc)
{ {
u32 *reg; u32 *reg;
unsigned long addr; unsigned long addr;
struct device_node *stdout = NULL, *escc = NULL, *macio = NULL;
struct device_node *ch, *ch_def = NULL, *ch_a = NULL;
char *path;
int i, x; int i, x;
if (np == NULL) escc = of_find_node_by_name(NULL, "escc");
np = of_find_node_by_name(NULL, "escc"); if (escc == NULL)
if (np == NULL || np->parent == NULL) goto bail;
return; macio = of_get_parent(escc);
if (macio == NULL)
goto bail;
path = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
if (path != NULL)
stdout = of_find_node_by_path(path);
for (ch = NULL; (ch = of_get_next_child(escc, ch)) != NULL;) {
if (ch == stdout)
ch_def = of_node_get(ch);
if (strcmp(ch->name, "ch-a") == 0)
ch_a = of_node_get(ch);
}
if (ch_def == NULL && !force_scc)
goto bail;
ch = ch_def ? ch_def : ch_a;
udbg_printf("found SCC...\n");
/* Get address within mac-io ASIC */ /* Get address within mac-io ASIC */
reg = (u32 *)get_property(np, "reg", NULL); reg = (u32 *)get_property(escc, "reg", NULL);
if (reg == NULL) if (reg == NULL)
return; goto bail;
addr = reg[0]; addr = reg[0];
udbg_printf("local addr: %lx\n", addr);
/* Get address of mac-io PCI itself */ /* Get address of mac-io PCI itself */
reg = (u32 *)get_property(np->parent, "assigned-addresses", NULL); reg = (u32 *)get_property(macio, "assigned-addresses", NULL);
if (reg == NULL) if (reg == NULL)
return; goto bail;
addr += reg[2]; addr += reg[2];
udbg_printf("final addr: %lx\n", addr);
/* Lock the serial port */
pmac_call_feature(PMAC_FTR_SCC_ENABLE, ch,
PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);
/* Setup for 57600 8N1 */ /* Setup for 57600 8N1 */
if (ch == ch_a)
addr += 0x20; addr += 0x20;
sccc = (volatile u8 * __iomem) ioremap(addr & PAGE_MASK, PAGE_SIZE) ; sccc = (volatile u8 * __iomem) ioremap(addr & PAGE_MASK, PAGE_SIZE) ;
sccc += addr & ~PAGE_MASK; sccc += addr & ~PAGE_MASK;
sccd = sccc + 0x10; sccd = sccc + 0x10;
udbg_printf("ioremap result sccc: %p\n", sccc);
mb(); mb();
for (i = 20000; i != 0; --i) for (i = 20000; i != 0; --i)
...@@ -113,9 +134,17 @@ void udbg_init_scc(struct device_node *np) ...@@ -113,9 +134,17 @@ void udbg_init_scc(struct device_node *np)
udbg_getc_poll = udbg_scc_getc_poll; udbg_getc_poll = udbg_scc_getc_poll;
udbg_puts("Hello World !\n"); udbg_puts("Hello World !\n");
bail:
of_node_put(macio);
of_node_put(escc);
of_node_put(stdout);
of_node_put(ch_def);
of_node_put(ch_a);
} }
static void udbg_real_scc_putc(unsigned char c) #ifdef CONFIG_PPC64
static void udbg_real_scc_putc(char c)
{ {
while ((real_readb(sccc) & SCC_TXRDY) == 0) while ((real_readb(sccc) & SCC_TXRDY) == 0)
; ;
...@@ -133,3 +162,4 @@ void udbg_init_pmac_realmode(void) ...@@ -133,3 +162,4 @@ void udbg_init_pmac_realmode(void)
udbg_getc = NULL; udbg_getc = NULL;
udbg_getc_poll = NULL; udbg_getc_poll = NULL;
} }
#endif /* CONFIG_PPC64 */
...@@ -61,7 +61,7 @@ extern void pSeries_find_serial_port(void); ...@@ -61,7 +61,7 @@ extern void pSeries_find_serial_port(void);
int vtermno; /* virtual terminal# for udbg */ int vtermno; /* virtual terminal# for udbg */
#define __ALIGNED__ __attribute__((__aligned__(sizeof(long)))) #define __ALIGNED__ __attribute__((__aligned__(sizeof(long))))
static void udbg_hvsi_putc(unsigned char c) static void udbg_hvsi_putc(char c)
{ {
/* packet's seqno isn't used anyways */ /* packet's seqno isn't used anyways */
uint8_t packet[] __ALIGNED__ = { 0xff, 5, 0, 0, c }; uint8_t packet[] __ALIGNED__ = { 0xff, 5, 0, 0, c };
...@@ -112,7 +112,7 @@ static int udbg_hvsi_getc_poll(void) ...@@ -112,7 +112,7 @@ static int udbg_hvsi_getc_poll(void)
return ch; return ch;
} }
static unsigned char udbg_hvsi_getc(void) static char udbg_hvsi_getc(void)
{ {
int ch; int ch;
for (;;) { for (;;) {
...@@ -128,7 +128,7 @@ static unsigned char udbg_hvsi_getc(void) ...@@ -128,7 +128,7 @@ static unsigned char udbg_hvsi_getc(void)
} }
} }
static void udbg_putcLP(unsigned char c) static void udbg_putcLP(char c)
{ {
char buf[16]; char buf[16];
unsigned long rc; unsigned long rc;
...@@ -173,7 +173,7 @@ static int udbg_getc_pollLP(void) ...@@ -173,7 +173,7 @@ static int udbg_getc_pollLP(void)
return ch; return ch;
} }
static unsigned char udbg_getcLP(void) static char udbg_getcLP(void)
{ {
int ch; int ch;
for (;;) { for (;;) {
......
...@@ -3,9 +3,5 @@ ...@@ -3,9 +3,5 @@
ifdef CONFIG_PPC64 ifdef CONFIG_PPC64
EXTRA_CFLAGS += -mno-minimal-toc EXTRA_CFLAGS += -mno-minimal-toc
endif endif
obj-y += xmon.o ppc-dis.o ppc-opc.o setjmp.o start.o \
obj-$(CONFIG_8xx) += start_8xx.o nonstdio.o
obj-$(CONFIG_6xx) += start_32.o
obj-$(CONFIG_4xx) += start_32.o
obj-$(CONFIG_PPC64) += start_64.o
obj-y += xmon.o ppc-dis.o ppc-opc.o setjmp.o nonstdio.o
/*
* Copyright (C) 1996 Paul Mackerras.
*/
#include <linux/config.h>
#include <linux/string.h>
#include <asm/machdep.h>
#include <asm/io.h>
#include <asm/page.h>
#include <linux/adb.h>
#include <linux/pmu.h>
#include <linux/cuda.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/bitops.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 "nonstdio.h"
static volatile unsigned char __iomem *sccc, *sccd;
unsigned int TXRDY, RXRDY, DLAB;
static int use_serial;
static int use_screen;
static int via_modem;
static int xmon_use_sccb;
static struct device_node *channel_node;
void buf_access(void)
{
if (DLAB)
sccd[3] &= ~DLAB; /* reset DLAB */
}
extern int adb_init(void);
#ifdef CONFIG_PPC_CHRP
/*
* This looks in the "ranges" property for the primary PCI host bridge
* to find the physical address of the start of PCI/ISA I/O space.
* It is basically a cut-down version of pci_process_bridge_OF_ranges.
*/
static unsigned long chrp_find_phys_io_base(void)
{
struct device_node *node;
unsigned int *ranges;
unsigned long base = CHRP_ISA_IO_BASE;
int rlen = 0;
int np;
node = find_devices("isa");
if (node != NULL) {
node = node->parent;
if (node == NULL || node->type == NULL
|| strcmp(node->type, "pci") != 0)
node = NULL;
}
if (node == NULL)
node = find_devices("pci");
if (node == NULL)
return base;
ranges = (unsigned int *) get_property(node, "ranges", &rlen);
np = prom_n_addr_cells(node) + 5;
while ((rlen -= np * sizeof(unsigned int)) >= 0) {
if ((ranges[0] >> 24) == 1 && ranges[2] == 0) {
/* I/O space starting at 0, grab the phys base */
base = ranges[np - 3];
break;
}
ranges += np;
}
return base;
}
#endif /* CONFIG_PPC_CHRP */
void xmon_map_scc(void)
{
#ifdef CONFIG_PPC_MULTIPLATFORM
volatile unsigned char __iomem *base;
if (_machine == _MACH_Pmac) {
struct device_node *np;
unsigned long addr;
#ifdef CONFIG_BOOTX_TEXT
if (!use_screen && !use_serial
&& !machine_is_compatible("iMac")) {
/* see if there is a keyboard in the device tree
with a parent of type "adb" */
for (np = find_devices("keyboard"); np; np = np->next)
if (np->parent && np->parent->type
&& strcmp(np->parent->type, "adb") == 0)
break;
/* needs to be hacked if xmon_printk is to be used
from within find_via_pmu() */
#ifdef CONFIG_ADB_PMU
if (np != NULL && boot_text_mapped && find_via_pmu())
use_screen = 1;
#endif
#ifdef CONFIG_ADB_CUDA
if (np != NULL && boot_text_mapped && find_via_cuda())
use_screen = 1;
#endif
}
if (!use_screen && (np = find_devices("escc")) != NULL) {
/*
* look for the device node for the serial port
* we're using and see if it says it has a modem
*/
char *name = xmon_use_sccb? "ch-b": "ch-a";
char *slots;
int l;
np = np->child;
while (np != NULL && strcmp(np->name, name) != 0)
np = np->sibling;
if (np != NULL) {
/* XXX should parse this properly */
channel_node = np;
slots = get_property(np, "slot-names", &l);
if (slots != NULL && l >= 10
&& strcmp(slots+4, "Modem") == 0)
via_modem = 1;
}
}
btext_drawstring("xmon uses ");
if (use_screen)
btext_drawstring("screen and keyboard\n");
else {
if (via_modem)
btext_drawstring("modem on ");
btext_drawstring(xmon_use_sccb? "printer": "modem");
btext_drawstring(" port\n");
}
#endif /* CONFIG_BOOTX_TEXT */
#ifdef CHRP_ESCC
addr = 0xc1013020;
#else
addr = 0xf3013020;
#endif
TXRDY = 4;
RXRDY = 1;
np = find_devices("mac-io");
if (np && np->n_addrs)
addr = np->addrs[0].address + 0x13020;
base = (volatile unsigned char *) ioremap(addr & PAGE_MASK, PAGE_SIZE);
sccc = base + (addr & ~PAGE_MASK);
sccd = sccc + 0x10;
} else {
base = (volatile unsigned char *) isa_io_base;
#ifdef CONFIG_PPC_CHRP
if (_machine == _MACH_chrp)
base = (volatile unsigned char __iomem *)
ioremap(chrp_find_phys_io_base(), 0x1000);
#endif
sccc = base + 0x3fd;
sccd = base + 0x3f8;
if (xmon_use_sccb) {
sccc -= 0x100;
sccd -= 0x100;
}
TXRDY = 0x20;
RXRDY = 1;
DLAB = 0x80;
}
#elif defined(CONFIG_GEMINI)
/* should already be mapped by the kernel boot */
sccc = (volatile unsigned char __iomem *) 0xffeffb0d;
sccd = (volatile unsigned char __iomem *) 0xffeffb08;
TXRDY = 0x20;
RXRDY = 1;
DLAB = 0x80;
#elif defined(CONFIG_405GP)
sccc = (volatile unsigned char __iomem *)0xef600305;
sccd = (volatile unsigned char __iomem *)0xef600300;
TXRDY = 0x20;
RXRDY = 1;
DLAB = 0x80;
#endif /* platform */
}
static int scc_initialized = 0;
void xmon_init_scc(void);
extern void cuda_poll(void);
static inline void do_poll_adb(void)
{
#ifdef CONFIG_ADB_PMU
if (sys_ctrler == SYS_CTRLER_PMU)
pmu_poll_adb();
#endif /* CONFIG_ADB_PMU */
#ifdef CONFIG_ADB_CUDA
if (sys_ctrler == SYS_CTRLER_CUDA)
cuda_poll();
#endif /* CONFIG_ADB_CUDA */
}
int xmon_write(void *ptr, int nb)
{
char *p = ptr;
int i, c, ct;
#ifdef CONFIG_SMP
static unsigned long xmon_write_lock;
int lock_wait = 1000000;
int locked;
while ((locked = test_and_set_bit(0, &xmon_write_lock)) != 0)
if (--lock_wait == 0)
break;
#endif
#ifdef CONFIG_BOOTX_TEXT
if (use_screen) {
/* write it on the screen */
for (i = 0; i < nb; ++i)
btext_drawchar(*p++);
goto out;
}
#endif
if (!scc_initialized)
xmon_init_scc();
ct = 0;
for (i = 0; i < nb; ++i) {
while ((*sccc & TXRDY) == 0)
do_poll_adb();
c = p[i];
if (c == '\n' && !ct) {
c = '\r';
ct = 1;
--i;
} else {
ct = 0;
}
buf_access();
*sccd = c;
eieio();
}
out:
#ifdef CONFIG_SMP
if (!locked)
clear_bit(0, &xmon_write_lock);
#endif
return nb;
}
int xmon_wants_key;
int xmon_adb_keycode;
#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 */
"\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
"\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
static int xmon_get_adb_key(void)
{
int k, t, on;
xmon_wants_key = 1;
for (;;) {
xmon_adb_keycode = -1;
t = 0;
on = 0;
do {
if (--t < 0) {
on = 1 - on;
btext_drawchar(on? 0xdb: 0x20);
btext_drawchar('\b');
t = 200000;
}
do_poll_adb();
} while (xmon_adb_keycode == -1);
k = xmon_adb_keycode;
if (on)
btext_drawstring(" \b");
/* test for shift keys */
if ((k & 0x7f) == 0x38 || (k & 0x7f) == 0x7b) {
xmon_adb_shiftstate = (k & 0x80) == 0;
continue;
}
if (k >= 0x80)
continue; /* ignore up transitions */
k = (xmon_adb_shiftstate? xmon_shift_keytab: xmon_keytab)[k];
if (k != 0)
break;
}
xmon_wants_key = 0;
return k;
}
#endif /* CONFIG_BOOTX_TEXT */
int xmon_readchar(void)
{
#ifdef CONFIG_BOOTX_TEXT
if (use_screen)
return xmon_get_adb_key();
#endif
if (!scc_initialized)
xmon_init_scc();
while ((*sccc & RXRDY) == 0)
do_poll_adb();
buf_access();
return *sccd;
}
int xmon_read_poll(void)
{
if ((*sccc & RXRDY) == 0) {
do_poll_adb();
return -1;
}
buf_access();
return *sccd;
}
static unsigned char scc_inittab[] = {
13, 0, /* set baud rate divisor */
12, 1,
14, 1, /* baud rate gen enable, src=rtxc */
11, 0x50, /* clocks = br gen */
5, 0xea, /* tx 8 bits, assert DTR & RTS */
4, 0x46, /* x16 clock, 1 stop */
3, 0xc1, /* rx enable, 8 bits */
};
void xmon_init_scc(void)
{
if ( _machine == _MACH_chrp )
{
sccd[3] = 0x83; eieio(); /* LCR = 8N1 + DLAB */
sccd[0] = 12; eieio(); /* DLL = 9600 baud */
sccd[1] = 0; eieio();
sccd[2] = 0; eieio(); /* FCR = 0 */
sccd[3] = 3; eieio(); /* LCR = 8N1 */
sccd[1] = 0; eieio(); /* IER = 0 */
}
else if ( _machine == _MACH_Pmac )
{
int i, x;
unsigned long timeout;
if (channel_node != 0)
pmac_call_feature(
PMAC_FTR_SCC_ENABLE,
channel_node,
PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);
printk(KERN_INFO "Serial port locked ON by debugger !\n");
if (via_modem && channel_node != 0) {
unsigned int t0;
pmac_call_feature(
PMAC_FTR_MODEM_ENABLE,
channel_node, 0, 1);
printk(KERN_INFO "Modem powered up by debugger !\n");
t0 = get_tbl();
timeout = 3 * tb_ticks_per_sec;
if (timeout == 0)
/* assume 25MHz if tb_ticks_per_sec not set */
timeout = 75000000;
while (get_tbl() - t0 < timeout)
eieio();
}
/* use the B channel if requested */
if (xmon_use_sccb) {
sccc = (volatile unsigned char *)
((unsigned long)sccc & ~0x20);
sccd = sccc + 0x10;
}
for (i = 20000; i != 0; --i) {
x = *sccc; eieio();
}
*sccc = 9; eieio(); /* reset A or B side */
*sccc = ((unsigned long)sccc & 0x20)? 0x80: 0x40; eieio();
for (i = 0; i < sizeof(scc_inittab); ++i) {
*sccc = scc_inittab[i];
eieio();
}
}
scc_initialized = 1;
if (via_modem) {
for (;;) {
xmon_write("ATE1V1\r", 7);
if (xmon_expect("OK", 5)) {
xmon_write("ATA\r", 4);
if (xmon_expect("CONNECT", 40))
break;
}
xmon_write("+++", 3);
xmon_expect("OK", 3);
}
}
}
void xmon_enter(void)
{
#ifdef CONFIG_ADB_PMU
if (_machine == _MACH_Pmac) {
pmu_suspend();
}
#endif
}
void xmon_leave(void)
{
#ifdef CONFIG_ADB_PMU
if (_machine == _MACH_Pmac) {
pmu_resume();
}
#endif
}
/*
* Copyright (C) 1996 Paul Mackerras.
* Copyright (C) 2000 Dan Malek.
* Quick hack of Paul's code to make XMON work on 8xx processors. Lots
* of assumptions, like the SMC1 is used, it has been initialized by the
* loader at some point, and we can just stuff and suck bytes.
* We rely upon the 8xx uart driver to support us, as the interface
* changes between boot up and operational phases of the kernel.
*/
#include <linux/string.h>
#include <asm/machdep.h>
#include <asm/io.h>
#include <asm/page.h>
#include <linux/kernel.h>
#include <asm/8xx_immap.h>
#include <asm/mpc8xx.h>
#include <asm/commproc.h>
#include "nonstdio.h"
extern int xmon_8xx_write(char *str, int nb);
extern int xmon_8xx_read_poll(void);
extern int xmon_8xx_read_char(void);
void xmon_map_scc(void)
{
cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm);
}
void xmon_init_scc(void);
int xmon_write(void *ptr, int nb)
{
return(xmon_8xx_write(ptr, nb));
}
int xmon_readchar(void)
{
return xmon_8xx_read_char();
}
int xmon_read_poll(void)
{
return(xmon_8xx_read_poll());
}
...@@ -744,6 +744,9 @@ void __init setup_arch(char **cmdline_p) ...@@ -744,6 +744,9 @@ void __init setup_arch(char **cmdline_p)
/* so udelay does something sensible, assume <= 1000 bogomips */ /* so udelay does something sensible, assume <= 1000 bogomips */
loops_per_jiffy = 500000000 / HZ; loops_per_jiffy = 500000000 / HZ;
if (ppc_md.init_early)
ppc_md.init_early();
#ifdef CONFIG_PPC_MULTIPLATFORM #ifdef CONFIG_PPC_MULTIPLATFORM
/* This could be called "early setup arch", it must be done /* This could be called "early setup arch", it must be done
* now because xmon need it * now because xmon need it
......
...@@ -505,16 +505,23 @@ static int ...@@ -505,16 +505,23 @@ static int
create_iface(struct device_node *np, struct device *dev) create_iface(struct device_node *np, struct device *dev)
{ {
unsigned long steps; unsigned long steps;
unsigned bsteps, tsize, i, nchan, addroffset; unsigned bsteps, tsize, i, nchan;
struct keywest_iface* iface; struct keywest_iface* iface;
u32 *psteps, *prate; u32 *psteps, *prate, *addrp;
int rc; int rc;
if (np->n_intrs < 1 || np->n_addrs < 1) { if (np->n_intrs < 1) {
printk(KERN_ERR "%s: Missing interrupt or address !\n", printk(KERN_ERR "%s: Missing interrupt !\n",
np->full_name); np->full_name);
return -ENODEV; return -ENODEV;
} }
addrp = (u32 *)get_property(np, "AAPL,address", NULL);
if (addrp == NULL) {
printk(KERN_ERR "%s: Can't find address !\n",
np->full_name);
return -ENODEV;
}
if (pmac_low_i2c_lock(np)) if (pmac_low_i2c_lock(np))
return -ENODEV; return -ENODEV;
...@@ -525,13 +532,10 @@ create_iface(struct device_node *np, struct device *dev) ...@@ -525,13 +532,10 @@ create_iface(struct device_node *np, struct device *dev)
for (bsteps = 0; (steps & 0x01) == 0; bsteps++) for (bsteps = 0; (steps & 0x01) == 0; bsteps++)
steps >>= 1; steps >>= 1;
if (np->parent->name[0] == 'u') { if (np->parent->name[0] == 'u')
nchan = 2; nchan = 2;
addroffset = 3; else
} else {
addroffset = 0;
nchan = 1; nchan = 1;
}
tsize = sizeof(struct keywest_iface) + tsize = sizeof(struct keywest_iface) +
(sizeof(struct keywest_chan) + 4) * nchan; (sizeof(struct keywest_chan) + 4) * nchan;
...@@ -550,8 +554,7 @@ create_iface(struct device_node *np, struct device *dev) ...@@ -550,8 +554,7 @@ create_iface(struct device_node *np, struct device *dev)
iface->irq = np->intrs[0].line; iface->irq = np->intrs[0].line;
iface->channels = (struct keywest_chan *) iface->channels = (struct keywest_chan *)
(((unsigned long)(iface + 1) + 3UL) & ~3UL); (((unsigned long)(iface + 1) + 3UL) & ~3UL);
iface->base = ioremap(np->addrs[0].address + addroffset, iface->base = ioremap(*addrp, 0x1000);
np->addrs[0].size);
if (!iface->base) { if (!iface->base) {
printk(KERN_ERR "i2c-keywest: can't map inteface !\n"); printk(KERN_ERR "i2c-keywest: can't map inteface !\n");
kfree(iface); kfree(iface);
......
...@@ -127,39 +127,34 @@ struct adb_driver via_cuda_driver = { ...@@ -127,39 +127,34 @@ struct adb_driver via_cuda_driver = {
#endif /* CONFIG_ADB */ #endif /* CONFIG_ADB */
#ifdef CONFIG_PPC #ifdef CONFIG_PPC
int __init int __init find_via_cuda(void)
find_via_cuda(void)
{ {
int err;
struct adb_request req; struct adb_request req;
phys_addr_t taddr;
u32 *reg;
int err;
if (vias != 0) if (vias != 0)
return 1; return 1;
vias = find_devices("via-cuda"); vias = of_find_node_by_name(NULL, "via-cuda");
if (vias == 0) if (vias == 0)
return 0; return 0;
if (vias->next != 0)
printk(KERN_WARNING "Warning: only using 1st via-cuda\n");
#if 0
{ int i;
printk("find_via_cuda: node = %p, addrs =", vias->node);
for (i = 0; i < vias->n_addrs; ++i)
printk(" %x(%x)", vias->addrs[i].address, vias->addrs[i].size);
printk(", intrs =");
for (i = 0; i < vias->n_intrs; ++i)
printk(" %x", vias->intrs[i].line);
printk("\n"); }
#endif
if (vias->n_addrs != 1 || vias->n_intrs != 1) { reg = (u32 *)get_property(vias, "reg", NULL);
printk(KERN_ERR "via-cuda: expecting 1 address (%d) and 1 interrupt (%d)\n", if (reg == NULL) {
vias->n_addrs, vias->n_intrs); printk(KERN_ERR "via-cuda: No \"reg\" property !\n");
if (vias->n_addrs < 1 || vias->n_intrs < 1) goto fail;
return 0; }
taddr = of_translate_address(vias, reg);
if (taddr == 0) {
printk(KERN_ERR "via-cuda: Can't translate address !\n");
goto fail;
}
via = ioremap(taddr, 0x2000);
if (via == NULL) {
printk(KERN_ERR "via-cuda: Can't map address !\n");
goto fail;
} }
via = ioremap(vias->addrs->address, 0x2000);
cuda_state = idle; cuda_state = idle;
sys_ctrler = SYS_CTRLER_CUDA; sys_ctrler = SYS_CTRLER_CUDA;
...@@ -185,6 +180,11 @@ find_via_cuda(void) ...@@ -185,6 +180,11 @@ find_via_cuda(void)
cuda_poll(); cuda_poll();
return 1; return 1;
fail:
of_node_put(vias);
vias = NULL;
return 0;
} }
#endif /* CONFIG_PPC */ #endif /* CONFIG_PPC */
......
...@@ -147,6 +147,7 @@ static struct device_node *vias; ...@@ -147,6 +147,7 @@ static struct device_node *vias;
static int pmu_kind = PMU_UNKNOWN; static int pmu_kind = PMU_UNKNOWN;
static int pmu_fully_inited = 0; static int pmu_fully_inited = 0;
static int pmu_has_adb; static int pmu_has_adb;
static struct device_node *gpio_node;
static unsigned char __iomem *gpio_reg = NULL; static unsigned char __iomem *gpio_reg = NULL;
static int gpio_irq = -1; static int gpio_irq = -1;
static int gpio_irq_enabled = -1; static int gpio_irq_enabled = -1;
...@@ -295,22 +296,26 @@ static struct backlight_controller pmu_backlight_controller = { ...@@ -295,22 +296,26 @@ static struct backlight_controller pmu_backlight_controller = {
}; };
#endif /* CONFIG_PMAC_BACKLIGHT */ #endif /* CONFIG_PMAC_BACKLIGHT */
int int __init find_via_pmu(void)
find_via_pmu(void)
{ {
phys_addr_t taddr;
u32 *reg;
if (via != 0) if (via != 0)
return 1; return 1;
vias = find_devices("via-pmu"); vias = of_find_node_by_name(NULL, "via-pmu");
if (vias == 0) if (vias == NULL)
return 0; return 0;
if (vias->next != 0)
printk(KERN_WARNING "Warning: only using 1st via-pmu\n");
if (vias->n_addrs < 1 || vias->n_intrs < 1) { reg = (u32 *)get_property(vias, "reg", NULL);
printk(KERN_ERR "via-pmu: %d addresses, %d interrupts!\n", if (reg == NULL) {
vias->n_addrs, vias->n_intrs); printk(KERN_ERR "via-pmu: No \"reg\" property !\n");
if (vias->n_addrs < 1 || vias->n_intrs < 1) goto fail;
return 0; }
taddr = of_translate_address(vias, reg);
if (taddr == 0) {
printk(KERN_ERR "via-pmu: Can't translate address !\n");
goto fail;
} }
spin_lock_init(&pmu_lock); spin_lock_init(&pmu_lock);
...@@ -331,7 +336,8 @@ find_via_pmu(void) ...@@ -331,7 +336,8 @@ find_via_pmu(void)
pmu_kind = PMU_HEATHROW_BASED; pmu_kind = PMU_HEATHROW_BASED;
else if (device_is_compatible(vias->parent, "Keylargo") else if (device_is_compatible(vias->parent, "Keylargo")
|| device_is_compatible(vias->parent, "K2-Keylargo")) { || device_is_compatible(vias->parent, "K2-Keylargo")) {
struct device_node *gpio, *gpiop; struct device_node *gpiop;
phys_addr_t gaddr = 0;
pmu_kind = PMU_KEYLARGO_BASED; pmu_kind = PMU_KEYLARGO_BASED;
pmu_has_adb = (find_type_devices("adb") != NULL); pmu_has_adb = (find_type_devices("adb") != NULL);
...@@ -341,19 +347,24 @@ find_via_pmu(void) ...@@ -341,19 +347,24 @@ find_via_pmu(void)
PMU_INT_TICK | PMU_INT_TICK |
PMU_INT_ENVIRONMENT; PMU_INT_ENVIRONMENT;
gpiop = find_devices("gpio"); gpiop = of_find_node_by_name(NULL, "gpio");
if (gpiop && gpiop->n_addrs) { if (gpiop) {
gpio_reg = ioremap(gpiop->addrs->address, 0x10); reg = (u32 *)get_property(gpiop, "reg", NULL);
gpio = find_devices("extint-gpio1"); if (reg)
if (gpio == NULL) gaddr = of_translate_address(gpiop, reg);
gpio = find_devices("pmu-interrupt"); if (gaddr != 0)
if (gpio && gpio->parent == gpiop && gpio->n_intrs) gpio_reg = ioremap(gaddr, 0x10);
gpio_irq = gpio->intrs[0].line;
} }
if (gpio_reg == NULL)
printk(KERN_ERR "via-pmu: Can't find GPIO reg !\n");
} else } else
pmu_kind = PMU_UNKNOWN; pmu_kind = PMU_UNKNOWN;
via = ioremap(vias->addrs->address, 0x2000); via = ioremap(taddr, 0x2000);
if (via == NULL) {
printk(KERN_ERR "via-pmu: Can't map address !\n");
goto fail;
}
out_8(&via[IER], IER_CLR | 0x7f); /* disable all intrs */ out_8(&via[IER], IER_CLR | 0x7f); /* disable all intrs */
out_8(&via[IFR], 0x7f); /* clear IFR */ out_8(&via[IFR], 0x7f); /* clear IFR */
...@@ -371,17 +382,19 @@ find_via_pmu(void) ...@@ -371,17 +382,19 @@ find_via_pmu(void)
sys_ctrler = SYS_CTRLER_PMU; sys_ctrler = SYS_CTRLER_PMU;
return 1; return 1;
fail:
of_node_put(vias);
vias = NULL;
return 0;
} }
#ifdef CONFIG_ADB #ifdef CONFIG_ADB
static int static int pmu_probe(void)
pmu_probe(void)
{ {
return vias == NULL? -ENODEV: 0; return vias == NULL? -ENODEV: 0;
} }
static int __init static int __init pmu_init(void)
pmu_init(void)
{ {
if (vias == NULL) if (vias == NULL)
return -ENODEV; return -ENODEV;
...@@ -405,7 +418,7 @@ static int __init via_pmu_start(void) ...@@ -405,7 +418,7 @@ static int __init via_pmu_start(void)
bright_req_2.complete = 1; bright_req_2.complete = 1;
batt_req.complete = 1; batt_req.complete = 1;
#if defined(CONFIG_PPC32) && !defined(CONFIG_PPC_MERGE) #ifndef CONFIG_PPC_MERGE
if (pmu_kind == PMU_KEYLARGO_BASED) if (pmu_kind == PMU_KEYLARGO_BASED)
openpic_set_irq_priority(vias->intrs[0].line, openpic_set_irq_priority(vias->intrs[0].line,
OPENPIC_PRIORITY_DEFAULT + 1); OPENPIC_PRIORITY_DEFAULT + 1);
...@@ -418,11 +431,23 @@ static int __init via_pmu_start(void) ...@@ -418,11 +431,23 @@ static int __init via_pmu_start(void)
return -EAGAIN; return -EAGAIN;
} }
if (pmu_kind == PMU_KEYLARGO_BASED && gpio_irq != -1) { if (pmu_kind == PMU_KEYLARGO_BASED) {
if (request_irq(gpio_irq, gpio1_interrupt, 0, "GPIO1 ADB", (void *)0)) gpio_node = of_find_node_by_name(NULL, "extint-gpio1");
printk(KERN_ERR "pmu: can't get irq %d (GPIO1)\n", gpio_irq); if (gpio_node == NULL)
gpio_node = of_find_node_by_name(NULL,
"pmu-interrupt");
if (gpio_node && gpio_node->n_intrs > 0)
gpio_irq = gpio_node->intrs[0].line;
if (gpio_irq != -1) {
if (request_irq(gpio_irq, gpio1_interrupt, 0,
"GPIO1 ADB", (void *)0))
printk(KERN_ERR "pmu: can't get irq %d"
" (GPIO1)\n", gpio_irq);
else
gpio_irq_enabled = 1; gpio_irq_enabled = 1;
} }
}
/* Enable interrupts */ /* Enable interrupts */
out_8(&via[IER], IER_SET | SR_INT | CB1_INT); out_8(&via[IER], IER_SET | SR_INT | CB1_INT);
...@@ -1371,7 +1396,6 @@ pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs) ...@@ -1371,7 +1396,6 @@ pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs)
} }
pmu_done(req); pmu_done(req);
} else { } else {
#if defined(CONFIG_XMON) && !defined(CONFIG_PPC64)
if (len == 4 && data[1] == 0x2c) { if (len == 4 && data[1] == 0x2c) {
extern int xmon_wants_key, xmon_adb_keycode; extern int xmon_wants_key, xmon_adb_keycode;
if (xmon_wants_key) { if (xmon_wants_key) {
...@@ -1379,7 +1403,6 @@ pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs) ...@@ -1379,7 +1403,6 @@ pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs)
return; return;
} }
} }
#endif /* defined(CONFIG_XMON) && !defined(CONFIG_PPC64) */
#ifdef CONFIG_ADB #ifdef CONFIG_ADB
/* /*
* XXX On the [23]400 the PMU gives us an up * XXX On the [23]400 the PMU gives us an up
......
...@@ -7,21 +7,22 @@ ...@@ -7,21 +7,22 @@
#define __PPC_BTEXT_H #define __PPC_BTEXT_H
#ifdef __KERNEL__ #ifdef __KERNEL__
extern void btext_clearscreen(void); extern int btext_find_display(int allow_nonstdout);
extern void btext_flushscreen(void);
extern int boot_text_mapped;
extern int btext_initialize(struct device_node *np);
extern void map_boot_text(void);
extern void init_boot_display(void);
extern void btext_update_display(unsigned long phys, int width, int height, extern void btext_update_display(unsigned long phys, int width, int height,
int depth, int pitch); int depth, int pitch);
extern void btext_setup_display(int width, int height, int depth, int pitch,
unsigned long address);
extern void btext_prepare_BAT(void);
extern void btext_unmap(void);
extern void btext_drawchar(char c); extern void btext_drawchar(char c);
extern void btext_drawstring(const char *str); extern void btext_drawstring(const char *str);
extern void btext_drawhex(unsigned long v); extern void btext_drawhex(unsigned long v);
extern void btext_drawtext(const char *c, unsigned int len);
extern void btext_clearscreen(void);
extern void btext_flushscreen(void);
extern void btext_flushline(void);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* __PPC_BTEXT_H */ #endif /* __PPC_BTEXT_H */
...@@ -13,8 +13,8 @@ ...@@ -13,8 +13,8 @@
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/init.h> #include <linux/init.h>
extern void (*udbg_putc)(unsigned char c); extern void (*udbg_putc)(char c);
extern unsigned char (*udbg_getc)(void); extern char (*udbg_getc)(void);
extern int (*udbg_getc_poll)(void); extern int (*udbg_getc_poll)(void);
extern void udbg_puts(const char *s); extern void udbg_puts(const char *s);
...@@ -30,5 +30,8 @@ extern unsigned int udbg_probe_uart_speed(void __iomem *comport, ...@@ -30,5 +30,8 @@ extern unsigned int udbg_probe_uart_speed(void __iomem *comport,
unsigned int clock); unsigned int clock);
struct device_node; struct device_node;
extern void udbg_init_scc(struct device_node *np); extern void udbg_scc_init(int force_scc);
extern int udbg_adb_init(int force_btext);
extern void udbg_adb_init_early(void);
#endif /* _ASM_POWERPC_UDBG_H */ #endif /* _ASM_POWERPC_UDBG_H */
...@@ -17,7 +17,7 @@ extern unsigned long disp_BAT[2]; ...@@ -17,7 +17,7 @@ extern unsigned long disp_BAT[2];
extern boot_infos_t disp_bi; extern boot_infos_t disp_bi;
extern int boot_text_mapped; extern int boot_text_mapped;
extern void init_boot_display(void); extern void btext_init(boot_infos_t *bi);
extern void btext_welcome(void); extern void btext_welcome(void);
extern void btext_prepare_BAT(void); extern void btext_prepare_BAT(void);
extern void btext_setup_display(int width, int height, int depth, int pitch, extern void btext_setup_display(int width, int height, int depth, int pitch,
......
...@@ -35,8 +35,10 @@ struct machdep_calls { ...@@ -35,8 +35,10 @@ struct machdep_calls {
int (*get_irq)(struct pt_regs *); int (*get_irq)(struct pt_regs *);
/* A general init function, called by ppc_init in init/main.c. /* A general init function, called by ppc_init in init/main.c.
May be NULL. */ May be NULL. DEPRECATED ! */
void (*init)(void); void (*init)(void);
/* For compatibility with merged platforms */
void (*init_early)(void);
void (*restart)(char *cmd); void (*restart)(char *cmd);
void (*power_off)(void); void (*power_off)(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment