PCI: OF: Add generic function to parse and allocate PCI resources
The patch moves the gen_pci_parse_request_of_pci_ranges() function from drivers/pci/host/pci-host-common.c into drivers/pci/of.c to easily share common source code between PCI host drivers. Signed-off-by: Cyrille Pitchen <cyrille.pitchen@free-electrons.com> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
This commit is contained in:
parent
9de0eec29c
commit
3a8f77e486
|
@ -24,50 +24,6 @@
|
|||
#include <linux/pci-ecam.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
static int gen_pci_parse_request_of_pci_ranges(struct device *dev,
|
||||
struct list_head *resources, struct resource **bus_range)
|
||||
{
|
||||
int err, res_valid = 0;
|
||||
struct device_node *np = dev->of_node;
|
||||
resource_size_t iobase;
|
||||
struct resource_entry *win, *tmp;
|
||||
|
||||
err = of_pci_get_host_bridge_resources(np, 0, 0xff, resources, &iobase);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = devm_request_pci_bus_resources(dev, resources);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
resource_list_for_each_entry_safe(win, tmp, resources) {
|
||||
struct resource *res = win->res;
|
||||
|
||||
switch (resource_type(res)) {
|
||||
case IORESOURCE_IO:
|
||||
err = pci_remap_iospace(res, iobase);
|
||||
if (err) {
|
||||
dev_warn(dev, "error %d: failed to map resource %pR\n",
|
||||
err, res);
|
||||
resource_list_destroy_entry(win);
|
||||
}
|
||||
break;
|
||||
case IORESOURCE_MEM:
|
||||
res_valid |= !(res->flags & IORESOURCE_PREFETCH);
|
||||
break;
|
||||
case IORESOURCE_BUS:
|
||||
*bus_range = res;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (res_valid)
|
||||
return 0;
|
||||
|
||||
dev_err(dev, "non-prefetchable memory resource required\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void gen_pci_unmap_cfg(void *ptr)
|
||||
{
|
||||
pci_ecam_free((struct pci_config_window *)ptr);
|
||||
|
@ -82,9 +38,9 @@ static struct pci_config_window *gen_pci_init(struct device *dev,
|
|||
struct pci_config_window *cfg;
|
||||
|
||||
/* Parse our PCI ranges and request their resources */
|
||||
err = gen_pci_parse_request_of_pci_ranges(dev, resources, &bus_range);
|
||||
err = pci_parse_request_of_pci_ranges(dev, resources, &bus_range);
|
||||
if (err)
|
||||
goto err_out;
|
||||
return ERR_PTR(err);
|
||||
|
||||
err = of_address_to_resource(dev->of_node, 0, &cfgres);
|
||||
if (err) {
|
||||
|
@ -135,7 +91,6 @@ int pci_host_common_probe(struct platform_device *pdev,
|
|||
of_pci_check_probe_only();
|
||||
|
||||
/* Parse and map our Configuration Space windows */
|
||||
INIT_LIST_HEAD(&resources);
|
||||
cfg = gen_pci_init(dev, &resources, ops);
|
||||
if (IS_ERR(cfg))
|
||||
return PTR_ERR(cfg);
|
||||
|
|
|
@ -88,3 +88,54 @@ struct irq_domain *pci_host_bridge_of_msi_domain(struct pci_bus *bus)
|
|||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
int pci_parse_request_of_pci_ranges(struct device *dev,
|
||||
struct list_head *resources,
|
||||
struct resource **bus_range)
|
||||
{
|
||||
int err, res_valid = 0;
|
||||
struct device_node *np = dev->of_node;
|
||||
resource_size_t iobase;
|
||||
struct resource_entry *win, *tmp;
|
||||
|
||||
INIT_LIST_HEAD(resources);
|
||||
err = of_pci_get_host_bridge_resources(np, 0, 0xff, resources, &iobase);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = devm_request_pci_bus_resources(dev, resources);
|
||||
if (err)
|
||||
goto out_release_res;
|
||||
|
||||
resource_list_for_each_entry_safe(win, tmp, resources) {
|
||||
struct resource *res = win->res;
|
||||
|
||||
switch (resource_type(res)) {
|
||||
case IORESOURCE_IO:
|
||||
err = pci_remap_iospace(res, iobase);
|
||||
if (err) {
|
||||
dev_warn(dev, "error %d: failed to map resource %pR\n",
|
||||
err, res);
|
||||
resource_list_destroy_entry(win);
|
||||
}
|
||||
break;
|
||||
case IORESOURCE_MEM:
|
||||
res_valid |= !(res->flags & IORESOURCE_PREFETCH);
|
||||
break;
|
||||
case IORESOURCE_BUS:
|
||||
if (bus_range)
|
||||
*bus_range = res;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (res_valid)
|
||||
return 0;
|
||||
|
||||
dev_err(dev, "non-prefetchable memory resource required\n");
|
||||
err = -EINVAL;
|
||||
|
||||
out_release_res:
|
||||
pci_free_resource_list(resources);
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -2182,6 +2182,9 @@ void pci_release_of_node(struct pci_dev *dev);
|
|||
void pci_set_bus_of_node(struct pci_bus *bus);
|
||||
void pci_release_bus_of_node(struct pci_bus *bus);
|
||||
struct irq_domain *pci_host_bridge_of_msi_domain(struct pci_bus *bus);
|
||||
int pci_parse_request_of_pci_ranges(struct device *dev,
|
||||
struct list_head *resources,
|
||||
struct resource **bus_range);
|
||||
|
||||
/* Arch may override this (weak) */
|
||||
struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus);
|
||||
|
@ -2206,6 +2209,12 @@ static inline struct device_node *
|
|||
pci_device_to_OF_node(const struct pci_dev *pdev) { return NULL; }
|
||||
static inline struct irq_domain *
|
||||
pci_host_bridge_of_msi_domain(struct pci_bus *bus) { return NULL; }
|
||||
static inline int pci_parse_request_of_pci_ranges(struct device *dev,
|
||||
struct list_head *resources,
|
||||
struct resource **bus_range)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
|
|
Loading…
Reference in New Issue