aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/of/address.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/of/address.c')
-rw-r--r--drivers/of/address.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 9e69b4f0d204..3c4b2af51611 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -223,6 +223,73 @@ int of_pci_address_to_resource(struct device_node *dev, int bar,
223 return __of_address_to_resource(dev, addrp, size, flags, NULL, r); 223 return __of_address_to_resource(dev, addrp, size, flags, NULL, r);
224} 224}
225EXPORT_SYMBOL_GPL(of_pci_address_to_resource); 225EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
226
227int of_pci_range_parser_init(struct of_pci_range_parser *parser,
228 struct device_node *node)
229{
230 const int na = 3, ns = 2;
231 int rlen;
232
233 parser->node = node;
234 parser->pna = of_n_addr_cells(node);
235 parser->np = parser->pna + na + ns;
236
237 parser->range = of_get_property(node, "ranges", &rlen);
238 if (parser->range == NULL)
239 return -ENOENT;
240
241 parser->end = parser->range + rlen / sizeof(__be32);
242
243 return 0;
244}
245EXPORT_SYMBOL_GPL(of_pci_range_parser_init);
246
247struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
248 struct of_pci_range *range)
249{
250 const int na = 3, ns = 2;
251
252 if (!range)
253 return NULL;
254
255 if (!parser->range || parser->range + parser->np > parser->end)
256 return NULL;
257
258 range->pci_space = parser->range[0];
259 range->flags = of_bus_pci_get_flags(parser->range);
260 range->pci_addr = of_read_number(parser->range + 1, ns);
261 range->cpu_addr = of_translate_address(parser->node,
262 parser->range + na);
263 range->size = of_read_number(parser->range + parser->pna + na, ns);
264
265 parser->range += parser->np;
266
267 /* Now consume following elements while they are contiguous */
268 while (parser->range + parser->np <= parser->end) {
269 u32 flags, pci_space;
270 u64 pci_addr, cpu_addr, size;
271
272 pci_space = be32_to_cpup(parser->range);
273 flags = of_bus_pci_get_flags(parser->range);
274 pci_addr = of_read_number(parser->range + 1, ns);
275 cpu_addr = of_translate_address(parser->node,
276 parser->range + na);
277 size = of_read_number(parser->range + parser->pna + na, ns);
278
279 if (flags != range->flags)
280 break;
281 if (pci_addr != range->pci_addr + range->size ||
282 cpu_addr != range->cpu_addr + range->size)
283 break;
284
285 range->size += size;
286 parser->range += parser->np;
287 }
288
289 return range;
290}
291EXPORT_SYMBOL_GPL(of_pci_range_parser_one);
292
226#endif /* CONFIG_PCI */ 293#endif /* CONFIG_PCI */
227 294
228/* 295/*