mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	PCI: mvebu: Convert to use pci_host_bridge directly
Rather than using the ARM-specific pci_common_init_dev() API, use the pci_host_bridge logic directly. Unfortunately, we can't use devm_of_pci_get_host_bridge_resources(), because the DT binding for describing PCIe apertures for this PCI controller is a bit special, and we cannot retrieve them from the 'ranges' property. Therefore, we still have some special code to handle this. Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
This commit is contained in:
		
							parent
							
								
									5a553d6ba1
								
							
						
					
					
						commit
						42342073e3
					
				
					 1 changed files with 62 additions and 72 deletions
				
			
		| 
						 | 
					@ -125,6 +125,7 @@ struct mvebu_pcie {
 | 
				
			||||||
	struct platform_device *pdev;
 | 
						struct platform_device *pdev;
 | 
				
			||||||
	struct mvebu_pcie_port *ports;
 | 
						struct mvebu_pcie_port *ports;
 | 
				
			||||||
	struct msi_controller *msi;
 | 
						struct msi_controller *msi;
 | 
				
			||||||
 | 
						struct list_head resources;
 | 
				
			||||||
	struct resource io;
 | 
						struct resource io;
 | 
				
			||||||
	struct resource realio;
 | 
						struct resource realio;
 | 
				
			||||||
	struct resource mem;
 | 
						struct resource mem;
 | 
				
			||||||
| 
						 | 
					@ -800,7 +801,7 @@ static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
 | 
				
			||||||
static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
 | 
					static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
 | 
				
			||||||
			      int where, int size, u32 val)
 | 
								      int where, int size, u32 val)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata);
 | 
						struct mvebu_pcie *pcie = bus->sysdata;
 | 
				
			||||||
	struct mvebu_pcie_port *port;
 | 
						struct mvebu_pcie_port *port;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -826,7 +827,7 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
 | 
				
			||||||
