]> www.infradead.org Git - users/rw/ppcboot.git/commitdiff
* Fix bug in I2C uCode-Patch Handling
authorwdenk <wdenk>
Mon, 19 Nov 2001 16:24:41 +0000 (16:24 +0000)
committerwdenk <wdenk>
Mon, 19 Nov 2001 16:24:41 +0000 (16:24 +0000)
  Patch by David Petersen, 19 Nov 2001

* Add I2C support for Xicor X40430 EEPROM (ICU862 board)

CHANGELOG
board/lwmon/README.keybd
common/cmd_eeprom.c
common/cmd_elf.c [new file with mode: 0644]
cpu/mpc8xx/fec.c
cpu/mpc8xx/i2c.c
include/config_ICU862.h
include/config_lwmon.h

index fd6673471a6d1707fe85da6d345fb07433758c9c..93f0e8f3ddd37545e12efb6b2c76843fee1b5d14 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -56,6 +56,11 @@ To do:
 Modifications for 1.1.1:
 ======================================================================
 
+* Fix bug in I2C uCode-Patch Handling
+  Patch by David Petersen, 19 Nov 2001
+
+* Add I2C support for Xicor X40430 EEPROM (ICU862 board)
+
 * Add support for direct TFTP download to flash memory (optional).
   Patch by David Petersen, 26 Oct 2001
 
index 5abc2d337e07aec48ffc905a35c789a347ffa0c4..fcf3b55fc5b630fe61a7bb1975ca4931ed173573 100644 (file)
@@ -114,11 +114,11 @@ setzt  ("run  nfsargs", vgl. (3)), dann die Netzwerkkonfiguration an-
 gefügt ("run addip", vgl. (4)),  und  schließlich  die  Systemconsole
 definiert ("run addfb").
 
-Dabei wird im Normalfall die Definition (5) verwendt; wurde llerdings
-beim Reset die entsprechende Taste gedrückt gehalten, so  wird  diese
-Definition  bei der Ausführung des in (2) definierten Kommandos über-
-schrieben, so daß Linux die Bootmeldungen auch über das  Framebuffer-
-Device (=LCD-Display) ausgibt.
+Dabei wird im Normalfall die Definition (5)  verwendt;  wurde  aller-
+dings  beim  Reset die entsprechende Taste gedrückt gehalten, so wird
+diese Definition bei der Ausführung des in (2) definierten  Kommandos
+überschrieben,  so  daß  Linux die Bootmeldungen auch über das Frame-
+buffer-Device (=LCD-Display) ausgibt.
 
 Beachten Sie die Verdoppelung der '\'-Escapes in der  Definition  von
 "key_cmd#" - diese ist erforderlich, weil der String _zweimal_ inter-
index db1081addd1e0d874338297bbd1204d476febb2c..f1e520ebfcbbe4838334472076f452ba1d46a17f 100644 (file)
@@ -35,6 +35,13 @@ extern int  eeprom_write (unsigned offset, uchar *buffer, unsigned cnt);
 
 #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)
@@ -167,6 +174,13 @@ int eeprom_write (unsigned offset, uchar *buffer, unsigned cnt)
        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
@@ -216,6 +230,95 @@ int eeprom_write (unsigned offset, uchar *buffer, unsigned cnt)
 #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;
diff --git a/common/cmd_elf.c b/common/cmd_elf.c
new file mode 100644 (file)
index 0000000..4f65b82
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+ * 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 */
index de7db2d50573ebace59fd990288c00cf492a9c42..f89475b62af07117b03625dd8e65464b95574452 100644 (file)
@@ -338,12 +338,12 @@ int eth_init (bd_t * bd)
        */
 
        /* Has Utopia been configured? */
