forked from mirrors/linux
		
	PCI: 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
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
dbf9826d57 ("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>
			
			
This commit is contained in:
		
							parent
							
								
									8d598cabf5
								
							
						
					
					
						commit
						5d2917d469
					
				
					 1 changed files with 73 additions and 43 deletions
				
			
		| 
						 | 
					@ -108,8 +108,6 @@
 | 
				
			||||||
#define RCAR_PCI_MAX_RESOURCES 4
 | 
					#define RCAR_PCI_MAX_RESOURCES 4
 | 
				
			||||||
#define MAX_NR_INBOUND_MAPS 6
 | 
					#define MAX_NR_INBOUND_MAPS 6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static unsigned long global_io_offset;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct rcar_msi {
 | 
					struct rcar_msi {
 | 
				
			||||||
	DECLARE_BITMAP(used, INT_PCI_MSI_NR);
 | 
						DECLARE_BITMAP(used, INT_PCI_MSI_NR);
 | 
				
			||||||
	struct irq_domain *domain;
 | 
						struct irq_domain *domain;
 | 
				
			||||||
| 
						 | 
					@ -138,8 +136,7 @@ struct rcar_pcie {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	struct device		*dev;
 | 
						struct device		*dev;
 | 
				
			||||||
	void __iomem		*base;
 | 
						void __iomem		*base;
 | 
				
			||||||
	struct resource		res[RCAR_PCI_MAX_RESOURCES];
 | 
						struct list_head	resources;
 | 
				
			||||||
	struct resource		busn;
 | 
					 | 
				
			||||||
	int			root_bus_nr;
 | 
						int			root_bus_nr;
 | 
				
			||||||
	struct clk		*clk;
 | 
						struct clk		*clk;
 | 
				
			||||||
	struct clk		*bus_clk;
 | 
						struct clk		*bus_clk;
 | 
				
			||||||
| 
						 | 
					@ -323,10 +320,9 @@ static struct pci_ops rcar_pcie_ops = {
 | 
				
			||||||
	.write	= rcar_pcie_write_conf,
 | 
						.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 */
 | 
						/* Setup PCIe address space mappings for each resource */
 | 
				
			||||||
	resource_size_t size;
 | 
						resource_size_t size;
 | 
				
			||||||
	resource_size_t res_start;
 | 
						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));
 | 
						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;
 | 
						struct resource_entry *win;
 | 
				
			||||||
	int i;
 | 
						int i = 0;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	pcie->root_bus_nr = pcie->busn.start;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Setup PCI resources */
 | 
						/* 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)
 | 
							if (!res->flags)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		rcar_pcie_setup_window(i, pcie);
 | 
							switch (resource_type(res)) {
 | 
				
			||||||
 | 
							case IORESOURCE_IO:
 | 
				
			||||||
		if (res->flags & IORESOURCE_IO) {
 | 
							case IORESOURCE_MEM:
 | 
				
			||||||
			phys_addr_t io_start = pci_pio_to_address(res->start);
 | 
								rcar_pcie_setup_window(i, pci, res);
 | 
				
			||||||
			pci_ioremap_io(global_io_offset, io_start);
 | 
								i++;
 | 
				
			||||||
			global_io_offset += SZ_64K;
 | 
								break;
 | 
				
			||||||
 | 
							case IORESOURCE_BUS:
 | 
				
			||||||
 | 
								pci->root_bus_nr = res->start;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pci_add_resource(resource, res);
 | 
							pci_add_resource(resource, res);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	pci_add_resource(resource, &pcie->busn);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 1;
 | 
						return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -923,14 +921,63 @@ static const struct of_device_id rcar_pcie_of_match[] = {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
MODULE_DEVICE_TABLE(of, 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)
 | 
					static int rcar_pcie_probe(struct platform_device *pdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct rcar_pcie *pcie;
 | 
						struct rcar_pcie *pcie;
 | 
				
			||||||
	unsigned int data;
 | 
						unsigned int data;
 | 
				
			||||||
	struct of_pci_range range;
 | 
					 | 
				
			||||||
	struct of_pci_range_parser parser;
 | 
					 | 
				
			||||||
	const struct of_device_id *of_id;
 | 
						const struct of_device_id *of_id;
 | 
				
			||||||
	int err, win = 0;
 | 
						int err;
 | 
				
			||||||
	int (*hw_init_fn)(struct rcar_pcie *);
 | 
						int (*hw_init_fn)(struct rcar_pcie *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL);
 | 
						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;
 | 
						pcie->dev = &pdev->dev;
 | 
				
			||||||
	platform_set_drvdata(pdev, pcie);
 | 
						platform_set_drvdata(pdev, pcie);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Get the bus range */
 | 
						INIT_LIST_HEAD(&pcie->resources);
 | 
				
			||||||
	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;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (of_pci_range_parser_init(&parser, pdev->dev.of_node)) {
 | 
						rcar_pcie_parse_request_of_pci_ranges(pcie);
 | 
				
			||||||
		dev_err(&pdev->dev, "missing ranges property\n");
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = rcar_pcie_get_resources(pdev, pcie);
 | 
						err = rcar_pcie_get_resources(pdev, pcie);
 | 
				
			||||||
	if (err < 0) {
 | 
						if (err < 0) {
 | 
				
			||||||
| 
						 | 
					@ -957,16 +997,6 @@ static int rcar_pcie_probe(struct platform_device *pdev)
 | 
				
			||||||
		return err;
 | 
							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);
 | 
						 err = rcar_pcie_parse_map_dma_ranges(pcie, pdev->dev.of_node);
 | 
				
			||||||
	 if (err)
 | 
						 if (err)
 | 
				
			||||||
		return err;
 | 
							return err;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue