From patchwork Mon Mar 9 09:09:18 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Kent X-Patchwork-Id: 447952 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from arrakis.dune.hu (arrakis.dune.hu [78.24.191.176]) (using TLSv1.1 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42C6314011D for ; Mon, 9 Mar 2015 20:15:37 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="verification failed; unprotected key" header.d=themaw.net header.i=@themaw.net header.b=oZSf1lCV; dkim-adsp=unknown (unprotected policy); dkim-atps=neutral Received: from arrakis.dune.hu (localhost [127.0.0.1]) by arrakis.dune.hu (Postfix) with ESMTP id AE2D228C165; Mon, 9 Mar 2015 10:11:45 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on arrakis.dune.hu X-Spam-Level: X-Spam-Status: No, score=-1.5 required=5.0 tests=BAYES_00,T_DKIM_INVALID autolearn=unavailable version=3.3.2 Received: from arrakis.dune.hu (localhost [127.0.0.1]) by arrakis.dune.hu (Postfix) with ESMTP id 9A8AD2890D1 for ; Mon, 9 Mar 2015 10:10:01 +0100 (CET) X-policyd-weight: using cached result; rate: -8.5 Received: from out2-smtp.messagingengine.com (out2-smtp.messagingengine.com [66.111.4.26]) by arrakis.dune.hu (Postfix) with ESMTPS for ; Mon, 9 Mar 2015 10:10:01 +0100 (CET) Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id 5FF4C21514 for ; Mon, 9 Mar 2015 05:10:11 -0400 (EDT) Received: from frontend1 ([10.202.2.160]) by compute4.internal (MEProxy); Mon, 09 Mar 2015 05:10:12 -0400 DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=themaw.net; h= x-sasl-enc:subject:from:to:cc:date:message-id:in-reply-to :references:mime-version:content-type:content-transfer-encoding; s=mesmtp; bh=6rdTs1PhjsPQ8V8Umu+SVrMqkVg=; b=oZSf1lCVKO/MxG+wQO YvELprTWZcWw3EHeIf4SPzAQjwuvtGUNJiboCqoI9QEu4R8Yw2acklRhbn9hRYg3 n7g2eLXnuR1WUi0EQKQP4TzUbAWRoFQefxWLaEg4gkt9WBTDbUKZeMzr39pdKiQf YFSGjSiEkcPmXZBJOXU06lfbM= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d= messagingengine.com; h=x-sasl-enc:subject:from:to:cc:date :message-id:in-reply-to:references:mime-version:content-type :content-transfer-encoding; s=smtpout; bh=6rdTs1PhjsPQ8V8Umu+SVr MqkVg=; b=PXG9yoR3viAAoVyyofRdcT+Ac7XkdlEpiVzznFeOnAcE9eMa2GKLyt UbhhB1hPqne4hUnUj+jbmHqMXD18hsfmBwOwoX36FNnt5FdapafJB505oXawfhx+ I6rt4/Q4M1NAd1JN33jRpkSa3pV7ciUb46ECoLWduZZYNAaBuwzXg= X-Sasl-enc: vtfkQ1hI9yiWB2/f3sf7CHdzgsA5XuaBCZ3sB61h7cZb 1425892211 Received: from perseus.themaw.net (unknown [58.7.183.112]) by mail.messagingengine.com (Postfix) with ESMTPA id EDBD5C002A6; Mon, 9 Mar 2015 05:10:11 -0400 (EDT) Received: from perseus.themaw.net (localhost [127.0.0.1]) by perseus.themaw.net (Postfix) with ESMTP id 03D4A1202A1; Mon, 9 Mar 2015 17:09:18 +0800 (AWST) From: Ian Kent To: Zajec Date: Mon, 09 Mar 2015 17:09:18 +0800 Message-ID: <20150309090917.2671.60110.stgit@perseus.themaw.net> In-Reply-To: <20150309085735.2671.64296.stgit@perseus.themaw.net> References: <20150309085735.2671.64296.stgit@perseus.themaw.net> User-Agent: StGit/0.17-dirty MIME-Version: 1.0 Cc: Hauke Mehrtens , OpenWrt-devel Subject: [OpenWrt-Devel] [PATCH 6/6] bcm5301x - R8000 handle PEX8603 switch X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: OpenWrt Development List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: openwrt-devel-bounces@lists.openwrt.org Sender: "openwrt-devel" The Netgear R8000 has a PEX8603 connected to the BCM53012 and if it isn't configured during the bus scan the PCI layer goes crazy trying to configure phantom devices. --- .../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.14/172-bcm5301x-R8000-handle-PEX8603-switch.patch b/target/linux/bcm53xx/patches-3.14/172-bcm5301x-R8000-handle-PEX8603-switch.patch new file mode 100644 index 0000000..e321845 --- /dev/null +++ b/target/linux/bcm53xx/patches-3.14/172-bcm5301x-R8000-handle-PEX8603-switch.patch @@ -0,0 +1,225 @@ +bcm5301x - 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 + +--- 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 ++ ++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); ++ ++ 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) { ++ 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 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..e321845 --- /dev/null +++ b/target/linux/bcm53xx/patches-3.18/172-bcm5301x-R8000-handle-PEX8603-switch.patch @@ -0,0 +1,225 @@ +bcm5301x - 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 + +--- 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 ++ ++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); ++ ++ 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) { ++ 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