[PATCH 1/3] staging: jnx: PCI quirks for all Juniper platforms
From: Pantelis Antoniou
Date: Fri Oct 07 2016 - 11:20:08 EST
From: Rajat Jain <rajatjain@xxxxxxxxxxx>
PCI quirks for all juniper platforms. This is located here
since the same PCI devices are present on both PPC and x86
platforms, so per-arch quirks are not appropriate.
Signed-off-by: Debjit Ghosh <dghosh@xxxxxxxxxxx>
Signed-off-by: Georgi Vlaev <gvlaev@xxxxxxxxxxx>
Signed-off-by: Guenter Roeck <groeck@xxxxxxxxxxx>
Signed-off-by: JawaharBalaji Thirumalaisamy <jawaharb@xxxxxxxxxxx>
Signed-off-by: Rajat Jain <rajatjain@xxxxxxxxxxx>
Signed-off-by: Shyamshankar Dharmarajan <shyamd@xxxxxxxxxxx>
[Ported from Juniper kernel]
Signed-off-by: Pantelis Antoniou <pantelis.antoniou@xxxxxxxxxxxx>
---
drivers/staging/jnx/Kconfig | 6 ++
drivers/staging/jnx/Makefile | 1 +
drivers/staging/jnx/jnx-chip-pci-quirks.c | 105 ++++++++++++++++++++++++++++++
3 files changed, 112 insertions(+)
create mode 100644 drivers/staging/jnx/jnx-chip-pci-quirks.c
diff --git a/drivers/staging/jnx/Kconfig b/drivers/staging/jnx/Kconfig
index 5d2b207..f01ef54 100644
--- a/drivers/staging/jnx/Kconfig
+++ b/drivers/staging/jnx/Kconfig
@@ -21,4 +21,10 @@ config JNX_SYSTEM
endmenu
+config JNX_CHIP_PCI_QUIRKS
+ bool
+ select PCI_MMCONFIG
+ ---help---
+ PCI quirks for the Juniper chips (ASICs, CPLDs, FPGAs)
+
endif # JNX_DEVICES
diff --git a/drivers/staging/jnx/Makefile b/drivers/staging/jnx/Makefile
index 52b8286..b29699c 100644
--- a/drivers/staging/jnx/Makefile
+++ b/drivers/staging/jnx/Makefile
@@ -3,3 +3,4 @@
#
obj-$(CONFIG_JNX_SYSTEM) += jnx-subsys.o jnx-board-core.o
+obj-$(CONFIG_JNX_CHIP_PCI_QUIRKS)+= jnx-chip-pci-quirks.o
diff --git a/drivers/staging/jnx/jnx-chip-pci-quirks.c b/drivers/staging/jnx/jnx-chip-pci-quirks.c
new file mode 100644
index 0000000..f90b4c7
--- /dev/null
+++ b/drivers/staging/jnx/jnx-chip-pci-quirks.c
@@ -0,0 +1,105 @@
+/*
+ * Common Juniper ASICs - PCI fixup code
+ *
+ * Guenter Roeck <groeck@xxxxxxxxxxx>
+ * Copyright 2012-2014 Juniper Networks
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation
+ */
+
+#include <linux/bitops.h>
+#include <linux/dmi.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/jnx/pci_ids.h>
+
+#define INTEL_DEBUG_REG 0x8F8
+#define INTEL_DEBUG_REG_IGNORE_GEN BIT(3)
+
+static void jnx_init_fpga(struct pci_dev *dev)
+{
+ /*
+ * PCI class reported by Juniper FPGAs (SAM/PAM) is
+ * "Unassigned class [ff00]". Change it to something more appropriate.
+ */
+ dev->class = PCI_CLASS_SYSTEM_OTHER << 8;
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JUNIPER, PCI_DEVICE_ID_JNX_SAM,
+ jnx_init_fpga);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JUNIPER, PCI_DEVICE_ID_JNX_SAM_OMEGA,
+ jnx_init_fpga);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JUNIPER, PCI_DEVICE_ID_JNX_SAM_X,
+ jnx_init_fpga);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JUNIPER, PCI_DEVICE_ID_JNX_PAM,
+ jnx_init_fpga);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JUNIPER, PCI_DEVICE_ID_JNX_CBC,
+ jnx_init_fpga);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JUNIPER, PCI_DEVICE_ID_JNX_CBC_P2,
+ jnx_init_fpga);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JUNIPER, PCI_DEVICE_ID_JNX_OMG_CBC,
+ jnx_init_fpga);
+
+static struct dmi_system_id jnx_asic_pci_bug_affected_platforms[] = {
+ {
+ .ident = "Juniper Networks PTX MLC Card",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Juniper Networks Inc."),
+ DMI_MATCH(DMI_BOARD_NAME, "0C0A")
+ },
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(dmi, jnx_asic_pci_bug_affected_platforms);
+
+/*
+ * Juniper Broadway ASICs have an issue where they report incorrect gen type
+ * (Gen-1 / Gen-2) for the PCIe link to the root port.
+ * This workaround needs to be applied to each Intel root port which connects
+ * to a juniper ASIC. It causes the root port to ignore the incorrect fields.
+ */
+static void fixup_intel_root_port(struct pci_dev *dev)
+{
+ struct pci_dev *rootport = dev;
+ u32 tmp32;
+ int ret = 0;
+
+ while (!pci_is_root_bus(rootport->bus))
+ rootport = pci_upstream_bridge(rootport);
+
+ if (rootport->vendor != PCI_VENDOR_ID_INTEL)
+ return;
+
+ ret = pci_read_config_dword(rootport, INTEL_DEBUG_REG, &tmp32);
+ tmp32 |= INTEL_DEBUG_REG_IGNORE_GEN;
+ ret |= pci_write_config_dword(rootport, INTEL_DEBUG_REG, tmp32);
+ if (ret)
+ dev_err(&rootport->dev,
+ "Error applying Intel root port quirk! CONFIG_PCI_MMCONFIG not selected?\n");
+}
+
+/*
+ * The TL/TQ ASICs report their device class as PCI_CLASS_NOT_DEFINED.
+ * Linux does not configure memory access for this class,
+ * so we have to ajust it to something acceptable.
+ */
+static void jnx_init_asic(struct pci_dev *dev)
+{
+ dev->class = PCI_CLASS_NETWORK_OTHER << 8;
+
+ if (dmi_check_system(jnx_asic_pci_bug_affected_platforms))
+ fixup_intel_root_port(dev);
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JUNIPER, PCI_DEVICE_ID_JNX_TF,
+ jnx_init_asic);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JUNIPER, PCI_DEVICE_ID_JNX_TL,
+ jnx_init_asic);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JUNIPER, PCI_DEVICE_ID_JNX_TQ,
+ jnx_init_asic);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JUNIPER, PCI_DEVICE_ID_JNX_OTN_FRAMER,
+ jnx_init_asic);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JUNIPER, PCI_DEVICE_ID_JNX_PE,
+ jnx_init_asic);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JUNIPER, PCI_DEVICE_ID_JNX_PF,
+ jnx_init_asic);
--
1.9.1