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 | |
parent | 27cc64c7cc9e41788e53655c717aeca2f55f2041 (diff) |
[SPARC64]: Convert sun4v virtual-device layer to in-kernel PROM device tree.
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | arch/sparc64/kernel/devices.c | 104 | ||||
-rw-r--r-- | drivers/serial/sunhv.c | 35 | ||||
-rw-r--r-- | include/asm-sparc64/vdev.h | 5 |
3 files changed, 56 insertions, 88 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 | ||
diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index f137804b3133..ba22e256c6f7 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c | |||
@@ -427,31 +427,32 @@ static int __init hv_console_compatible(char *buf, int len) | |||
427 | 427 | ||
428 | static unsigned int __init get_interrupt(void) | 428 | static unsigned int __init get_interrupt(void) |
429 | { | 429 | { |
430 | const char *cons_str = "console"; | 430 | struct device_node *dev_node; |
431 | const char *compat_str = "compatible"; | ||
432 | int node = prom_getchild(sun4v_vdev_root); | ||
433 | char buf[64]; | ||
434 | int err, len; | ||
435 | |||
436 | node = prom_searchsiblings(node, cons_str); | ||
437 | if (!node) | ||
438 | return 0; | ||
439 | 431 | ||
440 | len = prom_getproplen(node, compat_str); | 432 | dev_node = sun4v_vdev_root->child; |
441 | if (len == 0 || len == -1) | 433 | while (dev_node != NULL) { |
442 | return 0; | 434 | struct property *prop; |
443 | 435 | ||
444 | err = prom_getproperty(node, compat_str, buf, 64); | 436 | if (strcmp(dev_node->name, "console")) |
445 | if (err == -1) | 437 | goto next_sibling; |
446 | return 0; | 438 | |
439 | prop = of_find_property(dev_node, "compatible", NULL); | ||
440 | if (!prop) | ||
441 | goto next_sibling; | ||
447 | 442 | ||
448 | if (!hv_console_compatible(buf, len)) | 443 | if (hv_console_compatible(prop->value, prop->length)) |
444 | break; | ||
445 | |||
446 | next_sibling: | ||
447 | dev_node = dev_node->sibling; | ||
448 | } | ||
449 | if (!dev_node) | ||
449 | return 0; | 450 | return 0; |
450 | 451 | ||
451 | /* Ok, the this is the OBP node for the sun4v hypervisor | 452 | /* Ok, the this is the OBP node for the sun4v hypervisor |
452 | * console device. Decode the interrupt. | 453 | * console device. Decode the interrupt. |
453 | */ | 454 | */ |
454 | return sun4v_vdev_device_interrupt(node); | 455 | return sun4v_vdev_device_interrupt(dev_node); |
455 | } | 456 | } |
456 | 457 | ||
457 | static int __init sunhv_init(void) | 458 | static int __init sunhv_init(void) |
diff --git a/include/asm-sparc64/vdev.h b/include/asm-sparc64/vdev.h index 996e6be7b976..25637c57675d 100644 --- a/include/asm-sparc64/vdev.h +++ b/include/asm-sparc64/vdev.h | |||
@@ -7,10 +7,11 @@ | |||
7 | #define _SPARC64_VDEV_H | 7 | #define _SPARC64_VDEV_H |
8 | 8 | ||
9 | #include <linux/types.h> | 9 | #include <linux/types.h> |
10 | #include <asm/prom.h> | ||
10 | 11 | ||
11 | extern u32 sun4v_vdev_devhandle; | 12 | extern u32 sun4v_vdev_devhandle; |
12 | extern int sun4v_vdev_root; | 13 | extern struct device_node *sun4v_vdev_root; |
13 | 14 | ||
14 | extern unsigned int sun4v_vdev_device_interrupt(unsigned int); | 15 | extern unsigned int sun4v_vdev_device_interrupt(struct device_node *dev_node); |
15 | 16 | ||
16 | #endif /* !(_SPARC64_VDEV_H) */ | 17 | #endif /* !(_SPARC64_VDEV_H) */ |