2015-11-09 10:26:48

by Phil Edworthy

[permalink] [raw]
Subject: [PATCH 1/3 v2] PCI: pcie-rcar: Convert to DT resource parsing API

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 passing
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
dbf9826d "PCI: generic: Convert to DT resource parsing API".

Signed-off-by: Phil Edworthy <[email protected]>
---
v2:
- Remove incorrect res_valid check
---
drivers/pci/host/pcie-rcar.c | 116 +++++++++++++++++++++++++++----------------
1 file changed, 73 insertions(+), 43 deletions(-)

diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
index 6a3a612..c977fa6 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/host/pcie-rcar.c
@@ -108,8 +108,6 @@
#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;
--
1.9.1


2015-11-10 00:46:27

by Simon Horman

[permalink] [raw]
Subject: Re: [PATCH 1/3 v2] PCI: pcie-rcar: Convert to DT resource parsing API

On Mon, Nov 09, 2015 at 10:26:39AM +0000, Phil Edworthy wrote:
> 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 passing
> 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
> dbf9826d "PCI: generic: Convert to DT resource parsing API".
>
> Signed-off-by: Phil Edworthy <[email protected]>

I think the following should be carried over from v1:

Reported-by: Wolfram Sang <[email protected]>
Tested-by: Wolfram Sang <[email protected]>

Bjorn, I know there have been a few false starts with regards
to recent pcie-rcar changes. But some more rigor has been applied to this
one. Please consider applying it.

Acked-by: Simon Horman <[email protected]>

> ---
> v2:
> - Remove incorrect res_valid check
> ---
> drivers/pci/host/pcie-rcar.c | 116 +++++++++++++++++++++++++++----------------
> 1 file changed, 73 insertions(+), 43 deletions(-)
>
> diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
> index 6a3a612..c977fa6 100644
> --- a/drivers/pci/host/pcie-rcar.c
> +++ b/drivers/pci/host/pcie-rcar.c
> @@ -108,8 +108,6 @@
> #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;
> --
> 1.9.1
>