diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/of/address.c | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'drivers/of/address.c')
-rw-r--r-- | drivers/of/address.c | 76 |
1 files changed, 21 insertions, 55 deletions
diff --git a/drivers/of/address.c b/drivers/of/address.c index 0125524c08c..72c33fbe451 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c | |||
@@ -1,5 +1,4 @@ | |||
1 | 1 | ||
2 | #include <linux/device.h> | ||
3 | #include <linux/io.h> | 2 | #include <linux/io.h> |
4 | #include <linux/ioport.h> | 3 | #include <linux/ioport.h> |
5 | #include <linux/module.h> | 4 | #include <linux/module.h> |
@@ -9,13 +8,13 @@ | |||
9 | 8 | ||
10 | /* Max address size we deal with */ | 9 | /* Max address size we deal with */ |
11 | #define OF_MAX_ADDR_CELLS 4 | 10 | #define OF_MAX_ADDR_CELLS 4 |
12 | #define OF_CHECK_ADDR_COUNT(na) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS) | 11 | #define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \ |
13 | #define OF_CHECK_COUNTS(na, ns) (OF_CHECK_ADDR_COUNT(na) && (ns) > 0) | 12 | (ns) > 0) |
14 | 13 | ||
15 | static struct of_bus *of_match_bus(struct device_node *np); | 14 | static struct of_bus *of_match_bus(struct device_node *np); |
16 | static int __of_address_to_resource(struct device_node *dev, | 15 | static int __of_address_to_resource(struct device_node *dev, |
17 | const __be32 *addrp, u64 size, unsigned int flags, | 16 | const __be32 *addrp, u64 size, unsigned int flags, |
18 | const char *name, struct resource *r); | 17 | struct resource *r); |
19 | 18 | ||
20 | /* Debug utility */ | 19 | /* Debug utility */ |
21 | #ifdef DEBUG | 20 | #ifdef DEBUG |
@@ -37,9 +36,9 @@ struct of_bus { | |||
37 | int (*match)(struct device_node *parent); | 36 | int (*match)(struct device_node *parent); |
38 | void (*count_cells)(struct device_node *child, | 37 | void (*count_cells)(struct device_node *child, |
39 | int *addrc, int *sizec); | 38 | int *addrc, int *sizec); |
40 | u64 (*map)(__be32 *addr, const __be32 *range, | 39 | u64 (*map)(u32 *addr, const __be32 *range, |
41 | int na, int ns, int pna); | 40 | int na, int ns, int pna); |
42 | int (*translate)(__be32 *addr, u64 offset, int na); | 41 | int (*translate)(u32 *addr, u64 offset, int na); |
43 | unsigned int (*get_flags)(const __be32 *addr); | 42 | unsigned int (*get_flags)(const __be32 *addr); |
44 | }; | 43 | }; |
45 | 44 | ||
@@ -56,7 +55,7 @@ static void of_bus_default_count_cells(struct device_node *dev, | |||
56 | *sizec = of_n_size_cells(dev); | 55 | *sizec = of_n_size_cells(dev); |
57 | } | 56 | } |
58 | 57 | ||
59 | static u64 of_bus_default_map(__be32 *addr, const __be32 *range, | 58 | static u64 of_bus_default_map(u32 *addr, const __be32 *range, |
60 | int na, int ns, int pna) | 59 | int na, int ns, int pna) |
61 | { | 60 | { |
62 | u64 cp, s, da; | 61 | u64 cp, s, da; |
@@ -69,20 +68,12 @@ static u64 of_bus_default_map(__be32 *addr, const __be32 *range, | |||
69 | (unsigned long long)cp, (unsigned long long)s, | 68 | (unsigned long long)cp, (unsigned long long)s, |
70 | (unsigned long long)da); | 69 | (unsigned long long)da); |
71 | 70 | ||
72 | /* | ||
73 | * If the number of address cells is larger than 2 we assume the | ||
74 | * mapping doesn't specify a physical address. Rather, the address | ||
75 | * specifies an identifier that must match exactly. | ||
76 | */ | ||
77 | if (na > 2 && memcmp(range, addr, na * 4) != 0) | ||
78 | return OF_BAD_ADDR; | ||
79 | |||
80 | if (da < cp || da >= (cp + s)) | 71 | if (da < cp || da >= (cp + s)) |
81 | return OF_BAD_ADDR; | 72 | return OF_BAD_ADDR; |
82 | return da - cp; | 73 | return da - cp; |
83 | } | 74 | } |
84 | 75 | ||
85 | static int of_bus_default_translate(__be32 *addr, u64 offset, int na) | 76 | static int of_bus_default_translate(u32 *addr, u64 offset, int na) |
86 | { | 77 | { |
87 | u64 a = of_read_number(addr, na); | 78 | u64 a = of_read_number(addr, na); |
88 | memset(addr, 0, na * 4); | 79 | memset(addr, 0, na * 4); |
@@ -138,7 +129,7 @@ static unsigned int of_bus_pci_get_flags(const __be32 *addr) | |||
138 | return flags; | 129 | return flags; |
139 | } | 130 | } |
140 | 131 | ||
141 | static u64 of_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns, | 132 | static u64 of_bus_pci_map(u32 *addr, const __be32 *range, int na, int ns, |
142 | int pna) | 133 | int pna) |
143 | { | 134 | { |
144 | u64 cp, s, da; | 135 | u64 cp, s, da; |
@@ -165,7 +156,7 @@ static u64 of_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns, | |||
165 | return da - cp; | 156 | return da - cp; |
166 | } | 157 | } |
167 | 158 | ||
168 | static int of_bus_pci_translate(__be32 *addr, u64 offset, int na) | 159 | static int of_bus_pci_translate(u32 *addr, u64 offset, int na) |
169 | { | 160 | { |
170 | return of_bus_default_translate(addr + 1, offset, na - 1); | 161 | return of_bus_default_translate(addr + 1, offset, na - 1); |
171 | } | 162 | } |
@@ -190,7 +181,7 @@ const __be32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size, | |||
190 | } | 181 | } |
191 | bus->count_cells(dev, &na, &ns); | 182 | bus->count_cells(dev, &na, &ns); |
192 | of_node_put(parent); | 183 | of_node_put(parent); |
193 | if (!OF_CHECK_ADDR_COUNT(na)) | 184 | if (!OF_CHECK_COUNTS(na, ns)) |
194 | return NULL; | 185 | return NULL; |
195 | 186 | ||
196 | /* Get "reg" or "assigned-addresses" property */ | 187 | /* Get "reg" or "assigned-addresses" property */ |
@@ -224,7 +215,7 @@ int of_pci_address_to_resource(struct device_node *dev, int bar, | |||
224 | addrp = of_get_pci_address(dev, bar, &size, &flags); | 215 | addrp = of_get_pci_address(dev, bar, &size, &flags); |
225 | if (addrp == NULL) | 216 | if (addrp == NULL) |
226 | return -EINVAL; | 217 | return -EINVAL; |
227 | return __of_address_to_resource(dev, addrp, size, flags, NULL, r); | 218 | return __of_address_to_resource(dev, addrp, size, flags, r); |
228 | } | 219 | } |
229 | EXPORT_SYMBOL_GPL(of_pci_address_to_resource); | 220 | EXPORT_SYMBOL_GPL(of_pci_address_to_resource); |
230 | #endif /* CONFIG_PCI */ | 221 | #endif /* CONFIG_PCI */ |
@@ -247,7 +238,7 @@ static void of_bus_isa_count_cells(struct device_node *child, | |||
247 | *sizec = 1; | 238 | *sizec = 1; |
248 | } | 239 | } |
249 | 240 | ||
250 | static u64 of_bus_isa_map(__be32 *addr, const __be32 *range, int na, int ns, | 241 | static u64 of_bus_isa_map(u32 *addr, const __be32 *range, int na, int ns, |
251 | int pna) | 242 | int pna) |
252 | { | 243 | { |
253 | u64 cp, s, da; | 244 | u64 cp, s, da; |
@@ -270,7 +261,7 @@ static u64 of_bus_isa_map(__be32 *addr, const __be32 *range, int na, int ns, | |||
270 | return da - cp; | 261 | return da - cp; |
271 | } | 262 | } |
272 | 263 | ||
273 | static int of_bus_isa_translate(__be32 *addr, u64 offset, int na) | 264 | static int of_bus_isa_translate(u32 *addr, u64 offset, int na) |
274 | { | 265 | { |
275 | return of_bus_default_translate(addr + 1, offset, na - 1); | 266 | return of_bus_default_translate(addr + 1, offset, na - 1); |
276 | } | 267 | } |
@@ -338,7 +329,7 @@ static struct of_bus *of_match_bus(struct device_node *np) | |||
338 | } | 329 | } |
339 | 330 | ||
340 | static int of_translate_one(struct device_node *parent, struct of_bus *bus, | 331 | static int of_translate_one(struct device_node *parent, struct of_bus *bus, |
341 | struct of_bus *pbus, __be32 *addr, | 332 | struct of_bus *pbus, u32 *addr, |
342 | int na, int ns, int pna, const char *rprop) | 333 | int na, int ns, int pna, const char *rprop) |
343 | { | 334 | { |
344 | const __be32 *ranges; | 335 | const __be32 *ranges; |
@@ -409,12 +400,12 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus, | |||
409 | * that can be mapped to a cpu physical address). This is not really specified | 400 | * that can be mapped to a cpu physical address). This is not really specified |
410 | * that way, but this is traditionally the way IBM at least do things | 401 | * that way, but this is traditionally the way IBM at least do things |
411 | */ | 402 | */ |
412 | static u64 __of_translate_address(struct device_node *dev, | 403 | u64 __of_translate_address(struct device_node *dev, const __be32 *in_addr, |
413 | const __be32 *in_addr, const char *rprop) | 404 | const char *rprop) |
414 | { | 405 | { |
415 | struct device_node *parent = NULL; | 406 | struct device_node *parent = NULL; |
416 | struct of_bus *bus, *pbus; | 407 | struct of_bus *bus, *pbus; |
417 | __be32 addr[OF_MAX_ADDR_CELLS]; | 408 | u32 addr[OF_MAX_ADDR_CELLS]; |
418 | int na, ns, pna, pns; | 409 | int na, ns, pna, pns; |
419 | u64 result = OF_BAD_ADDR; | 410 | u64 result = OF_BAD_ADDR; |
420 | 411 | ||
@@ -498,25 +489,6 @@ u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr) | |||
498 | } | 489 | } |
499 | EXPORT_SYMBOL(of_translate_dma_address); | 490 | EXPORT_SYMBOL(of_translate_dma_address); |
500 | 491 | ||
501 | bool of_can_translate_address(struct device_node *dev) | ||
502 | { | ||
503 | struct device_node *parent; | ||
504 | struct of_bus *bus; | ||
505 | int na, ns; | ||
506 | |||
507 | parent = of_get_parent(dev); | ||
508 | if (parent == NULL) | ||
509 | return false; | ||
510 | |||
511 | bus = of_match_bus(parent); | ||
512 | bus->count_cells(dev, &na, &ns); | ||
513 | |||
514 | of_node_put(parent); | ||
515 | |||
516 | return OF_CHECK_COUNTS(na, ns); | ||
517 | } | ||
518 | EXPORT_SYMBOL(of_can_translate_address); | ||
519 | |||
520 | const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, | 492 | const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, |
521 | unsigned int *flags) | 493 | unsigned int *flags) |
522 | { | 494 | { |
@@ -533,7 +505,7 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, | |||
533 | bus = of_match_bus(parent); | 505 | bus = of_match_bus(parent); |
534 | bus->count_cells(dev, &na, &ns); | 506 | bus->count_cells(dev, &na, &ns); |
535 | of_node_put(parent); | 507 | of_node_put(parent); |
536 | if (!OF_CHECK_ADDR_COUNT(na)) | 508 | if (!OF_CHECK_COUNTS(na, ns)) |
537 | return NULL; | 509 | return NULL; |
538 | 510 | ||
539 | /* Get "reg" or "assigned-addresses" property */ | 511 | /* Get "reg" or "assigned-addresses" property */ |
@@ -557,7 +529,7 @@ EXPORT_SYMBOL(of_get_address); | |||
557 | 529 | ||
558 | static int __of_address_to_resource(struct device_node *dev, | 530 | static int __of_address_to_resource(struct device_node *dev, |
559 | const __be32 *addrp, u64 size, unsigned int flags, | 531 | const __be32 *addrp, u64 size, unsigned int flags, |
560 | const char *name, struct resource *r) | 532 | struct resource *r) |
561 | { | 533 | { |
562 | u64 taddr; | 534 | u64 taddr; |
563 | 535 | ||
@@ -579,8 +551,7 @@ static int __of_address_to_resource(struct device_node *dev, | |||
579 | r->end = taddr + size - 1; | 551 | r->end = taddr + size - 1; |
580 | } | 552 | } |
581 | r->flags = flags; | 553 | r->flags = flags; |
582 | r->name = name ? name : dev->full_name; | 554 | r->name = dev->full_name; |
583 | |||
584 | return 0; | 555 | return 0; |
585 | } | 556 | } |
586 | 557 | ||
@@ -598,16 +569,11 @@ int of_address_to_resource(struct device_node *dev, int index, | |||
598 | const __be32 *addrp; | 569 | const __be32 *addrp; |
599 | u64 size; | 570 | u64 size; |
600 | unsigned int flags; | 571 | unsigned int flags; |
601 | const char *name = NULL; | ||
602 | 572 | ||
603 | addrp = of_get_address(dev, index, &size, &flags); | 573 | addrp = of_get_address(dev, index, &size, &flags); |
604 | if (addrp == NULL) | 574 | if (addrp == NULL) |
605 | return -EINVAL; | 575 | return -EINVAL; |
606 | 576 | return __of_address_to_resource(dev, addrp, size, flags, r); | |
607 | /* Get optional "reg-names" property to add a name to a resource */ | ||
608 | of_property_read_string_index(dev, "reg-names", index, &name); | ||
609 | |||
610 | return __of_address_to_resource(dev, addrp, size, flags, name, r); | ||
611 | } | 577 | } |
612 | EXPORT_SYMBOL_GPL(of_address_to_resource); | 578 | EXPORT_SYMBOL_GPL(of_address_to_resource); |
613 | 579 | ||