* Patch by Sean Chang, 9 Aug 2004:
authorwdenk <wdenk>
Wed, 29 Sep 2004 22:43:59 +0000 (22:43 +0000)
committerwdenk <wdenk>
Wed, 29 Sep 2004 22:43:59 +0000 (22:43 +0000)
  - 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.

15 files changed:
CHANGELOG
board/xilinx/common/xipif_v1_23_b.c [new file with mode: 0644]
board/xilinx/common/xipif_v1_23_b.h
board/xilinx/ml300/Makefile
board/xilinx/ml300/ml300.c
board/xilinx/ml300/sw_services/uboot_v1_00_a/data/Ltypes
board/xilinx/ml300/sw_services/uboot_v1_00_a/data/uboot_v2_1_0.mld
board/xilinx/ml300/sw_services/uboot_v1_00_a/data/uboot_v2_1_0.tcl
board/xilinx/ml300/xparameters.h
board/xilinx/xilinx_enet/emac_adapter.c
board/xilinx/xilinx_iic/iic_adapter.c [new file with mode: 0644]
board/xilinx/xilinx_iic/xiic_l.c [new file with mode: 0644]
board/xilinx/xilinx_iic/xiic_l.h [new file with mode: 0644]
cpu/ppc4xx/440gx_enet.c
include/configs/ml300.h

index d9aed9eaef48b8aecded9ff29c6cb5d1237db35e..788ea84b22015b56daf7257ae9a10c44899c13a1 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -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 (file)
index 0000000..c7311ab
--- /dev/null
@@ -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;
+}
index b1520e921e22bfcd128fb3c6b9c89bb918efcaa7..3ce1fffba5f7a8ee8caf064264f291022804681b 100644 (file)
@@ -1,39 +1,22 @@
+/* $Id: xipif_v1_23_b.h,v 1.1 2002/03/18 23:24:52 linnj Exp $ */
 /******************************************************************************
 *
-*     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.
+*      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.
 *
 ******************************************************************************/
 /******************************************************************************
 *
 * RETURN VALUE:
 *
-* TRUE if interrupts are enabled for the IPIF, FALSE otherwise.
+* XTRUE if interrupts are enabled for the IPIF, XFALSE otherwise.
 *
 * NOTES:
 *
index d9007c02519eca50c9cfaea0b7aae1c353a3e2c3..880c494c99f1bb940ce1acf2a31bf0536f9b2852 100644 (file)
 # 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
 
index dbe8a8ac749e95633e990a4caee82aa1b1528268..f335fc1ba6dfcaf10263070afd84f504cd5a3c29 100644 (file)
 #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
index 319b925d36a29904ef9c3c0420d341e0d4bff79f..9daf14709613e367a6ec9b3df25f1d5c5844c912 100644 (file)
@@ -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
index e1aa7fd59d7f5f89ec23f5c2e46e873df121edc4..516924126d0e40b96847767a5bd0da6bf137db33 100644 (file)
@@ -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
index 8d939b4162ffa096c189e18644e85f6882681bf4..9d44f4493dad292850fc921db7fa0eb583f64bf4 100644 (file)
@@ -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]
index c6362562b540cd6460553eadf3101703360ba22e..2c56737dc5f53de17461c22655520ae3248e2901 100644 (file)
@@ -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
 
 /******************************************************************/
 
-#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
-
-/******************************************************************/
index a3c37baab9cc3ee7ec2eced44ca36fb0bb2e9b45..bf8cf0bccb4a98f7579661a2d05fa2d31f030a33 100644 (file)
 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 (file)
index 0000000..8ddba6a
--- /dev/null
@@ -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 (file)
index 0000000..6b78163
--- /dev/null
@@ -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 (file)
index 0000000..a2c4c49
--- /dev/null
@@ -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 */
index 54b25a56c521dcca31ec933b0d13c5e2a02a5498..1fa84be6e5f2cd11d91a00261d05b089d412e0d2 100644 (file)
@@ -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, &reg_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 */
index d93925ee66ce130a19ce1447d4904cb4db6f55ae..bcd5c17c5b3f7f9adf2b0f40eab8aa44408b34b8 100644 (file)
@@ -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
 #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     */