platforms += cobalt
 platforms += dec
 platforms += emma
+platforms += generic
 platforms += jazz
 platforms += jz4740
 platforms += lantiq
 
        prompt "System type"
        default SGI_IP22
 
+config MIPS_GENERIC
+       bool "Generic board-agnostic MIPS kernel"
+       select BOOT_RAW
+       select BUILTIN_DTB
+       select CEVT_R4K
+       select CLKSRC_MIPS_GIC
+       select COMMON_CLK
+       select CPU_MIPSR2_IRQ_VI
+       select CPU_MIPSR2_IRQ_EI
+       select CSRC_R4K
+       select DMA_PERDEV_COHERENT
+       select HW_HAS_PCI
+       select IRQ_MIPS_CPU
+       select LIBFDT
+       select MIPS_CPU_SCACHE
+       select MIPS_GIC
+       select MIPS_L1_CACHE_SHIFT_7
+       select NO_EXCEPT_FILL
+       select PCI_DRIVERS_GENERIC
+       select PINCTRL
+       select SMP_UP if SMP
+       select SYS_HAS_CPU_MIPS32_R1
+       select SYS_HAS_CPU_MIPS32_R2
+       select SYS_HAS_CPU_MIPS32_R6
+       select SYS_HAS_CPU_MIPS64_R1
+       select SYS_HAS_CPU_MIPS64_R2
+       select SYS_HAS_CPU_MIPS64_R6
+       select SYS_SUPPORTS_32BIT_KERNEL
+       select SYS_SUPPORTS_64BIT_KERNEL
+       select SYS_SUPPORTS_BIG_ENDIAN
+       select SYS_SUPPORTS_HIGHMEM
+       select SYS_SUPPORTS_LITTLE_ENDIAN
+       select SYS_SUPPORTS_MICROMIPS
+       select SYS_SUPPORTS_MIPS_CPS
+       select SYS_SUPPORTS_MIPS16
+       select SYS_SUPPORTS_MULTITHREADING
+       select SYS_SUPPORTS_RELOCATABLE
+       select SYS_SUPPORTS_SMARTMIPS
+       select USB_EHCI_BIG_ENDIAN_DESC if BIG_ENDIAN
+       select USB_EHCI_BIG_ENDIAN_MMIO if BIG_ENDIAN
+       select USB_OHCI_BIG_ENDIAN_DESC if BIG_ENDIAN
+       select USB_OHCI_BIG_ENDIAN_MMIO if BIG_ENDIAN
+       select USB_UHCI_BIG_ENDIAN_DESC if BIG_ENDIAN
+       select USB_UHCI_BIG_ENDIAN_MMIO if BIG_ENDIAN
+       select USE_OF
+       help
+         Select this to build a kernel which aims to support multiple boards,
+         generally using a flattened device tree passed from the bootloader
+         using the boot protocol defined in the UHI (Unified Hosting
+         Interface) specification.
+
 config MIPS_ALCHEMY
        bool "Alchemy processor based machines"
        select ARCH_PHYS_ADDR_T_64BIT
 source "arch/mips/bcm47xx/Kconfig"
 source "arch/mips/bcm63xx/Kconfig"
 source "arch/mips/bmips/Kconfig"
+source "arch/mips/generic/Kconfig"
 source "arch/mips/jazz/Kconfig"
 source "arch/mips/jz4740/Kconfig"
 source "arch/mips/lantiq/Kconfig"
 
 bootvars-y     = VMLINUX_LOAD_ADDRESS=$(load-y) \
                  VMLINUX_ENTRY_ADDRESS=$(entry-y) \
                  PLATFORM=$(platform-y)
+ifdef CONFIG_32BIT
+bootvars-y     += ADDR_BITS=32
+endif
+ifdef CONFIG_64BIT
+bootvars-y     += ADDR_BITS=64
+endif
 
 LDFLAGS                        += -m $(ld-emul)
 
        echo '  dtbs_install         - Install dtbs to $(INSTALL_DTBS_PATH)'
        echo
        echo '  These will be default as appropriate for a configured platform.'
+       echo
+       echo '  If you are targeting a system supported by generic kernels you may'
+       echo '  configure the kernel for a given architecture target like so:'
+       echo
+       echo '  {micro32,32,64}{r1,r2,r6}{el,}_defconfig <BOARDS="list of boards">'
+       echo
+       echo '  Otherwise, the following default configurations are available:'
 endef
