From 8bfda76892a39c033b5abf2c17035a444fffad08 Mon Sep 17 00:00:00 2001
From: florian <florian@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Date: Fri, 27 Apr 2007 08:29:19 +0000
Subject: [PATCH] Updated support for Zynos/adm5120eb boards, thanks Gabor

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@7061 3c298f89-4303-0410-b956-a3cf2f4a3e73
---
 .../files/arch/mips/adm5120/adm5120_info.c    | 105 +++++++++++++-----
 .../include/asm-mips/mach-adm5120/zynos.h     |  25 ++++-
 2 files changed, 100 insertions(+), 30 deletions(-)

diff --git a/target/linux/adm5120-2.6/files/arch/mips/adm5120/adm5120_info.c b/target/linux/adm5120-2.6/files/arch/mips/adm5120/adm5120_info.c
index 2ba21b892..67b3e42ee 100644
--- a/target/linux/adm5120-2.6/files/arch/mips/adm5120/adm5120_info.c
+++ b/target/linux/adm5120-2.6/files/arch/mips/adm5120/adm5120_info.c
@@ -235,6 +235,8 @@ static struct adm5120_board __initdata adm5120_boards[] = {
 	}
 };
 
+#define DUMMY_BOARD()	{.mach_type = MACH_ADM5120_UNKNOWN}
+
 struct mylo_board {
 	u16	vid;
 	u16	did;
@@ -243,7 +245,6 @@ struct mylo_board {
 	unsigned long	mach_type;
 };
 
-#define DUMMY_BOARD()	{.mach_type = MACH_ADM5120_UNKNOWN}
 
 #define MYLO_BOARD(v,d,sv,sd,mt) { .vid = (v), .did = (d), .svid = (sv), \
 	.sdid = (sd), .mach_type = (mt) }
@@ -286,11 +287,6 @@ struct zynos_board {
 	u16		board_id;
 };
 
-#define ZYNOS_VENDOR_ID_INVALID	0
-#define ZYNOS_VENDOR_ID_ZYXEL	1
-#define ZYNOS_VENDOR_ID_DLINK	2
-#define ZYNOS_VENDOR_ID_LUCENT	3
-
 #define ZYNOS_BOARD(vi, bi, mt) { .vendor_id = (vi), .board_id = (bi), \
 		.mach_type = (mt) }
 
@@ -332,6 +328,23 @@ static inline u32 read_le32(void *buf)
 		((u32)p[3] << 24));
 }
 
+static inline u16 read_be16(void *buf)
+{
+	u8 *p;
+
+	p = buf;
+	return (((u16)p[0] << 8) + (u16)p[1]);
+}
+
+static inline u32 read_be32(void *buf)
+{
+	u8 *p;
+
+	p = buf;
+	return (((u32)p[0] << 24) + ((u32)p[1] << 16) + ((u32)p[2] << 8) +
+		((u32)p[3]));
+}
+
 /*
  * CFE based boards
  */
@@ -496,56 +509,92 @@ out:
 /*
  * ZyNOS based boards
  */
-#define CHECK_VENDOR(n) (strnicmp(vendor, ZYNOS_VENDOR_ZYXEL, \
-		strlen(ZYNOS_VENDOR_ZYXEL)) == 0)
+static inline u32 zynos_dbgarea_present(u8 *data)
+{
+	u32 t;
 
-static unsigned int __init zynos_get_vendor_id(unsigned char *vendor)
+	t = read_be32(data+5);
+	if (t != ZYNOS_MAGIC_DBGAREA1)
+		return 0;
+
+	t = read_be32(data+9);
+	if (t != ZYNOS_MAGIC_DBGAREA2)
+		return 0;
+
+	return 1;
+}
+
+#define CHECK_VENDOR(n) (strnicmp(vendor,(n),strlen(n)) == 0)
+
+static inline unsigned int zynos_get_vendor_id(struct zynos_board_info *info)
 {
-	int ret;
+	unsigned char vendor[ZYNOS_NAME_LEN];
+	int i;
 
-	ret = ZYNOS_VENDOR_ID_INVALID;
+	for (i=0; i<ZYNOS_NAME_LEN; i++)
+		vendor[i]=info->vendor[i];
 
 	if CHECK_VENDOR(ZYNOS_VENDOR_ZYXEL)
-		ret = ZYNOS_VENDOR_ID_ZYXEL;
+		return ZYNOS_VENDOR_ID_ZYXEL;
 #if 0
 	/* TODO: there are no known ADM5120 based boards from other vendors */
-	else if CHECK_VENDOR(ZYNOS_VENDOR_DLINK)
-		ret = ZYNOS_VENDOR_ID_DLINK;
-	else if CHECK_VENDOR(ZYNOS_VENDOR_LUCENT)
-		ret = ZYNOS_VENDOR_ID_LUCENT;
+	if CHECK_VENDOR(ZYNOS_VENDOR_DLINK)
+		return ZYNOS_VENDOR_ID_DLINK;
+
+	if CHECK_VENDOR(ZYNOS_VENDOR_LUCENT)
+		return ZYNOS_VENDOR_ID_LUCENT;
+
+	if CHECK_VENDOR(ZYNOS_VENDOR_NETGEAR)
+		return ZYNOS_VENDOR_ID_NETGEAR;
 #endif
 
-	return ret;
+	return ZYNOS_VENDOR_ID_OTHER;
+}
+
+static inline u16 zynos_get_board_id(struct zynos_board_info *info)
+{
+	return read_be16(&info->board_id);
+}
+
+static inline u32 zynos_get_bootext_addr(struct zynos_board_info *info)
+{
+	return read_be32(&info->bootext_addr);
 }
 
