No subject


Thu Jun 25 05:52:11 EDT 2020


the switch are device function 0x08 and 0x10 on the switch device.

Can you also post the output of lspci on your device?

> 
> Signed-off-by: Ian Kent <raven at themaw.net>
> ---
>  .../172-bcm5301x-R8000-handle-PEX8603-switch.patch |  225 ++++++++++++++++++++
>  .../172-bcm5301x-R8000-handle-PEX8603-switch.patch |  225 ++++++++++++++++++++
>  2 files changed, 450 insertions(+)
>  create mode 100644 target/linux/bcm53xx/patches-3.14/172-bcm5301x-R8000-handle-PEX8603-switch.patch
>  create mode 100644 target/linux/bcm53xx/patches-3.18/172-bcm5301x-R8000-handle-PEX8603-switch.patch
> 


......


> diff --git a/target/linux/bcm53xx/patches-3.18/172-bcm5301x-R8000-handle-PEX8603-switch.patch b/target/linux/bcm53xx/patches-3.18/172-bcm5301x-R8000-handle-PEX8603-switch.patch
> new file mode 100644
> index 0000000..fc606b4
> --- /dev/null
> +++ b/target/linux/bcm53xx/patches-3.18/172-bcm5301x-R8000-handle-PEX8603-switch.patch
> @@ -0,0 +1,225 @@
> +bcm53xx: R8000 handle PEX8603 switch
> +
> +The Netgear R8000 has a PEX8603 which, if not configured at
> +bus probe results in quite a few phantom devices as it doesn't
> +respond properly to configuration requests. The device needs
> +to be configured when seen.
> +
> +Signed-off-by: Ian Kent <raven at themaw.net>
> +
> +--- a/drivers/pci/host/pci-host-bcm5301x.c
> ++++ b/drivers/pci/host/pci-host-bcm5301x.c
> +@@ -29,6 +29,21 @@
> + #define PCI_TARGET_LINK_SPEED_GEN2    0x2
> + #define PCI_TARGET_LINK_SPEED_GEN1    0x1
> + 
> ++#define PCI_MAX_BUS			4
> ++#define PLX_PRIM_SEC_BUS_NUM		(0x00000201 | (PCI_MAX_BUS << 16))
> ++
> ++#ifndef SZ_48M
> ++#define SZ_48M	(SZ_32M + SZ_16M)
> ++#endif

Please remove the ifndef, it should fail if this gets added.


