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:
committed by
Lorenzo Pieralisi
parent
9de0eec29c
commit
3a8f77e486
@@ -24,50 +24,6 @@
|
|||||||
#include <linux/pci-ecam.h>
|
#include <linux/pci-ecam.h>
|
||||||
#include <linux/platform_device.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)
|
static void gen_pci_unmap_cfg(void *ptr)
|
||||||
{
|
{
|
||||||
pci_ecam_free((struct pci_config_window *)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;
|
struct pci_config_window *cfg;
|
||||||
|
|
||||||
/* Parse our PCI ranges and request their resources */
|
/* 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)
|
if (err)
|
||||||
goto err_out;
|
return ERR_PTR(err);
|
||||||
|
|
||||||
err = of_address_to_resource(dev->of_node, 0, &cfgres);
|
err = of_address_to_resource(dev->of_node, 0, &cfgres);
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -135,7 +91,6 @@ int pci_host_common_probe(struct platform_device *pdev,
|
|||||||
of_pci_check_probe_only();
|
of_pci_check_probe_only();
|
||||||
|
|
||||||
/* Parse and map our Configuration Space windows */
|
/* Parse and map our Configuration Space windows */
|
||||||
INIT_LIST_HEAD(&resources);
|
|
||||||
cfg = gen_pci_init(dev, &resources, ops);
|
cfg = gen_pci_init(dev, &resources, ops);
|
||||||
if (IS_ERR(cfg))
|
if (IS_ERR(cfg))
|
||||||
return PTR_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;
|
return NULL;
|
||||||
#endif
|
#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_set_bus_of_node(struct pci_bus *bus);
|
||||||
void pci_release_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);
|
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) */
|
/* Arch may override this (weak) */
|
||||||
struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus);
|
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; }
|
pci_device_to_OF_node(const struct pci_dev *pdev) { return NULL; }
|
||||||
static inline struct irq_domain *
|
static inline struct irq_domain *
|
||||||
pci_host_bridge_of_msi_domain(struct pci_bus *bus) { return NULL; }
|
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 */
|
#endif /* CONFIG_OF */
|
||||||
|
|
||||||
#ifdef CONFIG_ACPI
|
#ifdef CONFIG_ACPI
|
||||||
|
|||||||
Reference in New Issue
Block a user