|
@@ -150,6 +150,11 @@ static inline u32 mvebu_readl(struct mvebu_pcie_port *port, u32 reg)
|
|
|
return readl(port->base + reg);
|
|
|
}
|
|
|
|
|
|
+static inline bool mvebu_has_ioport(struct mvebu_pcie_port *port)
|
|
|
+{
|
|
|
+ return port->io_target != -1 && port->io_attr != -1;
|
|
|
+}
|
|
|
+
|
|
|
static bool mvebu_pcie_link_up(struct mvebu_pcie_port *port)
|
|
|
{
|
|
|
return !(mvebu_readl(port, PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN);
|
|
@@ -314,6 +319,12 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ if (!mvebu_has_ioport(port)) {
|
|
|
+ dev_WARN(&port->pcie->pdev->dev,
|
|
|
+ "Attempt to set IO when IO is disabled\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* We read the PCI-to-PCI bridge emulated registers, and
|
|
|
* calculate the base address and size of the address decoding
|
|
@@ -428,9 +439,12 @@ static int mvebu_sw_pci_bridge_read(struct mvebu_pcie_port *port,
|
|
|
break;
|
|
|
|
|
|
case PCI_IO_BASE:
|
|
|
- *value = (bridge->secondary_status << 16 |
|
|
|
- bridge->iolimit << 8 |
|
|
|
- bridge->iobase);
|
|
|
+ if (!mvebu_has_ioport(port))
|
|
|
+ *value = bridge->secondary_status << 16;
|
|
|
+ else
|
|
|
+ *value = (bridge->secondary_status << 16 |
|
|
|
+ bridge->iolimit << 8 |
|
|
|
+ bridge->iobase);
|
|
|
break;
|
|
|
|
|
|
case PCI_MEMORY_BASE:
|
|
@@ -490,6 +504,9 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port,
|
|
|
{
|
|
|
u32 old = bridge->command;
|
|
|
|
|
|
+ if (!mvebu_has_ioport(port))
|
|
|
+ value &= ~PCI_COMMAND_IO;
|
|
|
+
|
|
|
bridge->command = value & 0xffff;
|
|
|
if ((old ^ bridge->command) & PCI_COMMAND_IO)
|
|
|
mvebu_pcie_handle_iobase_change(port);
|
|
@@ -660,7 +677,9 @@ static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
|
|
|
struct mvebu_pcie *pcie = sys_to_pcie(sys);
|
|
|
int i;
|
|
|
|
|
|
- pci_add_resource_offset(&sys->resources, &pcie->realio, sys->io_offset);
|
|
|
+ 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);
|
|
|
|
|
@@ -761,12 +780,17 @@ static void __iomem *mvebu_pcie_map_registers(struct platform_device *pdev,
|
|
|
#define DT_CPUADDR_TO_ATTR(cpuaddr) (((cpuaddr) >> 48) & 0xFF)
|
|
|
|
|
|
static int mvebu_get_tgt_attr(struct device_node *np, int devfn,
|
|
|
- unsigned long type, int *tgt, int *attr)
|
|
|
+ unsigned long type,
|
|
|
+ unsigned int *tgt,
|
|
|
+ unsigned int *attr)
|
|
|
{
|
|
|
const int na = 3, ns = 2;
|
|
|
const __be32 *range;
|
|
|
int rlen, nranges, rangesz, pna, i;
|
|
|
|
|
|
+ *tgt = -1;
|
|
|
+ *attr = -1;
|
|
|
+
|
|
|
range = of_get_property(np, "ranges", &rlen);
|
|
|
if (!range)
|
|
|
return -EINVAL;
|
|
@@ -836,16 +860,15 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
|
|
|
}
|
|
|
|
|
|
mvebu_mbus_get_pcie_io_aperture(&pcie->io);
|
|
|
- if (resource_size(&pcie->io) == 0) {
|
|
|
- dev_err(&pdev->dev, "invalid I/O aperture size\n");
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
|
|
|
- pcie->realio.flags = pcie->io.flags;
|
|
|
- pcie->realio.start = PCIBIOS_MIN_IO;
|
|
|
- pcie->realio.end = min_t(resource_size_t,
|
|
|
- IO_SPACE_LIMIT,
|
|
|
- resource_size(&pcie->io));
|
|
|
+ if (resource_size(&pcie->io) != 0) {
|
|
|
+ pcie->realio.flags = pcie->io.flags;
|
|
|
+ pcie->realio.start = PCIBIOS_MIN_IO;
|
|
|
+ pcie->realio.end = min_t(resource_size_t,
|
|
|
+ IO_SPACE_LIMIT,
|
|
|
+ resource_size(&pcie->io));
|
|
|
+ } else
|
|
|
+ pcie->realio = pcie->io;
|
|
|
|
|
|
/* Get the bus range */
|
|
|
ret = of_pci_parse_bus_range(np, &pcie->busn);
|
|
@@ -904,12 +927,12 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- ret = mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_IO,
|
|
|
- &port->io_target, &port->io_attr);
|
|
|
- if (ret < 0) {
|
|
|
- dev_err(&pdev->dev, "PCIe%d.%d: cannot get tgt/attr for io window\n",
|
|
|
- port->port, port->lane);
|
|
|
- continue;
|
|
|
+ if (resource_size(&pcie->io) != 0)
|
|
|
+ mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_IO,
|
|
|
+ &port->io_target, &port->io_attr);
|
|
|
+ else {
|
|
|
+ port->io_target = -1;
|
|
|
+ port->io_attr = -1;
|
|
|
}
|
|
|
|
|
|
port->reset_gpio = of_get_named_gpio_flags(child,
|