From: wdenk Date: Mon, 19 Nov 2001 16:24:41 +0000 (+0000) Subject: * Fix bug in I2C uCode-Patch Handling X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=651f5be14a214dda3a194d6b0aa3fbb723236d58;p=users%2Frw%2Fppcboot.git * Fix bug in I2C uCode-Patch Handling Patch by David Petersen, 19 Nov 2001 * Add I2C support for Xicor X40430 EEPROM (ICU862 board) --- diff --git a/CHANGELOG b/CHANGELOG index fd66734..93f0e8f 100644 --- 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 diff --git a/board/lwmon/README.keybd b/board/lwmon/README.keybd index 5abc2d3..fcf3b55 100644 --- a/board/lwmon/README.keybd +++ b/board/lwmon/README.keybd @@ -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- diff --git a/common/cmd_eeprom.c b/common/cmd_eeprom.c index db1081a..f1e520e 100644 --- a/common/cmd_eeprom.c +++ b/common/cmd_eeprom.c @@ -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 index 0000000..4f65b82 --- /dev/null +++ b/common/cmd_elf.c @@ -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 +#include +#include +#include + +#include +#include + + +#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 */ diff --git a/cpu/mpc8xx/fec.c b/cpu/mpc8xx/fec.c index de7db2d..f89475b 100644 --- a/cpu/mpc8xx/fec.c +++ b/cpu/mpc8xx/fec.c @@ -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) */ diff --git a/cpu/mpc8xx/i2c.c b/cpu/mpc8xx/i2c.c index 6531a3a..74b4da5 100644 --- a/cpu/mpc8xx/i2c.c +++ b/cpu/mpc8xx/i2c.c @@ -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) { diff --git a/include/config_ICU862.h b/include/config_ICU862.h index c5dde13..98ad376 100644 --- a/include/config_ICU862.h +++ b/include/config_ICU862.h @@ -89,12 +89,13 @@ #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 */ @@ -196,12 +197,6 @@ #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 */ diff --git a/include/config_lwmon.h b/include/config_lwmon.h index 33a5664..483dd7c 100644 --- a/include/config_lwmon.h +++ b/include/config_lwmon.h @@ -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