#endif
+
+#if defined(CFG_EEPROM_X40430)
+ /* Maximum number of times to poll for acknowledge after write.
+ */
+#define MAX_ACKNOWLEDGE_POLLS 10
+#endif
+
/* ------------------------------------------------------------------------- */
#if (CONFIG_COMMANDS & CFG_CMD_EEPROM)
unsigned blk_off;
int rcode = 0;
+#if defined(CFG_EEPROM_X40430)
+ uchar contr_r_addr[2];
+ uchar addr_void[2];
+ uchar contr_reg[2];
+ uchar ctrl_reg_v;
+ int i;
+#endif
/* Write data until done or would cross a write page boundary.
* We must write the address again when changing pages
#ifdef CONFIG_SPI
spi_write (addr, alen, buffer, len);
#else
+#if defined(CFG_EEPROM_X40430)
+ /* Get the value of the control register.
+ * Set current address (internal pointer in the x40430)
+ * to 0x1ff.
+ */
+ contr_r_addr[0] = 9;
+ contr_r_addr[1] = addr[1];
+ addr_void[0] = 0;
+ addr_void[1] = addr[1];
+#ifdef CFG_I2C_EEPROM_ADDR
+ contr_r_addr[0] |= CFG_I2C_EEPROM_ADDR;
+ addr_void[0] |= CFG_I2C_EEPROM_ADDR;
+#endif
+ contr_reg[0] = 0xff;
+ if (i2c_write (contr_r_addr, 1, contr_reg, 1) != 0) {
+ rcode = 1;
+ }
+ if (i2c_read (contr_r_addr, 1, contr_reg, 1) != 0) {
+ rcode = 1;
+ }
+ ctrl_reg_v = contr_reg[0];
+
+ /* Are any of the eeprom blocks write protected?
+ */
+ if (ctrl_reg_v & 0x18) {
+ ctrl_reg_v &= ~0x18; /* reset block protect bits */
+ ctrl_reg_v |= 0x02; /* set write enable latch */
+ ctrl_reg_v &= ~0x04; /* clear RWEL */
+
+ /* Set write enable latch.
+ */
+ contr_reg[0] = 0xff;
+ contr_reg[1] = 0x02;
+ if (i2c_write (contr_r_addr, 1, contr_reg, 2) != 0) {
+ rcode = 1;
+ }
+
+ /* Set register write enable latch.
+ */
+ contr_reg[0] = 0xff;
+ contr_reg[1] = 0x06;
+ if (i2c_write (contr_r_addr, 1, contr_reg, 2) != 0) {
+ rcode = 1;
+ }
+
+ /* Modify ctrl register.
+ */
+ contr_reg[0] = 0xff;
+ contr_reg[1] = ctrl_reg_v;
+ if (i2c_write (contr_r_addr, 1, contr_reg, 2) != 0) {
+ rcode = 1;
+ }
+
+ /* The write (above) is an operation on NV memory.
+ * These can take some time (~5ms), and the device
+ * will not respond to further I2C messages till
+ * it's completed the write.
+ * So poll device for an I2C acknowledge.
+ * When we get one we know we can continue with other
+ * operations.
+ */
+ contr_reg[0] = 0;
+ for (i = 0; i < MAX_ACKNOWLEDGE_POLLS; i++) {
+ if (i2c_read (addr_void, 1, contr_reg, 1) == 1)
+ break; /* got ack */
+#if defined(CFG_EEPROM_PAGE_WRITE_DELAY_MS)
+ udelay(CFG_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
+#endif
+ }
+ if (i == MAX_ACKNOWLEDGE_POLLS) {
+ printf("EEPROM poll acknowledge failed\n");
+ rcode = 1;
+ }
+ }
+
+ /* Is the write enable latch on?.
+ */
+ else if (!(ctrl_reg_v & 0x02)) {
+ /* Set write enable latch.
+ */
+ contr_reg[0] = 0xff;
+ contr_reg[1] = 0x02;
+ if (i2c_write (contr_r_addr, 1, contr_reg, 2) != 0) {
+ rcode = 1;
+ }
+ }
+ /* Write is enabled ... now write eeprom value.
+ */
+#endif
if (i2c_write (addr, alen, buffer, len) != 0) rcode = 1;
#endif
buffer += len;
--- /dev/null
+/*
+ * Copyright (c) 2001 William L. Pitts
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are freely
+ * permitted provided that the above copyright notice and this
+ * paragraph and the following disclaimer are duplicated in all
+ * such forms.
+ *
+ * This software is provided "AS IS" and without any express or
+ * implied warranties, including, without limitation, the implied
+ * warranties of merchantability and fitness for a particular
+ * purpose.
+ */
+
+#include <ppcboot.h>
+#include <command.h>
+#include <linux/ctype.h>
+#include <net.h>
+
+#include <cmd_elf.h>
+#include <elf.h>
+
+
+#if (CONFIG_COMMANDS & CFG_CMD_ELF)
+
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+
+/* ======================================================================
+ * Interpreter command to boot an arbitrary ELF image from memory.
+ * ====================================================================== */
+int do_bootelf( cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[] )
+{
+ unsigned long addr; /* Address of the ELF image */
+ unsigned long rc; /* Return value from user code */
+ /* -------------------------------------------------- */
+ int rcode = 0;
+
+ if (argc < 2)
+ addr = load_addr;
+ else
+ addr = simple_strtoul( argv[ 1 ], NULL, 16 );
+
+ if( ! valid_elf_image( addr ))
+ return 1;
+
+ addr = load_elf_image( addr );
+
+ printf ("## Starting application at 0x%08lx ...\n", addr);
+
+ /*
+ * pass address parameter as argv[0] (aka command name),
+ * and all remaining args
+ */
+ rc = ((ulong (*)(bd_t *, int, char *[]))addr) (bd, --argc, &argv[1]);
+ if (rc != 0) rcode = 1;
+
+ printf ("## Application terminated, rc = 0x%lx\n", rc);
+ return rcode;
+} /* do_bootelf */
+
+
+/* ======================================================================
+ * Interpreter command to boot VxWorks from a memory image. The image can
+ * be either an ELF image or a raw binary. Will attempt to setup the
+ * bootline and other parameters correctly.
+ * ====================================================================== */
+int do_bootvx( cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[] )
+{
+ unsigned long addr; /* Address of image */
+ unsigned long bootaddr; /* Address to put the bootline */
+ char * bootline; /* Text of the bootline */
+ char * tmp; /* Temporary char pointer */
+#if defined(CONFIG_4xx) || defined(CONFIG_IOP480)
+ char build_buf[ 80 ]; /* Buffer for building the bootline */
+#endif
+ /* -------------------------------------------------- */
+
+ /* Check the loadaddr variable. If we don't know where the image is
+ then we're done. */
+
+ if(( tmp = getenv( "loadaddr" )) != NULL )
+ {
+ addr = simple_strtoul( tmp, NULL, 16 );
+ }
+ else
+ {
+ printf( "No load address provided\n" );
+ return 1;
+ }
+
+ /* Check to see if we need to tftp the image ourselves before starting */
+
+ if(( argc == 2 ) && ( strcmp( argv[ 1 ], "tftp" ) == 0 ))
+ {
+ if( NetLoop( bd, TFTP ) == 0 )
+ return 1;
+ printf( "Automatic boot of VxWorks image at address 0x%08lx ... \n",
+ addr );
+ }
+
+ /* This should equate to NV_RAM_ADRS + NV_BOOT_OFFSET + NV_ENET_OFFSET
+ from the VxWorks BSP header files. This will vary from board to board */
+
+#if defined(CONFIG_WALNUT405)
+ tmp = (char *)CFG_NVRAM_BASE_ADDR + 0x500;
+ memcpy( (char *)tmp, (char *)&bd->bi_enetaddr[3], 3 );
+#elif defined(CONFIG_CPCI405)
+ tmp = (char *)CFG_NVRAM_BASE_ADDR + CFG_NVRAM_VXWORKS_OFFS;
+ memcpy( (char *)tmp, (char *)&bd->bi_enetaddr[0], 6 );
+#elif defined(CONFIG_OCRTC)
+ tmp = (char *)CFG_ETHERNET_MAC_ADDR;
+ memcpy( (char *)tmp, (char *)&bd->bi_enetaddr[0], 6 );
+#else
+ printf( "## Ethernet MAC address not copied to NV RAM\n" );
+#endif
+
+ /* Use bootaddr to find the location in memory that VxWorks will
+ look for the bootline string. The default value for PowerPC
+ is LOCAL_MEM_LOCAL_ADRS + BOOT_LINE_OFFSET which defaults
+ to 0x4200 */
+
+ if(( tmp = getenv( "bootaddr" )) == NULL )
+ bootaddr = 0x4200;
+ else
+ bootaddr = simple_strtoul( tmp, NULL, 16 );
+
+ /* Check to see if the bootline is defined in the 'bootargs' parameter.
+ If it is not defined, we may be able to construct the info */
+
+ if(( bootline = getenv( "bootargs" )) != NULL )
+ {
+ memcpy( (void *)bootaddr, bootline, MAX( strlen( bootline ), 255 ));
+ }
+ else
+ {
+#if defined(CONFIG_4xx)
+ sprintf( build_buf, "ibmEmac(0,0)" );
+
+ if(( tmp = getenv( "hostname" )) != NULL )
+ {
+ sprintf( &build_buf[ strlen( build_buf - 1 ) ], "host:%s ", tmp );
+ }
+ else
+ {
+ sprintf( &build_buf[ strlen( build_buf - 1 ) ], ": " );
+ }
+
+ if(( tmp = getenv( "ipaddr" )) != NULL )
+ {
+ sprintf( &build_buf[ strlen( build_buf - 1 ) ], "e=%s ", tmp );
+ }
+ memcpy( (void *)bootaddr, build_buf, MAX( strlen( build_buf ), 255 ));
+#elif defined(CONFIG_IOP480)
+ sprintf( build_buf, "dc(0,0)" );
+
+ if(( tmp = getenv( "hostname" )) != NULL )
+ {
+ sprintf( &build_buf[ strlen( build_buf - 1 ) ], "host:%s ", tmp );
+ }
+ else
+ {
+ sprintf( &build_buf[ strlen( build_buf - 1 ) ], ": " );
+ }
+
+ if(( tmp = getenv( "ipaddr" )) != NULL )
+ {
+ sprintf( &build_buf[ strlen( build_buf - 1 ) ], "e=%s ", tmp );
+ }
+ memcpy( (void *)bootaddr, build_buf, MAX( strlen( build_buf ), 255 ));
+#else
+
+ /* I'm not sure what the device should be for other
+ PPC flavors, the hostname and ipaddr should be ok to just copy */
+
+ printf( "No bootargs defined\n" );
+ return 1;
+#endif
+ }
+
+ /* If the data at the load address is an elf image, then treat it like
+ an elf image. Otherwise, assume that it is a binary image */
+
+ if( valid_elf_image( addr ))
+ {
+ addr = load_elf_image( addr );
+ }
+ else
+ {
+ printf( "## Not an ELF image, assuming binary\n" );
+ /* leave addr as load_addr */
+ }
+
+ printf ("## Using bootline (@ 0x%lx): %s\n", bootaddr, (char *)bootaddr);
+ printf ("## Starting vxWorks at 0x%08lx ...\n", addr);
+
+ ((void (*)(void))addr)();
+
+ printf ("## vxWorks terminated\n" );
+ return 1;
+} /* do_bootvx */
+
+
+/* ======================================================================
+ * Determine if a valid ELF image exists at the given memory location.
+ * First looks at the ELF header magic field, the makes sure that it is
+ * executable and makes sure that it is for a PowerPC.
+ * ====================================================================== */
+int valid_elf_image( unsigned long addr )
+{
+ Elf32_Ehdr * ehdr; /* Elf header structure pointer */
+ /* -------------------------------------------------- */
+
+ ehdr = (Elf32_Ehdr *)addr;
+
+ if( ! IS_ELF( *ehdr )) {
+ printf( "## No elf image at address 0x%08lx\n", addr );
+ return 0;
+ }
+
+ if( ehdr->e_type != ET_EXEC ) {
+ printf( "## Not a 32-bit elf image at address 0x%08lx\n", addr );
+ return 0;
+ }
+
+ if( ehdr->e_machine != EM_PPC ) {
+ printf( "## Not a PowerPC elf image at address 0x%08lx\n", addr );
+ return 0;
+ }
+
+ return 1;
+} /* valid_elf_image */
+
+
+/* ======================================================================
+ * A very simple elf loader, assumes the image is valid, returns the
+ * entry point address.
+ * ====================================================================== */
+unsigned long load_elf_image( unsigned long addr )
+{
+ Elf32_Ehdr * ehdr; /* Elf header structure pointer */
+ Elf32_Shdr * shdr; /* Section header structure pointer */
+ unsigned char * strtab = 0; /* String table pointer */
+ unsigned char * image; /* Binary image pointer */
+ int i; /* Loop counter */
+ /* -------------------------------------------------- */
+
+ ehdr = (Elf32_Ehdr *)addr;
+
+ /* Find the section header string table for output info */
+ shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
+ (ehdr->e_shstrndx * sizeof( Elf32_Shdr )));
+
+ if( shdr->sh_type == SHT_STRTAB )
+ strtab = ( unsigned char *)(addr + shdr->sh_offset);
+
+ /* Load each appropriate section */
+ for( i = 0; i < ehdr->e_shnum; ++i ) {
+ shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff + (i * sizeof( Elf32_Shdr )));
+
+ if( !( shdr->sh_flags & SHF_ALLOC )
+ || shdr->sh_type == SHT_NOBITS
+ || shdr->sh_addr == 0
+ || shdr->sh_size == 0 )
+ continue;
+
+ if( strtab ) {
+ printf( "Loading %s @ 0x%08lx (%ld bytes)\n",
+ &strtab[ shdr->sh_name ], (unsigned long)shdr->sh_addr,
+ (long)shdr->sh_size );
+ }
+
+ image = (unsigned char *)addr + shdr->sh_offset;
+ memcpy( (void *)shdr->sh_addr, (const void *)image, shdr->sh_size );
+ }
+
+ return ehdr->e_entry;
+} /* load_elf_image */
+
+/* ====================================================================== */
+#endif /* CFG_CMD_ELF */