From a06752e36be7fc74b4a928026b63b1bf1764497e Mon Sep 17 00:00:00 2001 From: wdenk Date: Wed, 29 Sep 2004 22:43:59 +0000 Subject: [PATCH] * 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. --- CHANGELOG | 17 + board/xilinx/common/xipif_v1_23_b.c | 331 +++++++++++ board/xilinx/common/xipif_v1_23_b.h | 53 +- board/xilinx/ml300/Makefile | 13 +- board/xilinx/ml300/ml300.c | 31 +- .../sw_services/uboot_v1_00_a/data/Ltypes | 72 ++- .../uboot_v1_00_a/data/uboot_v2_1_0.mld | 8 +- .../uboot_v1_00_a/data/uboot_v2_1_0.tcl | 29 +- board/xilinx/ml300/xparameters.h | 110 ++-- board/xilinx/xilinx_enet/emac_adapter.c | 9 +- board/xilinx/xilinx_iic/iic_adapter.c | 529 ++++++++++++++++++ board/xilinx/xilinx_iic/xiic_l.c | 484 ++++++++++++++++ board/xilinx/xilinx_iic/xiic_l.h | 150 +++++ cpu/ppc4xx/440gx_enet.c | 23 +- include/configs/ml300.h | 18 +- 15 files changed, 1719 insertions(+), 158 deletions(-) create mode 100644 board/xilinx/common/xipif_v1_23_b.c create mode 100644 board/xilinx/xilinx_iic/iic_adapter.c create mode 100644 board/xilinx/xilinx_iic/xiic_l.c create mode 100644 board/xilinx/xilinx_iic/xiic_l.h diff --git a/CHANGELOG b/CHANGELOG index d9aed9eaef..788ea84b22 100644 --- 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 index 0000000000..c7311ab9be --- /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 b1520e921e..3ce1fffba5 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 d9007c0251..880c494c99 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 dbe8a8ac74..f335fc1ba6 100644 --- a/board/xilinx/ml300/ml300.c +++ b/board/xilinx/ml300/ml300.c @@ -42,6 +42,10 @@ #include #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 319b925d36..9daf147096 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///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"//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 ' "${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 ' \ + "${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 e1aa7fd59d..516924126d 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 8d939b4162..9d44f4493d 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 c6362562b5..2c56737dc5 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 a3c37baab9..bf8cf0bccb 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 0000000000..8ddba6ade2 --- /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 +#include +#include +#include +#include "xparameters.h" + +#ifdef CFG_ENV_IS_IN_EEPROM +#include +#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 0000000000..6b7816373e --- /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. +* +*
+* 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
+* 
+* +****************************************************************************/ + +/***************************** 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 0000000000..a2c4c496a9 --- /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. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver	Who  Date     Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00b jhl  05/07/02 First release
+* 1.01c ecm  12/05/02 new rev
+* 
+* +*****************************************************************************/ + +#ifndef XIIC_L_H /* prevent circular inclusions */ +#define XIIC_L_H /* by using protection macros */ + +/***************************** Include Files ********************************/ + +#include "xbasic_types.h" + +/************************** Constant Definitions ****************************/ + +#define XIIC_MSB_OFFSET 3 + +#define XIIC_REG_OFFSET 0x100 + XIIC_MSB_OFFSET + +/* + * Register offsets in bytes from RegisterBase. Three is added to the + * base offset to access LSB (IBM style) of the word + */ +#define XIIC_CR_REG_OFFSET 0x00+XIIC_REG_OFFSET /* Control Register */ +#define XIIC_SR_REG_OFFSET 0x04+XIIC_REG_OFFSET /* Status Register */ +#define XIIC_DTR_REG_OFFSET 0x08+XIIC_REG_OFFSET /* Data Tx Register */ +#define XIIC_DRR_REG_OFFSET 0x0C+XIIC_REG_OFFSET /* Data Rx Register */ +#define XIIC_ADR_REG_OFFSET 0x10+XIIC_REG_OFFSET /* Address Register */ +#define XIIC_TFO_REG_OFFSET 0x14+XIIC_REG_OFFSET /* Tx FIFO Occupancy */ +#define XIIC_RFO_REG_OFFSET 0x18+XIIC_REG_OFFSET /* Rx FIFO Occupancy */ +#define XIIC_TBA_REG_OFFSET 0x1C+XIIC_REG_OFFSET /* 10 Bit Address reg */ +#define XIIC_RFD_REG_OFFSET 0x20+XIIC_REG_OFFSET /* Rx FIFO Depth reg */ + +/* Control Register masks */ + +#define XIIC_CR_ENABLE_DEVICE_MASK 0x01 /* Device enable = 1 */ +#define XIIC_CR_TX_FIFO_RESET_MASK 0x02 /* Transmit FIFO reset=1 */ +#define XIIC_CR_MSMS_MASK 0x04 /* Master starts Txing=1 */ +#define XIIC_CR_DIR_IS_TX_MASK 0x08 /* Dir of tx. Txing=1 */ +#define XIIC_CR_NO_ACK_MASK 0x10 /* Tx Ack. NO ack = 1 */ +#define XIIC_CR_REPEATED_START_MASK 0x20 /* Repeated start = 1 */ +#define XIIC_CR_GENERAL_CALL_MASK 0x40 /* Gen Call enabled = 1 */ + +/* Status Register masks */ + +#define XIIC_SR_GEN_CALL_MASK 0x01 /* 1=a mstr issued a GC */ +#define XIIC_SR_ADDR_AS_SLAVE_MASK 0x02 /* 1=when addr as slave */ +#define XIIC_SR_BUS_BUSY_MASK 0x04 /* 1 = bus is busy */ +#define XIIC_SR_MSTR_RDING_SLAVE_MASK 0x08 /* 1=Dir: mstr <-- slave */ +#define XIIC_SR_TX_FIFO_FULL_MASK 0x10 /* 1 = Tx FIFO full */ +#define XIIC_SR_RX_FIFO_FULL_MASK 0x20 /* 1 = Rx FIFO full */ +#define XIIC_SR_RX_FIFO_EMPTY_MASK 0x40 /* 1 = Rx FIFO empty */ + +/* IPIF Interrupt Status Register masks Interrupt occurs when... */ + +#define XIIC_INTR_ARB_LOST_MASK 0x01 /* 1 = arbitration lost */ +#define XIIC_INTR_TX_ERROR_MASK 0x02 /* 1=Tx error/msg complete*/ +#define XIIC_INTR_TX_EMPTY_MASK 0x04 /* 1 = Tx FIFO/reg empty */ +#define XIIC_INTR_RX_FULL_MASK 0x08 /* 1=Rx FIFO/reg=OCY level*/ +#define XIIC_INTR_BNB_MASK 0x10 /* 1 = Bus not busy */ +#define XIIC_INTR_AAS_MASK 0x20 /* 1 = when addr as slave */ +#define XIIC_INTR_NAAS_MASK 0x40 /* 1 = not addr as slave */ +#define XIIC_INTR_TX_HALF_MASK 0x80 /* 1 = TX FIFO half empty */ + +/* IPIF Device Interrupt Register masks */ + +#define XIIC_IPIF_IIC_MASK 0x00000004UL /* 1=inter enabled */ +#define XIIC_IPIF_ERROR_MASK 0x00000001UL /* 1=inter enabled */ +#define XIIC_IPIF_INTER_ENABLE_MASK (XIIC_IPIF_IIC_MASK | \ + XIIC_IPIF_ERROR_MASK) + +#define XIIC_TX_ADDR_SENT 0x00 +#define XIIC_TX_ADDR_MSTR_RECV_MASK 0x02 + +/* The following constants specify the depth of the FIFOs */ + +#define IIC_RX_FIFO_DEPTH 16 /* Rx fifo capacity */ +#define IIC_TX_FIFO_DEPTH 16 /* Tx fifo capacity */ + +/* The following constants specify groups of interrupts that are typically + * enabled or disables at the same time + */ +#define XIIC_TX_INTERRUPTS \ + (XIIC_INTR_TX_ERROR_MASK | XIIC_INTR_TX_EMPTY_MASK | \ + XIIC_INTR_TX_HALF_MASK) + +#define XIIC_TX_RX_INTERRUPTS (XIIC_INTR_RX_FULL_MASK | XIIC_TX_INTERRUPTS) + +/* The following constants are used with the following macros to specify the + * operation, a read or write operation. + */ +#define XIIC_READ_OPERATION 1 +#define XIIC_WRITE_OPERATION 0 + +/* The following constants are used with the transmit FIFO fill function to + * specify the role which the IIC device is acting as, a master or a slave. + */ +#define XIIC_MASTER_ROLE 1 +#define XIIC_SLAVE_ROLE 0 + +/**************************** Type Definitions ******************************/ + + +/***************** Macros (Inline Functions) Definitions ********************/ + + +/************************** Function Prototypes *****************************/ + +unsigned XIic_Recv(u32 BaseAddress, u8 Address, + u8 *BufferPtr, unsigned ByteCount); + +unsigned XIic_Send(u32 BaseAddress, u8 Address, + u8 *BufferPtr, unsigned ByteCount); + +#endif /* end of protection macro */ diff --git a/cpu/ppc4xx/440gx_enet.c b/cpu/ppc4xx/440gx_enet.c index 54b25a56c5..1fa84be6e5 100644 --- a/cpu/ppc4xx/440gx_enet.c +++ b/cpu/ppc4xx/440gx_enet.c @@ -167,8 +167,6 @@ static void ppc_440x_eth_halt (struct eth_device *dev) /* EMAC RESET */ out32 (EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST); - hw_p->print_speed = 1; /* print speed message again next time */ - return; } @@ -241,11 +239,9 @@ int ppc_440x_eth_setup_bridge(int devnum, bd_t * bis) zmiifer |= ZMII_FER_SMII << ZMII_FER_V (0); zmiifer |= ZMII_FER_SMII << ZMII_FER_V (1); rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(2); - rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(3); bis->bi_phymode[0] = BI_PHYMODE_ZMII; bis->bi_phymode[1] = BI_PHYMODE_ZMII; bis->bi_phymode[2] = BI_PHYMODE_RGMII; - bis->bi_phymode[3] = BI_PHYMODE_RGMII; break; case 0: default: @@ -426,8 +422,12 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis) bis->bi_phynum[devnum] = reg; - /* Reset the phy */ - miiphy_reset (reg); + /* + * Reset the phy, only if its the first time through + * otherwise, just check the speeds & feeds + */ + if (hw_p->first_init == 0) { + miiphy_reset (reg); #if defined(CONFIG_440_GX) #if defined(CONFIG_CIS8201_PHY) @@ -456,9 +456,10 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis) } #endif #endif - /* Start/Restart autonegotiation */ - phy_setup_aneg (reg); - udelay (1000); + /* Start/Restart autonegotiation */ + phy_setup_aneg (reg); + udelay (1000); + } miiphy_read (reg, PHY_BMSR, ®_short); @@ -1167,6 +1168,10 @@ int ppc_440x_eth_initialize (bd_t * bis) bis->bi_phymode[2] = 2; bis->bi_phymode[3] = 2; +#if defined (CONFIG_440_GX) + ppc_440x_eth_setup_bridge(0, bis); +#endif + for (eth_num = 0; eth_num < EMAC_NUM_DEV; eth_num++) { /* See if we can actually bring up the interface, otherwise, skip it */ diff --git a/include/configs/ml300.h b/include/configs/ml300.h index d93925ee66..bcd5c17c5b 100644 --- a/include/configs/ml300.h +++ b/include/configs/ml300.h @@ -38,7 +38,7 @@ * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. - * + * */ #ifndef __CONFIG_H @@ -56,9 +56,21 @@ #define CONFIG_4xx 1 /* ...member of PPC4xx family */ #define CONFIG_XILINX_ML300 1 /* ...on a Xilinx ML300 board */ -#define CFG_ENV_IS_NOWHERE 1 /* environment is in RAM */ +#define CFG_ENV_IS_IN_EEPROM 1 /* environment is in EEPROM */ + +/* following are used only if env is in EEPROM */ +#ifdef CFG_ENV_IS_IN_EEPROM +#define CFG_I2C_EEPROM_ADDR XPAR_PERSISTENT_0_IIC_0_EEPROMADDR +#define CFG_I2C_EEPROM_ADDR_LEN 1 +#define CFG_ENV_OFFSET XPAR_PERSISTENT_0_IIC_0_BASEADDR +#define CONFIG_MISC_INIT_R 1 /* used to call out convert_env() */ +#define CONFIG_ENV_OVERWRITE 1 /* allow users to update ethaddr and serial# */ +#endif + +#include "../board/xilinx/ml300/xparameters.h" + #define CFG_NO_FLASH 1 /* no flash */ -#define CFG_ENV_SIZE 0x2000 +#define CFG_ENV_SIZE XPAR_PERSISTENT_0_IIC_0_HIGHADDR - XPAR_PERSISTENT_0_IIC_0_BASEADDR + 1 #define CONFIG_BAUDRATE 9600 #define CONFIG_BOOTDELAY 3 /* autoboot after 3 seconds */ -- 2.25.1