diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sparc64/kernel/devices.c | 97 | ||||
-rw-r--r-- | arch/sparc64/kernel/of_device.c | 3 | ||||
-rw-r--r-- | arch/sparc64/kernel/prom.c | 23 |
3 files changed, 26 insertions, 97 deletions
diff --git a/arch/sparc64/kernel/devices.c b/arch/sparc64/kernel/devices.c index ddbe8cda06af..f8ef2f2b9b37 100644 --- a/arch/sparc64/kernel/devices.c +++ b/arch/sparc64/kernel/devices.c @@ -20,8 +20,6 @@ #include <asm/spitfire.h> #include <asm/timer.h> #include <asm/cpudata.h> -#include <asm/vdev.h> -#include <asm/irq.h> /* Used to synchronize acceses to NatSemi SUPER I/O chip configure * operations in asm/ns87303.h @@ -31,100 +29,6 @@ DEFINE_SPINLOCK(ns87303_lock); extern void cpu_probe(void); extern void central_probe(void); -u32 sun4v_vdev_devhandle; -struct device_node *sun4v_vdev_root; - -struct vdev_intmap { - unsigned int phys; - unsigned int irq; - unsigned int cnode; - unsigned int cinterrupt; -}; - -struct vdev_intmask { - unsigned int phys; - unsigned int interrupt; - unsigned int __unused; -}; - -static struct vdev_intmap *vdev_intmap; -static int vdev_num_intmap; -static struct vdev_intmask *vdev_intmask; - -static void __init sun4v_virtual_device_probe(void) -{ - struct linux_prom64_registers *regs; - struct property *prop; - struct device_node *dp; - int sz; - - if (tlb_type != hypervisor) - return; - - dp = of_find_node_by_name(NULL, "virtual-devices"); - if (!dp) { - prom_printf("SUN4V: Fatal error, no virtual-devices node.\n"); - prom_halt(); - } - - sun4v_vdev_root = dp; - - prop = of_find_property(dp, "reg", NULL); - regs = prop->value; - sun4v_vdev_devhandle = (regs[0].phys_addr >> 32UL) & 0x0fffffff; - - prop = of_find_property(dp, "interrupt-map", &sz); - vdev_intmap = prop->value; - vdev_num_intmap = sz / sizeof(struct vdev_intmap); - - prop = of_find_property(dp, "interrupt-map-mask", NULL); - vdev_intmask = prop->value; - - printk("%s: Virtual Device Bus devhandle[%x]\n", - dp->full_name, sun4v_vdev_devhandle); -} - -unsigned int sun4v_vdev_device_interrupt(struct device_node *dev_node) -{ - struct property *prop; - unsigned int irq, reg; - int i; - - prop = of_find_property(dev_node, "interrupts", NULL); - if (!prop) { - printk("VDEV: Cannot get \"interrupts\" " - "property for OBP node %s\n", - dev_node->full_name); - return 0; - } - irq = *(unsigned int *) prop->value; - - prop = of_find_property(dev_node, "reg", NULL); - if (!prop) { - printk("VDEV: Cannot get \"reg\" " - "property for OBP node %s\n", - dev_node->full_name); - return 0; - } - reg = *(unsigned int *) prop->value; - - for (i = 0; i < vdev_num_intmap; i++) { - if (vdev_intmap[i].phys == (reg & vdev_intmask->phys) && - vdev_intmap[i].irq == (irq & vdev_intmask->interrupt)) { - irq = vdev_intmap[i].cinterrupt; - break; - } - } - - if (i == vdev_num_intmap) { - printk("VDEV: No matching interrupt map entry " - "for OBP node %s\n", dev_node->full_name); - return 0; - } - - return sun4v_build_irq(sun4v_vdev_devhandle, irq); -} - static const char *cpu_mid_prop(void) { if (tlb_type == spitfire) @@ -289,7 +193,6 @@ void __init device_scan(void) } #endif - sun4v_virtual_device_probe(); central_probe(); cpu_probe(); diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index 3670dc8a7d5f..169b017eec0b 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -602,6 +602,9 @@ static void __init build_device_resources(struct of_device *op, build_res: memset(r, 0, sizeof(*r)); if (result != OF_BAD_ADDR) { + if (tlb_type == hypervisor) + result &= 0x0fffffffffffffffUL; + r->start = result; r->end = result + size - 1; r->flags = flags; diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index 8a70c52c0447..fa484d4f241e 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c @@ -1008,6 +1008,27 @@ static struct irq_trans pci_irq_trans_table[] = { }; #endif +static unsigned int sun4v_vdev_irq_build(struct device_node *dp, + unsigned int devino, + void *_data) +{ + u32 devhandle = (u32) (unsigned long) _data; + + return sun4v_build_irq(devhandle, devino); +} + +static void sun4v_vdev_irq_trans_init(struct device_node *dp) +{ + struct linux_prom64_registers *regs; + + dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller)); + dp->irq_trans->irq_build = sun4v_vdev_irq_build; + + regs = of_get_property(dp, "reg", NULL); + dp->irq_trans->data = (void *) (unsigned long) + ((regs->phys_addr >> 32UL) & 0x0fffffff); +} + static void irq_trans_init(struct device_node *dp) { const char *model; @@ -1034,6 +1055,8 @@ static void irq_trans_init(struct device_node *dp) #endif if (!strcmp(dp->name, "central")) return central_irq_trans_init(dp->child); + if (!strcmp(dp->name, "virtual-devices")) + return sun4v_vdev_irq_trans_init(dp); } static int is_root_node(const struct device_node *dp) |