diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2006-06-22 01:56:20 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-06-24 02:15:13 -0400 |
commit | 6760d28bc691bb255c501c9b680f2fc1162258b2 (patch) | |
tree | 8c6a249a56fc2a2eee995dbcb55daf4adf456705 /arch | |
parent | 27cc64c7cc9e41788e53655c717aeca2f55f2041 (diff) |
[SPARC64]: Convert sun4v virtual-device layer to in-kernel PROM device tree.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sparc64/kernel/devices.c | 104 |
1 files changed, 35 insertions, 69 deletions
diff --git a/arch/sparc64/kernel/devices.c b/arch/sparc64/kernel/devices.c index 0dd95ae50e12..136f872a8a57 100644 --- a/arch/sparc64/kernel/devices.c +++ b/arch/sparc64/kernel/devices.c | |||
@@ -33,7 +33,7 @@ extern void cpu_probe(void); | |||
33 | extern void central_probe(void); | 33 | extern void central_probe(void); |
34 | 34 | ||
35 | u32 sun4v_vdev_devhandle; | 35 | u32 sun4v_vdev_devhandle; |
36 | int sun4v_vdev_root; | 36 | struct device_node *sun4v_vdev_root; |
37 | 37 | ||
38 | struct vdev_intmap { | 38 | struct vdev_intmap { |
39 | unsigned int phys; | 39 | unsigned int phys; |
@@ -50,102 +50,68 @@ struct vdev_intmask { | |||
50 | 50 | ||
51 | static struct vdev_intmap *vdev_intmap; | 51 | static struct vdev_intmap *vdev_intmap; |
52 | static int vdev_num_intmap; | 52 | static int vdev_num_intmap; |
53 | static struct vdev_intmask vdev_intmask; | 53 | static struct vdev_intmask *vdev_intmask; |
54 | 54 | ||
55 | static void __init sun4v_virtual_device_probe(void) | 55 | static void __init sun4v_virtual_device_probe(void) |
56 | { | 56 | { |
57 | struct linux_prom64_registers regs; | 57 | struct linux_prom64_registers *regs; |
58 | struct vdev_intmap *ip; | 58 | struct property *prop; |
59 | int node, sz, err; | 59 | struct device_node *dp; |
60 | int sz; | ||
60 | 61 | ||
61 | if (tlb_type != hypervisor) | 62 | if (tlb_type != hypervisor) |
62 | return; | 63 | return; |
63 | 64 | ||
64 | node = prom_getchild(prom_root_node); | 65 | dp = of_find_node_by_name(NULL, "virtual-devices"); |
65 | node = prom_searchsiblings(node, "virtual-devices"); | 66 | if (!dp) { |
66 | if (!node) { | ||
67 | prom_printf("SUN4V: Fatal error, no virtual-devices node.\n"); | 67 | prom_printf("SUN4V: Fatal error, no virtual-devices node.\n"); |
68 | prom_halt(); | 68 | prom_halt(); |
69 | } | 69 | } |
70 | 70 | ||
71 | sun4v_vdev_root = node; | 71 | sun4v_vdev_root = dp; |
72 | 72 | ||
73 | prom_getproperty(node, "reg", (char *)®s, sizeof(regs)); | 73 | prop = of_find_property(dp, "reg", NULL); |
74 | sun4v_vdev_devhandle = (regs.phys_addr >> 32UL) & 0x0fffffff; | 74 | regs = prop->value; |
75 | sun4v_vdev_devhandle = (regs[0].phys_addr >> 32UL) & 0x0fffffff; | ||
75 | 76 | ||
76 | sz = prom_getproplen(node, "interrupt-map"); | 77 | prop = of_find_property(dp, "interrupt-map", &sz); |
77 | if (sz <= 0) { | 78 | vdev_intmap = prop->value; |
78 | prom_printf("SUN4V: Error, no vdev interrupt-map.\n"); | 79 | vdev_num_intmap = sz / sizeof(struct vdev_intmap); |
79 | prom_halt(); | ||
80 | } | ||
81 | |||
82 | if ((sz % sizeof(*ip)) != 0) { | ||
83 | prom_printf("SUN4V: Bogus interrupt-map property size %d\n", | ||
84 | sz); | ||
85 | prom_halt(); | ||
86 | } | ||
87 | |||
88 | vdev_intmap = ip = alloc_bootmem_low_pages(sz); | ||
89 | if (!vdev_intmap) { | ||
90 | prom_printf("SUN4V: Error, cannot allocate vdev_intmap.\n"); | ||
91 | prom_halt(); | ||
92 | } | ||
93 | |||
94 | err = prom_getproperty(node, "interrupt-map", (char *) ip, sz); | ||
95 | if (err == -1) { | ||
96 | prom_printf("SUN4V: Fatal error, no vdev interrupt-map.\n"); | ||
97 | prom_halt(); | ||
98 | } | ||
99 | if (err != sz) { | ||
100 | prom_printf("SUN4V: Inconsistent interrupt-map size, " | ||
101 | "proplen(%d) vs getprop(%d).\n", sz,err); | ||
102 | prom_halt(); | ||
103 | } | ||
104 | |||
105 | vdev_num_intmap = err / sizeof(*ip); | ||
106 | 80 | ||
107 | err = prom_getproperty(node, "interrupt-map-mask", | 81 | prop = of_find_property(dp, "interrupt-map-mask", NULL); |
108 | (char *) &vdev_intmask, | 82 | vdev_intmask = prop->value; |
109 | sizeof(vdev_intmask)); | ||
110 | if (err <= 0) { | ||
111 | prom_printf("SUN4V: Fatal error, no vdev " | ||
112 | "interrupt-map-mask.\n"); | ||
113 | prom_halt(); | ||
114 | } | ||
115 | if (err % sizeof(vdev_intmask)) { | ||
116 | prom_printf("SUN4V: Bogus interrupt-map-mask " | ||
117 | "property size %d\n", err); | ||
118 | prom_halt(); | ||
119 | } | ||
120 | 83 | ||
121 | printk("SUN4V: virtual-devices devhandle[%x]\n", | 84 | printk("%s: Virtual Device Bus devhandle[%x]\n", |
122 | sun4v_vdev_devhandle); | 85 | dp->full_name, sun4v_vdev_devhandle); |
123 | } | 86 | } |
124 | 87 | ||
125 | unsigned int sun4v_vdev_device_interrupt(unsigned int dev_node) | 88 | unsigned int sun4v_vdev_device_interrupt(struct device_node *dev_node) |
126 | { | 89 | { |
90 | struct property *prop; | ||
127 | unsigned int irq, reg; | 91 | unsigned int irq, reg; |
128 | int err, i; | 92 | int i; |
129 | 93 | ||
130 | err = prom_getproperty(dev_node, "interrupts", | 94 | prop = of_find_property(dev_node, "interrupts", NULL); |
131 | (char *) &irq, sizeof(irq)); | 95 | if (!prop) { |
132 | if (err <= 0) { | ||
133 | printk("VDEV: Cannot get \"interrupts\" " | 96 | printk("VDEV: Cannot get \"interrupts\" " |
134 | "property for OBP node %x\n", dev_node); | 97 | "property for OBP node %s\n", |
98 | dev_node->full_name); | ||
135 | return 0; | 99 | return 0; |
136 | } | 100 | } |
101 | irq = *(unsigned int *) prop->value; | ||
137 | 102 | ||
138 | err = prom_getproperty(dev_node, "reg", | 103 | prop = of_find_property(dev_node, "reg", NULL); |
139 | (char *) ®, sizeof(reg)); | 104 | if (!prop) { |
140 | if (err <= 0) { | ||
141 | printk("VDEV: Cannot get \"reg\" " | 105 | printk("VDEV: Cannot get \"reg\" " |
142 | "property for OBP node %x\n", dev_node); | 106 | "property for OBP node %s\n", |
107 | dev_node->full_name); | ||
143 | return 0; | 108 | return 0; |
144 | } | 109 | } |
110 | reg = *(unsigned int *) prop->value; | ||
145 | 111 | ||
146 | for (i = 0; i < vdev_num_intmap; i++) { | 112 | for (i = 0; i < vdev_num_intmap; i++) { |
147 | if (vdev_intmap[i].phys == (reg & vdev_intmask.phys) && | 113 | if (vdev_intmap[i].phys == (reg & vdev_intmask->phys) && |
148 | vdev_intmap[i].irq == (irq & vdev_intmask.interrupt)) { | 114 | vdev_intmap[i].irq == (irq & vdev_intmask->interrupt)) { |
149 | irq = vdev_intmap[i].cinterrupt; | 115 | irq = vdev_intmap[i].cinterrupt; |
150 | break; | 116 | break; |
151 | } | 117 | } |
@@ -153,7 +119,7 @@ unsigned int sun4v_vdev_device_interrupt(unsigned int dev_node) | |||
153 | 119 | ||
154 | if (i == vdev_num_intmap) { | 120 | if (i == vdev_num_intmap) { |
155 | printk("VDEV: No matching interrupt map entry " | 121 | printk("VDEV: No matching interrupt map entry " |
156 | "for OBP node %x\n", dev_node); | 122 | "for OBP node %s\n", dev_node->full_name); |
157 | return 0; | 123 | return 0; |
158 | } | 124 | } |
159 | 125 | ||