diff options
| author | wdenk <wdenk> | 2004-09-29 22:43:59 +0000 | 
|---|---|---|
| committer | wdenk <wdenk> | 2004-09-29 22:43:59 +0000 | 
| commit | a06752e36be7fc74b4a928026b63b1bf1764497e (patch) | |
| tree | b71ddbcee4e4cc03e8ea98738b605a1c3879a703 | |
| parent | da93ed8147a000505ac7b7ed4e2fb50532596a3c (diff) | |
| download | olio-uboot-2014.01-a06752e36be7fc74b4a928026b63b1bf1764497e.tar.xz olio-uboot-2014.01-a06752e36be7fc74b4a928026b63b1bf1764497e.zip | |
* Patch by Sean Chang, 9 Aug 2004:
  - Added I2C support for ML300.
  - Added support for ML300 to read out its environment information
    stored on the EEPROM.
  - Added support to use board specific parameters as part of
    U-Boot's environment information.
  - Updated MLD files to support configuration for new features
    above.
* Patches by Travis Sawyer, 5 Aug 2004:
  - Remove incorrect bridge settings for eth group 6
  - Add call to setup bridge in ppc_440x_eth_initialize
  - Fix ppc_440x_eth_init to reset the phy only if its the
    first time through, otherwise, just check the phy for the
    autonegotiated speed/duplex.  This allows the use of netconsole
  - only print the speed/duplex the first time the phy is reset.
