summaryrefslogtreecommitdiff
path: root/board
diff options
context:
space:
mode:
authorwdenk <wdenk>2004-09-29 22:43:59 +0000
committerwdenk <wdenk>2004-09-29 22:43:59 +0000
commita06752e36be7fc74b4a928026b63b1bf1764497e (patch)
treeb71ddbcee4e4cc03e8ea98738b605a1c3879a703 /board
parentda93ed8147a000505ac7b7ed4e2fb50532596a3c (diff)
downloadu-boot-imx-a06752e36be7fc74b4a928026b63b1bf1764497e.zip
u-boot-imx-a06752e36be7fc74b4a928026b63b1bf1764497e.tar.gz
u-boot-imx-a06752e36be7fc74b4a928026b63b1bf1764497e.tar.bz2
* 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.
Diffstat (limited to 'board')
-rw-r--r--board/xilinx/common/xipif_v1_23_b.c331
-rw-r--r--board/xilinx/common/xipif_v1_23_b.h53
-rw-r--r--board/xilinx/ml300/Makefile13
-rw-r--r--board/xilinx/ml300/ml300.c31
-rw-r--r--board/xilinx/ml300/sw_services/uboot_v1_00_a/data/Ltypes72
-rw-r--r--board/xilinx/ml300/sw_services/uboot_v1_00_a/data/uboot_v2_1_0.mld8
-rw-r--r--board/xilinx/ml300/sw_services/uboot_v1_00_a/data/uboot_v2_1_0.tcl29
-rw-r--r--board/xilinx/ml300/xparameters.h110
-rw-r--r--board/xilinx/xilinx_enet/emac_adapter.c9
-rw-r--r--board/xilinx/xilinx_iic/iic_adapter.c529
-rw-r--r--board/xilinx/xilinx_iic/xiic_l.c484
-rw-r--r--board/xilinx/xilinx_iic/xiic_l.h150
12 files changed, 1673 insertions, 146 deletions
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 0000000..c7311ab
--- /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 b1520e9..3ce1fff 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.
-*
-*
-* 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.
*
******************************************************************************/
/******************************************************************************
@@ -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 d9007c0..880c494 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 dbe8a8a..f335fc1 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 319b925..9daf147 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 e1aa7fd..5169241 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 8d939b4..9d44f44 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 c636256..2c56737 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 a3c37ba..bf8cf0b 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 0000000..8ddba6a
--- /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 0000000..6b78163
--- /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 0000000..a2c4c49
--- /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 */