static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 | 
					static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
 | 
				
			||||||
			      int size, u32 *val)
 | 
								      int size, u32 *val)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata);
 | 
						struct mvebu_pcie *pcie = bus->sysdata;
 | 
				
			||||||
	struct mvebu_pcie_port *port;
 | 
						struct mvebu_pcie_port *port;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -857,36 +858,6 @@ static struct pci_ops mvebu_pcie_ops = {
 | 
				
			||||||
	.write = mvebu_pcie_wr_conf,
 | 
						.write = mvebu_pcie_wr_conf,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct mvebu_pcie *pcie = sys_to_pcie(sys);
 | 
					 | 
				
			||||||
	int err, i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pcie->mem.name = "PCI MEM";
 | 
					 | 
				
			||||||
	pcie->realio.name = "PCI I/O";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (resource_size(&pcie->realio) != 0)
 | 
					 | 
				
			||||||
		pci_add_resource_offset(&sys->resources, &pcie->realio,
 | 
					 | 
				
			||||||
					sys->io_offset);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
 | 
					 | 
				
			||||||
	pci_add_resource(&sys->resources, &pcie->busn);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = devm_request_pci_bus_resources(&pcie->pdev->dev, &sys->resources);
 | 
					 | 
				
			||||||
	if (err)
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < pcie->nports; i++) {
 | 
					 | 
				
			||||||
		struct mvebu_pcie_port *port = &pcie->ports[i];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (!port->base)
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
		mvebu_pcie_setup_hw(port);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
 | 
					static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
 | 
				
			||||||
						 const struct resource *res,
 | 
											 const struct resource *res,
 | 
				
			||||||
						 resource_size_t start,
 | 
											 resource_size_t start,
 | 
				
			||||||
| 
						 | 
					@ -917,26 +888,6 @@ static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
 | 
				
			||||||
		return start;
 | 
							return start;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void mvebu_pcie_enable(struct mvebu_pcie *pcie)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct hw_pci hw;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	memset(&hw, 0, sizeof(hw));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef CONFIG_PCI_MSI
 | 
					 | 
				
			||||||
	hw.msi_ctrl = pcie->msi;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	hw.nr_controllers = 1;
 | 
					 | 
				
			||||||
	hw.private_data   = (void **)&pcie;
 | 
					 | 
				
			||||||
	hw.setup          = mvebu_pcie_setup;
 | 
					 | 
				
			||||||
	hw.map_irq        = of_irq_parse_and_map_pci;
 | 
					 | 
				
			||||||
	hw.ops            = &mvebu_pcie_ops;
 | 
					 | 
				
			||||||
	hw.align_resource = mvebu_pcie_align_resource;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pci_common_init_dev(&pcie->pdev->dev, &hw);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Looks up the list of register addresses encoded into the reg =
 | 
					 * Looks up the list of register addresses encoded into the reg =
 | 
				
			||||||
 * <...> property for one that matches the given port/lane. Once
 | 
					 * <...> property for one that matches the given port/lane. Once
 | 
				
			||||||
| 
						 | 
					@ -1190,28 +1141,39 @@ static void mvebu_pcie_powerdown(struct mvebu_pcie_port *port)
 | 
				
			||||||
	clk_disable_unprepare(port->clk);
 | 
						clk_disable_unprepare(port->clk);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int mvebu_pcie_probe(struct platform_device *pdev)
 | 
					/*
 | 
				
			||||||
 | 
					 * We can't use devm_of_pci_get_host_bridge_resources() because we
 | 
				
			||||||
 | 
					 * need to parse our special DT properties encoding the MEM and IO
 | 
				
			||||||
 | 
					 * apertures.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int mvebu_pcie_parse_request_resources(struct mvebu_pcie *pcie)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct device *dev = &pdev->dev;
 | 
						struct device *dev = &pcie->pdev->dev;
 | 
				
			||||||
	struct mvebu_pcie *pcie;
 | 
					 | 
				
			||||||
	struct device_node *np = dev->of_node;
 | 
						struct device_node *np = dev->of_node;
 | 
				
			||||||
	struct device_node *child;
 | 
						unsigned int i;
 | 
				
			||||||
	int num, i, ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
 | 
						INIT_LIST_HEAD(&pcie->resources);
 | 
				
			||||||
	if (!pcie)
 | 
					 | 
				
			||||||
		return -ENOMEM;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pcie->pdev = pdev;
 | 
						/* Get the bus range */
 | 
				
			||||||
	platform_set_drvdata(pdev, pcie);
 | 
						ret = of_pci_parse_bus_range(np, &pcie->busn);
 | 
				
			||||||
 | 
						if (ret) {
 | 
				
			||||||
 | 
							dev_err(dev, "failed to parse bus-range property: %d\n", ret);
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						pci_add_resource(&pcie->resources, &pcie->busn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Get the PCIe memory and I/O aperture */
 | 
						/* Get the PCIe memory aperture */
 | 
				
			||||||
	mvebu_mbus_get_pcie_mem_aperture(&pcie->mem);
 | 
						mvebu_mbus_get_pcie_mem_aperture(&pcie->mem);
 | 
				
			||||||
	if (resource_size(&pcie->mem) == 0) {
 | 
						if (resource_size(&pcie->mem) == 0) {
 | 
				
			||||||
		dev_err(dev, "invalid memory aperture size\n");
 | 
							dev_err(dev, "invalid memory aperture size\n");
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pcie->mem.name = "PCI MEM";
 | 
				
			||||||
 | 
						pci_add_resource(&pcie->resources, &pcie->mem);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Get the PCIe IO aperture */
 | 
				
			||||||
	mvebu_mbus_get_pcie_io_aperture(&pcie->io);
 | 
						mvebu_mbus_get_pcie_io_aperture(&pcie->io);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (resource_size(&pcie->io) != 0) {
 | 
						if (resource_size(&pcie->io) != 0) {
 | 
				
			||||||
| 
						 | 
					@ -1220,19 +1182,38 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
 | 
				
			||||||
		pcie->realio.end = min_t(resource_size_t,
 | 
							pcie->realio.end = min_t(resource_size_t,
 | 
				
			||||||
					 IO_SPACE_LIMIT - SZ_64K,
 | 
										 IO_SPACE_LIMIT - SZ_64K,
 | 
				
			||||||
					 resource_size(&pcie->io) - 1);
 | 
										 resource_size(&pcie->io) - 1);
 | 
				
			||||||
 | 
							pcie->realio.name = "PCI I/O";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (i = 0; i < resource_size(&pcie->realio); i += SZ_64K)
 | 
							for (i = 0; i < resource_size(&pcie->realio); i += SZ_64K)
 | 
				
			||||||
			pci_ioremap_io(i, pcie->io.start + i);
 | 
								pci_ioremap_io(i, pcie->io.start + i);
 | 
				
			||||||
	} else
 | 
					 | 
				
			||||||
		pcie->realio = pcie->io;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Get the bus range */
 | 
							pci_add_resource(&pcie->resources, &pcie->realio);
 | 
				
			||||||
	ret = of_pci_parse_bus_range(np, &pcie->busn);
 | 
					 | 
				
			||||||
	if (ret) {
 | 
					 | 
				
			||||||
		dev_err(dev, "failed to parse bus-range property: %d\n", ret);
 | 
					 | 
				
			||||||
		return ret;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return devm_request_pci_bus_resources(dev, &pcie->resources);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int mvebu_pcie_probe(struct platform_device *pdev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct device *dev = &pdev->dev;
 | 
				
			||||||
 | 
						struct mvebu_pcie *pcie;
 | 
				
			||||||
 | 
						struct pci_host_bridge *bridge;
 | 
				
			||||||
 | 
						struct device_node *np = dev->of_node;
 | 
				
			||||||
 | 
						struct device_node *child;
 | 
				
			||||||
 | 
						int num, i, ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bridge = devm_pci_alloc_host_bridge(dev, sizeof(struct mvebu_pcie));
 | 
				
			||||||
 | 
						if (!bridge)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pcie = pci_host_bridge_priv(bridge);
 | 
				
			||||||
 | 
						pcie->pdev = pdev;
 | 
				
			||||||
 | 
						platform_set_drvdata(pdev, pcie);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = mvebu_pcie_parse_request_resources(pcie);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	num = of_get_available_child_count(np);
 | 
						num = of_get_available_child_count(np);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pcie->ports = devm_kcalloc(dev, num, sizeof(*pcie->ports), GFP_KERNEL);
 | 
						pcie->ports = devm_kcalloc(dev, num, sizeof(*pcie->ports), GFP_KERNEL);
 | 
				
			||||||
| 
						 | 
					@ -1275,15 +1256,24 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							mvebu_pcie_setup_hw(port);
 | 
				
			||||||
		mvebu_pcie_set_local_dev_nr(port, 1);
 | 
							mvebu_pcie_set_local_dev_nr(port, 1);
 | 
				
			||||||
		mvebu_sw_pci_bridge_init(port);
 | 
							mvebu_sw_pci_bridge_init(port);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pcie->nports = i;
 | 
						pcie->nports = i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mvebu_pcie_enable(pcie);
 | 
						list_splice_init(&pcie->resources, &bridge->windows);
 | 
				
			||||||
 | 
						bridge->dev.parent = dev;
 | 
				
			||||||
 | 
						bridge->sysdata = pcie;
 | 
				
			||||||
 | 
						bridge->busnr = 0;
 | 
				
			||||||
 | 
						bridge->ops = &mvebu_pcie_ops;
 | 
				
			||||||
 | 
						bridge->map_irq = of_irq_parse_and_map_pci;
 | 
				
			||||||
 | 
						bridge->swizzle_irq = pci_common_swizzle;
 | 
				
			||||||
 | 
						bridge->align_resource = mvebu_pcie_align_resource;
 | 
				
			||||||
 | 
						bridge->msi = pcie->msi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return pci_host_probe(bridge);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct of_device_id mvebu_pcie_of_match_table[] = {
 | 
					static const struct of_device_id mvebu_pcie_of_match_table[] = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue