linux/drivers/of/of_pci.c
<<
>>
Prefs
   1#include <linux/kernel.h>
   2#include <linux/export.h>
   3#include <linux/of.h>
   4#include <linux/of_address.h>
   5#include <linux/of_pci.h>
   6#include <linux/slab.h>
   7
   8static inline int __of_pci_pci_compare(struct device_node *node,
   9                                       unsigned int data)
  10{
  11        int devfn;
  12
  13        devfn = of_pci_get_devfn(node);
  14        if (devfn < 0)
  15                return 0;
  16
  17        return devfn == data;
  18}
  19
  20struct device_node *of_pci_find_child_device(struct device_node *parent,
  21                                             unsigned int devfn)
  22{
  23        struct device_node *node, *node2;
  24
  25        for_each_child_of_node(parent, node) {
  26                if (__of_pci_pci_compare(node, devfn))
  27                        return node;
  28                /*
  29                 * Some OFs create a parent node "multifunc-device" as
  30                 * a fake root for all functions of a multi-function
  31                 * device we go down them as well.
  32                 */
  33                if (!strcmp(node->name, "multifunc-device")) {
  34                        for_each_child_of_node(node, node2) {
  35                                if (__of_pci_pci_compare(node2, devfn)) {
  36                                        of_node_put(node);
  37                                        return node2;
  38                                }
  39                        }
  40                }
  41        }
  42        return NULL;
  43}
  44EXPORT_SYMBOL_GPL(of_pci_find_child_device);
  45
  46/**
  47 * of_pci_get_devfn() - Get device and function numbers for a device node
  48 * @np: device node
  49 *
  50 * Parses a standard 5-cell PCI resource and returns an 8-bit value that can
  51 * be passed to the PCI_SLOT() and PCI_FUNC() macros to extract the device
  52 * and function numbers respectively. On error a negative error code is
  53 * returned.
  54 */
  55int of_pci_get_devfn(struct device_node *np)
  56{
  57        unsigned int size;
  58        const __be32 *reg;
  59
  60        reg = of_get_property(np, "reg", &size);
  61
  62        if (!reg || size < 5 * sizeof(__be32))
  63                return -EINVAL;
  64
  65        return (be32_to_cpup(reg) >> 8) & 0xff;
  66}
  67EXPORT_SYMBOL_GPL(of_pci_get_devfn);
  68
  69/**
  70 * of_pci_parse_bus_range() - parse the bus-range property of a PCI device
  71 * @node: device node
  72 * @res: address to a struct resource to return the bus-range
  73 *
  74 * Returns 0 on success or a negative error-code on failure.
  75 */
  76int of_pci_parse_bus_range(struct device_node *node, struct resource *res)
  77{
  78        const __be32 *values;
  79        int len;
  80
  81        values = of_get_property(node, "bus-range", &len);
  82        if (!values || len < sizeof(*values) * 2)
  83                return -EINVAL;
  84
  85        res->name = node->name;
  86        res->start = be32_to_cpup(values++);
  87        res->end = be32_to_cpup(values);
  88        res->flags = IORESOURCE_BUS;
  89
  90        return 0;
  91}
  92EXPORT_SYMBOL_GPL(of_pci_parse_bus_range);
  93
  94/**
  95 * This function will try to obtain the host bridge domain number by
  96 * finding a property called "linux,pci-domain" of the given device node.
  97 *
  98 * @node: device tree node with the domain information
  99 *
 100 * Returns the associated domain number from DT in the range [0-0xffff], or
 101 * a negative value if the required property is not found.
 102 */
 103int of_get_pci_domain_nr(struct device_node *node)
 104{
 105        const __be32 *value;
 106        int len;
 107        u16 domain;
 108
 109        value = of_get_property(node, "linux,pci-domain", &len);
 110        if (!value || len < sizeof(*value))
 111                return -EINVAL;
 112
 113        domain = (u16)be32_to_cpup(value);
 114
 115        return domain;
 116}
 117EXPORT_SYMBOL_GPL(of_get_pci_domain_nr);
 118
 119#if defined(CONFIG_OF_ADDRESS)
 120/**
 121 * of_pci_get_host_bridge_resources - Parse PCI host bridge resources from DT
 122 * @dev: device node of the host bridge having the range property
 123 * @busno: bus number associated with the bridge root bus
 124 * @bus_max: maximum number of buses for this bridge
 125 * @resources: list where the range of resources will be added after DT parsing
 126 * @io_base: pointer to a variable that will contain on return the physical
 127 * address for the start of the I/O range. Can be NULL if the caller doesn't
 128 * expect IO ranges to be present in the device tree.
 129 *
 130 * It is the caller's job to free the @resources list.
 131 *
 132 * This function will parse the "ranges" property of a PCI host bridge device
 133 * node and setup the resource mapping based on its content. It is expected
 134 * that the property conforms with the Power ePAPR document.
 135 *
 136 * It returns zero if the range parsing has been successful or a standard error
 137 * value if it failed.
 138 */
 139int of_pci_get_host_bridge_resources(struct device_node *dev,
 140                        unsigned char busno, unsigned char bus_max,
 141                        struct list_head *resources, resource_size_t *io_base)
 142{
 143        struct resource *res;
 144        struct resource *bus_range;
 145        struct of_pci_range range;
 146        struct of_pci_range_parser parser;
 147        char range_type[4];
 148        int err;
 149
 150        if (io_base)
 151                *io_base = (resource_size_t)OF_BAD_ADDR;
 152
 153        bus_range = kzalloc(sizeof(*bus_range), GFP_KERNEL);
 154        if (!bus_range)
 155                return -ENOMEM;
 156
 157        pr_info("PCI host bridge %s ranges:\n", dev->full_name);
 158
 159        err = of_pci_parse_bus_range(dev, bus_range);
 160        if (err) {
 161                bus_range->start = busno;
 162                bus_range->end = bus_max;
 163                bus_range->flags = IORESOURCE_BUS;
 164                pr_info("  No bus range found for %s, using %pR\n",
 165                        dev->full_name, bus_range);
 166        } else {
 167                if (bus_range->end > bus_range->start + bus_max)
 168                        bus_range->end = bus_range->start + bus_max;
 169        }
 170        pci_add_resource(resources, bus_range);
 171
 172        /* Check for ranges property */
 173        err = of_pci_range_parser_init(&parser, dev);
 174        if (err)
 175                goto parse_failed;
 176
 177        pr_debug("Parsing ranges property...\n");
 178        for_each_of_pci_range(&parser, &range) {
 179                /* Read next ranges element */
 180                if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_IO)
 181                        snprintf(range_type, 4, " IO");
 182                else if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_MEM)
 183                        snprintf(range_type, 4, "MEM");
 184                else
 185                        snprintf(range_type, 4, "err");
 186                pr_info("  %s %#010llx..%#010llx -> %#010llx\n", range_type,
 187                        range.cpu_addr, range.cpu_addr + range.size - 1,
 188                        range.pci_addr);
 189
 190                /*
 191                 * If we failed translation or got a zero-sized region
 192                 * then skip this range
 193                 */
 194                if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)
 195                        continue;
 196
 197                res = kzalloc(sizeof(struct resource), GFP_KERNEL);
 198                if (!res) {
 199                        err = -ENOMEM;
 200                        goto parse_failed;
 201                }
 202
 203                err = of_pci_range_to_resource(&range, dev, res);
 204                if (err)
 205                        goto conversion_failed;
 206
 207                if (resource_type(res) == IORESOURCE_IO) {
 208                        if (!io_base) {
 209                                pr_err("I/O range found for %s. Please provide an io_base pointer to save CPU base address\n",
 210                                        dev->full_name);
 211                                err = -EINVAL;
 212                                goto conversion_failed;
 213                        }
 214                        if (*io_base != (resource_size_t)OF_BAD_ADDR)
 215                                pr_warn("More than one I/O resource converted for %s. CPU base address for old range lost!\n",
 216                                        dev->full_name);
 217                        *io_base = range.cpu_addr;
 218                }
 219
 220                pci_add_resource_offset(resources, res, res->start - range.pci_addr);
 221        }
 222
 223        return 0;
 224
 225conversion_failed:
 226        kfree(res);
 227parse_failed:
 228        pci_free_resource_list(resources);
 229        return err;
 230}
 231EXPORT_SYMBOL_GPL(of_pci_get_host_bridge_resources);
 232#endif /* CONFIG_OF_ADDRESS */
 233
 234#ifdef CONFIG_PCI_MSI
 235
 236static LIST_HEAD(of_pci_msi_chip_list);
 237static DEFINE_MUTEX(of_pci_msi_chip_mutex);
 238
 239int of_pci_msi_chip_add(struct msi_controller *chip)
 240{
 241        if (!of_property_read_bool(chip->of_node, "msi-controller"))
 242                return -EINVAL;
 243
 244        mutex_lock(&of_pci_msi_chip_mutex);
 245        list_add(&chip->list, &of_pci_msi_chip_list);
 246        mutex_unlock(&of_pci_msi_chip_mutex);
 247
 248        return 0;
 249}
 250EXPORT_SYMBOL_GPL(of_pci_msi_chip_add);
 251
 252void of_pci_msi_chip_remove(struct msi_controller *chip)
 253{
 254        mutex_lock(&of_pci_msi_chip_mutex);
 255        list_del(&chip->list);
 256        mutex_unlock(&of_pci_msi_chip_mutex);
 257}
 258EXPORT_SYMBOL_GPL(of_pci_msi_chip_remove);
 259
 260struct msi_controller *of_pci_find_msi_chip_by_node(struct device_node *of_node)
 261{
 262        struct msi_controller *c;
 263
 264        mutex_lock(&of_pci_msi_chip_mutex);
 265        list_for_each_entry(c, &of_pci_msi_chip_list, list) {
 266                if (c->of_node == of_node) {
 267                        mutex_unlock(&of_pci_msi_chip_mutex);
 268                        return c;
 269                }
 270        }
 271        mutex_unlock(&of_pci_msi_chip_mutex);
 272
 273        return NULL;
 274}
 275EXPORT_SYMBOL_GPL(of_pci_find_msi_chip_by_node);
 276
 277#endif /* CONFIG_PCI_MSI */
 278