diff --git a/MAINTAINERS b/MAINTAINERS
index e64e5db314976dc9f73107c9bd616aeaa3dd9c70..a64a1fed74ccb4dc607beac4c82d824fbdefe35c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1336,6 +1336,7 @@ F:	arch/arm/mach-integrator/
 F:	arch/arm/mach-realview/
 F:	arch/arm/mach-versatile/
 F:	arch/arm/plat-versatile/
+F:	drivers/bus/arm-integrator-lm.c
 F:	drivers/clk/versatile/
 F:	drivers/i2c/busses/i2c-versatile.c
 F:	drivers/irqchip/irq-versatile-fpga.c
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 6d4e4497b59b243a2898561af1947102b8f8c05f..d4c8898868fc436fab3fcbaf4b0295767d7cbc3c 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -20,6 +20,15 @@ config ARM_CCI400_PORT_CTRL
 	  Low level power management driver for CCI400 cache coherent
 	  interconnect for ARM platforms.
 
+config ARM_INTEGRATOR_LM
+	bool "ARM Integrator Logic Module bus"
+	depends on HAS_IOMEM
+	depends on ARCH_INTEGRATOR || COMPILE_TEST
+	default ARCH_INTEGRATOR
+	help
+	  Say y here to enable support for the ARM Logic Module bus
+	  found on the ARM Integrator AP (Application Platform)
+
 config BRCMSTB_GISB_ARB
 	bool "Broadcom STB GISB bus arbiter"
 	depends on ARM || ARM64 || MIPS
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index 05f32cd694a41522f9b0fbcda2fde0366d427dbc..97552b427f12f0a0a6f0de2573d7074180a3146e 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -5,7 +5,7 @@
 
 # Interconnect bus drivers for ARM platforms
 obj-$(CONFIG_ARM_CCI)		+= arm-cci.o
-
+obj-$(CONFIG_ARM_INTEGRATOR_LM)	+= arm-integrator-lm.o
 obj-$(CONFIG_HISILICON_LPC)	+= hisi_lpc.o
 obj-$(CONFIG_BRCMSTB_GISB_ARB)	+= brcmstb_gisb.o
 obj-$(CONFIG_MOXTET)		+= moxtet.o
diff --git a/drivers/bus/arm-integrator-lm.c b/drivers/bus/arm-integrator-lm.c
new file mode 100644
index 0000000000000000000000000000000000000000..669ea7e1f92e9052ba679387cc8f5a1205ee1c9c
--- /dev/null
+++ b/drivers/bus/arm-integrator-lm.c
@@ -0,0 +1,128 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * ARM Integrator Logical Module bus driver
+ * Copyright (C) 2020 Linaro Ltd.
+ * Author: Linus Walleij <linus.walleij@linaro.org>
+ *
+ * See the device tree bindings for this block for more details on the
+ * hardware.
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/bitops.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+
+/* All information about the connected logic modules are in here */
+#define INTEGRATOR_SC_DEC_OFFSET	0x10
+
+/* Base address for the expansion modules */
+#define INTEGRATOR_AP_EXP_BASE		0xc0000000
+#define INTEGRATOR_AP_EXP_STRIDE	0x10000000
+
+static int integrator_lm_populate(int num, struct device *dev)
+{
+	struct device_node *np = dev->of_node;
+	struct device_node *child;
+	u32 base;
+	int ret;
+
+	base = INTEGRATOR_AP_EXP_BASE + (num * INTEGRATOR_AP_EXP_STRIDE);
+
+	/* Walk over the child nodes and see what chipselects we use */
+	for_each_available_child_of_node(np, child) {
+		struct resource res;
+
+		ret = of_address_to_resource(child, 0, &res);
+		if (ret) {
+			dev_info(dev, "no valid address on child\n");
+			continue;
+		}
+
+		/* First populate the syscon then any devices */
+		if (res.start == base) {
+			dev_info(dev, "populate module @0x%08x from DT\n",
+				 base);
+			ret = of_platform_default_populate(child, NULL, dev);
+			if (ret) {
+				dev_err(dev, "failed to populate module\n");
+				return ret;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static const struct of_device_id integrator_ap_syscon_match[] = {
+	{ .compatible = "arm,integrator-ap-syscon"},
+	{ },
+};
+
+static int integrator_ap_lm_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *syscon;
+	static struct regmap *map;
+	u32 val;
+	int ret;
+	int i;
+
+	/* Look up the system controller */
+	syscon = of_find_matching_node(NULL, integrator_ap_syscon_match);
+	if (IS_ERR(syscon)) {
+		dev_err(dev,
+			"could not find Integrator/AP system controller\n");
+		return PTR_ERR(syscon);
+	}
+	map = syscon_node_to_regmap(syscon);
+	if (IS_ERR(map)) {
+		dev_err(dev,
+			"could not find Integrator/AP system controller\n");
+		return PTR_ERR(map);
+	}
+
+	ret = regmap_read(map, INTEGRATOR_SC_DEC_OFFSET, &val);
+	if (ret) {
+		dev_err(dev, "could not read from Integrator/AP syscon\n");
+		return ret;
+	}
+
+	/* Loop over the connected modules */
+	for (i = 0; i < 4; i++) {
+		if (!(val & BIT(4 + i)))
+			continue;
+
+		dev_info(dev, "detected module in slot %d\n", i);
+		ret = integrator_lm_populate(i, dev);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static const struct of_device_id integrator_ap_lm_match[] = {
+	{ .compatible = "arm,integrator-ap-lm"},
+	{ },
+};
+
+static struct platform_driver integrator_ap_lm_driver = {
+	.probe = integrator_ap_lm_probe,
+	.driver = {
+		.name = "integratorap-lm",
+		.of_match_table = integrator_ap_lm_match,
+	},
+};
+module_platform_driver(integrator_ap_lm_driver);
+MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
+MODULE_DESCRIPTION("Integrator AP Logical Module driver");
+MODULE_LICENSE("GPL v2");