[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>
This commit is contained in:
Родитель
463ce0e103
Коммит
51d3082fe6
|
@ -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/
|
||||||
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
|
||||||
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
|
||||||
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);
|
||||||
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};
|
||||||
|
|
||||||
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;
|
||||||
* 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)
|
||||||
}
|
}
|
||||||
#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,
|
||||||
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,
|
||||||
* 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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
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)
|
||||||
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);
|
||||||
|
|
||||||
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)
|
||||||
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:
|
||||||
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:
|
||||||
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 @@
|
||||||
#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)
|
||||||
*/
|
*/
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
*/
|
*/
|
||||||
finish_device_tree();
|
finish_device_tree();
|
||||||
|
|
||||||
#ifdef CONFIG_BOOTX_TEXT
|
|
||||||
init_boot_display();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize xmon
|
* Initialize xmon
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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)
|
||||||
#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)
|
||||||
/* 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 {
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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
|
||||||
# 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 @@ found:
|
||||||
*/
|
*/
|
||||||
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)
|
||||||
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)
|
printk(KERN_INFO "Found %s memory controller & host bridge,"
|
||||||
return;
|
" revision: %d\n", uninorth_u3 ? "U3" : "UniNorth",
|
||||||
|
uninorth_rev);
|
||||||
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);
|
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
|
||||||
{
|
{
|
||||||
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
|
||||||
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 @@
|
||||||
|
|
||||||
#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,
|
||||||
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)
|
||||||
}
|
}
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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 @@
|
||||||
#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)
|
||||||
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)
|
||||||
* 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)
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
#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 = {
|
||||||
.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
|
||||||
|
|
|
@ -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 */
|
||||||
|
"\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);
|
||||||
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)
|
||||||
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[] = {
|
||||||
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)
|
||||||
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)
|
||||||
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);
|
||||||
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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
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 @@
|
||||||
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
|
|
||||||
|
|
|
@ -1,441 +0,0 @@
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
/*
|
|
||||||
* 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)
|
||||||
/* 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
|
||||||
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)
|
||||||
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)
|
||||||
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 = {
|
||||||
#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
|
reg = (u32 *)get_property(vias, "reg", NULL);
|
||||||
{ int i;
|
if (reg == NULL) {
|
||||||
|
printk(KERN_ERR "via-cuda: No \"reg\" property !\n");
|
||||||
printk("find_via_cuda: node = %p, addrs =", vias->node);
|
goto fail;
|
||||||
for (i = 0; i < vias->n_addrs; ++i)
|
}
|
||||||
printk(" %x(%x)", vias->addrs[i].address, vias->addrs[i].size);
|
taddr = of_translate_address(vias, reg);
|
||||||
printk(", intrs =");
|
if (taddr == 0) {
|
||||||
for (i = 0; i < vias->n_intrs; ++i)
|
printk(KERN_ERR "via-cuda: Can't translate address !\n");
|
||||||
printk(" %x", vias->intrs[i].line);
|
goto fail;
|
||||||
printk("\n"); }
|
}
|
||||||
#endif
|
via = ioremap(taddr, 0x2000);
|
||||||
|
if (via == NULL) {
|
||||||
if (vias->n_addrs != 1 || vias->n_intrs != 1) {
|
printk(KERN_ERR "via-cuda: Can't map address !\n");
|
||||||
printk(KERN_ERR "via-cuda: expecting 1 address (%d) and 1 interrupt (%d)\n",
|
goto fail;
|
||||||
vias->n_addrs, vias->n_intrs);
|
|
||||||
if (vias->n_addrs < 1 || vias->n_intrs < 1)
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
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)
|
||||||
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;
|
||||||
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 = {
|
||||||
};
|
};
|
||||||
#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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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 @@ next:
|
||||||
}
|
}
|
||||||
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 @@ next:
|
||||||
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 @@
|
||||||
#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 @@
|
||||||
#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,
|
||||||
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];
|
||||||
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 {
|
||||||
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);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче