summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHauke Mehrtens <hauke@hauke-m.de>2014-12-18 16:23:42 +0000
committerHauke Mehrtens <hauke@hauke-m.de>2014-12-18 16:23:42 +0000
commit192e945479a9c90eb7d6a3ff563084cb558ba31a (patch)
treefd77444cad07b38718519d5a18f65c506374f9be
parent180c1f330287fef2089d38d5b7bad063888a008a (diff)
downloadmtk-20170518-192e945479a9c90eb7d6a3ff563084cb558ba31a.zip
mtk-20170518-192e945479a9c90eb7d6a3ff563084cb558ba31a.tar.gz
mtk-20170518-192e945479a9c90eb7d6a3ff563084cb558ba31a.tar.bz2
bcm53xx: PCIe: add link check again
When there is no device connected to the controller we should not start the controller. This also changes between PCIe 1.0 and PCIe 2.0 speed based on the device. This code is based on code from the new Broadcom PCIe controller driver. Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> SVN-Revision: 43748
-rw-r--r--target/linux/bcm53xx/patches-3.14/170-pcie2-bcma-add-new-PCIe2-driver-for-bcma.patch81
-rw-r--r--target/linux/bcm53xx/patches-3.18/170-pcie2-bcma-add-new-PCIe2-driver-for-bcma.patch81
2 files changed, 112 insertions, 50 deletions
diff --git a/target/linux/bcm53xx/patches-3.14/170-pcie2-bcma-add-new-PCIe2-driver-for-bcma.patch b/target/linux/bcm53xx/patches-3.14/170-pcie2-bcma-add-new-PCIe2-driver-for-bcma.patch
index dcdbb8f..e963133 100644
--- a/target/linux/bcm53xx/patches-3.14/170-pcie2-bcma-add-new-PCIe2-driver-for-bcma.patch
+++ b/target/linux/bcm53xx/patches-3.14/170-pcie2-bcma-add-new-PCIe2-driver-for-bcma.patch
@@ -72,7 +72,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+obj-$(CONFIG_PCI_BCM5301X) += pci-host-bcm5301x.o
--- /dev/null
+++ b/drivers/pci/host/pci-host-bcm5301x.c
-@@ -0,0 +1,428 @@
+@@ -0,0 +1,459 @@
+/*
+ * Northstar PCI-Express driver
+ * Only supports Root-Complex (RC) mode
@@ -94,13 +94,16 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
-+#include <linux/interrupt.h>
+#include <linux/bcma/bcma.h>
+#include <linux/bcma/bcma_driver_pcie2.h>
-+#include <linux/of_irq.h>
+
+#define SOC_PCIE_HDR_OFF 0x400 /* 256 bytes per function */
+
++#define PCI_LINK_STATUS_CTRL_2_OFFSET 0xDC
++#define PCI_TARGET_LINK_SPEED_MASK 0xF
++#define PCI_TARGET_LINK_SPEED_GEN2 0x2
++#define PCI_TARGET_LINK_SPEED_GEN1 0x1
++
+static int bcma_pcie2_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
+{
+ struct pci_sys_data *sys = pdev->sysdata;
@@ -222,31 +225,59 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ * Check link status, return 0 if link is up in RC mode,
+ * otherwise return non-zero
+ */
-+static int bcma_pcie2_check_link(struct bcma_device *bdev, bool allow_gen2)
++static int bcma_pcie2_check_link(struct bcma_device *bdev, struct pci_sys_data *sys)
+{
-+ u32 devfn = 0;
+ u32 tmp32;
-+ u8 tmp8;
-+
-+ tmp32 = bcma_pcie2_read_config(bdev, 0, devfn, 0xdc, 4);
-+ tmp32 &= ~0xf;
-+ if (allow_gen2)
-+ tmp32 |= 2;
-+ else {
-+ /* force PCIE GEN1 */
-+ tmp32 |= 1;
-+ }
-+ bcma_pcie2_write_config(bdev, 0, devfn, 0xdc, 4, tmp32);
-+
-+ /* See if the port is in EP mode, indicated by header type 00 */
-+ tmp8 = bcma_pcie2_read_config(bdev, 0, devfn, PCI_HEADER_TYPE, 1);
-+ if (tmp8 != PCI_HEADER_TYPE_BRIDGE) {
-+ dev_info(&bdev->dev, "Port %d in End-Point mode - ignored\n",
-+ bdev->core_unit);
-+ return -ENODEV;
++ u16 tmp16;
++ u16 pos;
++ u8 nlw;
++ /*
++ * Setup callback (bcma_pcie2_setup) is called in pcibios_init_hw before
++ * creating bus root, so we don't have it here yet. On the other hand
++ * we really want to use pci_bus_find_capability helper to check NLW.
++ * Let's fake simple pci_bus just to query for capabilities.
++ */
++ struct pci_bus bus = {
++ .number = 0,
++ .ops = &bcma_pcie2_ops,
++ .sysdata = sys,
++ };
++
++ tmp32 = bcma_read32(bdev, BCMA_CORE_PCIE2_LINK_STATUS);
++ dev_dbg(&bdev->dev, "link status: 0x%08x\n", tmp32);
++
++ tmp32 = bcma_read32(bdev, BCMA_CORE_PCIE2_STRAP_STATUS);
++ dev_dbg(&bdev->dev, "strap status: 0x%08x\n", tmp32);
++
++ /* check link status to see if link is active */
++ pos = pci_bus_find_capability(&bus, 0, PCI_CAP_ID_EXP);
++ pci_bus_read_config_word(&bus, 0, pos + PCI_EXP_LNKSTA, &tmp16);
++ nlw = (tmp16 & PCI_EXP_LNKSTA_NLW) >> PCI_EXP_LNKSTA_NLW_SHIFT;
++
++ if (nlw == 0) {
++ /* try GEN 1 link speed */
++ tmp32 = bcma_pcie2_read_config(bdev, 0, 0,
++ PCI_LINK_STATUS_CTRL_2_OFFSET, 4);
++ if ((tmp32 & PCI_TARGET_LINK_SPEED_MASK) ==
++ PCI_TARGET_LINK_SPEED_GEN2) {
++ tmp32 &= ~PCI_TARGET_LINK_SPEED_MASK;
++ tmp32 |= PCI_TARGET_LINK_SPEED_GEN1;
++ bcma_pcie2_write_config(bdev, 0, 0,
++ PCI_LINK_STATUS_CTRL_2_OFFSET, 4, tmp32);
++ tmp32 = bcma_pcie2_read_config(bdev, 0, 0,
++ PCI_LINK_STATUS_CTRL_2_OFFSET, 4);
++ msleep(100);
++
++ pos = pci_bus_find_capability(&bus, 0, PCI_CAP_ID_EXP);
++ pci_bus_read_config_word(&bus, 0, pos + PCI_EXP_LNKSTA,
++ &tmp16);
++ nlw = (tmp16 & PCI_EXP_LNKSTA_NLW) >>
++ PCI_EXP_LNKSTA_NLW_SHIFT;
++ }
+ }
+
-+ return 0;
++ dev_info(&bdev->dev, "link: %s\n", nlw ? "UP" : "DOWN");
++ return nlw ? 0 : -ENODEV;
+}
+
+/*
@@ -438,7 +469,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ * Skip inactive ports -
+ * will need to change this for hot-plugging
+ */
-+ ret = bcma_pcie2_check_link(bdev, true);
++ ret = bcma_pcie2_check_link(bdev, sys);
+ if (ret)
+ return ret;
+
diff --git a/target/linux/bcm53xx/patches-3.18/170-pcie2-bcma-add-new-PCIe2-driver-for-bcma.patch b/target/linux/bcm53xx/patches-3.18/170-pcie2-bcma-add-new-PCIe2-driver-for-bcma.patch
index fc616d7..1a84604 100644
--- a/target/linux/bcm53xx/patches-3.18/170-pcie2-bcma-add-new-PCIe2-driver-for-bcma.patch
+++ b/target/linux/bcm53xx/patches-3.18/170-pcie2-bcma-add-new-PCIe2-driver-for-bcma.patch
@@ -72,7 +72,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+obj-$(CONFIG_PCI_BCM5301X) += pci-host-bcm5301x.o
--- /dev/null
+++ b/drivers/pci/host/pci-host-bcm5301x.c
-@@ -0,0 +1,428 @@
+@@ -0,0 +1,459 @@
+/*
+ * Northstar PCI-Express driver
+ * Only supports Root-Complex (RC) mode
@@ -94,13 +94,16 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
-+#include <linux/interrupt.h>
+#include <linux/bcma/bcma.h>
+#include <linux/bcma/bcma_driver_pcie2.h>
-+#include <linux/of_irq.h>
+
+#define SOC_PCIE_HDR_OFF 0x400 /* 256 bytes per function */
+
++#define PCI_LINK_STATUS_CTRL_2_OFFSET 0xDC
++#define PCI_TARGET_LINK_SPEED_MASK 0xF
++#define PCI_TARGET_LINK_SPEED_GEN2 0x2
++#define PCI_TARGET_LINK_SPEED_GEN1 0x1
++
+static int bcma_pcie2_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
+{
+ struct pci_sys_data *sys = pdev->sysdata;
@@ -222,31 +225,59 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ * Check link status, return 0 if link is up in RC mode,
+ * otherwise return non-zero
+ */
-+static int bcma_pcie2_check_link(struct bcma_device *bdev, bool allow_gen2)
++static int bcma_pcie2_check_link(struct bcma_device *bdev, struct pci_sys_data *sys)
+{
-+ u32 devfn = 0;
+ u32 tmp32;
-+ u8 tmp8;
-+
-+ tmp32 = bcma_pcie2_read_config(bdev, 0, devfn, 0xdc, 4);
-+ tmp32 &= ~0xf;
-+ if (allow_gen2)
-+ tmp32 |= 2;
-+ else {
-+ /* force PCIE GEN1 */
-+ tmp32 |= 1;
-+ }
-+ bcma_pcie2_write_config(bdev, 0, devfn, 0xdc, 4, tmp32);
-+
-+ /* See if the port is in EP mode, indicated by header type 00 */
-+ tmp8 = bcma_pcie2_read_config(bdev, 0, devfn, PCI_HEADER_TYPE, 1);
-+ if (tmp8 != PCI_HEADER_TYPE_BRIDGE) {
-+ dev_info(&bdev->dev, "Port %d in End-Point mode - ignored\n",
-+ bdev->core_unit);
-+ return -ENODEV;
++ u16 tmp16;
++ u16 pos;
++ u8 nlw;
++ /*
++ * Setup callback (bcma_pcie2_setup) is called in pcibios_init_hw before
++ * creating bus root, so we don't have it here yet. On the other hand
++ * we really want to use pci_bus_find_capability helper to check NLW.
++ * Let's fake simple pci_bus just to query for capabilities.
++ */
++ struct pci_bus bus = {
++ .number = 0,
++ .ops = &bcma_pcie2_ops,
++ .sysdata = sys,
++ };
++
++ tmp32 = bcma_read32(bdev, BCMA_CORE_PCIE2_LINK_STATUS);
++ dev_dbg(&bdev->dev, "link status: 0x%08x\n", tmp32);
++
++ tmp32 = bcma_read32(bdev, BCMA_CORE_PCIE2_STRAP_STATUS);
++ dev_dbg(&bdev->dev, "strap status: 0x%08x\n", tmp32);
++
++ /* check link status to see if link is active */
++ pos = pci_bus_find_capability(&bus, 0, PCI_CAP_ID_EXP);
++ pci_bus_read_config_word(&bus, 0, pos + PCI_EXP_LNKSTA, &tmp16);
++ nlw = (tmp16 & PCI_EXP_LNKSTA_NLW) >> PCI_EXP_LNKSTA_NLW_SHIFT;
++
++ if (nlw == 0) {
++ /* try GEN 1 link speed */
++ tmp32 = bcma_pcie2_read_config(bdev, 0, 0,
++ PCI_LINK_STATUS_CTRL_2_OFFSET, 4);
++ if ((tmp32 & PCI_TARGET_LINK_SPEED_MASK) ==
++ PCI_TARGET_LINK_SPEED_GEN2) {
++ tmp32 &= ~PCI_TARGET_LINK_SPEED_MASK;
++ tmp32 |= PCI_TARGET_LINK_SPEED_GEN1;
++ bcma_pcie2_write_config(bdev, 0, 0,
++ PCI_LINK_STATUS_CTRL_2_OFFSET, 4, tmp32);
++ tmp32 = bcma_pcie2_read_config(bdev, 0, 0,
++ PCI_LINK_STATUS_CTRL_2_OFFSET, 4);
++ msleep(100);
++
++ pos = pci_bus_find_capability(&bus, 0, PCI_CAP_ID_EXP);
++ pci_bus_read_config_word(&bus, 0, pos + PCI_EXP_LNKSTA,
++ &tmp16);
++ nlw = (tmp16 & PCI_EXP_LNKSTA_NLW) >>
++ PCI_EXP_LNKSTA_NLW_SHIFT;
++ }
+ }
+
-+ return 0;
++ dev_info(&bdev->dev, "link: %s\n", nlw ? "UP" : "DOWN");
++ return nlw ? 0 : -ENODEV;
+}
+
+/*
@@ -438,7 +469,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ * Skip inactive ports -
+ * will need to change this for hot-plugging
+ */
-+ ret = bcma_pcie2_check_link(bdev, true);
++ ret = bcma_pcie2_check_link(bdev, sys);
+ if (ret)
+ return ret;
+