[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [XenPPC] [PATCH] open pic detection
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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |