Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 13716
b: refs/heads/master
c: a23414b
h: refs/heads/master
v: v3
  • Loading branch information
Paul Mackerras committed Nov 10, 2005
1 parent ab228fb commit 4ab0e45
Show file tree
Hide file tree
Showing 9 changed files with 296 additions and 84 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8b553f32db3bf5d0ec0819c595932eb21cd45945
refs/heads/master: a23414beb6607dfd40d3245f7df9dd97a4e2c82b
9 changes: 8 additions & 1 deletion trunk/arch/powerpc/kernel/prom.c
Original file line number Diff line number Diff line change
Expand Up @@ -1264,7 +1264,14 @@ static int __init early_init_dt_scan_memory(unsigned long node,
unsigned long l;

/* We are scanning "memory" nodes only */
if (type == NULL || strcmp(type, "memory") != 0)
if (type == NULL) {
/*
* The longtrail doesn't have a device_type on the
* /memory node, so look for the node called /memory@0.
*/
if (depth != 1 || strcmp(uname, "memory@0") != 0)
return 0;
} else if (strcmp(type, "memory") != 0)
return 0;

reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l);
Expand Down
170 changes: 127 additions & 43 deletions trunk/arch/powerpc/kernel/prom_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,17 @@ extern const struct linux_logo logo_linux_clut224;
#ifdef CONFIG_PPC64
#define RELOC(x) (*PTRRELOC(&(x)))
#define ADDR(x) (u32) add_reloc_offset((unsigned long)(x))
#define OF_WORKAROUNDS 0
#else
#define RELOC(x) (x)
#define ADDR(x) (u32) (x)
#define OF_WORKAROUNDS of_workarounds
int of_workarounds;
#endif

#define OF_WA_CLAIM 1 /* do phys/virt claim separately, then map */
#define OF_WA_LONGTRAIL 2 /* work around longtrail bugs */

#define PROM_BUG() do { \
prom_printf("kernel BUG at %s line 0x%x!\n", \
RELOC(__FILE__), __LINE__); \
Expand Down Expand Up @@ -128,10 +134,11 @@ struct prom_args {

struct prom_t {
ihandle root;
ihandle chosen;
phandle chosen;
int cpu;
ihandle stdout;
ihandle mmumap;
ihandle memory;
};

struct mem_map_entry {
Expand Down Expand Up @@ -360,16 +367,36 @@ static void __init prom_printf(const char *format, ...)
static unsigned int __init prom_claim(unsigned long virt, unsigned long size,
unsigned long align)
{
int ret;
struct prom_t *_prom = &RELOC(prom);

ret = call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size,
(prom_arg_t)align);
if (ret != -1 && _prom->mmumap != 0)
/* old pmacs need us to map as well */
if (align == 0 && (OF_WORKAROUNDS & OF_WA_CLAIM)) {
/*
* Old OF requires we claim physical and virtual separately
* and then map explicitly (assuming virtual mode)
*/
int ret;
prom_arg_t result;

ret = call_prom_ret("call-method", 5, 2, &result,
ADDR("claim"), _prom->memory,
align, size, virt);
if (ret != 0 || result == -1)
return -1;
ret = call_prom_ret("call-method", 5, 2, &result,
ADDR("claim"), _prom->mmumap,
align, size, virt);
if (ret != 0) {
call_prom("call-method", 4, 1, ADDR("release"),
_prom->memory, size, virt);
return -1;
}
/* the 0x12 is M (coherence) + PP == read/write */
call_prom("call-method", 6, 1,
ADDR("map"), _prom->mmumap, 0, size, virt, virt);
return ret;
ADDR("map"), _prom->mmumap, 0x12, size, virt, virt);
return virt;
}
return call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size,
(prom_arg_t)align);
}

static void __init __attribute__((noreturn)) prom_panic(const char *reason)
Expand Down Expand Up @@ -415,11 +442,52 @@ static int inline prom_getproplen(phandle node, const char *pname)
return call_prom("getproplen", 2, 1, node, ADDR(pname));
}

