[PATCH u-boot-marvell 06/10] pci: pci_mvebu: Do not allow setting ROM BAR on PCI Bridge
Stefan Roese
sr at denx.de
Fri Nov 12 15:05:34 CET 2021
On 11/11/21 16:35, Marek Behún wrote:
> From: Pali Rohár <pali at kernel.org>
>
> The PCI Bridge which represents mvebu PCIe Root Port has Expansion ROM
> Base Address register at offset 0x30 but its meaning is different that
> of PCI's Expansion ROM BAR register, although the address format of
> the register is the same.
>
> In reality, this device does not have any configurable PCI BARs. So
> ensure that write operation into BARs (including Expansion ROM BAR) is a
> noop and registers always contain zero address which indicates that BARs
> are unsupported.
>
> Fixes: a7b61ab58d5d ("pci: pci_mvebu: Properly configure and use PCI Bridge (PCIe Root Port)")
> Signed-off-by: Pali Rohár <pali at kernel.org>
> Signed-off-by: Marek Behún <marek.behun at nic.cz>
Reviewed-by: Stefan Roese <sr at denx.de>
Thanks,
Stefan
> ---
> drivers/pci/pci_mvebu.c | 55 +++++++++++++++++++++++------------------
> 1 file changed, 31 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/pci/pci_mvebu.c b/drivers/pci/pci_mvebu.c
> index b545e62689..701a17dfb7 100644
> --- a/drivers/pci/pci_mvebu.c
> +++ b/drivers/pci/pci_mvebu.c
> @@ -93,7 +93,7 @@ struct mvebu_pcie {
> unsigned int mem_attr;
> unsigned int io_target;
> unsigned int io_attr;
> - u32 cfgcache[(0x34 - 0x10) / 4];
> + u32 cfgcache[(0x3c - 0x10) / 4];
> };
>
> /*
> @@ -189,20 +189,20 @@ static int mvebu_pcie_read_config(const struct udevice *bus, pci_dev_t bdf,
> }
>
> /*
> - * mvebu has different internal registers mapped into PCI config space
> - * in range 0x10-0x34 for PCI bridge, so do not access PCI config space
> - * for this range and instead read content from driver virtual cfgcache
> + * The configuration space of the PCI Bridge on primary (first) bus is
> + * of Type 0 but the BAR registers (including ROM BAR) don't have the
> + * same meaning as in the PCIe specification. Therefore do not access
> + * BAR registers and non-common registers (those which have different
> + * meaning for Type 0 and Type 1 config space) of the PCI Bridge and
> + * instead read their content from driver virtual cfgcache[].
> */
> - if (busno == pcie->first_busno && offset >= 0x10 && offset < 0x34) {
> + if (busno == pcie->first_busno && ((offset >= 0x10 && offset < 0x34) ||
> + (offset >= 0x38 && offset < 0x3c))) {
> data = pcie->cfgcache[(offset - 0x10) / 4];
> debug("(addr,size,val)=(0x%04x, %d, 0x%08x) from cfgcache\n",
> offset, size, data);
> *valuep = pci_conv_32_to_size(data, offset, size);
> return 0;
> - } else if (busno == pcie->first_busno &&
> - (offset & ~3) == PCI_ROM_ADDRESS1) {
> - /* mvebu has Expansion ROM Base Address (0x38) at offset 0x30 */
> - offset -= PCI_ROM_ADDRESS1 - PCIE_EXP_ROM_BAR_OFF;
> }
>
> /*
> @@ -269,17 +269,21 @@ static int mvebu_pcie_write_config(struct udevice *bus, pci_dev_t bdf,
> }
>
> /*
> - * mvebu has different internal registers mapped into PCI config space
> - * in range 0x10-0x34 for PCI bridge, so do not access PCI config space
> - * for this range and instead write content to driver virtual cfgcache
> + * As explained in mvebu_pcie_read_config(), PCI Bridge Type 1 specific
> + * config registers are not available, so we write their content only
> + * into driver virtual cfgcache[].
> + * And as explained in mvebu_pcie_probe(), mvebu has its own specific
> + * way for configuring primary and secondary bus numbers.
> */
> - if (busno == pcie->first_busno && offset >= 0x10 && offset < 0x34) {
> + if (busno == pcie->first_busno && ((offset >= 0x10 && offset < 0x34) ||
> + (offset >= 0x38 && offset < 0x3c))) {
> debug("Writing to cfgcache only\n");
> data = pcie->cfgcache[(offset - 0x10) / 4];
> data = pci_conv_size_to_32(data, value, offset, size);
> /* mvebu PCI bridge does not have configurable bars */
> if ((offset & ~3) == PCI_BASE_ADDRESS_0 ||
> - (offset & ~3) == PCI_BASE_ADDRESS_1)
> + (offset & ~3) == PCI_BASE_ADDRESS_1 ||
> + (offset & ~3) == PCI_ROM_ADDRESS1)
> data = 0x0;
> pcie->cfgcache[(offset - 0x10) / 4] = data;
> /* mvebu has its own way how to set PCI primary bus number */
> @@ -297,10 +301,6 @@ static int mvebu_pcie_write_config(struct udevice *bus, pci_dev_t bdf,
> pcie->sec_busno);
> }
> return 0;
> - } else if (busno == pcie->first_busno &&
> - (offset & ~3) == PCI_ROM_ADDRESS1) {
> - /* mvebu has Expansion ROM Base Address (0x38) at offset 0x30 */
> - offset -= PCI_ROM_ADDRESS1 - PCIE_EXP_ROM_BAR_OFF;
> }
>
> /*
> @@ -424,13 +424,20 @@ static int mvebu_pcie_probe(struct udevice *dev)
> * U-Boot cannot recognize as P2P Bridge.
> *
> * Note that this mvebu PCI Bridge does not have compliant Type 1
> - * Configuration Space. Header Type is reported as Type 0 and in
> - * range 0x10-0x34 it has aliased internal mvebu registers 0x10-0x34
> - * (e.g. PCIE_BAR_LO_OFF) and register 0x38 is reserved.
> + * Configuration Space. Header Type is reported as Type 0 and it
> + * has format of Type 0 config space.
> *
> - * Driver for this range redirects access to virtual cfgcache[] buffer
> - * which avoids changing internal mvebu registers. And changes Header
> - * Type response value to Type 1.
> + * Moreover Type 0 BAR registers (ranges 0x10 - 0x28 and 0x30 - 0x34)
> + * have the same format in Marvell's specification as in PCIe
> + * specification, but their meaning is totally different and they do
> + * different things: they are aliased into internal mvebu registers
> + * (e.g. PCIE_BAR_LO_OFF) and these should not be changed or
> + * reconfigured by pci device drivers.
> + *
> + * So our driver converts Type 0 config space to Type 1 and reports
> + * Header Type as Type 1. Access to BAR registers and to non-existent
> + * Type 1 registers is redirected to the virtual cfgcache[] buffer,
> + * which avoids changing unrelated registers.
> */
> reg = readl(pcie->base + PCIE_DEV_REV_OFF);
> reg &= ~0xffffff00;
>
Viele Grüße,
Stefan Roese
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-51 Fax: (+49)-8142-66989-80 Email: sr at denx.de
More information about the U-Boot
mailing list