diff options
Diffstat (limited to 'drivers/of/address.c')
-rw-r--r-- | drivers/of/address.c | 35 |
1 files changed, 31 insertions, 4 deletions
diff --git a/drivers/of/address.c b/drivers/of/address.c index 7e262a6124c5..72e496f1e9b0 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c | |||
@@ -9,8 +9,8 @@ | |||
9 | 9 | ||
10 | /* Max address size we deal with */ | 10 | /* Max address size we deal with */ |
11 | #define OF_MAX_ADDR_CELLS 4 | 11 | #define OF_MAX_ADDR_CELLS 4 |
12 | #define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \ | 12 | #define OF_CHECK_ADDR_COUNT(na) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS) |
13 | (ns) > 0) | 13 | #define OF_CHECK_COUNTS(na, ns) (OF_CHECK_ADDR_COUNT(na) && (ns) > 0) |
14 | 14 | ||
15 | static struct of_bus *of_match_bus(struct device_node *np); | 15 | static struct of_bus *of_match_bus(struct device_node *np); |
16 | static int __of_address_to_resource(struct device_node *dev, | 16 | static int __of_address_to_resource(struct device_node *dev, |
@@ -69,6 +69,14 @@ static u64 of_bus_default_map(u32 *addr, const __be32 *range, | |||
69 | (unsigned long long)cp, (unsigned long long)s, | 69 | (unsigned long long)cp, (unsigned long long)s, |
70 | (unsigned long long)da); | 70 | (unsigned long long)da); |
71 | 71 | ||
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 | |||
72 | if (da < cp || da >= (cp + s)) | 80 | if (da < cp || da >= (cp + s)) |
73 | return OF_BAD_ADDR; | 81 | return OF_BAD_ADDR; |
74 | return da - cp; | 82 | return da - cp; |
@@ -182,7 +190,7 @@ const __be32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size, | |||
182 | } | 190 | } |
183 | bus->count_cells(dev, &na, &ns); | 191 | bus->count_cells(dev, &na, &ns); |
184 | of_node_put(parent); | 192 | of_node_put(parent); |
185 | if (!OF_CHECK_COUNTS(na, ns)) | 193 | if (!OF_CHECK_ADDR_COUNT(na)) |
186 | return NULL; | 194 | return NULL; |
187 | 195 | ||
188 | /* Get "reg" or "assigned-addresses" property */ | 196 | /* Get "reg" or "assigned-addresses" property */ |
@@ -490,6 +498,25 @@ u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr) | |||
490 | } | 498 | } |
491 | EXPORT_SYMBOL(of_translate_dma_address); | 499 | EXPORT_SYMBOL(of_translate_dma_address); |
492 | 500 | ||
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 | |||
493 | const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, | 520 | const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, |
494 | unsigned int *flags) | 521 | unsigned int *flags) |
495 | { | 522 | { |
@@ -506,7 +533,7 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, | |||
506 | bus = of_match_bus(parent); | 533 | bus = of_match_bus(parent); |
507 | bus->count_cells(dev, &na, &ns); | 534 | bus->count_cells(dev, &na, &ns); |
508 | of_node_put(parent); | 535 | of_node_put(parent); |
509 | if (!OF_CHECK_COUNTS(na, ns)) | 536 | if (!OF_CHECK_ADDR_COUNT(na)) |
510 | return NULL; | 537 | return NULL; |
511 | 538 | ||
512 | /* Get "reg" or "assigned-addresses" property */ | 539 | /* Get "reg" or "assigned-addresses" property */ |