diff options
| author | David S. Miller <davem@sunset.davemloft.net> | 2006-06-21 21:18:47 -0400 |
|---|---|---|
| committer | David S. Miller <davem@sunset.davemloft.net> | 2006-06-24 02:15:07 -0400 |
| commit | e87dc35020bc555969810452f44bceaf8394eafa (patch) | |
| tree | b58f14d41f8e147f6ddc2d9657a88813fdb73bdf /arch/sparc64/kernel/pci.c | |
| parent | aaf7cec2769942035985716452107fc5ba0b11f6 (diff) | |
[SPARC64]: Use in-kernel OBP device tree for PCI controller probing.
It can be pushed even further down, but this is a first step.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/pci.c')
| -rw-r--r-- | arch/sparc64/kernel/pci.c | 53 |
1 files changed, 25 insertions, 28 deletions
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 9472580a4319..a868c3792efb 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <asm/irq.h> | 22 | #include <asm/irq.h> |
| 23 | #include <asm/ebus.h> | 23 | #include <asm/ebus.h> |
| 24 | #include <asm/isa.h> | 24 | #include <asm/isa.h> |
| 25 | #include <asm/prom.h> | ||
| 25 | 26 | ||
| 26 | unsigned long pci_memspace_mask = 0xffffffffUL; | 27 | unsigned long pci_memspace_mask = 0xffffffffUL; |
| 27 | 28 | ||
| @@ -177,16 +178,16 @@ void pci_config_write32(u32 *addr, u32 val) | |||
| 177 | } | 178 | } |
| 178 | 179 | ||
| 179 | /* Probe for all PCI controllers in the system. */ | 180 | /* Probe for all PCI controllers in the system. */ |
| 180 | extern void sabre_init(int, char *); | 181 | extern void sabre_init(struct device_node *, const char *); |
| 181 | extern void psycho_init(int, char *); | 182 | extern void psycho_init(struct device_node *, const char *); |
| 182 | extern void schizo_init(int, char *); | 183 | extern void schizo_init(struct device_node *, const char *); |
| 183 | extern void schizo_plus_init(int, char *); | 184 | extern void schizo_plus_init(struct device_node *, const char *); |
| 184 | extern void tomatillo_init(int, char *); | 185 | extern void tomatillo_init(struct device_node *, const char *); |
| 185 | extern void sun4v_pci_init(int, char *); | 186 | extern void sun4v_pci_init(struct device_node *, const char *); |
| 186 | 187 | ||
| 187 | static struct { | 188 | static struct { |
| 188 | char *model_name; | 189 | char *model_name; |
| 189 | void (*init)(int, char *); | 190 | void (*init)(struct device_node *, const char *); |
| 190 | } pci_controller_table[] __initdata = { | 191 | } pci_controller_table[] __initdata = { |
| 191 | { "SUNW,sabre", sabre_init }, | 192 | { "SUNW,sabre", sabre_init }, |
| 192 | { "pci108e,a000", sabre_init }, | 193 | { "pci108e,a000", sabre_init }, |
| @@ -204,7 +205,7 @@ static struct { | |||
| 204 | #define PCI_NUM_CONTROLLER_TYPES (sizeof(pci_controller_table) / \ | 205 | #define PCI_NUM_CONTROLLER_TYPES (sizeof(pci_controller_table) / \ |
| 205 | sizeof(pci_controller_table[0])) | 206 | sizeof(pci_controller_table[0])) |
| 206 | 207 | ||
| 207 | static int __init pci_controller_init(char *model_name, int namelen, int node) | 208 | static int __init pci_controller_init(const char *model_name, int namelen, struct device_node *dp) |
| 208 | { | 209 | { |
| 209 | int i; | 210 | int i; |
| 210 | 211 | ||
| @@ -212,18 +213,15 @@ static int __init pci_controller_init(char *model_name, int namelen, int node) | |||
| 212 | if (!strncmp(model_name, | 213 | if (!strncmp(model_name, |
| 213 | pci_controller_table[i].model_name, | 214 | pci_controller_table[i].model_name, |
| 214 | namelen)) { | 215 | namelen)) { |
| 215 | pci_controller_table[i].init(node, model_name); | 216 | pci_controller_table[i].init(dp, model_name); |
| 216 | return 1; | 217 | return 1; |
| 217 | } | 218 | } |
| 218 | } | 219 | } |
| 219 | printk("PCI: Warning unknown controller, model name [%s]\n", | ||
| 220 | model_name); | ||
| 221 | printk("PCI: Ignoring controller...\n"); | ||
| 222 | 220 | ||
| 223 | return 0; | 221 | return 0; |
| 224 | } | 222 | } |
| 225 | 223 | ||
| 226 | static int __init pci_is_controller(char *model_name, int namelen, int node) | 224 | static int __init pci_is_controller(const char *model_name, int namelen, struct device_node *dp) |
| 227 | { | 225 | { |
| 228 | int i; | 226 | int i; |
| 229 | 227 | ||
| @@ -237,36 +235,35 @@ static int __init pci_is_controller(char *model_name, int namelen, int node) | |||
| 237 | return 0; | 235 | return 0; |
| 238 | } | 236 | } |
| 239 | 237 | ||
| 240 | static int __init pci_controller_scan(int (*handler)(char *, int, int)) | 238 | static int __init pci_controller_scan(int (*handler)(const char *, int, struct device_node *)) |
| 241 | { | 239 | { |
| 242 | char namebuf[64]; | 240 | struct device_node *dp; |
| 243 | int node; | ||
| 244 | int count = 0; | 241 | int count = 0; |
| 245 | 242 | ||
| 246 | node = prom_getchild(prom_root_node); | 243 | for_each_node_by_name(dp, "pci") { |
| 247 | while ((node = prom_searchsiblings(node, "pci")) != 0) { | 244 | struct property *prop; |
| 248 | int len; | 245 | int len; |
| 249 | 246 | ||
| 250 | if ((len = prom_getproperty(node, "model", namebuf, sizeof(namebuf))) > 0 || | 247 | prop = of_find_property(dp, "model", &len); |
| 251 | (len = prom_getproperty(node, "compatible", namebuf, sizeof(namebuf))) > 0) { | 248 | if (!prop) |
| 249 | prop = of_find_property(dp, "compatible", &len); | ||
| 250 | |||
| 251 | if (prop) { | ||
| 252 | const char *model = prop->value; | ||
| 252 | int item_len = 0; | 253 | int item_len = 0; |
| 253 | 254 | ||
| 254 | /* Our value may be a multi-valued string in the | 255 | /* Our value may be a multi-valued string in the |
| 255 | * case of some compatible properties. For sanity, | 256 | * case of some compatible properties. For sanity, |
| 256 | * only try the first one. */ | 257 | * only try the first one. |
| 257 | 258 | */ | |
| 258 | while (namebuf[item_len] && len) { | 259 | while (model[item_len] && len) { |
| 259 | len--; | 260 | len--; |
| 260 | item_len++; | 261 | item_len++; |
| 261 | } | 262 | } |
| 262 | 263 | ||
| 263 | if (handler(namebuf, item_len, node)) | 264 | if (handler(model, item_len, dp)) |
| 264 | count++; | 265 | count++; |
| 265 | } | 266 | } |
| 266 | |||
| 267 | node = prom_getsibling(node); | ||
| 268 | if (!node) | ||
| 269 | break; | ||
| 270 | } | 267 | } |
| 271 | 268 | ||
| 272 | return count; | 269 | return count; |
