adm5120: add experimental 3.14 kernel support
[openwrt.git] / target / linux / adm5120 / files-3.14 / arch / mips / adm5120 / prom / routerboot.c
diff --git a/target/linux/adm5120/files-3.14/arch/mips/adm5120/prom/routerboot.c b/target/linux/adm5120/files-3.14/arch/mips/adm5120/prom/routerboot.c
new file mode 100644 (file)
index 0000000..d9a06d9
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ *  Mikrotik's RouterBOOT specific prom routines
+ *
+ *  Copyright (C) 2007-2008 Gabor Juhos <juhosg@openwrt.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/routerboot.h>
+
+#include <asm/bootinfo.h>
+#include <asm/addrspace.h>
+
+#include <asm/mach-adm5120/adm5120_defs.h>
+#include <prom/routerboot.h>
+#include "prom_read.h"
+
+struct rb_hard_settings rb_hs;
+static int rb_found;
+
+static int __init routerboot_load_hs(u8 *buf, u16 buflen)
+{
+       u16 id, len;
+
+       memset(&rb_hs, 0, sizeof(rb_hs));
+
+       if (buflen < 4)
+               return -1;
+
+       if (prom_read_le32(buf) != RB_MAGIC_HARD)
+               return -1;
+
+       /* skip magic value */
+       buf += 4;
+       buflen -= 4;
+
+       while (buflen > 2) {
+               id = prom_read_le16(buf);
+               buf += 2;
+               buflen -= 2;
+               if (id == RB_ID_TERMINATOR || buflen < 2)
+                       break;
+
+               len = prom_read_le16(buf);
+               buf += 2;
+               buflen -= 2;
+
+               if (buflen < len)
+                       break;
+
+               switch (id) {
+               case RB_ID_BIOS_VERSION:
+                       rb_hs.bios_ver = (char *)buf;
+                       break;
+               case RB_ID_BOARD_NAME:
+                       rb_hs.name = (char *)buf;
+                       break;
+               case RB_ID_MEMORY_SIZE:
+                       rb_hs.mem_size = prom_read_le32(buf);
+                       break;
+               case RB_ID_MAC_ADDRESS_COUNT:
+                       rb_hs.mac_count = prom_read_le32(buf);
+                       break;
+               case RB_ID_MAC_ADDRESS_PACK:
+                       if ((len / RB_MAC_SIZE) > 0)
+                               rb_hs.mac_base = buf;
+                       break;
+               }
+
+               buf += len;
+               buflen -= len;
+
+       }
+
+       return 0;
+}
+
+#define RB_BS_OFFS     0x14
+#define RB_OFFS_MAX    (128*1024)
+
+int __init routerboot_present(void)
+{
+       struct rb_bios_settings *bs;
+       u8 *base;
+       u32 off, len;
+
+       if (rb_found)
+               goto out;
+
+       base = (u8 *)KSEG1ADDR(ADM5120_SRAM0_BASE);
+       bs = (struct rb_bios_settings *)(base + RB_BS_OFFS);
+
+       off = prom_read_le32(&bs->hs_offs);
+       len = prom_read_le32(&bs->hs_size);
+       if (off > RB_OFFS_MAX)
+               goto out;
+
+       if (routerboot_load_hs(base+off, len) != 0)
+               goto out;
+
+       rb_found = 1;
+
+out:
+       return rb_found;
+}
+
+char *routerboot_get_boardname(void)
+{
+       if (rb_found == 0)
+               return NULL;
+
+       return rb_hs.name;
+}