[U-Boot] [PATCH 1/1] pci: pci_mvebu: ignore the local device
Chris Packham
judge.packham at gmail.com
Fri May 10 08:10:12 UTC 2019
Hi Marek,
On Fri, May 10, 2019 at 2:56 PM Marek BehĂșn <marek.behun at nic.cz> wrote:
>
> The local device (host "bridge"?) on pci_mvebu controller reports
> PCI_CLASS_MEMORY_OTHER in the class register.
>
> This does not work in U-Boot, because U-Boot then tries to autoconfigure
> this device in pci_auto.c. This causes the real connected PCIe device
> not to work (in U-Boot nor in Linux).
>
> Linux solves this by emulating PCI bridge device (see
> drivers/pci/pci-bridge-emul.c in Linux). The Marvell vendor/device IDs
> are used for this pci-bridge-emul device in Linux, but the actual
> register accesses are emulated and the value of class register is
> PCI_CLASS_BRIDGE_PCI.
>
> The simplest solution here in my opinion is to just ignore the local
> device in this driver's read/write methods. This fixes PCIe issues for
> me.
>
> Signed-off-by: Marek BehĂșn <marek.behun at nic.cz>
> Cc: Stefan Roese <sr at denx.de>
> Cc: Anton Schubert <anton.schubert at gmx.de>
> Cc: Dirk Eibach <dirk.eibach at gdsys.cc>
> Cc: Mario Six <mario.six at gdsys.cc>
> Cc: Chris Packham <chris.packham at alliedtelesis.co.nz>
> Cc: Phil Sutter <phil at nwl.cc>
> Cc: VlaoMao <vlaomao at gmail.com>
On the Allied Telesis x530
before:
=> pci enum
=> pci
Scanning PCI devices on bus 0
BusDevFun VendorId DeviceId Device Class Sub-Class
_____________________________________________________________
00.00.00 0x11ab 0x6820 Memory controller 0x80
00.01.00 0x11ab 0xc807 Network controller 0x00
after:
=> pci enum
=> pci
Scanning PCI devices on bus 0
BusDevFun VendorId DeviceId Device Class Sub-Class
_____________________________________________________________
00.01.00 0x11ab 0xc807 Network controller 0x00
Which appears to be the desired behaviour. The system booting to Linux
still seems OK.
Tested-by: Chris Packham <judge.packham at gmail.com>
> ---
> drivers/pci/pci_mvebu.c | 59 +++++++++++++++++------------------------
> 1 file changed, 24 insertions(+), 35 deletions(-)
>
> diff --git a/drivers/pci/pci_mvebu.c b/drivers/pci/pci_mvebu.c
> index e21dc10c2f..653f445a0f 100644
> --- a/drivers/pci/pci_mvebu.c
> +++ b/drivers/pci/pci_mvebu.c
> @@ -143,31 +143,31 @@ static int mvebu_pcie_read_config(struct udevice *bus, pci_dev_t bdf,
> struct mvebu_pcie *pcie = dev_get_platdata(bus);
> int local_bus = PCI_BUS(pcie->dev);
> int local_dev = PCI_DEV(pcie->dev);
> + int other_dev;
> u32 reg;
> u32 data;
>
> debug("PCIE CFG read: (b,d,f)=(%2d,%2d,%2d) ",
> PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
>
> - /* Only allow one other device besides the local one on the local bus */
> - if (PCI_BUS(bdf) == local_bus && PCI_DEV(bdf) != local_dev) {
> - if (local_dev == 0 && PCI_DEV(bdf) != 1) {
> - debug("- out of range\n");
> - /*
> - * If local dev is 0, the first other dev can
> - * only be 1
> - */
> - *valuep = pci_get_ff(size);
> - return 0;
> - } else if (local_dev != 0 && PCI_DEV(bdf) != 0) {
> - debug("- out of range\n");
> - /*
> - * If local dev is not 0, the first other dev can
> - * only be 0
> - */
> - *valuep = pci_get_ff(size);
> - return 0;
> - }
> + /*
> + * The local device has PCI_CLASS_MEMORY_OTHER in the class register.
> + * This does not work for U-Boot because pci_auto.c tries to configure
> + * this as a device. This results in U-Boot/Linux being unable to access
> + * PCIe devices.
> + *
> + * Linux solves this by emulating a bridge (see
> + * drivers/pci/pci-bridge-emul.c in Linux).
> + *
> + * Let's ignore the local device in U-Boot.
> + *
> + * Also only allow one other device besides the (ignored) local one.
> + */
> +
> + other_dev = local_dev ? 0 : 1;
> + if (PCI_BUS(bdf) == local_bus && PCI_DEV(bdf) != other_dev) {
> + *valuep = pci_get_ff(size);
> + return 0;
> }
>
> /* write address */
> @@ -187,28 +187,17 @@ static int mvebu_pcie_write_config(struct udevice *bus, pci_dev_t bdf,
> struct mvebu_pcie *pcie = dev_get_platdata(bus);
> int local_bus = PCI_BUS(pcie->dev);
> int local_dev = PCI_DEV(pcie->dev);
> + int other_dev;
> u32 data;
>
> debug("PCIE CFG write: (b,d,f)=(%2d,%2d,%2d) ",
> PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
> debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, value);
>
> - /* Only allow one other device besides the local one on the local bus */
> - if (PCI_BUS(bdf) == local_bus && PCI_DEV(bdf) != local_dev) {
> - if (local_dev == 0 && PCI_DEV(bdf) != 1) {
> - /*
> - * If local dev is 0, the first other dev can
> - * only be 1
> - */
> - return 0;
> - } else if (local_dev != 0 && PCI_DEV(bdf) != 0) {
> - /*
> - * If local dev is not 0, the first other dev can
> - * only be 0
> - */
> - return 0;
> - }
> - }
> + /* See the comment in mvebu_pcie_read_config */
> + other_dev = local_dev ? 0 : 1;
> + if (PCI_BUS(bdf) == local_bus && PCI_DEV(bdf) != other_dev)
> + return 0;
>
> writel(PCIE_CONF_ADDR(bdf, offset), pcie->base + PCIE_CONF_ADDR_OFF);
> data = pci_conv_size_to_32(0, value, offset, size);
> --
> 2.21.0
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot
More information about the U-Boot
mailing list