-       if (immap->im_ioport.iop_pdpar & (0x8000 >> 1)) {
+       if (immr->im_ioport.iop_pdpar & (0x8000 >> 1)) {
                /*
                 * YES - Use MUXED mode for UTOPIA bus.
                 * This frees Port A for use by MII (see 862UM table 41-6).
                 */
-               immap->im_ioport.utmode &= ~0x80;
+               immr->im_ioport.utmode &= ~0x80;
        } else {
                /*
                 * NO - set SPLIT mode for UTOPIA bus.
@@ -352,7 +352,7 @@ int eth_init (bd_t * bd)
                  * enabled anyway) but just tells the 862
                 * to use port A for MII (see 862UM table 41-6).
                 */
-               immap->im_ioport.utmode |= 0x80;
+               immr->im_ioport.utmode |= 0x80;
        }
 #endif /* !defined(CONFIG_ICU862) */
 
index 6531a3ac3bc215055fdf17c74182c7e4d02bc931..74b4da5754fbf1844622748bc63631e87d6f17cd 100644 (file)
@@ -172,7 +172,7 @@ i2c_init(int speed, int slaveaddr)
        volatile immap_t *immap = (immap_t *)CFG_IMMR ;
        volatile cpm8xx_t *cp = (cpm8xx_t *)&immap->im_cpm;
        volatile i2c8xx_t *i2c  = (i2c8xx_t *)&immap->im_i2c;
-       volatile iic_t *iip;
+       volatile iic_t *iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
        ulong rbase, tbase;
        volatile I2C_BD *rxbd, *txbd;
        uint dpaddr;
@@ -180,7 +180,6 @@ i2c_init(int speed, int slaveaddr)
 #ifdef CFG_I2C_UCODE_PATCH
        iip = (iic_t *)&cp->cp_dpmem[iip->iic_rpbase];
 #else
-       iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
        /* Disable relocation */
        iip->iic_rpbase = 0;
 #endif
@@ -276,14 +275,12 @@ i2c_newio(i2c_state_t *state)
 {
        volatile immap_t *immap = (immap_t *)CFG_IMMR ;
        volatile cpm8xx_t *cp = (cpm8xx_t *)&immap->im_cpm;
-       volatile iic_t *iip;
+       volatile iic_t *iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
 
        PRINTD(("[I2C] i2c_newio\n"));
 
 #ifdef CFG_I2C_UCODE_PATCH
        iip = (iic_t *)&cp->cp_dpmem[iip->iic_rpbase];
-#else
-       iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
 #endif
        state->rx_idx = 0;
        state->tx_idx = 0;
@@ -451,7 +448,7 @@ int i2c_doio(i2c_state_t *state)
        volatile immap_t *immap = (immap_t *)CFG_IMMR ;
        volatile cpm8xx_t *cp = (cpm8xx_t *)&immap->im_cpm;
        volatile i2c8xx_t *i2c  = (i2c8xx_t *)&immap->im_i2c;
-       volatile iic_t *iip;
+       volatile iic_t *iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
        volatile I2C_BD *txbd, *rxbd;
        volatile int j = 0;
 
@@ -459,8 +456,6 @@ int i2c_doio(i2c_state_t *state)
 
 #ifdef CFG_I2C_UCODE_PATCH
        iip = (iic_t *)&cp->cp_dpmem[iip->iic_rpbase];
-#else
-       iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
 #endif
 
        if (state->tx_idx <= 0 && state->rx_idx <= 0) {
index c5dde13255cdeeac3b32c612203600b6f5196a66..98ad376c8e1c0cc3f7f59e3adbcd91e95e802ade 100644 (file)
 #define CONFIG_MAC_PARTITION
 #define CONFIG_DOS_PARTITION
 
-#define CONFIG_SOFT_I2C                        /* Software I2C support enabled */
+#define        CONFIG_SOFT_I2C                 /* Software I2C support enabled */
 # define CFG_I2C_SPEED         50000
 # define CFG_I2C_SLAVE         0xFE
-# define CFG_EEPROM_PAGE_WRITE_BITS 4  /* The Xicor X40431 has 16 byte */
-                                       /* page write mode using last   */
-                                       /* 4 bits of the address        */
+# define CFG_I2C_EEPROM_ADDR   0x50
+
+#define CFG_EEPROM_X40430              /* Use a Xicor X40430 EEPROM    */
+#define CFG_EEPROM_PAGE_WRITE_BITS  4  /* 16 bytes page write mode     */
 
 #define        CONFIG_RTC_MPC8xx               /* use internal RTC of MPC8xx   */
 
 
 #define CFG_ENV_SECT_SIZE      0x40000 /* see README - env sector total size   */
 
-/*-----------------------------------------------------------------------
- * I2C/EEPROM Configuration
- */
-//#define CFG_I2C_CLOCK                33000   /* I²C Clock Rate in kHz                */
-//#define CFG_I2C_EEPROM_ADDR  0x58    /* EEPROM AT24C164                      */
-
 /*-----------------------------------------------------------------------
  * Cache Configuration
  */
index 33a5664e8cf2de277e6dcf52a4ddce26eac48668..483dd7c419c8cb89dbcbb522c0e1e3897d6c8418 100644 (file)
@@ -67,7 +67,7 @@
 #define CONFIG_LOADS_ECHO      1       /* echo on for serial download  */
 #undef CFG_LOADS_BAUD_CHANGE           /* don't allow baudrate change  */
 
-#if 1
+#if 0
 #define        CONFIG_WATCHDOG         1       /* watchdog enabled             */
 #endif