summaryrefslogtreecommitdiff
path: root/drivers/pci/controller/pci-mvebu.c
diff options
context:
space:
mode:
authorPali Rohár <pali@kernel.org>2022-01-04 18:35:25 +0300
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>2022-02-03 13:54:06 +0300
commit5c88ed798522c59c7656c1e5704ca0062f4d92dc (patch)
treee66d6745abb9169cde520e79d556d6d56da0c0d2 /drivers/pci/controller/pci-mvebu.c
parent7a02acdb5debff8cbee4a91efbba084f7b26a680 (diff)
downloadlinux-5c88ed798522c59c7656c1e5704ca0062f4d92dc.tar.xz
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.org Signed-off-by: Pali Rohár <pali@kernel.org> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Reviewed-by: Rob Herring <robh@kernel.org>
Diffstat (limited to 'drivers/pci/controller/pci-mvebu.c')
-rw-r--r--drivers/pci/controller/pci-mvebu.c29
1 files changed, 10 insertions, 19 deletions
diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index a7eaa58483dd..806cfcdb6b44 100644
--- a/drivers/pci/controller/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
@@ -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,
&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
* 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,
switch (reg) {
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);
break;
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 */
conf->iobase &= ~0xf0;
conf->iolimit &= ~0xf0;
+ conf->iobase |= 0xf0;
conf->iobaseupper = cpu_to_le16(0x0000);
conf->iolimitupper = cpu_to_le16(0x0000);
- if (mvebu_has_ioport(port))
- conf->iobase |= 0xf0;
}
break;
@@ -630,14 +618,14 @@ mvebu_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge,
break;
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 */
conf->iobase &= ~0xf0;
conf->iolimit &= ~0xf0;
+ conf->iobase |= 0xf0;
conf->iobaseupper = cpu_to_le16(0x0000);
conf->iolimitupper = cpu_to_le16(0x0000);
- if (mvebu_has_ioport(port))
- conf->iobase |= 0xf0;
}
break;
@@ -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)
{
+ unsigned int bridge_flags = PCI_BRIDGE_EMUL_NO_PREFMEM_FORWARD;
struct pci_bridge_emul *bridge = &port->bridge;
u32 pcie_cap = mvebu_readl(port, PCIE_CAP_PCIEXP);
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)
/* We support 32 bits I/O addressing */
bridge->conf.iobase = 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)
bridge->data = port;
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)