> ++
> ++struct pex86xx_info {
> ++	u8 busno;	/* Upstream bus PEX is on */
> ++	u8 slot;	/* Upstream slot PEX is at */
> ++	u16 active;	/* Active port count */
> ++	u16 ports;	/* Active port bit map */
> ++};
> ++struct pex86xx_info pex8603;
> ++
> + static int bcma_pcie2_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
> + {
> + 	struct pci_sys_data *sys = pdev->sysdata;
> +@@ -115,6 +130,39 @@ static int bcma_pcie2_read_config_pci(st
> + 	struct pci_sys_data *sys = bus->sysdata;
> + 	struct bcma_device *bdev = sys->private_data;
> + 
> ++	/* The PEX8603 won't return sensible values to the PCI layer so
> ++	 * we have to do that ourselves.
> ++	 */
> ++	if (pex8603.busno) {
> ++		u16 slot = PCI_SLOT(devfn);
> ++
> ++		/* Not the PEX upstream slot */
> ++		if (pex8603.busno == bus->number && pex8603.slot != slot)
> ++			goto done;
> ++
> ++		/* Not the PEX downstream bus? */
> ++		if (bus->number < pex8603.busno ||
> ++		    bus->number > pex8603.busno + 1)
> ++			goto done;
> ++
> ++		switch (bus->number - pex8603.busno) {
> ++		case 0:
> ++			/* Upstream port */
> ++			break;
> ++
> ++		case 1:
> ++			/* PEX8603, not present for slots other than 1 or 2 */
> ++			if (!(slot == 1 || slot == 2)) {
> ++				*val = 0xffffffff;
> ++				return PCIBIOS_SUCCESSFUL;
> ++			}
> ++			break;
> ++
> ++		default:
> ++			break;
> ++		}
> ++	}
> ++done:
> + 	*val = bcma_pcie2_read_config(bdev, bus->number, devfn, where, size);
> + 
> + 	return PCIBIOS_SUCCESSFUL;
> +@@ -126,6 +174,37 @@ static int bcma_pcie2_write_config_pci(s
> + 	struct pci_sys_data *sys = bus->sysdata;
> + 	struct bcma_device *bdev = sys->private_data;
> + 
> ++	/* Don't try and set anything on the PEX8603 if it isn't
> ++	 * valid.
> ++	 */
> ++	if (pex8603.busno) {
> ++		u16 slot = PCI_SLOT(devfn);
> ++
> ++		/* Not the PEX upstream slot */
> ++		if (pex8603.busno == bus->number && pex8603.slot != slot)
> ++			goto done;
> ++
> ++		/* Not the PEX downstream bus? */
> ++		if (bus->number < pex8603.busno ||
> ++		    bus->number > pex8603.busno + 1)
> ++			goto done;
> ++
> ++		switch (bus->number - pex8603.busno) {
> ++		case 0:
> ++			/* Upstream port */
> ++			break;
> ++
> ++		case 1:
> ++			/* PEX8603 slots only slots 1 and 2 present */
> ++			if (!(slot == 1 || slot == 2))
> ++				return PCIBIOS_SUCCESSFUL;
> ++			break;
> ++
> ++		default:
> ++			break;
> ++		}
> ++	}
> ++done:
> + 	bcma_pcie2_write_config(bdev, bus->number, devfn, where, size, val);
> + 
> + 	return PCIBIOS_SUCCESSFUL;
> +@@ -147,6 +226,113 @@ static void bcma_pcie2_fixup_class(struc
> + DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x8011, bcma_pcie2_fixup_class);
> + DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x8012, bcma_pcie2_fixup_class);
> + 
> ++static void bcma_pcie2_pex_switch_setup(struct pci_dev *dev)
> ++{
> ++	struct pci_sys_data *sys = dev->sysdata;
> ++	struct bcma_device *bdev = sys->private_data;
> ++	unsigned char busno = dev->bus->number;
> ++	unsigned int devfn = dev->devfn;
> ++	unsigned int slot = PCI_SLOT(devfn);
> ++	u32 addr = bdev->addr_s[0];
> ++	u32 tmp32;
> ++	u16 tmp16;
> ++
> ++	tmp32 = bcma_pcie2_read_config(bdev, busno, devfn, 0x100, 4);
> ++	if (!tmp32) {
> ++		dev_info(&bdev->dev, "failed to read PEX switch\n");
> ++		return;
> ++	}
> ++
> ++	/* Debug control register. */
> ++	tmp32 = bcma_pcie2_read_config(bdev, busno, devfn, 0x1dc, 4);
> ++	tmp32 &= ~(1<<22);
> ++	bcma_pcie2_write_config(bdev, busno, devfn, 0x1dc, 4, tmp32);
> ++
> ++	/* Set GPIO enable. */
> ++	tmp32 = bcma_pcie2_read_config(bdev, busno, devfn, 0x62c, 4);
> ++	tmp32 &= ~((1 << 0) | (1 << 1) | (1 << 3));
> ++	tmp32 |= ((1 << 4) | (1 << 5) | (1 << 7));
> ++	bcma_pcie2_write_config(bdev, busno, devfn, 0x62c, 4, tmp32);
> ++
> ++	mdelay(50);

You should use msleep(50) here.

> ++
> ++	tmp32 |= ((1<<0)|(1<<1));
> ++	bcma_pcie2_write_config(bdev, busno, devfn, 0x62c, 4, tmp32);
> ++
> ++	/* Bus master */
> ++	tmp16 = bcma_pcie2_read_config(bdev, busno, devfn, 0x4, 2);
> ++	tmp16 |= 0x06;
> ++	bcma_pcie2_write_config(bdev, busno, devfn, 0x4, 2, tmp16);
> ++
> ++	switch (slot) {

Are you sure this is correct?

Why does the vendor driver use the bus number and afterwards the device
function for the last two spaces and you are using only the slot number?

> ++	case 0:
> ++		/* Upstream port busno and slot */
> ++		pex8603.busno = busno;
> ++		pex8603.slot = slot;
> ++
> ++		bcma_pcie2_write_config(bdev, busno,
> ++					devfn, 0x18, 4, PLX_PRIM_SEC_BUS_NUM);
> ++
> ++		/* TODO: We need to scan all outgoing windows,
> ++		 * to look for a base limit pair for this register.
> ++		 */
> ++		/* MEM_BASE, MEM_LIM require 1MB alignment */
> ++		bcma_pcie2_write_config(bdev, busno,
> ++					devfn, PCI_MEMORY_BASE, 2,
> ++					addr >> 16);
> ++		BUG_ON(((addr + SZ_32M) >> 16) & 0xf);
> ++		bcma_pcie2_write_config(bdev, busno,
> ++					devfn, PCI_MEMORY_LIMIT, 2,
> ++					(addr + SZ_32M) >> 16);
> ++		break;
> ++
> ++	case 1:
> ++		bcma_pcie2_write_config(bdev, busno,
> ++					devfn, 0x18, 4,
> ++					(((busno + slot) << 16) |
> ++					 ((busno + slot) << 8) | busno));
> ++		BUG_ON(((addr + SZ_48M) >> 16) & 0xf);
> ++		bcma_pcie2_write_config(bdev, busno,
> ++					devfn, PCI_MEMORY_BASE, 4,
> ++					(addr + SZ_48M) >> 16);
> ++		BUG_ON(((addr + SZ_48M + SZ_32M) >> 16) & 0xf);
> ++		bcma_pcie2_write_config(bdev, busno,
> ++					devfn, PCI_MEMORY_LIMIT, 4,
> ++					(addr + SZ_48M + SZ_32M) >> 16);
> ++
> ++		/* Mark port bit number as active if successful */
> ++		tmp16 = bcma_pcie2_read_config(bdev, busno, devfn, 0x7A, 2);
> ++		if (tmp16 & PCI_EXP_LNKSTA_DLLLA) {
> ++			pex8603.ports |= ((1 << (slot - 1)) & 0xffff);
> ++			pex8603.active++;
> ++		}
> ++		break;
> ++
> ++	case 2:
> ++		bcma_pcie2_write_config(bdev, busno,
> ++					devfn, 0x18, 4,
> ++					(((busno + slot) << 16) |
> ++					 ((busno + slot) << 8) | busno));
> ++		BUG_ON(((addr + (SZ_48M * 2)) >> 16) & 0xf);
> ++		bcma_pcie2_write_config(bdev, busno,
> ++					devfn, PCI_MEMORY_BASE, 4,
> ++					(addr + (SZ_48M * 2)) >> 16);
> ++		BUG_ON(((addr + (SZ_48M * 2) + SZ_32M) >> 16) & 0xf);
> ++		bcma_pcie2_write_config(bdev, busno,
> ++					devfn, PCI_MEMORY_LIMIT, 4,
> ++					(addr + (SZ_48M * 2) + SZ_32M) >> 16);
> ++
> ++		/* Mark port bit number as active if successful */
> ++		tmp16 = bcma_pcie2_read_config(bdev, busno, devfn, 0x7A, 2);
> ++		if (tmp16 & PCI_EXP_LNKSTA_DLLLA) {
> ++			pex8603.ports |= ((1 << (slot - 1)) & 0xffff);
> ++			pex8603.active++;
> ++		}
> ++		break;
> ++	}
> ++}
> ++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8603, bcma_pcie2_pex_switch_setup);
> ++
> + /*
> +  * Check link status, return 0 if link is up in RC mode,
> +  * otherwise return non-zero
> _______________________________________________
> openwrt-devel mailing list
> openwrt-devel at lists.openwrt.org
> https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
> 
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list