提交 5c88ed79 编写于 作者: P Pali Rohár 提交者: Lorenzo Pieralisi

PCI: mvebu: Set PCI_BRIDGE_EMUL_NO_IO_FORWARD when IO is unsupported

This will make PCI bridge to return zeros when accessing IO base and limit
registers, as required by PCIe base specification.

This allows to remove adhoc checks around mvebu_pcie_handle_iobase_change()
function for unsupported IO ranges. PCI_BRIDGE_EMUL_NO_IO_FORWARD ensures
that there will be no non-zeros write to IO registers when IO is not
supported.

Link: https://lore.kernel.org/r/20220104153529.31647-8-pali@kernel.orgSigned-off-by: NPali Rohár <pali@kernel.org>
Signed-off-by: NLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: NRob Herring <robh@kernel.org>
上级 7a02acdb
...@@ -438,12 +438,6 @@ static int mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) ...@@ -438,12 +438,6 @@ static int mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
return mvebu_pcie_set_window(port, port->io_target, port->io_attr, return mvebu_pcie_set_window(port, port->io_target, port->io_attr,
&desired, &port->iowin); &desired, &port->iowin);
if (!mvebu_has_ioport(port)) {
dev_WARN(&port->pcie->pdev->dev,
"Attempt to set IO when IO is disabled\n");
return -EOPNOTSUPP;
}
/* /*
* We read the PCI-to-PCI bridge emulated registers, and * We read the PCI-to-PCI bridge emulated registers, and
* calculate the base address and size of the address decoding * calculate the base address and size of the address decoding
...@@ -599,24 +593,18 @@ mvebu_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge, ...@@ -599,24 +593,18 @@ mvebu_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge,
switch (reg) { switch (reg) {
case PCI_COMMAND: case PCI_COMMAND:
if (!mvebu_has_ioport(port)) {
conf->command = cpu_to_le16(
le16_to_cpu(conf->command) & ~PCI_COMMAND_IO);
new &= ~PCI_COMMAND_IO;
}
mvebu_writel(port, new, PCIE_CMD_OFF); mvebu_writel(port, new, PCIE_CMD_OFF);
break; break;
case PCI_IO_BASE: case PCI_IO_BASE:
if ((mask & 0xffff) && mvebu_pcie_handle_iobase_change(port)) { if ((mask & 0xffff) && mvebu_has_ioport(port) &&
mvebu_pcie_handle_iobase_change(port)) {
/* On error disable IO range */ /* On error disable IO range */
conf->iobase &= ~0xf0; conf->iobase &= ~0xf0;
conf->iolimit &= ~0xf0; conf->iolimit &= ~0xf0;
conf->iobase |= 0xf0;
conf->iobaseupper = cpu_to_le16(0x0000); conf->iobaseupper = cpu_to_le16(0x0000);
conf->iolimitupper = cpu_to_le16(0x0000); conf->iolimitupper = cpu_to_le16(0x0000);
if (mvebu_has_ioport(port))
conf->iobase |= 0xf0;
} }
break; break;
...@@ -630,14 +618,14 @@ mvebu_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge, ...@@ -630,14 +618,14 @@ mvebu_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge,
break; break;
case PCI_IO_BASE_UPPER16: case PCI_IO_BASE_UPPER16:
if (mvebu_pcie_handle_iobase_change(port)) { if (mvebu_has_ioport(port) &&
mvebu_pcie_handle_iobase_change(port)) {
/* On error disable IO range */ /* On error disable IO range */
conf->iobase &= ~0xf0; conf->iobase &= ~0xf0;
conf->iolimit &= ~0xf0; conf->iolimit &= ~0xf0;
conf->iobase |= 0xf0;
conf->iobaseupper = cpu_to_le16(0x0000); conf->iobaseupper = cpu_to_le16(0x0000);
conf->iolimitupper = cpu_to_le16(0x0000); conf->iolimitupper = cpu_to_le16(0x0000);
if (mvebu_has_ioport(port))
conf->iobase |= 0xf0;
} }
break; break;
...@@ -722,6 +710,7 @@ static const struct pci_bridge_emul_ops mvebu_pci_bridge_emul_ops = { ...@@ -722,6 +710,7 @@ static const struct pci_bridge_emul_ops mvebu_pci_bridge_emul_ops = {
*/ */
static int mvebu_pci_bridge_emul_init(struct mvebu_pcie_port *port) static int mvebu_pci_bridge_emul_init(struct mvebu_pcie_port *port)
{ {
unsigned int bridge_flags = PCI_BRIDGE_EMUL_NO_PREFMEM_FORWARD;
struct pci_bridge_emul *bridge = &port->bridge; struct pci_bridge_emul *bridge = &port->bridge;
u32 pcie_cap = mvebu_readl(port, PCIE_CAP_PCIEXP); u32 pcie_cap = mvebu_readl(port, PCIE_CAP_PCIEXP);
u8 pcie_cap_ver = ((pcie_cap >> 16) & PCI_EXP_FLAGS_VERS); u8 pcie_cap_ver = ((pcie_cap >> 16) & PCI_EXP_FLAGS_VERS);
...@@ -735,6 +724,8 @@ static int mvebu_pci_bridge_emul_init(struct mvebu_pcie_port *port) ...@@ -735,6 +724,8 @@ static int mvebu_pci_bridge_emul_init(struct mvebu_pcie_port *port)
/* We support 32 bits I/O addressing */ /* We support 32 bits I/O addressing */
bridge->conf.iobase = PCI_IO_RANGE_TYPE_32; bridge->conf.iobase = PCI_IO_RANGE_TYPE_32;
bridge->conf.iolimit = PCI_IO_RANGE_TYPE_32; bridge->conf.iolimit = PCI_IO_RANGE_TYPE_32;
} else {
bridge_flags |= PCI_BRIDGE_EMUL_NO_IO_FORWARD;
} }
/* /*
...@@ -747,7 +738,7 @@ static int mvebu_pci_bridge_emul_init(struct mvebu_pcie_port *port) ...@@ -747,7 +738,7 @@ static int mvebu_pci_bridge_emul_init(struct mvebu_pcie_port *port)
bridge->data = port; bridge->data = port;
bridge->ops = &mvebu_pci_bridge_emul_ops; bridge->ops = &mvebu_pci_bridge_emul_ops;
return pci_bridge_emul_init(bridge, PCI_BRIDGE_EMUL_NO_PREFMEM_FORWARD); return pci_bridge_emul_init(bridge, bridge_flags);
} }
static inline struct mvebu_pcie *sys_to_pcie(struct pci_sys_data *sys) static inline struct mvebu_pcie *sys_to_pcie(struct pci_sys_data *sys)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册