@@ -23,6 +23,7 @@
#include <linux/slab.h>
#include <asm/pci-bridge.h>
+#include "pci_quirks.h"
/*
* Called after each bus is probed, but before its children are examined
@@ -230,6 +231,43 @@ static struct acpi_pci_root_ops acpi_pci_root_ops = {
.prepare_resources = pci_acpi_root_prepare_resources,
};
+/*
+ * List of acpi_scan_handlers according to the specific
+ * Host Bridge controllers that are non ECAM compliant
+ */
+static struct acpi_scan_handler *quirks_array[] = {
+ 0
+};
+
+void acpi_arm64_quirks(void)
+{
+ int i = 0;
+
+ while (quirks_array[i]) {
+ acpi_scan_add_handler(quirks_array[i]);
+ i++;
+ }
+
+}
+
+/*
+ * pci_ops specified by vendors that are not
+ * ECAM compliant
+ */
+struct pci_ops *vendor_specific_ops;
+
+/* function to set vendor specific ops */
+void set_quirk_pci_ops(struct pci_ops *quirk_ops)
+{
+ vendor_specific_ops = quirk_ops;
+}
+
+/* function to unset vendor specific ops */
+void unset_quirk_pci_ops(void)
+{
+ vendor_specific_ops = NULL;
+}
+
/* Root bridge scanning */
struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
{
@@ -253,6 +291,9 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
return NULL;
}
+ if (vendor_specific_ops)
+ acpi_pci_root_ops.pci_ops = vendor_specific_ops;
+
bus = acpi_pci_root_create(root, &acpi_pci_root_ops, info, root);
/* After the PCI-E bus has been walked and all devices discovered,
new file mode 100644
@@ -0,0 +1,24 @@
+/*
+ * PCIe host controller declarations for ACPI quirks
+ *
+ * Copyright (C) 2015 HiSilicon Co., Ltd. http://www.hisilicon.com
+ *
+ *
+ * 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.
+ */
+
+#ifndef PCI_QUIRKS_H
+#define PCI_QUIRKS_H
+
+/* declarations of vendor specific quirks */
+extern struct acpi_scan_handler pci_root_hisi_handler;
+
+/* function to set vendor specific ops */
+void set_quirk_pci_ops(struct pci_ops *quirk_ops);
+
+/* function to unset vendor specific ops */
+void unset_quirk_pci_ops(void);
+
+#endif /*PCI_QUIRKS_H*/
@@ -863,5 +863,9 @@ void __init acpi_pci_root_init(void)
return;
pci_acpi_crs_quirks();
+
+ /* Call quirks for non ECAM ARM64 Host Brdge controllers */
+ acpi_arm64_quirks();
+
acpi_scan_add_handler_with_hotplug(&pci_root_handler, "pci_root");
}
@@ -99,6 +99,12 @@ void pci_acpi_crs_quirks(void);
static inline void pci_acpi_crs_quirks(void) { }
#endif
+#ifdef CONFIG_ARM64
+void acpi_arm64_quirks(void);
+#else
+static inline void acpi_arm64_quirks(void) { }
+#endif
+
/* --------------------------------------------------------------------------
Processor
-------------------------------------------------------------------------- */