diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 0c473d75e625..740e5b30d6fd 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -252,6 +252,14 @@ config PCIE_BUS_PEER2PEER
 
 endchoice
 
+config PCI_P2SB
+	bool "Primary to Sideband (P2SB) bridge access support"
+	depends on PCI && X86
+	help
+	  The Primary to Sideband bridge is an interface to some PCI
+	  devices connected through it. In particular, SPI NOR
+	  controller in Intel Apollo Lake SoC is one of such devices.
+
 source "drivers/pci/hotplug/Kconfig"
 source "drivers/pci/controller/Kconfig"
 source "drivers/pci/endpoint/Kconfig"
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index d62c4ac4ae1b..eee8d5dda7d9 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_PCI_IOV)		+= iov.o
 obj-$(CONFIG_PCI_BRIDGE_EMUL)	+= pci-bridge-emul.o
 obj-$(CONFIG_PCI_LABEL)		+= pci-label.o
 obj-$(CONFIG_X86_INTEL_MID)	+= pci-mid.o
+obj-$(CONFIG_PCI_P2SB)		+= pci-p2sb.o
 obj-$(CONFIG_PCI_SYSCALL)	+= syscall.o
 obj-$(CONFIG_PCI_STUB)		+= pci-stub.o
 obj-$(CONFIG_PCI_PF_STUB)	+= pci-pf-stub.o
diff --git a/drivers/pci/pci-p2sb.c b/drivers/pci/pci-p2sb.c
new file mode 100644
index 000000000000..68d7dad48cdb
--- /dev/null
+++ b/drivers/pci/pci-p2sb.c
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Primary to Sideband bridge (P2SB) access support
+ *
+ * Copyright (c) 2017, 2021 Intel Corporation.
+ *
+ * Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+ *	    Jonathan Yong <jonathan.yong@intel.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/export.h>
+#include <linux/pci-p2sb.h>
+
+#include <asm/cpu_device_id.h>
+#include <asm/intel-family.h>
+
+#include "pci.h"
+
+#define P2SBC_HIDE_BYTE			0xe1
+#define P2SBC_HIDE_BIT			BIT(0)
+
+static const struct x86_cpu_id p2sb_cpu_ids[] = {
+	X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT,	PCI_DEVFN(13, 0)),
+	{}
+};
+
+static int pci_p2sb_devfn(unsigned int *devfn)
+{
+	const struct x86_cpu_id *id;
+
+	id = x86_match_cpu(p2sb_cpu_ids);
+	if (!id)
+		return -ENODEV;
+
+	*devfn = (unsigned int)id->driver_data;
+	return 0;
+}
+
+/**
+ * pci_p2sb_bar - Get Primary to Sideband bridge (P2SB) device BAR
+ * @pdev:	PCI device to get a PCI bus to communicate with
+ * @devfn:	PCI slot and function to communicate with
+ * @mem:	memory resource to be filled in
+ *
+ * The BIOS prevents the P2SB device from being enumerated by the PCI
+ * subsystem, so we need to unhide and hide it back to lookup the BAR.
+ *
+ * Caller must provide a valid pointer to @mem.
+ *
+ * Locking is handled by pci_rescan_remove_lock mutex.
+ *
+ * Return:
+ * 0 on success or appropriate errno value on error.
+ */
+int pci_p2sb_bar(struct pci_dev *pdev, unsigned int devfn, struct resource *mem)
+{
+	struct pci_bus *bus = pdev->bus;
+	unsigned int df;
+	int ret;
+
+	/* Get devfn for P2SB device itself */
+	ret = pci_p2sb_devfn(&df);
+	if (ret)
+		return ret;
+
+	pci_lock_rescan_remove();
+
+	/* Unhide the P2SB device */
+	pci_bus_write_config_byte(bus, df, P2SBC_HIDE_BYTE, 0);
+
+	/* Read the first BAR of the device in question */
+	__pci_bus_read_base(bus, devfn, pci_bar_unknown, mem, PCI_BASE_ADDRESS_0, true);
+
+	/* Hide the P2SB device */
+	pci_bus_write_config_byte(bus, df, P2SBC_HIDE_BYTE, P2SBC_HIDE_BIT);
+
+	pci_unlock_rescan_remove();
+
+	pci_bus_info(bus, devfn, "BAR: %pR\n", mem);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pci_p2sb_bar);
diff --git a/include/linux/pci-p2sb.h b/include/linux/pci-p2sb.h
new file mode 100644
index 000000000000..15dd42737c84
--- /dev/null
+++ b/include/linux/pci-p2sb.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Primary to Sideband bridge (P2SB) access support
+ */
+
+#ifndef _PCI_P2SB_H
+#define _PCI_P2SB_H
+
+#include <linux/errno.h>
+
+struct pci_dev;
+struct resource;
+
+#if IS_BUILTIN(CONFIG_PCI_P2SB)
+
+int pci_p2sb_bar(struct pci_dev *pdev, unsigned int devfn, struct resource *mem);
+
+#else /* CONFIG_PCI_P2SB is not set */
+
+static inline
+int pci_p2sb_bar(struct pci_dev *pdev, unsigned int devfn, struct resource *mem)
+{
+	return -ENODEV;
+}
+
+#endif /* CONFIG_PCI_P2SB */
+
+#endif /* _PCI_P2SB_H */