-#define ZYNOS_INFO_ADDR	KSEG1ADDR(ADM5120_SRAM0_BASE+0x3F90)
-#define BOOTEXT_ADDR_2M	0xBFC08000
-#define BOOTEXT_ADDR_4M	0xBFC10000
+
+#define ZYNOS_INFO_ADDR		KSEG1ADDR(ADM5120_SRAM0_BASE+0x3F90)
+#define ZYNOS_HDBG_ADDR		KSEG1ADDR(ADM5120_SRAM0_BASE+0x4000)
+#define BOOTEXT_ADDR_MIN	KSEG1ADDR(ADM5120_SRAM0_BASE)
+#define BOOTEXT_ADDR_MAX	(BOOTEXT_ADDR_MIN + (2*1024*1024))
 
 static unsigned long __init zynos_detect_board(void)
 {
 	struct zynos_board_info *info;
 	struct zynos_board *board;
 	unsigned int vendor_id;
-	u32	bootext_addr;
+	u16	board_id;
+	u32	t;
 	unsigned long ret;
 
 	ret = MACH_ADM5120_UNKNOWN;
+	/* check presence of the dbgarea */
+	if (zynos_dbgarea_present((u8 *)ZYNOS_HDBG_ADDR) == 0)
+		goto out;
 
 	info = (struct zynos_board_info *)(ZYNOS_INFO_ADDR);
-	vendor_id = zynos_get_vendor_id(&info->vendor);
-	if (vendor_id == ZYNOS_VENDOR_ID_INVALID)
-		goto out;
 
-	bootext_addr = be32_to_cpu(info->bootext_addr);
-	if ((bootext_addr != BOOTEXT_ADDR_2M) ||
-		(bootext_addr != BOOTEXT_ADDR_4M))
+	/* check for a valid BootExt address */
+	t = zynos_get_bootext_addr(info);
+	if ((t < BOOTEXT_ADDR_MIN) || (t > BOOTEXT_ADDR_MAX))
 		goto out;
 
+	vendor_id = zynos_get_vendor_id(info);
+	board_id = zynos_get_board_id(info);
+
 	for (board = zynos_boards; board->mach_type != MACH_ADM5120_UNKNOWN;
 		board++) {
 		if ((board->vendor_id == vendor_id) &&
-			(board->board_id == be16_to_cpu(info->board_id))) {
+			(board->board_id == board_id)) {
 			ret = board->mach_type;
 			break;
 		}
diff --git a/target/linux/adm5120-2.6/files/include/asm-mips/mach-adm5120/zynos.h b/target/linux/adm5120-2.6/files/include/asm-mips/mach-adm5120/zynos.h
index aa2e555f6..ba372d3d3 100644
--- a/target/linux/adm5120-2.6/files/include/asm-mips/mach-adm5120/zynos.h
+++ b/target/linux/adm5120-2.6/files/include/asm-mips/mach-adm5120/zynos.h
@@ -33,16 +33,31 @@ struct zynos_board_info {
 	u8		dbgflag;
 } __attribute__ ((packed));
 
+/*
+ * Vendor IDs
+ */
+#define ZYNOS_VENDOR_ID_ZYXEL	0
+#define ZYNOS_VENDOR_ID_NETGEAR	1
+#define ZYNOS_VENDOR_ID_DLINK	2
+#define ZYNOS_VENDOR_ID_OTHER	3
+#define ZYNOS_VENDOR_ID_LUCENT	4
+
 /*
  * Vendor names
  */
-#define ZYNOS_VENDOR_ZYXEL	"ZyXEL"
+#define ZYNOS_VENDOR_DLINK	"D-Link"
 #define ZYNOS_VENDOR_LUCENT	"LUCENT"
-#define ZYNOS_VENDOR_NETGEAR	"D-Link"
+#define ZYNOS_VENDOR_NETGEAR	"NetGear"
+#define ZYNOS_VENDOR_ZYXEL	"ZyXEL"
 
 /*
  * Board IDs (big-endian)
  */
+#define ZYNOS_BOARD_ES2108	0x00F2	/* Ethernet Switch 2108 */
+#define ZYNOS_BOARD_ES2108F	0x01AF	/* Ethernet Switch 2108-F */
+#define ZYNOS_BOARD_ES2108G	0x00F3	/* Ethernet Switch 2108-G */
+#define ZYNOS_BOARD_ES2108LC	0x00FC	/* Ethernet Switch 2108-LC */
+#define ZYNOS_BOARD_ES2108PWR	0x00F4	/* Ethernet Switch 2108PWR */
 #define ZYNOS_BOARD_HS100	0x9FF1	/* HomeSafe 100/100W */
 #define ZYNOS_BOARD_P334	0x9FF5	/* Prestige 334 */
 #define ZYNOS_BOARD_P334U	0x9FDD	/* Prestige 334U */
@@ -54,4 +69,10 @@ struct zynos_board_info {
 #define ZYNOS_BOARD_P335PLUS	0x0025	/* Prestige 335Plus */
 #define ZYNOS_BOARD_P335U	0x9FDC	/* Prestige 335U */
 
+/*
+ * Some magic numbers (big-endian)
+ */
+#define ZYNOS_MAGIC_DBGAREA1	0x48646267	/* "Hdbg" */
+#define ZYNOS_MAGIC_DBGAREA2	0x61726561	/* "area" */
+
 #endif /* _ZYNOS_H */
-- 
2.20.1