+
+generic_config_dir = $(srctree)/arch/$(ARCH)/configs/generic
+generic_defconfigs :=
+
+#
+# If the user generates a generic kernel configuration without specifying a
+# list of boards to include the config fragments for, default to including all
+# available board config fragments.
+#
+ifeq ($(BOARDS),)
+BOARDS = $(patsubst board-%.config,%,$(notdir $(wildcard $(generic_config_dir)/board-*.config)))
+endif
+
+#
+# Generic kernel configurations which merge generic_defconfig with the
+# appropriate config fragments from arch/mips/configs/generic/, resulting in
+# the ability to easily configure the kernel for a given architecture,
+# endianness & set of boards without duplicating the needed configuration in
+# hundreds of defconfig files.
+#
+define gen_generic_defconfigs
+$(foreach bits,$(1),$(foreach rev,$(2),$(foreach endian,$(3),
+target := $(bits)$(rev)$(filter el,$(endian))_defconfig
+generic_defconfigs += $$(target)
+$$(target): $(generic_config_dir)/$(bits)$(rev).config
+$$(target): $(generic_config_dir)/$(endian).config
+)))
+endef
+
+$(eval $(call gen_generic_defconfigs,32 64,r1 r2 r6,eb el))
+$(eval $(call gen_generic_defconfigs,micro32,r2,eb el))
+
+.PHONY: $(generic_defconfigs)
+$(generic_defconfigs):
+       $(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh \
+               -m -O $(objtree) $(srctree)/arch/$(ARCH)/configs/generic_defconfig $^ \
+               $(foreach board,$(BOARDS),$(generic_config_dir)/board-$(board).config)
+       $(Q)$(MAKE) olddefconfig
+
+#
+# Prevent generic merge_config rules attempting to merge single fragments
+#
+$(generic_config_dir)/%.config: ;
 
 targets += vmlinux.lzma.itb
 targets += vmlinux.lzo.itb
 
+ifeq ($(ADDR_BITS),32)
+       itb_addr_cells = 1
+endif
+ifeq ($(ADDR_BITS),64)
+       itb_addr_cells = 2
+endif
+
 quiet_cmd_cpp_its_S = ITS     $@
       cmd_cpp_its_S = $(CPP) $(cpp_flags) -P -C -o $@ $< \
                        -DKERNEL_NAME="\"Linux $(KERNELRELEASE)\"" \
                        -DVMLINUX_BINARY="\"$(3)\"" \
                        -DVMLINUX_COMPRESSION="\"$(2)\"" \
                        -DVMLINUX_LOAD_ADDRESS=$(VMLINUX_LOAD_ADDRESS) \
-                       -DVMLINUX_ENTRY_ADDRESS=$(VMLINUX_ENTRY_ADDRESS)
+                       -DVMLINUX_ENTRY_ADDRESS=$(VMLINUX_ENTRY_ADDRESS) \
+                       -DADDR_BITS=$(ADDR_BITS) \
+                       -DADDR_CELLS=$(itb_addr_cells)
 
 $(obj)/vmlinux.its: $(srctree)/arch/mips/$(PLATFORM)/vmlinux.its.S FORCE
        $(call if_changed_dep,cpp_its_S,none,vmlinux.bin)
 
--- /dev/null
+CONFIG_CPU_MIPS32_R1=y
+CONFIG_HIGHMEM=y
 
--- /dev/null
+CONFIG_CPU_MIPS32_R2=y
+CONFIG_MIPS_O32_FP64_SUPPORT=y
+CONFIG_HIGHMEM=y
 
--- /dev/null
+CONFIG_CPU_MIPS32_R6=y
+CONFIG_HIGHMEM=y
 
--- /dev/null
+CONFIG_CPU_MIPS64_R1=y
+CONFIG_64BIT=y
+CONFIG_MIPS32_O32=y
+CONFIG_MIPS32_N32=y
 
--- /dev/null
+CONFIG_CPU_MIPS64_R2=y
+CONFIG_MIPS_O32_FP64_SUPPORT=y
+CONFIG_64BIT=y
+CONFIG_MIPS32_O32=y
+CONFIG_MIPS32_N32=y
 
--- /dev/null
+CONFIG_CPU_MIPS64_R6=y
+CONFIG_64BIT=y
+CONFIG_MIPS32_O32=y
+CONFIG_MIPS32_N32=y
 
--- /dev/null
+CONFIG_CPU_BIG_ENDIAN=y
 
--- /dev/null
+CONFIG_CPU_LITTLE_ENDIAN=y
 
--- /dev/null
+CONFIG_CPU_MIPS32_R2=y
+CONFIG_CPU_MICROMIPS=y
+CONFIG_MIPS_O32_FP64_SUPPORT=y
+CONFIG_HIGHMEM=y
 
--- /dev/null
+CONFIG_MIPS_GENERIC=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_CPS=y
+CONFIG_CPU_HAS_MSA=y
+CONFIG_HIGHMEM=y
+CONFIG_NR_CPUS=2
+CONFIG_MIPS_O32_FP64_SUPPORT=y
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_MEMCG=y
+CONFIG_MEMCG_SWAP=y
+CONFIG_BLK_CGROUP=y
+CONFIG_CFS_BANDWIDTH=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_CGROUP_PIDS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_NAMESPACES=y
+CONFIG_USER_NS=y
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_BPF_SYSCALL=y
+CONFIG_USERFAULTFD=y
+CONFIG_EMBEDDED=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_CC_STACKPROTECTOR_REGULAR=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_TRIM_UNUSED_KSYMS=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_NETFILTER=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_SCSI=y
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HWMON is not set
+CONFIG_MFD_SYSCON=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_KENSINGTON=y
+CONFIG_HID_LOGITECH=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MIPS_PLATFORM_DEVICES is not set
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
+CONFIG_FANOTIFY=y
+CONFIG_FUSE_FS=y
+CONFIG_CUSE=y
+CONFIG_OVERLAY_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_NFS_V4_2=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_INFO_REDUCED=y
+CONFIG_DEBUG_FS=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_FTRACE is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="earlycon"
+# CONFIG_XZ_DEC_X86 is not set
+# CONFIG_XZ_DEC_POWERPC is not set
+# CONFIG_XZ_DEC_IA64 is not set
+# CONFIG_XZ_DEC_ARM is not set
+# CONFIG_XZ_DEC_ARMTHUMB is not set
+# CONFIG_XZ_DEC_SPARC is not set
 
--- /dev/null
+if MIPS_GENERIC
+
+config LEGACY_BOARDS
+       bool
+       help
+         Select this from your board if the board must use a legacy, non-UHI,
+         boot protocol. This will cause the kernel to scan through the list of
+         supported machines calling their detect functions in turn if the
+         kernel is booted without being provided with an FDT via the UHI
+         boot protocol.
+
+endif
 
--- /dev/null
+#
+# Copyright (C) 2016 Imagination Technologies
+# Author: Paul Burton <paul.burton@imgtec.com>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation;  either version 2 of the  License, or (at your
+# option) any later version.
+#
+
+obj-y += init.o
+obj-y += irq.o
+obj-y += proc.o
 
--- /dev/null
+#
+# Copyright (C) 2016 Imagination Technologies
+# Author: Paul Burton <paul.burton@imgtec.com>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation;  either version 2 of the  License, or (at your
+# option) any later version.
+#
+
+platform-$(CONFIG_MIPS_GENERIC)        += generic/
+cflags-$(CONFIG_MIPS_GENERIC)  += -I$(srctree)/arch/mips/include/asm/mach-generic
+load-$(CONFIG_MIPS_GENERIC)    += 0xffffffff80100000
+all-$(CONFIG_MIPS_GENERIC)     := vmlinux.gz.itb
 
--- /dev/null
+/*
+ * Copyright (C) 2016 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clocksource.h>
+#include <linux/init.h>
+#include <linux/irqchip.h>
+#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
+
+#include <asm/fw/fw.h>
+#include <asm/irq_cpu.h>
+#include <asm/machine.h>
+#include <asm/mips-cpc.h>
+#include <asm/prom.h>
+#include <asm/smp-ops.h>
+#include <asm/time.h>
+
+static __initdata const void *fdt;
+static __initdata const struct mips_machine *mach;
+static __initdata const void *mach_match_data;
+
+void __init prom_init(void)
+{
+       const struct mips_machine *check_mach;
+       const struct of_device_id *match;
+
+       if ((fw_arg0 == -2) && !fdt_check_header((void *)fw_arg1)) {
+               /*
+                * We booted using the UHI boot protocol, so we have been
+                * provided with the appropriate device tree for the board.
+                * Make use of it & search for any machine struct based upon
+                * the root compatible string.
+                */
+               fdt = (void *)fw_arg1;
+
+               for_each_mips_machine(check_mach) {
+                       match = mips_machine_is_compatible(check_mach, fdt);
+                       if (match) {
+                               mach = check_mach;
+                               mach_match_data = match->data;
+                               break;
+                       }
+               }
+       } else if (IS_ENABLED(CONFIG_LEGACY_BOARDS)) {
+               /*
+                * We weren't booted using the UHI boot protocol, but do
+                * support some number of boards with legacy boot protocols.
+                * Attempt to find the right one.
+                */
+               for_each_mips_machine(check_mach) {
+                       if (!check_mach->detect)
+                               continue;
+
+                       if (!check_mach->detect())
+                               continue;
+
+                       mach = check_mach;
+               }
+
+               /*
+                * If we don't recognise the machine then we can't continue, so
+                * die here.
+                */
+               BUG_ON(!mach);
+
+               /* Retrieve the machine's FDT */
+               fdt = mach->fdt;
+       }
+
+       BUG_ON(!fdt);
+}
+
+void __init *plat_get_fdt(void)
+{
+       return (void *)fdt;
+}
+
+void __init plat_mem_setup(void)
+{
+       if (mach && mach->fixup_fdt)
+               fdt = mach->fixup_fdt(fdt, mach_match_data);
+
+       strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
+       __dt_setup_arch((void *)fdt);
+}
+
+void __init device_tree_init(void)
+{
+       int err;
+
+       unflatten_and_copy_device_tree();
+       mips_cpc_probe();
+
+       err = register_cps_smp_ops();
+       if (err)
+               err = register_up_smp_ops();
+}
+
+void __init plat_time_init(void)
+{
+       struct device_node *np;
+       struct clk *clk;
+
+       of_clk_init(NULL);
+
+       if (!cpu_has_counter) {
+               mips_hpt_frequency = 0;
+       } else if (mach && mach->measure_hpt_freq) {
+               mips_hpt_frequency = mach->measure_hpt_freq();
+       } else {
+               np = of_get_cpu_node(0, NULL);
+               if (!np) {
+                       pr_err("Failed to get CPU node\n");
+                       return;
+               }
+
+               clk = of_clk_get(np, 0);
+               if (IS_ERR(clk)) {
+                       pr_err("Failed to get CPU clock: %ld\n", PTR_ERR(clk));
+                       return;
+               }
+
+               mips_hpt_frequency = clk_get_rate(clk);
+               clk_put(clk);
+
+               switch (boot_cpu_type()) {
+               case CPU_20KC:
+               case CPU_25KF:
+                       /* The counter runs at the CPU clock rate */
+                       break;
+               default:
+                       /* The counter runs at half the CPU clock rate */
+                       mips_hpt_frequency /= 2;
+                       break;
+               }
+       }
+
+       clocksource_probe();
+}
+
+void __init arch_init_irq(void)
+{
+       struct device_node *intc_node;
+
+       intc_node = of_find_compatible_node(NULL, NULL,
+                                           "mti,cpu-interrupt-controller");
+       if (!cpu_has_veic && !intc_node)
+               mips_cpu_irq_init();
+
+       irqchip_init();
+}
+
+static int __init publish_devices(void)
+{
+       if (!of_have_populated_dt())
+               panic("Device-tree not present");
+
+       if (of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL))
+               panic("Failed to populate DT");
+
+       return 0;
+}
+arch_initcall(publish_devices);
+
+void __init prom_free_prom_memory(void)
+{
+}
 
