提交 a06752e3 编写于 作者: W wdenk

* 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.
上级 da93ed81
......@@ -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
......
/* $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;
}
/* $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:
*
......
......@@ -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
......
......@@ -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
#!/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
......@@ -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
......@@ -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]
......
/*******************************************************************
*
* 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
/******************************************************************/
......@@ -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;
}
......
/******************************************************************************
*
* 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
/* $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;
}
/* $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 */
......@@ -167,8 +167,6 @@ static void ppc_440x_eth_halt (struct eth_device *dev)
/* EMAC RESET */
out32 (EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST);
hw_p->print_speed = 1; /* print speed message again next time */
return;
}
......@@ -241,11 +239,9 @@ int ppc_440x_eth_setup_bridge(int devnum, bd_t * bis)
zmiifer |= ZMII_FER_SMII << ZMII_FER_V (0);
zmiifer |= ZMII_FER_SMII << ZMII_FER_V (1);
rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(2);
rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(3);
bis->bi_phymode[0] = BI_PHYMODE_ZMII;
bis->bi_phymode[1] = BI_PHYMODE_ZMII;
bis->bi_phymode[2] = BI_PHYMODE_RGMII;
bis->bi_phymode[3] = BI_PHYMODE_RGMII;
break;
case 0:
default:
......@@ -426,8 +422,12 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
bis->bi_phynum[devnum] = reg;
/* Reset the phy */
miiphy_reset (reg);
/*
* Reset the phy, only if its the first time through
* otherwise, just check the speeds & feeds
*/
if (hw_p->first_init == 0) {
miiphy_reset (reg);
#if defined(CONFIG_440_GX)
#if defined(CONFIG_CIS8201_PHY)
......@@ -456,9 +456,10 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
}
#endif
#endif
/* Start/Restart autonegotiation */
phy_setup_aneg (reg);
udelay (1000);
/* Start/Restart autonegotiation */
phy_setup_aneg (reg);
udelay (1000);
}
miiphy_read (reg, PHY_BMSR, &reg_short);
......@@ -1167,6 +1168,10 @@ int ppc_440x_eth_initialize (bd_t * bis)
bis->bi_phymode[2] = 2;
bis->bi_phymode[3] = 2;
#if defined (CONFIG_440_GX)
ppc_440x_eth_setup_bridge(0, bis);
#endif
for (eth_num = 0; eth_num < EMAC_NUM_DEV; eth_num++) {
/* See if we can actually bring up the interface, otherwise, skip it */
......
......@@ -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 */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册