Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'of_pci-3.11' of git://git.infradead.org/users/jcooper/linux into next/cleanup

From Jason Cooper, of/pci changes for v3.11.

The patches had Reviewed-by: from Rob Herring on the lists, but seems to
have been missed from the commit messages. These will be required as a base
for some of the other functionality in this merge window, so taking it through
arm-soc.

Signed-off-by: Olof Johansson <olof@lixom.net>

* tag 'of_pci-3.11' of git://git.infradead.org/users/jcooper/linux:
of/pci: Add of_pci_parse_bus_range() function
of/pci: Add of_pci_get_devfn() function
of/pci: Provide support for parsing PCI DT ranges property

+171 -5
+67
drivers/of/address.c
··· 227 227 return __of_address_to_resource(dev, addrp, size, flags, NULL, r); 228 228 } 229 229 EXPORT_SYMBOL_GPL(of_pci_address_to_resource); 230 + 231 + int of_pci_range_parser_init(struct of_pci_range_parser *parser, 232 + struct device_node *node) 233 + { 234 + const int na = 3, ns = 2; 235 + int rlen; 236 + 237 + parser->node = node; 238 + parser->pna = of_n_addr_cells(node); 239 + parser->np = parser->pna + na + ns; 240 + 241 + parser->range = of_get_property(node, "ranges", &rlen); 242 + if (parser->range == NULL) 243 + return -ENOENT; 244 + 245 + parser->end = parser->range + rlen / sizeof(__be32); 246 + 247 + return 0; 248 + } 249 + EXPORT_SYMBOL_GPL(of_pci_range_parser_init); 250 + 251 + struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser, 252 + struct of_pci_range *range) 253 + { 254 + const int na = 3, ns = 2; 255 + 256 + if (!range) 257 + return NULL; 258 + 259 + if (!parser->range || parser->range + parser->np > parser->end) 260 + return NULL; 261 + 262 + range->pci_space = parser->range[0]; 263 + range->flags = of_bus_pci_get_flags(parser->range); 264 + range->pci_addr = of_read_number(parser->range + 1, ns); 265 + range->cpu_addr = of_translate_address(parser->node, 266 + parser->range + na); 267 + range->size = of_read_number(parser->range + parser->pna + na, ns); 268 + 269 + parser->range += parser->np; 270 + 271 + /* Now consume following elements while they are contiguous */ 272 + while (parser->range + parser->np <= parser->end) { 273 + u32 flags, pci_space; 274 + u64 pci_addr, cpu_addr, size; 275 + 276 + pci_space = be32_to_cpup(parser->range); 277 + flags = of_bus_pci_get_flags(parser->range); 278 + pci_addr = of_read_number(parser->range + 1, ns); 279 + cpu_addr = of_translate_address(parser->node, 280 + parser->range + na); 281 + size = of_read_number(parser->range + parser->pna + na, ns); 282 + 283 + if (flags != range->flags) 284 + break; 285 + if (pci_addr != range->pci_addr + range->size || 286 + cpu_addr != range->cpu_addr + range->size) 287 + break; 288 + 289 + range->size += size; 290 + parser->range += parser->np; 291 + } 292 + 293 + return range; 294 + } 295 + EXPORT_SYMBOL_GPL(of_pci_range_parser_one); 296 + 230 297 #endif /* CONFIG_PCI */ 231 298 232 299 /*
+54 -5
drivers/of/of_pci.c
··· 5 5 #include <asm/prom.h> 6 6 7 7 static inline int __of_pci_pci_compare(struct device_node *node, 8 - unsigned int devfn) 8 + unsigned int data) 9 9 { 10 - unsigned int size; 11 - const __be32 *reg = of_get_property(node, "reg", &size); 10 + int devfn; 12 11 13 - if (!reg || size < 5 * sizeof(__be32)) 12 + devfn = of_pci_get_devfn(node); 13 + if (devfn < 0) 14 14 return 0; 15 - return ((be32_to_cpup(&reg[0]) >> 8) & 0xff) == devfn; 15 + 16 + return devfn == data; 16 17 } 17 18 18 19 struct device_node *of_pci_find_child_device(struct device_node *parent, ··· 41 40 return NULL; 42 41 } 43 42 EXPORT_SYMBOL_GPL(of_pci_find_child_device); 43 + 44 + /** 45 + * of_pci_get_devfn() - Get device and function numbers for a device node 46 + * @np: device node 47 + * 48 + * Parses a standard 5-cell PCI resource and returns an 8-bit value that can 49 + * be passed to the PCI_SLOT() and PCI_FUNC() macros to extract the device 50 + * and function numbers respectively. On error a negative error code is 51 + * returned. 52 + */ 53 + int of_pci_get_devfn(struct device_node *np) 54 + { 55 + unsigned int size; 56 + const __be32 *reg; 57 + 58 + reg = of_get_property(np, "reg", &size); 59 + 60 + if (!reg || size < 5 * sizeof(__be32)) 61 + return -EINVAL; 62 + 63 + return (be32_to_cpup(reg) >> 8) & 0xff; 64 + } 65 + EXPORT_SYMBOL_GPL(of_pci_get_devfn); 66 + 67 + /** 68 + * of_pci_parse_bus_range() - parse the bus-range property of a PCI device 69 + * @node: device node 70 + * @res: address to a struct resource to return the bus-range 71 + * 72 + * Returns 0 on success or a negative error-code on failure. 73 + */ 74 + int of_pci_parse_bus_range(struct device_node *node, struct resource *res) 75 + { 76 + const __be32 *values; 77 + int len; 78 + 79 + values = of_get_property(node, "bus-range", &len); 80 + if (!values || len < sizeof(*values) * 2) 81 + return -EINVAL; 82 + 83 + res->name = node->name; 84 + res->start = be32_to_cpup(values++); 85 + res->end = be32_to_cpup(values); 86 + res->flags = IORESOURCE_BUS; 87 + 88 + return 0; 89 + } 90 + EXPORT_SYMBOL_GPL(of_pci_parse_bus_range);
+48
include/linux/of_address.h
··· 4 4 #include <linux/errno.h> 5 5 #include <linux/of.h> 6 6 7 + struct of_pci_range_parser { 8 + struct device_node *node; 9 + const __be32 *range; 10 + const __be32 *end; 11 + int np; 12 + int pna; 13 + }; 14 + 15 + struct of_pci_range { 16 + u32 pci_space; 17 + u64 pci_addr; 18 + u64 cpu_addr; 19 + u64 size; 20 + u32 flags; 21 + }; 22 + 23 + #define for_each_of_pci_range(parser, range) \ 24 + for (; of_pci_range_parser_one(parser, range);) 25 + 26 + static inline void of_pci_range_to_resource(struct of_pci_range *range, 27 + struct device_node *np, 28 + struct resource *res) 29 + { 30 + res->flags = range->flags; 31 + res->start = range->cpu_addr; 32 + res->end = range->cpu_addr + range->size - 1; 33 + res->parent = res->child = res->sibling = NULL; 34 + res->name = np->full_name; 35 + } 36 + 7 37 #ifdef CONFIG_OF_ADDRESS 8 38 extern u64 of_translate_address(struct device_node *np, const __be32 *addr); 9 39 extern bool of_can_translate_address(struct device_node *dev); ··· 57 27 #define pci_address_to_pio pci_address_to_pio 58 28 #endif 59 29 30 + extern int of_pci_range_parser_init(struct of_pci_range_parser *parser, 31 + struct device_node *node); 32 + extern struct of_pci_range *of_pci_range_parser_one( 33 + struct of_pci_range_parser *parser, 34 + struct of_pci_range *range); 60 35 #else /* CONFIG_OF_ADDRESS */ 61 36 #ifndef of_address_to_resource 62 37 static inline int of_address_to_resource(struct device_node *dev, int index, ··· 85 50 #endif 86 51 static inline const __be32 *of_get_address(struct device_node *dev, int index, 87 52 u64 *size, unsigned int *flags) 53 + { 54 + return NULL; 55 + } 56 + 57 + static inline int of_pci_range_parser_init(struct of_pci_range_parser *parser, 58 + struct device_node *node) 59 + { 60 + return -1; 61 + } 62 + 63 + static inline struct of_pci_range *of_pci_range_parser_one( 64 + struct of_pci_range_parser *parser, 65 + struct of_pci_range *range) 88 66 { 89 67 return NULL; 90 68 }
+2
include/linux/of_pci.h
··· 10 10 struct device_node; 11 11 struct device_node *of_pci_find_child_device(struct device_node *parent, 12 12 unsigned int devfn); 13 + int of_pci_get_devfn(struct device_node *np); 14 + int of_pci_parse_bus_range(struct device_node *node, struct resource *res); 13 15 14 16 #endif