PCI: rcar: Convert to DT resource parsing API
authorPhil Edworthy <phil.edworthy@renesas.com>
Wed, 25 Nov 2015 15:30:37 +0000 (15:30 +0000)
committerBjorn Helgaas <bhelgaas@google.com>
Tue, 8 Dec 2015 20:38:33 +0000 (14:38 -0600)
The main purpose of this change is to avoid calling pci_ioremap_io() as
this is not available on arm64.  However, instead of doing the range
parsing in this driver we can utilise of_pci_get_host_bridge_resources().

This is similar to changes made to the generic PCI host driver in commit
dbf9826d5797 ("PCI: generic: Convert to DT resource parsing API")

Reported-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Tested-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Signed-off-by: Phil Edworthy <phil.edworthy@renesas.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Simon Horman <horms+renesas@verge.net.au>
drivers/pci/host/pcie-rcar.c

index f4fa6c537448cae9d25519a8697e212aa70facaa..d12faf40d7a176b69861707ad91023a9ff0d6505 100644 (file)
 #define RCAR_PCI_MAX_RESOURCES 4
 #define MAX_NR_INBOUND_MAPS 6
 
-static unsigned long global_io_offset;
-
 struct rcar_msi {
        DECLARE_BITMAP(used, INT_PCI_MSI_NR);
        struct irq_domain *domain;
@@ -138,8 +136,7 @@ struct rcar_pcie {
 #endif
        struct device           *dev;
        void __iomem            *base;
-       struct resource         res[RCAR_PCI_MAX_RESOURCES];
-       struct resource         busn;
+       struct list_head        resources;
        int                     root_bus_nr;
        struct clk              *clk;
        struct clk              *bus_clk;
@@ -323,10 +320,9 @@ static struct pci_ops rcar_pcie_ops = {
        .write  = rcar_pcie_write_conf,
 };
 
-static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
+static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie,
+                                  struct resource *res)
 {
-       struct resource *res = &pcie->res[win];
-
        /* Setup PCIe address space mappings for each resource */
        resource_size_t size;
        resource_size_t res_start;
@@ -359,31 +355,33 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie)
        rcar_pci_write_reg(pcie, mask, PCIEPTCTLR(win));
 }
 
-static int rcar_pcie_setup(struct list_head *resource, struct rcar_pcie *pcie)
+static int rcar_pcie_setup(struct list_head *resource, struct rcar_pcie *pci)
 {
-       struct resource *res;
-       int i;
-
-       pcie->root_bus_nr = pcie->busn.start;
+       struct resource_entry *win;
+       int i = 0;
 
        /* Setup PCI resources */
-       for (i = 0; i < RCAR_PCI_MAX_RESOURCES; i++) {
+       resource_list_for_each_entry(win, &pci->resources) {
+               struct resource *res = win->res;
 
-               res = &pcie->res[i];
                if (!res->flags)
                        continue;
 
-               rcar_pcie_setup_window(i, pcie);
-
-               if (res->flags & IORESOURCE_IO) {
-                       phys_addr_t io_start = pci_pio_to_address(res->start);
-                       pci_ioremap_io(global_io_offset, io_start);
-                       global_io_offset += SZ_64K;
+               switch (resource_type(res)) {
+               case IORESOURCE_IO:
+               case IORESOURCE_MEM:
+                       rcar_pcie_setup_window(i, pci, res);
+                       i++;
+                       break;
+               case IORESOURCE_BUS:
+                       pci->root_bus_nr = res->start;
+                       break;
+               default:
+                       continue;
                }
 
                pci_add_resource(resource, res);
        }
-       pci_add_resource(resource, &pcie->busn);
 
        return 1;
 }
@@ -923,14 +921,63 @@ static const struct of_device_id rcar_pcie_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, rcar_pcie_of_match);
 
+static void rcar_pcie_release_of_pci_ranges(struct rcar_pcie *pci)
+{
+       pci_free_resource_list(&pci->resources);
+}
+
+static int rcar_pcie_parse_request_of_pci_ranges(struct rcar_pcie *pci)
+{
+       int err;
+       struct device *dev = pci->dev;
+       struct device_node *np = dev->of_node;
+       resource_size_t iobase;
+       struct resource_entry *win;
+
+       err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pci->resources, &iobase);
+       if (err)
+               return err;
+
+       resource_list_for_each_entry(win, &pci->resources) {
+               struct resource *parent, *res = win->res;
+
+               switch (resource_type(res)) {
+               case IORESOURCE_IO:
+                       parent = &ioport_resource;
+                       err = pci_remap_iospace(res, iobase);
+                       if (err) {
+                               dev_warn(dev, "error %d: failed to map resource %pR\n",
+                                        err, res);
+                               continue;
+                       }
+                       break;
+               case IORESOURCE_MEM:
+                       parent = &iomem_resource;
+                       break;
+
+               case IORESOURCE_BUS:
+               default:
+                       continue;
+               }
+
+               err = devm_request_resource(dev, parent, res);
+               if (err)
+                       goto out_release_res;
+       }
+
+       return 0;
+
+out_release_res:
+       rcar_pcie_release_of_pci_ranges(pci);
+       return err;
+}
+
 static int rcar_pcie_probe(struct platform_device *pdev)
 {
        struct rcar_pcie *pcie;
        unsigned int data;
-       struct of_pci_range range;
-       struct of_pci_range_parser parser;
        const struct of_device_id *of_id;
-       int err, win = 0;
+       int err;
        int (*hw_init_fn)(struct rcar_pcie *);
 
        pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL);
@@ -940,16 +987,9 @@ static int rcar_pcie_probe(struct platform_device *pdev)
        pcie->dev = &pdev->dev;
        platform_set_drvdata(pdev, pcie);
 
-       /* Get the bus range */
-       if (of_pci_parse_bus_range(pdev->dev.of_node, &pcie->busn)) {
-               dev_err(&pdev->dev, "failed to parse bus-range property\n");
-               return -EINVAL;
-       }
+       INIT_LIST_HEAD(&pcie->resources);
 
-       if (of_pci_range_parser_init(&parser, pdev->dev.of_node)) {
-               dev_err(&pdev->dev, "missing ranges property\n");
-               return -EINVAL;
-       }
+       rcar_pcie_parse_request_of_pci_ranges(pcie);
 
        err = rcar_pcie_get_resources(pdev, pcie);
        if (err < 0) {
@@ -957,16 +997,6 @@ static int rcar_pcie_probe(struct platform_device *pdev)
                return err;
        }
 
-       for_each_of_pci_range(&parser, &range) {
-               err = of_pci_range_to_resource(&range, pdev->dev.of_node,
-                                               &pcie->res[win++]);
-               if (err < 0)
-                       return err;
-
-               if (win > RCAR_PCI_MAX_RESOURCES)
-                       break;
-       }
-
         err = rcar_pcie_parse_map_dma_ranges(pcie, pdev->dev.of_node);
         if (err)
                return err;