| -rw-r--r-- | CHANGELOG | 17 | ||||
| -rw-r--r-- | board/xilinx/common/xipif_v1_23_b.c | 331 | ||||
| -rw-r--r-- | board/xilinx/common/xipif_v1_23_b.h | 51 | ||||
| -rw-r--r-- | board/xilinx/ml300/Makefile | 13 | ||||
| -rw-r--r-- | board/xilinx/ml300/ml300.c | 31 | ||||
| -rw-r--r-- | board/xilinx/ml300/sw_services/uboot_v1_00_a/data/Ltypes | 72 | ||||
| -rw-r--r-- | board/xilinx/ml300/sw_services/uboot_v1_00_a/data/uboot_v2_1_0.mld | 8 | ||||
| -rw-r--r-- | board/xilinx/ml300/sw_services/uboot_v1_00_a/data/uboot_v2_1_0.tcl | 29 | ||||
| -rw-r--r-- | board/xilinx/ml300/xparameters.h | 110 | ||||
| -rw-r--r-- | board/xilinx/xilinx_enet/emac_adapter.c | 9 | ||||
| -rw-r--r-- | board/xilinx/xilinx_iic/iic_adapter.c | 529 | ||||
| -rw-r--r-- | board/xilinx/xilinx_iic/xiic_l.c | 484 | ||||
| -rw-r--r-- | board/xilinx/xilinx_iic/xiic_l.h | 150 | ||||
| -rw-r--r-- | cpu/ppc4xx/440gx_enet.c | 23 | ||||
| -rw-r--r-- | include/configs/ml300.h | 18 | 
15 files changed, 1718 insertions, 157 deletions
| @@ -2,6 +2,23 @@  Changes since U-Boot 1.1.1:  ====================================================================== +* Patch by Sean Chang, 9 Aug 2004: +  - Added I2C support for ML300. +  - Added support for ML300 to read out its environment information +    stored on the EEPROM. +  - Added support to use board specific parameters as part of +    U-Boot's environment information. +  - Updated MLD files to support configuration for new features +    above. + +* Patches by Travis Sawyer, 5 Aug 2004: +  - Remove incorrect bridge settings for eth group 6 +  - Add call to setup bridge in ppc_440x_eth_initialize +  - Fix ppc_440x_eth_init to reset the phy only if its the +    first time through, otherwise, just check the phy for the +    autonegotiated speed/duplex.  This allows the use of netconsole +  - only print the speed/duplex the first time the phy is reset. +  * Patch by Shlomo Kut, 29 Mar 2004:    Add support for MKS Instruments "Quantum" board diff --git a/board/xilinx/common/xipif_v1_23_b.c b/board/xilinx/common/xipif_v1_23_b.c new file mode 100644 index 000000000..c7311ab9b --- /dev/null +++ b/board/xilinx/common/xipif_v1_23_b.c @@ -0,0 +1,331 @@ +/* $Id: xipif_v1_23_b.c,v 1.1 2002/03/18 23:24:52 linnj Exp $ */ +/****************************************************************************** +* +*       XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" +*       AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND +*       SOLUTIONS FOR XILINX DEVICES.  BY PROVIDING THIS DESIGN, CODE, +*       OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, +*       APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION +*       THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, +*       AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE +*       FOR YOUR IMPLEMENTATION.  XILINX EXPRESSLY DISCLAIMS ANY +*       WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE +*       IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR +*       REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF +*       INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +*       FOR A PARTICULAR PURPOSE. +* +*       (c) Copyright 2002 Xilinx Inc. +*       All rights reserved. +* +******************************************************************************/ +/****************************************************************************** +* +* FILENAME: +* +* xipif.c +* +* DESCRIPTION: +* +* This file contains the implementation of the XIpIf component. The +* XIpIf component encapsulates the IPIF, which is the standard interface +* that IP must adhere to when connecting to a bus.  The purpose of this +* component is to encapsulate the IPIF processing such that maintainability +* is increased.  This component does not provide a lot of abstraction from +* from the details of the IPIF as it is considered a building block for +* device drivers.  A device driver designer must be familiar with the +* details of the IPIF hardware to use this component. +* +* The IPIF hardware provides a building block for all hardware devices such +* that each device does not need to reimplement these building blocks. The +* IPIF contains other building blocks, such as FIFOs and DMA channels, which +* are also common to many devices.  These blocks are implemented as separate +* hardware blocks and instantiated within the IPIF.  The primary hardware of +* the IPIF which is implemented by this software component is the interrupt +* architecture.  Since there are many blocks of a device which may generate +* interrupts, all the interrupt processing is contained in the common part +* of the device, the IPIF.  This interrupt processing is for the device level +* only and does not include any processing for the interrupt controller. +* +* A device is a mechanism such as an Ethernet MAC.  The device is made +* up of several parts which include an IPIF and the IP.  The IPIF contains most +* of the device infrastructure which is common to all devices, such as +* interrupt processing, DMA channels, and FIFOs.  The infrastructure may also +* be referred to as IPIF internal blocks since they are part of the IPIF and +* are separate blocks that can be selected based upon the needs of the device. +* The IP of the device is the logic that is unique to the device and interfaces +* to the IPIF of the device. +* +* In general, there are two levels of registers within the IPIF.  The first +* level, referred to as the device level, contains registers which are for the +* entire device.  The second level, referred to as the IP level, contains +* registers which are specific to the IP of the device.  The two levels of +* registers are designed to be hierarchical such that the device level is +* is a more general register set above the more specific registers of the IP. +* The IP level of registers provides functionality which is typically common +* across all devices and allows IP designers to focus on the unique aspects +* of the IP. +* +* The interrupt registers of the IPIF are parameterizable such that the only +* the number of bits necessary for the device are implemented. The functions +* of this component do not attempt to validate that the passed in arguments are +* valid based upon the number of implemented bits.  This is necessary to +* maintain the level of performance required for the common components.  Bits +* of the registers are assigned starting at the least significant bit of the +* registers. +* +* Critical Sections +* +* It is the responsibility of the device driver designer to use critical +* sections as necessary when calling functions of the IPIF.  This component +* does not use critical sections and it does access registers using +* read-modify-write operations.  Calls to IPIF functions from a main thread +* and from an interrupt context could produce unpredictable behavior such that +* the caller must provide the appropriate critical sections. +* +* Mutual Exclusion +* +* The functions of the IPIF are not thread safe such that the caller of all +* functions is responsible for ensuring mutual exclusion for an IPIF.  Mutual +* exclusion across multiple IPIF components is not necessary. +* +* NOTES: +* +* None. +* +* MODIFICATION HISTORY: +* +* Ver   Who  Date     Changes +* ----- ---- -------- ----------------------------------------------- +* 1.23b jhl  02/27/01 Repartioned to reduce size +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xipif_v1_23_b.h" +#include "xio.h" + +/************************** Constant Definitions *****************************/ + +/* the following constant is used to generate bit masks for register testing + * in the self test functions, it defines the starting bit mask that is to be + * shifted from the LSB to MSB in creating a register test mask + */ +#define XIIF_V123B_FIRST_BIT_MASK     1UL + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +static XStatus IpIntrSelfTest(u32 RegBaseAddress, u32 IpRegistersWidth); + +/****************************************************************************** +* +* FUNCTION: +* +* XIpIf_SelfTest +* +* DESCRIPTION: +* +* This function performs a self test on the specified IPIF component.  Many +* of the registers in the IPIF are tested to ensure proper operation.  This +* function is destructive because the IPIF is reset at the start of the test +* and at the end of the test to ensure predictable results.  The IPIF reset +* also resets the entire device that uses the IPIF.  This function exits with +* all interrupts for the device disabled. +* +* ARGUMENTS: +* +* InstancePtr points to the XIpIf to operate on. +* +* DeviceRegistersWidth contains the number of bits in the device interrupt +* registers. The hardware is parameterizable such that only the number of bits +* necessary to support a device are implemented.  This value must be between 0 +* and 32 with 0 indicating there are no device interrupt registers used. +* +* IpRegistersWidth contains the number of bits in the IP interrupt registers +* of the device.  The hardware is parameterizable such that only the number of +* bits necessary to support a device are implemented.  This value must be +* between 0 and 32 with 0 indicating there are no IP interrupt registers used. +* +* RETURN VALUE: +* +* A value of XST_SUCCESS indicates the test was successful with no errors. +* Any one of the following error values may also be returned. +* +*   XST_IPIF_RESET_REGISTER_ERROR       The value of a register at reset was +*                                       not valid +*   XST_IPIF_IP_STATUS_ERROR            A write to the IP interrupt status +*                                       register did not read back correctly +*   XST_IPIF_IP_ACK_ERROR               One or more bits in the IP interrupt +*                                       status register did not reset when acked +*   XST_IPIF_IP_ENABLE_ERROR            The IP interrupt enable register +*                                       did not read back correctly based upon +*                                       what was written to it +* +* NOTES: +* +* None. +* +******************************************************************************/ + +/* the following constant defines the maximum number of bits which may be + * used in the registers at the device and IP levels, this is based upon the + * number of bits available in the registers + */ +#define XIIF_V123B_MAX_REG_BIT_COUNT 32 + +XStatus +XIpIfV123b_SelfTest(u32 RegBaseAddress, u8 IpRegistersWidth) +{ +	XStatus Status; + +	/* assert to verify arguments are valid */ + +	XASSERT_NONVOID(IpRegistersWidth <= XIIF_V123B_MAX_REG_BIT_COUNT); + +	/* reset the IPIF such that it's in a known state before the test +	 * and interrupts are globally disabled +	 */ +	XIIF_V123B_RESET(RegBaseAddress); + +	/* perform the self test on the IP interrupt registers, if +	 * it is not successful exit with the status +	 */ +	Status = IpIntrSelfTest(RegBaseAddress, IpRegistersWidth); +	if (Status != XST_SUCCESS) { +		return Status; +	} + +	/* reset the IPIF such that it's in a known state before exiting test */ + +	XIIF_V123B_RESET(RegBaseAddress); + +	/* reaching this point means there were no errors, return success */ + +	return XST_SUCCESS; +} + +/****************************************************************************** +* +* FUNCTION: +* +* IpIntrSelfTest +* +* DESCRIPTION: +* +* Perform a self test on the IP interrupt registers of the IPIF. This +* function modifies registers of the IPIF such that they are not guaranteed +* to be in the same state when it returns.  Any bits in the IP interrupt +* status register which are set are assumed to be set by default after a reset +* and are not tested in the test. +* +* ARGUMENTS: +* +* InstancePtr points to the XIpIf to operate on. +* +* IpRegistersWidth contains the number of bits in the IP interrupt registers +* of the device.  The hardware is parameterizable such that only the number of +* bits necessary to support a device are implemented.  This value must be +* between 0 and 32 with 0 indicating there are no IP interrupt registers used. +* +* RETURN VALUE: +* +* A status indicating XST_SUCCESS if the test was successful.  Otherwise, one +* of the following values is returned. +* +*   XST_IPIF_RESET_REGISTER_ERROR       The value of a register at reset was +*                                       not valid +*   XST_IPIF_IP_STATUS_ERROR            A write to the IP interrupt status +*                                       register did not read back correctly +*   XST_IPIF_IP_ACK_ERROR               One or more bits in the IP status +*                                       register did not reset when acked +*   XST_IPIF_IP_ENABLE_ERROR            The IP interrupt enable register +*                                       did not read back correctly based upon +*                                       what was written to it +* NOTES: +* +* None. +* +******************************************************************************/ +static XStatus +IpIntrSelfTest(u32 RegBaseAddress, u32 IpRegistersWidth) +{ +	/* ensure that the IP interrupt interrupt enable register is  zero +	 * as it should be at reset, the interrupt status is dependent upon the +	 * IP such that it's reset value is not known +	 */ +	if (XIIF_V123B_READ_IIER(RegBaseAddress) != 0) { +		return XST_IPIF_RESET_REGISTER_ERROR; +	} + +	/* if there are any used IP interrupts, then test all of the interrupt +	 * bits in all testable registers +	 */ +	if (IpRegistersWidth > 0) { +		u32 BitCount; +		u32 IpInterruptMask = XIIF_V123B_FIRST_BIT_MASK; +		u32 Mask = XIIF_V123B_FIRST_BIT_MASK;	/* bits assigned MSB to LSB */ +		u32 InterruptStatus; + +		/* generate the register masks to be used for IP register tests, the +		 * number of bits supported by the hardware is parameterizable such +		 * that only that number of bits are implemented in the registers, the +		 * bits are allocated starting at the MSB of the registers +		 */ +		for (BitCount = 1; BitCount < IpRegistersWidth; BitCount++) { +			Mask = Mask << 1; +			IpInterruptMask |= Mask; +		} + +		/* get the current IP interrupt status register contents, any bits +		 * already set must default to 1 at reset in the device and these +		 * bits can't be tested in the following test, remove these bits from +		 * the mask that was generated for the test +		 */ +		InterruptStatus = XIIF_V123B_READ_IISR(RegBaseAddress); +		IpInterruptMask &= ~InterruptStatus; + +		/* set the bits in the device status register and verify them by reading +		 * the register again, all bits of the register are latched +		 */ +		XIIF_V123B_WRITE_IISR(RegBaseAddress, IpInterruptMask); +		InterruptStatus = XIIF_V123B_READ_IISR(RegBaseAddress); +		if ((InterruptStatus & IpInterruptMask) != IpInterruptMask) +		{ +			return XST_IPIF_IP_STATUS_ERROR; +		} + +		/* test to ensure that the bits set in the IP interrupt status register +		 * can be cleared by acknowledging them in the IP interrupt status +		 * register then read it again and verify it was cleared +		 */ +		XIIF_V123B_WRITE_IISR(RegBaseAddress, IpInterruptMask); +		InterruptStatus = XIIF_V123B_READ_IISR(RegBaseAddress); +		if ((InterruptStatus & IpInterruptMask) != 0) { +			return XST_IPIF_IP_ACK_ERROR; +		} + +		/* set the IP interrupt enable set register and then read the IP +		 * interrupt enable register and verify the interrupts were enabled +		 */ +		XIIF_V123B_WRITE_IIER(RegBaseAddress, IpInterruptMask); +		if (XIIF_V123B_READ_IIER(RegBaseAddress) != IpInterruptMask) { +			return XST_IPIF_IP_ENABLE_ERROR; +		} + +		/* clear the IP interrupt enable register and then read the +		 * IP interrupt enable register and verify the interrupts were disabled +		 */ +		XIIF_V123B_WRITE_IIER(RegBaseAddress, 0); +		if (XIIF_V123B_READ_IIER(RegBaseAddress) != 0) { +			return XST_IPIF_IP_ENABLE_ERROR; +		} +	} +	return XST_SUCCESS; +} diff --git a/board/xilinx/common/xipif_v1_23_b.h b/board/xilinx/common/xipif_v1_23_b.h index b1520e921..3ce1fffba 100644 --- a/board/xilinx/common/xipif_v1_23_b.h +++ b/board/xilinx/common/xipif_v1_23_b.h @@ -1,39 +1,22 @@ +/* $Id: xipif_v1_23_b.h,v 1.1 2002/03/18 23:24:52 linnj Exp $ */  /******************************************************************************  * -*     Author: Xilinx, Inc. +*	XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" +*	AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND +*	SOLUTIONS FOR XILINX DEVICES.  BY PROVIDING THIS DESIGN, CODE, +*	OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, +*	APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION +*	THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, +*	AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE +*	FOR YOUR IMPLEMENTATION.  XILINX EXPRESSLY DISCLAIMS ANY +*	WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE +*	IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR +*	REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF +*	INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +*	FOR A PARTICULAR PURPOSE.  * -* -*     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. -* -* -*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A -*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS -*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD, -*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE -*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING -*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. -*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO -*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY -*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM -*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND -*     FITNESS FOR A PARTICULAR PURPOSE. -* -* -*     Xilinx hardware products are not intended for use in life support -*     appliances, devices, or systems. Use in such applications is -*     expressly prohibited. -* -* -*     (c) Copyright 2002-2004 Xilinx Inc. -*     All rights reserved. -* -* -*     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., -*     675 Mass Ave, Cambridge, MA 02139, USA. +*	(c) Copyright 2002 Xilinx Inc. +*	All rights reserved.  *  ******************************************************************************/  /****************************************************************************** @@ -575,7 +558,7 @@  *  * RETURN VALUE:  * -* TRUE if interrupts are enabled for the IPIF, FALSE otherwise. +* XTRUE if interrupts are enabled for the IPIF, XFALSE otherwise.  *  * NOTES:  * diff --git a/board/xilinx/ml300/Makefile b/board/xilinx/ml300/Makefile index d9007c025..880c494c9 100644 --- a/board/xilinx/ml300/Makefile +++ b/board/xilinx/ml300/Makefile @@ -19,22 +19,23 @@  # along with this program; if not, write to the Free Software  # Foundation, Inc., 59 Temple Place, Suite 330, Boston,  # MA 02111-1307 USA -#  include $(TOPDIR)/config.mk -CFLAGS   += -I../ml300 -I../common -I../xilinx_enet +CFLAGS   += -I../ml300 -I../common -I../xilinx_enet -I../xilinx_iic  LIB	= lib$(BOARD).a -OBJS	= $(BOARD).o serial.o \ -	  ../xilinx_enet/emac_adapter.o ../xilinx_enet/xemac.o \ +OBJS	= $(BOARD).o \ +	  serial.o \ +	  ../xilinx_enet/emac_adapter.o  ../xilinx_enet/xemac.o \  	  ../xilinx_enet/xemac_options.o ../xilinx_enet/xemac_polled.o \  	  ../xilinx_enet/xemac_intr.o ../xilinx_enet/xemac_g.o \ -	  ../xilinx_enet/xemac_intr_dma.o \ +	  ../xilinx_enet/xemac_intr_dma.o ../xilinx_iic/iic_adapter.o \ +	  ../xilinx_iic/xiic_l.o ../common/xipif_v1_23_b.o \  	  ../common/xbasic_types.o ../common/xdma_channel.o \  	  ../common/xdma_channel_sg.o ../common/xpacket_fifo_v1_00_b.o \ -	  ../common/xversion.o +	  ../common/xversion.o \  SOBJS	= init.o diff --git a/board/xilinx/ml300/ml300.c b/board/xilinx/ml300/ml300.c index dbe8a8ac7..f335fc1ba 100644 --- a/board/xilinx/ml300/ml300.c +++ b/board/xilinx/ml300/ml300.c @@ -42,6 +42,10 @@  #include <asm/processor.h>  #include "xparameters.h" +#ifdef CFG_ENV_IS_IN_EEPROM +extern void convert_env(void); +#endif +  int  board_pre_init(void)  { @@ -51,22 +55,25 @@ board_pre_init(void)  int  checkboard(void)  { -	unsigned char *s = getenv("serial#"); -	unsigned char *e; +	uchar tmp[64];		/* long enough for environment variables */ +	uchar *s, *e; +	int i = getenv_r("L", tmp, sizeof (tmp)); -	if (!s || strncmp(s, "ML300", 9)) { +	if (i < 0) {  		printf("### No HW ID - assuming ML300");  	} else { -		for (e = s; *e; ++e) { +		for (e = tmp; *e; ++e) {  			if (*e == ' ')  				break;  		} -		for (; s < e; ++s) { +		printf("### Board Serial# is "); + +		for (s = tmp; s < e; ++s) {  			putc(*s);  		} -	} +	}  	putc('\n');  	return (0); @@ -107,3 +114,15 @@ get_PCI_freq(void)  	val = sys_info.freqPCI;  	return val;  } + +#ifdef CONFIG_MISC_INIT_R + +int +misc_init_r() +{ +	/* convert env name and value to u-boot standard */ +	convert_env(); +	return 0; +} + +#endif diff --git a/board/xilinx/ml300/sw_services/uboot_v1_00_a/data/Ltypes b/board/xilinx/ml300/sw_services/uboot_v1_00_a/data/Ltypes index 319b925d3..9daf14709 100644 --- a/board/xilinx/ml300/sw_services/uboot_v1_00_a/data/Ltypes +++ b/board/xilinx/ml300/sw_services/uboot_v1_00_a/data/Ltypes @@ -1,41 +1,55 @@  #!/bin/bash -if[$ -# -ne 1 ] -   then echo "usage: Ltypes filename" > &2 exit 2 fi FILE = "$1" +if [ $# -ne 1 ] +then +    echo "usage: Ltypes filename" >&2 +    exit 2 +fi + +FILE="$1"  #TMPFILE='mktemp "${FILE}.XXXXXX"' || exit 1 -   TMPFILE = $ { -   FILE} +TMPFILE=${FILE}.`date "+%s"` +touch $TMPFILE || exit 1 -   . ` date "+%s" ` touch $TMPFILE || exit 1  # Change all the Xilinx types to Linux types and put the result into a temp file -   sed -   - e 's/\bXTRUE\b/TRUE/g' -   - e 's/\bXFALSE\b/FALSE/g' -   - e 's/\bXNULL\b/NULL/g' -   - e 's/<asm/delay.h>/<asm\/delay.h>/g' -   - e 's/\bXENV_USLEEP\b/udelay/g' -   - e 's/\bXuint8\b/u8/g' -   - e 's/\bXuint16\b/u16/g' -   - e 's/\bXuint32\b/u32/g' -   - e 's/\bXint8\b/s8/g' -   - e 's/\bXint16\b/s16/g' -   - e 's/\bXint32\b/s32/g' - e 's/\bXboolean\b/u32/g' "${FILE}" > "${TMPFILE}" +sed	\ +	-e 's/\bXTRUE\b/TRUE/g' \ +	-e 's/\bXFALSE\b/FALSE/g' \ +	-e 's/\bXNULL\b/NULL/g' \ +	-e 's/"xenv.h"/<asm\/delay.h>/g' \ +	-e 's/\bXENV_USLEEP\b/udelay/g' \ +	-e 's/\bXuint8\b/u8/g' \ +	-e 's/\bXuint16\b/u16/g' \ +	-e 's/\bXuint32\b/u32/g' \ +	-e 's/\bXint8\b/s8/g' \ +	-e 's/\bXint16\b/s16/g' \ +	-e 's/\bXint32\b/s32/g' \ +	-e 's/\bXboolean\b/u32/g' \ +	"${FILE}" > "${TMPFILE}" +  # Overlay the original file with the temp file -   mv "${TMPFILE}" "${FILE}" +mv "${TMPFILE}" "${FILE}" +  # Are we doing xbasic_types.h? -   if["${FILE##*/}" = xbasic_types.h] -   then -# Remember as you're reading this that we've already gone through the prior -# sed script.  We need to do some other things to xbasic_types.h: -#   1) Add ifndefs around TRUE and FALSE defines -#   2) Remove definition of NULL as NULL -#   3) Replace most of the primitive types section with a #include -   sed - e '/u32 true/,/#define false/Ic\ +if [ "${FILE##*/}" = xbasic_types.h ] +then +    # Remember as you're reading this that we've already gone through the prior +    # sed script.  We need to do some other things to xbasic_types.h: +    #   1) Add ifndefs around TRUE and FALSE defines +    #   2) Remove definition of NULL as NULL +    #   3) Replace most of the primitive types section with a #include +    sed \ +	-e '/u32 true/,/#define false/Ic\  #ifndef TRUE\  #define TRUE 1\  #endif\  #ifndef FALSE\  #define FALSE 0\ -#endif' - e '/#define[[:space:]][[:space:]]*NULL[[:space:]][[:space:]]*NULL/d' - e '/typedef[[:space:]][[:space:]]*unsigned[[:space:]][[:space:]]*char[[:space:]][[:space:]]*u8/,/typedef[[:space:]][[:space:]]*unsigned[[:space:]][[:space:]]*long[[:space:]][[:space:]]*u32.*boolean/c\ -#include <linux/types.h>' "${FILE}" > "${TMPFILE}" mv "${TMPFILE}" "${FILE}" fi +#endif' \ +	-e '/#define[[:space:]][[:space:]]*NULL[[:space:]][[:space:]]*NULL/d' \ +	-e '/typedef[[:space:]][[:space:]]*unsigned[[:space:]][[:space:]]*char[[:space:]][[:space:]]*u8/,/typedef[[:space:]][[:space:]]*unsigned[[:space:]][[:space:]]*long[[:space:]][[:space:]]*u32.*boolean/c\ +#include <linux/types.h>' \ +	"${FILE}" > "${TMPFILE}" + +    mv "${TMPFILE}" "${FILE}" +fi diff --git a/board/xilinx/ml300/sw_services/uboot_v1_00_a/data/uboot_v2_1_0.mld b/board/xilinx/ml300/sw_services/uboot_v1_00_a/data/uboot_v2_1_0.mld index e1aa7fd59..516924126 100644 --- a/board/xilinx/ml300/sw_services/uboot_v1_00_a/data/uboot_v2_1_0.mld +++ b/board/xilinx/ml300/sw_services/uboot_v1_00_a/data/uboot_v2_1_0.mld @@ -42,7 +42,11 @@ BEGIN ARRAY connected_periphs PROPERTY desc = "Peripherals connected to U-Boot";  PROPERTY size = 0;  PARAM name = periph_name, desc = "Name of Peripheral connected", type = string;  END ARRAY -    PARAMETER name = TARGET_DIR, desc = -    "Target Directory for U-Boot BSP", type = string; +    PARAMETER name = TARGET_DIR, desc = "Target Directory for U-Boot BSP", type = string; + +# location of persistent storage in the IIC EEPROM (defaults are set for ML300) +PARAMETER name = IIC_PERSISTENT_BASEADDR, desc = "Start of persistent storage block in the EEPROM address space", type = int, default = 1024; +PARAMETER name = IIC_PERSISTENT_HIGHADDR, desc = "End of persistent storage block in the EEPROM address space", type = int, default = 2047; +PARAMETER name = IIC_PERSISTENT_EEPROMADDR, desc = "Address of the EEPROM on the IIC bus", type = int, default = 0xA0;  END LIBRARY diff --git a/board/xilinx/ml300/sw_services/uboot_v1_00_a/data/uboot_v2_1_0.tcl b/board/xilinx/ml300/sw_services/uboot_v1_00_a/data/uboot_v2_1_0.tcl index 8d939b416..9d44f4493 100644 --- a/board/xilinx/ml300/sw_services/uboot_v1_00_a/data/uboot_v2_1_0.tcl +++ b/board/xilinx/ml300/sw_services/uboot_v1_00_a/data/uboot_v2_1_0.tcl @@ -76,12 +76,18 @@ proc generate {libname} {  		xredefine_uartns550 $drv "xparameters.h"  	    }  elseif {[string compare -nocase $drvname "emac"] == 0} {  		xredefine_emac $drv "xparameters.h" +	    }  elseif {[string compare -nocase $drvname "iic"] == 0} { +		xredefine_iic $drv "xparameters.h"  	    }  	}      }      # define core_clock      xredefine_params $libname "xparameters.h" "CORE_CLOCK_FREQ_HZ" + +    # define the values for the persistent storage in IIC +    xredefine_params $libname "xparameters.h" "IIC_PERSISTENT_BASEADDR" "IIC_PERSISTENT_HIGHADDR" "IIC_PERSISTENT_EEPROMADDR" +  }  proc xget_corefreq {} { @@ -117,7 +123,16 @@ proc xredefine_params {handle file_name args} {  	if {$value != ""} {  	    set value [xformat_addr_string $value $arg] -	    set name [string toupper $arg] + +	    if {[string compare -nocase $arg "IIC_PERSISTENT_BASEADDR"] == 0} { +		set name "PERSISTENT_0_IIC_0_BASEADDR" +	    } elseif {[string compare -nocase $arg "IIC_PERSISTENT_HIGHADDR"] == 0} { +		set name "PERSISTENT_0_IIC_0_HIGHADDR" +	    } elseif {[string compare -nocase $arg "IIC_PERSISTENT_EEPROMADDR"] == 0} { +		set name "PERSISTENT_0_IIC_0_EEPROMADDR" +	    } else { +		set name [string toupper $arg] +	    }  	    set name [format "XPAR_%s" $name]  	    puts $file_handle "#define $name $value"  	} @@ -140,6 +155,11 @@ proc xredefine_emac {drvhandle file_name} {  } +proc xredefine_iic {drvhandle file_name} { +    xredefine_include_file $drvhandle $file_name "iic" "C_BASEADDR" "C_HIGHADDR" "C_TEN_BIT_ADR" "DEVICE_ID" + +} +  #######################  proc xredefine_include_file {drv_handle file_name drv_string args} { @@ -221,6 +241,8 @@ proc post_generate {lib_handle} {  	if {[string compare -nocase $drvname "emac"] == 0} {  	    xcopy_emac $drv $dirname +	} elseif {[string compare -nocase $drvname "iic"] == 0} { +	    xcopy_iic $drv $dirname  	}      } @@ -267,6 +289,11 @@ proc xcopy_emac {drv_handle dirname} {      xcopy_dir $dirname $emac  } +proc xcopy_iic {drv_handle dirname} { +    set iic "board/xilinx/xilinx_iic" +    xcopy_dir $dirname $iic +} +  proc xcopy_dir {srcdir dstdir} {      set dstdirname [format "%s%s" "uboot/" $dstdir] diff --git a/board/xilinx/ml300/xparameters.h b/board/xilinx/ml300/xparameters.h index c6362562b..2c56737dc 100644 --- a/board/xilinx/ml300/xparameters.h +++ b/board/xilinx/ml300/xparameters.h @@ -1,48 +1,58 @@  /*******************************************************************  *  * CAUTION: This file is automatically generated by libgen. -* Version: Xilinx EDK 6.1.2 EDK_G.14 +* Version: Xilinx EDK 6.2 EDK_Gm.11  * DO NOT EDIT.  * -*     Author: Xilinx, Inc. -* -* -*     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. -* -* -*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A -*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS -*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD, -*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE -*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING -*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. -*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO -*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY -*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM -*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND -*     FITNESS FOR A PARTICULAR PURPOSE. -* -* -*     Xilinx hardware products are not intended for use in life support -*     appliances, devices, or systems. Use in such applications is -*     expressly prohibited. -* -* -*     (c) Copyright 2002-2004 Xilinx Inc. -*     All rights reserved. -* -* -*     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., -*     675 Mass Ave, Cambridge, MA 02139, USA. +* Copyright (c) 2003 Xilinx, Inc.  All rights reserved.  *  * Description: Driver parameters  *  *******************************************************************/ +/******************************************************************/ + +/* U-Boot Redefines */ + +/******************************************************************/ + +#define XPAR_UARTNS550_0_BASEADDR (XPAR_OPB_UART16550_0_BASEADDR+0x1000) +#define XPAR_UARTNS550_0_HIGHADDR XPAR_OPB_UART16550_0_HIGHADDR +#define XPAR_UARTNS550_0_CLOCK_FREQ_HZ XPAR_XUARTNS550_CLOCK_HZ +#define XPAR_UARTNS550_0_DEVICE_ID XPAR_OPB_UART16550_0_DEVICE_ID +#define XPAR_UARTNS550_1_BASEADDR (XPAR_OPB_UART16550_1_BASEADDR+0x1000) +#define XPAR_UARTNS550_1_HIGHADDR XPAR_OPB_UART16550_1_HIGHADDR +#define XPAR_UARTNS550_1_CLOCK_FREQ_HZ XPAR_XUARTNS550_CLOCK_HZ +#define XPAR_UARTNS550_1_DEVICE_ID XPAR_OPB_UART16550_1_DEVICE_ID + +/******************************************************************/ + +#define XPAR_IIC_0_BASEADDR XPAR_OPB_IIC_0_BASEADDR +#define XPAR_IIC_0_HIGHADDR XPAR_OPB_IIC_0_HIGHADDR +#define XPAR_IIC_0_TEN_BIT_ADR XPAR_OPB_IIC_0_TEN_BIT_ADR +#define XPAR_IIC_0_DEVICE_ID XPAR_OPB_IIC_0_DEVICE_ID + +/******************************************************************/ + +#define XPAR_EMAC_0_BASEADDR XPAR_OPB_ETHERNET_0_BASEADDR +#define XPAR_EMAC_0_HIGHADDR XPAR_OPB_ETHERNET_0_HIGHADDR +#define XPAR_EMAC_0_DMA_PRESENT XPAR_OPB_ETHERNET_0_DMA_PRESENT +#define XPAR_EMAC_0_MII_EXIST XPAR_OPB_ETHERNET_0_MII_EXIST +#define XPAR_EMAC_0_ERR_COUNT_EXIST XPAR_OPB_ETHERNET_0_ERR_COUNT_EXIST +#define XPAR_EMAC_0_DEVICE_ID XPAR_OPB_ETHERNET_0_DEVICE_ID + +/******************************************************************/ + +#define XPAR_CORE_CLOCK_FREQ_HZ XPAR_CPU_PPC405_CORE_CLOCK_FREQ_HZ + +/******************************************************************/ + +#define XPAR_PERSISTENT_0_IIC_0_BASEADDR 0x00000400 +#define XPAR_PERSISTENT_0_IIC_0_HIGHADDR 0x000007FF +#define XPAR_PERSISTENT_0_IIC_0_EEPROMADDR 0xA0 + +/******************************************************************/ +  #define XPAR_XPCI_NUM_INSTANCES 1  #define XPAR_XPCI_CLOCK_HZ 33333333  #define XPAR_OPB_PCI_REF_0_DEVICE_ID 0 @@ -181,36 +191,6 @@  /******************************************************************/ -#define STDIN_BASEADDRESS 0xA0000000 -#define STDOUT_BASEADDRESS 0xA0000000  #define XPAR_CPU_PPC405_CORE_CLOCK_FREQ_HZ 300000000  /******************************************************************/ - -/* U-Boot Redefines */ - -/******************************************************************/ - -#define XPAR_UARTNS550_0_BASEADDR (XPAR_OPB_UART16550_0_BASEADDR+0x1000) -#define XPAR_UARTNS550_0_HIGHADDR XPAR_OPB_UART16550_0_HIGHADDR -#define XPAR_UARTNS550_0_CLOCK_FREQ_HZ XPAR_XUARTNS550_CLOCK_HZ -#define XPAR_UARTNS550_0_DEVICE_ID XPAR_OPB_UART16550_0_DEVICE_ID -#define XPAR_UARTNS550_1_BASEADDR (XPAR_OPB_UART16550_1_BASEADDR+0x1000) -#define XPAR_UARTNS550_1_HIGHADDR XPAR_OPB_UART16550_1_HIGHADDR -#define XPAR_UARTNS550_1_CLOCK_FREQ_HZ XPAR_XUARTNS550_CLOCK_HZ -#define XPAR_UARTNS550_1_DEVICE_ID XPAR_OPB_UART16550_1_DEVICE_ID - -/******************************************************************/ - -#define XPAR_EMAC_0_BASEADDR XPAR_OPB_ETHERNET_0_BASEADDR -#define XPAR_EMAC_0_HIGHADDR XPAR_OPB_ETHERNET_0_HIGHADDR -#define XPAR_EMAC_0_DMA_PRESENT XPAR_OPB_ETHERNET_0_DMA_PRESENT -#define XPAR_EMAC_0_MII_EXIST XPAR_OPB_ETHERNET_0_MII_EXIST -#define XPAR_EMAC_0_ERR_COUNT_EXIST XPAR_OPB_ETHERNET_0_ERR_COUNT_EXIST -#define XPAR_EMAC_0_DEVICE_ID XPAR_OPB_ETHERNET_0_DEVICE_ID - -/******************************************************************/ - -#define XPAR_CORE_CLOCK_FREQ_HZ XPAR_CPU_PPC405_CORE_CLOCK_FREQ_HZ - -/******************************************************************/ diff --git a/board/xilinx/xilinx_enet/emac_adapter.c b/board/xilinx/xilinx_enet/emac_adapter.c index a3c37baab..bf8cf0bcc 100644 --- a/board/xilinx/xilinx_enet/emac_adapter.c +++ b/board/xilinx/xilinx_enet/emac_adapter.c @@ -56,8 +56,10 @@  static XEmac Emac;  static char etherrxbuff[PKTSIZE_ALIGN];	/* Receive buffer */ -/* hardcoded MAC address for the Xilinx EMAC Core */ +/* hardcoded MAC address for the Xilinx EMAC Core when env is nowhere*/ +#ifdef CFG_ENV_IS_NOWHERE  static u8 EMACAddr[ENET_ADDR_LENGTH] = { 0x00, 0x0a, 0x35, 0x00, 0x22, 0x01 }; +#endif  static int initialized = 0; @@ -86,8 +88,11 @@ eth_init(bd_t * bis)  	/* make sure the Emac is stopped before it is started */  	(void) XEmac_Stop(&Emac); +#ifdef CFG_ENV_IS_NOWHERE  	memcpy(bis->bi_enetaddr, EMACAddr, 6); -	Result = XEmac_SetMacAddress(&Emac, EMACAddr); +#endif + +	Result = XEmac_SetMacAddress(&Emac, bis->bi_enetaddr);  	if (Result != XST_SUCCESS) {  		return 0;  	} diff --git a/board/xilinx/xilinx_iic/iic_adapter.c b/board/xilinx/xilinx_iic/iic_adapter.c new file mode 100644 index 000000000..8ddba6ade --- /dev/null +++ b/board/xilinx/xilinx_iic/iic_adapter.c @@ -0,0 +1,529 @@ +/****************************************************************************** +* +*     Author: Xilinx, Inc. +* +* +*     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. +* +* +*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A +*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS +*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD, +*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE +*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING +*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. +*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO +*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY +*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM +*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND +*     FITNESS FOR A PARTICULAR PURPOSE. +* +* +*     Xilinx hardware products are not intended for use in life support +*     appliances, devices, or systems. Use in such applications is +*     expressly prohibited. +* +* +*     (c) Copyright 2002-2004 Xilinx Inc. +*     All rights reserved. +* +* +*     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., +*     675 Mass Ave, Cambridge, MA 02139, USA. +* +******************************************************************************/ + +#include <common.h> +#include <environment.h> +#include <net.h> +#include <configs/ml300.h> +#include "xparameters.h" + +#ifdef CFG_ENV_IS_IN_EEPROM +#include <i2c.h> +#include "xiic_l.h" + +#define IIC_DELAY     5000 + +static u8 envStep = 0;		/* 0 means crc has not been read */ +const u8 hex[] = "0123456789ABCDEF"; /* lookup table for ML300 CRC */ + +/************************************************************************ + * Use Xilinx provided driver to send data to EEPROM using iic bus. + */ +static void +send(u32 adr, u8 * data, u32 len) +{ +	u8 sendBuf[34];		/* first 2-bit is address and others are data */ +	u32 pos, wlen; +	u32 ret; + +	wlen = 32; +	for (pos = 0; pos < len; pos += 32) { +		if ((len - pos) < 32) +			wlen = len - pos; + +		/* Put address and data bits together */ +		sendBuf[0] = (u8) ((adr + pos) >> 8); +		sendBuf[1] = (u8) (adr + pos); +		memcpy(&sendBuf[2], &data[pos], wlen); + +		/* Send to EEPROM through iic bus */ +		ret = XIic_Send(XPAR_IIC_0_BASEADDR, CFG_I2C_EEPROM_ADDR >> 1, +				sendBuf, wlen + 2); + +		udelay(IIC_DELAY); +	} +} + +/************************************************************************ + * Use Xilinx provided driver to read data from EEPROM using the iic bus. + */ +static void +receive(u32 adr, u8 * data, u32 len) +{ +	u8 address[2]; +	u32 ret; + +	address[0] = (u8) (adr >> 8); +	address[1] = (u8) adr; + +	/* Provide EEPROM address */ +	ret = +	    XIic_Send(XPAR_IIC_0_BASEADDR, CFG_I2C_EEPROM_ADDR >> 1, address, +		      2); +	/* Receive data from EEPROM */ +	ret = +	    XIic_Recv(XPAR_IIC_0_BASEADDR, CFG_I2C_EEPROM_ADDR >> 1, data, len); +} + +/************************************************************************ + * Convert a hexadecimal string to its equivalent integer value. + */ +static u8 +axtoi(u8 * hexStg) +{ +	u8 n;			/* position in string */ +	u8 m;			/* position in digit[] to shift */ +	u8 count;		/* loop index */ +	u8 intValue;		/* integer value of hex string */ +	u8 digit[2];		/* hold values to convert */ + +	for (n = 0; n < 2; n++) { +		if (hexStg[n] == '\0') +			break; +		if (hexStg[n] > 0x29 && hexStg[n] < 0x40) +			digit[n] = hexStg[n] & 0x0f; +		else if (hexStg[n] >= 'a' && hexStg[n] <= 'f') +			digit[n] = (hexStg[n] & 0x0f) + 9; +		else if (hexStg[n] >= 'A' && hexStg[n] <= 'F') +			digit[n] = (hexStg[n] & 0x0f) + 9; +		else +			break; +	} + +	intValue = 0; +	count = n; +	m = n - 1; +	n = 0; +	while (n < count) { +		intValue = intValue | (digit[n] << (m << 2)); +		m--;		/* adjust the position to set */ +		n++;		/* next digit to process */ +	} + +	return (intValue); +} + +/************************************************************************ + * Convert an integer string to its equivalent value. + */ +static u8 +atoi(uchar * string) +{ +	u8 res = 0; +	while (*string >= '0' && *string <= '9') { +		res *= 10; +		res += *string - '0'; +		string++; +	} + +	return res; +} + +/************************************************************************ + * Key-value pairs are separated by "=" sign. + */ +static void +findKey(uchar * buffer, int *loc, u8 len) +{ +	u32 i; + +	for (i = 0; i < len; i++) +		if (buffer[i] == '=') { +			*loc = i; +			return; +		} + +	/* return -1 is no "=" sign found */ +	*loc = -1; +} + +/************************************************************************ + * Compute a new ML300 CRC when user calls the saveenv command. + * Also update EEPROM with new CRC value. + */ +static u8 +update_crc(u32 len, uchar * data) +{ +	uchar temp[6] = { 'C', '=', 0x00, 0x00, 0x00, 0x00 }; +	u32 crc;		/* new crc value */ +	u32 i; + +	crc = 0; + +	/* calculate new CRC */ +	for (i = 0; i < len; i++) +		crc += data[i]; + +	/* CRC includes key for check sum */ +	crc += 'C' + '='; + +	/* compose new CRC to be updated */ +	temp[2] = hex[(crc >> 4) & 0xf]; +	temp[3] = hex[crc & 0xf]; + +	/* check to see if env size exceeded */ +	if (len + 6 > ENV_SIZE) { +		printf("ERROR: not enough space to store CRC on EEPROM"); +		return 1; +	} + +	memcpy(data + len, temp, 6); +	return 0; +} + +/************************************************************************ + * Read out ML300 CRC and compare it with a runtime calculated ML300 CRC. + * If equal, then pass back a u-boot CRC value, otherwise pass back + * junk to indicate CRC error. +*/ +static void +read_crc(uchar * buffer, int len) +{ +	u32 addr, n; +	u32 crc;		/* runtime crc */ +	u8 old[2] = { 0xff, 0xff };	/* current CRC in EEPROM */ +	u8 stop;		/* indication of end of env data */ +	u8 pre;			/* previous EEPROM data bit */ +	int i, loc; + +	addr = CFG_ENV_OFFSET;	/* start from first env address */ +	n = 0; +	pre = 1; +	stop = 1; +	crc = 0; + +	/* calculate runtime CRC according to ML300 and read back +	   old CRC stored in the EEPROM */ +	while (n < CFG_ENV_SIZE) { +		receive(addr, buffer, len); + +		/* found two null chars, end of env */ +		if ((pre || buffer[0]) == 0) +			break; + +		findKey(buffer, &loc, len); + +		/* found old check sum, read and store old CRC */ +		if ((loc == 0 && pre == 'C') +		    || (loc > 0 && buffer[loc - 1] == 'C')) +			receive(addr + loc + 1, old, 2); + +		pre = buffer[len - 1]; + +		/* calculate runtime ML300 CRC */ +		crc += buffer[0]; +		i = 1; +		do { +			crc += buffer[i]; +			stop = buffer[i] || buffer[i - 1]; +			i++; +		} while (stop && (i < len)); + +		if (stop == 0) +			break; + +		n += len; +		addr += len; +	} + +	/* exclude old CRC from runtime calculation */ +	crc -= (old[0] + old[1]); + +	/* match CRC values, send back u-boot CRC */ +	if ((old[0] == hex[(crc >> 4) & 0xf]) +	    && (old[1] == hex[crc & 0xf])) { +		crc = 0; +		n = 0; +		addr = +		    CFG_ENV_OFFSET - offsetof(env_t, crc) + offsetof(env_t, +								     data); +		/* calculate u-boot crc */ +		while (n < ENV_SIZE) { +			receive(addr, buffer, len); +			crc = crc32(crc, buffer, len); +			n += len; +			addr += len; +		} + +		memcpy(buffer, &crc, 4); +	} +} + +/************************************************************************ + * Convert IP address to hexadecimals. + */ +static void +ip_ml300(uchar * s, uchar * res) +{ +	uchar temp[2]; +	u8 i; + +	res[0] = 0x00; + +	for (i = 0; i < 4; i++) { +		sprintf(temp, "%02x", atoi(s)); +		s = strchr(s, '.') + 1; +		strcat(res, temp); +	} +} + +/************************************************************************ + * Change 0xff (255), a dummy null char to 0x00. + */ +static void +change_null(uchar * s) +{ +	if (s != NULL) { +		change_null(strchr(s + 1, 255)); +		*(strchr(s, 255)) = '\0'; +	} +} + +/************************************************************************ + * Update environment variable name and values to u-boot standard. + */ +void +convert_env(void) +{ +	uchar *s;		/* pointer to env value */ +	uchar temp[20];		/* temp storage for addresses */ + +	/* E -> ethaddr */ +	s = getenv("E"); +	if (s != NULL) { +		sprintf(temp, "%c%c.%c%c.%c%c.%c%c.%c%c.%c%c", +			*s++, *s++, *s++, *s++, *s++, *s++, +			*s++, *s++, *s++, *s++, *s++, *s); +		setenv("ethaddr", temp); +		setenv("E", NULL); +	} + +	/* L -> serial# */ +	s = getenv("L"); +	if (s != NULL) { +		setenv("serial#", s); +		setenv("L", NULL); +	} + +	/* I -> ipaddr */ +	s = getenv("I"); +	if (s != NULL) { +		sprintf(temp, "%d.%d.%d.%d", axtoi(s), axtoi(s + 2), +			axtoi(s + 4), axtoi(s + 6)); +		setenv("ipaddr", temp); +		setenv("I", NULL); +	} + +	/* S -> serverip */ +	s = getenv("S"); +	if (s != NULL) { +		sprintf(temp, "%d.%d.%d.%d", axtoi(s), axtoi(s + 2), +			axtoi(s + 4), axtoi(s + 6)); +		setenv("serverip", temp); +		setenv("S", NULL); +	} + +	/* A -> bootargs */ +	s = getenv("A"); +	if (s != NULL) { +		setenv("bootargs", s); +		setenv("A", NULL); +	} + +	/* F -> bootfile */ +	s = getenv("F"); +	if (s != NULL) { +		setenv("bootfile", s); +		setenv("F", NULL); +	} + +	/* M -> bootcmd */ +	s = getenv("M"); +	if (s != NULL) { +		setenv("bootcmd", s); +		setenv("M", NULL); +	} + +	/* Don't include C (CRC) */ +	setenv("C", NULL); +} + +/************************************************************************ + * Save user modified environment values back to EEPROM. + */ +static void +save_env(void) +{ +	uchar eprom[ENV_SIZE];	/* buffer to be written back to EEPROM */ +	uchar *s, temp[20]; +	uchar ff[] = { 0xff, 0x00 };	/* dummy null value */ +	u32 len;		/* length of env to be written to EEPROM */ + +	eprom[0] = 0x00; + +	/* ethaddr -> E */ +	s = getenv("ethaddr"); +	if (s != NULL) { +		strcat(eprom, "E="); +		sprintf(temp, "%c%c%c%c%c%c%c%c%c%c%c%c", +			*s, *(s + 1), *(s + 3), *(s + 4), *(s + 6), *(s + 7), +			*(s + 9), *(s + 10), *(s + 12), *(s + 13), *(s + 15), +			*(s + 16)); +		strcat(eprom, temp); +		strcat(eprom, ff); +	} + +	/* serial# -> L */ +	s = getenv("serial#"); +	if (s != NULL) { +		strcat(eprom, "L="); +		strcat(eprom, s); +		strcat(eprom, ff); +	} + +	/* ipaddr -> I */ +	s = getenv("ipaddr"); +	if (s != NULL) { +		strcat(eprom, "I="); +		ip_ml300(s, temp); +		strcat(eprom, temp); +		strcat(eprom, ff); +	} + +	/* serverip -> S */ +	s = getenv("serverip"); +	if (s != NULL) { +		strcat(eprom, "S="); +		ip_ml300(s, temp); +		strcat(eprom, temp); +		strcat(eprom, ff); +	} + +	/* bootargs -> A */ +	s = getenv("bootargs"); +	if (s != NULL) { +		strcat(eprom, "A="); +		strcat(eprom, s); +		strcat(eprom, ff); +	} + +	/* bootfile -> F */ +	s = getenv("bootfile"); +	if (s != NULL) { +		strcat(eprom, "F="); +		strcat(eprom, s); +		strcat(eprom, ff); +	} + +	/* bootcmd -> M */ +	s = getenv("bootcmd"); +	if (s != NULL) { +		strcat(eprom, "M="); +		strcat(eprom, s); +		strcat(eprom, ff); +	} + +	len = strlen(eprom);	/* find env length without crc */ +	change_null(eprom);	/* change 0xff to 0x00 */ + +	/* update EEPROM env values if there is enough space */ +	if (update_crc(len, eprom) == 0) +		send(CFG_ENV_OFFSET, eprom, len + 6); +} + +/************************************************************************ + * U-boot call for EEPROM read associated activities. + */ +int +i2c_read(uchar chip, uint addr, int alen, uchar * buffer, int len) +{ + +	if (envStep == 0) { +		/* first read call is for crc */ +		read_crc(buffer, len); +		++envStep; +		return 0; +	} else if (envStep == 1) { +		/* then read out EEPROM content for runtime u-boot CRC calculation */ +		receive(addr, buffer, len); + +		if (addr + len - CFG_ENV_OFFSET == CFG_ENV_SIZE) +			/* end of runtime crc read */ +			++envStep; +		return 0; +	} + +	if (len < 2) { +		/* when call getenv_r */ +		receive(addr, buffer, len); +	} else if (addr + len < CFG_ENV_OFFSET + CFG_ENV_SIZE) { +		/* calling env_relocate(), but don't read out +		   crc value from EEPROM */ +		receive(addr, buffer + 4, len); +	} else { +		receive(addr, buffer + 4, len - 4); +	} + +	return 0; + +} + +/************************************************************************ + * U-boot call for EEPROM write acativities. + */ +int +i2c_write(uchar chip, uint addr, int alen, uchar * buffer, int len) +{ +	/* save env on last page write called by u-boot */ +	if (addr + len >= CFG_ENV_OFFSET + CFG_ENV_SIZE) +		save_env(); + +	return 0; +} + +/************************************************************************ + * Dummy function. + */ +int +i2c_probe(uchar chip) +{ +	return 1; +} + +#endif diff --git a/board/xilinx/xilinx_iic/xiic_l.c b/board/xilinx/xilinx_iic/xiic_l.c new file mode 100644 index 000000000..6b7816373 --- /dev/null +++ b/board/xilinx/xilinx_iic/xiic_l.c @@ -0,0 +1,484 @@ +/* $Id: xiic_l.c,v 1.2 2002/12/05 19:32:40 meinelte Exp $ */ +/****************************************************************************** +* +*	XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" +*	AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND +*	SOLUTIONS FOR XILINX DEVICES.  BY PROVIDING THIS DESIGN, CODE, +*	OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, +*	APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION +*	THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, +*	AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE +*	FOR YOUR IMPLEMENTATION.  XILINX EXPRESSLY DISCLAIMS ANY +*	WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE +*	IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR +*	REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF +*	INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +*	FOR A PARTICULAR PURPOSE. +* +*	(c) Copyright 2002 Xilinx Inc. +*	All rights reserved. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xiic_l.c +* +* This file contains low-level driver functions that can be used to access the +* device.  The user should refer to the hardware device specification for more +* details of the device operation. +* +* <pre> +* MODIFICATION HISTORY: +* +* Ver	Who  Date     Changes +* ----- --- -------  ----------------------------------------------- +* 1.01b jhl 5/13/02  First release +* 1.01b jhl 10/14/02 Corrected bug in the receive function, the setup of the +*		     interrupt status mask was not being done in the loop such +*		     that a read would sometimes fail on the last byte because +*		     the transmit error which should have been ignored was +*		     being used.  This would leave an extra byte in the FIFO +*		     and the bus throttled such that the next operation would +*		     also fail.	 Also updated the receive function to not +*		     disable the device after the last byte until after the +*		     bus transitions to not busy which is more consistent +*		     with the expected behavior. +* 1.01c ecm 12/05/02 new rev +* </pre> +* +****************************************************************************/ + +/***************************** Include Files *******************************/ + +#include "xbasic_types.h" +#include "xio.h" +#include "xipif_v1_23_b.h" +#include "xiic_l.h" + +/************************** Constant Definitions ***************************/ + +/**************************** Type Definitions *****************************/ + + +/***************** Macros (Inline Functions) Definitions *******************/ + + +/****************************************************************************** +* +* This macro clears the specified interrupt in the IPIF interrupt status +* register.  It is non-destructive in that the register is read and only the +* interrupt specified is cleared.  Clearing an interrupt acknowledges it. +* +* @param    BaseAddress contains the IPIF registers base address. +* +* @param    InterruptMask contains the interrupts to be disabled +* +* @return +* +* None. +* +* @note +* +* Signature: void XIic_mClearIisr(u32 BaseAddress, +*				  u32 InterruptMask); +* +******************************************************************************/ +#define XIic_mClearIisr(BaseAddress, InterruptMask)		    \ +    XIIF_V123B_WRITE_IISR((BaseAddress),			    \ +	XIIF_V123B_READ_IISR(BaseAddress) & (InterruptMask)) + +/****************************************************************************** +* +* This macro sends the address for a 7 bit address during both read and write +* operations. It takes care of the details to format the address correctly. +* This macro is designed to be called internally to the drivers. +* +* @param    SlaveAddress contains the address of the slave to send to. +* +* @param    Operation indicates XIIC_READ_OPERATION or XIIC_WRITE_OPERATION +* +* @return +* +* None. +* +* @note +* +* Signature: void XIic_mSend7BitAddr(u16 SlaveAddress, u8 Operation); +* +******************************************************************************/ +#define XIic_mSend7BitAddress(BaseAddress, SlaveAddress, Operation)	    \ +{									    \ +    u8 LocalAddr = (u8)(SlaveAddress << 1);			    \ +    LocalAddr = (LocalAddr & 0xFE) | (Operation);			    \ +    XIo_Out8(BaseAddress + XIIC_DTR_REG_OFFSET, LocalAddr);		    \ +} + +/************************** Function Prototypes ****************************/ + +static unsigned RecvData (u32 BaseAddress, u8 * BufferPtr, +			  unsigned ByteCount); +static unsigned SendData (u32 BaseAddress, u8 * BufferPtr, +			  unsigned ByteCount); + +/************************** Variable Definitions **************************/ + + +/****************************************************************************/ +/** +* Receive data as a master on the IIC bus.  This function receives the data +* using polled I/O and blocks until the data has been received.	 It only +* supports 7 bit addressing and non-repeated start modes of operation.	The +* user is responsible for ensuring the bus is not busy if multiple masters +* are present on the bus. +* +* @param    BaseAddress contains the base address of the IIC device. +* @param    Address contains the 7 bit IIC address of the device to send the +*	    specified data to. +* @param    BufferPtr points to the data to be sent. +* @param    ByteCount is the number of bytes to be sent. +* +* @return +* +* The number of bytes received. +* +* @note +* +* None +* +******************************************************************************/ +unsigned XIic_Recv (u32 BaseAddress, u8 Address, +		    u8 * BufferPtr, unsigned ByteCount) +{ +	u8 CntlReg; +	unsigned RemainingByteCount; + +	/* Tx error is enabled incase the address (7 or 10) has no device to answer +	 * with Ack. When only one byte of data, must set NO ACK before address goes +	 * out therefore Tx error must not be enabled as it will go off immediately +	 * and the Rx full interrupt will be checked.  If full, then the one byte +	 * was received and the Tx error will be disabled without sending an error +	 * callback msg. +	 */ +	XIic_mClearIisr (BaseAddress, +			 XIIC_INTR_RX_FULL_MASK | XIIC_INTR_TX_ERROR_MASK | +			 XIIC_INTR_ARB_LOST_MASK); + +	/* Set receive FIFO occupancy depth for 1 byte (zero based) +	 */ +	XIo_Out8 (BaseAddress + XIIC_RFD_REG_OFFSET, 0); + +	/* 7 bit slave address, send the address for a read operation +	 * and set the state to indicate the address has been sent +	 */ +	XIic_mSend7BitAddress (BaseAddress, Address, XIIC_READ_OPERATION); + +	/* MSMS gets set after putting data in FIFO. Start the master receive +	 * operation by setting CR Bits MSMS to Master, if the buffer is only one +	 * byte, then it should not be acknowledged to indicate the end of data +	 */ +	CntlReg = XIIC_CR_MSMS_MASK | XIIC_CR_ENABLE_DEVICE_MASK; +	if (ByteCount == 1) { +		CntlReg |= XIIC_CR_NO_ACK_MASK; +	} + +	/* Write out the control register to start receiving data and call the +	 * function to receive each byte into the buffer +	 */ +	XIo_Out8 (BaseAddress + XIIC_CR_REG_OFFSET, CntlReg); + +	/* Clear the latched interrupt status for the bus not busy bit which must +	 * be done while the bus is busy +	 */ +	XIic_mClearIisr (BaseAddress, XIIC_INTR_BNB_MASK); + +	/* Try to receive the data from the IIC bus */ + +	RemainingByteCount = RecvData (BaseAddress, BufferPtr, ByteCount); +	/* +	 * The receive is complete, disable the IIC device and return the number of +	 * bytes that was received +	 */ +	XIo_Out8 (BaseAddress + XIIC_CR_REG_OFFSET, 0); + +	/* Return the number of bytes that was received */ + +	return ByteCount - RemainingByteCount; +} + +/****************************************************************************** +* +* Receive the specified data from the device that has been previously addressed +* on the IIC bus.  This function assumes that the 7 bit address has been sent +* and it should wait for the transmit of the address to complete. +* +* @param    BaseAddress contains the base address of the IIC device. +* @param    BufferPtr points to the buffer to hold the data that is received. +* @param    ByteCount is the number of bytes to be received. +* +* @return +* +* The number of bytes remaining to be received. +* +* @note +* +* This function does not take advantage of the receive FIFO because it is +* designed for minimal code space and complexity.  It contains loops that +* that could cause the function not to return if the hardware is not working. +* +* This function assumes that the calling function will disable the IIC device +* after this function returns. +* +******************************************************************************/ +static unsigned RecvData (u32 BaseAddress, u8 * BufferPtr, unsigned ByteCount) +{ +	u8 CntlReg; +	u32 IntrStatusMask; +	u32 IntrStatus; + +	/* Attempt to receive the specified number of bytes on the IIC bus */ + +	while (ByteCount > 0) { +		/* Setup the mask to use for checking errors because when receiving one +		 * byte OR the last byte of a multibyte message an error naturally +		 * occurs when the no ack is done to tell the slave the last byte +		 */ +		if (ByteCount == 1) { +			IntrStatusMask = +				XIIC_INTR_ARB_LOST_MASK | XIIC_INTR_BNB_MASK; +		} else { +			IntrStatusMask = +				XIIC_INTR_ARB_LOST_MASK | +				XIIC_INTR_TX_ERROR_MASK | XIIC_INTR_BNB_MASK; +		} + +		/* Wait for the previous transmit and the 1st receive to complete +		 * by checking the interrupt status register of the IPIF +		 */ +		while (1) { +			IntrStatus = XIIF_V123B_READ_IISR (BaseAddress); +			if (IntrStatus & XIIC_INTR_RX_FULL_MASK) { +				break; +			} +			/* Check the transmit error after the receive full because when +			 * sending only one byte transmit error will occur because of the +			 * no ack to indicate the end of the data +			 */ +			if (IntrStatus & IntrStatusMask) { +				return ByteCount; +			} +		} + +		CntlReg = XIo_In8 (BaseAddress + XIIC_CR_REG_OFFSET); + +		/* Special conditions exist for the last two bytes so check for them +		 * Note that the control register must be setup for these conditions +		 * before the data byte which was already received is read from the +		 * receive FIFO (while the bus is throttled +		 */ +		if (ByteCount == 1) { +			/* For the last data byte, it has already been read and no ack +			 * has been done, so clear MSMS while leaving the device enabled +			 * so it can get off the IIC bus appropriately with a stop. +			 */ +			XIo_Out8 (BaseAddress + XIIC_CR_REG_OFFSET, +				  XIIC_CR_ENABLE_DEVICE_MASK); +		} + +		/* Before the last byte is received, set NOACK to tell the slave IIC +		 * device that it is the end, this must be done before reading the byte +		 * from the FIFO +		 */ +		if (ByteCount == 2) { +			/* Write control reg with NO ACK allowing last byte to +			 * have the No ack set to indicate to slave last byte read. +			 */ +			XIo_Out8 (BaseAddress + XIIC_CR_REG_OFFSET, +				  CntlReg | XIIC_CR_NO_ACK_MASK); +		} + +		/* Read in data from the FIFO and unthrottle the bus such that the +		 * next byte is read from the IIC bus +		 */ +		*BufferPtr++ = XIo_In8 (BaseAddress + XIIC_DRR_REG_OFFSET); + +		/* Clear the latched interrupt status so that it will be updated with +		 * the new state when it changes, this must be done after the receive +		 * register is read +		 */ +		XIic_mClearIisr (BaseAddress, XIIC_INTR_RX_FULL_MASK | +				 XIIC_INTR_TX_ERROR_MASK | +				 XIIC_INTR_ARB_LOST_MASK); +		ByteCount--; +	} + +	/* Wait for the bus to transition to not busy before returning, the IIC +	 * device cannot be disabled until this occurs.	 It should transition as +	 * the MSMS bit of the control register was cleared before the last byte +	 * was read from the FIFO. +	 */ +	while (1) { +		if (XIIF_V123B_READ_IISR (BaseAddress) & XIIC_INTR_BNB_MASK) { +			break; +		} +	} + +	return ByteCount; +} + +/****************************************************************************/ +/** +* Send data as a master on the IIC bus.	 This function sends the data +* using polled I/O and blocks until the data has been sent.  It only supports +* 7 bit addressing and non-repeated start modes of operation.  The user is +* responsible for ensuring the bus is not busy if multiple masters are present +* on the bus. +* +* @param    BaseAddress contains the base address of the IIC device. +* @param    Address contains the 7 bit IIC address of the device to send the +*	    specified data to. +* @param    BufferPtr points to the data to be sent. +* @param    ByteCount is the number of bytes to be sent. +* +* @return +* +* The number of bytes sent. +* +* @note +* +* None +* +******************************************************************************/ +unsigned XIic_Send (u32 BaseAddress, u8 Address, +		    u8 * BufferPtr, unsigned ByteCount) +{ +	unsigned RemainingByteCount; + +	/* Put the address into the FIFO to be sent and indicate that the operation +	 * to be performed on the bus is a write operation +	 */ +	XIic_mSend7BitAddress (BaseAddress, Address, XIIC_WRITE_OPERATION); + +	/* Clear the latched interrupt status so that it will be updated with the +	 * new state when it changes, this must be done after the address is put +	 * in the FIFO +	 */ +	XIic_mClearIisr (BaseAddress, XIIC_INTR_TX_EMPTY_MASK | +			 XIIC_INTR_TX_ERROR_MASK | XIIC_INTR_ARB_LOST_MASK); + +	/* MSMS must be set after putting data into transmit FIFO, indicate the +	 * direction is transmit, this device is master and enable the IIC device +	 */ +	XIo_Out8 (BaseAddress + XIIC_CR_REG_OFFSET, +		  XIIC_CR_MSMS_MASK | XIIC_CR_DIR_IS_TX_MASK | +		  XIIC_CR_ENABLE_DEVICE_MASK); + +	/* Clear the latched interrupt +	 * status for the bus not busy bit which must be done while the bus is busy +	 */ +	XIic_mClearIisr (BaseAddress, XIIC_INTR_BNB_MASK); + +	/* Send the specified data to the device on the IIC bus specified by the +	 * the address +	 */ +	RemainingByteCount = SendData (BaseAddress, BufferPtr, ByteCount); + +	/* +	 * The send is complete, disable the IIC device and return the number of +	 * bytes that was sent +	 */ +	XIo_Out8 (BaseAddress + XIIC_CR_REG_OFFSET, 0); + +	return ByteCount - RemainingByteCount; +} + +/****************************************************************************** +* +* Send the specified buffer to the device that has been previously addressed +* on the IIC bus.  This function assumes that the 7 bit address has been sent +* and it should wait for the transmit of the address to complete. +* +* @param    BaseAddress contains the base address of the IIC device. +* @param    BufferPtr points to the data to be sent. +* @param    ByteCount is the number of bytes to be sent. +* +* @return +* +* The number of bytes remaining to be sent. +* +* @note +* +* This function does not take advantage of the transmit FIFO because it is +* designed for minimal code space and complexity.  It contains loops that +* that could cause the function not to return if the hardware is not working. +* +******************************************************************************/ +static unsigned SendData (u32 BaseAddress, u8 * BufferPtr, unsigned ByteCount) +{ +	u32 IntrStatus; + +	/* Send the specified number of bytes in the specified buffer by polling +	 * the device registers and blocking until complete +	 */ +	while (ByteCount > 0) { +		/* Wait for the transmit to be empty before sending any more data +		 * by polling the interrupt status register +		 */ +		while (1) { +			IntrStatus = XIIF_V123B_READ_IISR (BaseAddress); + +			if (IntrStatus & (XIIC_INTR_TX_ERROR_MASK | +					  XIIC_INTR_ARB_LOST_MASK | +					  XIIC_INTR_BNB_MASK)) { +				return ByteCount; +			} + +			if (IntrStatus & XIIC_INTR_TX_EMPTY_MASK) { +				break; +			} +		} +		/* If there is more than one byte to send then put the next byte to send +		 * into the transmit FIFO +		 */ +		if (ByteCount > 1) { +			XIo_Out8 (BaseAddress + XIIC_DTR_REG_OFFSET, +				  *BufferPtr++); +		} else { +			/* Set the stop condition before sending the last byte of data so that +			 * the stop condition will be generated immediately following the data +			 * This is done by clearing the MSMS bit in the control register. +			 */ +			XIo_Out8 (BaseAddress + XIIC_CR_REG_OFFSET, +				  XIIC_CR_ENABLE_DEVICE_MASK | +				  XIIC_CR_DIR_IS_TX_MASK); + +			/* Put the last byte to send in the transmit FIFO */ + +			XIo_Out8 (BaseAddress + XIIC_DTR_REG_OFFSET, +				  *BufferPtr++); +		} + +		/* Clear the latched interrupt status register and this must be done after +		 * the transmit FIFO has been written to or it won't clear +		 */ +		XIic_mClearIisr (BaseAddress, XIIC_INTR_TX_EMPTY_MASK); + +		/* Update the byte count to reflect the byte sent and clear the latched +		 * interrupt status so it will be updated for the new state +		 */ +		ByteCount--; +	} + +	/* Wait for the bus to transition to not busy before returning, the IIC +	 * device cannot be disabled until this occurs. +	 * Note that this is different from a receive operation because the stop +	 * condition causes the bus to go not busy. +	 */ +	while (1) { +		if (XIIF_V123B_READ_IISR (BaseAddress) & XIIC_INTR_BNB_MASK) { +			break; +		} +	} + +	return ByteCount; +} diff --git a/board/xilinx/xilinx_iic/xiic_l.h b/board/xilinx/xilinx_iic/xiic_l.h new file mode 100644 index 000000000..a2c4c496a --- /dev/null +++ b/board/xilinx/xilinx_iic/xiic_l.h @@ -0,0 +1,150 @@ +/* $Id: xiic_l.h,v 1.2 2002/12/05 19:32:40 meinelte Exp $ */ +/***************************************************************************** +* +*	XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" +*	AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND +*	SOLUTIONS FOR XILINX DEVICES.  BY PROVIDING THIS DESIGN, CODE, +*	OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, +*	APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION +*	THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, +*	AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE +*	FOR YOUR IMPLEMENTATION.  XILINX EXPRESSLY DISCLAIMS ANY +*	WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE +*	IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR +*	REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF +*	INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +*	FOR A PARTICULAR PURPOSE. +* +*	(c) Copyright 2002 Xilinx Inc. +*	All rights reserved. +* +*****************************************************************************/ +/****************************************************************************/ +/** +* +* @file xiic_l.h +* +* This header file contains identifiers and low-level driver functions (or +* macros) that can be used to access the device.  High-level driver functions +* are defined in xiic.h. +* +* <pre> +* MODIFICATION HISTORY: +* +* Ver	Who  Date     Changes +* ----- ---- -------- ----------------------------------------------- +* 1.00b jhl  05/07/02 First release +* 1.01c ecm  12/05/02 new rev +* </pre> +* +*****************************************************************************/ + +#ifndef XIIC_L_H /* prevent circular inclusions */ +#define XIIC_L_H /* by using protection macros */ + +/***************************** Include Files ********************************/ + +#include "xbasic_types.h" + +/************************** Constant Definitions ****************************/ + +#define XIIC_MSB_OFFSET		       3 + +#define XIIC_REG_OFFSET 0x100 + XIIC_MSB_OFFSET + +/* + * Register offsets in bytes from RegisterBase. Three is added to the + * base offset to access LSB (IBM style) of the word + */ +#define XIIC_CR_REG_OFFSET   0x00+XIIC_REG_OFFSET   /* Control Register	  */ +#define XIIC_SR_REG_OFFSET   0x04+XIIC_REG_OFFSET   /* Status Register	  */ +#define XIIC_DTR_REG_OFFSET  0x08+XIIC_REG_OFFSET   /* Data Tx Register	  */ +#define XIIC_DRR_REG_OFFSET  0x0C+XIIC_REG_OFFSET   /* Data Rx Register	  */ +#define XIIC_ADR_REG_OFFSET  0x10+XIIC_REG_OFFSET   /* Address Register	  */ +#define XIIC_TFO_REG_OFFSET  0x14+XIIC_REG_OFFSET   /* Tx FIFO Occupancy  */ +#define XIIC_RFO_REG_OFFSET  0x18+XIIC_REG_OFFSET   /* Rx FIFO Occupancy  */ +#define XIIC_TBA_REG_OFFSET  0x1C+XIIC_REG_OFFSET   /* 10 Bit Address reg */ +#define XIIC_RFD_REG_OFFSET  0x20+XIIC_REG_OFFSET   /* Rx FIFO Depth reg  */ + +/* Control Register masks */ + +#define XIIC_CR_ENABLE_DEVICE_MASK	  0x01	/* Device enable = 1	  */ +#define XIIC_CR_TX_FIFO_RESET_MASK	  0x02	/* Transmit FIFO reset=1  */ +#define XIIC_CR_MSMS_MASK		  0x04	/* Master starts Txing=1  */ +#define XIIC_CR_DIR_IS_TX_MASK		  0x08	/* Dir of tx. Txing=1	  */ +#define XIIC_CR_NO_ACK_MASK		  0x10	/* Tx Ack. NO ack = 1	  */ +#define XIIC_CR_REPEATED_START_MASK	  0x20	/* Repeated start = 1	  */ +#define XIIC_CR_GENERAL_CALL_MASK	  0x40	/* Gen Call enabled = 1	  */ + +/* Status Register masks */ + +#define XIIC_SR_GEN_CALL_MASK		  0x01	/* 1=a mstr issued a GC	  */ +#define XIIC_SR_ADDR_AS_SLAVE_MASK	  0x02	/* 1=when addr as slave	  */ +#define XIIC_SR_BUS_BUSY_MASK		  0x04	/* 1 = bus is busy	  */ +#define XIIC_SR_MSTR_RDING_SLAVE_MASK	  0x08	/* 1=Dir: mstr <-- slave  */ +#define XIIC_SR_TX_FIFO_FULL_MASK	  0x10	/* 1 = Tx FIFO full	  */ +#define XIIC_SR_RX_FIFO_FULL_MASK	  0x20	/* 1 = Rx FIFO full	  */ +#define XIIC_SR_RX_FIFO_EMPTY_MASK	  0x40	/* 1 = Rx FIFO empty	  */ + +/* IPIF Interrupt Status Register masks	   Interrupt occurs when...	  */ + +#define XIIC_INTR_ARB_LOST_MASK		  0x01	/* 1 = arbitration lost	  */ +#define XIIC_INTR_TX_ERROR_MASK		  0x02	/* 1=Tx error/msg complete*/ +#define XIIC_INTR_TX_EMPTY_MASK		  0x04	/* 1 = Tx FIFO/reg empty  */ +#define XIIC_INTR_RX_FULL_MASK		  0x08	/* 1=Rx FIFO/reg=OCY level*/ +#define XIIC_INTR_BNB_MASK		  0x10	/* 1 = Bus not busy	  */ +#define XIIC_INTR_AAS_MASK		  0x20	/* 1 = when addr as slave */ +#define XIIC_INTR_NAAS_MASK		  0x40	/* 1 = not addr as slave  */ +#define XIIC_INTR_TX_HALF_MASK		  0x80	/* 1 = TX FIFO half empty */ + +/* IPIF Device Interrupt Register masks */ + +#define XIIC_IPIF_IIC_MASK	    0x00000004UL    /* 1=inter enabled */ +#define XIIC_IPIF_ERROR_MASK	    0x00000001UL    /* 1=inter enabled */ +#define XIIC_IPIF_INTER_ENABLE_MASK  (XIIC_IPIF_IIC_MASK |  \ +				      XIIC_IPIF_ERROR_MASK) + +#define XIIC_TX_ADDR_SENT	      0x00 +#define XIIC_TX_ADDR_MSTR_RECV_MASK   0x02 + +/* The following constants specify the depth of the FIFOs */ + +#define IIC_RX_FIFO_DEPTH	  16   /* Rx fifo capacity		 */ +#define IIC_TX_FIFO_DEPTH	  16   /* Tx fifo capacity		 */ + +/* The following constants specify groups of interrupts that are typically + * enabled or disables at the same time + */ +#define XIIC_TX_INTERRUPTS					    \ +	    (XIIC_INTR_TX_ERROR_MASK | XIIC_INTR_TX_EMPTY_MASK |    \ +	     XIIC_INTR_TX_HALF_MASK) + +#define XIIC_TX_RX_INTERRUPTS (XIIC_INTR_RX_FULL_MASK | XIIC_TX_INTERRUPTS) + +/* The following constants are used with the following macros to specify the + * operation, a read or write operation. + */ +#define XIIC_READ_OPERATION  1 +#define XIIC_WRITE_OPERATION 0 + +/* The following constants are used with the transmit FIFO fill function to + * specify the role which the IIC device is acting as, a master or a slave. + */ +#define XIIC_MASTER_ROLE     1 +#define XIIC_SLAVE_ROLE	     0 + +/**************************** Type Definitions ******************************/ + + +/***************** Macros (Inline Functions) Definitions ********************/ + + +/************************** Function Prototypes *****************************/ + +unsigned XIic_Recv(u32 BaseAddress, u8 Address, +		   u8 *BufferPtr, unsigned ByteCount); + +unsigned XIic_Send(u32 BaseAddress, u8 Address, +		   u8 *BufferPtr, unsigned ByteCount); + +#endif		  /* end of protection macro */ diff --git a/cpu/ppc4xx/440gx_enet.c b/cpu/ppc4xx/440gx_enet.c index 54b25a56c..1fa84be6e 100644 --- a/cpu/ppc4xx/440gx_enet.c +++ b/cpu/ppc4xx/440gx_enet.c @@ -167,8 +167,6 @@ static void ppc_440x_eth_halt (struct eth_device *dev)  	/* EMAC RESET */  	out32 (EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST); -	hw_p->print_speed = 1;	/* print speed message again next time */ -  	return;  } @@ -241,11 +239,9 @@ int ppc_440x_eth_setup_bridge(int devnum, bd_t * bis)  		zmiifer |= ZMII_FER_SMII << ZMII_FER_V (0);  		zmiifer |= ZMII_FER_SMII << ZMII_FER_V (1);  		rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(2); -		rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(3);  		bis->bi_phymode[0] = BI_PHYMODE_ZMII;  		bis->bi_phymode[1] = BI_PHYMODE_ZMII;  		bis->bi_phymode[2] = BI_PHYMODE_RGMII; -		bis->bi_phymode[3] = BI_PHYMODE_RGMII;  		break;  	case 0:  	default: @@ -426,8 +422,12 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)  	bis->bi_phynum[devnum] = reg; -	/* Reset the phy */ -	miiphy_reset (reg); +	/* +	 * Reset the phy, only if its the first time through +	 * otherwise, just check the speeds & feeds +	 */ +	if (hw_p->first_init == 0) { +		miiphy_reset (reg);  #if defined(CONFIG_440_GX)  #if defined(CONFIG_CIS8201_PHY) @@ -456,9 +456,10 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)  	}  #endif  #endif -	/* Start/Restart autonegotiation */ -	phy_setup_aneg (reg); -	udelay (1000); +		/* Start/Restart autonegotiation */ +		phy_setup_aneg (reg); +		udelay (1000); +	}  	miiphy_read (reg, PHY_BMSR, ®_short); @@ -1167,6 +1168,10 @@ int ppc_440x_eth_initialize (bd_t * bis)  	bis->bi_phymode[2] = 2;  	bis->bi_phymode[3] = 2; +#if defined (CONFIG_440_GX) +	ppc_440x_eth_setup_bridge(0, bis); +#endif +  	for (eth_num = 0; eth_num < EMAC_NUM_DEV; eth_num++) {  		/* See if we can actually bring up the interface, otherwise, skip it */ diff --git a/include/configs/ml300.h b/include/configs/ml300.h index d93925ee6..bcd5c17c5 100644 --- a/include/configs/ml300.h +++ b/include/configs/ml300.h @@ -38,7 +38,7 @@   *     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.,   *     675 Mass Ave, Cambridge, MA 02139, USA. -  * + *   */  #ifndef __CONFIG_H @@ -56,9 +56,21 @@  #define CONFIG_4xx		1	/* ...member of PPC4xx family	*/  #define CONFIG_XILINX_ML300	1	/* ...on a Xilinx ML300 board	*/ -#define CFG_ENV_IS_NOWHERE	1	/* environment is in RAM */ +#define CFG_ENV_IS_IN_EEPROM	1	/* environment is in EEPROM */ + +/* following are used only if env is in EEPROM */ +#ifdef	CFG_ENV_IS_IN_EEPROM +#define CFG_I2C_EEPROM_ADDR	XPAR_PERSISTENT_0_IIC_0_EEPROMADDR +#define CFG_I2C_EEPROM_ADDR_LEN 1 +#define CFG_ENV_OFFSET		XPAR_PERSISTENT_0_IIC_0_BASEADDR +#define CONFIG_MISC_INIT_R	1	/* used to call out convert_env() */ +#define CONFIG_ENV_OVERWRITE	1	/* allow users to update ethaddr and serial# */ +#endif + +#include "../board/xilinx/ml300/xparameters.h" +  #define CFG_NO_FLASH		1	/* no flash */ -#define CFG_ENV_SIZE		0x2000 +#define CFG_ENV_SIZE		XPAR_PERSISTENT_0_IIC_0_HIGHADDR - XPAR_PERSISTENT_0_IIC_0_BASEADDR + 1  #define CONFIG_BAUDRATE		9600  #define CONFIG_BOOTDELAY	3	/* autoboot after 3 seconds	*/ |