static int inline prom_setprop(phandle node, const char *pname,
void *value, size_t valuelen)
static void add_string(char **str, const char *q)
{
return call_prom("setprop", 4, 1, node, ADDR(pname),
(u32)(unsigned long) value, (u32) valuelen);
char *p = *str;

while (*q)
*p++ = *q++;
*p++ = ' ';
*str = p;
}

static char *tohex(unsigned int x)
{
static char digits[] = "0123456789abcdef";
static char result[9];
int i;

result[8] = 0;
i = 8;
do {
--i;
result[i] = digits[x & 0xf];
x >>= 4;
} while (x != 0 && i > 0);
return &result[i];
}

static int __init prom_setprop(phandle node, const char *nodename,
const char *pname, void *value, size_t valuelen)
{
char cmd[256], *p;

if (!(OF_WORKAROUNDS & OF_WA_LONGTRAIL))
return call_prom("setprop", 4, 1, node, ADDR(pname),
(u32)(unsigned long) value, (u32) valuelen);

/* gah... setprop doesn't work on longtrail, have to use interpret */
p = cmd;
add_string(&p, "dev");
add_string(&p, nodename);
add_string(&p, tohex((u32)(unsigned long) value));
add_string(&p, tohex(valuelen));
add_string(&p, tohex(ADDR(pname)));
add_string(&p, tohex(strlen(RELOC(pname))));
add_string(&p, "property");
*p = 0;
return call_prom("interpret", 1, 1, (u32)(unsigned long) cmd);
}

/* We can't use the standard versions because of RELOC headaches. */
Expand Down Expand Up @@ -980,15 +1048,15 @@ static void __init prom_instantiate_rtas(void)

rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
if (!IHANDLE_VALID(rtas_inst)) {
prom_printf("opening rtas package failed");
prom_printf("opening rtas package failed (%x)\n", rtas_inst);
return;
}

prom_printf("instantiating rtas at 0x%x ...", base);

if (call_prom_ret("call-method", 3, 2, &entry,
ADDR("instantiate-rtas"),
rtas_inst, base) == PROM_ERROR
rtas_inst, base) != 0
|| entry == 0) {
prom_printf(" failed\n");
return;
Expand All @@ -997,8 +1065,10 @@ static void __init prom_instantiate_rtas(void)

reserve_mem(base, size);

prom_setprop(rtas_node, "linux,rtas-base", &base, sizeof(base));
prom_setprop(rtas_node, "linux,rtas-entry", &entry, sizeof(entry));
prom_setprop(rtas_node, "/rtas", "linux,rtas-base",
&base, sizeof(base));
prom_setprop(rtas_node, "/rtas", "linux,rtas-entry",
&entry, sizeof(entry));

prom_debug("rtas base = 0x%x\n", base);
prom_debug("rtas entry = 0x%x\n", entry);
Expand Down Expand Up @@ -1089,10 +1159,6 @@ static void __init prom_initialize_tce_table(void)
if (base < local_alloc_bottom)
local_alloc_bottom = base;

/* Save away the TCE table attributes for later use. */
prom_setprop(node, "linux,tce-base", &base, sizeof(base));
prom_setprop(node, "linux,tce-size", &minsize, sizeof(minsize));

/* It seems OF doesn't null-terminate the path :-( */
memset(path, 0, sizeof(path));
/* Call OF to setup the TCE hardware */
Expand All @@ -1101,6 +1167,10 @@ static void __init prom_initialize_tce_table(void)
prom_printf("package-to-path failed\n");
}

/* Save away the TCE table attributes for later use. */
prom_setprop(node, path, "linux,tce-base", &base, sizeof(base));
prom_setprop(node, path, "linux,tce-size", &minsize, sizeof(minsize));

