Commit 323fc750 authored by Bjorn Helgaas's avatar Bjorn Helgaas

Merge branch 'remotes/lorenzo/pci/mvebu'

  - Fix mvebu I/O space remapping issues (Thomas Petazzoni)

  - Use generic pci_host_bridge in mvebu instead of ARM-specific API
    (Thomas Petazzoni)

* remotes/lorenzo/pci/mvebu:
  PCI: mvebu: Drop bogus comment above mvebu_pcie_map_registers()
  PCI: mvebu: Convert to use pci_host_bridge directly
  PCI: mvebu: Use resource_size() to remap I/O space
  PCI: mvebu: Only remap I/O space if configured
  PCI: mvebu: Fix I/O space end address calculation
  PCI: mvebu: Remove redundant platform_set_drvdata() call
parents 732c4701 f23d0d44
...@@ -125,6 +125,7 @@ struct mvebu_pcie { ...@@ -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, ...@@ -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, ...@@ -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 = { ...@@ -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,31 +888,6 @@ static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev, ...@@ -917,31 +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 =
* <...> property for one that matches the given port/lane. Once
* found, maps it.
*/
static void __iomem *mvebu_pcie_map_registers(struct platform_device *pdev, static void __iomem *mvebu_pcie_map_registers(struct platform_device *pdev,
struct device_node *np, struct device_node *np,
struct mvebu_pcie_port *port) struct mvebu_pcie_port *port)
...@@ -1190,46 +1136,79 @@ static void mvebu_pcie_powerdown(struct mvebu_pcie_port *port) ...@@ -1190,46 +1136,79 @@ 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) {
pcie->realio.flags = pcie->io.flags; pcie->realio.flags = pcie->io.flags;
pcie->realio.start = PCIBIOS_MIN_IO; pcie->realio.start = PCIBIOS_MIN_IO;
pcie->realio.end = min_t(resource_size_t, pcie->realio.end = min_t(resource_size_t,
IO_SPACE_LIMIT, IO_SPACE_LIMIT - SZ_64K,
resource_size(&pcie->io)); resource_size(&pcie->io) - 1);
} else pcie->realio.name = "PCI I/O";
pcie->realio = pcie->io;
/* Get the bus range */ for (i = 0; i < resource_size(&pcie->realio); i += SZ_64K)
ret = of_pci_parse_bus_range(np, &pcie->busn); pci_ioremap_io(i, pcie->io.start + i);
if (ret) {
dev_err(dev, "failed to parse bus-range property: %d\n", ret); pci_add_resource(&pcie->resources, &pcie->realio);
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);
...@@ -1272,20 +1251,24 @@ static int mvebu_pcie_probe(struct platform_device *pdev) ...@@ -1272,20 +1251,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;
for (i = 0; i < (IO_SPACE_LIMIT - SZ_64K); i += SZ_64K) list_splice_init(&pcie->resources, &bridge->windows);
pci_ioremap_io(i, pcie->io.start + i); bridge->dev.parent = dev;
bridge->sysdata = pcie;
mvebu_pcie_enable(pcie); bridge->busnr = 0;
bridge->ops = &mvebu_pcie_ops;
platform_set_drvdata(pdev, pcie); bridge->map_irq = of_irq_parse_and_map_pci;
bridge->swizzle_irq = pci_common_swizzle;
return 0; bridge->align_resource = mvebu_pcie_align_resource;
bridge->msi = pcie->msi;
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[] = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment