diff --git a/arch/arm/include/asm/dma-direct.h b/arch/arm/include/asm/dma-direct.h
index 77fcb7ee5ec907..1f04a5e1c615de 100644
--- a/arch/arm/include/asm/dma-direct.h
+++ b/arch/arm/include/asm/dma-direct.h
@@ -13,12 +13,12 @@ static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn)
 {
 	if (dev && dev->dma_range_map)
 		pfn = PFN_DOWN(translate_phys_to_dma(dev, PFN_PHYS(pfn)));
-	return (dma_addr_t)__pfn_to_bus(pfn);
+	return (dma_addr_t)__pfn_to_phys(pfn);
 }
 
 static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr)
 {
-	unsigned long pfn = __bus_to_pfn(addr);
+	unsigned long pfn = __phys_to_pfn(addr);
 
 	if (dev && dev->dma_range_map)
 		pfn = PFN_DOWN(translate_dma_to_phys(dev, PFN_PHYS(pfn)));
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index 99035b5891ef44..af612606136ff2 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -346,8 +346,6 @@ static inline unsigned long __virt_to_idmap(unsigned long x)
 #ifndef __virt_to_bus
 #define __virt_to_bus	__virt_to_phys
 #define __bus_to_virt	__phys_to_virt
-#define __pfn_to_bus(x)	__pfn_to_phys(x)
-#define __bus_to_pfn(x)	__phys_to_pfn(x)
 #endif
 
 /*
diff --git a/arch/arm/mach-footbridge/cats-pci.c b/arch/arm/mach-footbridge/cats-pci.c
index 0b2fd7e2e9b429..257cb068ac0c5b 100644
--- a/arch/arm/mach-footbridge/cats-pci.c
+++ b/arch/arm/mach-footbridge/cats-pci.c
@@ -13,6 +13,7 @@
 #include <asm/irq.h>
 #include <asm/mach/pci.h>
 #include <asm/mach-types.h>
+#include "common.h"
 
 /* cats host-specific stuff */
 static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 };
@@ -56,8 +57,10 @@ static struct hw_pci cats_pci __initdata = {
 
 static int __init cats_pci_init(void)
 {
-	if (machine_is_cats())
-		pci_common_init(&cats_pci);
+	if (!machine_is_cats())
+		return 0;
+	bus_register_notifier(&pci_bus_type, &footbridge_pci_dma_nb);
+	pci_common_init(&cats_pci);
 	return 0;
 }
 
diff --git a/arch/arm/mach-footbridge/common.c b/arch/arm/mach-footbridge/common.c
index eee095f0e2f6c2..dc14d72ca7bb3f 100644
--- a/arch/arm/mach-footbridge/common.c
+++ b/arch/arm/mach-footbridge/common.c
@@ -12,6 +12,8 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/spinlock.h>
+#include <linux/device/bus.h>
+#include <linux/dma-mapping.h>
 #include <video/vga.h>
 
 #include <asm/page.h>
@@ -219,8 +221,17 @@ void footbridge_restart(enum reboot_mode mode, const char *cmd)
 	}
 }
 
-#ifdef CONFIG_FOOTBRIDGE_ADDIN
-
+#ifdef CONFIG_FOOTBRIDGE_HOST
+/*
+ * The footbridge is programmed to expose the system RAM at 0xe0000000.
+ * The requirement is that the RAM isn't placed at bus address 0, which
+ * would clash with VGA cards.
+ */
+static inline unsigned long fb_bus_sdram_offset(void)
+{
+	return 0xe0000000;
+}
+#elif defined(CONFIG_FOOTBRIDGE_ADDIN)
 static inline unsigned long fb_bus_sdram_offset(void)
 {
 	return *CSR_PCISDRAMBASE & 0xfffffff0;
@@ -248,17 +259,24 @@ unsigned long __bus_to_virt(unsigned long res)
 	return res;
 }
 EXPORT_SYMBOL(__bus_to_virt);
+#else
+#error "Undefined footbridge mode"
+#endif
 
-unsigned long __pfn_to_bus(unsigned long pfn)
+static int footbridge_pci_dma_notifier(struct notifier_block *nb,
+		unsigned long event, void *data)
 {
-	return __pfn_to_phys(pfn) + (fb_bus_sdram_offset() - PHYS_OFFSET);
-}
-EXPORT_SYMBOL(__pfn_to_bus);
+	struct device *dev = data;
 
-unsigned long __bus_to_pfn(unsigned long bus)
-{
-	return __phys_to_pfn(bus - (fb_bus_sdram_offset() - PHYS_OFFSET));
+	if (event != BUS_NOTIFY_ADD_DEVICE)
+		return NOTIFY_DONE;
+
+	if (dma_direct_set_offset(dev, PAGE_OFFSET, fb_bus_sdram_offset(),
+			(u64)-1))
+		WARN_ONCE(1, "failed to set DMA offset\n");
+	return NOTIFY_OK;
 }
-EXPORT_SYMBOL(__bus_to_pfn);
 
-#endif
+struct notifier_block footbridge_pci_dma_nb = {
+	.notifier_call		= footbridge_pci_dma_notifier,
+};
diff --git a/arch/arm/mach-footbridge/common.h b/arch/arm/mach-footbridge/common.h
index e12587db59c4c8..1773a4183b580c 100644
--- a/arch/arm/mach-footbridge/common.h
+++ b/arch/arm/mach-footbridge/common.h
@@ -1,4 +1,5 @@
 /* SPDX-License-Identifier: GPL-2.0 */
