diff options
Diffstat (limited to 'arch/sparc')
| -rw-r--r-- | arch/sparc/kernel/of_device.c | 2 | ||||
| -rw-r--r-- | arch/sparc/kernel/prom.c | 106 | ||||
| -rw-r--r-- | arch/sparc/lib/Makefile | 2 | ||||
| -rw-r--r-- | arch/sparc/lib/iomap.c | 48 |
4 files changed, 140 insertions, 18 deletions
diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c index 001b8673b4bd..80a809478781 100644 --- a/arch/sparc/kernel/of_device.c +++ b/arch/sparc/kernel/of_device.c | |||
| @@ -138,6 +138,7 @@ struct bus_type ebus_bus_type = { | |||
| 138 | .suspend = of_device_suspend, | 138 | .suspend = of_device_suspend, |
| 139 | .resume = of_device_resume, | 139 | .resume = of_device_resume, |
| 140 | }; | 140 | }; |
| 141 | EXPORT_SYMBOL(ebus_bus_type); | ||
| 141 | #endif | 142 | #endif |
| 142 | 143 | ||
| 143 | #ifdef CONFIG_SBUS | 144 | #ifdef CONFIG_SBUS |
| @@ -149,6 +150,7 @@ struct bus_type sbus_bus_type = { | |||
| 149 | .suspend = of_device_suspend, | 150 | .suspend = of_device_suspend, |
| 150 | .resume = of_device_resume, | 151 | .resume = of_device_resume, |
| 151 | }; | 152 | }; |
| 153 | EXPORT_SYMBOL(sbus_bus_type); | ||
| 152 | #endif | 154 | #endif |
| 153 | 155 | ||
| 154 | static int __init of_bus_driver_init(void) | 156 | static int __init of_bus_driver_init(void) |
diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c index 63b2b9bd778e..946ce6d15819 100644 --- a/arch/sparc/kernel/prom.c +++ b/arch/sparc/kernel/prom.c | |||
| @@ -27,6 +27,11 @@ | |||
| 27 | 27 | ||
| 28 | static struct device_node *allnodes; | 28 | static struct device_node *allnodes; |
| 29 | 29 | ||
| 30 | /* use when traversing tree through the allnext, child, sibling, | ||
| 31 | * or parent members of struct device_node. | ||
| 32 | */ | ||
| 33 | static DEFINE_RWLOCK(devtree_lock); | ||
| 34 | |||
| 30 | int of_device_is_compatible(struct device_node *device, const char *compat) | 35 | int of_device_is_compatible(struct device_node *device, const char *compat) |
| 31 | { | 36 | { |
| 32 | const char* cp; | 37 | const char* cp; |
| @@ -185,6 +190,54 @@ int of_getintprop_default(struct device_node *np, const char *name, int def) | |||
| 185 | } | 190 | } |
| 186 | EXPORT_SYMBOL(of_getintprop_default); | 191 | EXPORT_SYMBOL(of_getintprop_default); |
| 187 | 192 | ||
| 193 | int of_set_property(struct device_node *dp, const char *name, void *val, int len) | ||
| 194 | { | ||
| 195 | struct property **prevp; | ||
| 196 | void *new_val; | ||
| 197 | int err; | ||
| 198 | |||
| 199 | new_val = kmalloc(len, GFP_KERNEL); | ||
| 200 | if (!new_val) | ||
| 201 | return -ENOMEM; | ||
| 202 | |||
| 203 | memcpy(new_val, val, len); | ||
| 204 | |||
| 205 | err = -ENODEV; | ||
| 206 | |||
| 207 | write_lock(&devtree_lock); | ||
| 208 | prevp = &dp->properties; | ||
| 209 | while (*prevp) { | ||
| 210 | struct property *prop = *prevp; | ||
| 211 | |||
| 212 | if (!strcmp(prop->name, name)) { | ||
| 213 | void *old_val = prop->value; | ||
| 214 | int ret; | ||
| 215 | |||
| 216 | ret = prom_setprop(dp->node, name, val, len); | ||
| 217 | err = -EINVAL; | ||
| 218 | if (ret >= 0) { | ||
| 219 | prop->value = new_val; | ||
| 220 | prop->length = len; | ||
| 221 | |||
| 222 | if (OF_IS_DYNAMIC(prop)) | ||
| 223 | kfree(old_val); | ||
| 224 | |||
| 225 | OF_MARK_DYNAMIC(prop); | ||
| 226 | |||
| 227 | err = 0; | ||
| 228 | } | ||
| 229 | break; | ||
| 230 | } | ||
| 231 | prevp = &(*prevp)->next; | ||
| 232 | } | ||
| 233 | write_unlock(&devtree_lock); | ||
| 234 | |||
| 235 | /* XXX Upate procfs if necessary... */ | ||
| 236 | |||
| 237 | return err; | ||
| 238 | } | ||
| 239 | EXPORT_SYMBOL(of_set_property); | ||
| 240 | |||
| 188 | static unsigned int prom_early_allocated; | 241 | static unsigned int prom_early_allocated; |
| 189 | 242 | ||
| 190 | static void * __init prom_early_alloc(unsigned long size) | 243 | static void * __init prom_early_alloc(unsigned long size) |
| @@ -354,7 +407,9 @@ static char * __init build_full_name(struct device_node *dp) | |||
| 354 | return n; | 407 | return n; |
| 355 | } | 408 | } |
| 356 | 409 | ||
| 357 | static struct property * __init build_one_prop(phandle node, char *prev) | 410 | static unsigned int unique_id; |
| 411 | |||
| 412 | static struct property * __init build_one_prop(phandle node, char *prev, char *special_name, void *special_val, int special_len) | ||
| 358 | { | 413 | { |
| 359 | static struct property *tmp = NULL; | 414 | static struct property *tmp = NULL; |
| 360 | struct property *p; | 415 | struct property *p; |
| @@ -364,25 +419,34 @@ static struct property * __init build_one_prop(phandle node, char *prev) | |||
| 364 | p = tmp; | 419 | p = tmp; |
| 365 | memset(p, 0, sizeof(*p) + 32); | 420 | memset(p, 0, sizeof(*p) + 32); |
| 366 | tmp = NULL; | 421 | tmp = NULL; |
| 367 | } else | 422 | } else { |
| 368 | p = prom_early_alloc(sizeof(struct property) + 32); | 423 | p = prom_early_alloc(sizeof(struct property) + 32); |
| 424 | p->unique_id = unique_id++; | ||
| 425 | } | ||
| 369 | 426 | ||
| 370 | p->name = (char *) (p + 1); | 427 | p->name = (char *) (p + 1); |
| 371 | if (prev == NULL) { | 428 | if (special_name) { |
| 372 | prom_firstprop(node, p->name); | 429 | p->length = special_len; |
| 430 | p->value = prom_early_alloc(special_len); | ||
| 431 | memcpy(p->value, special_val, special_len); | ||
| 373 | } else { | 432 | } else { |
| 374 | prom_nextprop(node, prev, p->name); | 433 | if (prev == NULL) { |
| 375 | } | 434 | prom_firstprop(node, p->name); |
| 376 | if (strlen(p->name) == 0) { | 435 | } else { |
| 377 | tmp = p; | 436 | prom_nextprop(node, prev, p->name); |
| 378 | return NULL; | 437 | } |
| 379 | } | 438 | if (strlen(p->name) == 0) { |
| 380 | p->length = prom_getproplen(node, p->name); | 439 | tmp = p; |
| 381 | if (p->length <= 0) { | 440 | return NULL; |
| 382 | p->length = 0; | 441 | } |
| 383 | } else { | 442 | p->length = prom_getproplen(node, p->name); |
| 384 | p->value = prom_early_alloc(p->length); | 443 | if (p->length <= 0) { |
| 385 | len = prom_getproperty(node, p->name, p->value, p->length); | 444 | p->length = 0; |
| 445 | } else { | ||
| 446 | p->value = prom_early_alloc(p->length + 1); | ||
| 447 | prom_getproperty(node, p->name, p->value, p->length); | ||
| 448 | ((unsigned char *)p->value)[p->length] = '\0'; | ||
| 449 | } | ||
| 386 | } | 450 | } |
| 387 | return p; | 451 | return p; |
| 388 | } | 452 | } |
| @@ -391,9 +455,14 @@ static struct property * __init build_prop_list(phandle node) | |||
| 391 | { | 455 | { |
| 392 | struct property *head, *tail; | 456 | struct property *head, *tail; |
| 393 | 457 | ||
| 394 | head = tail = build_one_prop(node, NULL); | 458 | head = tail = build_one_prop(node, NULL, |
| 459 | ".node", &node, sizeof(node)); | ||
| 460 | |||
| 461 | tail->next = build_one_prop(node, NULL, NULL, NULL, 0); | ||
| 462 | tail = tail->next; | ||
| 395 | while(tail) { | 463 | while(tail) { |
| 396 | tail->next = build_one_prop(node, tail->name); | 464 | tail->next = build_one_prop(node, tail->name, |
| 465 | NULL, NULL, 0); | ||
| 397 | tail = tail->next; | 466 | tail = tail->next; |
| 398 | } | 467 | } |
| 399 | 468 | ||
| @@ -422,6 +491,7 @@ static struct device_node * __init create_node(phandle node) | |||
| 422 | return NULL; | 491 | return NULL; |
| 423 | 492 | ||
| 424 | dp = prom_early_alloc(sizeof(*dp)); | 493 | dp = prom_early_alloc(sizeof(*dp)); |
| 494 | dp->unique_id = unique_id++; | ||
| 425 | 495 | ||
| 426 | kref_init(&dp->kref); | 496 | kref_init(&dp->kref); |
| 427 | 497 | ||
diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile index fa5006946062..5db7e1d85385 100644 --- a/arch/sparc/lib/Makefile +++ b/arch/sparc/lib/Makefile | |||
| @@ -9,3 +9,5 @@ lib-y := mul.o rem.o sdiv.o udiv.o umul.o urem.o ashrdi3.o memcpy.o memset.o \ | |||
| 9 | strncpy_from_user.o divdi3.o udivdi3.o strlen_user.o \ | 9 | strncpy_from_user.o divdi3.o udivdi3.o strlen_user.o \ |
| 10 | copy_user.o locks.o atomic.o atomic32.o bitops.o \ | 10 | copy_user.o locks.o atomic.o atomic32.o bitops.o \ |
| 11 | lshrdi3.o ashldi3.o rwsem.o muldi3.o bitext.o | 11 | lshrdi3.o ashldi3.o rwsem.o muldi3.o bitext.o |
| 12 | |||
| 13 | obj-y += iomap.o | ||
diff --git a/arch/sparc/lib/iomap.c b/arch/sparc/lib/iomap.c new file mode 100644 index 000000000000..54501c1ca785 --- /dev/null +++ b/arch/sparc/lib/iomap.c | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | /* | ||
| 2 | * Implement the sparc iomap interfaces | ||
| 3 | */ | ||
| 4 | #include <linux/pci.h> | ||
| 5 | #include <linux/module.h> | ||
| 6 | #include <asm/io.h> | ||
| 7 | |||
| 8 | /* Create a virtual mapping cookie for an IO port range */ | ||
| 9 | void __iomem *ioport_map(unsigned long port, unsigned int nr) | ||
| 10 | { | ||
| 11 | return (void __iomem *) (unsigned long) port; | ||
| 12 | } | ||
| 13 | |||
| 14 | void ioport_unmap(void __iomem *addr) | ||
| 15 | { | ||
| 16 | /* Nothing to do */ | ||
| 17 | } | ||
| 18 | EXPORT_SYMBOL(ioport_map); | ||
| 19 | EXPORT_SYMBOL(ioport_unmap); | ||
| 20 | |||
| 21 | /* Create a virtual mapping cookie for a PCI BAR (memory or IO) */ | ||
| 22 | void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) | ||
| 23 | { | ||
| 24 | unsigned long start = pci_resource_start(dev, bar); | ||
| 25 | unsigned long len = pci_resource_len(dev, bar); | ||
| 26 | unsigned long flags = pci_resource_flags(dev, bar); | ||
| 27 | |||
| 28 | if (!len || !start) | ||
| 29 | return NULL; | ||
| 30 | if (maxlen && len > maxlen) | ||
| 31 | len = maxlen; | ||
| 32 | if (flags & IORESOURCE_IO) | ||
| 33 | return ioport_map(start, len); | ||
| 34 | if (flags & IORESOURCE_MEM) { | ||
| 35 | if (flags & IORESOURCE_CACHEABLE) | ||
| 36 | return ioremap(start, len); | ||
| 37 | return ioremap_nocache(start, len); | ||
| 38 | } | ||
| 39 | /* What? */ | ||
| 40 | return NULL; | ||
| 41 | } | ||
| 42 | |||
| 43 | void pci_iounmap(struct pci_dev *dev, void __iomem * addr) | ||
| 44 | { | ||
| 45 | /* nothing to do */ | ||
| 46 | } | ||
| 47 | EXPORT_SYMBOL(pci_iomap); | ||
| 48 | EXPORT_SYMBOL(pci_iounmap); | ||
