#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
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)
}
#endif
- sun4v_virtual_device_probe();
central_probe();
cpu_probe();
};
#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;
#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)