Signed-off-by: Maria Butrico <butrico@xxxxxxxxxxxxxx>
summary: open pic detection.
Moved the open pic detection code from boot_of to its
own location. The cew code uses the OFD tree.
diff -r d16209a2476e xen/arch/ppc/Makefile
--- a/xen/arch/ppc/Makefile Wed May 17 17:57:54 2006 -0400
+++ b/xen/arch/ppc/Makefile Thu May 18 10:15:31 2006 -0400
@@ -36,6 +36,7 @@ obj-y += smp.o
obj-y += smp.o
obj-y += time.o
obj-y += usercopy.o
+obj-y += find_mpic.o
obj-$(debug) += 0opt.o
obj-$(crash_debug) += gdbstub.o
diff -r d16209a2476e xen/arch/ppc/boot_of.c
--- a/xen/arch/ppc/boot_of.c Wed May 17 17:57:54 2006 -0400
+++ b/xen/arch/ppc/boot_of.c Thu May 18 10:15:31 2006 -0400
@@ -36,7 +36,6 @@ static char bootargs[256];
static char bootargs[256];
static char dom0args[256];
-extern unsigned long opic_addr;
extern struct ns16550_defaults ns16550;
#undef OF_DEBUG
@@ -920,31 +919,6 @@ static int __init boot_of_rtas(void)
return 1;
}
-static void __init boot_of_pic(void)
-{
- int root;
- int p;
- u32 addr_cells = 1;
- int rc;
- u32 addr[2];
-
- root = of_finddevice("/");
- p = of_getchild(root);
-
- /* code is writen to assume sizes of 1 */
- of_getprop(root, "#address-cells", &addr_cells, sizeof (addr_cells));
- rc = of_getprop(root, "platform-open-pic", addr, sizeof (addr));
- if (rc <= 0) {
- of_panic("cannot find the openpic\n");
- }
- opic_addr = addr[0];
- if (addr_cells == 2) {
- opic_addr <<= 32;
- opic_addr |= addr[1];
- }
- of_printf("OF: found OpenPIC at: 0x%lx\n", opic_addr);
-}
-
static void __init boot_of_dart(void)
{
int n;
@@ -1010,7 +984,6 @@ multiboot_info_t __init *boot_of_init(
boot_of_serial();
boot_of_cpus();
boot_of_rtas();
- boot_of_pic();
boot_of_dart();
/* end of OF */
diff -r d16209a2476e xen/arch/ppc/external.c
--- a/xen/arch/ppc/external.c Wed May 17 17:57:54 2006 -0400
+++ b/xen/arch/ppc/external.c Thu May 18 10:15:31 2006 -0400
@@ -26,6 +26,7 @@
#include <asm/current.h>
#include <asm/hardirq.h>
#include <asm/mpic.h>
+#include "find_mpic.h"
#undef DEBUG
#ifdef DEBUG
@@ -38,7 +39,6 @@ extern void do_IRQ(struct cpu_user_regs
int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1};
-unsigned long opic_addr;
unsigned long io_apic_irqs;
int ioapic_ack_new = 1;
@@ -166,7 +166,7 @@ static void xen_set_affinity(unsigned in
}
}
-void init_IRQ(void)
+void init_IRQ(unsigned long oftree)
{
unsigned int isu_size;
unsigned int irq_offset;
@@ -188,9 +188,18 @@ void init_IRQ(void)
senses = NULL;
senses_count = 0;
+
+ if (find_mpic(oftree)) {
+ printk("%s: ERROR: Could not find open pic.\n", __func__);
+ return;
+ } else {
+ unsigned long opic_addr = get_mpic_address();
+ unsigned int opic_flags = get_mpic_flags();
+
mpic = mpic_alloc(opic_addr,
- MPIC_PRIMARY | MPIC_BIG_ENDIAN |
- MPIC_BROKEN_U3 | MPIC_WANTS_RESET,
+ MPIC_PRIMARY |
+ MPIC_BROKEN_U3 | MPIC_WANTS_RESET |
+ opic_flags,
isu_size, irq_offset, irq_count,
ipi_offset, senses, senses_count, "Xen-U3-MPIC");
@@ -219,6 +228,7 @@ void init_IRQ(void)
mpic->hc_irq.set_affinity = xen_set_affinity;
printk("%s: success\n", __func__);
+ }
}
void ack_APIC_irq(void) {
diff -r d16209a2476e xen/arch/ppc/setup.c
--- a/xen/arch/ppc/setup.c Wed May 17 17:57:54 2006 -0400
+++ b/xen/arch/ppc/setup.c Thu May 18 10:15:31 2006 -0400
@@ -37,6 +37,7 @@
#include <asm/debugger.h>
#include <asm/delay.h>
+#define DEBUG
unsigned long xenheap_phys_end;
/* opt_noht: If true, Hyperthreading is ignored. */
@@ -73,7 +74,7 @@ extern char exception_vectors_end[];
/* move us to a header file */
extern void initialize_keytable(void);
-extern void init_IRQ(void);
+extern void init_IRQ(unsigned long oftree);
int is_kernel_text(unsigned long addr)
{
@@ -115,7 +116,7 @@ static void __init start_of_day(void)
{
struct domain *idle_domain;
- init_IRQ();
+ init_IRQ(oftree);
scheduler_init();
@@ -188,7 +189,7 @@ static void __init __start_xen(multiboot
modules_start = mod[0].mod_start;
modules_size = mod[mbi->mods_count-1].mod_end - mod[0].mod_start;
- /* OF dev tree is tthe last module */
+ /* OF dev tree is the last module */
oftree = mod[mbi->mods_count-1].mod_start;
oftree_end = mod[mbi->mods_count-1].mod_end;
oftree_len = oftree_end - oftree;
diff -r d16209a2476e xen/arch/ppc/find_mpic.c
--- /dev/null Thu Jan 1 00:00:00 1970 +0000
+++ b/xen/arch/ppc/find_mpic.c Thu May 18 10:15:31 2006 -0400
@@ -0,0 +1,310 @@
+
+#include <xen/config.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+#include <xen/compile.h>
+#include <public/of-devtree.h>
+#include <asm/mpic.h>
+
+#undef DEBUG
+#undef NOSERIAL
+#ifdef DEBUG
+ #ifdef NOSERIAL
+ int of_printf(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+ #define DBG(fmt...) of_printf(fmt)
+ #else
+ #define DBG(fmt...) printk(fmt)
+ #endif /* #ifdef NOSERIAL */
+#else
+#define DBG(fmt...)
+#endif
+
+#define PANIC(fmt...) DBG(fmt)
+
+unsigned long opic_addr;
+unsigned int opic_flags;
+
+
+/*
+ * from OF_IEEE_1275
+ *
+ * pg 175, property "ranges"
+ *
+ * The number of integers in each size entry is
+ * determined by the value of the #size-cells property of this node (the node
in which the ranges property appears)
+ * or 1 if the #size-cells property is absent.
+ *
+ *
+ * pg 177, property "reg"
+ *
+ * The number of integers in each size entry is determined by the value of the
"#size-cells" property in the parent node.
+ * If the parent node has no such property, the value is one.
+ */
+static unsigned long reg2(void *oft_p, ofdn_t c)
+{
+ int rc;
+ /* the struct isa_reg_property is for a value of 2 for #address-cells and a
+ * value of 1 for #size-cells (of the parent).
+ */
+ struct isa_reg_property {
+ u32 space;
+ u32 address;
+ u32 size;
+ } isa_reg;
+
+ rc = ofd_getprop(oft_p, c, "reg", &isa_reg, sizeof(isa_reg));
+
+ DBG("%s: reg property address=0x%08x size=0x%08x\n", __func__,
+ isa_reg.address, isa_reg.size);
+ return isa_reg.address;
+}
+
+static unsigned long reg1(void *oft_p, ofdn_t c)
+{
+ int rc;
+ /* the struct reg_property32 is for a value of 1 for #address-cells and
+ * a value of 1 for #size-cells.
+ */
+ struct reg_property32 {
+ u32 address;
+ u32 size;
+ } reg;
+
+ rc = ofd_getprop(oft_p, c, "reg", ®, sizeof(reg));
+
+ DBG("%s: reg property address=0x%08x size=0x%08x\n", __func__,
+ reg.address, reg.size);
+ return reg.address;
+}
+
+static unsigned long find_reg_addr_from_node(void *oft_p, ofdn_t c)
+{
+ int p_len;
+ unsigned long reg_addr = 0;
+ u32 size_c = 1;
+ u32 addr_c = 2;
+ ofdn_t parent;
+
+ if (c == OFD_ROOT) {
+ parent = c;
+ } else {
+ parent = ofd_node_parent(oft_p, c);
+ }
+
+ p_len = ofd_getprop(oft_p, parent, "#size-cells", &size_c, sizeof(size_c));
+ DBG("%s size is %d\n", __func__, size_c);
+
+ p_len = ofd_getprop(oft_p, parent, "#address-cells", &addr_c,
sizeof(addr_c));
+ DBG("%s address is %d\n", __func__, addr_c);
+
+ if ( 1 != size_c ) {
+ PANIC("Unsupported size for reg property\n");
+ }
+
+ if ( 1 == addr_c) {
+ reg_addr = reg1(oft_p, c);
+ } else if ( 2 == addr_c ) {
+ reg_addr = reg2(oft_p, c);
+ } else {
+ PANIC("Unsupported address size for reg property\n");
+ }
+ DBG("%s: address 0x%lx\n", __func__, reg_addr);
+ return reg_addr;
+}
+
+/*
+ * from OF_IEEE_1275
+ *
+ * pg 175, property "ranges"
+ *
+ * The ranges property value is a sequence of
+ * child-phys parent-phys size
+ * specifications. Child-phys is an address, encoded as with encode-phys, in
the child address space. Parent-phys is an
+ * address (likewise encoded as with encode-phys) in the parent address space.
Size is a list of integers, each encoded as
+ * with encode-int, denoting the length of the child's address range.
+ */
+static unsigned long find_ranges_addr_from_node(void *oft_p, ofdn_t c)
+{
+ unsigned long ranges_addr = 0;
+ int ranges_i;
+ ofdn_t parent;
+ u32 addr_c = 2;
+ u32 ranges[64];
+ int p_len;
+
+ parent = ofd_node_parent(oft_p, c);
+ parent = ofd_node_parent(oft_p, parent);
+
+ p_len = ofd_getprop(oft_p, parent, "ranges", &ranges, sizeof(ranges));
+ DBG("%s: ranges\n", __func__);
+ int i; for (i=0; i<p_len; i++) {DBG("%08x ", ranges[i]);}
+ DBG("\n");
+
+ p_len = ofd_getprop(oft_p, parent, "#address-cells", &addr_c,
sizeof(addr_c));
+ DBG("%s address is %d\n", __func__, addr_c);
+ ranges_i = addr_c; /* skip over the child address */
+
+ DBG("%s address is %d\n", __func__, addr_c);
+ switch (addr_c) {
+ case 1:
+ ranges_addr = ranges[ranges_i];
+ break;
+ case 2:
+ ranges_addr = (((u64)ranges[ranges_i]) << 32) |
+ ranges[ranges_i + 1];
+ break;
+ case 3: /* the G5 case, how to squeeze 96 bits into 64 */
+ ranges_addr = (((u64)ranges[ranges_i+1]) << 32) |
+ ranges[ranges_i + 2];
+ break;
+ case 4:
+ ranges_addr = (((u64)ranges[ranges_i+2]) << 32) |
+ ranges[ranges_i + 4];
+ break;
+ default:
+ PANIC("#address-cells out of range\n");
+ break;
+ }
+
+ DBG("%s: address 0x%lx\n", __func__, ranges_addr);
+ return ranges_addr;
+}
+
+static unsigned long find_pic_address_from_node(void *oft_p, ofdn_t c)
+{
+ unsigned long reg_addr, range_addr, addr;
+
+ /*
+ * The address is the sum of the address in the reg property of this node
+ * and the ranges property of the granparent node.
+ */
+ reg_addr = find_reg_addr_from_node(oft_p, c);
+ range_addr = find_ranges_addr_from_node(oft_p, c);
+ addr = reg_addr + range_addr;
+ DBG("%s: address 0x%lx\n", __func__, addr);
+ return addr;
+}
+
+static unsigned int find_pic_flags_from_node(void *oft_p, ofdn_t c)
+{
+ int be_len;
+ unsigned int flags = 0;
+
+ /* does it have the property big endian? */
+ be_len = ofd_getprop(oft_p, c, "big_endian", NULL, 0);
+ if (be_len >= 0) {
+ DBG("%s: Big Endian found\n", __func__);
+ flags |= MPIC_BIG_ENDIAN;
+ }
+ DBG("%s: flags 0x%x\n", __func__, flags);
+ return flags;
+}
+
+static int find_mpic_simple_probe(void *oft_p )
+{
+ u32 addr_cells;
+ int rc;
+ u32 addr[2];
+
+ rc = ofd_getprop(oft_p, OFD_ROOT, "#address-cells", &addr_cells,
sizeof(addr_cells));
+ if ( rc < 0 ) {
+ /* if the property does not exist use its default value, 2 */
+ addr_cells = 2;
+ }
+
+ rc = ofd_getprop(oft_p, OFD_ROOT, "platform-open-pic", addr, sizeof(addr));
+ if (rc < 0) {
+ return rc;
+ }
+
+ opic_addr = addr[0];
+ if (addr_cells == 2) {
+ opic_addr <<= 32;
+ opic_addr |= addr[1];
+ }
+ DBG("%s: found OpenPIC at: 0x%lx\n", __func__, opic_addr);
+ /* we did not really find the pic device, only its address.
+ * We use big endian by default
+ */
+ opic_flags |= MPIC_BIG_ENDIAN | MPIC_BROKEN_U3;
+ return 0;
+}
+
+static int find_mpic_canonical_probe(void *oft_p)
+{
+ ofdn_t c;
+ const char mpic_type[] = "open-pic";
+ /* some paths are special and we cannot find the address
+ * by the usual method */
+ const char *excluded_paths[] = { "/interrupt-controller" };
+
+ /*
+ * Search through the OFD tree for all devices of type 'open_pic'.
+ * We select the one without an 'interrupt' property.
+ */
+ c = ofd_node_find_by_prop(oft_p, OFD_ROOT, "device_type", mpic_type,
+ sizeof(mpic_type));
+ while (c > 0) {
+ int int_len;
+ int good_mpic;
+ const char * path = ofd_node_path(oft_p, c);
+
+ good_mpic = 0;
+ int_len = ofd_getprop(oft_p, c, "interrupts", NULL, 0);
+ if (int_len < 0) {
+ int i;
+
+ /* there is no property interrupt. This could be the pic */
+ DBG("%s: potential OpenPIC in: %s\n", __func__, path);
+ good_mpic = 1;
+
+ for (i = 0; i < ARRAY_SIZE(excluded_paths) && good_mpic; i++) {
+ const char *excluded_path = excluded_paths[i];
+ if (!strncmp(path, excluded_path, strlen(excluded_path)))
+ good_mpic = 0;
+ }
+ }
+
+ if (good_mpic) {
+ DBG("%s: found OpenPIC in: %s\n", __func__, path);
+ opic_addr = find_pic_address_from_node(oft_p, c);
+ opic_flags = find_pic_flags_from_node(oft_p, c);
+ return 0;
+ }
+
+ c = ofd_node_find_next(oft_p, c);
+ }
+
+ DBG("%s: Could not find a pic\n", __func__);
+ return -1;
+}
+
+int find_mpic(unsigned long oftree)
+{
+ void *oft_p;
+ int rc;
+
+ opic_addr = (unsigned long) -1;
+ opic_flags = 0;
+
+ oft_p = (void *) oftree;
+ rc = find_mpic_simple_probe(oft_p);
+
+ if (rc < 0) {
+ DBG("%s: Searching for pic ...\n", __func__);
+ rc = find_mpic_canonical_probe(oft_p);
+ }
+
+ return rc;
+}
+
+unsigned long get_mpic_address()
+{
+ return opic_addr;
+}
+
+unsigned int get_mpic_flags()
+{
+ return opic_flags;
+}
diff -r d16209a2476e xen/arch/ppc/find_mpic.h
--- /dev/null Thu Jan 1 00:00:00 1970 +0000
+++ b/xen/arch/ppc/find_mpic.h Thu May 18 10:15:31 2006 -0400
@@ -0,0 +1,8 @@
+#ifndef _FIND_MPIC_H
+#define _FIND_MPIC_H
+
+int find_mpic(unsigned long oftree);
+unsigned long get_mpic_address();
+unsigned int get_mpic_flags();
+
+#endif /* #ifndef _FIND_MPIC_H */
_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ppc-devel
|