--- /dev/null
+/*
+ * Copyright (C) 2016 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clocksource.h>
+#include <linux/init.h>
+#include <linux/irqchip/mips-gic.h>
+#include <linux/types.h>
+
+#include <asm/irq.h>
+
+int get_c0_fdc_int(void)
+{
+       int mips_cpu_fdc_irq;
+
+       if (cpu_has_veic)
+               panic("Unimplemented!");
+       else if (gic_present)
+               mips_cpu_fdc_irq = gic_get_c0_fdc_int();
+       else if (cp0_fdc_irq >= 0)
+               mips_cpu_fdc_irq = MIPS_CPU_IRQ_BASE + cp0_fdc_irq;
+       else
+               mips_cpu_fdc_irq = -1;
+
+       return mips_cpu_fdc_irq;
+}
+
+int get_c0_perfcount_int(void)
+{
+       int mips_cpu_perf_irq;
+
+       if (cpu_has_veic)
+               panic("Unimplemented!");
+       else if (gic_present)
+               mips_cpu_perf_irq = gic_get_c0_perfcount_int();
+       else if (cp0_perfcount_irq >= 0)
+               mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
+       else
+               mips_cpu_perf_irq = -1;
+
+       return mips_cpu_perf_irq;
+}
+
+unsigned int get_c0_compare_int(void)
+{
+       int mips_cpu_timer_irq;
+
+       if (cpu_has_veic)
+               panic("Unimplemented!");
+       else if (gic_present)
+               mips_cpu_timer_irq = gic_get_c0_compare_int();
+       else
+               mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
+
+       return mips_cpu_timer_irq;
+}
 
--- /dev/null
+/*
+ * Copyright (C) 2016 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/of.h>
+
+#include <asm/bootinfo.h>
+
+const char *get_system_type(void)
+{
+       const char *str;
+       int err;
+
+       err = of_property_read_string(of_root, "model", &str);
+       if (!err)
+               return str;
+
+       err = of_property_read_string_index(of_root, "compatible", 0, &str);
+       if (!err)
+               return str;
+
+       return "Unknown";
+}
 
--- /dev/null
+/dts-v1/;
+
+/ {
+       description = KERNEL_NAME;
+       #address-cells = <ADDR_CELLS>;
+
+       images {
+               kernel@0 {
+                       description = KERNEL_NAME;
+                       data = /incbin/(VMLINUX_BINARY);
+                       type = "kernel";
+                       arch = "mips";
+                       os = "linux";
+                       compression = VMLINUX_COMPRESSION;
+                       load = /bits/ ADDR_BITS <VMLINUX_LOAD_ADDRESS>;
+                       entry = /bits/ ADDR_BITS <VMLINUX_ENTRY_ADDRESS>;
+                       hash@0 {
+                               algo = "sha1";
+                       };
+               };
+       };
+
+       configurations {
+               default = "conf@default";
+
+               conf@default {
+                       description = "Generic Linux kernel";
+                       kernel = "kernel@0";
+               };
+       };
+};
 
--- /dev/null
+/*
+ * Copyright (C) 2016 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __MIPS_ASM_MACHINE_H__
+#define __MIPS_ASM_MACHINE_H__
+
+#include <linux/libfdt.h>
+#include <linux/of.h>
+
+struct mips_machine {
+       const struct of_device_id *matches;
+       const void *fdt;
+       bool (*detect)(void);
+       const void *(*fixup_fdt)(const void *fdt, const void *match_data);
+       unsigned int (*measure_hpt_freq)(void);
+};
+
+extern long __mips_machines_start;
+extern long __mips_machines_end;
+
+#define MIPS_MACHINE(name)                                             \
+       static const struct mips_machine __mips_mach_##name             \
+               __used __section(.mips.machines.init)
+
+#define for_each_mips_machine(mach)                                    \
+       for ((mach) = (struct mips_machine *)&__mips_machines_start;    \
+            (mach) < (struct mips_machine *)&__mips_machines_end;      \
+            (mach)++)
+
+/**
+ * mips_machine_is_compatible() - check if a machine is compatible with an FDT
+ * @mach: the machine struct to check
+ * @fdt: the FDT to check for compatibility with
+ *
+ * Check whether the given machine @mach is compatible with the given flattened
+ * device tree @fdt, based upon the compatibility property of the root node.
+ *
+ * Return: the device id matched if any, else NULL
+ */
+static inline const struct of_device_id *
+mips_machine_is_compatible(const struct mips_machine *mach, const void *fdt)
+{
+       const struct of_device_id *match;
+
+       if (!mach->matches)
+               return NULL;
+
+       for (match = mach->matches; match->compatible; match++) {
+               if (fdt_node_check_compatible(fdt, 0, match->compatible) == 0)
+                       return match;
+       }
+
+       return NULL;
+}
+
+#endif /* __MIPS_ASM_MACHINE_H__ */