diff mbox

[1/3,v2] PCI: pcie-rcar: Convert to DT resource parsing API

Message ID PS1PR06MB11801A23491F06B6BE81DB6AF5150@PS1PR06MB1180.apcprd06.prod.outlook.com
State Superseded
Headers show

Commit Message

Phil Edworthy Nov. 9, 2015, 10:26 a.m. UTC
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 <phil.edworthy@renesas.com>
---
v2:
 - Remove incorrect res_valid check
---
 drivers/pci/host/pcie-rcar.c | 116 +++++++++++++++++++++++++++----------------
 1 file changed, 73 insertions(+), 43 deletions(-)

Comments

Simon Horman Nov. 10, 2015, 12:46 a.m. UTC | #1
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 <phil.edworthy@renesas.com>

I think the following should be carried over from v1:

Reported-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Tested-by: Wolfram Sang <wsa+renesas@sang-engineering.com>

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 <horms+renesas@verge.net.au>

> ---
> 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
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

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;