+#include <linux/notifier.h>
 #include <linux/reboot.h>
 
 extern void footbridge_timer_init(void);
@@ -13,3 +14,5 @@ extern void isa_init_irq(unsigned int irq);
 extern void footbridge_restart(enum reboot_mode, const char *);
 
 extern void footbridge_sched_clock(void);
+
+extern struct notifier_block footbridge_pci_dma_nb;
diff --git a/arch/arm/mach-footbridge/ebsa285-pci.c b/arch/arm/mach-footbridge/ebsa285-pci.c
index 6f28aaa9ca79b2..80b4f5ace20b35 100644
--- a/arch/arm/mach-footbridge/ebsa285-pci.c
+++ b/arch/arm/mach-footbridge/ebsa285-pci.c
@@ -13,6 +13,7 @@
 #include <asm/irq.h>
 #include <asm/mach/pci.h>
 #include <asm/mach-types.h>
+#include "common.h"
 
 static int irqmap_ebsa285[] __initdata = { IRQ_IN3, IRQ_IN1, IRQ_IN0, IRQ_PCI };
 
@@ -40,8 +41,10 @@ static struct hw_pci ebsa285_pci __initdata = {
 
 static int __init ebsa285_init_pci(void)
 {
-	if (machine_is_ebsa285())
-		pci_common_init(&ebsa285_pci);
+	if (!machine_is_ebsa285())
+		return 0;
+	bus_register_notifier(&pci_bus_type, &footbridge_pci_dma_nb);
+	pci_common_init(&ebsa285_pci);
 	return 0;
 }
 
diff --git a/arch/arm/mach-footbridge/include/mach/memory.h b/arch/arm/mach-footbridge/include/mach/memory.h
index 46fd4a8872b9a3..3a5d2638c18f88 100644
--- a/arch/arm/mach-footbridge/include/mach/memory.h
+++ b/arch/arm/mach-footbridge/include/mach/memory.h
@@ -26,8 +26,6 @@
 #ifndef __ASSEMBLY__
 extern unsigned long __virt_to_bus(unsigned long);
 extern unsigned long __bus_to_virt(unsigned long);
-extern unsigned long __pfn_to_bus(unsigned long);
-extern unsigned long __bus_to_pfn(unsigned long);
 #endif
 #define __virt_to_bus	__virt_to_bus
 #define __bus_to_virt	__bus_to_virt
@@ -42,8 +40,6 @@ extern unsigned long __bus_to_pfn(unsigned long);
 #define BUS_OFFSET		0xe0000000
 #define __virt_to_bus(x)	((x) + (BUS_OFFSET - PAGE_OFFSET))
 #define __bus_to_virt(x)	((x) - (BUS_OFFSET - PAGE_OFFSET))
-#define __pfn_to_bus(x)		(__pfn_to_phys(x) + (BUS_OFFSET - PHYS_OFFSET))
-#define __bus_to_pfn(x)		__phys_to_pfn((x) - (BUS_OFFSET - PHYS_OFFSET))
 
 #else
 
diff --git a/arch/arm/mach-footbridge/netwinder-pci.c b/arch/arm/mach-footbridge/netwinder-pci.c
index 9473aa0305e5f7..68dac9446e7f44 100644
--- a/arch/arm/mach-footbridge/netwinder-pci.c
+++ b/arch/arm/mach-footbridge/netwinder-pci.c
@@ -13,6 +13,7 @@
 #include <asm/irq.h>
 #include <asm/mach/pci.h>
 #include <asm/mach-types.h>
+#include "common.h"
 
 /*
  * We now use the slot ID instead of the device identifiers to select
@@ -54,8 +55,10 @@ static struct hw_pci netwinder_pci __initdata = {
 
 static int __init netwinder_pci_init(void)
 {
-	if (machine_is_netwinder())
-		pci_common_init(&netwinder_pci);
+	if (!machine_is_netwinder())
+		return 0;
+	bus_register_notifier(&pci_bus_type, &footbridge_pci_dma_nb);
+	pci_common_init(&netwinder_pci);
 	return 0;
 }
 
diff --git a/arch/arm/mach-footbridge/personal-pci.c b/arch/arm/mach-footbridge/personal-pci.c
index 4391e433a4b2fc..5d6759e158b9d0 100644
--- a/arch/arm/mach-footbridge/personal-pci.c
+++ b/arch/arm/mach-footbridge/personal-pci.c
@@ -13,6 +13,7 @@
 #include <asm/irq.h>
 #include <asm/mach/pci.h>
 #include <asm/mach-types.h>
+#include "common.h"
 
 static int irqmap_personal_server[] __initdata = {
 	IRQ_IN0, IRQ_IN1, IRQ_IN2, IRQ_IN3, 0, 0, 0,
@@ -50,8 +51,10 @@ static struct hw_pci personal_server_pci __initdata = {
 
 static int __init personal_pci_init(void)
 {
-	if (machine_is_personal_server())
-		pci_common_init(&personal_server_pci);
+	if (!machine_is_personal_server())
+		return 0;
+	bus_register_notifier(&pci_bus_type, &footbridge_pci_dma_nb);
+	pci_common_init(&personal_server_pci);
 	return 0;
 }
 
