ppc64: Add support for PowerMacs in the OF client interface code (prom.c)

Also move some of the init cruft into separate function to make
things slightly more readable. We sill need to significantly
cleanup that file, but that will come later...

Properly export the OF device-tree accessors to modules
parent 81eda1c7
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/delay.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/rtas.h> #include <asm/rtas.h>
#include <asm/lmb.h> #include <asm/lmb.h>
...@@ -48,6 +49,7 @@ ...@@ -48,6 +49,7 @@
#include <asm/pci_dma.h> #include <asm/pci_dma.h>
#include <asm/bootinfo.h> #include <asm/bootinfo.h>
#include <asm/ppcdebug.h> #include <asm/ppcdebug.h>
#include <asm/btext.h>
#include <asm/sections.h> #include <asm/sections.h>
#include "open_pic.h" #include "open_pic.h"
...@@ -115,24 +117,15 @@ typedef unsigned long interpret_func(struct device_node *, unsigned long, ...@@ -115,24 +117,15 @@ typedef unsigned long interpret_func(struct device_node *, unsigned long,
static interpret_func interpret_pci_props; static interpret_func interpret_pci_props;
static interpret_func interpret_isa_props; static interpret_func interpret_isa_props;
static interpret_func interpret_root_props; static interpret_func interpret_root_props;
static interpret_func interpret_dbdma_props;
static interpret_func interpret_macio_props;
#ifndef FB_MAX /* avoid pulling in all of the fb stuff */ #ifndef FB_MAX /* avoid pulling in all of the fb stuff */
#define FB_MAX 8 #define FB_MAX 8
#endif #endif
/* prom structure */
struct prom_t prom = { struct prom_t prom;
0, /* entry */
0, /* chosen */
0, /* cpu */
0, /* stdout */
0, /* disp_node */
{0,0,0,{0},NULL}, /* args */
0, /* version */
32, /* encode_phys_size */
0 /* bi_rec pointer */
};
char *prom_display_paths[FB_MAX] __initdata = { 0, }; char *prom_display_paths[FB_MAX] __initdata = { 0, };
unsigned int prom_num_displays = 0; unsigned int prom_num_displays = 0;
...@@ -140,7 +133,6 @@ char *of_stdout_device = 0; ...@@ -140,7 +133,6 @@ char *of_stdout_device = 0;
extern struct rtas_t rtas; extern struct rtas_t rtas;
extern unsigned long klimit; extern unsigned long klimit;
extern unsigned long embedded_sysmap_end;
extern struct lmb lmb; extern struct lmb lmb;
#define MAX_PHB 16 * 3 // 16 Towers * 3 PHBs/tower #define MAX_PHB 16 * 3 // 16 Towers * 3 PHBs/tower
...@@ -343,6 +335,11 @@ prom_initialize_naca(unsigned long mem) ...@@ -343,6 +335,11 @@ prom_initialize_naca(unsigned long mem)
RELOC("d-cache-size"), RELOC("d-cache-size"),
&size, sizeof(size)); &size, sizeof(size));
if (_systemcfg->platform == PLATFORM_POWERMAC)
call_prom(RELOC("getprop"), 4, 1, node,
RELOC("d-cache-block-size"),
&lsize, sizeof(lsize));
else
call_prom(RELOC("getprop"), 4, 1, node, call_prom(RELOC("getprop"), 4, 1, node,
RELOC("d-cache-line-size"), RELOC("d-cache-line-size"),
&lsize, sizeof(lsize)); &lsize, sizeof(lsize));
...@@ -356,6 +353,11 @@ prom_initialize_naca(unsigned long mem) ...@@ -356,6 +353,11 @@ prom_initialize_naca(unsigned long mem)
RELOC("i-cache-size"), RELOC("i-cache-size"),
&size, sizeof(size)); &size, sizeof(size));
if (_systemcfg->platform == PLATFORM_POWERMAC)
call_prom(RELOC("getprop"), 4, 1, node,
RELOC("i-cache-block-size"),
&lsize, sizeof(lsize));
else
call_prom(RELOC("getprop"), 4, 1, node, call_prom(RELOC("getprop"), 4, 1, node,
RELOC("i-cache-line-size"), RELOC("i-cache-line-size"),
&lsize, sizeof(lsize)); &lsize, sizeof(lsize));
...@@ -379,6 +381,8 @@ prom_initialize_naca(unsigned long mem) ...@@ -379,6 +381,8 @@ prom_initialize_naca(unsigned long mem)
struct isa_reg_property reg; struct isa_reg_property reg;
union pci_range ranges; union pci_range ranges;
if (_systemcfg->platform == PLATFORM_POWERMAC)
continue;
type[0] = 0; type[0] = 0;
call_prom(RELOC("getprop"), 4, 1, node, call_prom(RELOC("getprop"), 4, 1, node,
RELOC("ibm,aix-loc"), type, sizeof(type)); RELOC("ibm,aix-loc"), type, sizeof(type));
...@@ -409,25 +413,28 @@ prom_initialize_naca(unsigned long mem) ...@@ -409,25 +413,28 @@ prom_initialize_naca(unsigned long mem)
} }
} }
if (_systemcfg->platform == PLATFORM_POWERMAC)
_naca->interrupt_controller = IC_OPEN_PIC;
else {
_naca->interrupt_controller = IC_INVALID; _naca->interrupt_controller = IC_INVALID;
for (node = 0; prom_next_node(&node); ) { for (node = 0; prom_next_node(&node); ) {
type[0] = 0; type[0] = 0;
call_prom(RELOC("getprop"), 4, 1, node, RELOC("name"), call_prom(RELOC("getprop"), 4, 1, node, RELOC("name"),
type, sizeof(type)); type, sizeof(type));
if (strcmp(type, RELOC("interrupt-controller"))) { if (strcmp(type, RELOC("interrupt-controller")))
continue; continue;
}
call_prom(RELOC("getprop"), 4, 1, node, RELOC("compatible"), call_prom(RELOC("getprop"), 4, 1, node, RELOC("compatible"),
type, sizeof(type)); type, sizeof(type));
if (strstr(type, RELOC("open-pic"))) { if (strstr(type, RELOC("open-pic")))
_naca->interrupt_controller = IC_OPEN_PIC; _naca->interrupt_controller = IC_OPEN_PIC;
} else if (strstr(type, RELOC("ppc-xicp"))) { else if (strstr(type, RELOC("ppc-xicp")))
_naca->interrupt_controller = IC_PPC_XIC; _naca->interrupt_controller = IC_PPC_XIC;
} else { else
prom_print(RELOC("prom: failed to recognize interrupt-controller\n")); prom_print(RELOC("prom: failed to recognize"
} " interrupt-controller\n"));
break; break;
} }
}
if (_naca->interrupt_controller == IC_INVALID) { if (_naca->interrupt_controller == IC_INVALID) {
prom_print(RELOC("prom: failed to find interrupt-controller\n")); prom_print(RELOC("prom: failed to find interrupt-controller\n"));
...@@ -440,7 +447,8 @@ prom_initialize_naca(unsigned long mem) ...@@ -440,7 +447,8 @@ prom_initialize_naca(unsigned long mem)
_systemcfg->physicalMemorySize = lmb_phys_mem_size(); _systemcfg->physicalMemorySize = lmb_phys_mem_size();
if (_systemcfg->platform == PLATFORM_PSERIES) { if (_systemcfg->platform == PLATFORM_PSERIES ||
_systemcfg->platform == PLATFORM_POWERMAC) {
unsigned long rnd_mem_size, pteg_count; unsigned long rnd_mem_size, pteg_count;
/* round mem_size up to next power of 2 */ /* round mem_size up to next power of 2 */
...@@ -519,12 +527,19 @@ prom_initialize_lmb(unsigned long mem) ...@@ -519,12 +527,19 @@ prom_initialize_lmb(unsigned long mem)
char type[64]; char type[64];
unsigned long i, offset = reloc_offset(); unsigned long i, offset = reloc_offset();
struct prom_t *_prom = PTRRELOC(&prom); struct prom_t *_prom = PTRRELOC(&prom);
struct systemcfg *_systemcfg = RELOC(systemcfg);
union lmb_reg_property reg; union lmb_reg_property reg;
unsigned long lmb_base, lmb_size; unsigned long lmb_base, lmb_size;
unsigned long num_regs, bytes_per_reg = (_prom->encode_phys_size*2)/8; unsigned long num_regs, bytes_per_reg = (_prom->encode_phys_size*2)/8;
lmb_init(); lmb_init();
/* XXX Quick HACK. Proper fix is to drop those structures and properly use
* #address-cells. PowerMac has #size-cell set to 1 and #address-cells to 2
*/
if (_systemcfg->platform == PLATFORM_POWERMAC)
bytes_per_reg = 12;
for (node = 0; prom_next_node(&node); ) { for (node = 0; prom_next_node(&node); ) {
type[0] = 0; type[0] = 0;
call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"), call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"),
...@@ -537,7 +552,15 @@ prom_initialize_lmb(unsigned long mem) ...@@ -537,7 +552,15 @@ prom_initialize_lmb(unsigned long mem)
&reg, sizeof(reg)) / bytes_per_reg; &reg, sizeof(reg)) / bytes_per_reg;
for (i=0; i < num_regs ;i++) { for (i=0; i < num_regs ;i++) {
if (_prom->encode_phys_size == 32) { if (_systemcfg->platform == PLATFORM_POWERMAC) {
lmb_base = ((unsigned long)reg.addrPM[i].address_hi) << 32;
lmb_base |= (unsigned long)reg.addrPM[i].address_lo;
lmb_size = reg.addrPM[i].size;
if (lmb_base > 0x80000000ull) {
prom_print(RELOC("Skipping memory above 2Gb for now, not yet supported\n"));
continue;
}
} else if (_prom->encode_phys_size == 32) {
lmb_base = reg.addr32[i].address; lmb_base = reg.addr32[i].address;
lmb_size = reg.addr32[i].size; lmb_size = reg.addr32[i].size;
} else { } else {
...@@ -922,19 +945,47 @@ prom_hold_cpus(unsigned long mem) ...@@ -922,19 +945,47 @@ prom_hold_cpus(unsigned long mem)
struct paca_struct *_xPaca = PTRRELOC(&paca[0]); struct paca_struct *_xPaca = PTRRELOC(&paca[0]);
struct prom_t *_prom = PTRRELOC(&prom); struct prom_t *_prom = PTRRELOC(&prom);
/* On pmac, we just fill out the various global bitmasks and
* arrays indicating our CPUs are here, they are actually started
* later on from pmac_smp
*/
if (_systemcfg->platform == PLATFORM_POWERMAC) {
for (node = 0; prom_next_node(&node); ) {
type[0] = 0;
call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"),
type, sizeof(type));
if (strcmp(type, RELOC("cpu")) != 0)
continue;
reg = -1;
call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"),
&reg, sizeof(reg));
_xPaca[cpuid].xHwProcNum = reg;
#ifdef CONFIG_SMP
cpu_set(cpuid, RELOC(cpu_available_map));
cpu_set(cpuid, RELOC(cpu_possible_map));
cpu_set(cpuid, RELOC(cpu_present_at_boot));
if (reg == 0)
cpu_set(cpuid, RELOC(cpu_online_map));
#endif /* CONFIG_SMP */
cpuid++;
}
return;
}
/* Initially, we must have one active CPU. */ /* Initially, we must have one active CPU. */
_systemcfg->processorCount = 1; _systemcfg->processorCount = 1;
#ifdef DEBUG_PROM #ifdef DEBUG_PROM
prom_print(RELOC("prom_hold_cpus: start...\n")); prom_print(RELOC("prom_hold_cpus: start...\n"));
prom_print(RELOC(" 1) spinloop = 0x")); prom_print(RELOC(" 1) spinloop = 0x"));
prom_print_hex(spinloop); prom_print_hex((unsigned long)spinloop);
prom_print_nl(); prom_print_nl();
prom_print(RELOC(" 1) *spinloop = 0x")); prom_print(RELOC(" 1) *spinloop = 0x"));
prom_print_hex(*spinloop); prom_print_hex(*spinloop);
prom_print_nl(); prom_print_nl();
prom_print(RELOC(" 1) acknowledge = 0x")); prom_print(RELOC(" 1) acknowledge = 0x"));
prom_print_hex(acknowledge); prom_print_hex((unsigned long)acknowledge);
prom_print_nl(); prom_print_nl();
prom_print(RELOC(" 1) *acknowledge = 0x")); prom_print(RELOC(" 1) *acknowledge = 0x"));
prom_print_hex(*acknowledge); prom_print_hex(*acknowledge);
...@@ -1212,6 +1263,144 @@ smt_setup(void) ...@@ -1212,6 +1263,144 @@ smt_setup(void)
_naca->smt_state = my_smt_enabled; _naca->smt_state = my_smt_enabled;
} }
#ifdef CONFIG_BOOTX_TEXT
/* This function will enable the early boot text when doing OF booting. This
* way, xmon output should work too
*/
static void __init setup_disp_fake_bi(ihandle dp)
{
int width = 640, height = 480, depth = 8, pitch;
unsigned address;
struct pci_reg_property addrs[8];
int i, naddrs;
char name[64];
unsigned long offset = reloc_offset();
char *getprop = RELOC("getprop");
prom_print(RELOC("Initializing fake screen: "));
memset(name, 0, sizeof(name));
call_prom(getprop, 4, 1, dp, RELOC("name"), name, sizeof(name));
name[sizeof(name)-1] = 0;
prom_print(name);
prom_print(RELOC("\n"));
call_prom(getprop, 4, 1, dp, RELOC("width"), &width, sizeof(width));
call_prom(getprop, 4, 1, dp, RELOC("height"), &height, sizeof(height));
call_prom(getprop, 4, 1, dp, RELOC("depth"), &depth, sizeof(depth));
pitch = width * ((depth + 7) / 8);
call_prom(getprop, 4, 1, dp, RELOC("linebytes"),
&pitch, sizeof(pitch));
if (pitch == 1)
pitch = 0x1000; /* for strange IBM display */
address = 0;
prom_print(RELOC("width "));
prom_print_hex(width);
prom_print(RELOC(" height "));
prom_print_hex(height);
prom_print(RELOC(" depth "));
prom_print_hex(depth);
prom_print(RELOC(" linebytes "));
prom_print_hex(pitch);
prom_print(RELOC("\n"));
call_prom(getprop, 4, 1, dp, RELOC("address"),
&address, sizeof(address));
if (address == 0) {
/* look for an assigned address with a size of >= 1MB */
naddrs = (int) call_prom(getprop, 4, 1, dp,
RELOC("assigned-addresses"),
addrs, sizeof(addrs));
naddrs /= sizeof(struct pci_reg_property);
for (i = 0; i < naddrs; ++i) {
if (addrs[i].size_lo >= (1 << 20)) {
address = addrs[i].addr.a_lo;
/* use the BE aperture if possible */
if (addrs[i].size_lo >= (16 << 20))
address += (8 << 20);
break;
}
}
if (address == 0) {
prom_print(RELOC("Failed to get address of frame buffer\n"));
return;
}
}
btext_setup_display(width, height, depth, pitch, address);
prom_print(RELOC("Addr of fb: "));
prom_print_hex(address);
prom_print_nl();
RELOC(boot_text_mapped) = 0;
}
#endif /* CONFIG_BOOTX_TEXT */
static void __init prom_init_client_services(unsigned long pp)
{
unsigned long offset = reloc_offset();
struct prom_t *_prom = PTRRELOC(&prom);
/* Get a handle to the prom entry point before anything else */
_prom->entry = pp;
/* Init default value for phys size */
_prom->encode_phys_size = 32;
/* get a handle for the stdout device */
_prom->chosen = (ihandle)call_prom(RELOC("finddevice"), 1, 1,
RELOC("/chosen"));
if ((long)_prom->chosen <= 0)
prom_panic(RELOC("cannot find chosen")); /* msg won't be printed :( */
/* get device tree root */
_prom->root = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/"));
if ((long)_prom->root <= 0)
prom_panic(RELOC("cannot find device tree root")); /* msg won't be printed :( */
}
static void __init prom_init_stdout(void)
{
unsigned long offset = reloc_offset();
struct prom_t *_prom = PTRRELOC(&prom);
u32 val;
if ((long)call_prom(RELOC("getprop"), 4, 1, _prom->chosen,
RELOC("stdout"), &val,
sizeof(val)) <= 0)
prom_panic(RELOC("cannot find stdout"));
_prom->stdout = (ihandle)(unsigned long)val;
}
static int __init prom_find_machine_type(void)
{
unsigned long offset = reloc_offset();
struct prom_t *_prom = PTRRELOC(&prom);
char compat[256];
int len, i = 0;
len = (int)(long)call_prom(RELOC("getprop"), 4, 1, _prom->root,
RELOC("compatible"),
compat, sizeof(compat)-1);
if (len > 0) {
compat[len] = 0;
while (i < len) {
char *p = &compat[i];
int sl = strlen(p);
if (sl == 0)
break;
if (strstr(p, RELOC("Power Macintosh")) ||
strstr(p, RELOC("MacRISC4")))
return PLATFORM_POWERMAC;
i += sl + 1;
}
}
/* Default to pSeries */
return PLATFORM_PSERIES;
}
/* /*
* We enter here early on, when the Open Firmware prom is still * We enter here early on, when the Open Firmware prom is still
* handling exceptions and the MMU hash table for us. * handling exceptions and the MMU hash table for us.
...@@ -1222,7 +1411,7 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp, ...@@ -1222,7 +1411,7 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
unsigned long r6, unsigned long r7) unsigned long r6, unsigned long r7)
{ {
unsigned long mem; unsigned long mem;
ihandle prom_root, prom_cpu; ihandle prom_cpu;
phandle cpu_pkg; phandle cpu_pkg;
unsigned long offset = reloc_offset(); unsigned long offset = reloc_offset();
long l; long l;
...@@ -1241,39 +1430,27 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp, ...@@ -1241,39 +1430,27 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
RELOC(systemcfg) = _systemcfg = (struct systemcfg *)(SYSTEMCFG_VIRT_ADDR - offset); RELOC(systemcfg) = _systemcfg = (struct systemcfg *)(SYSTEMCFG_VIRT_ADDR - offset);
RELOC(naca) = (struct naca_struct *)(NACA_VIRT_ADDR - offset); RELOC(naca) = (struct naca_struct *)(NACA_VIRT_ADDR - offset);
/* Default machine type. */ /* Init interface to Open Firmware and pickup bi-recs */
_systemcfg->platform = PLATFORM_PSERIES; prom_init_client_services(pp);
#if 0 /* Init prom stdout device */
/* Reset klimit to take into account the embedded system map */ prom_init_stdout();
if (RELOC(embedded_sysmap_end))
RELOC(klimit) = __va(PAGE_ALIGN(RELOC(embedded_sysmap_end)));
#endif
/* Get a handle to the prom entry point before anything else */ /* check out if we have bi_recs */
_prom->entry = pp;
_prom->bi_recs = prom_bi_rec_verify((struct bi_record *)r6); _prom->bi_recs = prom_bi_rec_verify((struct bi_record *)r6);
if ( _prom->bi_recs != NULL ) { if ( _prom->bi_recs != NULL )
RELOC(klimit) = PTRUNRELOC((unsigned long)_prom->bi_recs + _prom->bi_recs->data[1]); RELOC(klimit) = PTRUNRELOC((unsigned long)_prom->bi_recs +
} _prom->bi_recs->data[1]);
/* First get a handle for the stdout device */ /* Default machine type. */
_prom->chosen = (ihandle)call_prom(RELOC("finddevice"), 1, 1, _systemcfg->platform = prom_find_machine_type();
RELOC("/chosen"));
if ((long)_prom->chosen <= 0)
prom_panic(RELOC("cannot find chosen")); /* msg won't be printed :( */
/* On pSeries, copy the CPU hold code */ /* On pSeries, copy the CPU hold code */
if (_systemcfg->platform == PLATFORM_PSERIES) if (_systemcfg->platform == PLATFORM_PSERIES)
copy_and_flush(0, KERNELBASE - offset, 0x100, 0); copy_and_flush(0, KERNELBASE - offset, 0x100, 0);
if ((long)call_prom(RELOC("getprop"), 4, 1, _prom->chosen,
RELOC("stdout"), &getprop_rval,
sizeof(getprop_rval)) <= 0)
prom_panic(RELOC("cannot find stdout"));
_prom->stdout = (ihandle)(unsigned long)getprop_rval;
/* Start storing things at klimit */
mem = RELOC(klimit) - offset; mem = RELOC(klimit) - offset;
/* Get the full OF pathname of the stdout device */ /* Get the full OF pathname of the stdout device */
...@@ -1284,13 +1461,10 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp, ...@@ -1284,13 +1461,10 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
mem += strlen(p) + 1; mem += strlen(p) + 1;
getprop_rval = 1; getprop_rval = 1;
prom_root = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/"));
if (prom_root != (ihandle)-1) {
call_prom(RELOC("getprop"), 4, 1, call_prom(RELOC("getprop"), 4, 1,
prom_root, RELOC("#size-cells"), _prom->root, RELOC("#size-cells"),
&getprop_rval, sizeof(getprop_rval)); &getprop_rval, sizeof(getprop_rval));
} _prom->encode_phys_size = (getprop_rval == 1) ? 32 : 64;
_prom->encode_phys_size = (getprop_rval==1) ? 32 : 64;
/* Determine which cpu is actually running right _now_ */ /* Determine which cpu is actually running right _now_ */
if ((long)call_prom(RELOC("getprop"), 4, 1, _prom->chosen, if ((long)call_prom(RELOC("getprop"), 4, 1, _prom->chosen,
...@@ -1329,12 +1503,23 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp, ...@@ -1329,12 +1503,23 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
mem = DOUBLEWORD_ALIGN(mem + strlen(d) + 1); mem = DOUBLEWORD_ALIGN(mem + strlen(d) + 1);
} }
RELOC(cmd_line[0]) = 0;
if ((long)_prom->chosen > 0) {
call_prom(RELOC("getprop"), 4, 1, _prom->chosen,
RELOC("bootargs"), p, sizeof(cmd_line));
if (p != NULL && p[0] != 0)
strncpy(RELOC(cmd_line), p, sizeof(cmd_line));
}
RELOC(cmd_line[sizeof(cmd_line) - 1]) = 0;
mem = prom_initialize_lmb(mem); mem = prom_initialize_lmb(mem);
mem = prom_bi_rec_reserve(mem); mem = prom_bi_rec_reserve(mem);
mem = check_display(mem); mem = check_display(mem);
if (_systemcfg->platform != PLATFORM_POWERMAC)
prom_instantiate_rtas(); prom_instantiate_rtas();
/* Initialize some system info into the Naca early... */ /* Initialize some system info into the Naca early... */
...@@ -1360,6 +1545,13 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp, ...@@ -1360,6 +1545,13 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
if (_systemcfg->platform == PLATFORM_PSERIES) if (_systemcfg->platform == PLATFORM_PSERIES)
prom_initialize_tce_table(); prom_initialize_tce_table();
#ifdef CONFIG_BOOTX_TEXT
if(_prom->disp_node) {
prom_print(RELOC("Setting up bi display...\n"));
setup_disp_fake_bi(_prom->disp_node);
}
#endif /* CONFIG_BOOTX_TEXT */
prom_print(RELOC("Calling quiesce ...\n")); prom_print(RELOC("Calling quiesce ...\n"));
call_prom(RELOC("quiesce"), 0, 0); call_prom(RELOC("quiesce"), 0, 0);
phys = KERNELBASE - offset; phys = KERNELBASE - offset;
...@@ -1476,6 +1668,10 @@ check_display(unsigned long mem) ...@@ -1476,6 +1668,10 @@ check_display(unsigned long mem)
RELOC(prom_display_paths[i]) = PTRUNRELOC(path); RELOC(prom_display_paths[i]) = PTRUNRELOC(path);
if (RELOC(prom_num_displays) >= FB_MAX) if (RELOC(prom_num_displays) >= FB_MAX)
break; break;
/* XXX Temporary workaround: only open the first display so we don't
* lose debug output
*/
break;
} }
return DOUBLEWORD_ALIGN(mem); return DOUBLEWORD_ALIGN(mem);
} }
...@@ -1689,9 +1885,9 @@ finish_node(struct device_node *np, unsigned long mem_start, ...@@ -1689,9 +1885,9 @@ finish_node(struct device_node *np, unsigned long mem_start,
np->type = get_property(np, "device_type", 0); np->type = get_property(np, "device_type", 0);
/* get the device addresses and interrupts */ /* get the device addresses and interrupts */
if (ifunc != NULL) { if (ifunc != NULL)
mem_start = ifunc(np, mem_start, naddrc, nsizec); mem_start = ifunc(np, mem_start, naddrc, nsizec);
}
mem_start = finish_node_interrupts(np, mem_start); mem_start = finish_node_interrupts(np, mem_start);
/* Look for #address-cells and #size-cells properties. */ /* Look for #address-cells and #size-cells properties. */
...@@ -1705,7 +1901,6 @@ finish_node(struct device_node *np, unsigned long mem_start, ...@@ -1705,7 +1901,6 @@ finish_node(struct device_node *np, unsigned long mem_start,
/* the f50 sets the name to 'display' and 'compatible' to what we /* the f50 sets the name to 'display' and 'compatible' to what we
* expect for the name -- Cort * expect for the name -- Cort
*/ */
ifunc = NULL;
if (!strcmp(np->name, "display")) if (!strcmp(np->name, "display"))
np->name = get_property(np, "compatible", 0); np->name = get_property(np, "compatible", 0);
...@@ -1715,8 +1910,19 @@ finish_node(struct device_node *np, unsigned long mem_start, ...@@ -1715,8 +1910,19 @@ finish_node(struct device_node *np, unsigned long mem_start,
ifunc = NULL; ifunc = NULL;
else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci")) else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci"))
ifunc = interpret_pci_props; ifunc = interpret_pci_props;
else if (!strcmp(np->type, "dbdma"))
ifunc = interpret_dbdma_props;
else if (!strcmp(np->type, "mac-io") || ifunc == interpret_macio_props)
ifunc = interpret_macio_props;
else if (!strcmp(np->type, "isa")) else if (!strcmp(np->type, "isa"))
ifunc = interpret_isa_props; ifunc = interpret_isa_props;
else if (!strcmp(np->name, "uni-n") || !strcmp(np->name, "u3"))
ifunc = interpret_root_props;
else if (!((ifunc == interpret_dbdma_props
|| ifunc == interpret_macio_props)
&& (!strcmp(np->type, "escc")
|| !strcmp(np->type, "media-bay"))))
ifunc = NULL;
for (child = np->child; child != NULL; child = child->sibling) for (child = np->child; child != NULL; child = child->sibling)
mem_start = finish_node(child, mem_start, ifunc, mem_start = finish_node(child, mem_start, ifunc,
...@@ -1893,6 +2099,12 @@ finish_node_interrupts(struct device_node *np, unsigned long mem_start) ...@@ -1893,6 +2099,12 @@ finish_node_interrupts(struct device_node *np, unsigned long mem_start)
if (n <= 0) if (n <= 0)
continue; continue;
np->intrs[i].line = openpic_to_irq(virt_irq_create_mapping(irq[0])); np->intrs[i].line = openpic_to_irq(virt_irq_create_mapping(irq[0]));
/* We offset irq numbers for the u3 MPIC by 128 in PowerMac */
if (systemcfg->platform == PLATFORM_POWERMAC && ic && ic->parent) {
char *name = get_property(ic->parent, "name", NULL);
if (name && !strcmp(name, "u3"))
np->intrs[i].line += 128;
}
if (n > 1) if (n > 1)
np->intrs[i].sense = irq[1]; np->intrs[i].sense = irq[1];
if (n > 2) { if (n > 2) {
...@@ -1964,6 +2176,78 @@ interpret_pci_props(struct device_node *np, unsigned long mem_start, ...@@ -1964,6 +2176,78 @@ interpret_pci_props(struct device_node *np, unsigned long mem_start,
return mem_start; return mem_start;
} }
static unsigned long __init
interpret_dbdma_props(struct device_node *np, unsigned long mem_start,
int naddrc, int nsizec)
{
struct reg_property32 *rp;
struct address_range *adr;
unsigned long base_address;
int i, l;
struct device_node *db;
base_address = 0;
for (db = np->parent; db != NULL; db = db->parent) {
if (!strcmp(db->type, "dbdma") && db->n_addrs != 0) {
base_address = db->addrs[0].address;
break;
}
}
rp = (struct reg_property32 *) get_property(np, "reg", &l);
if (rp != 0 && l >= sizeof(struct reg_property32)) {
i = 0;
adr = (struct address_range *) mem_start;
while ((l -= sizeof(struct reg_property32)) >= 0) {
adr[i].space = 2;
adr[i].address = rp[i].address + base_address;
adr[i].size = rp[i].size;
++i;
}
np->addrs = adr;
np->n_addrs = i;
mem_start += i * sizeof(struct address_range);
}
return mem_start;
}
static unsigned long __init
interpret_macio_props(struct device_node *np, unsigned long mem_start,
int naddrc, int nsizec)
{
struct reg_property32 *rp;
struct address_range *adr;
unsigned long base_address;
int i, l;
struct device_node *db;
base_address = 0;
for (db = np->parent; db != NULL; db = db->parent) {
if (!strcmp(db->type, "mac-io") && db->n_addrs != 0) {
base_address = db->addrs[0].address;
break;
}
}
rp = (struct reg_property32 *) get_property(np, "reg", &l);
if (rp != 0 && l >= sizeof(struct reg_property32)) {
i = 0;
adr = (struct address_range *) mem_start;
while ((l -= sizeof(struct reg_property32)) >= 0) {
adr[i].space = 2;
adr[i].address = rp[i].address + base_address;
adr[i].size = rp[i].size;
++i;
}
np->addrs = adr;
np->n_addrs = i;
mem_start += i * sizeof(struct address_range);
}
return mem_start;
}
static unsigned long __init static unsigned long __init
interpret_isa_props(struct device_node *np, unsigned long mem_start, interpret_isa_props(struct device_node *np, unsigned long mem_start,
int naddrc, int nsizec) int naddrc, int nsizec)
...@@ -2212,6 +2496,7 @@ struct device_node *of_find_node_by_name(struct device_node *from, ...@@ -2212,6 +2496,7 @@ struct device_node *of_find_node_by_name(struct device_node *from,
read_unlock(&devtree_lock); read_unlock(&devtree_lock);
return np; return np;
} }
EXPORT_SYMBOL(of_find_node_by_name);
/** /**
* of_find_node_by_type - Find a node by its "device_type" property * of_find_node_by_type - Find a node by its "device_type" property
...@@ -2275,6 +2560,7 @@ struct device_node *of_find_compatible_node(struct device_node *from, ...@@ -2275,6 +2560,7 @@ struct device_node *of_find_compatible_node(struct device_node *from,
read_unlock(&devtree_lock); read_unlock(&devtree_lock);
return np; return np;
} }
EXPORT_SYMBOL(of_find_compatible_node);
/** /**
* of_find_node_by_path - Find a node matching a full OF path * of_find_node_by_path - Find a node matching a full OF path
...@@ -2295,6 +2581,7 @@ struct device_node *of_find_node_by_path(const char *path) ...@@ -2295,6 +2581,7 @@ struct device_node *of_find_node_by_path(const char *path)
read_unlock(&devtree_lock); read_unlock(&devtree_lock);
return np; return np;
} }
EXPORT_SYMBOL(of_find_node_by_path);
/** /**
* of_find_all_nodes - Get next node in global list * of_find_all_nodes - Get next node in global list
...@@ -2318,6 +2605,7 @@ struct device_node *of_find_all_nodes(struct device_node *prev) ...@@ -2318,6 +2605,7 @@ struct device_node *of_find_all_nodes(struct device_node *prev)
read_unlock(&devtree_lock); read_unlock(&devtree_lock);
return np; return np;
} }
EXPORT_SYMBOL(of_find_all_nodes);
/** /**
* of_get_parent - Get a node's parent if any * of_get_parent - Get a node's parent if any
...@@ -2338,6 +2626,7 @@ struct device_node *of_get_parent(const struct device_node *node) ...@@ -2338,6 +2626,7 @@ struct device_node *of_get_parent(const struct device_node *node)
read_unlock(&devtree_lock); read_unlock(&devtree_lock);
return np; return np;
} }
EXPORT_SYMBOL(of_get_parent);
/** /**
* of_get_next_child - Iterate a node childs * of_get_next_child - Iterate a node childs
...@@ -2362,6 +2651,7 @@ struct device_node *of_get_next_child(const struct device_node *node, ...@@ -2362,6 +2651,7 @@ struct device_node *of_get_next_child(const struct device_node *node,
read_unlock(&devtree_lock); read_unlock(&devtree_lock);
return next; return next;
} }
EXPORT_SYMBOL(of_get_next_child);
/** /**
* of_node_get - Increment refcount of a node * of_node_get - Increment refcount of a node
...@@ -2378,6 +2668,7 @@ struct device_node *of_node_get(struct device_node *node) ...@@ -2378,6 +2668,7 @@ struct device_node *of_node_get(struct device_node *node)
} }
return NULL; return NULL;
} }
EXPORT_SYMBOL(of_node_get);
/** /**
* of_node_put - Decrement refcount of a node * of_node_put - Decrement refcount of a node
...@@ -2401,6 +2692,7 @@ void of_node_put(struct device_node *node) ...@@ -2401,6 +2692,7 @@ void of_node_put(struct device_node *node)
else else
atomic_dec(&node->_users); atomic_dec(&node->_users);
} }
EXPORT_SYMBOL(of_node_put);
/** /**
* of_node_cleanup - release a dynamically allocated node * of_node_cleanup - release a dynamically allocated node
...@@ -2658,6 +2950,12 @@ static int of_finish_dynamic_node(struct device_node *node) ...@@ -2658,6 +2950,12 @@ static int of_finish_dynamic_node(struct device_node *node)
goto out; goto out;
} }
/* We don't support that function on PowerMac, at least
* not yet
*/
if (systemcfg->platform == PLATFORM_POWERMAC)
return -ENODEV;
/* do the work of interpret_pci_props */ /* do the work of interpret_pci_props */
if (parent->type && !strcmp(parent->type, "pci")) { if (parent->type && !strcmp(parent->type, "pci")) {
struct address_range *adr; struct address_range *adr;
......
...@@ -23,6 +23,7 @@ extern unsigned long reloc_offset(void); ...@@ -23,6 +23,7 @@ extern unsigned long reloc_offset(void);
union lmb_reg_property { union lmb_reg_property {
struct reg_property32 addr32[MAX_LMB_REGIONS]; struct reg_property32 addr32[MAX_LMB_REGIONS];
struct reg_property64 addr64[MAX_LMB_REGIONS]; struct reg_property64 addr64[MAX_LMB_REGIONS];
struct reg_property_pmac addrPM[MAX_LMB_REGIONS];
}; };
#define LMB_MEMORY_AREA 1 #define LMB_MEMORY_AREA 1
......
...@@ -108,6 +108,12 @@ struct reg_property64 { ...@@ -108,6 +108,12 @@ struct reg_property64 {
unsigned long size; unsigned long size;
}; };
struct reg_property_pmac {
unsigned int address_hi;
unsigned int address_lo;
unsigned int size;
};
struct translation_property { struct translation_property {
unsigned long virt; unsigned long virt;
unsigned long size; unsigned long size;
...@@ -207,6 +213,7 @@ struct prom_args { ...@@ -207,6 +213,7 @@ struct prom_args {
struct prom_t { struct prom_t {
unsigned long entry; unsigned long entry;
ihandle root;
ihandle chosen; ihandle chosen;
int cpu; int cpu;
ihandle stdout; ihandle stdout;
......
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