prom_debug("TCE table: %s\n", path);
prom_debug("\tnode = 0x%x\n", node);
prom_debug("\tbase = 0x%x\n", base);
Expand Down Expand Up @@ -1342,6 +1412,7 @@ static void __init prom_init_client_services(unsigned long pp)
/*
* For really old powermacs, we need to map things we claim.
* For that, we need the ihandle of the mmu.
* Also, on the longtrail, we need to work around other bugs.
*/
static void __init prom_find_mmu(void)
{
Expand All @@ -1355,12 +1426,19 @@ static void __init prom_find_mmu(void)
if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0)
return;
version[sizeof(version) - 1] = 0;
prom_printf("OF version is '%s'\n", version);
/* XXX might need to add other versions here */
if (strcmp(version, "Open Firmware, 1.0.5") != 0)
if (strcmp(version, "Open Firmware, 1.0.5") == 0)
of_workarounds = OF_WA_CLAIM;
else if (strncmp(version, "FirmWorks,3.", 12) == 0) {
of_workarounds = OF_WA_CLAIM | OF_WA_LONGTRAIL;
call_prom("interpret", 1, 1, "dev /memory 0 to allow-reclaim");
} else
return;
_prom->memory = call_prom("open", 1, 1, ADDR("/memory"));
prom_getprop(_prom->chosen, "mmu", &_prom->mmumap,
sizeof(_prom->mmumap));
if (!IHANDLE_VALID(_prom->memory) || !IHANDLE_VALID(_prom->mmumap))
of_workarounds &= ~OF_WA_CLAIM; /* hmmm */
}
#else
#define prom_find_mmu()
Expand All @@ -1382,16 +1460,17 @@ static void __init prom_init_stdout(void)
memset(path, 0, 256);
call_prom("instance-to-path", 3, 1, _prom->stdout, path, 255);
val = call_prom("instance-to-package", 1, 1, _prom->stdout);
prom_setprop(_prom->chosen, "linux,stdout-package", &val, sizeof(val));
prom_setprop(_prom->chosen, "/chosen", "linux,stdout-package",
&val, sizeof(val));
prom_printf("OF stdout device is: %s\n", RELOC(of_stdout_device));
prom_setprop(_prom->chosen, "linux,stdout-path",
RELOC(of_stdout_device), strlen(RELOC(of_stdout_device))+1);
prom_setprop(_prom->chosen, "/chosen", "linux,stdout-path",
path, strlen(path) + 1);

/* If it's a display, note it */
memset(type, 0, sizeof(type));
prom_getprop(val, "device_type", type, sizeof(type));
if (strcmp(type, RELOC("display")) == 0)
prom_setprop(val, "linux,boot-display", NULL, 0);
prom_setprop(val, path, "linux,boot-display", NULL, 0);
}

static void __init prom_close_stdin(void)
Expand Down Expand Up @@ -1514,7 +1593,7 @@ static void __init prom_check_displays(void)

/* Success */
prom_printf("done\n");
prom_setprop(node, "linux,opened", NULL, 0);
prom_setprop(node, path, "linux,opened", NULL, 0);

/* Setup a usable color table when the appropriate
* method is available. Should update this to set-colors */
Expand Down Expand Up @@ -1884,9 +1963,11 @@ static void __init fixup_device_tree(void)
/* interrupt on this revision of u3 is number 0 and level */
interrupts[0] = 0;
interrupts[1] = 1;
prom_setprop(i2c, "interrupts", &interrupts, sizeof(interrupts));
prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupts",
&interrupts, sizeof(interrupts));
parent = (u32)mpic;
prom_setprop(i2c, "interrupt-parent", &parent, sizeof(parent));
prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupt-parent",
&parent, sizeof(parent));
#endif
}

Expand Down Expand Up @@ -1922,11 +2003,11 @@ static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4;

