|
@@ -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;
|