[U-Boot] [PATCH] IXP425: Add new IXP425 board emPC-A400 Part 2/2

Stefan Althoefer stefan.althoefer at web.de
Thu Dec 4 22:10:13 CET 2008


[PATCH] IXP425: Add new IXP425 board emPC-A400

This patch adds support for the emPC-A400 CPU board from
Janz Automationssysteme. It will also apply to some
of the Janz emVIEW displays which are based on this CPU
board.

Besides of the board support, the patch includes
two features which are (up to now) private to this
port but might be of interrest to others.

1. Ability to download microcode to the NPE unit. This
   code works without using the Intel Library (which
   makes it smaller). This is good if you do not want
   to do networking in u-boot, but want boot an NFS-rooted
   linux system (where linux cannot load the microcode
   by itself).
   Refer to boards/empca400/cmd_npe.c
2. Ability to boot the IXP425 Windows-CE kernel. Refer
   to boards/empca400/cmd_bootce.c.



The patch is against "latest" u-boot git-repository

Please (still) be patient if style of submission or patches are
offending.

Signed-off-by: Stefan Althoefer <stefan.althoefer at web.de>
----

diff -uprN u-boot-orig//board/empca400/cmd_bootce.c u-boot/board/empca400/cmd_bootce.c
--- u-boot-orig//board/empca400/cmd_bootce.c	1970-01-01 01:00:00.000000000 +0100
+++ u-boot/board/empca400/cmd_bootce.c	2008-12-03 11:58:03.000000000 +0100
@@ -0,0 +1,313 @@
+/*
+ * (C) Copyright 2008
+ * Janz Automationssysteme AG <www.janz.de>
+ * Stefan Althoefer <as at janz.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * cmd_bootce.c - boot Windows-CE kernel
+ *
+ * This is able to boot Windows-CE on the IXP425 platform.
+ * I believe it is not usable for other platforms, because of
+ * the special passing of parameters to the Win-CE kernel
+ * and due to some fixed loading addresses.
+ */
+#include <common.h>
+#include <command.h>
+#include <net.h>
+
+#define DRIVER_GLOBALS_PHYS     0x1f8000
+#define DRIVER_GLOBALS_SIZE       0x1000
+
+typedef unsigned char  UCHAR;
+typedef unsigned short USHORT;
+typedef unsigned short WORD;
+typedef unsigned int   UINT;
+typedef unsigned long  DWORD;
+
+/* 
+ * @struct EDBG_ADDR | Addressing info for the debug Ethernet subsystem
+ *
+ * For speed, all values are stored in net byte order (big endian).  Use the
+ * htonl/ntohl/htons/ntohs macros to convert to/from local byte order.
+ */
+typedef struct _EDBG_ADDR {
+	DWORD  dwIP;    /* @field IP address (net byte order) */
+	USHORT wMAC[3]; /* @field Ethernet address (net byte order) */
+	USHORT wPort;   /* @field UDP port # (net byte order) - only used if appropriate */
+
+} EDBG_ADDR;
+
+/* For debugging over ethernet. Controls debug messages, ethernet shell */
+/* and kernel debugger.  Note that this struct should not be zeroed */
+/* out by OEMInit, as the eboot bootloader passes us state info. */
+typedef struct _DBG_ETH_GLOBALS 
+{
+#define EBOOT_MAGIC_NUM 0x45424F54 /* "EBOT" */
+	DWORD EbootMagicNum;     /* To detect if ether bootloader is present */
+	UCHAR etherEnabled;      /* If non-zero, ethernet card present */
+	UCHAR etherFlags;        /* Set by eboot loader. Controls which components */
+	/* are enabled over ether (see ethdbg.h) */
+	UCHAR ucEdbgAdapterType; /* Type of debug Ether adapter  */
+	UCHAR ucEdbgIRQ;         /* IRQ line to use for debug Ether adapter */
+
+	DWORD     dwEdbgBaseAddr;   /* Base I/O address for debug Ether adapter */
+	EDBG_ADDR TargetAddr;       /* IP and ether address of Odo */
+	DWORD     SubnetMask;       /* Subnet mask */
+	EDBG_ADDR DownloadHostAddr; /* IP and ether address of host who started us */
+
+	/* The following addresses are assumed valid if the corresponding flag in */
+	/* etherFlags is set. */
+	EDBG_ADDR DbgHostAddr;   /* IP/ether addr and UDP port of host receiving dbg msgs */
+	EDBG_ADDR KdbgHostAddr;  /* IP/ether addr and UDP port of host running kernel debugger */
+	EDBG_ADDR PpshHostAddr;  /* IP/ether addr and UDP port of host running ether text shell */
+	DWORD DHCPLeaseTime;     /* DHCP lease duration in seconds. */
+	DWORD EdbgFlags;         /* Information about ethernet system */
+	WORD  KitlTransport;     /* Transport for KITL communications. */
+	UCHAR fmtBuf[170];
+} DBG_ETH_GLOBALS;
+
+/* Un-initialized Miscellaneous */
+typedef struct _UNINIT_MISC_GLOBALS {
+	UINT CPUSteppingID;      /* Contains the Current CPU ID (including stepping) */
+	UCHAR EbootDevice;
+	UCHAR reserved[3];       /* Reserved (for alignment purpose) */
+	WORD  MACnpe0[3];        /* NPE0 mac address */
+	WORD  MACnpe1[3];        /* NPE1 mac address */
+	WORD MACrndis[3];        /* RNDIS mac address */
+	UCHAR padding[230];
+} UNINIT_MISC_GLOBALS, *PUNINIT_MISC_GLOBALS;
+
+/* For ucEdbgAdapterType field */
+#define EDBG_ADAPTER_IXDP425NPE0 7
+#define EDBG_ADAPTER_IXDP425NPE1 8
+
+/* For EbootDevice field */
+#define BOOT_DEVICE_NONE        0
+#define BOOT_DEVICE_PCI         1
+#define BOOT_DEVICE_RTL         BOOT_DEVICE_PCI
+#define BOOT_DEVICE_NPE_ETH0    2
+#define BOOT_DEVICE_NPE_ETH1    3
+
+/* for KitlTransport field */
+#define KTS_DEFAULT             0
+#define KTS_ETHER               1
+#define KTS_SERIAL              2
+#define KTS_NONE               63
+
+#define KTS_PASSIVE_MODE     0x40
+
+
+
+/* ---------------------------------------------------------------- */
+
+static inline unsigned int mswap32(unsigned int x)
+{
+	return (
+		((x<<24) & 0xff000000) |
+		((x<< 8) & 0x00ff0000) |
+		((x>> 8) & 0x0000ff00) |
+		((x>>24) & 0x000000ff) );
+}
+
+
+static inline unsigned short mswap16(unsigned short x)
+{
+	return (
+		((x<< 8) & 0xff00) |
+		((x>> 8) & 0x00ff) );
+}
+
+
+static int get_mac_from_env(USHORT *mac, char *env)
+{
+	char *pcTmp = getenv(env);
+	unsigned char addr[6];
+	char *pcEnd;
+	int i;
+
+	if( pcTmp != NULL ){
+		for (i = 0; i < 6; i++) {
+			addr[i] =
+				pcTmp ? simple_strtoul (pcTmp, &pcEnd, 16) : 0;
+			pcTmp = (*pcTmp) ? pcEnd + 1 : pcEnd;
+		}
+	}
+
+	mac[0] = mswap16(addr[0]+(addr[1]<<8));
+	mac[1] = mswap16(addr[2]+(addr[3]<<8));
+	mac[2] = mswap16(addr[4]+(addr[5]<<8));
+
+	return 0;
+}
+
+
+int do_bootce(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+	int    i;
+	volatile char   *vpC;
+	char   *net_addr;
+	int    cross_boot;
+	int    kernelSize;
+	char   *kitltransport;
+	void   (*theKernel)(void);
+
+	DBG_ETH_GLOBALS     *pDbgEth;
+	UNINIT_MISC_GLOBALS  *pUninitMiscGlobals;
+
+	/* Strip off cmd-name */
+	argc--, argv++;
+
+	cross_boot = 0;
+	if (getenv("crossboot"))
+		cross_boot = 1;
+
+	/* parse flags */
+	while ((argc>0) && (argv[0][0] == '-')) {
+		switch( argv[0][1] ){
+		case 'x':
+			cross_boot = 1;
+			argc--, argv++;
+			break;
+
+		default:
+			printf("%s: command error (unknown option flag)\n", __FUNCTION__);
+			return 1;
+		}
+	}
+
+
+	switch (argc) {
+	case 2:
+		theKernel = (void(*)(void)) simple_strtoul (argv[0], NULL, 16);
+		kernelSize = simple_strtoul (argv[1], NULL, 16);
+		break;
+	default:
+		printf("%s: command error (too few parameters)\n", __FUNCTION__);
+		return 1;
+	}
+
+	printf("%s: doing CE: %x, %x\n", __FUNCTION__, (int)theKernel, kernelSize);
+
+	/* Blank driver physical area */
+	vpC = (volatile char *)DRIVER_GLOBALS_PHYS;
+	i = 0;
+	while (i < DRIVER_GLOBALS_SIZE) {
+		*vpC++ = 0;
+		i++;
+	}
+
+	pUninitMiscGlobals = (UNINIT_MISC_GLOBALS *)(DRIVER_GLOBALS_PHYS+0x800);
+	pDbgEth = (DBG_ETH_GLOBALS *)(DRIVER_GLOBALS_PHYS+0x900);
+
+	pUninitMiscGlobals->EbootDevice = BOOT_DEVICE_NPE_ETH0;  /* FIXME: From ENV */
+	get_mac_from_env(pUninitMiscGlobals->MACnpe0, "ethaddr");
+	if (getenv("eth1addr") != 0) {
+		get_mac_from_env(pUninitMiscGlobals->MACnpe1, "eth1addr");
+	} else {
+		/* Was used with early boards */
+		get_mac_from_env(pUninitMiscGlobals->MACnpe1, "ethaddr1");
+	}
+
+	pDbgEth->EbootMagicNum = mswap32(EBOOT_MAGIC_NUM);
+	pDbgEth->ucEdbgAdapterType = EDBG_ADAPTER_IXDP425NPE0;  /* FIXME: From ENV */
+
+	net_addr = getenv("ipaddr");
+	if (net_addr == 0) {
+		printf("ipaddr not set\n");
+		return 1;
+	} else {
+		pDbgEth->TargetAddr.dwIP = string_to_ip(net_addr);
+	}
+	get_mac_from_env(pDbgEth->TargetAddr.wMAC, "ethaddr");
+
+	net_addr = getenv("serverip");
+	if (net_addr == 0) {
+		printf("serverip not set\n");
+		return 1;
+	} else {
+		pDbgEth->DownloadHostAddr.dwIP = string_to_ip(net_addr);
+	}
+
+	net_addr = getenv("netmask");
+	if (net_addr == 0) {
+		pDbgEth->SubnetMask = string_to_ip("255.255.255.0");
+		printf("using default netmask 255.255.255.0\n");
+	} else {
+		pDbgEth->SubnetMask = string_to_ip(net_addr);
+	}
+
+	if ((kitltransport=getenv("kitltransport")) != 0) {
+		pDbgEth->KitlTransport = mswap16(simple_strtoul (kitltransport, NULL, 16));
+	} else {
+		/* default. FIXME: This should be KTS_NONE? */
+		pDbgEth->KitlTransport = mswap16(KTS_ETHER);
+	}
+
+	if (cross_boot) {
+		volatile int   *pk;
+		volatile int   dummy;
+		unsigned long  reg;
+		int            ksize;
+
+		printf("cross endian\n");
+	
+		/* swap the kernel code */
+		ksize = kernelSize;
+		pk = (int *)theKernel;
+		for (i=0; i<ksize/(sizeof(int)); i++) {
+			*pk = mswap32(*pk);
+			pk++;
+		}
+	
+		/* read more data to flush the cache (hopefully we do not reach
+		   end of RAM) */
+		for (i=0; i<64*1024; i++) {
+			dummy = *pk++;
+		}
+
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+		/* turn off Big-Endian mode */
+		asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (reg));
+		reg &= ~(1<<7);
+		asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (reg));
+#else
+		/* turn on Big-Endian mode */
+		asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (reg));
+		reg |= (1<<7);
+		asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (reg));
+#endif
+	}
+    
+	theKernel();
+    
+	return 0;
+}
+
+
+U_BOOT_CMD(
+	bootce, 4, 0, do_bootce,
+	"bootce  - boot WinCE nk.nb0\n",
+	"[-x] <addr>\n"
+	"    - boot WinCE nk.nb0 located at 'addr'. If '-x' is given, cross endian\n"
+	"      boot will be performed (BE->LE)\n"
+);
+


More information about the U-Boot mailing list