diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2006-02-13 20:42:16 -0800 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-03-20 01:12:44 -0800 |
commit | e77227eb4e17591a6a511b9c0ff6e8ad7350c575 (patch) | |
tree | be8b7f13fd2ff0543879286b04045f6c3587dda3 /arch/sparc64 | |
parent | d5eb4004303b4dd04ec83b926b5fc2d9ceda4b2e (diff) |
[SPARC64]: Probe virtual-devices root node on sun4v.
This is where we learn how to get the interrupts
for things like the hypervisor console device.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64')
-rw-r--r-- | arch/sparc64/kernel/devices.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/arch/sparc64/kernel/devices.c b/arch/sparc64/kernel/devices.c index ac11d872ef7..817132826e0 100644 --- a/arch/sparc64/kernel/devices.c +++ b/arch/sparc64/kernel/devices.c @@ -12,6 +12,7 @@ #include <linux/string.h> #include <linux/spinlock.h> #include <linux/errno.h> +#include <linux/bootmem.h> #include <asm/page.h> #include <asm/oplib.h> @@ -20,6 +21,7 @@ #include <asm/spitfire.h> #include <asm/timer.h> #include <asm/cpudata.h> +#include <asm/vdev.h> /* Used to synchronize acceses to NatSemi SUPER I/O chip configure * operations in asm/ns87303.h @@ -29,6 +31,61 @@ DEFINE_SPINLOCK(ns87303_lock); extern void cpu_probe(void); extern void central_probe(void); +u32 sun4v_vdev_devhandle; +int sun4v_vdev_root; +struct linux_prom_pci_intmap *sun4v_vdev_intmap; +int sun4v_vdev_num_intmap; +struct linux_prom_pci_intmap sun4v_vdev_intmask; + +static void __init sun4v_virtual_device_probe(void) +{ + struct linux_prom64_registers regs; + struct linux_prom_pci_intmap *ip; + int node, sz, err; + + if (tlb_type != hypervisor) + return; + + node = prom_getchild(prom_root_node); + node = prom_searchsiblings(node, "virtual-devices"); + if (!node) { + prom_printf("SUN4V: Fatal error, no virtual-devices node.\n"); + prom_halt(); + } + + sun4v_vdev_root = node; + + prom_getproperty(node, "reg", (char *)®s, sizeof(regs)); + sun4v_vdev_devhandle = (regs.phys_addr >> 32UL) & 0x0fffffff; + + sz = sizeof(*ip) * 64; + sun4v_vdev_intmap = ip = alloc_bootmem_low_pages(sz); + if (!sun4v_vdev_intmap) { + prom_printf("SUN4V: Error, cannot allocate vdev intmap.\n"); + prom_halt(); + } + + err = prom_getproperty(node, "interrupt-map", (char *) ip, sz); + if (err == -1) { + prom_printf("SUN4V: Fatal error, no vdev interrupt-map.\n"); + prom_halt(); + } + + sun4v_vdev_num_intmap = err / sizeof(*ip); + + err = prom_getproperty(node, "interrupt-map-mask", + (char *) &sun4v_vdev_intmask, + sizeof(sun4v_vdev_intmask)); + if (err == -1) { + prom_printf("SUN4V: Fatal error, no vdev " + "interrupt-map-mask.\n"); + prom_halt(); + } + + printk("SUN4V: virtual-devices devhandle[%x]\n", + sun4v_vdev_devhandle); +} + static const char *cpu_mid_prop(void) { if (tlb_type == spitfire) @@ -177,6 +234,7 @@ void __init device_scan(void) } #endif + sun4v_virtual_device_probe(); central_probe(); cpu_probe(); |