#include <linux/sizes.h>
 #include <linux/device.h>
 #include <linux/dma-contiguous.h>
+#include <linux/decompress/generic.h>
 
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
        return 0;
 }
 
+/* In some conditions (e.g. big endian bootloader with a little endian
+   kernel), the initrd might appear byte swapped.  Try to detect this and
+   byte swap it if needed.  */
+static void __init maybe_bswap_initrd(void)
+{
+#if defined(CONFIG_CPU_CAVIUM_OCTEON)
+       u64 buf;
+
+       /* Check for CPIO signature */
+       if (!memcmp((void *)initrd_start, "070701", 6))
+               return;
+
+       /* Check for compressed initrd */
+       if (decompress_method((unsigned char *)initrd_start, 8, NULL))
+               return;
+
+       /* Try again with a byte swapped header */
+       buf = swab64p((u64 *)initrd_start);
+       if (!memcmp(&buf, "070701", 6) ||
+           decompress_method((unsigned char *)(&buf), 8, NULL)) {
+               unsigned long i;
+
+               pr_info("Byteswapped initrd detected\n");
+               for (i = initrd_start; i < ALIGN(initrd_end, 8); i += 8)
+                       swab64s((u64 *)i);
+       }
+#endif
+}
+
 static void __init finalize_initrd(void)
 {
        unsigned long size = initrd_end - initrd_start;
                goto disable;
        }
 
+       maybe_bswap_initrd();
+
        reserve_bootmem(__pa(initrd_start), size, BOOTMEM_DEFAULT);
        initrd_below_start_ok = 1;