struct page *vmemmap __ro_after_init;
 EXPORT_SYMBOL(vmemmap);
 
+/*
+ * We create both ZONE_DMA and ZONE_DMA32. ZONE_DMA covers the first 1G of
+ * memory as some devices, namely the Raspberry Pi 4, have peripherals with
+ * this limited view of the memory. ZONE_DMA32 will cover the rest of the 32
+ * bit addressable memory area.
+ */
+phys_addr_t arm64_dma_phys_limit __ro_after_init;
 phys_addr_t arm64_dma32_phys_limit __ro_after_init;
 
 #ifdef CONFIG_KEXEC_CORE
 {
 }
 #endif /* CONFIG_CRASH_DUMP */
+
 /*
- * Return the maximum physical address for ZONE_DMA32 (DMA_BIT_MASK(32)). It
- * currently assumes that for memory starting above 4G, 32-bit devices will
- * use a DMA offset.
+ * Return the maximum physical address for a zone with a given address size
+ * limit. It currently assumes that for memory starting above 4G, 32-bit
+ * devices will use a DMA offset.
  */
-static phys_addr_t __init max_zone_dma32_phys(void)
+static phys_addr_t __init max_zone_phys(unsigned int zone_bits)
 {
-       phys_addr_t offset = memblock_start_of_DRAM() & GENMASK_ULL(63, 32);
-       return min(offset + (1ULL << 32), memblock_end_of_DRAM());
+       phys_addr_t offset = memblock_start_of_DRAM() & GENMASK_ULL(63, zone_bits);
+       return min(offset + (1ULL << zone_bits), memblock_end_of_DRAM());
 }
 
 #ifdef CONFIG_NUMA
 {
        unsigned long max_zone_pfns[MAX_NR_ZONES]  = {0};
 
+#ifdef CONFIG_ZONE_DMA
+       max_zone_pfns[ZONE_DMA] = PFN_DOWN(arm64_dma_phys_limit);
+#endif
 #ifdef CONFIG_ZONE_DMA32
        max_zone_pfns[ZONE_DMA32] = PFN_DOWN(arm64_dma32_phys_limit);
 #endif
        struct memblock_region *reg;
        unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
        unsigned long max_dma32 = min;
+       unsigned long max_dma = min;
 
        memset(zone_size, 0, sizeof(zone_size));
 
-       /* 4GB maximum for 32-bit only capable devices */
+#ifdef CONFIG_ZONE_DMA
+       max_dma = PFN_DOWN(arm64_dma_phys_limit);
+       zone_size[ZONE_DMA] = max_dma - min;
+       max_dma32 = max_dma;
+#endif
 #ifdef CONFIG_ZONE_DMA32
        max_dma32 = PFN_DOWN(arm64_dma32_phys_limit);
-       zone_size[ZONE_DMA32] = max_dma32 - min;
+       zone_size[ZONE_DMA32] = max_dma32 - max_dma;
 #endif
        zone_size[ZONE_NORMAL] = max - max_dma32;
 
 
                if (start >= max)
                        continue;
-
+#ifdef CONFIG_ZONE_DMA
+               if (start < max_dma) {
+                       unsigned long dma_end = min_not_zero(end, max_dma);
+                       zhole_size[ZONE_DMA] -= dma_end - start;
+               }
+#endif
 #ifdef CONFIG_ZONE_DMA32
                if (start < max_dma32) {
-                       unsigned long dma_end = min(end, max_dma32);
-                       zhole_size[ZONE_DMA32] -= dma_end - start;
+                       unsigned long dma32_end = min(end, max_dma32);
+                       unsigned long dma32_start = max(start, max_dma);
+                       zhole_size[ZONE_DMA32] -= dma32_end - dma32_start;
                }
 #endif
                if (end > max_dma32) {
 
        early_init_fdt_scan_reserved_mem();
 
-       /* 4GB maximum for 32-bit only capable devices */
+       if (IS_ENABLED(CONFIG_ZONE_DMA))
+               arm64_dma_phys_limit = max_zone_phys(ARCH_ZONE_DMA_BITS);
+
        if (IS_ENABLED(CONFIG_ZONE_DMA32))
-               arm64_dma32_phys_limit = max_zone_dma32_phys();
+               arm64_dma32_phys_limit = max_zone_phys(32);
        else
                arm64_dma32_phys_limit = PHYS_MASK + 1;
 
 
        high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
 
-       dma_contiguous_reserve(arm64_dma32_phys_limit);
+       dma_contiguous_reserve(arm64_dma_phys_limit ? : arm64_dma32_phys_limit);
 }
 
 void __init bootmem_init(void)
 void __init mem_init(void)
 {
        if (swiotlb_force == SWIOTLB_FORCE ||
-           max_pfn > (arm64_dma32_phys_limit >> PAGE_SHIFT))
+           max_pfn > PFN_DOWN(arm64_dma_phys_limit ? : arm64_dma32_phys_limit))
                swiotlb_init(1);
        else
                swiotlb_force = SWIOTLB_NO_FORCE;