diff options
author | Stephen Warren <swarren@nvidia.com> | 2012-07-25 19:34:37 -0400 |
---|---|---|
committer | Rob Herring <rob.herring@calxeda.com> | 2012-08-03 09:01:46 -0400 |
commit | 5d61b165c892853f2daf6220d2ec6577487e273a (patch) | |
tree | 3bcff9b185383c768b702461c1194cb8eb9d0002 /drivers/of/address.c | |
parent | 0d7614f09c1ebdbaa1599a5aba7593f147bf96ee (diff) |
of: Allow busses with #size-cells=0
It's quite legitimate for a DT node to specify #size-cells=0. One example
is a node that's used to collect a number of non-memory-mapped devices.
In that scenario, there may be multiple child nodes with the same name
(type) thus necessitating the use of unit addresses in node names, and
reg properties:
/ {
regulators {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <0>;
regulator@0 {
compatible = "regulator-fixed";
reg = <0>;
...
};
regulator@1 {
compatible = "regulator-fixed";
reg = <1>;
...
};
...
};
};
However, #size-cells=0 prevents translation of reg property values into
the parent node's address space. In turn, this triggers the kernel to
emit error messages during boot, such as:
prom_parse: Bad cell count for /regulators/regulator@0
To prevent printing these error messages for legitimate DT content, a
number of changes are made:
1) of_get_address()/of_get_pci_address() are modified only to validate
the value of #address-cells, and not #size-cells.
2) of_can_translate_address() is added to indicate whether address
translation is possible.
3) of_device_make_bus_id() is modified to name devices based on the
translated address only where possible, and otherwise fall back to
using the (first cell of the) raw untranslated address.
4) of_device_alloc() is modified to create memory resources for a device
only if the address can be translated into the CPU's address space.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Diffstat (limited to 'drivers/of/address.c')
-rw-r--r-- | drivers/of/address.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/drivers/of/address.c b/drivers/of/address.c index 7e262a6124c5..7a07751428de 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, |
@@ -182,7 +182,7 @@ const __be32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size, | |||
182 | } | 182 | } |
183 | bus->count_cells(dev, &na, &ns); | 183 | bus->count_cells(dev, &na, &ns); |
184 | of_node_put(parent); | 184 | of_node_put(parent); |
185 | if (!OF_CHECK_COUNTS(na, ns)) | 185 | if (!OF_CHECK_ADDR_COUNT(na)) |
186 | return NULL; | 186 | return NULL; |
187 | 187 | ||
188 | /* Get "reg" or "assigned-addresses" property */ | 188 | /* Get "reg" or "assigned-addresses" property */ |
@@ -490,6 +490,25 @@ u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr) | |||
490 | } | 490 | } |
491 | EXPORT_SYMBOL(of_translate_dma_address); | 491 | EXPORT_SYMBOL(of_translate_dma_address); |
492 | 492 | ||
493 | bool of_can_translate_address(struct device_node *dev) | ||
494 | { | ||
495 | struct device_node *parent; | ||
496 | struct of_bus *bus; | ||
497 | int na, ns; | ||
498 | |||
499 | parent = of_get_parent(dev); | ||
500 | if (parent == NULL) | ||
501 | return false; | ||
502 | |||
503 | bus = of_match_bus(parent); | ||
504 | bus->count_cells(dev, &na, &ns); | ||
505 | |||
506 | of_node_put(parent); | ||
507 | |||
508 | return OF_CHECK_COUNTS(na, ns); | ||
509 | } | ||
510 | EXPORT_SYMBOL(of_can_translate_address); | ||
511 | |||
493 | const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, | 512 | const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, |
494 | unsigned int *flags) | 513 | unsigned int *flags) |
495 | { | 514 | { |
@@ -506,7 +525,7 @@ const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, | |||
506 | bus = of_match_bus(parent); | 525 | bus = of_match_bus(parent); |
507 | bus->count_cells(dev, &na, &ns); | 526 | bus->count_cells(dev, &na, &ns); |
508 | of_node_put(parent); | 527 | of_node_put(parent); |
509 | if (!OF_CHECK_COUNTS(na, ns)) | 528 | if (!OF_CHECK_ADDR_COUNT(na)) |
510 | return NULL; | 529 | return NULL; |
511 | 530 | ||
512 | /* Get "reg" or "assigned-addresses" property */ | 531 | /* Get "reg" or "assigned-addresses" property */ |