val = RELOC(prom_initrd_start);
prom_setprop(_prom->chosen, "linux,initrd-start", &val,
sizeof(val));
prom_setprop(_prom->chosen, "/chosen", "linux,initrd-start",
&val, sizeof(val));
val = RELOC(prom_initrd_end);
prom_setprop(_prom->chosen, "linux,initrd-end", &val,
sizeof(val));
prom_setprop(_prom->chosen, "/chosen", "linux,initrd-end",
&val, sizeof(val));

reserve_mem(RELOC(prom_initrd_start),
RELOC(prom_initrd_end) - RELOC(prom_initrd_start));
Expand Down Expand Up @@ -1969,14 +2050,15 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
prom_init_client_services(pp);

/*
* Init prom stdout device
* See if this OF is old enough that we need to do explicit maps
* and other workarounds
*/
prom_init_stdout();
prom_find_mmu();

/*
* See if this OF is old enough that we need to do explicit maps
* Init prom stdout device
*/
prom_find_mmu();
prom_init_stdout();

/*
* Check for an initrd
Expand All @@ -1989,7 +2071,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
*/
RELOC(of_platform) = prom_find_machine_type();
getprop_rval = RELOC(of_platform);
prom_setprop(_prom->chosen, "linux,platform",
prom_setprop(_prom->chosen, "/chosen", "linux,platform",
&getprop_rval, sizeof(getprop_rval));

#ifdef CONFIG_PPC_PSERIES
Expand Down Expand Up @@ -2050,21 +2132,23 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
* Fill in some infos for use by the kernel later on
*/
if (RELOC(prom_memory_limit))
prom_setprop(_prom->chosen, "linux,memory-limit",
prom_setprop(_prom->chosen, "/chosen", "linux,memory-limit",
&RELOC(prom_memory_limit),
sizeof(prom_memory_limit));
#ifdef CONFIG_PPC64
if (RELOC(ppc64_iommu_off))
prom_setprop(_prom->chosen, "linux,iommu-off", NULL, 0);
prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off",
NULL, 0);

if (RELOC(iommu_force_on))
prom_setprop(_prom->chosen, "linux,iommu-force-on", NULL, 0);
prom_setprop(_prom->chosen, "/chosen", "linux,iommu-force-on",
NULL, 0);

if (RELOC(prom_tce_alloc_start)) {
prom_setprop(_prom->chosen, "linux,tce-alloc-start",
prom_setprop(_prom->chosen, "/chosen", "linux,tce-alloc-start",
&RELOC(prom_tce_alloc_start),
sizeof(prom_tce_alloc_start));
prom_setprop(_prom->chosen, "linux,tce-alloc-end",
prom_setprop(_prom->chosen, "/chosen", "linux,tce-alloc-end",
&RELOC(prom_tce_alloc_end),
sizeof(prom_tce_alloc_end));
}
Expand Down
4 changes: 3 additions & 1 deletion trunk/arch/powerpc/platforms/chrp/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,9 @@ static void __init chrp_find_openpic(void)
printk(KERN_INFO "OpenPIC at %lx\n", opaddr);

irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */
prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS - 4);
prom_get_irq_senses(init_senses, NUM_ISA_INTERRUPTS, NR_IRQS - 4);
/* i8259 cascade is always positive level */
init_senses[0] = IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE;

iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len);
if (iranges == NULL)
Expand Down
3 changes: 3 additions & 0 deletions trunk/arch/ppc/boot/include/of1275.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ extern prom_entry of_prom_entry;

/* function declarations */

int call_prom(const char *service, int nargs, int nret, ...);
int call_prom_ret(const char *service, int nargs, int nret,
unsigned int *rets, ...);
void * claim(unsigned int virt, unsigned int size, unsigned int align);
int map(unsigned int phys, unsigned int virt, unsigned int size);
void enter(void);
Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/ppc/boot/of1275/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
#

lib-y := claim.o enter.o exit.o finddevice.o getprop.o ofinit.o \
ofstdio.o read.o release.o write.o map.o
ofstdio.o read.o release.o write.o map.o call_prom.o
Loading

0 comments on commit 4ab0e45

Please sign in to comment.