diff options
| author | wdenk <wdenk> | 2004-02-23 23:54:43 +0000 | 
|---|---|---|
| committer | wdenk <wdenk> | 2004-02-23 23:54:43 +0000 | 
| commit | 028ab6b598b628326116acd88e0f35aa9f526d12 (patch) | |
| tree | 0d54315bd92d713a405004b6e36fca8d2b7c53e3 | |
| parent | 63e73c9a8ed5b32d9c4067ffaad953e9a8fe8f0a (diff) | |
| download | olio-uboot-2014.01-028ab6b598b628326116acd88e0f35aa9f526d12.tar.xz olio-uboot-2014.01-028ab6b598b628326116acd88e0f35aa9f526d12.zip | |
* Patch by Peter Ryser, 20 Feb 2004:
  Add support for the Xilinx ML300 platform
* Patch by Stephan Linz, 17 Feb 2004:
  Fix watchdog support for NIOS
* Patch by Josh Fryman, 16 Feb 2004:
  Fix byte-swapping for cfi_flash.c for different bus widths
* Patch by Jon Diekema, 14 Jeb 2004:
  Remove duplicate "FPGA Support" notes from the README file
57 files changed, 12176 insertions, 170 deletions
| @@ -2,6 +2,18 @@  Changes for U-Boot 1.0.2:  ====================================================================== +* Patch by Peter Ryser, 20 Feb 2004: +  Add support for the Xilinx ML300 platform + +* Patch by Stephan Linz, 17 Feb 2004: +  Fix watchdog support for NIOS + +* Patch by Josh Fryman, 16 Feb 2004: +  Fix byte-swapping for cfi_flash.c for different bus widths + +* Patch by Jon Diekema, 14 Jeb 2004: +  Remove duplicate "FPGA Support" notes from the README file +  * Patches by Reinhard Meyer, 14 Feb 2004:    - update board/emk tree; use common flash driver    - Corrected tested bits in machine check exception in cpu/mpc5xxx/traps.c @@ -61,10 +61,10 @@ LIST_4xx="	\  	CPCI440		CPCIISER4	CRAYL1		csb272		\  	DASA_SIM	DP405		DU405		EBONY		\  	ERIC		EXBITGEN	HUB405		MIP405		\ -	MIP405T		ML2		OCRTC		ORSG		\ -	PCI405		PIP405		PLU405		PMC405		\ -	PPChameleonEVB	VOH405		W7OLMC		W7OLMG		\ -	WALNUT405	XPEDITE1K					\ +	MIP405T		ML2		ml300		OCRTC		\ +	ORSG		PCI405		PIP405		PLU405		\ +	PMC405		PPChameleonEVB	VOH405		W7OLMC		\ +	W7OLMG		WALNUT405	XPEDITE1K			\  "  ######################################################################### @@ -593,6 +593,9 @@ MIP405T_config:unconfig  ML2_config:unconfig  	@./mkconfig $(@:_config=) ppc ppc4xx ml2 +ml300_config:unconfig +	@./mkconfig $(@:_config=) ppc ppc4xx ml300 xilinx +  OCRTC_config		\  ORSG_config:	unconfig  	@./mkconfig $(@:_config=) ppc ppc4xx ocrtc esd @@ -1159,60 +1159,6 @@ The following options need to be configured:  		CONFIG_FPGA -		Used to specify the types of FPGA devices. For -		example, -		#define CONFIG_FPGA  CFG_XILINX_VIRTEX2 - -		CFG_FPGA_PROG_FEEDBACK - -		Enable printing of hash marks during FPGA -		configuration. - -		CFG_FPGA_CHECK_BUSY - -		Enable checks on FPGA configuration interface busy -		status by the configuration function. This option -		will require a board or device specific function to -		be written. - -		CONFIG_FPGA_DELAY - -		If defined, a function that provides delays in the -		FPGA configuration driver. - -		CFG_FPGA_CHECK_CTRLC - -		Allow Control-C to interrupt FPGA configuration - -		CFG_FPGA_CHECK_ERROR - -		Check for configuration errors during FPGA bitfile -		loading. For example, abort during Virtex II -		configuration if the INIT_B line goes low (which -		indicated a CRC error). - -		CFG_FPGA_WAIT_INIT - -		Maximum time to wait for the INIT_B line to deassert -		after PROB_B has been deasserted during a Virtex II -		FPGA configuration sequence. The default time is 500 mS. - -		CFG_FPGA_WAIT_BUSY - -		Maximum time to wait for BUSY to deassert during -		Virtex II FPGA configuration. The default is 5 mS. - -		CFG_FPGA_WAIT_CONFIG - -		Time to wait after FPGA configuration. The default is -		200 mS. - -- FPGA Support: CONFIG_FPGA_COUNT - -		Specify the number of FPGA devices to support. - -		CONFIG_FPGA -  		Used to specify the types of FPGA devices.  For example,  		#define CONFIG_FPGA  CFG_XILINX_VIRTEX2 diff --git a/board/emk/top860/top860.c b/board/emk/top860/top860.c index 931c0d1b6..84afaaa2b 100644 --- a/board/emk/top860/top860.c +++ b/board/emk/top860/top860.c @@ -145,4 +145,3 @@ int misc_init_r (void)  	return (0);  } - diff --git a/board/omap1610inn/omap1610innovator.c b/board/omap1610inn/omap1610innovator.c index 0f67a0c59..521eee34c 100644 --- a/board/omap1610inn/omap1610innovator.c +++ b/board/omap1610inn/omap1610innovator.c @@ -11,7 +11,7 @@   * Kshitij Gupta <Kshitij@ti.com>   *   * Modified for OMAP 1610 H2 board by Nishant Kamat, Jan 2004 - *  + *   * See file CREDITS for list of people who contributed to this   * project.   * @@ -112,9 +112,9 @@ void ether__init (void)  #ifdef CONFIG_H2_OMAP1610  	#define LAN_RESET_REGISTER 0x0400001c -	/* The debug board on which the lan chip resides may not be powered  -	 * ON at the same time as the OMAP chip. So wait in a loop until the  -	 * lan reset register (on the debug board) is available (powered on)  +	/* The debug board on which the lan chip resides may not be powered +	 * ON at the same time as the OMAP chip. So wait in a loop until the +	 * lan reset register (on the debug board) is available (powered on)  	 * and reset the lan chip.  	 */ @@ -123,7 +123,7 @@ void ether__init (void)  		*((volatile unsigned short *) LAN_RESET_REGISTER) = 0x0001;  		udelay (3);  	} while (*((volatile unsigned short *) LAN_RESET_REGISTER) != 0x0001); -	 +  	do {  		*((volatile unsigned short *) LAN_RESET_REGISTER) = 0x0000;  		udelay (3); diff --git a/board/omap1610inn/platform.S b/board/omap1610inn/platform.S index 17756953e..4d6224ccc 100644 --- a/board/omap1610inn/platform.S +++ b/board/omap1610inn/platform.S @@ -6,7 +6,7 @@   * Kshitij Gupta <Kshitij@ti.com>   *   * Modified for OMAP 1610 H2 board by Nishant Kamat, Jan 2004 - *  + *   * See file CREDITS for list of people who contributed to this   * project.   * @@ -251,7 +251,7 @@ common_tc:  	ldr	r0,	REG_TC_EMIFS_CS3_CONFIG  	str	r1,	[r0] /* Chip Select 3 */ -#ifdef CONFIG_H2_OMAP1610	 +#ifdef CONFIG_H2_OMAP1610  	/* inserting additional 2 clock cycle hold time for LAN */  	ldr     r0,     REG_TC_EMIFS_CS1_ADVANCED  	ldr    	r1,     VAL_TC_EMIFS_CS1_ADVANCED diff --git a/board/xilinx/common/xbasic_types.c b/board/xilinx/common/xbasic_types.c new file mode 100644 index 000000000..c3a171a35 --- /dev/null +++ b/board/xilinx/common/xbasic_types.c @@ -0,0 +1,165 @@ +/****************************************************************************** +* +*     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. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xbasic_types.c +* +* This file contains basic functions for Xilinx software IP. +* +* <pre> +* MODIFICATION HISTORY: +* +* Ver   Who    Date   Changes +* ----- ---- -------- ------------------------------------------------------- +* 1.00a rpm  11/07/03 Added XNullHandler function as a stub interrupt handler +* </pre> +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xbasic_types.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + +/** + * This variable allows testing to be done easier with asserts. An assert + * sets this variable such that a driver can evaluate this variable + * to determine if an assert occurred. + */ +unsigned int XAssertStatus; + +/** + * This variable allows the assert functionality to be changed for testing + * such that it does not wait infinitely. Use the debugger to disable the + * waiting during testing of asserts. + */ +u32 XWaitInAssert = TRUE; + +/* The callback function to be invoked when an assert is taken */ +static XAssertCallback XAssertCallbackRoutine = (XAssertCallback) NULL; + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* +* Implements assert. Currently, it calls a user-defined callback function +* if one has been set.  Then, it potentially enters an infinite loop depending +* on the value of the XWaitInAssert variable. +* +* @param    File is the name of the filename of the source +* @param    Line is the linenumber within File +* +* @return +* +* None. +* +* @note +* +* None. +* +******************************************************************************/ +void +XAssert(char *File, int Line) +{ +	/* if the callback has been set then invoke it */ +	if (XAssertCallbackRoutine != NULL) { +		(*XAssertCallbackRoutine) (File, Line); +	} + +	/* if specified, wait indefinitely such that the assert will show up +	 * in testing +	 */ +	while (XWaitInAssert) { +	} +} + +/*****************************************************************************/ +/** +* +* Sets up a callback function to be invoked when an assert occurs. If there +* was already a callback installed, then it is replaced. +* +* @param    Routine is the callback to be invoked when an assert is taken +* +* @return +* +* None. +* +* @note +* +* This function has no effect if NDEBUG is set +* +******************************************************************************/ +void +XAssertSetCallback(XAssertCallback Routine) +{ +	XAssertCallbackRoutine = Routine; +} + +/*****************************************************************************/ +/** +* +* Null handler function. This follows the XInterruptHandler signature for +* interrupt handlers. It can be used to assign a null handler (a stub) to an +* interrupt controller vector table. +* +* @param    NullParameter is an arbitrary void pointer and not used. +* +* @return +* +* None. +* +* @note +* +* None. +* +******************************************************************************/ +void +XNullHandler(void *NullParameter) +{ +} diff --git a/board/xilinx/common/xbasic_types.h b/board/xilinx/common/xbasic_types.h new file mode 100644 index 000000000..ef0b7c255 --- /dev/null +++ b/board/xilinx/common/xbasic_types.h @@ -0,0 +1,283 @@ +/****************************************************************************** +* +*     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. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xbasic_types.h +* +* This file contains basic types for Xilinx software IP.  These types do not +* follow the standard naming convention with respect to using the component +* name in front of each name because they are considered to be primitives. +* +* @note +* +* This file contains items which are architecture dependent. +* +* <pre> +* MODIFICATION HISTORY: +* +* Ver	Who    Date   Changes +* ----- ---- -------- ------------------------------------------------------- +* 1.00a rmm  12/14/01 First release +*	rmm  05/09/03 Added "xassert always" macros to rid ourselves of diab +*		      compiler warnings +* 1.00a rpm  11/07/03 Added XNullHandler function as a stub interrupt handler +* </pre> +* +******************************************************************************/ + +#ifndef XBASIC_TYPES_H		/* prevent circular inclusions */ +#define XBASIC_TYPES_H		/* by using protection macros */ + +/***************************** Include Files *********************************/ + +/************************** Constant Definitions *****************************/ + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef NULL +#define NULL 0 +#endif +/** Null */ + +#define XCOMPONENT_IS_READY	0x11111111	/* component has been initialized */ +#define XCOMPONENT_IS_STARTED	0x22222222	/* component has been started */ + +/* the following constants and declarations are for unit test purposes and are + * designed to be used in test applications. + */ +#define XTEST_PASSED	0 +#define XTEST_FAILED	1 + +#define XASSERT_NONE	 0 +#define XASSERT_OCCURRED 1 + +extern unsigned int XAssertStatus; +extern void XAssert(char *, int); + +/**************************** Type Definitions *******************************/ + +/** @name Primitive types + * These primitive types are created for transportability. + * They are dependent upon the target architecture. + * @{ + */ +#include <linux/types.h> + +typedef struct { +	u32 Upper; +	u32 Lower; +} Xuint64; + +/*@}*/ + +/** + * This data type defines an interrupt handler for a device. + * The argument points to the instance of the component + */ +typedef void (*XInterruptHandler) (void *InstancePtr); + +/** + * This data type defines a callback to be invoked when an + * assert occurs. The callback is invoked only when asserts are enabled + */ +typedef void (*XAssertCallback) (char *FilenamePtr, int LineNumber); + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** +* Return the most significant half of the 64 bit data type. +* +* @param x is the 64 bit word. +* +* @return +* +* The upper 32 bits of the 64 bit word. +* +* @note +* +* None. +* +******************************************************************************/ +#define XUINT64_MSW(x) ((x).Upper) + +/*****************************************************************************/ +/** +* Return the least significant half of the 64 bit data type. +* +* @param x is the 64 bit word. +* +* @return +* +* The lower 32 bits of the 64 bit word. +* +* @note +* +* None. +* +******************************************************************************/ +#define XUINT64_LSW(x) ((x).Lower) + +#ifndef NDEBUG + +/*****************************************************************************/ +/** +* This assert macro is to be used for functions that do not return anything +* (void). This in conjunction with the XWaitInAssert boolean can be used to +* accomodate tests so that asserts which fail allow execution to continue. +* +* @param expression is the expression to evaluate. If it evaluates to false, +*	 the assert occurs. +* +* @return +* +* Returns void unless the XWaitInAssert variable is true, in which case +* no return is made and an infinite loop is entered. +* +* @note +* +* None. +* +******************************************************************************/ +#define XASSERT_VOID(expression)			\ +{							\ +	if (expression) {				\ +		XAssertStatus = XASSERT_NONE;		\ +	} else {					\ +		XAssert(__FILE__, __LINE__);		\ +		XAssertStatus = XASSERT_OCCURRED;	\ +		return;					\ +	}						\ +} + +/*****************************************************************************/ +/** +* This assert macro is to be used for functions that do return a value. This in +* conjunction with the XWaitInAssert boolean can be used to accomodate tests so +* that asserts which fail allow execution to continue. +* +* @param expression is the expression to evaluate. If it evaluates to false, +*	 the assert occurs. +* +* @return +* +* Returns 0 unless the XWaitInAssert variable is true, in which case +* no return is made and an infinite loop is entered. +* +* @note +* +* None. +* +******************************************************************************/ +#define XASSERT_NONVOID(expression)		   \ +{						   \ +	if (expression) {			   \ +		XAssertStatus = XASSERT_NONE;	   \ +	} else {				   \ +		XAssert(__FILE__, __LINE__);	   \ +		XAssertStatus = XASSERT_OCCURRED;  \ +		return 0;			   \ +	}					   \ +} + +/*****************************************************************************/ +/** +* Always assert. This assert macro is to be used for functions that do not +* return anything (void). Use for instances where an assert should always +* occur. +* +* @return +* +* Returns void unless the XWaitInAssert variable is true, in which case +* no return is made and an infinite loop is entered. +* +* @note +* +* None. +* +******************************************************************************/ +#define XASSERT_VOID_ALWAYS()			   \ +{						   \ +	XAssert(__FILE__, __LINE__);		   \ +	XAssertStatus = XASSERT_OCCURRED;	   \ +	return;					   \ +} + +/*****************************************************************************/ +/** +* Always assert. This assert macro is to be used for functions that do return +* a value. Use for instances where an assert should always occur. +* +* @return +* +* Returns void unless the XWaitInAssert variable is true, in which case +* no return is made and an infinite loop is entered. +* +* @note +* +* None. +* +******************************************************************************/ +#define XASSERT_NONVOID_ALWAYS()		   \ +{						   \ +	XAssert(__FILE__, __LINE__);		   \ +	XAssertStatus = XASSERT_OCCURRED;	   \ +	return 0;				   \ +} + +#else + +#define XASSERT_VOID(expression) +#define XASSERT_VOID_ALWAYS() +#define XASSERT_NONVOID(expression) +#define XASSERT_NONVOID_ALWAYS() +#endif + +/************************** Function Prototypes ******************************/ + +void XAssertSetCallback(XAssertCallback Routine); +void XNullHandler(void *NullParameter); + +#endif	/* end of protection macro */ diff --git a/board/xilinx/common/xbuf_descriptor.h b/board/xilinx/common/xbuf_descriptor.h new file mode 100644 index 000000000..fdd51d58d --- /dev/null +++ b/board/xilinx/common/xbuf_descriptor.h @@ -0,0 +1,252 @@ +/****************************************************************************** +* +*     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. +* +* FILENAME: +* +* xbuf_descriptor.h +* +* DESCRIPTION: +* +* This file contains the interface for the XBufDescriptor component. +* The XBufDescriptor component is a passive component that only maps over +* a buffer descriptor data structure shared by the scatter gather DMA hardware +* and software. The component's primary purpose is to provide encapsulation of +* the buffer descriptor processing.  See the source file xbuf_descriptor.c for +* details. +* +* NOTES: +* +* Most of the functions of this component are implemented as macros in order +* to optimize the processing.  The names are not all uppercase such that they +* can be switched between macros and functions easily. +* +******************************************************************************/ + +#ifndef XBUF_DESCRIPTOR_H	/* prevent circular inclusions */ +#define XBUF_DESCRIPTOR_H	/* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xbasic_types.h" +#include "xdma_channel_i.h" + +/************************** Constant Definitions *****************************/ + +/* The following constants allow access to all fields of a buffer descriptor + * and are necessary at this level of visibility to allow macros to access + * and modify the fields of a buffer descriptor.  It is not expected that the + * user of a buffer descriptor would need to use these constants. + */ + +#define XBD_DEVICE_STATUS_OFFSET    0 +#define XBD_CONTROL_OFFSET	    1 +#define XBD_SOURCE_OFFSET	    2 +#define XBD_DESTINATION_OFFSET	    3 +#define XBD_LENGTH_OFFSET	    4 +#define XBD_STATUS_OFFSET	    5 +#define XBD_NEXT_PTR_OFFSET	    6 +#define XBD_ID_OFFSET		    7 +#define XBD_FLAGS_OFFSET	    8 +#define XBD_RQSTED_LENGTH_OFFSET    9 + +#define XBD_SIZE_IN_WORDS	    10 + +/* + * The following constants define the bits of the flags field of a buffer + * descriptor + */ + +#define XBD_FLAGS_LOCKED_MASK	    1UL + +/**************************** Type Definitions *******************************/ + +typedef u32 XBufDescriptor[XBD_SIZE_IN_WORDS]; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/* each of the following macros are named the same as functions rather than all + * upper case in order to allow either the macros or the functions to be + * used, see the source file xbuf_descriptor.c for documentation + */ + +#define XBufDescriptor_Initialize(InstancePtr)			\ +{								\ +    (*((u32 *)InstancePtr + XBD_CONTROL_OFFSET) = 0);	    \ +    (*((u32 *)InstancePtr + XBD_SOURCE_OFFSET) = 0);	    \ +    (*((u32 *)InstancePtr + XBD_DESTINATION_OFFSET) = 0);   \ +    (*((u32 *)InstancePtr + XBD_LENGTH_OFFSET) = 0);	    \ +    (*((u32 *)InstancePtr + XBD_STATUS_OFFSET) = 0);	    \ +    (*((u32 *)InstancePtr + XBD_DEVICE_STATUS_OFFSET) = 0); \ +    (*((u32 *)InstancePtr + XBD_NEXT_PTR_OFFSET) = 0);	    \ +    (*((u32 *)InstancePtr + XBD_ID_OFFSET) = 0);	    \ +    (*((u32 *)InstancePtr + XBD_FLAGS_OFFSET) = 0);	    \ +    (*((u32 *)InstancePtr + XBD_RQSTED_LENGTH_OFFSET) = 0); \ +} + +#define XBufDescriptor_GetControl(InstancePtr)	 \ +    (u32)(*((u32 *)InstancePtr + XBD_CONTROL_OFFSET)) + +#define XBufDescriptor_SetControl(InstancePtr, Control)	 \ +    (*((u32 *)InstancePtr + XBD_CONTROL_OFFSET) = (u32)Control) + +#define XBufDescriptor_IsLastControl(InstancePtr) \ +    (u32)(*((u32 *)InstancePtr + XBD_CONTROL_OFFSET) & \ +	       XDC_CONTROL_LAST_BD_MASK) + +#define XBufDescriptor_SetLast(InstancePtr) \ +    (*((u32 *)InstancePtr + XBD_CONTROL_OFFSET) |= XDC_CONTROL_LAST_BD_MASK) + +#define XBufDescriptor_GetSrcAddress(InstancePtr) \ +    ((u32 *)(*((u32 *)InstancePtr + XBD_SOURCE_OFFSET))) + +#define XBufDescriptor_SetSrcAddress(InstancePtr, Source) \ +    (*((u32 *)InstancePtr + XBD_SOURCE_OFFSET) = (u32)Source) + +#define XBufDescriptor_GetDestAddress(InstancePtr) \ +    ((u32 *)(*((u32 *)InstancePtr + XBD_DESTINATION_OFFSET))) + +#define XBufDescriptor_SetDestAddress(InstancePtr, Destination) \ +    (*((u32 *)InstancePtr + XBD_DESTINATION_OFFSET) = (u32)Destination) + +#define XBufDescriptor_GetLength(InstancePtr)				\ +    (u32)(*((u32 *)InstancePtr + XBD_RQSTED_LENGTH_OFFSET) -	\ +	      *((u32 *)InstancePtr + XBD_LENGTH_OFFSET)) + +#define XBufDescriptor_SetLength(InstancePtr, Length)			    \ +{									    \ +    (*((u32 *)InstancePtr + XBD_LENGTH_OFFSET) = (u32)(Length));    \ +    (*((u32 *)InstancePtr + XBD_RQSTED_LENGTH_OFFSET) = (u32)(Length));\ +} + +#define XBufDescriptor_GetStatus(InstancePtr)	 \ +    (u32)(*((u32 *)InstancePtr + XBD_STATUS_OFFSET)) + +#define XBufDescriptor_SetStatus(InstancePtr, Status)	 \ +    (*((u32 *)InstancePtr + XBD_STATUS_OFFSET) = (u32)Status) + +#define XBufDescriptor_IsLastStatus(InstancePtr) \ +    (u32)(*((u32 *)InstancePtr + XBD_STATUS_OFFSET) & \ +	       XDC_STATUS_LAST_BD_MASK) + +#define XBufDescriptor_GetDeviceStatus(InstancePtr) \ +    ((u32)(*((u32 *)InstancePtr + XBD_DEVICE_STATUS_OFFSET))) + +#define XBufDescriptor_SetDeviceStatus(InstancePtr, Status) \ +    (*((u32 *)InstancePtr + XBD_DEVICE_STATUS_OFFSET) = (u32)Status) + +#define XBufDescriptor_GetNextPtr(InstancePtr) \ +    (XBufDescriptor *)(*((u32 *)InstancePtr + XBD_NEXT_PTR_OFFSET)) + +#define XBufDescriptor_SetNextPtr(InstancePtr, NextPtr) \ +    (*((u32 *)InstancePtr + XBD_NEXT_PTR_OFFSET) = (u32)NextPtr) + +#define XBufDescriptor_GetId(InstancePtr) \ +    (u32)(*((u32 *)InstancePtr + XBD_ID_OFFSET)) + +#define XBufDescriptor_SetId(InstancePtr, Id) \ +    (*((u32 *)InstancePtr + XBD_ID_OFFSET) = (u32)Id) + +#define XBufDescriptor_GetFlags(InstancePtr) \ +    (u32)(*((u32 *)InstancePtr + XBD_FLAGS_OFFSET)) + +#define XBufDescriptor_SetFlags(InstancePtr, Flags) \ +    (*((u32 *)InstancePtr + XBD_FLAGS_OFFSET) = (u32)Flags) + +#define XBufDescriptor_Lock(InstancePtr) \ +    (*((u32 *)InstancePtr + XBD_FLAGS_OFFSET) |= XBD_FLAGS_LOCKED_MASK) + +#define XBufDescriptor_Unlock(InstancePtr) \ +    (*((u32 *)InstancePtr + XBD_FLAGS_OFFSET) &= ~XBD_FLAGS_LOCKED_MASK) + +#define XBufDescriptor_IsLocked(InstancePtr) \ +    (*((u32 *)InstancePtr + XBD_FLAGS_OFFSET) & XBD_FLAGS_LOCKED_MASK) + +/************************** Function Prototypes ******************************/ + +/* The following prototypes are provided to allow each of the functions to + * be implemented as a function rather than a macro, and to provide the + * syntax to allow users to understand how to call the macros, they are + * commented out to prevent linker errors + * + +u32 XBufDescriptor_Initialize(XBufDescriptor* InstancePtr); + +u32 XBufDescriptor_GetControl(XBufDescriptor* InstancePtr); +void XBufDescriptor_SetControl(XBufDescriptor* InstancePtr, u32 Control); + +u32 XBufDescriptor_IsLastControl(XBufDescriptor* InstancePtr); +void XBufDescriptor_SetLast(XBufDescriptor* InstancePtr); + +u32 XBufDescriptor_GetLength(XBufDescriptor* InstancePtr); +void XBufDescriptor_SetLength(XBufDescriptor* InstancePtr, u32 Length); + +u32 XBufDescriptor_GetStatus(XBufDescriptor* InstancePtr); +void XBufDescriptor_SetStatus(XBufDescriptor* InstancePtr, u32 Status); +u32 XBufDescriptor_IsLastStatus(XBufDescriptor* InstancePtr); + +u32 XBufDescriptor_GetDeviceStatus(XBufDescriptor* InstancePtr); +void XBufDescriptor_SetDeviceStatus(XBufDescriptor* InstancePtr, +				    u32 Status); + +u32 XBufDescriptor_GetSrcAddress(XBufDescriptor* InstancePtr); +void XBufDescriptor_SetSrcAddress(XBufDescriptor* InstancePtr, +				  u32 SourceAddress); + +u32 XBufDescriptor_GetDestAddress(XBufDescriptor* InstancePtr); +void XBufDescriptor_SetDestAddress(XBufDescriptor* InstancePtr, +				   u32 DestinationAddress); + +XBufDescriptor* XBufDescriptor_GetNextPtr(XBufDescriptor* InstancePtr); +void XBufDescriptor_SetNextPtr(XBufDescriptor* InstancePtr, +			       XBufDescriptor* NextPtr); + +u32 XBufDescriptor_GetId(XBufDescriptor* InstancePtr); +void XBufDescriptor_SetId(XBufDescriptor* InstancePtr, u32 Id); + +u32 XBufDescriptor_GetFlags(XBufDescriptor* InstancePtr); +void XBufDescriptor_SetFlags(XBufDescriptor* InstancePtr, u32 Flags); + +void XBufDescriptor_Lock(XBufDescriptor* InstancePtr); +void XBufDescriptor_Unlock(XBufDescriptor* InstancePtr); +u32 XBufDescriptor_IsLocked(XBufDescriptor* InstancePtr); + +void XBufDescriptor_Copy(XBufDescriptor* InstancePtr, +			 XBufDescriptor* DestinationPtr); + +*/ + +#endif				/* end of protection macro */ diff --git a/board/xilinx/common/xdma_channel.c b/board/xilinx/common/xdma_channel.c new file mode 100644 index 000000000..25f1e2602 --- /dev/null +++ b/board/xilinx/common/xdma_channel.c @@ -0,0 +1,738 @@ +/****************************************************************************** +* +*     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. +* +* FILENAME: +* +* xdma_channel.c +* +* DESCRIPTION: +* +* This file contains the DMA channel component. This component supports +* a distributed DMA design in which each device can have it's own dedicated +* DMA channel, as opposed to a centralized DMA design. This component +* performs processing for DMA on all devices. +* +* See xdma_channel.h for more information about this component. +* +* NOTES: +* +* None. +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xdma_channel.h" +#include "xbasic_types.h" +#include "xio.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_Initialize +* +* DESCRIPTION: +* +* This function initializes a DMA channel.  This function must be called +* prior to using a DMA channel.  Initialization of a channel includes setting +* up the registers base address, and resetting the channel such that it's in a +* known state.  Interrupts for the channel are disabled when the channel is +* reset. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on. +* +* BaseAddress contains the base address of the registers for the DMA channel. +* +* RETURN VALUE: +* +* XST_SUCCESS indicating initialization was successful. +* +* NOTES: +* +* None. +* +******************************************************************************/ +XStatus +XDmaChannel_Initialize(XDmaChannel * InstancePtr, u32 BaseAddress) +{ +	/* assert to verify input arguments, don't assert base address */ + +	XASSERT_NONVOID(InstancePtr != NULL); + +	/* setup the base address of the registers for the DMA channel such +	 * that register accesses can be done +	 */ +	InstancePtr->RegBaseAddress = BaseAddress; + +	/* initialize the scatter gather list such that it indicates it has not +	 * been created yet and the DMA channel is ready to use (initialized) +	 */ +	InstancePtr->GetPtr = NULL; +	InstancePtr->PutPtr = NULL; +	InstancePtr->CommitPtr = NULL; +	InstancePtr->LastPtr = NULL; + +	InstancePtr->TotalDescriptorCount = 0; +	InstancePtr->ActiveDescriptorCount = 0; +	InstancePtr->IsReady = XCOMPONENT_IS_READY; + +	/* initialize the version of the component +	 */ +	XVersion_FromString(&InstancePtr->Version, "1.00a"); + +	/* reset the DMA channel such that it's in a known state and ready +	 * and indicate the initialization occured with no errors, note that +	 * the is ready variable must be set before this call or reset will assert +	 */ +	XDmaChannel_Reset(InstancePtr); + +	return XST_SUCCESS; +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_IsReady +* +* DESCRIPTION: +* +* This function determines if a DMA channel component has been successfully +* initialized such that it's ready to use. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on. +* +* RETURN VALUE: +* +* TRUE if the DMA channel component is ready, FALSE otherwise. +* +* NOTES: +* +* None. +* +******************************************************************************/ +u32 +XDmaChannel_IsReady(XDmaChannel * InstancePtr) +{ +	/* assert to verify input arguments used by the base component */ + +	XASSERT_NONVOID(InstancePtr != NULL); + +	return InstancePtr->IsReady == XCOMPONENT_IS_READY; +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_GetVersion +* +* DESCRIPTION: +* +* This function gets the software version for the specified DMA channel +* component. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on. +* +* RETURN VALUE: +* +* A pointer to the software version of the specified DMA channel. +* +* NOTES: +* +* None. +* +******************************************************************************/ +XVersion * +XDmaChannel_GetVersion(XDmaChannel * InstancePtr) +{ +	/* assert to verify input arguments */ + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* return a pointer to the version of the DMA channel */ + +	return &InstancePtr->Version; +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_SelfTest +* +* DESCRIPTION: +* +* This function performs a self test on the specified DMA channel.  This self +* test is destructive as the DMA channel is reset and a register default is +* verified. +* +* ARGUMENTS: +* +* InstancePtr is a pointer to the DMA channel to be operated on. +* +* RETURN VALUE: +* +* XST_SUCCESS is returned if the self test is successful, or one of the +* following errors. +* +*	XST_DMA_RESET_REGISTER_ERROR 		Indicates the control register value +*										after a reset was not correct +* +* NOTES: +* +* This test does not performs a DMA transfer to test the channel because the +* DMA hardware will not currently allow a non-local memory transfer to non-local +* memory (memory copy), but only allows a non-local memory to or from the device +* memory (typically a FIFO). +* +******************************************************************************/ + +#define XDC_CONTROL_REG_RESET_MASK  0x98000000UL	/* control reg reset value */ + +XStatus +XDmaChannel_SelfTest(XDmaChannel * InstancePtr) +{ +	u32 ControlReg; + +	/* assert to verify input arguments */ + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* reset the DMA channel such that it's in a known state before the test +	 * it resets to no interrupts enabled, the desired state for the test +	 */ +	XDmaChannel_Reset(InstancePtr); + +	/* this should be the first test to help prevent a lock up with the polling +	 * loop that occurs later in the test, check the reset value of the DMA +	 * control register to make sure it's correct, return with an error if not +	 */ +	ControlReg = XDmaChannel_GetControl(InstancePtr); +	if (ControlReg != XDC_CONTROL_REG_RESET_MASK) { +		return XST_DMA_RESET_REGISTER_ERROR; +	} + +	return XST_SUCCESS; +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_Reset +* +* DESCRIPTION: +* +* This function resets the DMA channel. This is a destructive operation such +* that it should not be done while a channel is being used.  If the DMA channel +* is transferring data into other blocks, such as a FIFO, it may be necessary +* to reset other blocks.  This function does not modify the contents of a +* scatter gather list for a DMA channel such that the user is responsible for +* getting buffer descriptors from the list if necessary. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on. +* +* RETURN VALUE: +* +* None. +* +* NOTES: +* +* None. +* +******************************************************************************/ +void +XDmaChannel_Reset(XDmaChannel * InstancePtr) +{ +	/* assert to verify input arguments */ + +	XASSERT_VOID(InstancePtr != NULL); +	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* reset the DMA channel such that it's in a known state, the reset +	 * register is self clearing such that it only has to be set +	 */ +	XIo_Out32(InstancePtr->RegBaseAddress + XDC_RST_REG_OFFSET, +		  XDC_RESET_MASK); +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_GetControl +* +* DESCRIPTION: +* +* This function gets the control register contents of the DMA channel. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on. +* +* RETURN VALUE: +* +* The control register contents of the DMA channel. One or more of the +* following values may be contained the register.  Each of the values are +* unique bit masks. +* +*	XDC_DMACR_SOURCE_INCR_MASK	Increment the source address +*	XDC_DMACR_DEST_INCR_MASK	Increment the destination address +*	XDC_DMACR_SOURCE_LOCAL_MASK Local source address +*	XDC_DMACR_DEST_LOCAL_MASK	Local destination address +*	XDC_DMACR_SG_ENABLE_MASK	Scatter gather enable +*	XDC_DMACR_GEN_BD_INTR_MASK	Individual buffer descriptor interrupt +*	XDC_DMACR_LAST_BD_MASK		Last buffer descriptor in a packet +* +* NOTES: +* +* None. +* +******************************************************************************/ +u32 +XDmaChannel_GetControl(XDmaChannel * InstancePtr) +{ +	/* assert to verify input arguments */ + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* return the contents of the DMA control register */ + +	return XIo_In32(InstancePtr->RegBaseAddress + XDC_DMAC_REG_OFFSET); +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_SetControl +* +* DESCRIPTION: +* +* This function sets the control register of the specified DMA channel. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on. +* +* Control contains the value to be written to the control register of the DMA +* channel. One or more of the following values may be contained the register. +* Each of the values are unique bit masks such that they may be ORed together +* to enable multiple bits or inverted and ANDed to disable multiple bits. +* +*	XDC_DMACR_SOURCE_INCR_MASK	Increment the source address +*	XDC_DMACR_DEST_INCR_MASK	Increment the destination address +*	XDC_DMACR_SOURCE_LOCAL_MASK Local source address +*	XDC_DMACR_DEST_LOCAL_MASK	Local destination address +*	XDC_DMACR_SG_ENABLE_MASK	Scatter gather enable +*	XDC_DMACR_GEN_BD_INTR_MASK	Individual buffer descriptor interrupt +*	XDC_DMACR_LAST_BD_MASK		Last buffer descriptor in a packet +* +* RETURN VALUE: +* +* None. +* +* NOTES: +* +* None. +* +******************************************************************************/ +void +XDmaChannel_SetControl(XDmaChannel * InstancePtr, u32 Control) +{ +	/* assert to verify input arguments except the control which can't be +	 * asserted since all values are valid +	 */ +	XASSERT_VOID(InstancePtr != NULL); +	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* set the DMA control register to the specified value */ + +	XIo_Out32(InstancePtr->RegBaseAddress + XDC_DMAC_REG_OFFSET, Control); +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_GetStatus +* +* DESCRIPTION: +* +* This function gets the status register contents of the DMA channel. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on. +* +* RETURN VALUE: +* +* The status register contents of the DMA channel. One or more of the +* following values may be contained the register. Each of the values are +* unique bit masks. +* +*	XDC_DMASR_BUSY_MASK			The DMA channel is busy +*	XDC_DMASR_BUS_ERROR_MASK	A bus error occurred +*	XDC_DMASR_BUS_TIMEOUT_MASK	A bus timeout occurred +*	XDC_DMASR_LAST_BD_MASK		The last buffer descriptor of a packet +* +* NOTES: +* +* None. +* +******************************************************************************/ +u32 +XDmaChannel_GetStatus(XDmaChannel * InstancePtr) +{ +	/* assert to verify input arguments */ + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* return the contents of the DMA status register */ + +	return XIo_In32(InstancePtr->RegBaseAddress + XDC_DMAS_REG_OFFSET); +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_SetIntrStatus +* +* DESCRIPTION: +* +* This function sets the interrupt status register of the specified DMA channel. +* Setting any bit of the interrupt status register will clear the bit to +* indicate the interrupt processing has been completed. The definitions of each +* bit in the register match the definition of the bits in the interrupt enable +* register. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on. +* +* Status contains the value to be written to the status register of the DMA +* channel.  One or more of the following values may be contained the register. +* Each of the values are unique bit masks such that they may be ORed together +* to enable multiple bits or inverted and ANDed to disable multiple bits. +* +*	XDC_IXR_DMA_DONE_MASK		The dma operation is done +*	XDC_IXR_DMA_ERROR_MASK	    The dma operation had an error +*	XDC_IXR_PKT_DONE_MASK	    A packet is complete +*	XDC_IXR_PKT_THRESHOLD_MASK 	The packet count threshold reached +*	XDC_IXR_PKT_WAIT_BOUND_MASK The packet wait bound reached +*	XDC_IXR_SG_DISABLE_ACK_MASK The scatter gather disable completed +*	XDC_IXR_BD_MASK				A buffer descriptor is done +* +* RETURN VALUE: +* +* None. +* +* NOTES: +* +* None. +* +******************************************************************************/ +void +XDmaChannel_SetIntrStatus(XDmaChannel * InstancePtr, u32 Status) +{ +	/* assert to verify input arguments except the status which can't be +	 * asserted since all values are valid +	 */ +	XASSERT_VOID(InstancePtr != NULL); +	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* set the interrupt status register with the specified value such that +	 * all bits which are set in the register are cleared effectively clearing +	 * any active interrupts +	 */ +	XIo_Out32(InstancePtr->RegBaseAddress + XDC_IS_REG_OFFSET, Status); +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_GetIntrStatus +* +* DESCRIPTION: +* +* This function gets the interrupt status register of the specified DMA channel. +* The interrupt status register indicates which interrupts are active +* for the DMA channel.  If an interrupt is active, the status register must be +* set (written) with the bit set for each interrupt which has been processed +* in order to clear the interrupts.  The definitions of each bit in the register +* match the definition of the bits in the interrupt enable register. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on. +* +* RETURN VALUE: +* +* The interrupt status register contents of the specified DMA channel. +* One or more of the following values may be contained the register. +* Each of the values are unique bit masks. +* +*	XDC_IXR_DMA_DONE_MASK		The dma operation is done +*	XDC_IXR_DMA_ERROR_MASK	    The dma operation had an error +*	XDC_IXR_PKT_DONE_MASK	    A packet is complete +*	XDC_IXR_PKT_THRESHOLD_MASK 	The packet count threshold reached +*	XDC_IXR_PKT_WAIT_BOUND_MASK The packet wait bound reached +*	XDC_IXR_SG_DISABLE_ACK_MASK The scatter gather disable completed +*	XDC_IXR_SG_END_MASK			Current descriptor was the end of the list +*	XDC_IXR_BD_MASK				A buffer descriptor is done +* +* NOTES: +* +* None. +* +******************************************************************************/ +u32 +XDmaChannel_GetIntrStatus(XDmaChannel * InstancePtr) +{ +	/* assert to verify input arguments */ + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* return the contents of the interrupt status register */ + +	return XIo_In32(InstancePtr->RegBaseAddress + XDC_IS_REG_OFFSET); +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_SetIntrEnable +* +* DESCRIPTION: +* +* This function sets the interrupt enable register of the specified DMA +* channel.  The interrupt enable register contains bits which enable +* individual interrupts for the DMA channel.  The definitions of each bit +* in the register match the definition of the bits in the interrupt status +* register. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on. +* +* Enable contains the interrupt enable register contents to be written +* in the DMA channel. One or more of the following values may be contained +* the register. Each of the values are unique bit masks such that they may be +* ORed together to enable multiple bits or inverted and ANDed to disable +* multiple bits. +* +*	XDC_IXR_DMA_DONE_MASK		The dma operation is done +*	XDC_IXR_DMA_ERROR_MASK	    The dma operation had an error +*	XDC_IXR_PKT_DONE_MASK	    A packet is complete +*	XDC_IXR_PKT_THRESHOLD_MASK 	The packet count threshold reached +*	XDC_IXR_PKT_WAIT_BOUND_MASK The packet wait bound reached +*	XDC_IXR_SG_DISABLE_ACK_MASK The scatter gather disable completed +*	XDC_IXR_SG_END_MASK			Current descriptor was the end of the list +*	XDC_IXR_BD_MASK				A buffer descriptor is done +* +* RETURN VALUE: +* +* None. +* +* NOTES: +* +* None. +* +******************************************************************************/ +void +XDmaChannel_SetIntrEnable(XDmaChannel * InstancePtr, u32 Enable) +{ +	/* assert to verify input arguments except the enable which can't be +	 * asserted since all values are valid +	 */ +	XASSERT_VOID(InstancePtr != NULL); +	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* set the interrupt enable register to the specified value */ + +	XIo_Out32(InstancePtr->RegBaseAddress + XDC_IE_REG_OFFSET, Enable); +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_GetIntrEnable +* +* DESCRIPTION: +* +* This function gets the interrupt enable of the DMA channel.  The +* interrupt enable contains flags which enable individual interrupts for the +* DMA channel. The definitions of each bit in the register match the definition +* of the bits in the interrupt status register. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on. +* +* RETURN VALUE: +* +* The interrupt enable of the DMA channel.  One or more of the following values +* may be contained the register. Each of the values are unique bit masks. +* +*	XDC_IXR_DMA_DONE_MASK		The dma operation is done +*	XDC_IXR_DMA_ERROR_MASK	    The dma operation had an error +*	XDC_IXR_PKT_DONE_MASK	    A packet is complete +*	XDC_IXR_PKT_THRESHOLD_MASK 	The packet count threshold reached +*	XDC_IXR_PKT_WAIT_BOUND_MASK The packet wait bound reached +*	XDC_IXR_SG_DISABLE_ACK_MASK The scatter gather disable completed +*	XDC_IXR_BD_MASK				A buffer descriptor is done +* +* NOTES: +* +* None. +* +******************************************************************************/ +u32 +XDmaChannel_GetIntrEnable(XDmaChannel * InstancePtr) +{ +	/* assert to verify input arguments */ + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* return the contents of the interrupt enable register */ + +	return XIo_In32(InstancePtr->RegBaseAddress + XDC_IE_REG_OFFSET); +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_Transfer +* +* DESCRIPTION: +* +* This function starts the DMA channel transferring data from a memory source +* to a memory destination. This function only starts the operation and returns +* before the operation may be complete.  If the interrupt is enabled, an +* interrupt will be generated when the operation is complete, otherwise it is +* necessary to poll the channel status to determine when it's complete.  It is +* the responsibility of the caller to determine when the operation is complete +* by handling the generated interrupt or polling the status.  It is also the +* responsibility of the caller to ensure that the DMA channel is not busy with +* another transfer before calling this function. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on. +* +* SourcePtr contains a pointer to the source memory where the data is to +* be tranferred from and must be 32 bit aligned. +* +* DestinationPtr contains a pointer to the destination memory where the data +* is to be transferred and must be 32 bit aligned. +* +* ByteCount contains the number of bytes to transfer during the DMA operation. +* +* RETURN VALUE: +* +* None. +* +* NOTES: +* +* The DMA h/w will not currently allow a non-local memory transfer to non-local +* memory (memory copy), but only allows a non-local memory to or from the device +* memory (typically a FIFO). +* +* It is the responsibility of the caller to ensure that the cache is +* flushed and invalidated both before and after the DMA operation completes +* if the memory pointed to is cached. The caller must also ensure that the +* pointers contain a physical address rather than a virtual address +* if address translation is being used. +* +******************************************************************************/ +void +XDmaChannel_Transfer(XDmaChannel * InstancePtr, +		     u32 * SourcePtr, u32 * DestinationPtr, u32 ByteCount) +{ +	/* assert to verify input arguments and the alignment of any arguments +	 * which have expected alignments +	 */ +	XASSERT_VOID(InstancePtr != NULL); +	XASSERT_VOID(SourcePtr != NULL); +	XASSERT_VOID(((u32) SourcePtr & 3) == 0); +	XASSERT_VOID(DestinationPtr != NULL); +	XASSERT_VOID(((u32) DestinationPtr & 3) == 0); +	XASSERT_VOID(ByteCount != 0); +	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* setup the source and destination address registers for the transfer */ + +	XIo_Out32(InstancePtr->RegBaseAddress + XDC_SA_REG_OFFSET, +		  (u32) SourcePtr); + +	XIo_Out32(InstancePtr->RegBaseAddress + XDC_DA_REG_OFFSET, +		  (u32) DestinationPtr); + +	/* start the DMA transfer to copy from the source buffer to the +	 * destination buffer by writing the length to the length register +	 */ +	XIo_Out32(InstancePtr->RegBaseAddress + XDC_LEN_REG_OFFSET, ByteCount); +} diff --git a/board/xilinx/common/xdma_channel.h b/board/xilinx/common/xdma_channel.h new file mode 100644 index 000000000..06976c3e0 --- /dev/null +++ b/board/xilinx/common/xdma_channel.h @@ -0,0 +1,291 @@ +/****************************************************************************** +* +*     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. +* +* FILENAME: +* +* xdma_channel.h +* +* DESCRIPTION: +* +* This file contains the DMA channel component implementation. This component +* supports a distributed DMA design in which each device can have it's own +* dedicated DMA channel, as opposed to a centralized DMA design. +* A device which uses DMA typically contains two DMA channels, one for +* sending data and the other for receiving data. +* +* This component is designed to be used as a basic building block for +* designing a device driver. It provides registers accesses such that all +* DMA processing can be maintained easier, but the device driver designer +* must still understand all the details of the DMA channel. +* +* The DMA channel allows a CPU to minimize the CPU interaction required to move +* data between a memory and a device.  The CPU requests the DMA channel to +* perform a DMA operation and typically continues performing other processing +* until the DMA operation completes.  DMA could be considered a primitive form +* of multiprocessing such that caching and address translation can be an issue. +* +* Scatter Gather Operations +* +* The DMA channel may support scatter gather operations. A scatter gather +* operation automates the DMA channel such that multiple buffers can be +* sent or received with minimal software interaction with the hardware.  Buffer +* descriptors, contained in the XBufDescriptor component, are used by the +* scatter gather operations of the DMA channel to describe the buffers to be +* processed. +* +* Scatter Gather List Operations +* +* A scatter gather list may be supported by each DMA channel.  The scatter +* gather list allows buffer descriptors to be put into the list by a device +* driver which requires scatter gather.  The hardware processes the buffer +* descriptors which are contained in the list and modifies the buffer +* descriptors to reflect the status of the DMA operations.  The device driver +* is notified by interrupt that specific DMA events occur including scatter +* gather events.  The device driver removes the completed buffer descriptors +* from the scatter gather list to evaluate the status of each DMA operation. +* +* The scatter gather list is created and buffer descriptors are inserted into +* the list.  Buffer descriptors are never removed from the list after it's +* creation such that a put operation copies from a temporary buffer descriptor +* to a buffer descriptor in the list.  Get operations don't copy from the list +* to a temporary, but return a pointer to the buffer descriptor in the list. +* A buffer descriptor in the list may be locked to prevent it from being +* overwritten by a put operation.  This allows the device driver to get a +* descriptor from a scatter gather list and prevent it from being overwritten +* until the buffer associated with the buffer descriptor has been processed. +* +* Typical Scatter Gather Processing +* +* The following steps illustrate the typical processing to use the +* scatter gather features of a DMA channel. +* +* 1. Create a scatter gather list for the DMA channel which puts empty buffer +*    descriptors into the list. +* 2. Create buffer descriptors which describe the buffers to be filled with +* 	 receive data or the buffers which contain data to be sent. +* 3. Put buffer descriptors into the DMA channel scatter list such that scatter +*    gather operations are requested. +* 4. Commit the buffer descriptors in the list such that they are ready to be +*    used by the DMA channel hardware. +* 5. Start the scatter gather operations of the DMA channel. +* 6. Process any interrupts which occur as a result of the scatter gather +*    operations or poll the DMA channel to determine the status. +* +* Interrupts +* +* Each DMA channel has the ability to generate an interrupt.  This component +* does not perform processing for the interrupt as this processing is typically +* tightly coupled with the device which is using the DMA channel.  It is the +* responsibility of the caller of DMA functions to manage the interrupt +* including connecting to the interrupt and enabling/disabling the interrupt. +* +* Critical Sections +* +* It is the responsibility of the device driver designer to use critical +* sections as necessary when calling functions of the DMA channel.  This +* component does not use critical sections and it does access registers using +* read-modify-write operations.  Calls to DMA functions from a main thread +* and from an interrupt context could produce unpredictable behavior such that +* the caller must provide the appropriate critical sections. +* +* Address Translation +* +* All addresses of data structures which are passed to DMA functions must +* be physical (real) addresses as opposed to logical (virtual) addresses. +* +* Caching +* +* The memory which is passed to the function which creates the scatter gather +* list must not be cached such that buffer descriptors are non-cached.  This +* is necessary because the buffer descriptors are kept in a ring buffer and +* not directly accessible to the caller of DMA functions. +* +* The caller of DMA functions is responsible for ensuring that any data +* buffers which are passed to the DMA channel are cache-line aligned if +* necessary. +* +* The caller of DMA functions is responsible for ensuring that any data +* buffers which are passed to the DMA channel have been flushed from the cache. +* +* The caller of DMA functions is responsible for ensuring that the cache is +* invalidated prior to using any data buffers which are the result of a DMA +* operation. +* +* Memory Alignment +* +* The addresses of data buffers which are passed to DMA functions must be +* 32 bit word aligned since the DMA hardware performs 32 bit word transfers. +* +* Mutual Exclusion +* +* The functions of the DMA channel are not thread safe such that the caller +* of all DMA functions is responsible for ensuring mutual exclusion for a +* DMA channel.  Mutual exclusion across multiple DMA channels is not +* necessary. +* +* NOTES: +* +* Many of the provided functions which are register accessors don't provide +* a lot of error detection. The caller is expected to understand the impact +* of a function call based upon the current state of the DMA channel.  This +* is done to minimize the overhead in this component. +* +******************************************************************************/ + +#ifndef XDMA_CHANNEL_H		/* prevent circular inclusions */ +#define XDMA_CHANNEL_H		/* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xdma_channel_i.h"	/* constants shared with buffer descriptor */ +#include "xbasic_types.h" +#include "xstatus.h" +#include "xversion.h" +#include "xbuf_descriptor.h" + +/************************** Constant Definitions *****************************/ + +/* the following constants provide access to the bit fields of the DMA control + * register (DMACR) + */ +#define XDC_DMACR_SOURCE_INCR_MASK	0x80000000UL	/* increment source address */ +#define XDC_DMACR_DEST_INCR_MASK	0x40000000UL	/* increment dest address */ +#define XDC_DMACR_SOURCE_LOCAL_MASK 0x20000000UL	/* local source address */ +#define XDC_DMACR_DEST_LOCAL_MASK	0x10000000UL	/* local dest address */ +#define XDC_DMACR_SG_DISABLE_MASK	0x08000000UL	/* scatter gather disable */ +#define XDC_DMACR_GEN_BD_INTR_MASK	0x04000000UL	/* descriptor interrupt */ +#define XDC_DMACR_LAST_BD_MASK		XDC_CONTROL_LAST_BD_MASK	/* last buffer */ +															 /*     descriptor  */ + +/* the following constants provide access to the bit fields of the DMA status + * register (DMASR) + */ +#define XDC_DMASR_BUSY_MASK			0x80000000UL	/* channel is busy */ +#define XDC_DMASR_BUS_ERROR_MASK	0x40000000UL	/* bus error occurred */ +#define XDC_DMASR_BUS_TIMEOUT_MASK	0x20000000UL	/* bus timeout occurred */ +#define XDC_DMASR_LAST_BD_MASK		XDC_STATUS_LAST_BD_MASK	/* last buffer */ +														    /* descriptor  */ +#define XDC_DMASR_SG_BUSY_MASK		0x08000000UL	/* scatter gather is busy */ + +/* the following constants provide access to the bit fields of the interrupt + * status register (ISR) and the interrupt enable register (IER), bit masks + * match for both registers such that they are named IXR + */ +#define XDC_IXR_DMA_DONE_MASK		0x1UL	/* dma operation done */ +#define XDC_IXR_DMA_ERROR_MASK	    0x2UL	/* dma operation error */ +#define XDC_IXR_PKT_DONE_MASK	    0x4UL	/* packet done */ +#define XDC_IXR_PKT_THRESHOLD_MASK 	0x8UL	/* packet count threshold */ +#define XDC_IXR_PKT_WAIT_BOUND_MASK 0x10UL	/* packet wait bound reached */ +#define XDC_IXR_SG_DISABLE_ACK_MASK 0x20UL	/* scatter gather disable +						   acknowledge occurred */ +#define XDC_IXR_SG_END_MASK			0x40UL	/* last buffer descriptor +							   disabled scatter gather */ +#define XDC_IXR_BD_MASK				0x80UL	/* buffer descriptor done */ + +/**************************** Type Definitions *******************************/ + +/* + * the following structure contains data which is on a per instance basis + * for the XDmaChannel component + */ +typedef struct XDmaChannelTag { +	XVersion Version;	/* version of the driver */ +	u32 RegBaseAddress;	/* base address of registers */ +	u32 IsReady;		/* device is initialized and ready */ + +	XBufDescriptor *PutPtr;	/* keep track of where to put into list */ +	XBufDescriptor *GetPtr;	/* keep track of where to get from list */ +	XBufDescriptor *CommitPtr;	/* keep track of where to commit in list */ +	XBufDescriptor *LastPtr;	/* keep track of the last put in the list */ +	u32 TotalDescriptorCount;	/* total # of descriptors in the list */ +	u32 ActiveDescriptorCount;	/* # of descriptors pointing to buffers +					   * in the buffer descriptor list */ +} XDmaChannel; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +XStatus XDmaChannel_Initialize(XDmaChannel * InstancePtr, u32 BaseAddress); +u32 XDmaChannel_IsReady(XDmaChannel * InstancePtr); +XVersion *XDmaChannel_GetVersion(XDmaChannel * InstancePtr); +XStatus XDmaChannel_SelfTest(XDmaChannel * InstancePtr); +void XDmaChannel_Reset(XDmaChannel * InstancePtr); + +/* Control functions */ + +u32 XDmaChannel_GetControl(XDmaChannel * InstancePtr); +void XDmaChannel_SetControl(XDmaChannel * InstancePtr, u32 Control); + +/* Status functions */ + +u32 XDmaChannel_GetStatus(XDmaChannel * InstancePtr); +void XDmaChannel_SetIntrStatus(XDmaChannel * InstancePtr, u32 Status); +u32 XDmaChannel_GetIntrStatus(XDmaChannel * InstancePtr); +void XDmaChannel_SetIntrEnable(XDmaChannel * InstancePtr, u32 Enable); +u32 XDmaChannel_GetIntrEnable(XDmaChannel * InstancePtr); + +/* DMA without scatter gather functions */ + +void XDmaChannel_Transfer(XDmaChannel * InstancePtr, +			  u32 * SourcePtr, u32 * DestinationPtr, u32 ByteCount); + +/* Scatter gather functions */ + +XStatus XDmaChannel_SgStart(XDmaChannel * InstancePtr); +XStatus XDmaChannel_SgStop(XDmaChannel * InstancePtr, +			   XBufDescriptor ** BufDescriptorPtr); +XStatus XDmaChannel_CreateSgList(XDmaChannel * InstancePtr, +				 u32 * MemoryPtr, u32 ByteCount); +u32 XDmaChannel_IsSgListEmpty(XDmaChannel * InstancePtr); + +XStatus XDmaChannel_PutDescriptor(XDmaChannel * InstancePtr, +				  XBufDescriptor * BufDescriptorPtr); +XStatus XDmaChannel_CommitPuts(XDmaChannel * InstancePtr); +XStatus XDmaChannel_GetDescriptor(XDmaChannel * InstancePtr, +				  XBufDescriptor ** BufDescriptorPtr); + +/* Packet functions for interrupt collescing */ + +u32 XDmaChannel_GetPktCount(XDmaChannel * InstancePtr); +void XDmaChannel_DecrementPktCount(XDmaChannel * InstancePtr); +XStatus XDmaChannel_SetPktThreshold(XDmaChannel * InstancePtr, u8 Threshold); +u8 XDmaChannel_GetPktThreshold(XDmaChannel * InstancePtr); +void XDmaChannel_SetPktWaitBound(XDmaChannel * InstancePtr, u32 WaitBound); +u32 XDmaChannel_GetPktWaitBound(XDmaChannel * InstancePtr); + +#endif				/* end of protection macro */ diff --git a/board/xilinx/common/xdma_channel_i.h b/board/xilinx/common/xdma_channel_i.h new file mode 100644 index 000000000..e9f343bbb --- /dev/null +++ b/board/xilinx/common/xdma_channel_i.h @@ -0,0 +1,110 @@ +/****************************************************************************** +* +*     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. +* +* FILENAME: +* +* xdma_channel_i.h +* +* DESCRIPTION: +* +* This file contains data which is shared internal data for the DMA channel +* component. It is also shared with the buffer descriptor component which is +* very tightly coupled with the DMA channel component. +* +* NOTES: +* +* The last buffer descriptor constants must be located here to prevent a +* circular dependency between the DMA channel component and the buffer +* descriptor component. +* +******************************************************************************/ + +#ifndef XDMA_CHANNEL_I_H	/* prevent circular inclusions */ +#define XDMA_CHANNEL_I_H	/* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xbasic_types.h" +#include "xstatus.h" +#include "xversion.h" + +/************************** Constant Definitions *****************************/ + +#define XDC_DMA_CHANNEL_V1_00_A		"1.00a" + +/* the following constant provides access to the bit fields of the DMA control + * register (DMACR) which must be shared between the DMA channel component + * and the buffer descriptor component + */ +#define XDC_CONTROL_LAST_BD_MASK	0x02000000UL	/* last buffer descriptor */ + +/* the following constant provides access to the bit fields of the DMA status + * register (DMASR) which must be shared between the DMA channel component + * and the buffer descriptor component + */ +#define XDC_STATUS_LAST_BD_MASK		0x10000000UL	/* last buffer descriptor */ + +/* the following constants provide access to each of the registers of a DMA + * channel + */ +#define XDC_RST_REG_OFFSET	0	/* reset register */ +#define XDC_MI_REG_OFFSET	0	/* module information register */ +#define XDC_DMAC_REG_OFFSET	4	/* DMA control register */ +#define XDC_SA_REG_OFFSET	8	/* source address register */ +#define XDC_DA_REG_OFFSET	12	/* destination address register */ +#define XDC_LEN_REG_OFFSET	16	/* length register */ +#define XDC_DMAS_REG_OFFSET	20	/* DMA status register */ +#define XDC_BDA_REG_OFFSET	24	/* buffer descriptor address register */ +#define XDC_SWCR_REG_OFFSET 28	/* software control register */ +#define XDC_UPC_REG_OFFSET	32	/* unserviced packet count register */ +#define	XDC_PCT_REG_OFFSET	36	/* packet count threshold register */ +#define XDC_PWB_REG_OFFSET	40	/* packet wait bound register */ +#define XDC_IS_REG_OFFSET	44	/* interrupt status register */ +#define XDC_IE_REG_OFFSET	48	/* interrupt enable register */ + +/* the following constant is written to the reset register to reset the + * DMA channel + */ +#define XDC_RESET_MASK				0x0000000AUL + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +#endif				/* end of protection macro */ diff --git a/board/xilinx/common/xdma_channel_sg.c b/board/xilinx/common/xdma_channel_sg.c new file mode 100644 index 000000000..a8e94625b --- /dev/null +++ b/board/xilinx/common/xdma_channel_sg.c @@ -0,0 +1,1317 @@ +/* $Id: xdma_channel_sg.c,v 1.6 2003/02/03 19:50:33 moleres 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. +* +* FILENAME: +* +* xdma_channel_sg.c +* +* DESCRIPTION: +* +* This file contains the implementation of the XDmaChannel component which is +* related to scatter gather operations. +* +* Scatter Gather Operations +* +* The DMA channel may support scatter gather operations. A scatter gather +* operation automates the DMA channel such that multiple buffers can be +* sent or received with minimal software interaction with the hardware.	 Buffer +* descriptors, contained in the XBufDescriptor component, are used by the +* scatter gather operations of the DMA channel to describe the buffers to be +* processed. +* +* Scatter Gather List Operations +* +* A scatter gather list may be supported by each DMA channel.  The scatter +* gather list allows buffer descriptors to be put into the list by a device +* driver which requires scatter gather.	 The hardware processes the buffer +* descriptors which are contained in the list and modifies the buffer +* descriptors to reflect the status of the DMA operations.  The device driver +* is notified by interrupt that specific DMA events occur including scatter +* gather events.  The device driver removes the completed buffer descriptors +* from the scatter gather list to evaluate the status of each DMA operation. +* +* The scatter gather list is created and buffer descriptors are inserted into +* the list.  Buffer descriptors are never removed from the list after it's +* creation such that a put operation copies from a temporary buffer descriptor +* to a buffer descriptor in the list.  Get operations don't copy from the list +* to a temporary, but return a pointer to the buffer descriptor in the list. +* A buffer descriptor in the list may be locked to prevent it from being +* overwritten by a put operation.  This allows the device driver to get a +* descriptor from a scatter gather list and prevent it from being overwritten +* until the buffer associated with the buffer descriptor has been processed. +* +* The get and put functions only operate on the list and are asynchronous from +* the hardware which may be using the list of descriptors.  This is important +* because there are no checks in the get and put functions to ensure that the +* hardware has processed the descriptors.  This must be handled by the driver +* using the DMA scatter gather channel through the use of the other functions. +* When a scatter gather operation is started, the start function does ensure +* that the descriptor to start has not already been processed by the hardware +* and is not the first of a series of descriptors that have not been committed +* yet. +* +* Descriptors are put into the list but not marked as ready to use by the +* hardware until a commit operation is done.  This allows multiple descriptors +* which may contain a single packet of information for a protocol to be +* guaranteed not to cause any underflow conditions during transmission. The +* hardware design only allows descriptors to cause it to stop after a descriptor +* has been processed rather than before it is processed.  A series of +* descriptors are put into the list followed by a commit operation, or each +* descriptor may be commited.  A commit operation is performed by changing a +* single descriptor, the first of the series of puts, to indicate that the +* hardware may now use all descriptors after it.  The last descriptor in the +* list is always set to cause the hardware to stop after it is processed. +* +* Typical Scatter Gather Processing +* +* The following steps illustrate the typical processing to use the +* scatter gather features of a DMA channel. +* +* 1. Create a scatter gather list for the DMA channel which puts empty buffer +*    descriptors into the list. +* 2. Create buffer descriptors which describe the buffers to be filled with +*    receive data or the buffers which contain data to be sent. +* 3. Put buffer descriptors into the DMA channel scatter list such that scatter +*    gather operations are requested. +* 4. Commit the buffer descriptors in the list such that they are ready to be +*    used by the DMA channel hardware. +* 5. Start the scatter gather operations of the DMA channel. +* 6. Process any interrupts which occur as a result of the scatter gather +*    operations or poll the DMA channel to determine the status.  This may +*    be accomplished by getting the packet count for the channel and then +*    getting the appropriate number of descriptors from the list for that +*    number of packets. +* +* Minimizing Interrupts +* +* The Scatter Gather operating mode is designed to reduce the amount of CPU +* throughput necessary to manage the hardware for devices. A key to the CPU +* throughput is the number and rate of interrupts that the CPU must service. +* Devices with higher data rates can cause larger numbers of interrupts and +* higher frequency interrupts. Ideally the number of interrupts can be reduced +* by only generating an interrupt when a specific amount of data has been +* received from the interface. This design suffers from a lack of interrupts +* when the amount of data received is less than the specified amount of data +* to generate an interrupt. In order to help minimize the number of interrupts +* which the CPU must service, an algorithm referred to as "interrupt coalescing" +* is utilized. +* +* Interrupt Coalescing +* +* The principle of interrupt coalescing is to wait before generating an +* interrupt until a certain number of packets have been received or sent. An +* interrupt is also generated if a smaller number of packets have been received +* followed by a certain period of time with no packet reception. This is a +* trade-off of latency for bandwidth and is accomplished using several +* mechanisms of the hardware including a counter for packets received or +* transmitted and a packet timer. These two hardware mechanisms work in +* combination to allow a reduction in the number of interrupts processed by the +* CPU for packet reception. +* +* Unserviced Packet Count +* +* The purpose of the packet counter is to count the number of packets received +* or transmitted and provide an interrupt when a specific number of packets +* have been processed by the hardware. An interrupt is generated whenever the +* counter is greater than or equal to the Packet Count Threshold. This counter +* contains an accurate count of the number of packets that the hardware has +* processed, either received or transmitted, and the software has not serviced. +* +* The packet counter allows the number of interrupts to be reduced by waiting +* to generate an interrupt until enough packets are received. For packet +* reception, packet counts of less than the number to generate an interrupt +* would not be serviced without the addition of a packet timer. This counter is +* continuously updated by the hardware, not latched to the value at the time +* the interrupt occurred. +* +* The packet counter can be used within the interrupt service routine for the +* device to reduce the number of interrupts. The interrupt service routine +* loops while performing processing for each packet which has been received or +* transmitted and decrements the counter by a specified value. At the same time, +* the hardware is possibly continuing to receive or transmit more packets such +* that the software may choose, based upon the value in the packet counter, to +* remain in the interrupt service routine rather than exiting and immediately +* returning. This feature should be used with caution as reducing the number of +* interrupts is beneficial, but unbounded interrupt processing is not desirable. +* +* Since the hardware may be incrementing the packet counter simultaneously +* with the software decrementing the counter, there is a need for atomic +* operations. The hardware ensures that the operation is atomic such that +* simultaneous accesses are properly handled. +* +* Packet Wait Bound +* +* The purpose of the packet wait bound is to augment the unserviced packet +* count. Whenever there is no pending interrupt for the channel and the +* unserviced packet count is non-zero, a timer starts counting timeout at the +* value contained the the packet wait bound register.  If the timeout is +* reached, an interrupt is generated such that the software may service the +* data which was buffered. +* +* NOTES: +* +* Special Test Conditions: +* +* The scatter gather list processing must be thoroughly tested if changes are +* made.	 Testing should include putting and committing single descriptors and +* putting multiple descriptors followed by a single commit.  There are some +* conditions in the code which handle the exception conditions. +* +* The Put Pointer points to the next location in the descriptor list to copy +* in a new descriptor. The Get Pointer points to the next location in the +* list to get a descriptor from.  The Get Pointer only allows software to +* have a traverse the list after the hardware has finished processing some +* number of descriptors.  The Commit Pointer points to the descriptor in the +* list which is to be committed.  It is also used to determine that no +* descriptor is waiting to be commited (NULL).	The Last Pointer points to +* the last descriptor that was put into the list.  It typically points +* to the previous descriptor to the one pointed to by the Put Pointer. +* Comparisons are done between these pointers to determine when the following +* special conditions exist. + +* Single Put And Commit +* +* The buffer descriptor is ready to be used by the hardware so it is important +* for the descriptor to not appear to be waiting to be committed.  The commit +* pointer is reset when a commit is done indicating there are no descriptors +* waiting to be committed.  In all cases but this one, the descriptor is +* changed to cause the hardware to go to the next descriptor after processing +* this one.  But in this case, this is the last descriptor in the list such +* that it must not be changed. +* +* 3 Or More Puts And Commit +* +* A series of 3 or more puts followed by a single commit is different in that +* only the 1st descriptor put into the list is changed when the commit is done. +* This requires each put starting on the 3rd to change the previous descriptor +* so that it allows the hardware to continue to the next descriptor in the list. +* +* The 1st Put Following A Commit +* +* The commit caused the commit pointer to be NULL indicating that there are no +* descriptors waiting to be committed.	It is necessary for the next put to set +* the commit pointer so that a commit must follow the put for the hardware to +* use the descriptor. +* +* <pre> +* MODIFICATION HISTORY: +* +* Ver	Who  Date     Changes +* ----- ---- -------- ------------------------------------------------------ +* 1.00a rpm  02/03/03 Removed the XST_DMA_SG_COUNT_EXCEEDED return code +*		      from SetPktThreshold. +* </pre> +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xdma_channel.h" +#include "xbasic_types.h" +#include "xio.h" +#include "xbuf_descriptor.h" +#include "xstatus.h" + +/************************** Constant Definitions *****************************/ + +#define XDC_SWCR_SG_ENABLE_MASK 0x80000000UL	/* scatter gather enable */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/* the following macro copies selected fields of a buffer descriptor to another + * buffer descriptor, this was provided by the buffer descriptor component but + * was moved here since it is only used internally to this component and since + * it does not copy all fields + */ +#define CopyBufferDescriptor(InstancePtr, DestinationPtr)	   \ +{								   \ +    *((u32 *)DestinationPtr + XBD_CONTROL_OFFSET) =	       \ +	*((u32 *)InstancePtr + XBD_CONTROL_OFFSET);	       \ +    *((u32 *)DestinationPtr + XBD_SOURCE_OFFSET) =	       \ +	*((u32 *)InstancePtr + XBD_SOURCE_OFFSET);	       \ +    *((u32 *)DestinationPtr + XBD_DESTINATION_OFFSET) =	       \ +	*((u32 *)InstancePtr + XBD_DESTINATION_OFFSET);	       \ +    *((u32 *)DestinationPtr + XBD_LENGTH_OFFSET) =	       \ +	*((u32 *)InstancePtr + XBD_LENGTH_OFFSET);	       \ +    *((u32 *)DestinationPtr + XBD_STATUS_OFFSET) =	       \ +	*((u32 *)InstancePtr + XBD_STATUS_OFFSET);	       \ +    *((u32 *)DestinationPtr + XBD_DEVICE_STATUS_OFFSET) =      \ +	*((u32 *)InstancePtr + XBD_DEVICE_STATUS_OFFSET);      \ +    *((u32 *)DestinationPtr + XBD_ID_OFFSET) =		       \ +	*((u32 *)InstancePtr + XBD_ID_OFFSET);		       \ +    *((u32 *)DestinationPtr + XBD_FLAGS_OFFSET) =	       \ +	*((u32 *)InstancePtr + XBD_FLAGS_OFFSET);	       \ +    *((u32 *)DestinationPtr + XBD_RQSTED_LENGTH_OFFSET) =      \ +	*((u32 *)InstancePtr + XBD_RQSTED_LENGTH_OFFSET);      \ +} + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_SgStart +* +* DESCRIPTION: +* +* This function starts a scatter gather operation for a scatter gather +* DMA channel.	The first buffer descriptor in the buffer descriptor list +* will be started with the scatter gather operation.  A scatter gather list +* should have previously been created for the DMA channel and buffer +* descriptors put into the scatter gather list such that there are scatter +* operations ready to be performed. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA +* channel should be configured to use scatter gather in order for this function +* to be called. +* +* RETURN VALUE: +* +* A status containing XST_SUCCESS if scatter gather was started successfully +* for the DMA channel. +* +* A value of XST_DMA_SG_NO_LIST indicates the scatter gather list has not +* been created. +* +* A value of XST_DMA_SG_LIST_EMPTY indicates scatter gather was not started +* because the scatter gather list of the DMA channel does not contain any +* buffer descriptors that are ready to be processed by the hardware. +* +* A value of XST_DMA_SG_IS_STARTED indicates scatter gather was not started +* because the scatter gather was not stopped, but was already started. +* +* A value of XST_DMA_SG_BD_NOT_COMMITTED indicates the buffer descriptor of +* scatter gather list which was to be started is not committed to the list. +* This status is more likely if this function is being called from an ISR +* and non-ISR processing is putting descriptors into the list. +* +* A value of XST_DMA_SG_NO_DATA indicates that the buffer descriptor of the +* scatter gather list which was to be started had already been used by the +* hardware for a DMA transfer that has been completed. +* +* NOTES: +* +* It is the responsibility of the caller to get all the buffer descriptors +* after performing a stop operation and before performing a start operation. +* If buffer descriptors are not retrieved between stop and start operations, +* buffer descriptors may be processed by the hardware more than once. +* +******************************************************************************/ +XStatus +XDmaChannel_SgStart(XDmaChannel * InstancePtr) +{ +	u32 Register; +	XBufDescriptor *LastDescriptorPtr; + +	/* assert to verify input arguments */ + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* if a scatter gather list has not been created yet, return a status */ + +	if (InstancePtr->TotalDescriptorCount == 0) { +		return XST_DMA_SG_NO_LIST; +	} + +	/* if the scatter gather list exists but is empty then return a status */ + +	if (XDmaChannel_IsSgListEmpty(InstancePtr)) { +		return XST_DMA_SG_LIST_EMPTY; +	} + +	/* if scatter gather is busy for the DMA channel, return a status because +	 * restarting it could lose data +	 */ + +	Register = XIo_In32(InstancePtr->RegBaseAddress + XDC_DMAS_REG_OFFSET); +	if (Register & XDC_DMASR_SG_BUSY_MASK) { +		return XST_DMA_SG_IS_STARTED; +	} + +	/* get the address of the last buffer descriptor which the DMA hardware +	 * finished processing +	 */ +	LastDescriptorPtr = +	    (XBufDescriptor *) XIo_In32(InstancePtr->RegBaseAddress + +					XDC_BDA_REG_OFFSET); + +	/* setup the first buffer descriptor that will be sent when the scatter +	 * gather channel is enabled, this is only necessary one time since +	 * the BDA register of the channel maintains the last buffer descriptor +	 * processed +	 */ +	if (LastDescriptorPtr == NULL) { +		XIo_Out32(InstancePtr->RegBaseAddress + XDC_BDA_REG_OFFSET, +			  (u32) InstancePtr->GetPtr); +	} else { +		XBufDescriptor *NextDescriptorPtr; + +		/* get the next descriptor to be started, if the status indicates it +		 * hasn't already been used by the h/w, then it's OK to start it, +		 * s/w sets the status of each descriptor to busy and then h/w clears +		 * the busy when it is complete +		 */ +		NextDescriptorPtr = +		    XBufDescriptor_GetNextPtr(LastDescriptorPtr); + +		if ((XBufDescriptor_GetStatus(NextDescriptorPtr) & +		     XDC_DMASR_BUSY_MASK) == 0) { +			return XST_DMA_SG_NO_DATA; +		} +		/* don't start the DMA SG channel if the descriptor to be processed +		 * by h/w is to be committed by the s/w, this function can be called +		 * such that it interrupts a thread that was putting into the list +		 */ +		if (NextDescriptorPtr == InstancePtr->CommitPtr) { +			return XST_DMA_SG_BD_NOT_COMMITTED; +		} +	} + +	/* start the scatter gather operation by clearing the stop bit in the +	 * control register and setting the enable bit in the s/w control register, +	 * both of these are necessary to cause it to start, right now the order of +	 * these statements is important, the software control register should be +	 * set 1st.  The other order can cause the CPU to have a loss of sync +	 * because it cannot read/write the register while the DMA operation is +	 * running +	 */ + +	Register = XIo_In32(InstancePtr->RegBaseAddress + XDC_SWCR_REG_OFFSET); + +	XIo_Out32(InstancePtr->RegBaseAddress + XDC_SWCR_REG_OFFSET, +		  Register | XDC_SWCR_SG_ENABLE_MASK); + +	Register = XIo_In32(InstancePtr->RegBaseAddress + XDC_DMAC_REG_OFFSET); + +	XIo_Out32(InstancePtr->RegBaseAddress + XDC_DMAC_REG_OFFSET, +		  Register & ~XDC_DMACR_SG_DISABLE_MASK); + +	/* indicate the DMA channel scatter gather operation was started +	 * successfully +	 */ +	return XST_SUCCESS; +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_SgStop +* +* DESCRIPTION: +* +* This function stops a scatter gather operation for a scatter gather +* DMA channel. This function starts the process of stopping a scatter +* gather operation that is in progress and waits for the stop to be completed. +* Since it waits for the operation to stopped before returning, this function +* could take an amount of time relative to the size of the DMA scatter gather +* operation which is in progress.  The scatter gather list of the DMA channel +* is not modified by this function such that starting the scatter gather +* channel after stopping it will cause it to resume.  This operation is +* considered to be a graceful stop in that the scatter gather operation +* completes the current buffer descriptor before stopping. +* +* If the interrupt is enabled, an interrupt will be generated when the +* operation is stopped and the caller is responsible for handling the +* interrupt. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA +* channel should be configured to use scatter gather in order for this function +* to be called. +* +* BufDescriptorPtr is also a return value which contains a pointer to the +* buffer descriptor which the scatter gather operation completed when it +* was stopped. +* +* RETURN VALUE: +* +* A status containing XST_SUCCESS if scatter gather was stopped successfully +* for the DMA channel. +* +* A value of XST_DMA_SG_IS_STOPPED indicates scatter gather was not stoppped +* because the scatter gather is not started, but was already stopped. +* +* BufDescriptorPtr contains a pointer to the buffer descriptor which was +* completed when the operation was stopped. +* +* NOTES: +* +* This function implements a loop which polls the hardware for an infinite +* amount of time. If the hardware is not operating correctly, this function +* may never return. +* +******************************************************************************/ +XStatus +XDmaChannel_SgStop(XDmaChannel * InstancePtr, +		   XBufDescriptor ** BufDescriptorPtr) +{ +	u32 Register; + +	/* assert to verify input arguments */ + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(BufDescriptorPtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* get the contents of the software control register, if scatter gather is not +	 * enabled (started), then return a status because the disable acknowledge +	 * would not be generated +	 */ +	Register = XIo_In32(InstancePtr->RegBaseAddress + XDC_SWCR_REG_OFFSET); + +	if ((Register & XDC_SWCR_SG_ENABLE_MASK) == 0) { +		return XST_DMA_SG_IS_STOPPED; +	} + +	/* Ensure the interrupt status for the scatter gather is cleared such +	 * that this function will wait til the disable has occurred, writing +	 * a 1 to only that bit in the register will clear only it +	 */ +	XIo_Out32(InstancePtr->RegBaseAddress + XDC_IS_REG_OFFSET, +		  XDC_IXR_SG_DISABLE_ACK_MASK); + +	/* disable scatter gather by writing to the software control register +	 * without modifying any other bits of the register +	 */ +	XIo_Out32(InstancePtr->RegBaseAddress + XDC_SWCR_REG_OFFSET, +		  Register & ~XDC_SWCR_SG_ENABLE_MASK); + +	/* scatter gather does not disable immediately, but after the current +	 * buffer descriptor is complete, so wait for the DMA channel to indicate +	 * the disable is complete +	 */ +	do { +		Register = +		    XIo_In32(InstancePtr->RegBaseAddress + XDC_IS_REG_OFFSET); +	} while ((Register & XDC_IXR_SG_DISABLE_ACK_MASK) == 0); + +	/* Ensure the interrupt status for the scatter gather disable is cleared, +	 * writing a 1 to only that bit in the register will clear only it +	 */ +	XIo_Out32(InstancePtr->RegBaseAddress + XDC_IS_REG_OFFSET, +		  XDC_IXR_SG_DISABLE_ACK_MASK); + +	/* set the specified buffer descriptor pointer to point to the buffer +	 * descriptor that the scatter gather DMA channel was processing +	 */ +	*BufDescriptorPtr = +	    (XBufDescriptor *) XIo_In32(InstancePtr->RegBaseAddress + +					XDC_BDA_REG_OFFSET); + +	return XST_SUCCESS; +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_CreateSgList +* +* DESCRIPTION: +* +* This function creates a scatter gather list in the DMA channel.  A scatter +* gather list consists of a list of buffer descriptors that are available to +* be used for scatter gather operations.  Buffer descriptors are put into the +* list to request a scatter gather operation to be performed. +* +* A number of buffer descriptors are created from the specified memory and put +* into a buffer descriptor list as empty buffer descriptors. This function must +* be called before non-empty buffer descriptors may be put into the DMA channel +* to request scatter gather operations. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA +* channel should be configured to use scatter gather in order for this function +* to be called. +* +* MemoryPtr contains a pointer to the memory which is to be used for buffer +* descriptors and must not be cached. +* +* ByteCount contains the number of bytes for the specified memory to be used +* for buffer descriptors. +* +* RETURN VALUE: +* +* A status contains XST_SUCCESS if the scatter gather list was successfully +* created. +* +* A value of XST_DMA_SG_LIST_EXISTS indicates that the scatter gather list +* was not created because the list has already been created. +* +* NOTES: +* +* None. +* +******************************************************************************/ +XStatus +XDmaChannel_CreateSgList(XDmaChannel * InstancePtr, +			 u32 * MemoryPtr, u32 ByteCount) +{ +	XBufDescriptor *BufferDescriptorPtr = (XBufDescriptor *) MemoryPtr; +	XBufDescriptor *PreviousDescriptorPtr = NULL; +	XBufDescriptor *StartOfListPtr = BufferDescriptorPtr; +	u32 UsedByteCount; + +	/* assert to verify valid input arguments, alignment for those +	 * arguments that have alignment restrictions, and at least enough +	 * memory for one buffer descriptor +	 */ +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(MemoryPtr != NULL); +	XASSERT_NONVOID(((u32) MemoryPtr & 3) == 0); +	XASSERT_NONVOID(ByteCount != 0); +	XASSERT_NONVOID(ByteCount >= sizeof (XBufDescriptor)); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* if the scatter gather list has already been created, then return +	 * with a status +	 */ +	if (InstancePtr->TotalDescriptorCount != 0) { +		return XST_DMA_SG_LIST_EXISTS; +	} + +	/* loop thru the specified memory block and create as many buffer +	 * descriptors as possible putting each into the list which is +	 * implemented as a ring buffer, make sure not to use any memory which +	 * is not large enough for a complete buffer descriptor +	 */ +	UsedByteCount = 0; +	while ((UsedByteCount + sizeof (XBufDescriptor)) <= ByteCount) { +		/* setup a pointer to the next buffer descriptor in the memory and +		 * update # of used bytes to know when all of memory is used +		 */ +		BufferDescriptorPtr = (XBufDescriptor *) ((u32) MemoryPtr + +							  UsedByteCount); + +		/* initialize the new buffer descriptor such that it doesn't contain +		 * garbage which could be used by the DMA hardware +		 */ +		XBufDescriptor_Initialize(BufferDescriptorPtr); + +		/* if this is not the first buffer descriptor to be created, +		 * then link it to the last created buffer descriptor +		 */ +		if (PreviousDescriptorPtr != NULL) { +			XBufDescriptor_SetNextPtr(PreviousDescriptorPtr, +						  BufferDescriptorPtr); +		} + +		/* always keep a pointer to the last created buffer descriptor such +		 * that they can be linked together in the ring buffer +		 */ +		PreviousDescriptorPtr = BufferDescriptorPtr; + +		/* keep a count of the number of descriptors in the list to allow +		 * error processing to be performed +		 */ +		InstancePtr->TotalDescriptorCount++; + +		UsedByteCount += sizeof (XBufDescriptor); +	} + +	/* connect the last buffer descriptor created and inserted in the list +	 * to the first such that a ring buffer is created +	 */ +	XBufDescriptor_SetNextPtr(BufferDescriptorPtr, StartOfListPtr); + +	/* initialize the ring buffer to indicate that there are no +	 * buffer descriptors in the list which point to valid data buffers +	 */ +	InstancePtr->PutPtr = BufferDescriptorPtr; +	InstancePtr->GetPtr = BufferDescriptorPtr; +	InstancePtr->CommitPtr = NULL; +	InstancePtr->LastPtr = BufferDescriptorPtr; +	InstancePtr->ActiveDescriptorCount = 0; + +	/* indicate the scatter gather list was successfully created */ + +	return XST_SUCCESS; +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_IsSgListEmpty +* +* DESCRIPTION: +* +* This function determines if the scatter gather list of a DMA channel is +* empty with regard to buffer descriptors which are pointing to buffers to be +* used for scatter gather operations. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA +* channel should be configured to use scatter gather in order for this function +* to be called. +* +* RETURN VALUE: +* +* A value of TRUE if the scatter gather list is empty, otherwise a value of +* FALSE. +* +* NOTES: +* +* None. +* +******************************************************************************/ +u32 +XDmaChannel_IsSgListEmpty(XDmaChannel * InstancePtr) +{ +	/* assert to verify valid input arguments */ + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* if the number of descriptors which are being used in the list is zero +	 * then the list is empty +	 */ +	return (InstancePtr->ActiveDescriptorCount == 0); +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_PutDescriptor +* +* DESCRIPTION: +* +* This function puts a buffer descriptor into the DMA channel scatter +* gather list. A DMA channel maintains a list of buffer descriptors which are +* to be processed.  This function puts the specified buffer descriptor +* at the next location in the list.  Note that since the list is already intact, +* the information in the parameter is copied into the list (rather than modify +* list pointers on the fly). +* +* After buffer descriptors are put into the list, they must also be committed +* by calling another function.	This allows multiple buffer descriptors which +* span a single packet to be put into the list while preventing the hardware +* from starting the first buffer descriptor of the packet. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA +* channel should be configured to use scatter gather in order for this function +* to be called. +* +* BufferDescriptorPtr is a pointer to the buffer descriptor to be put into +* the next available location of the scatter gather list. +* +* RETURN VALUE: +* +* A status which indicates XST_SUCCESS if the buffer descriptor was +* successfully put into the scatter gather list. +* +* A value of XST_DMA_SG_NO_LIST indicates the scatter gather list has not +* been created. +* +* A value of XST_DMA_SG_LIST_FULL indicates the buffer descriptor was not +* put into the list because the list was full. +* +* A value of XST_DMA_SG_BD_LOCKED indicates the buffer descriptor was not +* put into the list because the buffer descriptor in the list which is to +* be overwritten was locked.  A locked buffer descriptor indicates the higher +* layered software is still using the buffer descriptor. +* +* NOTES: +* +* It is necessary to create a scatter gather list for a DMA channel before +* putting buffer descriptors into it. +* +******************************************************************************/ +XStatus +XDmaChannel_PutDescriptor(XDmaChannel * InstancePtr, +			  XBufDescriptor * BufferDescriptorPtr) +{ +	u32 Control; + +	/* assert to verify valid input arguments and alignment for those +	 * arguments that have alignment restrictions +	 */ +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(BufferDescriptorPtr != NULL); +	XASSERT_NONVOID(((u32) BufferDescriptorPtr & 3) == 0); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* if a scatter gather list has not been created yet, return a status */ + +	if (InstancePtr->TotalDescriptorCount == 0) { +		return XST_DMA_SG_NO_LIST; +	} + +	/* if the list is full because all descriptors are pointing to valid +	 * buffers, then indicate an error, this code assumes no list or an +	 * empty list is detected above +	 */ +	if (InstancePtr->ActiveDescriptorCount == +	    InstancePtr->TotalDescriptorCount) { +		return XST_DMA_SG_LIST_FULL; +	} + +	/* if the buffer descriptor in the list which is to be overwritten is +	 * locked, then don't overwrite it and return a status +	 */ +	if (XBufDescriptor_IsLocked(InstancePtr->PutPtr)) { +		return XST_DMA_SG_BD_LOCKED; +	} + +	/* set the scatter gather stop bit in the control word of the descriptor +	 * to cause the h/w to stop after it processes this descriptor since it +	 * will be the last in the list +	 */ +	Control = XBufDescriptor_GetControl(BufferDescriptorPtr); +	XBufDescriptor_SetControl(BufferDescriptorPtr, +				  Control | XDC_DMACR_SG_DISABLE_MASK); + +	/* set both statuses in the descriptor so we tell if they are updated with +	 * the status of the transfer, the hardware should change the busy in the +	 * DMA status to be false when it completes +	 */ +	XBufDescriptor_SetStatus(BufferDescriptorPtr, XDC_DMASR_BUSY_MASK); +	XBufDescriptor_SetDeviceStatus(BufferDescriptorPtr, 0); + +	/* copy the descriptor into the next position in the list so it's ready to +	 * be used by the h/w, this assumes the descriptor in the list prior to this +	 * one still has the stop bit in the control word set such that the h/w +	 * use this one yet +	 */ +	CopyBufferDescriptor(BufferDescriptorPtr, InstancePtr->PutPtr); + +	/* only the last in the list and the one to be committed have scatter gather +	 * disabled in the control word, a commit requires only one descriptor +	 * to be changed, when # of descriptors to commit > 2 all others except the +	 * 1st and last have scatter gather enabled +	 */ +	if ((InstancePtr->CommitPtr != InstancePtr->LastPtr) && +	    (InstancePtr->CommitPtr != NULL)) { +		Control = XBufDescriptor_GetControl(InstancePtr->LastPtr); +		XBufDescriptor_SetControl(InstancePtr->LastPtr, +					  Control & ~XDC_DMACR_SG_DISABLE_MASK); +	} + +	/* update the list data based upon putting a descriptor into the list, +	 * these operations must be last +	 */ +	InstancePtr->ActiveDescriptorCount++; + +	/* only update the commit pointer if it is not already active, this allows +	 * it to be deactivated after every commit such that a single descriptor +	 * which is committed does not appear to be waiting to be committed +	 */ +	if (InstancePtr->CommitPtr == NULL) { +		InstancePtr->CommitPtr = InstancePtr->LastPtr; +	} + +	/* these updates MUST BE LAST after the commit pointer update in order for +	 * the commit pointer to track the correct descriptor to be committed +	 */ +	InstancePtr->LastPtr = InstancePtr->PutPtr; +	InstancePtr->PutPtr = XBufDescriptor_GetNextPtr(InstancePtr->PutPtr); + +	return XST_SUCCESS; +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_CommitPuts +* +* DESCRIPTION: +* +* This function commits the buffer descriptors which have been put into the +* scatter list for the DMA channel since the last commit operation was +* performed.  This enables the calling functions to put several buffer +* descriptors into the list (e.g.,a packet's worth) before allowing the scatter +* gather operations to start.  This prevents the DMA channel hardware from +* starting to use the buffer descriptors in the list before they are ready +* to be used (multiple buffer descriptors for a single packet). +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA +* channel should be configured to use scatter gather in order for this function +* to be called. +* +* RETURN VALUE: +* +* A status indicating XST_SUCCESS if the buffer descriptors of the list were +* successfully committed. +* +* A value of XST_DMA_SG_NOTHING_TO_COMMIT indicates that the buffer descriptors +* were not committed because there was nothing to commit in the list.  All the +* buffer descriptors which are in the list are commited. +* +* NOTES: +* +* None. +* +******************************************************************************/ +XStatus +XDmaChannel_CommitPuts(XDmaChannel * InstancePtr) +{ +	/* assert to verify input arguments */ + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* if the buffer descriptor to be committed is already committed or +	 * the list is empty (none have been put in), then indicate an error +	 */ +	if ((InstancePtr->CommitPtr == NULL) || +	    XDmaChannel_IsSgListEmpty(InstancePtr)) { +		return XST_DMA_SG_NOTHING_TO_COMMIT; +	} + +	/* last descriptor in the list must have scatter gather disabled so the end +	 * of the list is hit by h/w, if descriptor to commit is not last in list, +	 * commit descriptors by enabling scatter gather in the descriptor +	 */ +	if (InstancePtr->CommitPtr != InstancePtr->LastPtr) { +		u32 Control; + +		Control = XBufDescriptor_GetControl(InstancePtr->CommitPtr); +		XBufDescriptor_SetControl(InstancePtr->CommitPtr, Control & +					  ~XDC_DMACR_SG_DISABLE_MASK); +	} +	/* Update the commit pointer to indicate that there is nothing to be +	 * committed, this state is used by start processing to know that the +	 * buffer descriptor to start is not waiting to be committed +	 */ +	InstancePtr->CommitPtr = NULL; + +	return XST_SUCCESS; +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_GetDescriptor +* +* DESCRIPTION: +* +* This function gets a buffer descriptor from the scatter gather list of the +* DMA channel. The buffer descriptor is retrieved from the scatter gather list +* and the scatter gather list is updated to not include the retrieved buffer +* descriptor.  This is typically done after a scatter gather operation +* completes indicating that a data buffer has been successfully sent or data +* has been received into the data buffer. The purpose of this function is to +* allow the device using the scatter gather operation to get the results of the +* operation. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA +* channel should be configured to use scatter gather in order for this function +* to be called. +* +* BufDescriptorPtr is a pointer to a pointer to the buffer descriptor which +* was retrieved from the list.	The buffer descriptor is not really removed +* from the list, but it is changed to a state such that the hardware will not +* use it again until it is put into the scatter gather list of the DMA channel. +* +* RETURN VALUE: +* +* A status indicating XST_SUCCESS if a buffer descriptor was retrieved from +* the scatter gather list of the DMA channel. +* +* A value of XST_DMA_SG_NO_LIST indicates the scatter gather list has not +* been created. +* +* A value of XST_DMA_SG_LIST_EMPTY indicates no buffer descriptor was +* retrieved from the list because there are no buffer descriptors to be +* processed in the list. +* +* BufDescriptorPtr is updated to point to the buffer descriptor which was +* retrieved from the list if the status indicates success. +* +* NOTES: +* +* None. +* +******************************************************************************/ +XStatus +XDmaChannel_GetDescriptor(XDmaChannel * InstancePtr, +			  XBufDescriptor ** BufDescriptorPtr) +{ +	u32 Control; + +	/* assert to verify input arguments */ + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(BufDescriptorPtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* if a scatter gather list has not been created yet, return a status */ + +	if (InstancePtr->TotalDescriptorCount == 0) { +		return XST_DMA_SG_NO_LIST; +	} + +	/* if the buffer descriptor list is empty, then indicate an error */ + +	if (XDmaChannel_IsSgListEmpty(InstancePtr)) { +		return XST_DMA_SG_LIST_EMPTY; +	} + +	/* retrieve the next buffer descriptor which is ready to be processed from +	 * the buffer descriptor list for the DMA channel, set the control word +	 * such that hardware will stop after the descriptor has been processed +	 */ +	Control = XBufDescriptor_GetControl(InstancePtr->GetPtr); +	XBufDescriptor_SetControl(InstancePtr->GetPtr, +				  Control | XDC_DMACR_SG_DISABLE_MASK); + +	/* set the input argument, which is also an output, to point to the +	 * buffer descriptor which is to be retrieved from the list +	 */ +	*BufDescriptorPtr = InstancePtr->GetPtr; + +	/* update the pointer of the DMA channel to reflect the buffer descriptor +	 * was retrieved from the list by setting it to the next buffer descriptor +	 * in the list and indicate one less descriptor in the list now +	 */ +	InstancePtr->GetPtr = XBufDescriptor_GetNextPtr(InstancePtr->GetPtr); +	InstancePtr->ActiveDescriptorCount--; + +	return XST_SUCCESS; +} + +/*********************** Interrupt Collescing Functions **********************/ + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_GetPktCount +* +* DESCRIPTION: +* +* This function returns the value of the unserviced packet count register of +* the DMA channel.  This count represents the number of packets that have been +* sent or received by the hardware, but not processed by software. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA +* channel should be configured to use scatter gather in order for this function +* to be called. +* +* RETURN VALUE: +* +* The unserviced packet counter register contents for the DMA channel. +* +* NOTES: +* +* None. +* +******************************************************************************/ +u32 +XDmaChannel_GetPktCount(XDmaChannel * InstancePtr) +{ +	/* assert to verify input arguments */ + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* get the unserviced packet count from the register and return it */ + +	return XIo_In32(InstancePtr->RegBaseAddress + XDC_UPC_REG_OFFSET); +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_DecrementPktCount +* +* DESCRIPTION: +* +* This function decrements the value of the unserviced packet count register. +* This informs the hardware that the software has processed a packet.  The +* unserviced packet count register may only be decremented by one in the +* hardware. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA +* channel should be configured to use scatter gather in order for this function +* to be called. +* +* RETURN VALUE: +* +* None. +* +* NOTES: +* +* None. +* +******************************************************************************/ +void +XDmaChannel_DecrementPktCount(XDmaChannel * InstancePtr) +{ +	u32 Register; + +	/* assert to verify input arguments */ + +	XASSERT_VOID(InstancePtr != NULL); +	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* if the unserviced packet count register can be decremented (rather +	 * than rolling over) decrement it by writing a 1 to the register, +	 * this is the only valid write to the register as it serves as an +	 * acknowledge that a packet was handled by the software +	 */ +	Register = XIo_In32(InstancePtr->RegBaseAddress + XDC_UPC_REG_OFFSET); +	if (Register > 0) { +		XIo_Out32(InstancePtr->RegBaseAddress + XDC_UPC_REG_OFFSET, +			  1UL); +	} +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_SetPktThreshold +* +* DESCRIPTION: +* +* This function sets the value of the packet count threshold register of the +* DMA channel.	It reflects the number of packets that must be sent or +* received before generating an interrupt.  This value helps implement +* a concept called "interrupt coalescing", which is used to reduce the number +* of interrupts from devices with high data rates. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA +* channel should be configured to use scatter gather in order for this function +* to be called. +* +* Threshold is the value that is written to the threshold register of the +* DMA channel. +* +* RETURN VALUE: +* +* A status containing XST_SUCCESS if the packet count threshold was +* successfully set. +* +* NOTES: +* +* The packet threshold could be set to larger than the number of descriptors +* allocated to the DMA channel. In this case, the wait bound will take over +* and always indicate data arrival. There was a check in this function that +* returned an error if the treshold was larger than the number of descriptors, +* but that was removed because users would then have to set the threshold +* only after they set descriptor space, which is an order dependency that +* caused confustion. +* +******************************************************************************/ +XStatus +XDmaChannel_SetPktThreshold(XDmaChannel * InstancePtr, u8 Threshold) +{ +	/* assert to verify input arguments, don't assert the threshold since +	 * it's range is unknown +	 */ +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* set the packet count threshold in the register such that an interrupt +	 * may be generated, if enabled, when the packet count threshold is +	 * reached or exceeded +	 */ +	XIo_Out32(InstancePtr->RegBaseAddress + XDC_PCT_REG_OFFSET, +		  (u32) Threshold); + +	/* indicate the packet count threshold was successfully set */ + +	return XST_SUCCESS; +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_GetPktThreshold +* +* DESCRIPTION: +* +* This function gets the value of the packet count threshold register of the +* DMA channel.	This value reflects the number of packets that must be sent or +* received before generating an interrupt.  This value helps implement a concept +* called "interrupt coalescing", which is used to reduce the number of +* interrupts from devices with high data rates. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA +* channel should be configured to use scatter gather in order for this function +* to be called. +* +* RETURN VALUE: +* +* The packet threshold register contents for the DMA channel and is a value in +* the range 0 - 1023.  A value of 0 indicates the packet wait bound timer is +* disabled. +* +* NOTES: +* +* None. +* +******************************************************************************/ +u8 +XDmaChannel_GetPktThreshold(XDmaChannel * InstancePtr) +{ +	/* assert to verify input arguments */ + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* get the packet count threshold from the register and return it, +	 * since only 8 bits are used, cast it to return only those bits */ + +	return (u8) XIo_In32(InstancePtr->RegBaseAddress + XDC_PCT_REG_OFFSET); +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_SetPktWaitBound +* +* DESCRIPTION: +* +* This function sets the value of the packet wait bound register of the +* DMA channel.	This value reflects the timer value used to trigger an +* interrupt when not enough packets have been received to reach the packet +* count threshold. +* +* The timer is in millisecond units with +/- 33% accuracy. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA +* channel should be configured to use scatter gather in order for this function +* to be called. +* +* WaitBound is the value, in milliseconds, to be stored in the wait bound +* register of the DMA channel and is a value in the range 0  - 1023.  A value +* of 0 disables the packet wait bound timer. +* +* RETURN VALUE: +* +* None. +* +* NOTES: +* +* None. +* +******************************************************************************/ +void +XDmaChannel_SetPktWaitBound(XDmaChannel * InstancePtr, u32 WaitBound) +{ +	/* assert to verify input arguments */ + +	XASSERT_VOID(InstancePtr != NULL); +	XASSERT_VOID(WaitBound < 1024); +	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* set the packet wait bound in the register such that interrupt may be +	 * generated, if enabled, when packets have not been handled for a specific +	 * amount of time +	 */ +	XIo_Out32(InstancePtr->RegBaseAddress + XDC_PWB_REG_OFFSET, WaitBound); +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_GetPktWaitBound +* +* DESCRIPTION: +* +* This function gets the value of the packet wait bound register of the +* DMA channel.	This value contains the timer value used to trigger an +* interrupt when not enough packets have been received to reach the packet +* count threshold. +* +* The timer is in millisecond units with +/- 33% accuracy. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on.  The DMA +* channel should be configured to use scatter gather in order for this function +* to be called. +* +* RETURN VALUE: +* +* The packet wait bound register contents for the DMA channel. +* +* NOTES: +* +* None. +* +******************************************************************************/ +u32 +XDmaChannel_GetPktWaitBound(XDmaChannel * InstancePtr) +{ +	/* assert to verify input arguments */ + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* get the packet wait bound from the register and return it */ + +	return XIo_In32(InstancePtr->RegBaseAddress + XDC_PWB_REG_OFFSET); +} diff --git a/board/xilinx/common/xio.h b/board/xilinx/common/xio.h new file mode 100644 index 000000000..5bb09c894 --- /dev/null +++ b/board/xilinx/common/xio.h @@ -0,0 +1,81 @@ +/* + * xio.h + * + * Defines XIo functions for Xilinx OCP in terms of Linux primitives + * + * Author: MontaVista Software, Inc. + *         source@mvista.com + * + * Copyright 2002 MontaVista Software 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. + * + *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *  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 XIO_H +#define XIO_H + +#include "xbasic_types.h" +#include <asm/io.h> + +typedef u32 XIo_Address; + +extern inline u8 +XIo_In8(XIo_Address InAddress) +{ +	return (u8) in_8((volatile unsigned char *) InAddress); +} +extern inline u16 +XIo_In16(XIo_Address InAddress) +{ +	return (u16) in_be16((volatile unsigned short *) InAddress); +} +extern inline u32 +XIo_In32(XIo_Address InAddress) +{ +	return (u32) in_be32((volatile unsigned *) InAddress); +} +extern inline void +XIo_Out8(XIo_Address OutAddress, u8 Value) +{ +	out_8((volatile unsigned char *) OutAddress, Value); +} +extern inline void +XIo_Out16(XIo_Address OutAddress, u16 Value) +{ +	out_be16((volatile unsigned short *) OutAddress, Value); +} +extern inline void +XIo_Out32(XIo_Address OutAddress, u32 Value) +{ +	out_be32((volatile unsigned *) OutAddress, Value); +} + +#define XIo_ToLittleEndian16(s,d) (*(u16*)(d) = cpu_to_le16((u16)(s))) +#define XIo_ToLittleEndian32(s,d) (*(u32*)(d) = cpu_to_le32((u32)(s))) +#define XIo_ToBigEndian16(s,d) (*(u16*)(d) = cpu_to_be16((u16)(s))) +#define XIo_ToBigEndian32(s,d) (*(u32*)(d) = cpu_to_be32((u32)(s))) + +#define XIo_FromLittleEndian16(s,d) (*(u16*)(d) = le16_to_cpu((u16)(s))) +#define XIo_FromLittleEndian32(s,d) (*(u32*)(d) = le32_to_cpu((u32)(s))) +#define XIo_FromBigEndian16(s,d) (*(u16*)(d) = be16_to_cpu((u16)(s))) +#define XIo_FromBigEndian32(s,d) (*(u32*)(d) = be32_to_cpu((u32)(s))) + +#endif				/* XIO_H */ diff --git a/board/xilinx/common/xipif_v1_23_b.h b/board/xilinx/common/xipif_v1_23_b.h new file mode 100644 index 000000000..b1520e921 --- /dev/null +++ b/board/xilinx/common/xipif_v1_23_b.h @@ -0,0 +1,763 @@ +/****************************************************************************** +* +*     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. +* +******************************************************************************/ +/****************************************************************************** +* +* FILENAME: +* +* xipif.h +* +* DESCRIPTION: +* +* 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. +* +* 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 minimize size +* +******************************************************************************/ + +#ifndef XIPIF_H			/* prevent circular inclusions */ +#define XIPIF_H			/* by using protection macros */ + +/***************************** Include Files *********************************/ +#include "xbasic_types.h" +#include "xstatus.h" +#include "xversion.h" + +/************************** Constant Definitions *****************************/ + +/* the following constants define the register offsets for the registers of the + * IPIF, there are some holes in the memory map for reserved addresses to allow + * other registers to be added and still match the memory map of the interrupt + * controller registers + */ +#define XIIF_V123B_DISR_OFFSET	   0UL	/* device interrupt status register */ +#define XIIF_V123B_DIPR_OFFSET	   4UL	/* device interrupt pending register */ +#define XIIF_V123B_DIER_OFFSET	   8UL	/* device interrupt enable register */ +#define XIIF_V123B_DIIR_OFFSET	   24UL /* device interrupt ID register */ +#define XIIF_V123B_DGIER_OFFSET	   28UL /* device global interrupt enable reg */ +#define XIIF_V123B_IISR_OFFSET	   32UL /* IP interrupt status register */ +#define XIIF_V123B_IIER_OFFSET	   40UL /* IP interrupt enable register */ +#define XIIF_V123B_RESETR_OFFSET   64UL /* reset register */ + +#define XIIF_V123B_RESET_MASK		  0xAUL + +/* the following constant is used for the device global interrupt enable + * register, to enable all interrupts for the device, this is the only bit + * in the register + */ +#define XIIF_V123B_GINTR_ENABLE_MASK	  0x80000000UL + +/* the following constants contain the masks to identify each internal IPIF + * condition in the device registers of the IPIF, interrupts are assigned + * in the register from LSB to the MSB + */ +#define XIIF_V123B_ERROR_MASK		  1UL	/* LSB of the register */ + +/* The following constants contain interrupt IDs which identify each internal + * IPIF condition, this value must correlate with the mask constant for the + * error + */ +#define XIIF_V123B_ERROR_INTERRUPT_ID	  0	/* interrupt bit #, (LSB = 0) */ +#define XIIF_V123B_NO_INTERRUPT_ID	  128	/* no interrupts are pending */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************** +* +* MACRO: +* +* XIIF_V123B_RESET +* +* DESCRIPTION: +* +* Reset the IPIF component and hardware.  This is a destructive operation that +* could cause the loss of data since resetting the IPIF of a device also +* resets the device using the IPIF and any blocks, such as FIFOs or DMA +* channels, within the IPIF.  All registers of the IPIF will contain their +* reset value when this function returns. +* +* ARGUMENTS: +* +* RegBaseAddress contains the base address of the IPIF registers. +* +* RETURN VALUE: +* +* None. +* +* NOTES: +* +* None. +* +******************************************************************************/ + +/* the following constant is used in the reset register to cause the IPIF to + * reset + */ +#define XIIF_V123B_RESET(RegBaseAddress) \ +    XIo_Out32(RegBaseAddress + XIIF_V123B_RESETR_OFFSET, XIIF_V123B_RESET_MASK) + +/****************************************************************************** +* +* MACRO: +* +* XIIF_V123B_WRITE_DISR +* +* DESCRIPTION: +* +* This function sets the device interrupt status register to the value. +* This register indicates the status of interrupt sources for a device +* which contains the IPIF.  The status is independent of whether interrupts +* are enabled and could be used for polling a device at a higher level rather +* than a more detailed level. +* +* Each bit of the register correlates to a specific interrupt source within the +* device which contains the IPIF.  With the exception of some internal IPIF +* conditions, the contents of this register are not latched but indicate +* the live status of the interrupt sources within the device.  Writing any of +* the non-latched bits of the register will have no effect on the register. +* +* For the latched bits of this register only, setting a bit which is zero +* within this register causes an interrupt to generated.  The device global +* interrupt enable register and the device interrupt enable register must be set +* appropriately to allow an interrupt to be passed out of the device. The +* interrupt is cleared by writing to this register with the bits to be +* cleared set to a one and all others to zero.	This register implements a +* toggle on write functionality meaning any bits which are set in the value +* written cause the bits in the register to change to the opposite state. +* +* This function writes the specified value to the register such that +* some bits may be set and others cleared.  It is the caller's responsibility +* to get the value of the register prior to setting the value to prevent a +* destructive behavior. +* +* ARGUMENTS: +* +* RegBaseAddress contains the base address of the IPIF registers. +* +* Status contains the value to be written to the interrupt status register of +* the device.  The only bits which can be written are the latched bits which +* contain the internal IPIF conditions.	 The following values may be used to +* set the status register or clear an interrupt condition. +* +*   XIIF_V123B_ERROR_MASK     Indicates a device error in the IPIF +* +* RETURN VALUE: +* +* None. +* +* NOTES: +* +* None. +* +******************************************************************************/ +#define XIIF_V123B_WRITE_DISR(RegBaseAddress, Status) \ +    XIo_Out32((RegBaseAddress) + XIIF_V123B_DISR_OFFSET, (Status)) + +/****************************************************************************** +* +* MACRO: +* +* XIIF_V123B_READ_DISR +* +* DESCRIPTION: +* +* This function gets the device interrupt status register contents. +* This register indicates the status of interrupt sources for a device +* which contains the IPIF.  The status is independent of whether interrupts +* are enabled and could be used for polling a device at a higher level. +* +* Each bit of the register correlates to a specific interrupt source within the +* device which contains the IPIF.  With the exception of some internal IPIF +* conditions, the contents of this register are not latched but indicate +* the live status of the interrupt sources within the device. +* +* For only the latched bits of this register, the interrupt may be cleared by +* writing to these bits in the status register. +* +* ARGUMENTS: +* +* RegBaseAddress contains the base address of the IPIF registers. +* +* RETURN VALUE: +* +* A status which contains the value read from the interrupt status register of +* the device. The bit definitions are specific to the device with +* the exception of the latched internal IPIF condition bits. The following +* values may be used to detect internal IPIF conditions in the status. +* +*   XIIF_V123B_ERROR_MASK     Indicates a device error in the IPIF +* +* NOTES: +* +* None. +* +******************************************************************************/ +#define XIIF_V123B_READ_DISR(RegBaseAddress) \ +    XIo_In32((RegBaseAddress) + XIIF_V123B_DISR_OFFSET) + +/****************************************************************************** +* +* MACRO: +* +* XIIF_V123B_WRITE_DIER +* +* DESCRIPTION: +* +* This function sets the device interrupt enable register contents. +* This register controls which interrupt sources of the device are allowed to +* generate an interrupt.  The device global interrupt enable register must also +* be set appropriately for an interrupt to be passed out of the device. +* +* Each bit of the register correlates to a specific interrupt source within the +* device which contains the IPIF.  Setting a bit in this register enables that +* interrupt source to generate an interrupt.  Clearing a bit in this register +* disables interrupt generation for that interrupt source. +* +* This function writes only the specified value to the register such that +* some interrupts source may be enabled and others disabled.  It is the +* caller's responsibility to get the value of the interrupt enable register +* prior to setting the value to prevent an destructive behavior. +* +* An interrupt source may not be enabled to generate an interrupt, but can +* still be polled in the interrupt status register. +* +* ARGUMENTS: +* +* RegBaseAddress contains the base address of the IPIF registers. +* +* Enable contains the value to be written to the interrupt enable register +* of the device.  The bit definitions are specific to the device with +* the exception of the internal IPIF conditions. The following +* values may be used to enable the internal IPIF conditions interrupts. +* +*   XIIF_V123B_ERROR_MASK     Indicates a device error in the IPIF +* +* RETURN VALUE: +* +* None. +* +* NOTES: +* +* Signature: u32 XIIF_V123B_WRITE_DIER(u32 RegBaseAddress, +*					  u32 Enable) +* +******************************************************************************/ +#define XIIF_V123B_WRITE_DIER(RegBaseAddress, Enable) \ +    XIo_Out32((RegBaseAddress) + XIIF_V123B_DIER_OFFSET, (Enable)) + +/****************************************************************************** +* +* MACRO: +* +* XIIF_V123B_READ_DIER +* +* DESCRIPTION: +* +* This function gets the device interrupt enable register contents. +* This register controls which interrupt sources of the device +* are allowed to generate an interrupt.	 The device global interrupt enable +* register and the device interrupt enable register must also be set +* appropriately for an interrupt to be passed out of the device. +* +* Each bit of the register correlates to a specific interrupt source within the +* device which contains the IPIF.  Setting a bit in this register enables that +* interrupt source to generate an interrupt if the global enable is set +* appropriately.  Clearing a bit in this register disables interrupt generation +* for that interrupt source regardless of the global interrupt enable. +* +* ARGUMENTS: +* +* RegBaseAddress contains the base address of the IPIF registers. +* +* RETURN VALUE: +* +* The value read from the interrupt enable register of the device.  The bit +* definitions are specific to the device with the exception of the internal +* IPIF conditions. The following values may be used to determine from the +* value if the internal IPIF conditions interrupts are enabled. +* +*   XIIF_V123B_ERROR_MASK     Indicates a device error in the IPIF +* +* NOTES: +* +* None. +* +******************************************************************************/ +#define XIIF_V123B_READ_DIER(RegBaseAddress) \ +    XIo_In32((RegBaseAddress) + XIIF_V123B_DIER_OFFSET) + +/****************************************************************************** +* +* MACRO: +* +* XIIF_V123B_READ_DIPR +* +* DESCRIPTION: +* +* This function gets the device interrupt pending register contents. +* This register indicates the pending interrupt sources, those that are waiting +* to be serviced by the software, for a device which contains the IPIF. +* An interrupt must be enabled in the interrupt enable register of the IPIF to +* be pending. +* +* Each bit of the register correlates to a specific interrupt source within the +* the device which contains the IPIF.  With the exception of some internal IPIF +* conditions, the contents of this register are not latched since the condition +* is latched in the IP interrupt status register, by an internal block of the +* IPIF such as a FIFO or DMA channel, or by the IP of the device.  This register +* is read only and is not latched, but it is necessary to acknowledge (clear) +* the interrupt condition by performing the appropriate processing for the IP +* or block within the IPIF. +* +* This register can be thought of as the contents of the interrupt status +* register ANDed with the contents of the interrupt enable register. +* +* ARGUMENTS: +* +* RegBaseAddress contains the base address of the IPIF registers. +* +* RETURN VALUE: +* +* The value read from the interrupt pending register of the device.  The bit +* definitions are specific to the device with the exception of the latched +* internal IPIF condition bits. The following values may be used to detect +* internal IPIF conditions in the value. +* +*   XIIF_V123B_ERROR_MASK     Indicates a device error in the IPIF +* +* NOTES: +* +* None. +* +******************************************************************************/ +#define XIIF_V123B_READ_DIPR(RegBaseAddress) \ +    XIo_In32((RegBaseAddress) + XIIF_V123B_DIPR_OFFSET) + +/****************************************************************************** +* +* MACRO: +* +* XIIF_V123B_READ_DIIR +* +* DESCRIPTION: +* +* This function gets the device interrupt ID for the highest priority interrupt +* which is pending from the interrupt ID register. This function provides +* priority resolution such that faster interrupt processing is possible. +* Without priority resolution, it is necessary for the software to read the +* interrupt pending register and then check each interrupt source to determine +* if an interrupt is pending.  Priority resolution becomes more important as the +* number of interrupt sources becomes larger. +* +* Interrupt priorities are based upon the bit position of the interrupt in the +* interrupt pending register with bit 0 being the highest priority. The +* interrupt ID is the priority of the interrupt, 0 - 31, with 0 being the +* highest priority. The interrupt ID register is live rather than latched such +* that multiple calls to this function may not yield the same results.	A +* special value, outside of the interrupt priority range of 0 - 31, is +* contained in the register which indicates that no interrupt is pending.  This +* may be useful for allowing software to continue processing interrupts in a +* loop until there are no longer any interrupts pending. +* +* The interrupt ID is designed to allow a function pointer table to be used +* in the software such that the interrupt ID is used as an index into that +* table.  The function pointer table could contain an instance pointer, such +* as to DMA channel, and a function pointer to the function which handles +* that interrupt.  This design requires the interrupt processing of the device +* driver to be partitioned into smaller more granular pieces based upon +* hardware used by the device, such as DMA channels and FIFOs. +* +* It is not mandatory that this function be used by the device driver software. +* It may choose to read the pending register and resolve the pending interrupt +* priorities on it's own. +* +* ARGUMENTS: +* +* RegBaseAddress contains the base address of the IPIF registers. +* +* RETURN VALUE: +* +* An interrupt ID, 0 - 31, which identifies the highest priority interrupt +* which is pending.  A value of XIIF_NO_INTERRUPT_ID indicates that there is +* no interrupt pending. The following values may be used to identify the +* interrupt ID for the internal IPIF interrupts. +* +*   XIIF_V123B_ERROR_INTERRUPT_ID     Indicates a device error in the IPIF +* +* NOTES: +* +* None. +* +******************************************************************************/ +#define XIIF_V123B_READ_DIIR(RegBaseAddress) \ +    XIo_In32((RegBaseAddress) + XIIF_V123B_DIIR_OFFSET) + +/****************************************************************************** +* +* MACRO: +* +* XIIF_V123B_GLOBAL_INTR_DISABLE +* +* DESCRIPTION: +* +* This function disables all interrupts for the device by writing to the global +* interrupt enable register.  This register provides the ability to disable +* interrupts without any modifications to the interrupt enable register such +* that it is minimal effort to restore the interrupts to the previous enabled +* state.  The corresponding function, XIpIf_GlobalIntrEnable, is provided to +* restore the interrupts to the previous enabled state.	 This function is +* designed to be used in critical sections of device drivers such that it is +* not necessary to disable other device interrupts. +* +* ARGUMENTS: +* +* RegBaseAddress contains the base address of the IPIF registers. +* +* RETURN VALUE: +* +* None. +* +* NOTES: +* +* None. +* +******************************************************************************/ +#define XIIF_V123B_GINTR_DISABLE(RegBaseAddress) \ +    XIo_Out32((RegBaseAddress) + XIIF_V123B_DGIER_OFFSET, 0) + +/****************************************************************************** +* +* MACRO: +* +* XIIF_V123B_GINTR_ENABLE +* +* DESCRIPTION: +* +* This function writes to the global interrupt enable register to enable +* interrupts from the device.  This register provides the ability to enable +* interrupts without any modifications to the interrupt enable register such +* that it is minimal effort to restore the interrupts to the previous enabled +* state.  This function does not enable individual interrupts as the interrupt +* enable register must be set appropriately.  This function is designed to be +* used in critical sections of device drivers such that it is not necessary to +* disable other device interrupts. +* +* ARGUMENTS: +* +* RegBaseAddress contains the base address of the IPIF registers. +* +* RETURN VALUE: +* +* None. +* +* NOTES: +* +* None. +* +******************************************************************************/ +#define XIIF_V123B_GINTR_ENABLE(RegBaseAddress)		  \ +    XIo_Out32((RegBaseAddress) + XIIF_V123B_DGIER_OFFSET, \ +	       XIIF_V123B_GINTR_ENABLE_MASK) + +/****************************************************************************** +* +* MACRO: +* +* XIIF_V123B_IS_GINTR_ENABLED +* +* DESCRIPTION: +* +* This function determines if interrupts are enabled at the global level by +* reading the gloabl interrupt register. This register provides the ability to +* disable interrupts without any modifications to the interrupt enable register +* such that it is minimal effort to restore the interrupts to the previous +* enabled state. +* +* ARGUMENTS: +* +* RegBaseAddress contains the base address of the IPIF registers. +* +* RETURN VALUE: +* +* TRUE if interrupts are enabled for the IPIF, FALSE otherwise. +* +* NOTES: +* +* None. +* +******************************************************************************/ +#define XIIF_V123B_IS_GINTR_ENABLED(RegBaseAddress)		\ +    (XIo_In32((RegBaseAddress) + XIIF_V123B_DGIER_OFFSET) ==	\ +	      XIIF_V123B_GINTR_ENABLE_MASK) + +/****************************************************************************** +* +* MACRO: +* +* XIIF_V123B_WRITE_IISR +* +* DESCRIPTION: +* +* This function sets the IP interrupt status register to the specified value. +* This register indicates the status of interrupt sources for the IP of the +* device.  The IP is defined as the part of the device that connects to the +* IPIF.	 The status is independent of whether interrupts are enabled such that +* the status register may also be polled when interrupts are not enabled. +* +* Each bit of the register correlates to a specific interrupt source within the +* IP.  All bits of this register are latched. Setting a bit which is zero +* within this register causes an interrupt to be generated.  The device global +* interrupt enable register and the device interrupt enable register must be set +* appropriately to allow an interrupt to be passed out of the device. The +* interrupt is cleared by writing to this register with the bits to be +* cleared set to a one and all others to zero.	This register implements a +* toggle on write functionality meaning any bits which are set in the value +* written cause the bits in the register to change to the opposite state. +* +* This function writes only the specified value to the register such that +* some status bits may be set and others cleared.  It is the caller's +* responsibility to get the value of the register prior to setting the value +* to prevent an destructive behavior. +* +* ARGUMENTS: +* +* RegBaseAddress contains the base address of the IPIF registers. +* +* Status contains the value to be written to the IP interrupt status +* register.  The bit definitions are specific to the device IP. +* +* RETURN VALUE: +* +* None. +* +* NOTES: +* +* None. +* +******************************************************************************/ +#define XIIF_V123B_WRITE_IISR(RegBaseAddress, Status) \ +    XIo_Out32((RegBaseAddress) + XIIF_V123B_IISR_OFFSET, (Status)) + +/****************************************************************************** +* +* MACRO: +* +* XIIF_V123B_READ_IISR +* +* DESCRIPTION: +* +* This function gets the contents of the IP interrupt status register. +* This register indicates the status of interrupt sources for the IP of the +* device.  The IP is defined as the part of the device that connects to the +* IPIF. The status is independent of whether interrupts are enabled such +* that the status register may also be polled when interrupts are not enabled. +* +* Each bit of the register correlates to a specific interrupt source within the +* device.  All bits of this register are latched.  Writing a 1 to a bit within +* this register causes an interrupt to be generated if enabled in the interrupt +* enable register and the global interrupt enable is set.  Since the status is +* latched, each status bit must be acknowledged in order for the bit in the +* status register to be updated.  Each bit can be acknowledged by writing a +* 0 to the bit in the status register. + +* ARGUMENTS: +* +* RegBaseAddress contains the base address of the IPIF registers. +* +* RETURN VALUE: +* +* A status which contains the value read from the IP interrupt status register. +* The bit definitions are specific to the device IP. +* +* NOTES: +* +* None. +* +******************************************************************************/ +#define XIIF_V123B_READ_IISR(RegBaseAddress) \ +    XIo_In32((RegBaseAddress) + XIIF_V123B_IISR_OFFSET) + +/****************************************************************************** +* +* MACRO: +* +* XIIF_V123B_WRITE_IIER +* +* DESCRIPTION: +* +* This function sets the IP interrupt enable register contents.	 This register +* controls which interrupt sources of the IP are allowed to generate an +* interrupt.  The global interrupt enable register and the device interrupt +* enable register must also be set appropriately for an interrupt to be +* passed out of the device containing the IPIF and the IP. +* +* Each bit of the register correlates to a specific interrupt source within the +* IP.  Setting a bit in this register enables the interrupt source to generate +* an interrupt.	 Clearing a bit in this register disables interrupt generation +* for that interrupt source. +* +* This function writes only the specified value to the register such that +* some interrupt sources may be enabled and others disabled.  It is the +* caller's responsibility to get the value of the interrupt enable register +* prior to setting the value to prevent an destructive behavior. +* +* ARGUMENTS: +* +* RegBaseAddress contains the base address of the IPIF registers. +* +* Enable contains the value to be written to the IP interrupt enable register. +* The bit definitions are specific to the device IP. +* +* RETURN VALUE: +* +* None. +* +* NOTES: +* +* None. +* +******************************************************************************/ +#define XIIF_V123B_WRITE_IIER(RegBaseAddress, Enable) \ +    XIo_Out32((RegBaseAddress) + XIIF_V123B_IIER_OFFSET, (Enable)) + +/****************************************************************************** +* +* MACRO: +* +* XIIF_V123B_READ_IIER +* +* DESCRIPTION: +* +* +* This function gets the IP interrupt enable register contents.	 This register +* controls which interrupt sources of the IP are allowed to generate an +* interrupt.  The global interrupt enable register and the device interrupt +* enable register must also be set appropriately for an interrupt to be +* passed out of the device containing the IPIF and the IP. +* +* Each bit of the register correlates to a specific interrupt source within the +* IP.  Setting a bit in this register enables the interrupt source to generate +* an interrupt.	 Clearing a bit in this register disables interrupt generation +* for that interrupt source. +* +* ARGUMENTS: +* +* RegBaseAddress contains the base address of the IPIF registers. +* +* RETURN VALUE: +* +* The contents read from the IP interrupt enable register.  The bit definitions +* are specific to the device IP. +* +* NOTES: +* +* Signature: u32 XIIF_V123B_READ_IIER(u32 RegBaseAddress) +* +******************************************************************************/ +#define XIIF_V123B_READ_IIER(RegBaseAddress) \ +    XIo_In32((RegBaseAddress) + XIIF_V123B_IIER_OFFSET) + +/************************** Function Prototypes ******************************/ + +/* + * Initialization Functions + */ +XStatus XIpIfV123b_SelfTest(u32 RegBaseAddress, u8 IpRegistersWidth); + +#endif				/* end of protection macro */ diff --git a/board/xilinx/common/xpacket_fifo_v1_00_b.c b/board/xilinx/common/xpacket_fifo_v1_00_b.c new file mode 100644 index 000000000..ae2d6d43c --- /dev/null +++ b/board/xilinx/common/xpacket_fifo_v1_00_b.c @@ -0,0 +1,448 @@ +/****************************************************************************** +* +*     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. +* +******************************************************************************/ +/*****************************************************************************/ +/* +* +* @file xpacket_fifo_v1_00_b.c +* +* Contains functions for the XPacketFifoV100b component. See xpacket_fifo_v1_00_b.h +* for more information about the component. +* +* <pre> +* MODIFICATION HISTORY: +* +* Ver   Who  Date     Changes +* ----- ---- -------- ----------------------------------------------- +* 1.00b rpm 03/26/02  First release +* </pre> +* +*****************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xbasic_types.h" +#include "xio.h" +#include "xstatus.h" +#include "xpacket_fifo_v1_00_b.h" + +/************************** Constant Definitions *****************************/ + +/* width of a FIFO word */ + +#define XPF_FIFO_WIDTH_BYTE_COUNT       4UL + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************* Variable Definitions ******************************/ + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/* +* +* This function initializes a packet FIFO.  Initialization resets the +* FIFO such that it's empty and ready to use. +* +* @param InstancePtr contains a pointer to the FIFO to operate on. +* @param RegBaseAddress contains the base address of the registers for +*        the packet FIFO. +* @param DataBaseAddress contains the base address of the data for +*        the packet FIFO. +* +* @return +* +* Always returns XST_SUCCESS. +* +* @note +* +* None. +* +******************************************************************************/ +XStatus +XPacketFifoV100b_Initialize(XPacketFifoV100b * InstancePtr, +			    u32 RegBaseAddress, u32 DataBaseAddress) +{ +	/* assert to verify input argument are valid */ + +	XASSERT_NONVOID(InstancePtr != NULL); + +	/* initialize the component variables to the specified state */ + +	InstancePtr->RegBaseAddress = RegBaseAddress; +	InstancePtr->DataBaseAddress = DataBaseAddress; +	InstancePtr->IsReady = XCOMPONENT_IS_READY; + +	/* reset the FIFO such that it's empty and ready to use and indicate the +	 * initialization was successful, note that the is ready variable must be +	 * set prior to calling the reset function to prevent an assert +	 */ +	XPF_V100B_RESET(InstancePtr); + +	return XST_SUCCESS; +} + +/*****************************************************************************/ +/* +* +* This function performs a self-test on the specified packet FIFO.  The self +* test resets the FIFO and reads a register to determine if it is the correct +* reset value.  This test is destructive in that any data in the FIFO will +* be lost. +* +* @param InstancePtr is a pointer to the packet FIFO to be operated on. +* +* @param FifoType specifies the type of FIFO, read or write, for the self test. +*        The FIFO type is specified by the values XPF_READ_FIFO_TYPE or +*        XPF_WRITE_FIFO_TYPE. +* +* @return +* +* XST_SUCCESS is returned if the selftest is successful, or +* XST_PFIFO_BAD_REG_VALUE indicating that the value readback from the +* occupancy/vacancy count register after a reset does not match the +* specified reset value. +* +* @note +* +* None. +* +******************************************************************************/ +XStatus +XPacketFifoV100b_SelfTest(XPacketFifoV100b * InstancePtr, u32 FifoType) +{ +	u32 Register; + +	/* assert to verify valid input arguments */ + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID((FifoType == XPF_READ_FIFO_TYPE) || +			(FifoType == XPF_WRITE_FIFO_TYPE)); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* reset the fifo and then check to make sure the occupancy/vacancy +	 * register contents are correct for a reset condition +	 */ +	XPF_V100B_RESET(InstancePtr); + +	Register = XIo_In32(InstancePtr->RegBaseAddress + +			    XPF_COUNT_STATUS_REG_OFFSET); + +	/* check the value of the register to ensure that it's correct for the +	 * specified FIFO type since both FIFO types reset to empty, but a bit +	 * in the register changes definition based upon FIFO type +	 */ + +	if (FifoType == XPF_READ_FIFO_TYPE) { +		/* check the regiser value for a read FIFO which should be empty */ + +		if (Register != XPF_EMPTY_FULL_MASK) { +			return XST_PFIFO_BAD_REG_VALUE; +		} +	} else { +		/* check the register value for a write FIFO which should not be full +		 * on reset +		 */ +		if ((Register & XPF_EMPTY_FULL_MASK) != 0) { +			return XST_PFIFO_BAD_REG_VALUE; +		} +	} + +	/* the test was successful */ + +	return XST_SUCCESS; +} + +/*****************************************************************************/ +/* +* +* Read data from a FIFO and puts it into a specified buffer. The packet FIFO is +* currently 32 bits wide such that an input buffer which is a series of bytes +* is filled from the FIFO a word at a time. If the requested byte count is not +* a multiple of 32 bit words, it is necessary for this function to format the +* remaining 32 bit word from the FIFO into a series of bytes in the buffer. +* There may be up to 3 extra bytes which must be extracted from the last word +* of the FIFO and put into the buffer. +* +* @param InstancePtr contains a pointer to the FIFO to operate on. +* @param BufferPtr points to the memory buffer to write the data into. This +*        buffer must be 32 bit aligned or an alignment exception could be +*        generated. Since this buffer is a byte buffer, the data is assumed to +*        be endian independent. +* @param ByteCount contains the number of bytes to read from the FIFO. This +*        number of bytes must be present in the FIFO or an error will be +*        returned. +* +* @return +* +* XST_SUCCESS indicates the operation was successful.  If the number of +* bytes specified by the byte count is not present in the FIFO +* XST_PFIFO_LACK_OF_DATA is returned. +* +* If the function was successful, the specified buffer is modified to contain +* the bytes which were removed from the FIFO. +* +* @note +* +* Note that the exact number of bytes which are present in the FIFO is +* not known by this function.  It can only check for a number of 32 bit +* words such that if the byte count specified is incorrect, but is still +* possible based on the number of words in the FIFO, up to 3 garbage bytes +* may be present at the end of the buffer. +* <br><br> +* This function assumes that if the device consuming data from the FIFO is +* a byte device, the order of the bytes to be consumed is from the most +* significant byte to the least significant byte of a 32 bit word removed +* from the FIFO. +* +******************************************************************************/ +XStatus +XPacketFifoV100b_Read(XPacketFifoV100b * InstancePtr, +		      u8 * BufferPtr, u32 ByteCount) +{ +	u32 FifoCount; +	u32 WordCount; +	u32 ExtraByteCount; +	u32 *WordBuffer = (u32 *) BufferPtr; + +	/* assert to verify valid input arguments including 32 bit alignment of +	 * the buffer pointer +	 */ +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(BufferPtr != NULL); +	XASSERT_NONVOID(((u32) BufferPtr & +			 (XPF_FIFO_WIDTH_BYTE_COUNT - 1)) == 0); +	XASSERT_NONVOID(ByteCount != 0); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* get the count of how many 32 bit words are in the FIFO, if there aren't +	 * enought words to satisfy the request, return an error +	 */ + +	FifoCount = XIo_In32(InstancePtr->RegBaseAddress + +			     XPF_COUNT_STATUS_REG_OFFSET) & XPF_COUNT_MASK; + +	if ((FifoCount * XPF_FIFO_WIDTH_BYTE_COUNT) < ByteCount) { +		return XST_PFIFO_LACK_OF_DATA; +	} + +	/* calculate the number of words to read from the FIFO before the word +	 * containing the extra bytes, and calculate the number of extra bytes +	 * the extra bytes are defined as those at the end of the buffer when +	 * the buffer does not end on a 32 bit boundary +	 */ +	WordCount = ByteCount / XPF_FIFO_WIDTH_BYTE_COUNT; +	ExtraByteCount = ByteCount % XPF_FIFO_WIDTH_BYTE_COUNT; + +	/* Read the 32 bit words from the FIFO for all the buffer except the +	 * last word which contains the extra bytes, the following code assumes +	 * that the buffer is 32 bit aligned, otherwise an alignment exception could +	 * be generated +	 */ +	for (FifoCount = 0; FifoCount < WordCount; FifoCount++) { +		WordBuffer[FifoCount] = XIo_In32(InstancePtr->DataBaseAddress); +	} + +	/* if there are extra bytes to handle, read the last word from the FIFO +	 * and insert the extra bytes into the buffer +	 */ +	if (ExtraByteCount > 0) { +		u32 LastWord; +		u8 *ExtraBytesBuffer = (u8 *) (WordBuffer + WordCount); + +		/* get the last word from the FIFO for the extra bytes */ + +		LastWord = XIo_In32(InstancePtr->DataBaseAddress); + +		/* one extra byte in the last word, put the byte into the next location +		 * of the buffer, bytes in a word of the FIFO are ordered from most +		 * significant byte to least +		 */ +		if (ExtraByteCount == 1) { +			ExtraBytesBuffer[0] = (u8) (LastWord >> 24); +		} + +		/* two extra bytes in the last word, put each byte into the next two +		 * locations of the buffer +		 */ +		else if (ExtraByteCount == 2) { +			ExtraBytesBuffer[0] = (u8) (LastWord >> 24); +			ExtraBytesBuffer[1] = (u8) (LastWord >> 16); +		} +		/* three extra bytes in the last word, put each byte into the next three +		 * locations of the buffer +		 */ +		else if (ExtraByteCount == 3) { +			ExtraBytesBuffer[0] = (u8) (LastWord >> 24); +			ExtraBytesBuffer[1] = (u8) (LastWord >> 16); +			ExtraBytesBuffer[2] = (u8) (LastWord >> 8); +		} +	} +	return XST_SUCCESS; +} + +/*****************************************************************************/ +/* +* +* Write data into a packet FIFO. The packet FIFO is currently 32 bits wide +* such that an input buffer which is a series of bytes must be written into the +* FIFO a word at a time. If the buffer is not a multiple of 32 bit words, it is +* necessary for this function to format the remaining bytes into a single 32 +* bit word to be inserted into the FIFO. This is necessary to avoid any +* accesses past the end of the buffer. +* +* @param InstancePtr contains a pointer to the FIFO to operate on. +* @param BufferPtr points to the memory buffer that data is to be read from +*        and written into the FIFO. Since this buffer is a byte buffer, the data +*        is assumed to be endian independent. This buffer must be 32 bit aligned +*        or an alignment exception could be generated. +* @param ByteCount contains the number of bytes to read from the buffer and to +*        write to the FIFO. +* +* @return +* +* XST_SUCCESS is returned if the operation succeeded.  If there is not enough +* room in the FIFO to hold the specified bytes, XST_PFIFO_NO_ROOM is +* returned. +* +* @note +* +* This function assumes that if the device inserting data into the FIFO is +* a byte device, the order of the bytes in each 32 bit word is from the most +* significant byte to the least significant byte. +* +******************************************************************************/ +XStatus +XPacketFifoV100b_Write(XPacketFifoV100b * InstancePtr, +		       u8 * BufferPtr, u32 ByteCount) +{ +	u32 FifoCount; +	u32 WordCount; +	u32 ExtraByteCount; +	u32 *WordBuffer = (u32 *) BufferPtr; + +	/* assert to verify valid input arguments including 32 bit alignment of +	 * the buffer pointer +	 */ +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(BufferPtr != NULL); +	XASSERT_NONVOID(((u32) BufferPtr & +			 (XPF_FIFO_WIDTH_BYTE_COUNT - 1)) == 0); +	XASSERT_NONVOID(ByteCount != 0); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* get the count of how many words may be inserted into the FIFO */ + +	FifoCount = XIo_In32(InstancePtr->RegBaseAddress + +			     XPF_COUNT_STATUS_REG_OFFSET) & XPF_COUNT_MASK; + +	/* Calculate the number of 32 bit words required to insert the specified +	 * number of bytes in the FIFO and determine the number of extra bytes +	 * if the buffer length is not a multiple of 32 bit words +	 */ + +	WordCount = ByteCount / XPF_FIFO_WIDTH_BYTE_COUNT; +	ExtraByteCount = ByteCount % XPF_FIFO_WIDTH_BYTE_COUNT; + +	/* take into account the extra bytes in the total word count */ + +	if (ExtraByteCount > 0) { +		WordCount++; +	} + +	/* if there's not enough room in the FIFO to hold the specified +	 * number of bytes, then indicate an error, +	 */ +	if (FifoCount < WordCount) { +		return XST_PFIFO_NO_ROOM; +	} + +	/* readjust the word count to not take into account the extra bytes */ + +	if (ExtraByteCount > 0) { +		WordCount--; +	} + +	/* Write all the bytes of the buffer which can be written as 32 bit +	 * words into the FIFO, waiting to handle the extra bytes seperately +	 */ +	for (FifoCount = 0; FifoCount < WordCount; FifoCount++) { +		XIo_Out32(InstancePtr->DataBaseAddress, WordBuffer[FifoCount]); +	} + +	/* if there are extra bytes to handle, extract them from the buffer +	 * and create a 32 bit word and write it to the FIFO +	 */ +	if (ExtraByteCount > 0) { +		u32 LastWord = 0; +		u8 *ExtraBytesBuffer = (u8 *) (WordBuffer + WordCount); + +		/* one extra byte in the buffer, put the byte into the last word +		 * to be inserted into the FIFO, perform this processing inline rather +		 * than in a loop to help performance +		 */ +		if (ExtraByteCount == 1) { +			LastWord = ExtraBytesBuffer[0] << 24; +		} + +		/* two extra bytes in the buffer, put each byte into the last word +		 * to be inserted into the FIFO +		 */ +		else if (ExtraByteCount == 2) { +			LastWord = ExtraBytesBuffer[0] << 24 | +			    ExtraBytesBuffer[1] << 16; +		} + +		/* three extra bytes in the buffer, put each byte into the last word +		 * to be inserted into the FIFO +		 */ +		else if (ExtraByteCount == 3) { +			LastWord = ExtraBytesBuffer[0] << 24 | +			    ExtraBytesBuffer[1] << 16 | +			    ExtraBytesBuffer[2] << 8; +		} + +		/* write the last 32 bit word to the FIFO and return with no errors */ + +		XIo_Out32(InstancePtr->DataBaseAddress, LastWord); +	} + +	return XST_SUCCESS; +} diff --git a/board/xilinx/common/xpacket_fifo_v1_00_b.h b/board/xilinx/common/xpacket_fifo_v1_00_b.h new file mode 100644 index 000000000..1cda0e8cc --- /dev/null +++ b/board/xilinx/common/xpacket_fifo_v1_00_b.h @@ -0,0 +1,306 @@ +/****************************************************************************** +* +*     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. +* +******************************************************************************/ +/*****************************************************************************/ +/* +* +* @file xpacket_fifo_v1_00_b.h +* +* This component is a common component because it's primary purpose is to +* prevent code duplication in drivers. A driver which must handle a packet +* FIFO uses this component rather than directly manipulating a packet FIFO. +* +* A FIFO is a device which has dual port memory such that one user may be +* inserting data into the FIFO while another is consuming data from the FIFO. +* A packet FIFO is designed for use with packet protocols such as Ethernet and +* ATM.  It is typically only used with devices when DMA and/or Scatter Gather +* is used.  It differs from a nonpacket FIFO in that it does not provide any +* interrupts for thresholds of the FIFO such that it is less useful without +* DMA. +* +* @note +* +* This component has the capability to generate an interrupt when an error +* condition occurs.  It is the user's responsibility to provide the interrupt +* processing to handle the interrupt. This component provides the ability to +* determine if that interrupt is active, a deadlock condition, and the ability +* to reset the FIFO to clear the condition. In this condition, the device which +* is using the FIFO should also be reset to prevent other problems. This error +* condition could occur as a normal part of operation if the size of the FIFO +* is not setup correctly.  See the hardware IP specification for more details. +* +* <pre> +* MODIFICATION HISTORY: +* +* Ver   Who  Date     Changes +* ----- ---- -------- ----------------------------------------------- +* 1.00b rpm 03/26/02  First release +* </pre> +* +*****************************************************************************/ +#ifndef XPACKET_FIFO_H		/* prevent circular inclusions */ +#define XPACKET_FIFO_H		/* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xbasic_types.h" +#include "xstatus.h" + +/************************** Constant Definitions *****************************/ + +/* + * These constants specify the FIFO type and are mutually exclusive + */ +#define XPF_READ_FIFO_TYPE      0	/* a read FIFO */ +#define XPF_WRITE_FIFO_TYPE     1	/* a write FIFO */ + +/* + * These constants define the offsets to each of the registers from the + * register base address, each of the constants are a number of bytes + */ +#define XPF_RESET_REG_OFFSET            0UL +#define XPF_MODULE_INFO_REG_OFFSET      0UL +#define XPF_COUNT_STATUS_REG_OFFSET     4UL + +/* + * This constant is used with the Reset Register + */ +#define XPF_RESET_FIFO_MASK             0x0000000A + +/* + * These constants are used with the Occupancy/Vacancy Count Register. This + * register also contains FIFO status + */ +#define XPF_COUNT_MASK                  0x0000FFFF +#define XPF_DEADLOCK_MASK               0x20000000 +#define XPF_ALMOST_EMPTY_FULL_MASK      0x40000000 +#define XPF_EMPTY_FULL_MASK             0x80000000 + +/**************************** Type Definitions *******************************/ + +/* + * The XPacketFifo driver instance data. The driver is required to allocate a + * variable of this type for every packet FIFO in the device. + */ +typedef struct { +	u32 RegBaseAddress;	/* Base address of registers */ +	u32 IsReady;		/* Device is initialized and ready */ +	u32 DataBaseAddress;	/* Base address of data for FIFOs */ +} XPacketFifoV100b; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/* +* +* Reset the specified packet FIFO.  Resetting a FIFO will cause any data +* contained in the FIFO to be lost. +* +* @param InstancePtr contains a pointer to the FIFO to operate on. +* +* @return +* +* None. +* +* @note +* +* Signature: void XPF_V100B_RESET(XPacketFifoV100b *InstancePtr) +* +******************************************************************************/ +#define XPF_V100B_RESET(InstancePtr) \ +    XIo_Out32((InstancePtr)->RegBaseAddress + XPF_RESET_REG_OFFSET, XPF_RESET_FIFO_MASK); + +/*****************************************************************************/ +/* +* +* Get the occupancy count for a read packet FIFO and the vacancy count for a +* write packet FIFO. These counts indicate the number of 32-bit words +* contained (occupancy) in the FIFO or the number of 32-bit words available +* to write (vacancy) in the FIFO. +* +* @param InstancePtr contains a pointer to the FIFO to operate on. +* +* @return +* +* The occupancy or vacancy count for the specified packet FIFO. +* +* @note +* +* Signature: u32 XPF_V100B_GET_COUNT(XPacketFifoV100b *InstancePtr) +* +******************************************************************************/ +#define XPF_V100B_GET_COUNT(InstancePtr) \ +    (XIo_In32((InstancePtr)->RegBaseAddress + XPF_COUNT_STATUS_REG_OFFSET) & \ +    XPF_COUNT_MASK) + +/*****************************************************************************/ +/* +* +* Determine if the specified packet FIFO is almost empty. Almost empty is +* defined for a read FIFO when there is only one data word in the FIFO. +* +* @param InstancePtr contains a pointer to the FIFO to operate on. +* +* @return +* +* TRUE if the packet FIFO is almost empty, FALSE otherwise. +* +* @note +* +* Signature: u32 XPF_V100B_IS_ALMOST_EMPTY(XPacketFifoV100b *InstancePtr) +* +******************************************************************************/ +#define XPF_V100B_IS_ALMOST_EMPTY(InstancePtr) \ +    (XIo_In32((InstancePtr)->RegBaseAddress + XPF_COUNT_STATUS_REG_OFFSET) & \ +    XPF_ALMOST_EMPTY_FULL_MASK) + +/*****************************************************************************/ +/* +* +* Determine if the specified packet FIFO is almost full. Almost full is +* defined for a write FIFO when there is only one available data word in the +* FIFO. +* +* @param InstancePtr contains a pointer to the FIFO to operate on. +* +* @return +* +* TRUE if the packet FIFO is almost full, FALSE otherwise. +* +* @note +* +* Signature: u32 XPF_V100B_IS_ALMOST_FULL(XPacketFifoV100b *InstancePtr) +* +******************************************************************************/ +#define XPF_V100B_IS_ALMOST_FULL(InstancePtr) \ +    (XIo_In32((InstancePtr)->RegBaseAddress + XPF_COUNT_STATUS_REG_OFFSET) & \ +    XPF_ALMOST_EMPTY_FULL_MASK) + +/*****************************************************************************/ +/* +* +* Determine if the specified packet FIFO is empty. This applies only to a +* read FIFO. +* +* @param InstancePtr contains a pointer to the FIFO to operate on. +* +* @return +* +* TRUE if the packet FIFO is empty, FALSE otherwise. +* +* @note +* +* Signature: u32 XPF_V100B_IS_EMPTY(XPacketFifoV100b *InstancePtr) +* +******************************************************************************/ +#define XPF_V100B_IS_EMPTY(InstancePtr) \ +    (XIo_In32((InstancePtr)->RegBaseAddress + XPF_COUNT_STATUS_REG_OFFSET) & \ +    XPF_EMPTY_FULL_MASK) + +/*****************************************************************************/ +/* +* +* Determine if the specified packet FIFO is full. This applies only to a +* write FIFO. +* +* @param InstancePtr contains a pointer to the FIFO to operate on. +* +* @return +* +* TRUE if the packet FIFO is full, FALSE otherwise. +* +* @note +* +* Signature: u32 XPF_V100B_IS_FULL(XPacketFifoV100b *InstancePtr) +* +******************************************************************************/ +#define XPF_V100B_IS_FULL(InstancePtr) \ +    (XIo_In32((InstancePtr)->RegBaseAddress + XPF_COUNT_STATUS_REG_OFFSET) & \ +    XPF_EMPTY_FULL_MASK) + +/*****************************************************************************/ +/* +* +* Determine if the specified packet FIFO is deadlocked.  This condition occurs +* when the FIFO is full and empty at the same time and is caused by a packet +* being written to the FIFO which exceeds the total data capacity of the FIFO. +* It occurs because of the mark/restore features of the packet FIFO which allow +* retransmission of a packet. The software should reset the FIFO and any devices +* using the FIFO when this condition occurs. +* +* @param InstancePtr contains a pointer to the FIFO to operate on. +* +* @return +* +* TRUE if the packet FIFO is deadlocked, FALSE otherwise. +* +* @note +* +* This component has the capability to generate an interrupt when an error +* condition occurs.  It is the user's responsibility to provide the interrupt +* processing to handle the interrupt. This function provides the ability to +* determine if a deadlock condition, and the ability to reset the FIFO to +* clear the condition. +* +* In this condition, the device which is using the FIFO should also be reset +* to prevent other problems. This error condition could occur as a normal part +* of operation if the size of the FIFO is not setup correctly. +* +* Signature: u32 XPF_V100B_IS_DEADLOCKED(XPacketFifoV100b *InstancePtr) +* +******************************************************************************/ +#define XPF_V100B_IS_DEADLOCKED(InstancePtr) \ +    (XIo_In32((InstancePtr)->RegBaseAddress + XPF_COUNT_STATUS_REG_OFFSET) & \ +    XPF_DEADLOCK_MASK) + +/************************** Function Prototypes ******************************/ + +/* Standard functions */ + +XStatus XPacketFifoV100b_Initialize(XPacketFifoV100b * InstancePtr, +				    u32 RegBaseAddress, u32 DataBaseAddress); +XStatus XPacketFifoV100b_SelfTest(XPacketFifoV100b * InstancePtr, u32 FifoType); + +/* Data functions */ + +XStatus XPacketFifoV100b_Read(XPacketFifoV100b * InstancePtr, +			      u8 * ReadBufferPtr, u32 ByteCount); +XStatus XPacketFifoV100b_Write(XPacketFifoV100b * InstancePtr, +			       u8 * WriteBufferPtr, u32 ByteCount); + +#endif				/* end of protection macro */ diff --git a/board/xilinx/common/xstatus.h b/board/xilinx/common/xstatus.h new file mode 100644 index 000000000..ffda4d7d4 --- /dev/null +++ b/board/xilinx/common/xstatus.h @@ -0,0 +1,347 @@ +/****************************************************************************** +* +*     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. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xstatus.h +* +* This file contains Xilinx software status codes.  Status codes have their +* own data type called XStatus.  These codes are used throughout the Xilinx +* device drivers. +* +******************************************************************************/ + +#ifndef XSTATUS_H		/* prevent circular inclusions */ +#define XSTATUS_H		/* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xbasic_types.h" + +/************************** Constant Definitions *****************************/ + +/*********************** Common statuses 0 - 500 *****************************/ + +#define XST_SUCCESS                     0L +#define XST_FAILURE                     1L +#define XST_DEVICE_NOT_FOUND            2L +#define XST_DEVICE_BLOCK_NOT_FOUND      3L +#define XST_INVALID_VERSION             4L +#define XST_DEVICE_IS_STARTED           5L +#define XST_DEVICE_IS_STOPPED           6L +#define XST_FIFO_ERROR                  7L	/* an error occurred during an +						   operation with a FIFO such as +						   an underrun or overrun, this +						   error requires the device to +						   be reset */ +#define XST_RESET_ERROR                 8L	/* an error occurred which requires +						   the device to be reset */ +#define XST_DMA_ERROR                   9L	/* a DMA error occurred, this error +						   typically requires the device +						   using the DMA to be reset */ +#define XST_NOT_POLLED                  10L	/* the device is not configured for +						   polled mode operation */ +#define XST_FIFO_NO_ROOM                11L	/* a FIFO did not have room to put +						   the specified data into */ +#define XST_BUFFER_TOO_SMALL            12L	/* the buffer is not large enough +						   to hold the expected data */ +#define XST_NO_DATA                     13L	/* there was no data available */ +#define XST_REGISTER_ERROR              14L	/* a register did not contain the +						   expected value */ +#define XST_INVALID_PARAM               15L	/* an invalid parameter was passed +						   into the function */ +#define XST_NOT_SGDMA                   16L	/* the device is not configured for +						   scatter-gather DMA operation */ +#define XST_LOOPBACK_ERROR              17L	/* a loopback test failed */ +#define XST_NO_CALLBACK                 18L	/* a callback has not yet been +						 * registered */ +#define XST_NO_FEATURE                  19L	/* device is not configured with +						 * the requested feature */ +#define XST_NOT_INTERRUPT               20L	/* device is not configured for +						 * interrupt mode operation */ +#define XST_DEVICE_BUSY                 21L	/* device is busy */ +#define XST_ERROR_COUNT_MAX             22L	/* the error counters of a device +						 * have maxed out */ +#define XST_IS_STARTED                  23L	/* used when part of device is +						 * already started i.e. +						 * sub channel */ +#define XST_IS_STOPPED                  24L	/* used when part of device is +						 * already stopped i.e. +						 * sub channel */ + +/***************** Utility Component statuses 401 - 500  *********************/ + +#define XST_MEMTEST_FAILED              401L	/* memory test failed */ + +/***************** Common Components statuses 501 - 1000 *********************/ + +/********************* Packet Fifo statuses 501 - 510 ************************/ + +#define XST_PFIFO_LACK_OF_DATA          501L	/* not enough data in FIFO   */ +#define XST_PFIFO_NO_ROOM               502L	/* not enough room in FIFO   */ +#define XST_PFIFO_BAD_REG_VALUE         503L	/* self test, a register value +						   was invalid after reset */ + +/************************** DMA statuses 511 - 530 ***************************/ + +#define XST_DMA_TRANSFER_ERROR          511L	/* self test, DMA transfer +						   failed */ +#define XST_DMA_RESET_REGISTER_ERROR    512L	/* self test, a register value +						   was invalid after reset */ +#define XST_DMA_SG_LIST_EMPTY           513L	/* scatter gather list contains +						   no buffer descriptors ready +						   to be processed */ +#define XST_DMA_SG_IS_STARTED           514L	/* scatter gather not stopped */ +#define XST_DMA_SG_IS_STOPPED           515L	/* scatter gather not running */ +#define XST_DMA_SG_LIST_FULL            517L	/* all the buffer desciptors of +						   the scatter gather list are +						   being used */ +#define XST_DMA_SG_BD_LOCKED            518L	/* the scatter gather buffer +						   descriptor which is to be +						   copied over in the scatter +						   list is locked */ +#define XST_DMA_SG_NOTHING_TO_COMMIT    519L	/* no buffer descriptors have been +						   put into the scatter gather +						   list to be commited */ +#define XST_DMA_SG_COUNT_EXCEEDED       521L	/* the packet count threshold +						   specified was larger than the +						   total # of buffer descriptors +						   in the scatter gather list */ +#define XST_DMA_SG_LIST_EXISTS          522L	/* the scatter gather list has +						   already been created */ +#define XST_DMA_SG_NO_LIST              523L	/* no scatter gather list has +						   been created */ +#define XST_DMA_SG_BD_NOT_COMMITTED     524L	/* the buffer descriptor which was +						   being started was not committed +						   to the list */ +#define XST_DMA_SG_NO_DATA              525L	/* the buffer descriptor to start +						   has already been used by the +						   hardware so it can't be reused +						 */ + +/************************** IPIF statuses 531 - 550 ***************************/ + +#define XST_IPIF_REG_WIDTH_ERROR        531L	/* an invalid register width +						   was passed into the function */ +#define XST_IPIF_RESET_REGISTER_ERROR   532L	/* the value of a register at +						   reset was not valid */ +#define XST_IPIF_DEVICE_STATUS_ERROR    533L	/* a write to the device interrupt +						   status register did not read +						   back correctly */ +#define XST_IPIF_DEVICE_ACK_ERROR       534L	/* the device interrupt status +						   register did not reset when +						   acked */ +#define XST_IPIF_DEVICE_ENABLE_ERROR    535L	/* the device interrupt enable +						   register was not updated when +						   other registers changed */ +#define XST_IPIF_IP_STATUS_ERROR        536L	/* a write to the IP interrupt +						   status register did not read +						   back correctly */ +#define XST_IPIF_IP_ACK_ERROR           537L	/* the IP interrupt status register +						   did not reset when acked */ +#define XST_IPIF_IP_ENABLE_ERROR        538L	/* IP interrupt enable register was +						   not updated correctly when other +						   registers changed */ +#define XST_IPIF_DEVICE_PENDING_ERROR   539L	/* The device interrupt pending +						   register did not indicate the +						   expected value */ +#define XST_IPIF_DEVICE_ID_ERROR        540L	/* The device interrupt ID register +						   did not indicate the expected +						   value */ + +/****************** Device specific statuses 1001 - 4095 *********************/ + +/********************* Ethernet statuses 1001 - 1050 *************************/ + +#define XST_EMAC_MEMORY_SIZE_ERROR  1001L	/* Memory space is not big enough +						 * to hold the minimum number of +						 * buffers or descriptors */ +#define XST_EMAC_MEMORY_ALLOC_ERROR 1002L	/* Memory allocation failed */ +#define XST_EMAC_MII_READ_ERROR     1003L	/* MII read error */ +#define XST_EMAC_MII_BUSY           1004L	/* An MII operation is in progress */ +#define XST_EMAC_OUT_OF_BUFFERS     1005L	/* Adapter is out of buffers */ +#define XST_EMAC_PARSE_ERROR        1006L	/* Invalid adapter init string */ +#define XST_EMAC_COLLISION_ERROR    1007L	/* Excess deferral or late +						 * collision on polled send */ + +/*********************** UART statuses 1051 - 1075 ***************************/ +#define XST_UART + +#define XST_UART_INIT_ERROR         1051L +#define XST_UART_START_ERROR        1052L +#define XST_UART_CONFIG_ERROR       1053L +#define XST_UART_TEST_FAIL          1054L +#define XST_UART_BAUD_ERROR         1055L +#define XST_UART_BAUD_RANGE         1056L + +/************************ IIC statuses 1076 - 1100 ***************************/ + +#define XST_IIC_SELFTEST_FAILED         1076	/* self test failed            */ +#define XST_IIC_BUS_BUSY                1077	/* bus found busy              */ +#define XST_IIC_GENERAL_CALL_ADDRESS    1078	/* mastersend attempted with   */ +					     /* general call address        */ +#define XST_IIC_STAND_REG_RESET_ERROR   1079	/* A non parameterizable reg   */ +					     /* value after reset not valid */ +#define XST_IIC_TX_FIFO_REG_RESET_ERROR 1080	/* Tx fifo included in design  */ +					     /* value after reset not valid */ +#define XST_IIC_RX_FIFO_REG_RESET_ERROR 1081	/* Rx fifo included in design  */ +					     /* value after reset not valid */ +#define XST_IIC_TBA_REG_RESET_ERROR     1082	/* 10 bit addr incl in design  */ +					     /* value after reset not valid */ +#define XST_IIC_CR_READBACK_ERROR       1083	/* Read of the control register */ +					     /* didn't return value written */ +#define XST_IIC_DTR_READBACK_ERROR      1084	/* Read of the data Tx reg     */ +					     /* didn't return value written */ +#define XST_IIC_DRR_READBACK_ERROR      1085	/* Read of the data Receive reg */ +					     /* didn't return value written */ +#define XST_IIC_ADR_READBACK_ERROR      1086	/* Read of the data Tx reg     */ +					     /* didn't return value written */ +#define XST_IIC_TBA_READBACK_ERROR      1087	/* Read of the 10 bit addr reg */ +					     /* didn't return written value */ +#define XST_IIC_NOT_SLAVE               1088	/* The device isn't a slave    */ + +/*********************** ATMC statuses 1101 - 1125 ***************************/ + +#define XST_ATMC_ERROR_COUNT_MAX    1101L	/* the error counters in the ATM +						   controller hit the max value +						   which requires the statistics +						   to be cleared */ + +/*********************** Flash statuses 1126 - 1150 **************************/ + +#define XST_FLASH_BUSY                1126L	/* Flash is erasing or programming */ +#define XST_FLASH_READY               1127L	/* Flash is ready for commands */ +#define XST_FLASH_ERROR               1128L	/* Flash had detected an internal +						   error. Use XFlash_DeviceControl +						   to retrieve device specific codes */ +#define XST_FLASH_ERASE_SUSPENDED     1129L	/* Flash is in suspended erase state */ +#define XST_FLASH_WRITE_SUSPENDED     1130L	/* Flash is in suspended write state */ +#define XST_FLASH_PART_NOT_SUPPORTED  1131L	/* Flash type not supported by +						   driver */ +#define XST_FLASH_NOT_SUPPORTED       1132L	/* Operation not supported */ +#define XST_FLASH_TOO_MANY_REGIONS    1133L	/* Too many erase regions */ +#define XST_FLASH_TIMEOUT_ERROR       1134L	/* Programming or erase operation +						   aborted due to a timeout */ +#define XST_FLASH_ADDRESS_ERROR       1135L	/* Accessed flash outside its +						   addressible range */ +#define XST_FLASH_ALIGNMENT_ERROR     1136L	/* Write alignment error */ +#define XST_FLASH_BLOCKING_CALL_ERROR 1137L	/* Couldn't return immediately from +						   write/erase function with +						   XFL_NON_BLOCKING_WRITE/ERASE +						   option cleared */ +#define XST_FLASH_CFI_QUERY_ERROR     1138L	/* Failed to query the device */ + +/*********************** SPI statuses 1151 - 1175 ****************************/ + +#define XST_SPI_MODE_FAULT          1151	/* master was selected as slave */ +#define XST_SPI_TRANSFER_DONE       1152	/* data transfer is complete */ +#define XST_SPI_TRANSMIT_UNDERRUN   1153	/* slave underruns transmit register */ +#define XST_SPI_RECEIVE_OVERRUN     1154	/* device overruns receive register */ +#define XST_SPI_NO_SLAVE            1155	/* no slave has been selected yet */ +#define XST_SPI_TOO_MANY_SLAVES     1156	/* more than one slave is being +						 * selected */ +#define XST_SPI_NOT_MASTER          1157	/* operation is valid only as master */ +#define XST_SPI_SLAVE_ONLY          1158	/* device is configured as slave-only */ +#define XST_SPI_SLAVE_MODE_FAULT    1159	/* slave was selected while disabled */ + +/********************** OPB Arbiter statuses 1176 - 1200 *********************/ + +#define XST_OPBARB_INVALID_PRIORITY  1176	/* the priority registers have either +						 * one master assigned to two or more +						 * priorities, or one master not +						 * assigned to any priority +						 */ +#define XST_OPBARB_NOT_SUSPENDED     1177	/* an attempt was made to modify the +						 * priority levels without first +						 * suspending the use of priority +						 * levels +						 */ +#define XST_OPBARB_PARK_NOT_ENABLED  1178	/* bus parking by id was enabled but +						 * bus parking was not enabled +						 */ +#define XST_OPBARB_NOT_FIXED_PRIORITY 1179	/* the arbiter must be in fixed +						 * priority mode to allow the +						 * priorities to be changed +						 */ + +/************************ Intc statuses 1201 - 1225 **************************/ + +#define XST_INTC_FAIL_SELFTEST      1201	/* self test failed */ +#define XST_INTC_CONNECT_ERROR      1202	/* interrupt already in use */ + +/********************** TmrCtr statuses 1226 - 1250 **************************/ + +#define XST_TMRCTR_TIMER_FAILED     1226	/* self test failed */ + +/********************** WdtTb statuses 1251 - 1275 ***************************/ + +#define XST_WDTTB_TIMER_FAILED      1251L + +/********************** PlbArb statuses 1276 - 1300 **************************/ + +#define XST_PLBARB_FAIL_SELFTEST    1276L + +/********************** Plb2Opb statuses 1301 - 1325 *************************/ + +#define XST_PLB2OPB_FAIL_SELFTEST   1301L + +/********************** Opb2Plb statuses 1326 - 1350 *************************/ + +#define XST_OPB2PLB_FAIL_SELFTEST   1326L + +/********************** SysAce statuses 1351 - 1360 **************************/ + +#define XST_SYSACE_NO_LOCK          1351L	/* No MPU lock has been granted */ + +/********************** PCI Bridge statuses 1361 - 1375 **********************/ + +#define XST_PCI_INVALID_ADDRESS     1361L + +/**************************** Type Definitions *******************************/ + +/** + * The status typedef. + */ +typedef u32 XStatus; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +#endif				/* end of protection macro */ diff --git a/board/xilinx/common/xversion.c b/board/xilinx/common/xversion.c new file mode 100644 index 000000000..c8a691585 --- /dev/null +++ b/board/xilinx/common/xversion.c @@ -0,0 +1,350 @@ +/****************************************************************************** +* +*     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. +* +******************************************************************************/ +/***************************************************************************** +* +* This file contains the implementation of the XVersion component. This +* component represents a version ID.  It is encapsulated within a component +* so that it's type and implementation can change without affecting users of +* it. +* +* The version is formatted as X.YYZ where X = 0 - 9, Y = 00 - 99, Z = a - z +* X is the major revision, YY is the minor revision, and Z is the +* compatability revision. +* +* Packed versions are also utilized for the configuration ROM such that +* memory is minimized. A packed version consumes only 16 bits and is +* formatted as follows. +* +* <pre> +* Revision                  Range       Bit Positions +* +* Major Revision            0 - 9       Bits 15 - 12 +* Minor Revision            0 - 99      Bits 11 - 5 +* Compatability Revision    a - z       Bits 4 - 0 +</pre> +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xbasic_types.h" +#include "xversion.h" + +/************************** Constant Definitions *****************************/ + +/* the following constants define the masks and shift values to allow the + * revisions to be packed and unpacked, a packed version is packed into a 16 + * bit value in the following format, XXXXYYYYYYYZZZZZ, where XXXX is the + * major revision, YYYYYYY is the minor revision, and ZZZZZ is the compatability + * revision + */ +#define XVE_MAJOR_SHIFT_VALUE       12 +#define XVE_MINOR_ONLY_MASK         0x0FE0 +#define XVE_MINOR_SHIFT_VALUE       5 +#define XVE_COMP_ONLY_MASK          0x001F + +/* the following constants define the specific characters of a version string + * for each character of the revision, a version string is in the following + * format, "X.YYZ" where X is the major revision (0 - 9), YY is the minor + * revision (00 - 99), and Z is the compatability revision (a - z) + */ +#define XVE_MAJOR_CHAR      0	/* major revision 0 - 9 */ +#define XVE_MINOR_TENS_CHAR 2	/* minor revision tens 0 - 9 */ +#define XVE_MINOR_ONES_CHAR 3	/* minor revision ones 0 - 9 */ +#define XVE_COMP_CHAR       4	/* compatability revision a - z */ +#define XVE_END_STRING_CHAR 5 + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static u32 IsVersionStringValid(s8 * StringPtr); + +/***************************************************************************** +* +* Unpacks a packed version into the specified version. Versions are packed +* into the configuration ROM to reduce the amount storage. A packed version +* is a binary format as oppossed to a non-packed version which is implemented +* as a string. +* +* @param    InstancePtr points to the version to unpack the packed version into. +* @param    PackedVersion contains the packed version to unpack. +* +* @return +* +* None. +* +* @note +* +* None. +* +******************************************************************************/ +void +XVersion_UnPack(XVersion * InstancePtr, u16 PackedVersion) +{ +	/* not implemented yet since CROM related */ +} + +/***************************************************************************** +* +* Packs a version into the specified packed version. Versions are packed into +* the configuration ROM to reduce the amount storage. +* +* @param    InstancePtr points to the version to pack. +* @param    PackedVersionPtr points to the packed version which will receive +*           the new packed version. +* +* @return +* +* A status, XST_SUCCESS, indicating the packing was accomplished +* successfully, or an error, XST_INVALID_VERSION, indicating the specified +* input version was not valid such that the pack did not occur +* <br><br> +* The packed version pointed to by PackedVersionPtr is modified with the new +* packed version if the status indicates success. +* +* @note +* +* None. +* +******************************************************************************/ +XStatus +XVersion_Pack(XVersion * InstancePtr, u16 * PackedVersionPtr) +{ +	/* not implemented yet since CROM related */ + +	return XST_SUCCESS; +} + +/***************************************************************************** +* +* Determines if two versions are equal. +* +* @param    InstancePtr points to the first version to be compared. +* @param    VersionPtr points to a second version to be compared. +* +* @return +* +* TRUE if the versions are equal, FALSE otherwise. +* +* @note +* +* None. +* +******************************************************************************/ +u32 +XVersion_IsEqual(XVersion * InstancePtr, XVersion * VersionPtr) +{ +	u8 *Version1 = (u8 *) InstancePtr; +	u8 *Version2 = (u8 *) VersionPtr; +	int Index; + +	/* assert to verify input arguments */ + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(VersionPtr != NULL); + +	/* check each byte of the versions to see if they are the same, +	 * return at any point a byte differs between them +	 */ +	for (Index = 0; Index < sizeof (XVersion); Index++) { +		if (Version1[Index] != Version2[Index]) { +			return FALSE; +		} +	} + +	/* No byte was found to be different between the versions, so indicate +	 * the versions are equal +	 */ +	return TRUE; +} + +/***************************************************************************** +* +* Converts a version to a null terminated string. +* +* @param    InstancePtr points to the version to convert. +* @param    StringPtr points to the string which will be the result of the +*           conversion. This does not need to point to a null terminated +*           string as an input, but must point to storage which is an adequate +*           amount to hold the result string. +* +* @return +* +* The null terminated string is inserted at the location pointed to by +* StringPtr if the status indicates success. +* +* @note +* +* It is necessary for the caller to have already allocated the storage to +* contain the string.  The amount of memory necessary for the string is +* specified in the version header file. +* +******************************************************************************/ +void +XVersion_ToString(XVersion * InstancePtr, s8 * StringPtr) +{ +	/* assert to verify input arguments */ + +	XASSERT_VOID(InstancePtr != NULL); +	XASSERT_VOID(StringPtr != NULL); + +	/* since version is implemented as a string, just copy the specified +	 * input into the specified output +	 */ +	XVersion_Copy(InstancePtr, (XVersion *) StringPtr); +} + +/***************************************************************************** +* +* Initializes a version from a null terminated string. Since the string may not +* be a format which is compatible with the version, an error could occur. +* +* @param    InstancePtr points to the version which is to be initialized. +* @param    StringPtr points to a null terminated string which will be +*           converted to a version.  The format of the string must match the +*           version string format which is X.YYX where X = 0 - 9, YY = 00 - 99, +*           Z = a - z. +* +* @return +* +* A status, XST_SUCCESS, indicating the conversion was accomplished +* successfully, or XST_INVALID_VERSION indicating the version string format +* was not valid. +* +* @note +* +* None. +* +******************************************************************************/ +XStatus +XVersion_FromString(XVersion * InstancePtr, s8 * StringPtr) +{ +	/* assert to verify input arguments */ + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(StringPtr != NULL); + +	/* if the version string specified is not valid, return an error */ + +	if (!IsVersionStringValid(StringPtr)) { +		return XST_INVALID_VERSION; +	} + +	/* copy the specified string into the specified version and indicate the +	 * conversion was successful +	 */ +	XVersion_Copy((XVersion *) StringPtr, InstancePtr); + +	return XST_SUCCESS; +} + +/***************************************************************************** +* +* Copies the contents of a version to another version. +* +* @param    InstancePtr points to the version which is the source of data for +*           the copy operation. +* @param    VersionPtr points to another version which is the destination of +*           the copy operation. +* +* @return +* +* None. +* +* @note +* +* None. +* +******************************************************************************/ +void +XVersion_Copy(XVersion * InstancePtr, XVersion * VersionPtr) +{ +	u8 *Source = (u8 *) InstancePtr; +	u8 *Destination = (u8 *) VersionPtr; +	int Index; + +	/* assert to verify input arguments */ + +	XASSERT_VOID(InstancePtr != NULL); +	XASSERT_VOID(VersionPtr != NULL); + +	/* copy each byte of the source version to the destination version */ + +	for (Index = 0; Index < sizeof (XVersion); Index++) { +		Destination[Index] = Source[Index]; +	} +} + +/***************************************************************************** +* +* Determines if the specified version is valid. +* +* @param    StringPtr points to the string to be validated. +* +* @return +* +* TRUE if the version string is a valid format, FALSE otherwise. +* +* @note +* +* None. +* +******************************************************************************/ +static u32 +IsVersionStringValid(s8 * StringPtr) +{ +	/* if the input string is not a valid format, "X.YYZ" where X = 0 - 9, +	 * YY = 00 - 99, and Z = a - z, then indicate it's not valid +	 */ +	if ((StringPtr[XVE_MAJOR_CHAR] < '0') || +	    (StringPtr[XVE_MAJOR_CHAR] > '9') || +	    (StringPtr[XVE_MINOR_TENS_CHAR] < '0') || +	    (StringPtr[XVE_MINOR_TENS_CHAR] > '9') || +	    (StringPtr[XVE_MINOR_ONES_CHAR] < '0') || +	    (StringPtr[XVE_MINOR_ONES_CHAR] > '9') || +	    (StringPtr[XVE_COMP_CHAR] < 'a') || +	    (StringPtr[XVE_COMP_CHAR] > 'z')) { +		return FALSE; +	} + +	return TRUE; +} diff --git a/board/xilinx/common/xversion.h b/board/xilinx/common/xversion.h new file mode 100644 index 000000000..17f9da7a0 --- /dev/null +++ b/board/xilinx/common/xversion.h @@ -0,0 +1,97 @@ +/****************************************************************************** +* +*     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. +* +******************************************************************************/ +/***************************************************************************** +* +* This file contains the interface for the XVersion component. This +* component represents a version ID.  It is encapsulated within a component +* so that it's type and implementation can change without affecting users of +* it. +* +* The version is formatted as X.YYZ where X = 0 - 9, Y = 00 - 99, Z = a - z +* X is the major revision, YY is the minor revision, and Z is the +* compatability revision. +* +* Packed versions are also utilized for the configuration ROM such that +* memory is minimized. A packed version consumes only 16 bits and is +* formatted as follows. +* +* <pre> +* Revision                  Range       Bit Positions +* +* Major Revision            0 - 9       Bits 15 - 12 +* Minor Revision            0 - 99      Bits 11 - 5 +* Compatability Revision    a - z       Bits 4 - 0 +* </pre> +* +******************************************************************************/ + +#ifndef XVERSION_H		/* prevent circular inclusions */ +#define XVERSION_H		/* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xbasic_types.h" +#include "xstatus.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/* the following data type is used to hold a null terminated version string + * consisting of the following format, "X.YYX" + */ +typedef s8 XVersion[6]; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +void XVersion_UnPack(XVersion * InstancePtr, u16 PackedVersion); + +XStatus XVersion_Pack(XVersion * InstancePtr, u16 * PackedVersion); + +u32 XVersion_IsEqual(XVersion * InstancePtr, XVersion * VersionPtr); + +void XVersion_ToString(XVersion * InstancePtr, s8 * StringPtr); + +XStatus XVersion_FromString(XVersion * InstancePtr, s8 * StringPtr); + +void XVersion_Copy(XVersion * InstancePtr, XVersion * VersionPtr); + +#endif				/* end of protection macro */ diff --git a/board/xilinx/ml300/Makefile b/board/xilinx/ml300/Makefile new file mode 100644 index 000000000..d9007c025 --- /dev/null +++ b/board/xilinx/ml300/Makefile @@ -0,0 +1,57 @@ +# +# (C) Copyright 2000 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# 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. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# 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., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +CFLAGS   += -I../ml300 -I../common -I../xilinx_enet + +LIB	= lib$(BOARD).a + +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 \ +	  ../common/xbasic_types.o ../common/xdma_channel.o \ +	  ../common/xdma_channel_sg.o ../common/xpacket_fifo_v1_00_b.o \ +	  ../common/xversion.o + +SOBJS	= init.o + +$(LIB):	$(OBJS) $(SOBJS) +	$(AR) crv $@ $^ + +clean: +	rm -f $(SOBJS) $(OBJS) + +distclean:	clean +	rm -f $(LIB) core *.bak .depend + +######################################################################### + +.depend:	Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) +		$(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/xilinx/ml300/config.mk b/board/xilinx/ml300/config.mk new file mode 100644 index 000000000..57ddb2fd7 --- /dev/null +++ b/board/xilinx/ml300/config.mk @@ -0,0 +1,29 @@ +# +# (C) Copyright 2000 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# 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. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# 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., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +# +# esd ADCIOP boards +# + +#TEXT_BASE = 0xFFFE0000 +TEXT_BASE = 0x04000000 diff --git a/board/xilinx/ml300/init.S b/board/xilinx/ml300/init.S new file mode 100644 index 000000000..f753df851 --- /dev/null +++ b/board/xilinx/ml300/init.S @@ -0,0 +1,48 @@ +/* + * init.S: Stubs for U-Boot initialization + * + *     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. + * + * + */ + +	.globl ext_bus_cntlr_init +ext_bus_cntlr_init: +	blr + +	.globl sdram_init +sdram_init: +	blr diff --git a/board/xilinx/ml300/ml300.c b/board/xilinx/ml300/ml300.c new file mode 100644 index 000000000..dbe8a8ac7 --- /dev/null +++ b/board/xilinx/ml300/ml300.c @@ -0,0 +1,109 @@ +/* + * ml300.c: U-Boot platform support for Xilinx ML300 board + * + *     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 <asm/processor.h> +#include "xparameters.h" + +int +board_pre_init(void) +{ +	return 0; +} + +int +checkboard(void) +{ +	unsigned char *s = getenv("serial#"); +	unsigned char *e; + +	if (!s || strncmp(s, "ML300", 9)) { +		printf("### No HW ID - assuming ML300"); +	} else { +		for (e = s; *e; ++e) { +			if (*e == ' ') +				break; +		} + +		for (; s < e; ++s) { +			putc(*s); +		} +	} + +	putc('\n'); + +	return (0); +} + +long int +initdram(int board_type) +{ +	return 128 * 1024 * 1024; +} + +int +testdram(void) +{ +	printf("test: xxx MB - ok\n"); + +	return (0); +} + +/* implement functions originally in cpu/ppc4xx/speed.c */ +void +get_sys_info(sys_info_t * sysInfo) +{ +	sysInfo->freqProcessor = XPAR_CORE_CLOCK_FREQ_HZ; + +	/* only correct if the PLB and OPB run at the same frequency */ +	sysInfo->freqPLB = XPAR_UARTNS550_0_CLOCK_FREQ_HZ; +	sysInfo->freqPCI = XPAR_UARTNS550_0_CLOCK_FREQ_HZ / 3; +} + +ulong +get_PCI_freq(void) +{ +	ulong val; +	PPC405_SYS_INFO sys_info; + +	get_sys_info(&sys_info); +	val = sys_info.freqPCI; +	return val; +} diff --git a/board/xilinx/ml300/serial.c b/board/xilinx/ml300/serial.c new file mode 100644 index 000000000..19bcc6ff3 --- /dev/null +++ b/board/xilinx/ml300/serial.c @@ -0,0 +1,155 @@ +/* + *     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 <asm/u-boot.h> +#include <asm/processor.h> +#include <common.h> +#include <command.h> +#include <configs/ml300.h> +#include "xparameters.h" + +#define USE_CHAN1 \ +	((defined XPAR_UARTNS550_0_BASEADDR) && (defined CFG_INIT_CHAN1)) +#define USE_CHAN2 \ +	((defined XPAR_UARTNS550_1_BASEADDR) && (defined CFG_INIT_CHAN2)) + +#if USE_CHAN1 +#include <ns16550.h> +#endif + +#if USE_CHAN1 +const NS16550_t COM_PORTS[] = { (NS16550_t) (XPAR_UARTNS550_0_BASEADDR + 3) +#if USE_CHAN2 +	    , (NS16550_t) (XPAR_UARTNS550_1_BASEADDR + 3) +#endif +}; +#endif + +int +serial_init(void) +{ +#if USE_CHAN1 +	DECLARE_GLOBAL_DATA_PTR; +	int clock_divisor; + +	clock_divisor = XPAR_UARTNS550_0_CLOCK_FREQ_HZ / 16 / gd->baudrate; +	(void) NS16550_init(COM_PORTS[0], clock_divisor); +#if USE_CHAN2 +	clock_divisor = XPAR_UARTNS550_1_CLOCK_FREQ_HZ / 16 / gd->baudrate; +	(void) NS16550_init(COM_PORTS[1], clock_divisor); +#endif +#endif +	return 0; + +} + +void +serial_putc(const char c) +{ +	if (c == '\n') +		NS16550_putc(COM_PORTS[CFG_DUART_CHAN], '\r'); + +	NS16550_putc(COM_PORTS[CFG_DUART_CHAN], c); +} + +int +serial_getc(void) +{ +	return NS16550_getc(COM_PORTS[CFG_DUART_CHAN]); +} + +int +serial_tstc(void) +{ +	return NS16550_tstc(COM_PORTS[CFG_DUART_CHAN]); +} + +void +serial_setbrg(void) +{ +#if USE_CHAN1 +	DECLARE_GLOBAL_DATA_PTR; +	int clock_divisor; + +	clock_divisor = XPAR_UARTNS550_0_CLOCK_FREQ_HZ / 16 / gd->baudrate; +	NS16550_reinit(COM_PORTS[0], clock_divisor); +#if USE_CHAN2 +	clock_divisor = XPAR_UARTNS550_1_CLOCK_FREQ_HZ / 16 / gd->baudrate; +	NS16550_reinit(COM_PORTS[1], clock_divisor); +#endif +#endif +} + +void +serial_puts(const char *s) +{ +	while (*s) { +		serial_putc(*s++); +	} +} + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +void +kgdb_serial_init(void) +{ +} + +void +putDebugChar(int c) +{ +	serial_putc(c); +} + +void +putDebugStr(const char *str) +{ +	serial_puts(str); +} + +int +getDebugChar(void) +{ +	return serial_getc(); +} + +void +kgdb_interruptible(int yes) +{ +	return; +} +#endif				/* CFG_CMD_KGDB */ 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 new file mode 100644 index 000000000..319b925d3 --- /dev/null +++ b/board/xilinx/ml300/sw_services/uboot_v1_00_a/data/Ltypes @@ -0,0 +1,41 @@ +#!/bin/bash + +if[$ +# -ne 1 ] +   then echo "usage: Ltypes filename" > &2 exit 2 fi FILE = "$1" +#TMPFILE='mktemp "${FILE}.XXXXXX"' || exit 1 +   TMPFILE = $ { +   FILE} + +   . ` 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}" +# Overlay the original file with the temp 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\ +#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 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 new file mode 100644 index 000000000..e1aa7fd59 --- /dev/null +++ b/board/xilinx/ml300/sw_services/uboot_v1_00_a/data/uboot_v2_1_0.mld @@ -0,0 +1,48 @@ +# (c) Copyright 2004 Xilinx Inc. +#     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. + +OPTION psf_version = 2.1; + +BEGIN LIBRARY uboot OPTION DRC = uboot_drc; + +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; + +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 new file mode 100644 index 000000000..8d939b416 --- /dev/null +++ b/board/xilinx/ml300/sw_services/uboot_v1_00_a/data/uboot_v2_1_0.tcl @@ -0,0 +1,298 @@ +# +#      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. +# +# Globals +lappend drvlist +set ltypes "../../../sw_services/uboot_v1_00_a/data/Ltypes" + +proc uboot_drc {lib_handle} { +    puts "U-Boot DRC..." +} + +proc generate {libname} { +     +    global drvlist +     +    # Get list of peripherals connected to uboot +    set conn_periphs [xget_handle $libname "ARRAY" "connected_periphs"] +    #lappend drvlist +    if {[string compare -nocase $conn_periphs ""] != 0} { +	set conn_periphs_elems [xget_handle $conn_periphs "ELEMENTS" "*"] +	# For each periph +	foreach periph_elem $conn_periphs_elems { +	    set periph [xget_value $periph_elem "PARAMETER" "periph_name"] +	    # 1. Get driver +	    set drv [xget_swhandle $periph] +	    set posn [lsearch -exact $drvlist $drv] +	    if {$posn == -1} { +		lappend drvlist $drv +	    } +	} +	 +	set file_handle [xopen_include_file "xparameters.h"] +	puts $file_handle "\n/******************************************************************/\n" +	puts $file_handle "/* U-Boot Redefines */" +	puts $file_handle "\n/******************************************************************/\n" +	close $file_handle +	 +	foreach drv $drvlist { +	    set drvname [xget_value $drv "NAME"] +	     +	    #Redefines xparameters.h +	    if {[string compare -nocase $drvname "uartns550"] == 0} { +		xredefine_uartns550 $drv "xparameters.h" +	    }  elseif {[string compare -nocase $drvname "emac"] == 0} { +		xredefine_emac $drv "xparameters.h" +	    } +	} +    } +     +    # define core_clock +    xredefine_params $libname "xparameters.h" "CORE_CLOCK_FREQ_HZ" +} + +proc xget_corefreq {} { +    set processor [xget_processor]  +    set name [xget_value $processor "NAME"] +    puts "procname : $name" +    set processor_driver [xget_swhandle [xget_value $processor "NAME"]] +    puts "procdrv : $processor_driver" +    if {[string compare -nocase $processor_driver ""] != 0} { +	set arg "CORE_CLOCK_FREQ_HZ" +	#set retval [xget_value $processor_driver "PARAMETER" $arg] +	set retval [xget_dname [xget_value $processor_driver "NAME"] $arg] +	return $retval +    } +} + +# procedure that adds # defines to xparameters.h as XPAR_argument +proc xredefine_params {handle file_name args} { +     +    puts "xredfine ..." +    # Open include file +    set file_handle [xopen_include_file $file_name] +    puts "args : $args" + +    foreach arg $args { +	if {[string compare -nocase $arg "CORE_CLOCK_FREQ_HZ"] == 0} { +	    set value [xget_corefreq] +	    puts "corefreq : $value" +	} else { +	    set value [xget_value $handle "PARAMETER" $arg] +	    puts "value : $value" +	} +	 +	if {$value != ""} { +	    set value [xformat_addr_string $value $arg] +	    set name [string toupper $arg] +	    set name [format "XPAR_%s" $name] +	    puts $file_handle "#define $name $value" +	} +    } + +    puts $file_handle "\n/******************************************************************/\n" +    close $file_handle +} + +# uart redefines... +proc xredefine_uartns550 {drvhandle file_name} { +     +    xredefine_include_file $drvhandle $file_name "uartns550" "C_BASEADDR" "C_HIGHADDR" "CLOCK_HZ" "DEVICE_ID" +     +} + +proc xredefine_emac {drvhandle file_name} { +     +    xredefine_include_file $drvhandle $file_name "emac" "C_BASEADDR" "C_HIGHADDR" "C_DMA_PRESENT" "C_MII_EXIST" "C_ERR_COUNT_EXIST" "DEVICE_ID" +     +} + +####################### + +proc xredefine_include_file {drv_handle file_name drv_string args} { +     +    # Open include file +    set file_handle [xopen_include_file $file_name] +     +    # Get all peripherals connected to this driver +    set periphs [xget_periphs $drv_handle]  +     +    set pname [format "XPAR_%s_" [string toupper $drv_string]] +     +    # Print all parameters for all peripherals +    set device_id 0 +    set sub_periphs 1 +    foreach periph $periphs { +	puts "$periph : $drv_string : $sub_periphs" + +	for {set i 0} {$i < $sub_periphs} {incr i} { +	    foreach arg $args { +		set name "${pname}${device_id}_" +	     +		if {[string compare -nocase "CLOCK_HZ" $arg] == 0} { +		    set xdrv_string [format "%s%s" "X" $drv_string] +		    set value [xget_dname $xdrv_string $arg] +		    set name "${name}CLOCK_FREQ_HZ" +		} else { +		    if {[string match C_* $arg]} { +			set name [format "%s%s" $name [string range $arg 2 end]] +		    } else { +			set name "${name}${arg}" +		    } +		    set value [xget_name $periph $arg] +		} + +		if {[string compare -nocase "uartns550" $drv_string] == 0} { +		    if {[string compare -nocase "C_BASEADDR" $arg] == 0} { +			set value [format "(%s%s%s)" $value "+" "0x1000"] +		    } +		} + +		puts $file_handle "#define $name $value" +		if {[string compare -nocase "DEVICE_ID" $arg] == 0} { +		    incr device_id +		} +	    } +	} +    }		 +    puts $file_handle "\n/******************************************************************/\n" +    close $file_handle +} + +################################################## +# procedure post_generate +# This generates the drivers directory for uboot +# and runs the ltypes script +################################################## + +proc post_generate {lib_handle} { +     +    global drvlist +     +    # Create U-Boot tree structure +    set pwd [pwd] +    set common_dir "uboot/board/xilinx/common" +    set xilinx_enet_dir "uboot/board/xilinx/xilinx_enet" +    set ml300_dir  "uboot/board/xilinx/ml300" +     +    exec bash -c "mkdir -p $common_dir $xilinx_enet_dir $ml300_dir" +     +    # Copy files for xilinx_ocp +    xcopy_commonfiles + +    foreach drv $drvlist { +	set drvname [xget_value $drv "NAME"] +	set ver [xget_value $drv "PARAMETER" "DRIVER_VER"] +	set ver [string map {. _} $ver] +	set dirname [format "%s_v%s" $drvname $ver] +	 +	if {[string compare -nocase $drvname "emac"] == 0} { +	    xcopy_emac $drv $dirname +	} +    } +     +    # Call Ltypes Script here +    set uboot "uboot" +    xltype_file $uboot + +    # Move xparameters.h around +    exec bash -c "cp ../../include/xparameters.h $ml300_dir" + +    # copy the whole U-Boot BSP to its final destination +    set value [xget_value $lib_handle "PARAMETER" TARGET_DIR] +    puts "TARGET_DIR : $value" + +    if {$value != ""} { +        if {[file isdirectory $value] == 0} { +            exec bash -c "mkdir -p $value" +        } +        exec bash -c "cp -Rp uboot/* $value" +    } +} + +proc xcopy_commonfiles {} { + +    global drvlist + +    set common_dir "uboot/board/xilinx/common" +     +    foreach drv $drvlist { +	set depends [xget_value $drv "OPTION" "DEPENDS"] +	foreach dep $depends { +	    puts "dep : $dep" +	    if {[file isdirectory "../$dep"] == 1} { +		exec bash -c "cp -f ../$dep/src/*.c $common_dir" +		exec bash -c "cp -f ../$dep/src/*.h $common_dir" +	    } +	} +    } +     +} + +proc xcopy_emac {drv_handle dirname} { +    set emac "board/xilinx/xilinx_enet" +    xcopy_dir $dirname $emac +} + +proc xcopy_dir {srcdir dstdir} { +     +    set dstdirname [format "%s%s" "uboot/" $dstdir] +    if {[file isdirectory "../$srcdir"] == 1} { +	# Copy files from src to dst +	exec bash -c "mkdir -p $dstdirname" +	exec bash -c "cp -f ../$srcdir/src/*.c $dstdirname" +	exec bash -c "cp -f ../$srcdir/src/*.h $dstdirname" +    } else { +	puts "$srcdir does not exist ..." +    } +} + + +proc xltype_file {filename} { + +    global ltypes + +    puts $filename + +    if {[file isdirectory $filename]} { +	foreach entry [glob -nocomplain [file join $filename *]] { +	    xltype_file $entry +	} +    } else { +	exec bash -c "$ltypes $filename" +    } +     +} diff --git a/board/xilinx/ml300/u-boot.lds b/board/xilinx/ml300/u-boot.lds new file mode 100644 index 000000000..e7b7e107b --- /dev/null +++ b/board/xilinx/ml300/u-boot.lds @@ -0,0 +1,146 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +OUTPUT_ARCH(powerpc) +ENTRY(_start) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); +/* Do we need any of these for elf? +   __DYNAMIC = 0;    */ +SECTIONS +{ +  /* Read-only sections, merged into text segment: */ +  . = + SIZEOF_HEADERS; +  .interp : { *(.interp) } +  .hash          : { *(.hash)		} +  .dynsym        : { *(.dynsym)		} +  .dynstr        : { *(.dynstr)		} +  .rel.text      : { *(.rel.text)		} +  .rela.text     : { *(.rela.text) 	} +  .rel.data      : { *(.rel.data)		} +  .rela.data     : { *(.rela.data) 	} +  .rel.rodata    : { *(.rel.rodata) 	} +  .rela.rodata   : { *(.rela.rodata) 	} +  .rel.got       : { *(.rel.got)		} +  .rela.got      : { *(.rela.got)		} +  .rel.ctors     : { *(.rel.ctors)	} +  .rela.ctors    : { *(.rela.ctors)	} +  .rel.dtors     : { *(.rel.dtors)	} +  .rela.dtors    : { *(.rela.dtors)	} +  .rel.bss       : { *(.rel.bss)		} +  .rela.bss      : { *(.rela.bss)		} +  .rel.plt       : { *(.rel.plt)		} +  .rela.plt      : { *(.rela.plt)		} +  .init          : { *(.init)	} +  .plt : { *(.plt) } +  .text      : +  { +    /* WARNING - the following is hand-optimized to fit within	*/ +    /* the sector layout of our flash chips!	XXX FIXME XXX	*/ +/* +    cpu/ppc4xx/start.o	(.text) +    board/xilinx/ml300/init.o	(.text) +    cpu/ppc4xx/kgdb.o	(.text) +    cpu/ppc4xx/traps.o	(.text) +    cpu/ppc4xx/interrupts.o	(.text) +    cpu/ppc4xx/serial.o	(.text) +    cpu/ppc4xx/cpu_init.o	(.text) +    cpu/ppc4xx/speed.o	(.text) +    cpu/ppc4xx/405gp_enet.o	(.text) +    common/dlmalloc.o	(.text) +    lib_generic/crc32.o		(.text) +    lib_ppc/extable.o	(.text) +    lib_generic/zlib.o		(.text) +*/ +/*    . = env_offset;*/ +/*    common/environment.o(.text)*/ + +    *(.text) +    *(.fixup) +    *(.got1) +  } +  _etext = .; +  PROVIDE (etext = .); +  .rodata    : +  { +    *(.rodata) +    *(.rodata1) +    *(.rodata.str1.4) +  } +  .fini      : { *(.fini)    } =0 +  .ctors     : { *(.ctors)   } +  .dtors     : { *(.dtors)   } + +  /* Read-write section, merged into data segment: */ +  . = (. + 0x00FF) & 0xFFFFFF00; +  _erotext = .; +  PROVIDE (erotext = .); +  .reloc   : +  { +    *(.got) +    _GOT2_TABLE_ = .; +    *(.got2) +    _FIXUP_TABLE_ = .; +    *(.fixup) +  } +  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2; +  __fixup_entries = (. - _FIXUP_TABLE_)>>2; + +  .data    : +  { +    *(.data) +    *(.data1) +    *(.sdata) +    *(.sdata2) +    *(.dynamic) +    CONSTRUCTORS +  } +  _edata  =  .; +  PROVIDE (edata = .); + +  __u_boot_cmd_start = .; +  .u_boot_cmd : { *(.u_boot_cmd) } +  __u_boot_cmd_end = .; + + +  __start___ex_table = .; +  __ex_table : { *(__ex_table) } +  __stop___ex_table = .; + +  . = ALIGN(256); +  __init_begin = .; +  .text.init : { *(.text.init) } +  .data.init : { *(.data.init) } +  . = ALIGN(256); +  __init_end = .; + +  __bss_start = .; +  .bss       : +  { +   *(.sbss) *(.scommon) +   *(.dynbss) +   *(.bss) +   *(COMMON) +  } +  _end = . ; +  PROVIDE (end = .); +} diff --git a/board/xilinx/ml300/u-boot.lds.debug b/board/xilinx/ml300/u-boot.lds.debug new file mode 100644 index 000000000..d483424ad --- /dev/null +++ b/board/xilinx/ml300/u-boot.lds.debug @@ -0,0 +1,135 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +OUTPUT_ARCH(powerpc) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); +/* Do we need any of these for elf? +   __DYNAMIC = 0;    */ +SECTIONS +{ +  /* Read-only sections, merged into text segment: */ +  . = + SIZEOF_HEADERS; +  .interp : { *(.interp) } +  .hash          : { *(.hash)		} +  .dynsym        : { *(.dynsym)		} +  .dynstr        : { *(.dynstr)		} +  .rel.text      : { *(.rel.text)		} +  .rela.text     : { *(.rela.text) 	} +  .rel.data      : { *(.rel.data)		} +  .rela.data     : { *(.rela.data) 	} +  .rel.rodata    : { *(.rel.rodata) 	} +  .rela.rodata   : { *(.rela.rodata) 	} +  .rel.got       : { *(.rel.got)		} +  .rela.got      : { *(.rela.got)		} +  .rel.ctors     : { *(.rel.ctors)	} +  .rela.ctors    : { *(.rela.ctors)	} +  .rel.dtors     : { *(.rel.dtors)	} +  .rela.dtors    : { *(.rela.dtors)	} +  .rel.bss       : { *(.rel.bss)		} +  .rela.bss      : { *(.rela.bss)		} +  .rel.plt       : { *(.rel.plt)		} +  .rela.plt      : { *(.rela.plt)		} +  .init          : { *(.init)	} +  .plt : { *(.plt) } +  .text      : +  { +    /* WARNING - the following is hand-optimized to fit within	*/ +    /* the sector layout of our flash chips!	XXX FIXME XXX	*/ + +    mpc8xx/start.o	(.text) +    common/dlmalloc.o	(.text) +    lib_generic/vsprintf.o	(.text) +    lib_generic/crc32.o		(.text) +    lib_ppc/extable.o	(.text) + +    common/environment.o(.text) + +    *(.text) +    *(.fixup) +    *(.got1) +  } +  _etext = .; +  PROVIDE (etext = .); +  .rodata    : +  { +    *(.rodata) +    *(.rodata1) +  } +  .fini      : { *(.fini)    } =0 +  .ctors     : { *(.ctors)   } +  .dtors     : { *(.dtors)   } + +  /* Read-write section, merged into data segment: */ +  . = (. + 0x0FFF) & 0xFFFFF000; +  _erotext = .; +  PROVIDE (erotext = .); +  .reloc   : +  { +    *(.got) +    _GOT2_TABLE_ = .; +    *(.got2) +    _FIXUP_TABLE_ = .; +    *(.fixup) +  } +  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2; +  __fixup_entries = (. - _FIXUP_TABLE_)>>2; + +  .data    : +  { +    *(.data) +    *(.data1) +    *(.sdata) +    *(.sdata2) +    *(.dynamic) +    CONSTRUCTORS +  } +  _edata  =  .; +  PROVIDE (edata = .); + +  __u_boot_cmd_start = .; +  .u_boot_cmd : { *(.u_boot_cmd) } +  __u_boot_cmd_end = .; + + +  __start___ex_table = .; +  __ex_table : { *(__ex_table) } +  __stop___ex_table = .; + +  . = ALIGN(4096); +  __init_begin = .; +  .text.init : { *(.text.init) } +  .data.init : { *(.data.init) } +  . = ALIGN(4096); +  __init_end = .; + +  __bss_start = .; +  .bss       : +  { +   *(.sbss) *(.scommon) +   *(.dynbss) +   *(.bss) +   *(COMMON) +  } +  _end = . ; +  PROVIDE (end = .); +} diff --git a/board/xilinx/ml300/xparameters.h b/board/xilinx/ml300/xparameters.h new file mode 100644 index 000000000..c6362562b --- /dev/null +++ b/board/xilinx/ml300/xparameters.h @@ -0,0 +1,216 @@ +/******************************************************************* +* +* CAUTION: This file is automatically generated by libgen. +* Version: Xilinx EDK 6.1.2 EDK_G.14 +* 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. +* +* Description: Driver parameters +* +*******************************************************************/ + +#define XPAR_XPCI_NUM_INSTANCES 1 +#define XPAR_XPCI_CLOCK_HZ 33333333 +#define XPAR_OPB_PCI_REF_0_DEVICE_ID 0 +#define XPAR_OPB_PCI_REF_0_BASEADDR 0x20000000 +#define XPAR_OPB_PCI_REF_0_HIGHADDR 0x3FFFFFFF +#define XPAR_OPB_PCI_REF_0_CONFIG_ADDR 0x3C000000 +#define XPAR_OPB_PCI_REF_0_CONFIG_DATA 0x3C000004 +#define XPAR_OPB_PCI_REF_0_LCONFIG_ADDR 0x3E000000 +#define XPAR_OPB_PCI_REF_0_MEM_BASEADDR 0x20000000 +#define XPAR_OPB_PCI_REF_0_MEM_HIGHADDR 0x37FFFFFF +#define XPAR_OPB_PCI_REF_0_IO_BASEADDR 0x38000000 +#define XPAR_OPB_PCI_REF_0_IO_HIGHADDR 0x3BFFFFFF + +/******************************************************************/ + +#define XPAR_XEMAC_NUM_INSTANCES 1 +#define XPAR_OPB_ETHERNET_0_BASEADDR 0x60000000 +#define XPAR_OPB_ETHERNET_0_HIGHADDR 0x60003FFF +#define XPAR_OPB_ETHERNET_0_DEVICE_ID 0 +#define XPAR_OPB_ETHERNET_0_ERR_COUNT_EXIST 1 +#define XPAR_OPB_ETHERNET_0_DMA_PRESENT 1 +#define XPAR_OPB_ETHERNET_0_MII_EXIST 1 + +/******************************************************************/ + +#define XPAR_MY_OPB_GPIO_0_DEVICE_ID_0 0 +#define XPAR_MY_OPB_GPIO_0_BASEADDR_0 0x90000000 +#define XPAR_MY_OPB_GPIO_0_HIGHADDR_0 (0x90000000+0x7) +#define XPAR_MY_OPB_GPIO_0_DEVICE_ID_1 1 +#define XPAR_MY_OPB_GPIO_0_BASEADDR_1 (0x90000000+0x8) +#define XPAR_MY_OPB_GPIO_0_HIGHADDR_1 (0x90000000+0x1F) +#define XPAR_XGPIO_NUM_INSTANCES 2 + +/******************************************************************/ + +#define XPAR_XIIC_NUM_INSTANCES 1 +#define XPAR_OPB_IIC_0_BASEADDR 0xA8000000 +#define XPAR_OPB_IIC_0_HIGHADDR 0xA80001FF +#define XPAR_OPB_IIC_0_DEVICE_ID 0 +#define XPAR_OPB_IIC_0_TEN_BIT_ADR 0 + +/******************************************************************/ + +#define XPAR_XUARTNS550_NUM_INSTANCES 2 +#define XPAR_XUARTNS550_CLOCK_HZ 100000000 +#define XPAR_OPB_UART16550_0_BASEADDR 0xA0000000 +#define XPAR_OPB_UART16550_0_HIGHADDR 0xA0001FFF +#define XPAR_OPB_UART16550_0_DEVICE_ID 0 +#define XPAR_OPB_UART16550_1_BASEADDR 0xA0010000 +#define XPAR_OPB_UART16550_1_HIGHADDR 0xA0011FFF +#define XPAR_OPB_UART16550_1_DEVICE_ID 1 + +/******************************************************************/ + +#define XPAR_XSPI_NUM_INSTANCES 1 +#define XPAR_OPB_SPI_0_BASEADDR 0xA4000000 +#define XPAR_OPB_SPI_0_HIGHADDR 0xA400007F +#define XPAR_OPB_SPI_0_DEVICE_ID 0 +#define XPAR_OPB_SPI_0_FIFO_EXIST 1 +#define XPAR_OPB_SPI_0_SPI_SLAVE_ONLY 0 +#define XPAR_OPB_SPI_0_NUM_SS_BITS 1 + +/******************************************************************/ + +#define XPAR_XPS2_NUM_INSTANCES 2 +#define XPAR_OPB_PS2_DUAL_REF_0_DEVICE_ID_0 0 +#define XPAR_OPB_PS2_DUAL_REF_0_BASEADDR_0 0xA9000000 +#define XPAR_OPB_PS2_DUAL_REF_0_HIGHADDR_0 (0xA9000000+0x3F) +#define XPAR_OPB_PS2_DUAL_REF_0_DEVICE_ID_1 1 +#define XPAR_OPB_PS2_DUAL_REF_0_BASEADDR_1 (0xA9000000+0x1000) +#define XPAR_OPB_PS2_DUAL_REF_0_HIGHADDR_1 (0xA9000000+0x103F) + +/******************************************************************/ + +#define XPAR_XTOUCHSCREEN_NUM_INSTANCES 1 +#define XPAR_OPB_TSD_REF_0_BASEADDR 0xAA000000 +#define XPAR_OPB_TSD_REF_0_HIGHADDR 0xAA000007 +#define XPAR_OPB_TSD_REF_0_DEVICE_ID 0 + +/******************************************************************/ + +#define XPAR_OPB_AC97_CONTROLLER_REF_0_BASEADDR 0xA6000000 +#define XPAR_OPB_AC97_CONTROLLER_REF_0_HIGHADDR 0xA60000FF +#define XPAR_OPB_PAR_PORT_REF_0_BASEADDR 0x90010000 +#define XPAR_OPB_PAR_PORT_REF_0_HIGHADDR 0x900100FF +#define XPAR_PLB_DDR_0_BASEADDR 0x00000000 +#define XPAR_PLB_DDR_0_HIGHADDR 0x0FFFFFFF + +/******************************************************************/ + +#define XPAR_XINTC_HAS_IPR 1 +#define XPAR_INTC_MAX_NUM_INTR_INPUTS 18 +#define XPAR_XINTC_USE_DCR 0 +#define XPAR_XINTC_NUM_INSTANCES 1 +#define XPAR_DCR_INTC_0_BASEADDR 0xD0000FC0 +#define XPAR_DCR_INTC_0_HIGHADDR 0xD0000FDF +#define XPAR_DCR_INTC_0_DEVICE_ID 0 +#define XPAR_DCR_INTC_0_KIND_OF_INTR 0x00038000 + +/******************************************************************/ + +#define XPAR_DCR_INTC_0_MISC_LOGIC_0_PHY_MII_INT_INTR 0 +#define XPAR_DCR_INTC_0_OPB_ETHERNET_0_IP2INTC_IRPT_INTR 1 +#define XPAR_DCR_INTC_0_MISC_LOGIC_0_IIC_TEMP_CRIT_INTR 2 +#define XPAR_DCR_INTC_0_MISC_LOGIC_0_IIC_IRQ_INTR 3 +#define XPAR_DCR_INTC_0_OPB_IIC_0_IP2INTC_IRPT_INTR 4 +#define XPAR_DCR_INTC_0_OPB_SYSACE_0_SYSACE_IRQ_INTR 5 +#define XPAR_DCR_INTC_0_OPB_UART16550_0_IP2INTC_IRPT_INTR 6 +#define XPAR_DCR_INTC_0_OPB_UART16550_1_IP2INTC_IRPT_INTR 7 +#define XPAR_DCR_INTC_0_OPB_PS2_DUAL_REF_0_SYS_INTR1_INTR 8 +#define XPAR_DCR_INTC_0_OPB_PS2_DUAL_REF_0_SYS_INTR2_INTR 9 +#define XPAR_DCR_INTC_0_OPB_SPI_0_IP2INTC_IRPT_INTR 10 +#define XPAR_DCR_INTC_0_OPB_TSD_REF_0_INTR_INTR 11 +#define XPAR_DCR_INTC_0_OPB_AC97_CONTROLLER_REF_0_PLAYBACK_INTERRUPT_INTR 12 +#define XPAR_DCR_INTC_0_OPB_AC97_CONTROLLER_REF_0_RECORD_INTERRUPT_INTR 13 +#define XPAR_DCR_INTC_0_OPB_PCI_REF_0_INTR_OUT_INTR 14 +#define XPAR_DCR_INTC_0_PLB2OPB_BRIDGE_0_BUS_ERROR_DET_INTR 15 +#define XPAR_DCR_INTC_0_PLB_V34_0_BUS_ERROR_DET_INTR 16 +#define XPAR_DCR_INTC_0_OPB2PLB_BRIDGE_0_BUS_ERROR_DET_INTR 17 + +/******************************************************************/ + +#define XPAR_XTFT_NUM_INSTANCES 1 +#define XPAR_PLB_TFT_CNTLR_REF_0_DCR_BASEADDR 0xD0000200 +#define XPAR_PLB_TFT_CNTLR_REF_0_DCR_HIGHADDR 0xD0000207 +#define XPAR_PLB_TFT_CNTLR_REF_0_DEVICE_ID 0 + +/******************************************************************/ + +#define XPAR_XSYSACE_MEM_WIDTH 8 +#define XPAR_XSYSACE_NUM_INSTANCES 1 +#define XPAR_OPB_SYSACE_0_BASEADDR 0xCF000000 +#define XPAR_OPB_SYSACE_0_HIGHADDR 0xCF0001FF +#define XPAR_OPB_SYSACE_0_DEVICE_ID 0 +#define XPAR_OPB_SYSACE_0_MEM_WIDTH 8 + +/******************************************************************/ + +#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 new file mode 100644 index 000000000..a3c37baab --- /dev/null +++ b/board/xilinx/xilinx_enet/emac_adapter.c @@ -0,0 +1,153 @@ +/****************************************************************************** +* +*     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 <net.h> +#include <configs/ml300.h> +#include "xparameters.h" +#include "xemac.h" + +#if defined(XPAR_EMAC_0_DEVICE_ID) +/* + * ENET_MAX_MTU and ENET_MAX_MTU_ALIGNED are set from + * PKTSIZE and PKTSIZE_ALIGN (include/net.h) + */ + +#define ENET_MAX_MTU           PKTSIZE +#define ENET_MAX_MTU_ALIGNED   PKTSIZE_ALIGN +#define ENET_ADDR_LENGTH       6 + +static XEmac Emac; +static char etherrxbuff[PKTSIZE_ALIGN];	/* Receive buffer */ + +/* hardcoded MAC address for the Xilinx EMAC Core */ +static u8 EMACAddr[ENET_ADDR_LENGTH] = { 0x00, 0x0a, 0x35, 0x00, 0x22, 0x01 }; + +static int initialized = 0; + +void +eth_halt(void) +{ +	if (initialized) +		(void) XEmac_Stop(&Emac); +} + +int +eth_init(bd_t * bis) +{ +	u32 Options; +	XStatus Result; + +#ifdef DEBUG +	printf("EMAC Initialization Started\n\r"); +#endif + +	Result = XEmac_Initialize(&Emac, XPAR_EMAC_0_DEVICE_ID); +	if (Result != XST_SUCCESS) { +		return 0; +	} + +	/* make sure the Emac is stopped before it is started */ +	(void) XEmac_Stop(&Emac); + +	memcpy(bis->bi_enetaddr, EMACAddr, 6); +	Result = XEmac_SetMacAddress(&Emac, EMACAddr); +	if (Result != XST_SUCCESS) { +		return 0; +	} + +	Options = +	    (XEM_POLLED_OPTION | XEM_UNICAST_OPTION | XEM_BROADCAST_OPTION | +	     XEM_FDUPLEX_OPTION | XEM_INSERT_FCS_OPTION | +	     XEM_INSERT_PAD_OPTION); +	Result = XEmac_SetOptions(&Emac, Options); +	if (Result != XST_SUCCESS) { +		return 0; +	} + +	Result = XEmac_Start(&Emac); +	if (Result != XST_SUCCESS) { +		return 0; +	} +#ifdef DEBUG +	printf("EMAC Initialization complete\n\r"); +#endif + +	initialized = 1; + +	return (0); +} + +/*-----------------------------------------------------------------------------+ ++-----------------------------------------------------------------------------*/ +int +eth_send(volatile void *ptr, int len) +{ +	XStatus Result; + +	if (len > ENET_MAX_MTU) +		len = ENET_MAX_MTU; + +	Result = XEmac_PollSend(&Emac, (u8 *) ptr, len); +	if (Result == XST_SUCCESS) { +		return (1); +	} else { +		printf("Error while sending frame\n\r"); +		return (0); +	} + +} + +int +eth_rx(void) +{ +	u32 RecvFrameLength; +	XStatus Result; + +	RecvFrameLength = PKTSIZE; +	Result = XEmac_PollRecv(&Emac, (u8 *) etherrxbuff, &RecvFrameLength); +	if (Result == XST_SUCCESS) { +		NetReceive(etherrxbuff, RecvFrameLength); +		return (1); +	} else { +		return (0); +	} +} + +#endif diff --git a/board/xilinx/xilinx_enet/xemac.c b/board/xilinx/xilinx_enet/xemac.c new file mode 100644 index 000000000..48b4ede70 --- /dev/null +++ b/board/xilinx/xilinx_enet/xemac.c @@ -0,0 +1,844 @@ +/****************************************************************************** +* +*     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. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xemac.c +* +* The XEmac driver. Functions in this file are the minimum required functions +* for this driver. See xemac.h for a detailed description of the driver. +* +* <pre> +* MODIFICATION HISTORY: +* +* Ver   Who  Date     Changes +* ----- ---- -------- ------------------------------------------------------- +* 1.00a rpm  07/31/01 First release +* 1.00b rpm  02/20/02 Repartitioned files and functions +* 1.00b rpm  07/23/02 Removed the PHY reset from Initialize() +* 1.00b rmm  09/23/02 Removed commented code in Initialize(). Recycled as +*                     XEmac_mPhyReset macro in xemac_l.h. +* 1.00c rpm  12/05/02 New version includes support for simple DMA +* 1.00c rpm  12/12/02 Changed location of IsStarted assignment in XEmac_Start +*                     to be sure the flag is set before the device and +*                     interrupts are enabled. +* 1.00c rpm  02/03/03 SelfTest was not clearing polled mode. Take driver out +*                     of polled mode in XEmac_Reset() to fix this problem. +* 1.00c rmm  05/13/03 Fixed diab compiler warnings relating to asserts. +* </pre> +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xbasic_types.h" +#include "xemac_i.h" +#include "xio.h" +#include "xipif_v1_23_b.h"	/* Uses v1.23b of the IPIF */ + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static XStatus ConfigureDma(XEmac * InstancePtr); +static XStatus ConfigureFifo(XEmac * InstancePtr); +static void StubFifoHandler(void *CallBackRef); +static void StubErrorHandler(void *CallBackRef, XStatus ErrorCode); +static void StubSgHandler(void *CallBackRef, XBufDescriptor * BdPtr, +			  u32 NumBds); + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* Initialize a specific XEmac instance/driver.  The initialization entails: +* - Initialize fields of the XEmac structure +* - Clear the Ethernet statistics for this device +* - Initialize the IPIF component with its register base address +* - Configure the FIFO components with their register base addresses. +* - If the device is configured with DMA, configure the DMA channel components +*   with their register base addresses. At some later time, memory pools for +*   the scatter-gather descriptor lists may be passed to the driver. +* - Reset the Ethernet MAC +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param DeviceId is the unique id of the device controlled by this XEmac +*        instance.  Passing in a device id associates the generic XEmac +*        instance to a specific device, as chosen by the caller or application +*        developer. +* +* @return +* +* - XST_SUCCESS if initialization was successful +* - XST_DEVICE_IS_STARTED if the device has already been started +* - XST_DEVICE_NOT_FOUND if device configuration information was not found for +*   a device with the supplied device ID. +* +* @note +* +* None. +* +******************************************************************************/ +XStatus +XEmac_Initialize(XEmac * InstancePtr, u16 DeviceId) +{ +	XStatus Result; +	XEmac_Config *ConfigPtr;	/* configuration information */ + +	XASSERT_NONVOID(InstancePtr != NULL); + +	/* +	 * If the device is started, disallow the initialize and return a status +	 * indicating it is started.  This allows the user to stop the device +	 * and reinitialize, but prevents a user from inadvertently initializing +	 */ +	if (InstancePtr->IsStarted == XCOMPONENT_IS_STARTED) { +		return XST_DEVICE_IS_STARTED; +	} + +	/* +	 * Lookup the device configuration in the temporary CROM table. Use this +	 * configuration info down below when initializing this component. +	 */ +	ConfigPtr = XEmac_LookupConfig(DeviceId); +	if (ConfigPtr == NULL) { +		return XST_DEVICE_NOT_FOUND; +	} + +	/* +	 * Set some default values +	 */ +	InstancePtr->IsReady = 0; +	InstancePtr->IsStarted = 0; +	InstancePtr->IpIfDmaConfig = ConfigPtr->IpIfDmaConfig; +	InstancePtr->HasMii = ConfigPtr->HasMii; +	InstancePtr->HasMulticastHash = FALSE; + +	/* Always default polled to false, let user configure this mode */ +	InstancePtr->IsPolled = FALSE; +	InstancePtr->FifoRecvHandler = StubFifoHandler; +	InstancePtr->FifoSendHandler = StubFifoHandler; +	InstancePtr->ErrorHandler = StubErrorHandler; +	InstancePtr->SgRecvHandler = StubSgHandler; +	InstancePtr->SgSendHandler = StubSgHandler; + +	/* +	 * Clear the statistics for this driver +	 */ +	XEmac_mClearStruct((u8 *) & InstancePtr->Stats, sizeof (XEmac_Stats)); + +	/* +	 * Initialize the device register base addresses +	 */ +	InstancePtr->BaseAddress = ConfigPtr->BaseAddress; + +	/* +	 * Configure the send and receive FIFOs in the MAC +	 */ +	Result = ConfigureFifo(InstancePtr); +	if (Result != XST_SUCCESS) { +		return Result; +	} + +	/* +	 * If the device is configured for DMA, configure the send and receive DMA +	 * channels in the MAC. +	 */ +	if (XEmac_mIsDma(InstancePtr)) { +		Result = ConfigureDma(InstancePtr); +		if (Result != XST_SUCCESS) { +			return Result; +		} +	} + +	/* +	 * Indicate the component is now ready to use. Note that this is done before +	 * we reset the device and the PHY below, which may seem a bit odd. The +	 * choice was made to move it here rather than remove the asserts in various +	 * functions (e.g., Reset() and all functions that it calls).  Applications +	 * that use multiple threads, one to initialize the XEmac driver and one +	 * waiting on the IsReady condition could have a problem with this sequence. +	 */ +	InstancePtr->IsReady = XCOMPONENT_IS_READY; + +	/* +	 * Reset the MAC to get it into its initial state. It is expected that +	 * device configuration by the user will take place after this +	 * initialization is done, but before the device is started. +	 */ +	XEmac_Reset(InstancePtr); + +	return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Start the Ethernet controller as follows: +*   - If not in polled mode +*       - Set the internal interrupt enable registers appropriately +*       - Enable interrupts within the device itself. Note that connection of +*         the driver's interrupt handler to the interrupt source (typically +*         done using the interrupt controller component) is done by the higher +*         layer software. +*       - If the device is configured with scatter-gather DMA, start the DMA +*         channels if the descriptor lists are not empty +*   - Enable the transmitter +*   - Enable the receiver +* +* The PHY is enabled after driver initialization. We assume the upper layer +* software has configured it and the EMAC appropriately before this function +* is called. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* +* @return +* +* - XST_SUCCESS if the device was started successfully +* - XST_NO_CALLBACK if a callback function has not yet been registered using +*   the SetxxxHandler function. This is required if in interrupt mode. +* - XST_DEVICE_IS_STARTED if the device is already started +* - XST_DMA_SG_NO_LIST if configured for scatter-gather DMA and a descriptor +*   list has not yet been created for the send or receive channel. +* +* @note +* +* The driver tries to match the hardware configuration. So if the hardware +* is configured with scatter-gather DMA, the driver expects to start the +* scatter-gather channels and expects that the user has set up the buffer +* descriptor lists already. If the user expects to use the driver in a mode +* different than how the hardware is configured, the user should modify the +* configuration table to reflect the mode to be used. Modifying the config +* table is a workaround for now until we get some experience with how users +* are intending to use the hardware in its different configurations. For +* example, if the hardware is built with scatter-gather DMA but the user is +* intending to use only simple DMA, the user either needs to modify the config +* table as a workaround or rebuild the hardware with only simple DMA. +* +* This function makes use of internal resources that are shared between the +* Start, Stop, and SetOptions functions. So if one task might be setting device +* options while another is trying to start the device, the user is required to +* provide protection of this shared data (typically using a semaphore). +* +******************************************************************************/ +XStatus +XEmac_Start(XEmac * InstancePtr) +{ +	u32 ControlReg; +	XStatus Result; + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* +	 * If it is already started, return a status indicating so +	 */ +	if (InstancePtr->IsStarted == XCOMPONENT_IS_STARTED) { +		return XST_DEVICE_IS_STARTED; +	} + +	/* +	 * If not polled, enable interrupts +	 */ +	if (!InstancePtr->IsPolled) { +		/* +		 * Verify that the callbacks have been registered, then enable +		 * interrupts +		 */ +		if (XEmac_mIsSgDma(InstancePtr)) { +			if ((InstancePtr->SgRecvHandler == StubSgHandler) || +			    (InstancePtr->SgSendHandler == StubSgHandler)) { +				return XST_NO_CALLBACK; +			} + +			/* Enable IPIF interrupts */ +			XIIF_V123B_WRITE_DIER(InstancePtr->BaseAddress, +					      XEM_IPIF_DMA_DFT_MASK | +					      XIIF_V123B_ERROR_MASK); +			XIIF_V123B_WRITE_IIER(InstancePtr->BaseAddress, +					      XEM_EIR_DFT_SG_MASK); + +			/* Enable scatter-gather DMA interrupts */ +			XDmaChannel_SetIntrEnable(&InstancePtr->RecvChannel, +						  XEM_DMA_SG_INTR_MASK); +			XDmaChannel_SetIntrEnable(&InstancePtr->SendChannel, +						  XEM_DMA_SG_INTR_MASK); +		} else { +			if ((InstancePtr->FifoRecvHandler == StubFifoHandler) || +			    (InstancePtr->FifoSendHandler == StubFifoHandler)) { +				return XST_NO_CALLBACK; +			} + +			/* Enable IPIF interrupts (used by simple DMA also) */ +			XIIF_V123B_WRITE_DIER(InstancePtr->BaseAddress, +					      XEM_IPIF_FIFO_DFT_MASK | +					      XIIF_V123B_ERROR_MASK); +			XIIF_V123B_WRITE_IIER(InstancePtr->BaseAddress, +					      XEM_EIR_DFT_FIFO_MASK); +		} + +		/* Enable the global IPIF interrupt output */ +		XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress); +	} + +	/* +	 * Indicate that the device is started before we enable the transmitter +	 * or receiver. This needs to be done before because as soon as the +	 * receiver is enabled we may get an interrupt, and there are functions +	 * in the interrupt handling path that rely on the IsStarted flag. +	 */ +	InstancePtr->IsStarted = XCOMPONENT_IS_STARTED; + +	/* +	 * Enable the transmitter, and receiver (do a read/modify/write to preserve +	 * current settings). There is no critical section here since this register +	 * is not modified during interrupt context. +	 */ +	ControlReg = XIo_In32(InstancePtr->BaseAddress + XEM_ECR_OFFSET); +	ControlReg &= ~(XEM_ECR_XMIT_RESET_MASK | XEM_ECR_RECV_RESET_MASK); +	ControlReg |= (XEM_ECR_XMIT_ENABLE_MASK | XEM_ECR_RECV_ENABLE_MASK); + +	XIo_Out32(InstancePtr->BaseAddress + XEM_ECR_OFFSET, ControlReg); + +	/* +	 * If configured with scatter-gather DMA and not polled, restart the +	 * DMA channels in case there are buffers ready to be sent or received into. +	 * The DMA SgStart function uses data that can be modified during interrupt +	 * context, so a critical section is required here. +	 */ +	if ((XEmac_mIsSgDma(InstancePtr)) && (!InstancePtr->IsPolled)) { +		XIIF_V123B_GINTR_DISABLE(InstancePtr->BaseAddress); + +		/* +		 * The only error we care about is if the list has not yet been +		 * created, or on receive, if no buffer descriptors have been +		 * added yet (the list is empty). Other errors are benign at this point. +		 */ +		Result = XDmaChannel_SgStart(&InstancePtr->RecvChannel); +		if ((Result == XST_DMA_SG_NO_LIST) +		    || (Result == XST_DMA_SG_LIST_EMPTY)) { +			XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress); +			return Result; +		} + +		Result = XDmaChannel_SgStart(&InstancePtr->SendChannel); +		if (Result == XST_DMA_SG_NO_LIST) { +			XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress); +			return Result; +		} + +		XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress); +	} + +	return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Stop the Ethernet MAC as follows: +*   - If the device is configured with scatter-gather DMA, stop the DMA +*     channels (wait for acknowledgment of stop) +*   - Disable the transmitter and receiver +*   - Disable interrupts if not in polled mode (the higher layer software is +*     responsible for disabling interrupts at the interrupt controller) +* +* The PHY is left enabled after a Stop is called. +* +* If the device is configured for scatter-gather DMA, the DMA engine stops at +* the next buffer descriptor in its list. The remaining descriptors in the list +* are not removed, so anything in the list will be transmitted or received when +* the device is restarted. The side effect of doing this is that the last +* buffer descriptor processed by the DMA engine before stopping may not be the +* last descriptor in the Ethernet frame. So when the device is restarted, a +* partial frame (i.e., a bad frame) may be transmitted/received. This is only a +* concern if a frame can span multiple buffer descriptors, which is dependent +* on the size of the network buffers. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* +* @return +* +* - XST_SUCCESS if the device was stopped successfully +* - XST_DEVICE_IS_STOPPED if the device is already stopped +* +* @note +* +* This function makes use of internal resources that are shared between the +* Start, Stop, and SetOptions functions. So if one task might be setting device +* options while another is trying to start the device, the user is required to +* provide protection of this shared data (typically using a semaphore). +* +******************************************************************************/ +XStatus +XEmac_Stop(XEmac * InstancePtr) +{ +	u32 ControlReg; + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* +	 * If the device is already stopped, do nothing but return a status +	 * indicating so +	 */ +	if (InstancePtr->IsStarted != XCOMPONENT_IS_STARTED) { +		return XST_DEVICE_IS_STOPPED; +	} + +	/* +	 * If configured for scatter-gather DMA, stop the DMA channels. Ignore +	 * the XST_DMA_SG_IS_STOPPED return code. There is a critical section +	 * here between SgStart and SgStop, and SgStart can be called in interrupt +	 * context, so disable interrupts while calling SgStop. +	 */ +	if (XEmac_mIsSgDma(InstancePtr)) { +		XBufDescriptor *BdTemp;	/* temporary descriptor pointer */ + +		XIIF_V123B_GINTR_DISABLE(InstancePtr->BaseAddress); + +		(void) XDmaChannel_SgStop(&InstancePtr->SendChannel, &BdTemp); +		(void) XDmaChannel_SgStop(&InstancePtr->RecvChannel, &BdTemp); + +		XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress); +	} + +	/* +	 * Disable the transmitter and receiver. There is no critical section +	 * here since this register is not modified during interrupt context. +	 */ +	ControlReg = XIo_In32(InstancePtr->BaseAddress + XEM_ECR_OFFSET); +	ControlReg &= ~(XEM_ECR_XMIT_ENABLE_MASK | XEM_ECR_RECV_ENABLE_MASK); +	XIo_Out32(InstancePtr->BaseAddress + XEM_ECR_OFFSET, ControlReg); + +	/* +	 * If not in polled mode, disable interrupts for IPIF (includes MAC and +	 * DMAs) +	 */ +	if (!InstancePtr->IsPolled) { +		XIIF_V123B_GINTR_DISABLE(InstancePtr->BaseAddress); +	} + +	InstancePtr->IsStarted = 0; + +	return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Reset the Ethernet MAC. This is a graceful reset in that the device is stopped +* first. Resets the DMA channels, the FIFOs, the transmitter, and the receiver. +* The PHY is not reset. Any frames in the scatter-gather descriptor lists will +* remain in the lists. The side effect of doing this is that after a reset and +* following a restart of the device, frames that were in the list before the +* reset may be transmitted or received. Reset must only be called after the +* driver has been initialized. +* +* The driver is also taken out of polled mode if polled mode was set. The user +* is responsbile for re-configuring the driver into polled mode after the +* reset if desired. +* +* The configuration after this reset is as follows: +*   - Half duplex +*   - Disabled transmitter and receiver +*   - Enabled PHY (the PHY is not reset) +*   - MAC transmitter does pad insertion, FCS insertion, and source address +*     overwrite. +*   - MAC receiver does not strip padding or FCS +*   - Interframe Gap as recommended by IEEE Std. 802.3 (96 bit times) +*   - Unicast addressing enabled +*   - Broadcast addressing enabled +*   - Multicast addressing disabled (addresses are preserved) +*   - Promiscuous addressing disabled +*   - Default packet threshold and packet wait bound register values for +*     scatter-gather DMA operation +*   - MAC address of all zeros +*   - Non-polled mode +* +* The upper layer software is responsible for re-configuring (if necessary) +* and restarting the MAC after the reset. Note that the PHY is not reset. PHY +* control is left to the upper layer software. Note also that driver statistics +* are not cleared on reset. It is up to the upper layer software to clear the +* statistics if needed. +* +* When a reset is required due to an internal error, the driver notifies the +* upper layer software of this need through the ErrorHandler callback and +* specific status codes.  The upper layer software is responsible for calling +* this Reset function and then re-configuring the device. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* +* @return +* +* None. +* +* @note +* +* None. +* +* @internal +* +* The reset is accomplished by setting the IPIF reset register.  This takes +* care of resetting all hardware blocks, including the MAC. +* +******************************************************************************/ +void +XEmac_Reset(XEmac * InstancePtr) +{ +	XASSERT_VOID(InstancePtr != NULL); +	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* +	 * Stop the device first +	 */ +	(void) XEmac_Stop(InstancePtr); + +	/* +	 * Take the driver out of polled mode +	 */ +	InstancePtr->IsPolled = FALSE; + +	/* +	 * Reset the entire IPIF at once.  If we choose someday to reset each +	 * hardware block separately, the reset should occur in the direction of +	 * data flow. For example, for the send direction the reset order is DMA +	 * first, then FIFO, then the MAC transmitter. +	 */ +	XIIF_V123B_RESET(InstancePtr->BaseAddress); + +	if (XEmac_mIsSgDma(InstancePtr)) { +		/* +		 * After reset, configure the scatter-gather DMA packet threshold and +		 * packet wait bound registers to default values. Ignore the return +		 * values of these functions since they only return error if the device +		 * is not stopped. +		 */ +		(void) XEmac_SetPktThreshold(InstancePtr, XEM_SEND, +					     XEM_SGDMA_DFT_THRESHOLD); +		(void) XEmac_SetPktThreshold(InstancePtr, XEM_RECV, +					     XEM_SGDMA_DFT_THRESHOLD); +		(void) XEmac_SetPktWaitBound(InstancePtr, XEM_SEND, +					     XEM_SGDMA_DFT_WAITBOUND); +		(void) XEmac_SetPktWaitBound(InstancePtr, XEM_RECV, +					     XEM_SGDMA_DFT_WAITBOUND); +	} +} + +/*****************************************************************************/ +/** +* +* Set the MAC address for this driver/device.  The address is a 48-bit value. +* The device must be stopped before calling this function. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param AddressPtr is a pointer to a 6-byte MAC address. +* +* @return +* +* - XST_SUCCESS if the MAC address was set successfully +* - XST_DEVICE_IS_STARTED if the device has not yet been stopped +* +* @note +* +* None. +* +******************************************************************************/ +XStatus +XEmac_SetMacAddress(XEmac * InstancePtr, u8 * AddressPtr) +{ +	u32 MacAddr = 0; + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(AddressPtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* +	 * The device must be stopped before setting the MAC address +	 */ +	if (InstancePtr->IsStarted == XCOMPONENT_IS_STARTED) { +		return XST_DEVICE_IS_STARTED; +	} + +	/* +	 * Set the device station address high and low registers +	 */ +	MacAddr = (AddressPtr[0] << 8) | AddressPtr[1]; +	XIo_Out32(InstancePtr->BaseAddress + XEM_SAH_OFFSET, MacAddr); + +	MacAddr = (AddressPtr[2] << 24) | (AddressPtr[3] << 16) | +	    (AddressPtr[4] << 8) | AddressPtr[5]; + +	XIo_Out32(InstancePtr->BaseAddress + XEM_SAL_OFFSET, MacAddr); + +	return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Get the MAC address for this driver/device. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param BufferPtr is an output parameter, and is a pointer to a buffer into +*        which the current MAC address will be copied. The buffer must be at +*        least 6 bytes. +* +* @return +* +* None. +* +* @note +* +* None. +* +******************************************************************************/ +void +XEmac_GetMacAddress(XEmac * InstancePtr, u8 * BufferPtr) +{ +	u32 MacAddrHi; +	u32 MacAddrLo; + +	XASSERT_VOID(InstancePtr != NULL); +	XASSERT_VOID(BufferPtr != NULL); +	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	MacAddrHi = XIo_In32(InstancePtr->BaseAddress + XEM_SAH_OFFSET); +	MacAddrLo = XIo_In32(InstancePtr->BaseAddress + XEM_SAL_OFFSET); + +	BufferPtr[0] = (u8) (MacAddrHi >> 8); +	BufferPtr[1] = (u8) MacAddrHi; +	BufferPtr[2] = (u8) (MacAddrLo >> 24); +	BufferPtr[3] = (u8) (MacAddrLo >> 16); +	BufferPtr[4] = (u8) (MacAddrLo >> 8); +	BufferPtr[5] = (u8) MacAddrLo; +} + +/******************************************************************************/ +/** +* +* Configure DMA capabilities. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* +* @return +* +* - XST_SUCCESS  if successful initialization of DMA +* +* @note +* +* None. +* +******************************************************************************/ +static XStatus +ConfigureDma(XEmac * InstancePtr) +{ +	XStatus Result; + +	/* +	 * Initialize the DMA channels with their base addresses. We assume +	 * scatter-gather DMA is the only possible configuration. Descriptor space +	 * will need to be set later by the upper layer. +	 */ +	Result = XDmaChannel_Initialize(&InstancePtr->RecvChannel, +					InstancePtr->BaseAddress + +					XEM_DMA_RECV_OFFSET); +	if (Result != XST_SUCCESS) { +		return Result; +	} + +	Result = XDmaChannel_Initialize(&InstancePtr->SendChannel, +					InstancePtr->BaseAddress + +					XEM_DMA_SEND_OFFSET); + +	return Result; +} + +/******************************************************************************/ +/** +* +* Configure the send and receive FIFO components with their base addresses +* and interrupt masks.  Currently the base addresses are defined constants. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* +* @return +* +* XST_SUCCESS if successful initialization of the packet FIFOs +* +* @note +* +* None. +* +******************************************************************************/ +static XStatus +ConfigureFifo(XEmac * InstancePtr) +{ +	XStatus Result; + +	/* +	 * Return status from the packet FIFOs initialization is ignored since +	 * they always return success. +	 */ +	Result = XPacketFifoV100b_Initialize(&InstancePtr->RecvFifo, +					     InstancePtr->BaseAddress + +					     XEM_PFIFO_RXREG_OFFSET, +					     InstancePtr->BaseAddress + +					     XEM_PFIFO_RXDATA_OFFSET); +	if (Result != XST_SUCCESS) { +		return Result; +	} + +	Result = XPacketFifoV100b_Initialize(&InstancePtr->SendFifo, +					     InstancePtr->BaseAddress + +					     XEM_PFIFO_TXREG_OFFSET, +					     InstancePtr->BaseAddress + +					     XEM_PFIFO_TXDATA_OFFSET); +	return Result; +} + +/******************************************************************************/ +/** +* +* This is a stub for the scatter-gather send and recv callbacks. The stub +* is here in case the upper layers forget to set the handlers. +* +* @param CallBackRef is a pointer to the upper layer callback reference +* @param BdPtr is a pointer to the first buffer descriptor in a list +* @param NumBds is the number of descriptors in the list. +* +* @return +* +* None. +* +* @note +* +* None. +* +******************************************************************************/ +static void +StubSgHandler(void *CallBackRef, XBufDescriptor * BdPtr, u32 NumBds) +{ +	XASSERT_VOID_ALWAYS(); +} + +/******************************************************************************/ +/** +* +* This is a stub for the non-DMA send and recv callbacks.  The stub is here in +* case the upper layers forget to set the handlers. +* +* @param CallBackRef is a pointer to the upper layer callback reference +* +* @return +* +* None. +* +* @note +* +* None. +* +******************************************************************************/ +static void +StubFifoHandler(void *CallBackRef) +{ +	XASSERT_VOID_ALWAYS(); +} + +/******************************************************************************/ +/** +* +* This is a stub for the asynchronous error callback.  The stub is here in +* case the upper layers forget to set the handler. +* +* @param CallBackRef is a pointer to the upper layer callback reference +* @param ErrorCode is the Xilinx error code, indicating the cause of the error +* +* @return +* +* None. +* +* @note +* +* None. +* +******************************************************************************/ +static void +StubErrorHandler(void *CallBackRef, XStatus ErrorCode) +{ +	XASSERT_VOID_ALWAYS(); +} + +/*****************************************************************************/ +/** +* +* Lookup the device configuration based on the unique device ID.  The table +* EmacConfigTable contains the configuration info for each device in the system. +* +* @param DeviceId is the unique device ID of the device being looked up. +* +* @return +* +* A pointer to the configuration table entry corresponding to the given +* device ID, or NULL if no match is found. +* +* @note +* +* None. +* +******************************************************************************/ +XEmac_Config * +XEmac_LookupConfig(u16 DeviceId) +{ +	XEmac_Config *CfgPtr = NULL; +	int i; + +	for (i = 0; i < XPAR_XEMAC_NUM_INSTANCES; i++) { +		if (XEmac_ConfigTable[i].DeviceId == DeviceId) { +			CfgPtr = &XEmac_ConfigTable[i]; +			break; +		} +	} + +	return CfgPtr; +} diff --git a/board/xilinx/xilinx_enet/xemac.h b/board/xilinx/xilinx_enet/xemac.h new file mode 100644 index 000000000..ed704bf29 --- /dev/null +++ b/board/xilinx/xilinx_enet/xemac.h @@ -0,0 +1,673 @@ +/****************************************************************************** +* +*     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. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xemac.h +* +* The Xilinx Ethernet driver component.	 This component supports the Xilinx +* Ethernet 10/100 MAC (EMAC). +* +* The Xilinx Ethernet 10/100 MAC supports the following features: +*   - Simple and scatter-gather DMA operations, as well as simple memory +*     mapped direct I/O interface (FIFOs). +*   - Media Independent Interface (MII) for connection to external +*     10/100 Mbps PHY transceivers. +*   - MII management control reads and writes with MII PHYs +*   - Independent internal transmit and receive FIFOs +*   - CSMA/CD compliant operations for half-duplex modes +*   - Programmable PHY reset signal +*   - Unicast, broadcast, and promiscuous address filtering (no multicast yet) +*   - Internal loopback +*   - Automatic source address insertion or overwrite (programmable) +*   - Automatic FCS insertion and stripping (programmable) +*   - Automatic pad insertion and stripping (programmable) +*   - Pause frame (flow control) detection in full-duplex mode +*   - Programmable interframe gap +*   - VLAN frame support. +*   - Pause frame support +* +* The device driver supports all the features listed above. +* +* <b>Driver Description</b> +* +* The device driver enables higher layer software (e.g., an application) to +* communicate to the EMAC. The driver handles transmission and reception of +* Ethernet frames, as well as configuration of the controller. It does not +* handle protocol stack functionality such as Link Layer Control (LLC) or the +* Address Resolution Protocol (ARP). The protocol stack that makes use of the +* driver handles this functionality. This implies that the driver is simply a +* pass-through mechanism between a protocol stack and the EMAC. A single device +* driver can support multiple EMACs. +* +* The driver is designed for a zero-copy buffer scheme. That is, the driver will +* not copy buffers. This avoids potential throughput bottlenecks within the +* driver. +* +* Since the driver is a simple pass-through mechanism between a protocol stack +* and the EMAC, no assembly or disassembly of Ethernet frames is done at the +* driver-level. This assumes that the protocol stack passes a correctly +* formatted Ethernet frame to the driver for transmission, and that the driver +* does not validate the contents of an incoming frame +* +* <b>PHY Communication</b> +* +* The driver provides rudimentary read and write functions to allow the higher +* layer software to access the PHY. The EMAC provides MII registers for the +* driver to access. This management interface can be parameterized away in the +* FPGA implementation process. If this is the case, the PHY read and write +* functions of the driver return XST_NO_FEATURE. +* +* External loopback is usually supported at the PHY. It is up to the user to +* turn external loopback on or off at the PHY. The driver simply provides pass- +* through functions for configuring the PHY. The driver does not read, write, +* or reset the PHY on its own. All control of the PHY must be done by the user. +* +* <b>Asynchronous Callbacks</b> +* +* The driver services interrupts and passes Ethernet frames to the higher layer +* software through asynchronous callback functions. When using the driver +* directly (i.e., not with the RTOS protocol stack), the higher layer +* software must register its callback functions during initialization. The +* driver requires callback functions for received frames, for confirmation of +* transmitted frames, and for asynchronous errors. +* +* <b>Interrupts</b> +* +* The driver has no dependencies on the interrupt controller. The driver +* provides two interrupt handlers.  XEmac_IntrHandlerDma() handles interrupts +* when the EMAC is configured with scatter-gather DMA.	XEmac_IntrHandlerFifo() +* handles interrupts when the EMAC is configured for direct FIFO I/O or simple +* DMA.	Either of these routines can be connected to the system interrupt +* controller by the user. +* +* <b>Interrupt Frequency</b> +* +* When the EMAC is configured with scatter-gather DMA, the frequency of +* interrupts can be controlled with the interrupt coalescing features of the +* scatter-gather DMA engine. The frequency of interrupts can be adjusted using +* the driver API functions for setting the packet count threshold and the packet +* wait bound values. +* +* The scatter-gather DMA engine only interrupts when the packet count threshold +* is reached, instead of interrupting for each packet. A packet is a generic +* term used by the scatter-gather DMA engine, and is equivalent to an Ethernet +* frame in our case. +* +* The packet wait bound is a timer value used during interrupt coalescing to +* trigger an interrupt when not enough packets have been received to reach the +* packet count threshold. +* +* These values can be tuned by the user to meet their needs. If there appear to +* be interrupt latency problems or delays in packet arrival that are longer than +* might be expected, the user should verify that the packet count threshold is +* set low enough to receive interrupts before the wait bound timer goes off. +* +* <b>Device Reset</b> +* +* Some errors that can occur in the device require a device reset. These errors +* are listed in the XEmac_SetErrorHandler() function header. The user's error +* handler is responsible for resetting the device and re-configuring it based on +* its needs (the driver does not save the current configuration). When +* integrating into an RTOS, these reset and re-configure obligations are +* taken care of by the Xilinx adapter software if it exists for that RTOS. +* +* <b>Device Configuration</b> +* +* The device can be configured in various ways during the FPGA implementation +* process.  Configuration parameters are stored in the xemac_g.c files. +* A table is defined where each entry contains configuration information +* for an EMAC device.  This information includes such things as the base address +* of the memory-mapped device, the base addresses of IPIF, DMA, and FIFO modules +* within the device, and whether the device has DMA, counter registers, +* multicast support, MII support, and flow control. +* +* The driver tries to use the features built into the device. So if, for +* example, the hardware is configured with scatter-gather DMA, the driver +* expects to start the scatter-gather channels and expects that the user has set +* up the buffer descriptor lists already. If the user expects to use the driver +* in a mode different than how the hardware is configured, the user should +* modify the configuration table to reflect the mode to be used. Modifying the +* configuration table is a workaround for now until we get some experience with +* how users are intending to use the hardware in its different configurations. +* For example, if the hardware is built with scatter-gather DMA but the user is +* intending to use only simple DMA, the user either needs to modify the config +* table as a workaround or rebuild the hardware with only simple DMA. The +* recommendation at this point is to build the hardware with the features you +* intend to use. If you're inclined to modify the table, do so before the call +* to XEmac_Initialize().  Here is a snippet of code that changes a device to +* simple DMA (the hardware needs to have DMA for this to work of course): +* <pre> +*	 XEmac_Config *ConfigPtr; +* +*	 ConfigPtr = XEmac_LookupConfig(DeviceId); +*	 ConfigPtr->IpIfDmaConfig = XEM_CFG_SIMPLE_DMA; +* </pre> +* +* <b>Simple DMA</b> +* +* Simple DMA is supported through the FIFO functions, FifoSend and FifoRecv, of +* the driver (i.e., there is no separate interface for it). The driver makes use +* of the DMA engine for a simple DMA transfer if the device is configured with +* DMA, otherwise it uses the FIFOs directly. While the simple DMA interface is +* therefore transparent to the user, the caching of network buffers is not. +* If the device is configured with DMA and the FIFO interface is used, the user +* must ensure that the network buffers are not cached or are cache coherent, +* since DMA will be used to transfer to and from the Emac device. If the device +* is configured with DMA and the user really wants to use the FIFOs directly, +* the user should rebuild the hardware without DMA. If unable to do this, there +* is a workaround (described above in Device Configuration) to modify the +* configuration table of the driver to fake the driver into thinking the device +* has no DMA. A code snippet follows: +* <pre> +*	 XEmac_Config *ConfigPtr; +* +*	 ConfigPtr = XEmac_LookupConfig(DeviceId); +*	 ConfigPtr->IpIfDmaConfig = XEM_CFG_NO_DMA; +* </pre> +* +* <b>Asserts</b> +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and it +* is recommended that users leave asserts on during development. +* +* <b>Building the driver</b> +* +* The XEmac driver is composed of several source files. Why so many?  This +* allows the user to build and link only those parts of the driver that are +* necessary. Since the EMAC hardware can be configured in various ways (e.g., +* with or without DMA), the driver too can be built with varying features. +* For the most part, this means that besides always linking in xemac.c, you +* link in only the driver functionality you want. Some of the choices you have +* are polled vs. interrupt, interrupt with FIFOs only vs. interrupt with DMA, +* self-test diagnostics, and driver statistics. Note that currently the DMA code +* must be linked in, even if you don't have DMA in the device. +* +* @note +* +* Xilinx drivers are typically composed of two components, one is the driver +* and the other is the adapter.	 The driver is independent of OS and processor +* and is intended to be highly portable.  The adapter is OS-specific and +* facilitates communication between the driver and an OS. +* <br><br> +* This driver is intended to be RTOS and processor independent.	 It works +* with physical addresses only.	 Any needs for dynamic memory management, +* threads or thread mutual exclusion, virtual memory, or cache control must +* be satisfied by the layer above this driver. +* +* <pre> +* MODIFICATION HISTORY: +* +* Ver	Who  Date     Changes +* ----- ---- -------- ------------------------------------------------------- +* 1.00a rpm  07/31/01 First release +* 1.00b rpm  02/20/02 Repartitioned files and functions +* 1.00b rpm  10/08/02 Replaced HasSgDma boolean with IpifDmaConfig enumerated +*		      configuration parameter +* 1.00c rpm  12/05/02 New version includes support for simple DMA and the delay +*		      argument to SgSend +* 1.00c rpm  02/03/03 The XST_DMA_SG_COUNT_EXCEEDED return code was removed +*		      from SetPktThreshold in the internal DMA driver. Also +*		      avoided compiler warnings by initializing Result in the +*		      DMA interrupt service routines. +* </pre> +* +******************************************************************************/ + +#ifndef XEMAC_H			/* prevent circular inclusions */ +#define XEMAC_H			/* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xbasic_types.h" +#include "xstatus.h" +#include "xparameters.h" +#include "xpacket_fifo_v1_00_b.h"	/* Uses v1.00b of Packet Fifo */ +#include "xdma_channel.h" + +/************************** Constant Definitions *****************************/ + +/* + * Device information + */ +#define XEM_DEVICE_NAME	    "xemac" +#define XEM_DEVICE_DESC	    "Xilinx Ethernet 10/100 MAC" + +/** @name Configuration options + * + * Device configuration options (see the XEmac_SetOptions() and + * XEmac_GetOptions() for information on how to use these options) + * @{ + */ +/** + * <pre> + *   XEM_BROADCAST_OPTION	 Broadcast addressing on or off (default is on) + *   XEM_UNICAST_OPTION		 Unicast addressing on or off (default is on) + *   XEM_PROMISC_OPTION		 Promiscuous addressing on or off (default is off) + *   XEM_FDUPLEX_OPTION		 Full duplex on or off (default is off) + *   XEM_POLLED_OPTION		 Polled mode on or off (default is off) + *   XEM_LOOPBACK_OPTION	 Internal loopback on or off (default is off) + *   XEM_FLOW_CONTROL_OPTION	 Interpret pause frames in full duplex mode + *				 (default is off) + *   XEM_INSERT_PAD_OPTION	 Pad short frames on transmit (default is on) + *   XEM_INSERT_FCS_OPTION	 Insert FCS (CRC) on transmit (default is on) + *   XEM_INSERT_ADDR_OPTION	 Insert source address on transmit (default is on) + *   XEM_OVWRT_ADDR_OPTION	 Overwrite source address on transmit. This is + *				 only used if source address insertion is on. + *				 (default is on) + *   XEM_STRIP_PAD_FCS_OPTION	 Strip FCS and padding from received frames + *				 (default is off) +  * </pre> + */ +#define XEM_UNICAST_OPTION	  0x00000001UL +#define XEM_BROADCAST_OPTION	  0x00000002UL +#define XEM_PROMISC_OPTION	  0x00000004UL +#define XEM_FDUPLEX_OPTION	  0x00000008UL +#define XEM_POLLED_OPTION	  0x00000010UL +#define XEM_LOOPBACK_OPTION	  0x00000020UL +#define XEM_FLOW_CONTROL_OPTION	  0x00000080UL +#define XEM_INSERT_PAD_OPTION	  0x00000100UL +#define XEM_INSERT_FCS_OPTION	  0x00000200UL +#define XEM_INSERT_ADDR_OPTION	  0x00000400UL +#define XEM_OVWRT_ADDR_OPTION	  0x00000800UL +#define XEM_STRIP_PAD_FCS_OPTION  0x00002000UL +/*@}*/ +/* + * Not supported yet: + *   XEM_MULTICAST_OPTION	 Multicast addressing on or off (default is off) + */ +/* NOT SUPPORTED YET... */ +#define XEM_MULTICAST_OPTION	  0x00000040UL + +/* + * Some default values for interrupt coalescing within the scatter-gather + * DMA engine. + */ +#define XEM_SGDMA_DFT_THRESHOLD	    1	/* Default pkt threshold */ +#define XEM_SGDMA_MAX_THRESHOLD	    255 /* Maximum pkt theshold */ +#define XEM_SGDMA_DFT_WAITBOUND	    5	/* Default pkt wait bound (msec) */ +#define XEM_SGDMA_MAX_WAITBOUND	    1023	/* Maximum pkt wait bound (msec) */ + +/* + * Direction identifiers. These are used for setting values like packet + * thresholds and wait bound for specific channels + */ +#define XEM_SEND    1 +#define XEM_RECV    2 + +/* + * Arguments to SgSend function to indicate whether to hold off starting + * the scatter-gather engine. + */ +#define XEM_SGDMA_NODELAY     0 /* start SG DMA immediately */ +#define XEM_SGDMA_DELAY	      1 /* do not start SG DMA */ + +/* + * Constants to determine the configuration of the hardware device. They are + * used to allow the driver to verify it can operate with the hardware. + */ +#define XEM_CFG_NO_IPIF		    0	/* Not supported by the driver */ +#define XEM_CFG_NO_DMA		    1	/* No DMA */ +#define XEM_CFG_SIMPLE_DMA	    2	/* Simple DMA */ +#define XEM_CFG_DMA_SG		    3	/* DMA scatter gather */ + +/* + * The next few constants help upper layers determine the size of memory + * pools used for Ethernet buffers and descriptor lists. + */ +#define XEM_MAC_ADDR_SIZE   6	/* six-byte MAC address */ +#define XEM_MTU		    1500	/* max size of Ethernet frame */ +#define XEM_HDR_SIZE	    14	/* size of Ethernet header */ +#define XEM_HDR_VLAN_SIZE   18	/* size of Ethernet header with VLAN */ +#define XEM_TRL_SIZE	    4	/* size of Ethernet trailer (FCS) */ +#define XEM_MAX_FRAME_SIZE  (XEM_MTU + XEM_HDR_SIZE + XEM_TRL_SIZE) +#define XEM_MAX_VLAN_FRAME_SIZE	 (XEM_MTU + XEM_HDR_VLAN_SIZE + XEM_TRL_SIZE) + +/* + * Define a default number of send and receive buffers + */ +#define XEM_MIN_RECV_BUFS   32	/* minimum # of recv buffers */ +#define XEM_DFT_RECV_BUFS   64	/* default # of recv buffers */ + +#define XEM_MIN_SEND_BUFS   16	/* minimum # of send buffers */ +#define XEM_DFT_SEND_BUFS   32	/* default # of send buffers */ + +#define XEM_MIN_BUFFERS	    (XEM_MIN_RECV_BUFS + XEM_MIN_SEND_BUFS) +#define XEM_DFT_BUFFERS	    (XEM_DFT_RECV_BUFS + XEM_DFT_SEND_BUFS) + +/* + * Define the number of send and receive buffer descriptors, used for + * scatter-gather DMA + */ +#define XEM_MIN_RECV_DESC   16	/* minimum # of recv descriptors */ +#define XEM_DFT_RECV_DESC   32	/* default # of recv descriptors */ + +#define XEM_MIN_SEND_DESC   8	/* minimum # of send descriptors */ +#define XEM_DFT_SEND_DESC   16	/* default # of send descriptors */ + +/**************************** Type Definitions *******************************/ + +/** + * Ethernet statistics (see XEmac_GetStats() and XEmac_ClearStats()) + */ +typedef struct { +	u32 XmitFrames;		 /**< Number of frames transmitted */ +	u32 XmitBytes;		 /**< Number of bytes transmitted */ +	u32 XmitLateCollisionErrors; +				 /**< Number of transmission failures +					  due to late collisions */ +	u32 XmitExcessDeferral;	 /**< Number of transmission failures +					  due o excess collision deferrals */ +	u32 XmitOverrunErrors;	 /**< Number of transmit overrun errors */ +	u32 XmitUnderrunErrors;	 /**< Number of transmit underrun errors */ +	u32 RecvFrames;		 /**< Number of frames received */ +	u32 RecvBytes;		 /**< Number of bytes received */ +	u32 RecvFcsErrors;	 /**< Number of frames discarded due +					  to FCS errors */ +	u32 RecvAlignmentErrors; /**< Number of frames received with +					  alignment errors */ +	u32 RecvOverrunErrors;	 /**< Number of frames discarded due +					  to overrun errors */ +	u32 RecvUnderrunErrors;	 /**< Number of recv underrun errors */ +	u32 RecvMissedFrameErrors; +				 /**< Number of frames missed by MAC */ +	u32 RecvCollisionErrors; /**< Number of frames discarded due +					  to collisions */ +	u32 RecvLengthFieldErrors; +				 /**< Number of frames discarded with +					  invalid length field */ +	u32 RecvShortErrors;	 /**< Number of short frames discarded */ +	u32 RecvLongErrors;	 /**< Number of long frames discarded */ +	u32 DmaErrors;		 /**< Number of DMA errors since init */ +	u32 FifoErrors;		 /**< Number of FIFO errors since init */ +	u32 RecvInterrupts;	 /**< Number of receive interrupts */ +	u32 XmitInterrupts;	 /**< Number of transmit interrupts */ +	u32 EmacInterrupts;	 /**< Number of MAC (device) interrupts */ +	u32 TotalIntrs;		 /**< Total interrupts */ +} XEmac_Stats; + +/** + * This typedef contains configuration information for a device. + */ +typedef struct { +	u16 DeviceId;	    /**< Unique ID  of device */ +	u32 BaseAddress;    /**< Register base address */ +	u32 HasCounters;   /**< Does device have counters? */ +	u8 IpIfDmaConfig;   /**< IPIF/DMA hardware configuration */ +	u32 HasMii;	   /**< Does device support MII? */ + +} XEmac_Config; + +/** @name Typedefs for callbacks + * Callback functions. + * @{ + */ +/** + * Callback when data is sent or received with scatter-gather DMA. + * + * @param CallBackRef is a callback reference passed in by the upper layer + *	  when setting the callback functions, and passed back to the upper + *	  layer when the callback is invoked. + * @param BdPtr is a pointer to the first buffer descriptor in a list of + *	  buffer descriptors. + * @param NumBds is the number of buffer descriptors in the list pointed + *	  to by BdPtr. + */ +typedef void (*XEmac_SgHandler) (void *CallBackRef, XBufDescriptor * BdPtr, +				 u32 NumBds); + +/** + * Callback when data is sent or received with direct FIFO communication or + * simple DMA. The user typically defines two callacks, one for send and one + * for receive. + * + * @param CallBackRef is a callback reference passed in by the upper layer + *	  when setting the callback functions, and passed back to the upper + *	  layer when the callback is invoked. + */ +typedef void (*XEmac_FifoHandler) (void *CallBackRef); + +/** + * Callback when an asynchronous error occurs. + * + * @param CallBackRef is a callback reference passed in by the upper layer + *	  when setting the callback functions, and passed back to the upper + *	  layer when the callback is invoked. + * @param ErrorCode is a Xilinx error code defined in xstatus.h.  Also see + *	  XEmac_SetErrorHandler() for a description of possible errors. + */ +typedef void (*XEmac_ErrorHandler) (void *CallBackRef, XStatus ErrorCode); +/*@}*/ + +/** + * The XEmac driver instance data. The user is required to allocate a + * variable of this type for every EMAC device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct { +	u32 BaseAddress;	/* Base address (of IPIF) */ +	u32 IsStarted;		/* Device is currently started */ +	u32 IsReady;		/* Device is initialized and ready */ +	u32 IsPolled;		/* Device is in polled mode */ +	u8 IpIfDmaConfig;	/* IPIF/DMA hardware configuration */ +	u32 HasMii;		/* Does device support MII? */ +	u32 HasMulticastHash;	/* Does device support multicast hash table? */ + +	XEmac_Stats Stats; +	XPacketFifoV100b RecvFifo;	/* FIFO used to receive frames */ +	XPacketFifoV100b SendFifo;	/* FIFO used to send frames */ + +	/* +	 * Callbacks +	 */ +	XEmac_FifoHandler FifoRecvHandler;	/* for non-DMA/simple DMA interrupts */ +	void *FifoRecvRef; +	XEmac_FifoHandler FifoSendHandler;	/* for non-DMA/simple DMA interrupts */ +	void *FifoSendRef; +	XEmac_ErrorHandler ErrorHandler;	/* for asynchronous errors */ +	void *ErrorRef; + +	XDmaChannel RecvChannel;	/* DMA receive channel driver */ +	XDmaChannel SendChannel;	/* DMA send channel driver */ + +	XEmac_SgHandler SgRecvHandler;	/* callback for scatter-gather DMA */ +	void *SgRecvRef; +	XEmac_SgHandler SgSendHandler;	/* callback for scatter-gather DMA */ +	void *SgSendRef; +} XEmac; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** +* +* This macro determines if the device is currently configured for +* scatter-gather DMA. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* +* @return +* +* Boolean TRUE if the device is configured for scatter-gather DMA, or FALSE +* if it is not. +* +* @note +* +* Signature: u32 XEmac_mIsSgDma(XEmac *InstancePtr) +* +******************************************************************************/ +#define XEmac_mIsSgDma(InstancePtr) \ +	    ((InstancePtr)->IpIfDmaConfig == XEM_CFG_DMA_SG) + +/*****************************************************************************/ +/** +* +* This macro determines if the device is currently configured for simple DMA. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* +* @return +* +* Boolean TRUE if the device is configured for simple DMA, or FALSE otherwise +* +* @note +* +* Signature: u32 XEmac_mIsSimpleDma(XEmac *InstancePtr) +* +******************************************************************************/ +#define XEmac_mIsSimpleDma(InstancePtr) \ +	    ((InstancePtr)->IpIfDmaConfig == XEM_CFG_SIMPLE_DMA) + +/*****************************************************************************/ +/** +* +* This macro determines if the device is currently configured with DMA (either +* simple DMA or scatter-gather DMA) +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* +* @return +* +* Boolean TRUE if the device is configured with DMA, or FALSE otherwise +* +* @note +* +* Signature: u32 XEmac_mIsDma(XEmac *InstancePtr) +* +******************************************************************************/ +#define XEmac_mIsDma(InstancePtr) \ +	    (XEmac_mIsSimpleDma(InstancePtr) || XEmac_mIsSgDma(InstancePtr)) + +/************************** Function Prototypes ******************************/ + +/* + * Initialization functions in xemac.c + */ +XStatus XEmac_Initialize(XEmac * InstancePtr, u16 DeviceId); +XStatus XEmac_Start(XEmac * InstancePtr); +XStatus XEmac_Stop(XEmac * InstancePtr); +void XEmac_Reset(XEmac * InstancePtr); +XEmac_Config *XEmac_LookupConfig(u16 DeviceId); + +/* + * Diagnostic functions in xemac_selftest.c + */ +XStatus XEmac_SelfTest(XEmac * InstancePtr); + +/* + * Polled functions in xemac_polled.c + */ +XStatus XEmac_PollSend(XEmac * InstancePtr, u8 * BufPtr, u32 ByteCount); +XStatus XEmac_PollRecv(XEmac * InstancePtr, u8 * BufPtr, u32 * ByteCountPtr); + +/* + * Interrupts with scatter-gather DMA functions in xemac_intr_dma.c + */ +XStatus XEmac_SgSend(XEmac * InstancePtr, XBufDescriptor * BdPtr, int Delay); +XStatus XEmac_SgRecv(XEmac * InstancePtr, XBufDescriptor * BdPtr); +XStatus XEmac_SetPktThreshold(XEmac * InstancePtr, u32 Direction, u8 Threshold); +XStatus XEmac_GetPktThreshold(XEmac * InstancePtr, u32 Direction, +			      u8 * ThreshPtr); +XStatus XEmac_SetPktWaitBound(XEmac * InstancePtr, u32 Direction, +			      u32 TimerValue); +XStatus XEmac_GetPktWaitBound(XEmac * InstancePtr, u32 Direction, +			      u32 * WaitPtr); +XStatus XEmac_SetSgRecvSpace(XEmac * InstancePtr, u32 * MemoryPtr, +			     u32 ByteCount); +XStatus XEmac_SetSgSendSpace(XEmac * InstancePtr, u32 * MemoryPtr, +			     u32 ByteCount); +void XEmac_SetSgRecvHandler(XEmac * InstancePtr, void *CallBackRef, +			    XEmac_SgHandler FuncPtr); +void XEmac_SetSgSendHandler(XEmac * InstancePtr, void *CallBackRef, +			    XEmac_SgHandler FuncPtr); + +void XEmac_IntrHandlerDma(void *InstancePtr);	/* interrupt handler */ + +/* + * Interrupts with direct FIFO functions in xemac_intr_fifo.c. Also used + * for simple DMA. + */ +XStatus XEmac_FifoSend(XEmac * InstancePtr, u8 * BufPtr, u32 ByteCount); +XStatus XEmac_FifoRecv(XEmac * InstancePtr, u8 * BufPtr, u32 * ByteCountPtr); +void XEmac_SetFifoRecvHandler(XEmac * InstancePtr, void *CallBackRef, +			      XEmac_FifoHandler FuncPtr); +void XEmac_SetFifoSendHandler(XEmac * InstancePtr, void *CallBackRef, +			      XEmac_FifoHandler FuncPtr); + +void XEmac_IntrHandlerFifo(void *InstancePtr);	/* interrupt handler */ + +/* + * General interrupt-related functions in xemac_intr.c + */ +void XEmac_SetErrorHandler(XEmac * InstancePtr, void *CallBackRef, +			   XEmac_ErrorHandler FuncPtr); + +/* + * MAC configuration in xemac_options.c + */ +XStatus XEmac_SetOptions(XEmac * InstancePtr, u32 OptionFlag); +u32 XEmac_GetOptions(XEmac * InstancePtr); +XStatus XEmac_SetMacAddress(XEmac * InstancePtr, u8 * AddressPtr); +void XEmac_GetMacAddress(XEmac * InstancePtr, u8 * BufferPtr); +XStatus XEmac_SetInterframeGap(XEmac * InstancePtr, u8 Part1, u8 Part2); +void XEmac_GetInterframeGap(XEmac * InstancePtr, u8 * Part1Ptr, u8 * Part2Ptr); + +/* + * Multicast functions in xemac_multicast.c (not supported by EMAC yet) + */ +XStatus XEmac_MulticastAdd(XEmac * InstancePtr, u8 * AddressPtr); +XStatus XEmac_MulticastClear(XEmac * InstancePtr); + +/* + * PHY configuration in xemac_phy.c + */ +XStatus XEmac_PhyRead(XEmac * InstancePtr, u32 PhyAddress, +		      u32 RegisterNum, u16 * PhyDataPtr); +XStatus XEmac_PhyWrite(XEmac * InstancePtr, u32 PhyAddress, +		       u32 RegisterNum, u16 PhyData); + +/* + * Statistics in xemac_stats.c + */ +void XEmac_GetStats(XEmac * InstancePtr, XEmac_Stats * StatsPtr); +void XEmac_ClearStats(XEmac * InstancePtr); + +#endif				/* end of protection macro */ diff --git a/board/xilinx/xilinx_enet/xemac_g.c b/board/xilinx/xilinx_enet/xemac_g.c new file mode 100644 index 000000000..9340f911f --- /dev/null +++ b/board/xilinx/xilinx_enet/xemac_g.c @@ -0,0 +1,60 @@ +/******************************************************************* +* +* CAUTION: This file is automatically generated by libgen. +* Version: Xilinx EDK 6.1.2 EDK_G.14 +* 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. +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xemac.h" + +/* +* The configuration table for devices +*/ + +XEmac_Config XEmac_ConfigTable[] = { +	{ +	 XPAR_OPB_ETHERNET_0_DEVICE_ID, +	 XPAR_OPB_ETHERNET_0_BASEADDR, +	 XPAR_OPB_ETHERNET_0_ERR_COUNT_EXIST, +	 XPAR_OPB_ETHERNET_0_DMA_PRESENT, +	 XPAR_OPB_ETHERNET_0_MII_EXIST} +}; diff --git a/board/xilinx/xilinx_enet/xemac_i.h b/board/xilinx/xilinx_enet/xemac_i.h new file mode 100644 index 000000000..9c160f388 --- /dev/null +++ b/board/xilinx/xilinx_enet/xemac_i.h @@ -0,0 +1,207 @@ +/****************************************************************************** +* +*     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. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xemac_i.h +* +* This header file contains internal identifiers, which are those shared +* between XEmac components.  The identifiers in this file are not intended for +* use external to the driver. +* +* <pre> +* MODIFICATION HISTORY: +* +* Ver	Who  Date     Changes +* ----- ---- -------- ----------------------------------------------- +* 1.00a rpm  07/31/01 First release +* 1.00b rpm  02/20/02 Repartitioned files and functions +* 1.00b rpm  04/29/02 Moved register definitions to xemac_l.h +* 1.00c rpm  12/05/02 New version includes support for simple DMA +* </pre> +* +******************************************************************************/ + +#ifndef XEMAC_I_H		/* prevent circular inclusions */ +#define XEMAC_I_H		/* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xemac.h" +#include "xemac_l.h" + +/************************** Constant Definitions *****************************/ + +/* + * Default buffer descriptor control word masks. The default send BD control + * is set for incrementing the source address by one for each byte transferred, + * and specify that the destination address (FIFO) is local to the device. The + * default receive BD control is set for incrementing the destination address + * by one for each byte transferred, and specify that the source address is + * local to the device. + */ +#define XEM_DFT_SEND_BD_MASK	(XDC_DMACR_SOURCE_INCR_MASK | \ +				 XDC_DMACR_DEST_LOCAL_MASK) +#define XEM_DFT_RECV_BD_MASK	(XDC_DMACR_DEST_INCR_MASK |  \ +				 XDC_DMACR_SOURCE_LOCAL_MASK) + +/* + * Masks for the IPIF Device Interrupt enable and status registers. + */ +#define XEM_IPIF_EMAC_MASK	0x00000004UL	/* MAC interrupt */ +#define XEM_IPIF_SEND_DMA_MASK	0x00000008UL	/* Send DMA interrupt */ +#define XEM_IPIF_RECV_DMA_MASK	0x00000010UL	/* Receive DMA interrupt */ +#define XEM_IPIF_RECV_FIFO_MASK 0x00000020UL	/* Receive FIFO interrupt */ +#define XEM_IPIF_SEND_FIFO_MASK 0x00000040UL	/* Send FIFO interrupt */ + +/* + * Default IPIF Device Interrupt mask when configured for DMA + */ +#define XEM_IPIF_DMA_DFT_MASK	(XEM_IPIF_SEND_DMA_MASK |   \ +				 XEM_IPIF_RECV_DMA_MASK |   \ +				 XEM_IPIF_EMAC_MASK |	    \ +				 XEM_IPIF_SEND_FIFO_MASK |  \ +				 XEM_IPIF_RECV_FIFO_MASK) + +/* + * Default IPIF Device Interrupt mask when configured without DMA + */ +#define XEM_IPIF_FIFO_DFT_MASK	(XEM_IPIF_EMAC_MASK |	    \ +				 XEM_IPIF_SEND_FIFO_MASK |  \ +				 XEM_IPIF_RECV_FIFO_MASK) + +#define XEM_IPIF_DMA_DEV_INTR_COUNT   7 /* Number of interrupt sources */ +#define XEM_IPIF_FIFO_DEV_INTR_COUNT  5 /* Number of interrupt sources */ +#define XEM_IPIF_DEVICE_INTR_COUNT  7	/* Number of interrupt sources */ +#define XEM_IPIF_IP_INTR_COUNT	    22	/* Number of MAC interrupts */ + +/* a mask for all transmit interrupts, used in polled mode */ +#define XEM_EIR_XMIT_ALL_MASK	(XEM_EIR_XMIT_DONE_MASK |	    \ +				 XEM_EIR_XMIT_ERROR_MASK |	    \ +				 XEM_EIR_XMIT_SFIFO_EMPTY_MASK |    \ +				 XEM_EIR_XMIT_LFIFO_FULL_MASK) + +/* a mask for all receive interrupts, used in polled mode */ +#define XEM_EIR_RECV_ALL_MASK	(XEM_EIR_RECV_DONE_MASK |	    \ +				 XEM_EIR_RECV_ERROR_MASK |	    \ +				 XEM_EIR_RECV_LFIFO_EMPTY_MASK |    \ +				 XEM_EIR_RECV_LFIFO_OVER_MASK |	    \ +				 XEM_EIR_RECV_LFIFO_UNDER_MASK |    \ +				 XEM_EIR_RECV_DFIFO_OVER_MASK |	    \ +				 XEM_EIR_RECV_MISSED_FRAME_MASK |   \ +				 XEM_EIR_RECV_COLLISION_MASK |	    \ +				 XEM_EIR_RECV_FCS_ERROR_MASK |	    \ +				 XEM_EIR_RECV_LEN_ERROR_MASK |	    \ +				 XEM_EIR_RECV_SHORT_ERROR_MASK |    \ +				 XEM_EIR_RECV_LONG_ERROR_MASK |	    \ +				 XEM_EIR_RECV_ALIGN_ERROR_MASK) + +/* a default interrupt mask for scatter-gather DMA operation */ +#define XEM_EIR_DFT_SG_MASK    (XEM_EIR_RECV_ERROR_MASK |	    \ +				XEM_EIR_RECV_LFIFO_OVER_MASK |	    \ +				XEM_EIR_RECV_LFIFO_UNDER_MASK |	    \ +				XEM_EIR_XMIT_SFIFO_OVER_MASK |	    \ +				XEM_EIR_XMIT_SFIFO_UNDER_MASK |	    \ +				XEM_EIR_XMIT_LFIFO_OVER_MASK |	    \ +				XEM_EIR_XMIT_LFIFO_UNDER_MASK |	    \ +				XEM_EIR_RECV_DFIFO_OVER_MASK |	    \ +				XEM_EIR_RECV_MISSED_FRAME_MASK |    \ +				XEM_EIR_RECV_COLLISION_MASK |	    \ +				XEM_EIR_RECV_FCS_ERROR_MASK |	    \ +				XEM_EIR_RECV_LEN_ERROR_MASK |	    \ +				XEM_EIR_RECV_SHORT_ERROR_MASK |	    \ +				XEM_EIR_RECV_LONG_ERROR_MASK |	    \ +				XEM_EIR_RECV_ALIGN_ERROR_MASK) + +/* a default interrupt mask for non-DMA operation (direct FIFOs) */ +#define XEM_EIR_DFT_FIFO_MASK  (XEM_EIR_XMIT_DONE_MASK |	    \ +				XEM_EIR_RECV_DONE_MASK |	    \ +				XEM_EIR_DFT_SG_MASK) + +/* + * Mask for the DMA interrupt enable and status registers when configured + * for scatter-gather DMA. + */ +#define XEM_DMA_SG_INTR_MASK	(XDC_IXR_DMA_ERROR_MASK	 |	\ +				 XDC_IXR_PKT_THRESHOLD_MASK |	\ +				 XDC_IXR_PKT_WAIT_BOUND_MASK |	\ +				 XDC_IXR_SG_END_MASK) + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/* +* +* Clears a structure of given size, in bytes, by setting each byte to 0. +* +* @param StructPtr is a pointer to the structure to be cleared. +* @param NumBytes is the number of bytes in the structure. +* +* @return +* +* None. +* +* @note +* +* Signature: void XEmac_mClearStruct(u8 *StructPtr, unsigned int NumBytes) +* +******************************************************************************/ +#define XEmac_mClearStruct(StructPtr, NumBytes)	    \ +{						    \ +    int i;					    \ +    u8 *BytePtr = (u8 *)(StructPtr);	    \ +    for (i=0; i < (unsigned int)(NumBytes); i++)    \ +    {						    \ +	*BytePtr++ = 0;				    \ +    }						    \ +} + +/************************** Variable Definitions *****************************/ + +extern XEmac_Config XEmac_ConfigTable[]; + +/************************** Function Prototypes ******************************/ + +void XEmac_CheckEmacError(XEmac * InstancePtr, u32 IntrStatus); +void XEmac_CheckFifoRecvError(XEmac * InstancePtr); +void XEmac_CheckFifoSendError(XEmac * InstancePtr); + +#endif				/* end of protection macro */ diff --git a/board/xilinx/xilinx_enet/xemac_intr.c b/board/xilinx/xilinx_enet/xemac_intr.c new file mode 100644 index 000000000..b9a262156 --- /dev/null +++ b/board/xilinx/xilinx_enet/xemac_intr.c @@ -0,0 +1,402 @@ +/****************************************************************************** +* +*     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. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xemac_intr.c +* +* This file contains general interrupt-related functions of the XEmac driver. +* +* <pre> +* MODIFICATION HISTORY: +* +* Ver   Who  Date     Changes +* ----- ---- -------- ----------------------------------------------- +* 1.00a rpm  07/31/01 First release +* 1.00b rpm  02/20/02 Repartitioned files and functions +* 1.00c rpm  12/05/02 New version includes support for simple DMA +* 1.00c rpm  03/31/03 Added comment to indicate that no Receive Length FIFO +*                     overrun interrupts occur in v1.00l and later of the EMAC +*                     device. This avoids the need to reset the device on +*                     receive overruns. +* </pre> +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xbasic_types.h" +#include "xemac_i.h" +#include "xio.h" +#include "xipif_v1_23_b.h"	/* Uses v1.23b of the IPIF */ + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* +* Set the callback function for handling asynchronous errors.  The upper layer +* software should call this function during initialization. +* +* The error callback is invoked by the driver within interrupt context, so it +* needs to do its job quickly. If there are potentially slow operations within +* the callback, these should be done at task-level. +* +* The Xilinx errors that must be handled by the callback are: +* - XST_DMA_ERROR indicates an unrecoverable DMA error occurred. This is +*   typically a bus error or bus timeout. The handler must reset and +*   re-configure the device. +* - XST_FIFO_ERROR indicates an unrecoverable FIFO error occurred. This is a +*   deadlock condition in the packet FIFO. The handler must reset and +*   re-configure the device. +* - XST_RESET_ERROR indicates an unrecoverable MAC error occurred, usually an +*   overrun or underrun. The handler must reset and re-configure the device. +* - XST_DMA_SG_NO_LIST indicates an attempt was made to access a scatter-gather +*   DMA list that has not yet been created. +* - XST_DMA_SG_LIST_EMPTY indicates the driver tried to get a descriptor from +*   the receive descriptor list, but the list was empty. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param CallBackRef is a reference pointer to be passed back to the adapter in +*        the callback. This helps the adapter correlate the callback to a +*        particular driver. +* @param FuncPtr is the pointer to the callback function. +* +* @return +* +* None. +* +* @note +* +* None. +* +******************************************************************************/ +void +XEmac_SetErrorHandler(XEmac * InstancePtr, void *CallBackRef, +		      XEmac_ErrorHandler FuncPtr) +{ +	XASSERT_VOID(InstancePtr != NULL); +	XASSERT_VOID(FuncPtr != NULL); +	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	InstancePtr->ErrorHandler = FuncPtr; +	InstancePtr->ErrorRef = CallBackRef; +} + +/****************************************************************************/ +/* +* +* Check the interrupt status bits of the Ethernet MAC for errors. Errors +* currently handled are: +* - Receive length FIFO overrun. Indicates data was lost due to the receive +*   length FIFO becoming full during the reception of a packet. Only a device +*   reset clears this condition. +* - Receive length FIFO underrun. An attempt to read an empty FIFO. Only a +*   device reset clears this condition. +* - Transmit status FIFO overrun. Indicates data was lost due to the transmit +*   status FIFO becoming full following the transmission of a packet. Only a +*   device reset clears this condition. +* - Transmit status FIFO underrun. An attempt to read an empty FIFO. Only a +*   device reset clears this condition. +* - Transmit length FIFO overrun. Indicates data was lost due to the transmit +*   length FIFO becoming full following the transmission of a packet. Only a +*   device reset clears this condition. +* - Transmit length FIFO underrun. An attempt to read an empty FIFO. Only a +*   device reset clears this condition. +* - Receive data FIFO overrun. Indicates data was lost due to the receive data +*   FIFO becoming full during the reception of a packet. +* - Receive data errors: +*   - Receive missed frame error. Valid data was lost by the MAC. +*   - Receive collision error. Data was lost by the MAC due to a collision. +*   - Receive FCS error.  Data was dicarded by the MAC due to FCS error. +*   - Receive length field error. Data was dicarded by the MAC due to an invalid +*     length field in the packet. +*   - Receive short error. Data was dicarded by the MAC because a packet was +*     shorter than allowed. +*   - Receive long error. Data was dicarded by the MAC because a packet was +*     longer than allowed. +*   - Receive alignment error. Data was truncated by the MAC because its length +*     was not byte-aligned. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param IntrStatus is the contents of the interrupt status register to be checked +* +* @return +* +* None. +* +* @note +* +* This function is intended for internal use only. +* +******************************************************************************/ +void +XEmac_CheckEmacError(XEmac * InstancePtr, u32 IntrStatus) +{ +	u32 ResetError = FALSE; + +	/* +	 * First check for receive fifo overrun/underrun errors. Most require a +	 * reset by the user to clear, but the data FIFO overrun error does not. +	 */ +	if (IntrStatus & XEM_EIR_RECV_DFIFO_OVER_MASK) { +		InstancePtr->Stats.RecvOverrunErrors++; +		InstancePtr->Stats.FifoErrors++; +	} + +	if (IntrStatus & XEM_EIR_RECV_LFIFO_OVER_MASK) { +		/* +		 * Receive Length FIFO overrun interrupts no longer occur in v1.00l +		 * and later of the EMAC device. Frames are just dropped by the EMAC +		 * if the length FIFO is full. The user would notice the Receive Missed +		 * Frame count incrementing without any other errors being reported. +		 * This code is left here for backward compatibility with v1.00k and +		 * older EMAC devices. +		 */ +		InstancePtr->Stats.RecvOverrunErrors++; +		InstancePtr->Stats.FifoErrors++; +		ResetError = TRUE;	/* requires a reset */ +	} + +	if (IntrStatus & XEM_EIR_RECV_LFIFO_UNDER_MASK) { +		InstancePtr->Stats.RecvUnderrunErrors++; +		InstancePtr->Stats.FifoErrors++; +		ResetError = TRUE;	/* requires a reset */ +	} + +	/* +	 * Now check for general receive errors. Get the latest count where +	 * available, otherwise just bump the statistic so we know the interrupt +	 * occurred. +	 */ +	if (IntrStatus & XEM_EIR_RECV_ERROR_MASK) { +		if (IntrStatus & XEM_EIR_RECV_MISSED_FRAME_MASK) { +			/* +			 * Caused by length FIFO or data FIFO overruns on receive side +			 */ +			InstancePtr->Stats.RecvMissedFrameErrors = +			    XIo_In32(InstancePtr->BaseAddress + +				     XEM_RMFC_OFFSET); +		} + +		if (IntrStatus & XEM_EIR_RECV_COLLISION_MASK) { +			InstancePtr->Stats.RecvCollisionErrors = +			    XIo_In32(InstancePtr->BaseAddress + XEM_RCC_OFFSET); +		} + +		if (IntrStatus & XEM_EIR_RECV_FCS_ERROR_MASK) { +			InstancePtr->Stats.RecvFcsErrors = +			    XIo_In32(InstancePtr->BaseAddress + +				     XEM_RFCSEC_OFFSET); +		} + +		if (IntrStatus & XEM_EIR_RECV_LEN_ERROR_MASK) { +			InstancePtr->Stats.RecvLengthFieldErrors++; +		} + +		if (IntrStatus & XEM_EIR_RECV_SHORT_ERROR_MASK) { +			InstancePtr->Stats.RecvShortErrors++; +		} + +		if (IntrStatus & XEM_EIR_RECV_LONG_ERROR_MASK) { +			InstancePtr->Stats.RecvLongErrors++; +		} + +		if (IntrStatus & XEM_EIR_RECV_ALIGN_ERROR_MASK) { +			InstancePtr->Stats.RecvAlignmentErrors = +			    XIo_In32(InstancePtr->BaseAddress + +				     XEM_RAEC_OFFSET); +		} + +		/* +		 * Bump recv interrupts stats only if not scatter-gather DMA (this +		 * stat gets bumped elsewhere in that case) +		 */ +		if (!XEmac_mIsSgDma(InstancePtr)) { +			InstancePtr->Stats.RecvInterrupts++;	/* TODO: double bump? */ +		} + +	} + +	/* +	 * Check for transmit errors. These apply to both DMA and non-DMA modes +	 * of operation. The entire device should be reset after overruns or +	 * underruns. +	 */ +	if (IntrStatus & (XEM_EIR_XMIT_SFIFO_OVER_MASK | +			  XEM_EIR_XMIT_LFIFO_OVER_MASK)) { +		InstancePtr->Stats.XmitOverrunErrors++; +		InstancePtr->Stats.FifoErrors++; +		ResetError = TRUE; +	} + +	if (IntrStatus & (XEM_EIR_XMIT_SFIFO_UNDER_MASK | +			  XEM_EIR_XMIT_LFIFO_UNDER_MASK)) { +		InstancePtr->Stats.XmitUnderrunErrors++; +		InstancePtr->Stats.FifoErrors++; +		ResetError = TRUE; +	} + +	if (ResetError) { +		/* +		 * If a reset error occurred, disable the EMAC interrupts since the +		 * reset-causing interrupt(s) is latched in the EMAC - meaning it will +		 * keep occurring until the device is reset. In order to give the higher +		 * layer software time to reset the device, we have to disable the +		 * overrun/underrun interrupts until that happens. We trust that the +		 * higher layer resets the device. We are able to get away with disabling +		 * all EMAC interrupts since the only interrupts it generates are for +		 * error conditions, and we don't care about any more errors right now. +		 */ +		XIIF_V123B_WRITE_IIER(InstancePtr->BaseAddress, 0); + +		/* +		 * Invoke the error handler callback, which should result in a reset +		 * of the device by the upper layer software. +		 */ +		InstancePtr->ErrorHandler(InstancePtr->ErrorRef, +					  XST_RESET_ERROR); +	} +} + +/*****************************************************************************/ +/* +* +* Check the receive packet FIFO for errors. FIFO error interrupts are: +* - Deadlock.  See the XPacketFifo component for a description of deadlock on a +*   FIFO. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* +* @return +* +* Although the function returns void, it can return an asynchronous error to the +* application through the error handler.  It can return XST_FIFO_ERROR if a FIFO +* error occurred. +* +* @note +* +* This function is intended for internal use only. +* +******************************************************************************/ +void +XEmac_CheckFifoRecvError(XEmac * InstancePtr) +{ +	/* +	 * Although the deadlock is currently the only interrupt from a packet +	 * FIFO, make sure it is deadlocked before taking action. There is no +	 * need to clear this interrupt since it requires a reset of the device. +	 */ +	if (XPF_V100B_IS_DEADLOCKED(&InstancePtr->RecvFifo)) { +		u32 IntrEnable; + +		InstancePtr->Stats.FifoErrors++; + +		/* +		 * Invoke the error callback function, which should result in a reset +		 * of the device by the upper layer software. We first need to disable +		 * the FIFO interrupt, since otherwise the upper layer thread that +		 * handles the reset may never run because this interrupt condition +		 * doesn't go away until a reset occurs (there is no way to ack it). +		 */ +		IntrEnable = XIIF_V123B_READ_DIER(InstancePtr->BaseAddress); +		XIIF_V123B_WRITE_DIER(InstancePtr->BaseAddress, +				      IntrEnable & ~XEM_IPIF_RECV_FIFO_MASK); + +		InstancePtr->ErrorHandler(InstancePtr->ErrorRef, +					  XST_FIFO_ERROR); +	} +} + +/*****************************************************************************/ +/* +* +* Check the send packet FIFO for errors. FIFO error interrupts are: +* - Deadlock. See the XPacketFifo component for a description of deadlock on a +*   FIFO. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* +* @return +* +* Although the function returns void, it can return an asynchronous error to the +* application through the error handler.  It can return XST_FIFO_ERROR if a FIFO +* error occurred. +* +* @note +* +* This function is intended for internal use only. +* +******************************************************************************/ +void +XEmac_CheckFifoSendError(XEmac * InstancePtr) +{ +	/* +	 * Although the deadlock is currently the only interrupt from a packet +	 * FIFO, make sure it is deadlocked before taking action. There is no +	 * need to clear this interrupt since it requires a reset of the device. +	 */ +	if (XPF_V100B_IS_DEADLOCKED(&InstancePtr->SendFifo)) { +		u32 IntrEnable; + +		InstancePtr->Stats.FifoErrors++; + +		/* +		 * Invoke the error callback function, which should result in a reset +		 * of the device by the upper layer software. We first need to disable +		 * the FIFO interrupt, since otherwise the upper layer thread that +		 * handles the reset may never run because this interrupt condition +		 * doesn't go away until a reset occurs (there is no way to ack it). +		 */ +		IntrEnable = XIIF_V123B_READ_DIER(InstancePtr->BaseAddress); +		XIIF_V123B_WRITE_DIER(InstancePtr->BaseAddress, +				      IntrEnable & ~XEM_IPIF_SEND_FIFO_MASK); + +		InstancePtr->ErrorHandler(InstancePtr->ErrorRef, +					  XST_FIFO_ERROR); +	} +} diff --git a/board/xilinx/xilinx_enet/xemac_intr_dma.c b/board/xilinx/xilinx_enet/xemac_intr_dma.c new file mode 100644 index 000000000..567abb42a --- /dev/null +++ b/board/xilinx/xilinx_enet/xemac_intr_dma.c @@ -0,0 +1,1344 @@ +/****************************************************************************** +* +*     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. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xemac_intr_dma.c +* +* Contains functions used in interrupt mode when configured with scatter-gather +* DMA. +* +* The interrupt handler, XEmac_IntrHandlerDma(), must be connected by the user +* to the interrupt controller. +* +* <pre> +* MODIFICATION HISTORY: +* +* Ver   Who  Date     Changes +* ----- ---- -------- --------------------------------------------------------- +* 1.00a rpm  07/31/01 First release +* 1.00b rpm  02/20/02 Repartitioned files and functions +* 1.00c rpm  12/05/02 New version includes support for simple DMA and the delay +*                     argument to SgSend +* 1.00c rpm  02/03/03 The XST_DMA_SG_COUNT_EXCEEDED return code was removed +*                     from SetPktThreshold in the internal DMA driver. Also +*                     avoided compiler warnings by initializing Result in the +*                     interrupt service routines. +* 1.00c rpm  03/26/03 Fixed a problem in the interrupt service routines where +*                     the interrupt status was toggled clear after a call to +*                     ErrorHandler, but if ErrorHandler reset the device the +*                     toggle actually asserted the interrupt because the +*                     reset had cleared it. +* </pre> +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xbasic_types.h" +#include "xemac_i.h" +#include "xio.h" +#include "xbuf_descriptor.h" +#include "xdma_channel.h" +#include "xipif_v1_23_b.h"	/* Uses v1.23b of the IPIF */ + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +static void HandleDmaRecvIntr(XEmac * InstancePtr); +static void HandleDmaSendIntr(XEmac * InstancePtr); +static void HandleEmacDmaIntr(XEmac * InstancePtr); + +/*****************************************************************************/ +/** +* +* Send an Ethernet frame using scatter-gather DMA. The caller attaches the +* frame to one or more buffer descriptors, then calls this function once for +* each descriptor. The caller is responsible for allocating and setting up the +* descriptor. An entire Ethernet frame may or may not be contained within one +* descriptor.  This function simply inserts the descriptor into the scatter- +* gather engine's transmit list. The caller is responsible for providing mutual +* exclusion to guarantee that a frame is contiguous in the transmit list. The +* buffer attached to the descriptor must be word-aligned. +* +* The driver updates the descriptor with the device control register before +* being inserted into the transmit list.  If this is the last descriptor in +* the frame, the inserts are committed, which means the descriptors for this +* frame are now available for transmission. +* +* It is assumed that the upper layer software supplies a correctly formatted +* Ethernet frame, including the destination and source addresses, the +* type/length field, and the data field.  It is also assumed that upper layer +* software does not append FCS at the end of the frame. +* +* The buffer attached to the descriptor must be word-aligned on the front end. +* +* This call is non-blocking.  Notification of error or successful transmission +* is done asynchronously through the send or error callback function. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param BdPtr is the address of a descriptor to be inserted into the transmit +*        ring. +* @param Delay indicates whether to start the scatter-gather DMA channel +*        immediately, or whether to wait. This allows the user to build up a +*        list of more than one descriptor before starting the transmission of +*        the packets, which allows the application to keep up with DMA and have +*        a constant stream of frames being transmitted. Use XEM_SGDMA_NODELAY or +*        XEM_SGDMA_DELAY, defined in xemac.h, as the value of this argument. If +*        the user chooses to delay and build a list, the user must call this +*        function with the XEM_SGDMA_NODELAY option or call XEmac_Start() to +*        kick off the tranmissions. +* +* @return +* +* - XST_SUCCESS if the buffer was successfull sent +* - XST_DEVICE_IS_STOPPED if the Ethernet MAC has not been started yet +* - XST_NOT_SGDMA if the device is not in scatter-gather DMA mode +* - XST_DMA_SG_LIST_FULL if the descriptor list for the DMA channel is full +* - XST_DMA_SG_BD_LOCKED if the DMA channel cannot insert the descriptor into +*   the list because a locked descriptor exists at the insert point +* - XST_DMA_SG_NOTHING_TO_COMMIT if even after inserting a descriptor into the +*   list, the DMA channel believes there are no new descriptors to commit. If +*   this is ever encountered, there is likely a thread mutual exclusion problem +*   on transmit. +* +* @note +* +* This function is not thread-safe. The user must provide mutually exclusive +* access to this function if there are to be multiple threads that can call it. +* +* @internal +* +* A status that should never be returned from this function, although +* the code is set up to handle it, is XST_DMA_SG_NO_LIST. Starting the device +* requires a list to be created, and this function requires the device to be +* started. +* +******************************************************************************/ +XStatus +XEmac_SgSend(XEmac * InstancePtr, XBufDescriptor * BdPtr, int Delay) +{ +	XStatus Result; +	u32 BdControl; + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(BdPtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* +	 * Be sure the device is configured for scatter-gather DMA, then be sure +	 * it is started. +	 */ +	if (!XEmac_mIsSgDma(InstancePtr)) { +		return XST_NOT_SGDMA; +	} + +	/* +	 * Set some descriptor control word defaults (source address increment +	 * and local destination address) and the destination address +	 * (the FIFO).  These are the same for every transmit descriptor. +	 */ +	BdControl = XBufDescriptor_GetControl(BdPtr); +	XBufDescriptor_SetControl(BdPtr, BdControl | XEM_DFT_SEND_BD_MASK); + +	XBufDescriptor_SetDestAddress(BdPtr, +				      InstancePtr->BaseAddress + +				      XEM_PFIFO_TXDATA_OFFSET); + +	/* +	 * Put the descriptor in the send list. The DMA component accesses data +	 * here that can also be modified in interrupt context, so a critical +	 * section is required. +	 */ +	XIIF_V123B_GINTR_DISABLE(InstancePtr->BaseAddress); + +	Result = XDmaChannel_PutDescriptor(&InstancePtr->SendChannel, BdPtr); +	if (Result != XST_SUCCESS) { +		XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress); +		return Result; +	} + +	/* +	 * If this is the last buffer in the frame, commit the inserts and start +	 * the DMA engine if necessary +	 */ +	if (XBufDescriptor_IsLastControl(BdPtr)) { +		Result = XDmaChannel_CommitPuts(&InstancePtr->SendChannel); +		if (Result != XST_SUCCESS) { +			XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress); +			return Result; +		} + +		if (Delay == XEM_SGDMA_NODELAY) { +			/* +			 * Start the DMA channel. Ignore the return status since we know the +			 * list exists and has at least one entry and we don't care if the +			 * channel is already started.  The DMA component accesses data here +			 * that can be modified at interrupt or task levels, so a critical +			 * section is required. +			 */ +			(void) XDmaChannel_SgStart(&InstancePtr->SendChannel); +		} +	} + +	XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress); + +	return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Add a descriptor, with an attached empty buffer, into the receive descriptor +* list. The buffer attached to the descriptor must be word-aligned. This is +* used by the upper layer software during initialization when first setting up +* the receive descriptors, and also during reception of frames to replace +* filled buffers with empty buffers. This function can be called when the +* device is started or stopped. Note that it does start the scatter-gather DMA +* engine.  Although this is not necessary during initialization, it is not a +* problem during initialization because the MAC receiver is not yet started. +* +* The buffer attached to the descriptor must be word-aligned on both the front +* end and the back end. +* +* Notification of received frames are done asynchronously through the receive +* callback function. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param BdPtr is a pointer to the buffer descriptor that will be added to the +*        descriptor list. +* +* @return +* +* - XST_SUCCESS if a descriptor was successfully returned to the driver +* - XST_NOT_SGDMA if the device is not in scatter-gather DMA mode +* - XST_DMA_SG_LIST_FULL if the receive descriptor list is full +* - XST_DMA_SG_BD_LOCKED if the DMA channel cannot insert the descriptor into +*   the list because a locked descriptor exists at the insert point. +* - XST_DMA_SG_NOTHING_TO_COMMIT if even after inserting a descriptor into the +*   list, the DMA channel believes there are no new descriptors to commit. +* +* @internal +* +* A status that should never be returned from this function, although +* the code is set up to handle it, is XST_DMA_SG_NO_LIST. Starting the device +* requires a list to be created, and this function requires the device to be +* started. +* +******************************************************************************/ +XStatus +XEmac_SgRecv(XEmac * InstancePtr, XBufDescriptor * BdPtr) +{ +	XStatus Result; +	u32 BdControl; + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(BdPtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* +	 * Be sure the device is configured for scatter-gather DMA +	 */ +	if (!XEmac_mIsSgDma(InstancePtr)) { +		return XST_NOT_SGDMA; +	} + +	/* +	 * Set some descriptor control word defaults (destination address increment +	 * and local source address) and the source address (the FIFO). These are +	 * the same for every receive descriptor. +	 */ +	BdControl = XBufDescriptor_GetControl(BdPtr); +	XBufDescriptor_SetControl(BdPtr, BdControl | XEM_DFT_RECV_BD_MASK); +	XBufDescriptor_SetSrcAddress(BdPtr, +				     InstancePtr->BaseAddress + +				     XEM_PFIFO_RXDATA_OFFSET); + +	/* +	 * Put the descriptor into the channel's descriptor list and commit. +	 * Although this function is likely called within interrupt context, there +	 * is the possibility that the upper layer software queues it to a task. +	 * In this case, a critical section is needed here to protect shared data +	 * in the DMA component. +	 */ +	XIIF_V123B_GINTR_DISABLE(InstancePtr->BaseAddress); + +	Result = XDmaChannel_PutDescriptor(&InstancePtr->RecvChannel, BdPtr); +	if (Result != XST_SUCCESS) { +		XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress); +		return Result; +	} + +	Result = XDmaChannel_CommitPuts(&InstancePtr->RecvChannel); +	if (Result != XST_SUCCESS) { +		XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress); +		return Result; +	} + +	/* +	 * Start the DMA channel. Ignore the return status since we know the list +	 * exists and has at least one entry and we don't care if the channel is +	 * already started. The DMA component accesses data here that can be +	 * modified at interrupt or task levels, so a critical section is required. +	 */ +	(void) XDmaChannel_SgStart(&InstancePtr->RecvChannel); + +	XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress); + +	return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* The interrupt handler for the Ethernet driver when configured with scatter- +* gather DMA. +* +* Get the interrupt status from the IpIf to determine the source of the +* interrupt.  The source can be: MAC, Recv Packet FIFO, Send Packet FIFO, Recv +* DMA channel, or Send DMA channel. The packet FIFOs only interrupt during +* "deadlock" conditions. +* +* @param InstancePtr is a pointer to the XEmac instance that just interrupted. +* +* @return +* +* None. +* +* @note +* +* None. +* +******************************************************************************/ +void +XEmac_IntrHandlerDma(void *InstancePtr) +{ +	u32 IntrStatus; +	XEmac *EmacPtr = (XEmac *) InstancePtr; + +	EmacPtr->Stats.TotalIntrs++; + +	/* +	 * Get the interrupt status from the IPIF. There is no clearing of +	 * interrupts in the IPIF. Interrupts must be cleared at the source. +	 */ +	IntrStatus = XIIF_V123B_READ_DIPR(EmacPtr->BaseAddress); + +	/* +	 * See which type of interrupt is being requested, and service it +	 */ +	if (IntrStatus & XEM_IPIF_RECV_DMA_MASK) {	/* Receive DMA interrupt */ +		EmacPtr->Stats.RecvInterrupts++; +		HandleDmaRecvIntr(EmacPtr); +	} + +	if (IntrStatus & XEM_IPIF_SEND_DMA_MASK) {	/* Send DMA interrupt */ +		EmacPtr->Stats.XmitInterrupts++; +		HandleDmaSendIntr(EmacPtr); +	} + +	if (IntrStatus & XEM_IPIF_EMAC_MASK) {	/* MAC interrupt */ +		EmacPtr->Stats.EmacInterrupts++; +		HandleEmacDmaIntr(EmacPtr); +	} + +	if (IntrStatus & XEM_IPIF_RECV_FIFO_MASK) {	/* Receive FIFO interrupt */ +		EmacPtr->Stats.RecvInterrupts++; +		XEmac_CheckFifoRecvError(EmacPtr); +	} + +	if (IntrStatus & XEM_IPIF_SEND_FIFO_MASK) {	/* Send FIFO interrupt */ +		EmacPtr->Stats.XmitInterrupts++; +		XEmac_CheckFifoSendError(EmacPtr); +	} + +	if (IntrStatus & XIIF_V123B_ERROR_MASK) { +		/* +		 * An error occurred internal to the IPIF. This is more of a debug and +		 * integration issue rather than a production error. Don't do anything +		 * other than clear it, which provides a spot for software to trap +		 * on the interrupt and begin debugging. +		 */ +		XIIF_V123B_WRITE_DISR(EmacPtr->BaseAddress, +				      XIIF_V123B_ERROR_MASK); +	} +} + +/*****************************************************************************/ +/** +* +* Set the packet count threshold for this device. The device must be stopped +* before setting the threshold. The packet count threshold is used for interrupt +* coalescing, which reduces the frequency of interrupts from the device to the +* processor. In this case, the scatter-gather DMA engine only interrupts when +* the packet count threshold is reached, instead of interrupting for each packet. +* A packet is a generic term used by the scatter-gather DMA engine, and is +* equivalent to an Ethernet frame in our case. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param Direction indicates the channel, send or receive, from which the +*        threshold register is read. +* @param Threshold is the value of the packet threshold count used during +*        interrupt coalescing. A value of 0 disables the use of packet threshold +*        by the hardware. +* +* @return +* +* - XST_SUCCESS if the threshold was successfully set +* - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA +* - XST_DEVICE_IS_STARTED if the device has not been stopped +* - XST_INVALID_PARAM if the Direction parameter is invalid. Turning on +*   asserts would also catch this error. +* +* @note +* +* The packet threshold could be set to larger than the number of descriptors +* allocated to the DMA channel. In this case, the wait bound will take over +* and always indicate data arrival. There was a check in this function that +* returned an error if the treshold was larger than the number of descriptors, +* but that was removed because users would then have to set the threshold +* only after they set descriptor space, which is an order dependency that +* caused confustion. +* +******************************************************************************/ +XStatus +XEmac_SetPktThreshold(XEmac * InstancePtr, u32 Direction, u8 Threshold) +{ +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(Direction == XEM_SEND || Direction == XEM_RECV); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* +	 * Be sure device is configured for scatter-gather DMA and has been stopped +	 */ +	if (!XEmac_mIsSgDma(InstancePtr)) { +		return XST_NOT_SGDMA; +	} + +	if (InstancePtr->IsStarted == XCOMPONENT_IS_STARTED) { +		return XST_DEVICE_IS_STARTED; +	} + +	/* +	 * Based on the direction, set the packet threshold in the +	 * corresponding DMA channel component.  Default to the receive +	 * channel threshold register (if an invalid Direction is passed). +	 */ +	switch (Direction) { +	case XEM_SEND: +		return XDmaChannel_SetPktThreshold(&InstancePtr->SendChannel, +						   Threshold); + +	case XEM_RECV: +		return XDmaChannel_SetPktThreshold(&InstancePtr->RecvChannel, +						   Threshold); + +	default: +		return XST_INVALID_PARAM; +	} +} + +/*****************************************************************************/ +/** +* +* Get the value of the packet count threshold for this driver/device. The packet +* count threshold is used for interrupt coalescing, which reduces the frequency +* of interrupts from the device to the processor. In this case, the +* scatter-gather DMA engine only interrupts when the packet count threshold is +* reached, instead of interrupting for each packet. A packet is a generic term +* used by the scatter-gather DMA engine, and is equivalent to an Ethernet frame +* in our case. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param Direction indicates the channel, send or receive, from which the +*        threshold register is read. +* @param ThreshPtr is a pointer to the byte into which the current value of the +*        packet threshold register will be copied. An output parameter. A value +*        of 0 indicates the use of packet threshold by the hardware is disabled. +* +* @return +* +* - XST_SUCCESS if the packet threshold was retrieved successfully +* - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA +* - XST_INVALID_PARAM if the Direction parameter is invalid. Turning on +*   asserts would also catch this error. +* +* @note +* +* None. +* +******************************************************************************/ +XStatus +XEmac_GetPktThreshold(XEmac * InstancePtr, u32 Direction, u8 * ThreshPtr) +{ +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(Direction == XEM_SEND || Direction == XEM_RECV); +	XASSERT_NONVOID(ThreshPtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	if (!XEmac_mIsSgDma(InstancePtr)) { +		return XST_NOT_SGDMA; +	} + +	/* +	 * Based on the direction, return the packet threshold set in the +	 * corresponding DMA channel component.  Default to the value in +	 * the receive channel threshold register (if an invalid Direction +	 * is passed). +	 */ +	switch (Direction) { +	case XEM_SEND: +		*ThreshPtr = +		    XDmaChannel_GetPktThreshold(&InstancePtr->SendChannel); +		break; + +	case XEM_RECV: +		*ThreshPtr = +		    XDmaChannel_GetPktThreshold(&InstancePtr->RecvChannel); +		break; + +	default: +		return XST_INVALID_PARAM; +	} + +	return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Set the packet wait bound timer for this driver/device. The device must be +* stopped before setting the timer value. The packet wait bound is used during +* interrupt coalescing to trigger an interrupt when not enough packets have been +* received to reach the packet count threshold. A packet is a generic term used +* by the scatter-gather DMA engine, and is equivalent to an Ethernet frame in +* our case. The timer is in milliseconds. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param Direction indicates the channel, send or receive, from which the +*        threshold register is read. +* @param TimerValue is the value of the packet wait bound used during interrupt +*        coalescing. It is in milliseconds in the range 0  - 1023. A value of 0 +*        disables the packet wait bound timer. +* +* @return +* +* - XST_SUCCESS if the packet wait bound was set successfully +* - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA +* - XST_DEVICE_IS_STARTED if the device has not been stopped +* - XST_INVALID_PARAM if the Direction parameter is invalid. Turning on +*   asserts would also catch this error. +* +* @note +* +* None. +* +******************************************************************************/ +XStatus +XEmac_SetPktWaitBound(XEmac * InstancePtr, u32 Direction, u32 TimerValue) +{ +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(Direction == XEM_SEND || Direction == XEM_RECV); +	XASSERT_NONVOID(TimerValue <= XEM_SGDMA_MAX_WAITBOUND); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* +	 * Be sure device is configured for scatter-gather DMA and has been stopped +	 */ +	if (!XEmac_mIsSgDma(InstancePtr)) { +		return XST_NOT_SGDMA; +	} + +	if (InstancePtr->IsStarted == XCOMPONENT_IS_STARTED) { +		return XST_DEVICE_IS_STARTED; +	} + +	/* +	 * Based on the direction, set the packet wait bound in the +	 * corresponding DMA channel component.  Default to the receive +	 * channel wait bound register (if an invalid Direction is passed). +	 */ +	switch (Direction) { +	case XEM_SEND: +		XDmaChannel_SetPktWaitBound(&InstancePtr->SendChannel, +					    TimerValue); +		break; + +	case XEM_RECV: +		XDmaChannel_SetPktWaitBound(&InstancePtr->RecvChannel, +					    TimerValue); +		break; + +	default: +		return XST_INVALID_PARAM; +	} + +	return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Get the packet wait bound timer for this driver/device. The packet wait bound +* is used during interrupt coalescing to trigger an interrupt when not enough +* packets have been received to reach the packet count threshold. A packet is a +* generic term used by the scatter-gather DMA engine, and is equivalent to an +* Ethernet frame in our case. The timer is in milliseconds. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param Direction indicates the channel, send or receive, from which the +*        threshold register is read. +* @param WaitPtr is a pointer to the byte into which the current value of the +*        packet wait bound register will be copied. An output parameter. Units +*        are in milliseconds in the range 0  - 1023. A value of 0 indicates the +*        packet wait bound timer is disabled. +* +* @return +* +* - XST_SUCCESS if the packet wait bound was retrieved successfully +* - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA +* - XST_INVALID_PARAM if the Direction parameter is invalid. Turning on +*   asserts would also catch this error. +* +* @note +* +* None. +* +******************************************************************************/ +XStatus +XEmac_GetPktWaitBound(XEmac * InstancePtr, u32 Direction, u32 * WaitPtr) +{ +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(Direction == XEM_SEND || Direction == XEM_RECV); +	XASSERT_NONVOID(WaitPtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	if (!XEmac_mIsSgDma(InstancePtr)) { +		return XST_NOT_SGDMA; +	} + +	/* +	 * Based on the direction, return the packet wait bound set in the +	 * corresponding DMA channel component.  Default to the value in +	 * the receive channel wait bound register (if an invalid Direction +	 * is passed). +	 */ +	switch (Direction) { +	case XEM_SEND: +		*WaitPtr = +		    XDmaChannel_GetPktWaitBound(&InstancePtr->SendChannel); +		break; + +	case XEM_RECV: +		*WaitPtr = +		    XDmaChannel_GetPktWaitBound(&InstancePtr->RecvChannel); +		break; + +	default: +		return XST_INVALID_PARAM; +	} + +	return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Give the driver the memory space to be used for the scatter-gather DMA +* receive descriptor list. This function should only be called once, during +* initialization of the Ethernet driver. The memory space must be big enough +* to hold some number of descriptors, depending on the needs of the system. +* The xemac.h file defines minimum and default numbers of descriptors +* which can be used to allocate this memory space. +* +* The memory space must be word-aligned. An assert will occur if asserts are +* turned on and the memory is not word-aligned. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param MemoryPtr is a pointer to the word-aligned memory. +* @param ByteCount is the length, in bytes, of the memory space. +* +* @return +* +* - XST_SUCCESS if the space was initialized successfully +* - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA +* - XST_DMA_SG_LIST_EXISTS if this list space has already been created +* +* @note +* +* If the device is configured for scatter-gather DMA, this function must be +* called AFTER the XEmac_Initialize() function because the DMA channel +* components must be initialized before the memory space is set. +* +******************************************************************************/ +XStatus +XEmac_SetSgRecvSpace(XEmac * InstancePtr, u32 * MemoryPtr, u32 ByteCount) +{ +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(MemoryPtr != NULL); +	XASSERT_NONVOID(ByteCount != 0); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	if (!XEmac_mIsSgDma(InstancePtr)) { +		return XST_NOT_SGDMA; +	} + +	return XDmaChannel_CreateSgList(&InstancePtr->RecvChannel, MemoryPtr, +					ByteCount); +} + +/*****************************************************************************/ +/** +* +* Give the driver the memory space to be used for the scatter-gather DMA +* transmit descriptor list. This function should only be called once, during +* initialization of the Ethernet driver. The memory space must be big enough +* to hold some number of descriptors, depending on the needs of the system. +* The xemac.h file defines minimum and default numbers of descriptors +* which can be used to allocate this memory space. +* +* The memory space must be word-aligned. An assert will occur if asserts are +* turned on and the memory is not word-aligned. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param MemoryPtr is a pointer to the word-aligned memory. +* @param ByteCount is the length, in bytes, of the memory space. +* +* @return +* +* - XST_SUCCESS if the space was initialized successfully +* - XST_NOT_SGDMA if the MAC is not configured for scatter-gather DMA +* - XST_DMA_SG_LIST_EXISTS if this list space has already been created +* +* @note +* +* If the device is configured for scatter-gather DMA, this function must be +* called AFTER the XEmac_Initialize() function because the DMA channel +* components must be initialized before the memory space is set. +* +******************************************************************************/ +XStatus +XEmac_SetSgSendSpace(XEmac * InstancePtr, u32 * MemoryPtr, u32 ByteCount) +{ +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(MemoryPtr != NULL); +	XASSERT_NONVOID(ByteCount != 0); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	if (!XEmac_mIsSgDma(InstancePtr)) { +		return XST_NOT_SGDMA; +	} + +	return XDmaChannel_CreateSgList(&InstancePtr->SendChannel, MemoryPtr, +					ByteCount); +} + +/*****************************************************************************/ +/** +* +* Set the callback function for handling received frames in scatter-gather DMA +* mode.  The upper layer software should call this function during +* initialization.  The callback is called once per frame received. The head of +* a descriptor list is passed in along with the number of descriptors in the +* list. Before leaving the callback, the upper layer software should attach a +* new buffer to each descriptor in the list. +* +* The callback is invoked by the driver within interrupt context, so it needs +* to do its job quickly. Sending the received frame up the protocol stack +* should be done at task-level. If there are other potentially slow operations +* within the callback, these too should be done at task-level. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param CallBackRef is a reference pointer to be passed back to the adapter in +*        the callback. This helps the adapter correlate the callback to a +*        particular driver. +* @param FuncPtr is the pointer to the callback function. +* +* @return +* +* None. +* +* @note +* +* None. +* +******************************************************************************/ +void +XEmac_SetSgRecvHandler(XEmac * InstancePtr, void *CallBackRef, +		       XEmac_SgHandler FuncPtr) +{ +	/* +	 * Asserted IsDmaSg here instead of run-time check because there is really +	 * no ill-effects of setting these when not configured for scatter-gather. +	 */ +	XASSERT_VOID(InstancePtr != NULL); +	XASSERT_VOID(FuncPtr != NULL); +	XASSERT_VOID(XEmac_mIsSgDma(InstancePtr)); +	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	InstancePtr->SgRecvHandler = FuncPtr; +	InstancePtr->SgRecvRef = CallBackRef; +} + +/*****************************************************************************/ +/** +* +* Set the callback function for handling confirmation of transmitted frames in +* scatter-gather DMA mode.  The upper layer software should call this function +* during initialization.  The callback is called once per frame sent. The head +* of a descriptor list is passed in along with the number of descriptors in +* the list. The callback is responsible for freeing buffers attached to these +* descriptors. +* +* The callback is invoked by the driver within interrupt context, so it needs +* to do its job quickly. If there are potentially slow operations within the +* callback, these should be done at task-level. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param CallBackRef is a reference pointer to be passed back to the adapter in +*        the callback. This helps the adapter correlate the callback to a +*        particular driver. +* @param FuncPtr is the pointer to the callback function. +* +* @return +* +* None. +* +* @note +* +* None. +* +******************************************************************************/ +void +XEmac_SetSgSendHandler(XEmac * InstancePtr, void *CallBackRef, +		       XEmac_SgHandler FuncPtr) +{ +	/* +	 * Asserted IsDmaSg here instead of run-time check because there is really +	 * no ill-effects of setting these when not configured for scatter-gather. +	 */ +	XASSERT_VOID(InstancePtr != NULL); +	XASSERT_VOID(FuncPtr != NULL); +	XASSERT_VOID(XEmac_mIsSgDma(InstancePtr)); +	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	InstancePtr->SgSendHandler = FuncPtr; +	InstancePtr->SgSendRef = CallBackRef; +} + +/*****************************************************************************/ +/* +* +* Handle an interrupt from the DMA receive channel. DMA interrupts are: +* +* - DMA error. DMA encountered a bus error or timeout. This is a fatal error +*   that requires reset of the channel.  The driver calls the error handler +*   of the upper layer software with an error code indicating the device should +*   be reset. +* - Packet count threshold reached.  For scatter-gather operations, indicates +*   the threshold for the number of packets not serviced by software has been +*   reached. The driver behaves as follows: +*       - Get the value of the packet counter, which tells us how many packets +*         are ready to be serviced +*       - For each packet +*           - For each descriptor, remove it from the scatter-gather list +*           - Check for the last descriptor in the frame, and if set +*               - Bump frame statistics +*               - Call the scatter-gather receive callback function +*               - Decrement the packet counter by one +*       Note that there are no receive errors reported in the status word of +*       the buffer descriptor.  If receive errors occur, the MAC drops the +*       packet, and we only find out about the errors through various error +*       count registers. +* - Packet wait bound reached.  For scatter-gather, indicates the time to wait +*   for the next packet has expired.  The driver follows the same logic as when +*   the packet count threshold interrupt is received. +* - Scatter-gather end acknowledge.  Hardware has reached the end of the +*   descriptor list.  The driver follows the same logic as when the packet count +*   threshold interrupt is received. In addition, the driver restarts the DMA +*   scatter-gather channel in case there are newly inserted descriptors. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* +* @return +* +* Although the function returns void, there are asynchronous errors that can +* be generated (by calling the ErrorHandler) from this function.  These are: +* - XST_DMA_SG_LIST_EMPTY indicates we tried to get a buffer descriptor from the +*   DMA channel, but there was not one ready for software. +* - XST_DMA_ERROR indicates a DMA bus error or timeout occurred. This is a fatal +*   error that requires reset. +* +* @note +* +* None. +* +******************************************************************************/ +static void +HandleDmaRecvIntr(XEmac * InstancePtr) +{ +	u32 IntrStatus; + +	/* +	 * Read the interrupt status +	 */ +	IntrStatus = XDmaChannel_GetIntrStatus(&InstancePtr->RecvChannel); + +	/* +	 * For packet threshold or wait bound interrupts, process desciptors. Also +	 * process descriptors on a SG end acknowledgement, which means the end of +	 * the descriptor list has been reached by the hardware. For receive, this +	 * is potentially trouble since it means the descriptor list is full, +	 * unless software can process enough packets quickly enough so the +	 * hardware has room to put new packets. +	 */ +	if (IntrStatus & (XDC_IXR_PKT_THRESHOLD_MASK | +			  XDC_IXR_PKT_WAIT_BOUND_MASK | XDC_IXR_SG_END_MASK)) { +		XStatus Result = XST_SUCCESS; +		u32 NumFrames; +		u32 NumProcessed; +		u32 NumBuffers; +		u32 NumBytes; +		u32 IsLast; +		XBufDescriptor *FirstBdPtr; +		XBufDescriptor *BdPtr; + +		/* +		 * Get the number of unserviced packets +		 */ +		NumFrames = XDmaChannel_GetPktCount(&InstancePtr->RecvChannel); + +		for (NumProcessed = 0; NumProcessed < NumFrames; NumProcessed++) { +			IsLast = FALSE; +			FirstBdPtr = NULL; +			NumBuffers = 0; +			NumBytes = 0; + +			/* +			 * For each packet, get the descriptor from the list. On the +			 * last one in the frame, make the callback to the upper layer. +			 */ +			while (!IsLast) { +				Result = +				    XDmaChannel_GetDescriptor(&InstancePtr-> +							      RecvChannel, +							      &BdPtr); +				if (Result != XST_SUCCESS) { +					/* +					 * An error getting a buffer descriptor from the list. +					 * This should not happen, but if it does, report it to +					 * the error callback and break out of the loops to service +					 * other interrupts. +					 */ +					InstancePtr->ErrorHandler(InstancePtr-> +								  ErrorRef, +								  Result); +					break; +				} + +				/* +				 * Keep a pointer to the first descriptor in the list, as it +				 * will be passed to the upper layers in a bit. By the fact +				 * that we received this packet means no errors occurred, so +				 * no need to check the device status word for errors. +				 */ +				if (FirstBdPtr == NULL) { +					FirstBdPtr = BdPtr; +				} + +				NumBytes += XBufDescriptor_GetLength(BdPtr); + +				/* +				 * Check to see if this is the last descriptor in the frame, +				 * and if so, set the IsLast flag to get out of the loop. +				 */ +				if (XBufDescriptor_IsLastStatus(BdPtr)) { +					IsLast = TRUE; +				} + +				/* +				 * Bump the number of buffers in this packet +				 */ +				NumBuffers++; + +			}	/* end while loop */ + +			/* +			 * Check for error that occurred inside the while loop, and break +			 * out of the for loop if there was one so other interrupts can +			 * be serviced. +			 */ +			if (Result != XST_SUCCESS) { +				break; +			} + +			InstancePtr->Stats.RecvFrames++; +			InstancePtr->Stats.RecvBytes += NumBytes; + +			/* +			 * Make the callback to the upper layers, passing it the first +			 * descriptor in the packet and the number of descriptors in the +			 * packet. +			 */ +			InstancePtr->SgRecvHandler(InstancePtr->SgRecvRef, +						   FirstBdPtr, NumBuffers); + +			/* +			 * Decrement the packet count register to reflect the fact we +			 * just processed a packet +			 */ +			XDmaChannel_DecrementPktCount(&InstancePtr-> +						      RecvChannel); + +		}		/* end for loop */ + +		/* +		 * If the interrupt was an end-ack, check the descriptor list again to +		 * see if it is empty. If not, go ahead and restart the scatter-gather +		 * channel. This is to fix a possible race condition where, on receive, +		 * the driver attempted to start a scatter-gather channel that was +		 * already started, which resulted in no action from the XDmaChannel +		 * component. But, just after the XDmaChannel component saw that the +		 * hardware was already started, the hardware stopped because it +		 * reached the end of the list.  In that case, this interrupt is +		 * generated and we can restart the hardware here. +		 */ +		if (IntrStatus & XDC_IXR_SG_END_MASK) { +			/* +			 * Ignore the return status since we know the list exists and we +			 * don't care if the list is empty or the channel is already started. +			 */ +			(void) XDmaChannel_SgStart(&InstancePtr->RecvChannel); +		} +	} + +	/* +	 * All interrupts are handled (except the error below) so acknowledge +	 * (clear) the interrupts by writing the value read above back to the status +	 * register. The packet count interrupt must be acknowledged after the +	 * decrement, otherwise it will come right back. We clear the interrupts +	 * before we handle the error interrupt because the ErrorHandler should +	 * result in a reset, which clears the interrupt status register. So we +	 * don't want to toggle the interrupt back on by writing the interrupt +	 * status register with an old value after a reset. +	 */ +	XDmaChannel_SetIntrStatus(&InstancePtr->RecvChannel, IntrStatus); + +	/* +	 * Check for DMA errors and call the error callback function if an error +	 * occurred (DMA bus or timeout error), which should result in a reset of +	 * the device by the upper layer software. +	 */ +	if (IntrStatus & XDC_IXR_DMA_ERROR_MASK) { +		InstancePtr->Stats.DmaErrors++; +		InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XST_DMA_ERROR); +	} +} + +/*****************************************************************************/ +/* +* +* Handle an interrupt from the DMA send channel. DMA interrupts are: +* +* - DMA error. DMA encountered a bus error or timeout. This is a fatal error +*   that requires reset of the channel.  The driver calls the error handler +*   of the upper layer software with an error code indicating the device should +*   be reset. +* - Packet count threshold reached.  For scatter-gather operations, indicates +*   the threshold for the number of packets not serviced by software has been +*   reached. The driver behaves as follows: +*       - Get the value of the packet counter, which tells us how many packets +*         are ready to be serviced +*       - For each packet +*           - For each descriptor, remove it from the scatter-gather list +*           - Check for the last descriptor in the frame, and if set +*               - Bump frame statistics +*               - Call the scatter-gather receive callback function +*               - Decrement the packet counter by one +*       Note that there are no receive errors reported in the status word of +*       the buffer descriptor.  If receive errors occur, the MAC drops the +*       packet, and we only find out about the errors through various error +*       count registers. +* - Packet wait bound reached.  For scatter-gather, indicates the time to wait +*   for the next packet has expired.  The driver follows the same logic as when +*   the packet count threshold interrupt is received. +* - Scatter-gather end acknowledge.  Hardware has reached the end of the +*   descriptor list.  The driver follows the same logic as when the packet count +*   threshold interrupt is received. In addition, the driver restarts the DMA +*   scatter-gather channel in case there are newly inserted descriptors. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* +* @return +* +* Although the function returns void, there are asynchronous errors +* that can be generated from this function.  These are: +* - XST_DMA_SG_LIST_EMPTY indicates we tried to get a buffer descriptor from +*   the DMA channel, but there was not one ready for software. +* - XST_DMA_ERROR indicates a DMA bus error or timeout occurred. This is a +*   fatal error that requires reset. +* +* @note +* +* None. +* +******************************************************************************/ +static void +HandleDmaSendIntr(XEmac * InstancePtr) +{ +	u32 IntrStatus; + +	/* +	 * Read the interrupt status +	 */ +	IntrStatus = XDmaChannel_GetIntrStatus(&InstancePtr->SendChannel); + +	/* +	 * For packet threshold or wait bound interrupt, process descriptors. Also +	 * process descriptors on a SG end acknowledgement, which means the end of +	 * the descriptor list has been reached by the hardware. For transmit, +	 * this is a normal condition during times of light traffic.  In fact, the +	 * wait bound interrupt may be masked for transmit since the end-ack would +	 * always occur before the wait bound expires. +	 */ +	if (IntrStatus & (XDC_IXR_PKT_THRESHOLD_MASK | +			  XDC_IXR_PKT_WAIT_BOUND_MASK | XDC_IXR_SG_END_MASK)) { +		XStatus Result = XST_SUCCESS; +		u32 NumFrames; +		u32 NumProcessed; +		u32 NumBuffers; +		u32 NumBytes; +		u32 IsLast; +		XBufDescriptor *FirstBdPtr; +		XBufDescriptor *BdPtr; + +		/* +		 * Get the number of unserviced packets +		 */ +		NumFrames = XDmaChannel_GetPktCount(&InstancePtr->SendChannel); + +		for (NumProcessed = 0; NumProcessed < NumFrames; NumProcessed++) { +			IsLast = FALSE; +			FirstBdPtr = NULL; +			NumBuffers = 0; +			NumBytes = 0; + +			/* +			 * For each frame, traverse the descriptor list and look for +			 * errors. On the last one in the frame, make the callback. +			 */ +			while (!IsLast) { +				Result = +				    XDmaChannel_GetDescriptor(&InstancePtr-> +							      SendChannel, +							      &BdPtr); +				if (Result != XST_SUCCESS) { +					/* +					 * An error getting a buffer descriptor from the list. +					 * This should not happen, but if it does, report it to +					 * the error callback and break out of the loops to service +					 * other interrupts +					 */ +					InstancePtr->ErrorHandler(InstancePtr-> +								  ErrorRef, +								  Result); +					break; +				} + +				/* +				 * Keep a pointer to the first descriptor in the list and +				 * check the device status for errors. The device status is +				 * only available in the first descriptor of a packet. +				 */ +				if (FirstBdPtr == NULL) { +					u32 XmitStatus; + +					FirstBdPtr = BdPtr; + +					XmitStatus = +					    XBufDescriptor_GetDeviceStatus +					    (BdPtr); +					if (XmitStatus & +					    XEM_TSR_EXCESS_DEFERRAL_MASK) { +						InstancePtr->Stats. +						    XmitExcessDeferral++; +					} + +					if (XmitStatus & +					    XEM_TSR_LATE_COLLISION_MASK) { +						InstancePtr->Stats. +						    XmitLateCollisionErrors++; +					} +				} + +				NumBytes += XBufDescriptor_GetLength(BdPtr); + +				/* +				 * Check to see if this is the last descriptor in the frame, +				 * and if so, set the IsLast flag to get out of the loop. The +				 * transmit channel must check the last bit in the control +				 * word, not the status word (the DMA engine does not update +				 * the last bit in the status word for the transmit direction). +				 */ +				if (XBufDescriptor_IsLastControl(BdPtr)) { +					IsLast = TRUE; +				} + +				/* +				 * Bump the number of buffers in this packet +				 */ +				NumBuffers++; + +			}	/* end while loop */ + +			/* +			 * Check for error that occurred inside the while loop, and break +			 * out of the for loop if there was one so other interrupts can +			 * be serviced. +			 */ +			if (Result != XST_SUCCESS) { +				break; +			} + +			InstancePtr->Stats.XmitFrames++; +			InstancePtr->Stats.XmitBytes += NumBytes; + +			/* +			 * Make the callback to the upper layers, passing it the first +			 * descriptor in the packet and the number of descriptors in the +			 * packet. +			 */ +			InstancePtr->SgSendHandler(InstancePtr->SgSendRef, +						   FirstBdPtr, NumBuffers); + +			/* +			 * Decrement the packet count register to reflect the fact we +			 * just processed a packet +			 */ +			XDmaChannel_DecrementPktCount(&InstancePtr-> +						      SendChannel); + +		}		/* end for loop */ + +		/* +		 * If the interrupt was an end-ack, check the descriptor list again to +		 * see if it is empty. If not, go ahead and restart the scatter-gather +		 * channel. This is to fix a possible race condition where, on transmit, +		 * the driver attempted to start a scatter-gather channel that was +		 * already started, which resulted in no action from the XDmaChannel +		 * component. But, just after the XDmaChannel component saw that the +		 * hardware was already started, the hardware stopped because it +		 * reached the end of the list.  In that case, this interrupt is +		 * generated and we can restart the hardware here. +		 */ +		if (IntrStatus & XDC_IXR_SG_END_MASK) { +			/* +			 * Ignore the return status since we know the list exists and we +			 * don't care if the list is empty or the channel is already started. +			 */ +			(void) XDmaChannel_SgStart(&InstancePtr->SendChannel); +		} +	} + +	/* +	 * All interrupts are handled (except the error below) so acknowledge +	 * (clear) the interrupts by writing the value read above back to the status +	 * register. The packet count interrupt must be acknowledged after the +	 * decrement, otherwise it will come right back. We clear the interrupts +	 * before we handle the error interrupt because the ErrorHandler should +	 * result in a reset, which clears the interrupt status register. So we +	 * don't want to toggle the interrupt back on by writing the interrupt +	 * status register with an old value after a reset. +	 */ +	XDmaChannel_SetIntrStatus(&InstancePtr->SendChannel, IntrStatus); + +	/* +	 * Check for DMA errors and call the error callback function if an error +	 * occurred (DMA bus or timeout error), which should result in a reset of +	 * the device by the upper layer software. +	 */ +	if (IntrStatus & XDC_IXR_DMA_ERROR_MASK) { +		InstancePtr->Stats.DmaErrors++; +		InstancePtr->ErrorHandler(InstancePtr->ErrorRef, XST_DMA_ERROR); +	} +} + +/*****************************************************************************/ +/* +* +* Handle an interrupt from the Ethernet MAC when configured with scatter-gather +* DMA. The only interrupts handled in this case are errors. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* +* @return +* +* None. +* +* @note +* +* None. +* +******************************************************************************/ +static void +HandleEmacDmaIntr(XEmac * InstancePtr) +{ +	u32 IntrStatus; + +	/* +	 * When configured with DMA, the EMAC generates interrupts only when errors +	 * occur. We clear the interrupts immediately so that any latched status +	 * interrupt bits will reflect the true status of the device, and so any +	 * pulsed interrupts (non-status) generated during the Isr will not be lost. +	 */ +	IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress); +	XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress, IntrStatus); + +	/* +	 * Check the MAC for errors +	 */ +	XEmac_CheckEmacError(InstancePtr, IntrStatus); +} diff --git a/board/xilinx/xilinx_enet/xemac_l.h b/board/xilinx/xilinx_enet/xemac_l.h new file mode 100644 index 000000000..a463937db --- /dev/null +++ b/board/xilinx/xilinx_enet/xemac_l.h @@ -0,0 +1,462 @@ +/****************************************************************************** +* +*     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. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xemac_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 xemac.h. +* +* <pre> +* MODIFICATION HISTORY: +* +* Ver	Who  Date     Changes +* ----- ---- -------- ----------------------------------------------- +* 1.00b rpm  04/26/02 First release +* 1.00b rmm  09/23/02 Added XEmac_mPhyReset macro +* 1.00c rpm  12/05/02 New version includes support for simple DMA +* </pre> +* +******************************************************************************/ + +#ifndef XEMAC_L_H		/* prevent circular inclusions */ +#define XEMAC_L_H		/* by using protection macros */ + +/***************************** Include Files *********************************/ + +#include "xbasic_types.h" +#include "xio.h" + +/************************** Constant Definitions *****************************/ + +/* Offset of the MAC registers from the IPIF base address */ +#define XEM_REG_OFFSET	   0x1100UL + +/* + * Register offsets for the Ethernet MAC. Each register is 32 bits. + */ +#define XEM_EMIR_OFFSET	  (XEM_REG_OFFSET + 0x0)	/* EMAC Module ID */ +#define XEM_ECR_OFFSET	  (XEM_REG_OFFSET + 0x4)	/* MAC Control */ +#define XEM_IFGP_OFFSET	  (XEM_REG_OFFSET + 0x8)	/* Interframe Gap */ +#define XEM_SAH_OFFSET	  (XEM_REG_OFFSET + 0xC)	/* Station addr, high */ +#define XEM_SAL_OFFSET	  (XEM_REG_OFFSET + 0x10)	/* Station addr, low */ +#define XEM_MGTCR_OFFSET  (XEM_REG_OFFSET + 0x14)	/* MII mgmt control */ +#define XEM_MGTDR_OFFSET  (XEM_REG_OFFSET + 0x18)	/* MII mgmt data */ +#define XEM_RPLR_OFFSET	  (XEM_REG_OFFSET + 0x1C)	/* Rx packet length */ +#define XEM_TPLR_OFFSET	  (XEM_REG_OFFSET + 0x20)	/* Tx packet length */ +#define XEM_TSR_OFFSET	  (XEM_REG_OFFSET + 0x24)	/* Tx status */ +#define XEM_RMFC_OFFSET	  (XEM_REG_OFFSET + 0x28)	/* Rx missed frames */ +#define XEM_RCC_OFFSET	  (XEM_REG_OFFSET + 0x2C)	/* Rx collisions */ +#define XEM_RFCSEC_OFFSET (XEM_REG_OFFSET + 0x30)	/* Rx FCS errors */ +#define XEM_RAEC_OFFSET	  (XEM_REG_OFFSET + 0x34)	/* Rx alignment errors */ +#define XEM_TEDC_OFFSET	  (XEM_REG_OFFSET + 0x38)	/* Transmit excess +							 * deferral cnt */ + +/* + * Register offsets for the IPIF components + */ +#define XEM_ISR_OFFSET		 0x20UL /* Interrupt status */ + +#define XEM_DMA_OFFSET		 0x2300UL +#define XEM_DMA_SEND_OFFSET	 (XEM_DMA_OFFSET + 0x0) /* DMA send channel */ +#define XEM_DMA_RECV_OFFSET	 (XEM_DMA_OFFSET + 0x40)	/* DMA recv channel */ + +#define XEM_PFIFO_OFFSET	 0x2000UL +#define XEM_PFIFO_TXREG_OFFSET	 (XEM_PFIFO_OFFSET + 0x0)	/* Tx registers */ +#define XEM_PFIFO_RXREG_OFFSET	 (XEM_PFIFO_OFFSET + 0x10)	/* Rx registers */ +#define XEM_PFIFO_TXDATA_OFFSET	 (XEM_PFIFO_OFFSET + 0x100)	/* Tx keyhole */ +#define XEM_PFIFO_RXDATA_OFFSET	 (XEM_PFIFO_OFFSET + 0x200)	/* Rx keyhole */ + +/* + * EMAC Module Identification Register (EMIR) + */ +#define XEM_EMIR_VERSION_MASK	 0xFFFF0000UL	/* Device version */ +#define XEM_EMIR_TYPE_MASK	 0x0000FF00UL	/* Device type */ + +/* + * EMAC Control Register (ECR) + */ +#define XEM_ECR_FULL_DUPLEX_MASK	 0x80000000UL	/* Full duplex mode */ +#define XEM_ECR_XMIT_RESET_MASK		 0x40000000UL	/* Reset transmitter */ +#define XEM_ECR_XMIT_ENABLE_MASK	 0x20000000UL	/* Enable transmitter */ +#define XEM_ECR_RECV_RESET_MASK		 0x10000000UL	/* Reset receiver */ +#define XEM_ECR_RECV_ENABLE_MASK	 0x08000000UL	/* Enable receiver */ +#define XEM_ECR_PHY_ENABLE_MASK		 0x04000000UL	/* Enable PHY */ +#define XEM_ECR_XMIT_PAD_ENABLE_MASK	 0x02000000UL	/* Enable xmit pad insert */ +#define XEM_ECR_XMIT_FCS_ENABLE_MASK	 0x01000000UL	/* Enable xmit FCS insert */ +#define XEM_ECR_XMIT_ADDR_INSERT_MASK	 0x00800000UL	/* Enable xmit source addr +							 * insertion */ +#define XEM_ECR_XMIT_ERROR_INSERT_MASK	 0x00400000UL	/* Insert xmit error */ +#define XEM_ECR_XMIT_ADDR_OVWRT_MASK	 0x00200000UL	/* Enable xmit source addr +							 * overwrite */ +#define XEM_ECR_LOOPBACK_MASK		 0x00100000UL	/* Enable internal +							 * loopback */ +#define XEM_ECR_RECV_STRIP_ENABLE_MASK	 0x00080000UL	/* Enable recv pad/fcs strip */ +#define XEM_ECR_UNICAST_ENABLE_MASK	 0x00020000UL	/* Enable unicast addr */ +#define XEM_ECR_MULTI_ENABLE_MASK	 0x00010000UL	/* Enable multicast addr */ +#define XEM_ECR_BROAD_ENABLE_MASK	 0x00008000UL	/* Enable broadcast addr */ +#define XEM_ECR_PROMISC_ENABLE_MASK	 0x00004000UL	/* Enable promiscuous mode */ +#define XEM_ECR_RECV_ALL_MASK		 0x00002000UL	/* Receive all frames */ +#define XEM_ECR_RESERVED2_MASK		 0x00001000UL	/* Reserved */ +#define XEM_ECR_MULTI_HASH_ENABLE_MASK	 0x00000800UL	/* Enable multicast hash */ +#define XEM_ECR_PAUSE_FRAME_MASK	 0x00000400UL	/* Interpret pause frames */ +#define XEM_ECR_CLEAR_HASH_MASK		 0x00000200UL	/* Clear hash table */ +#define XEM_ECR_ADD_HASH_ADDR_MASK	 0x00000100UL	/* Add hash table address */ + +/* + * Interframe Gap Register (IFGR) + */ +#define XEM_IFGP_PART1_MASK	    0xF8000000UL	/* Interframe Gap Part1 */ +#define XEM_IFGP_PART1_SHIFT	    27 +#define XEM_IFGP_PART2_MASK	    0x07C00000UL	/* Interframe Gap Part2 */ +#define XEM_IFGP_PART2_SHIFT	    22 + +/* + * Station Address High Register (SAH) + */ +#define XEM_SAH_ADDR_MASK	    0x0000FFFFUL	/* Station address high bytes */ + +/* + * Station Address Low Register (SAL) + */ +#define XEM_SAL_ADDR_MASK	    0xFFFFFFFFUL	/* Station address low bytes */ + +/* + * MII Management Control Register (MGTCR) + */ +#define XEM_MGTCR_START_MASK	    0x80000000UL	/* Start/Busy */ +#define XEM_MGTCR_RW_NOT_MASK	    0x40000000UL	/* Read/Write Not (direction) */ +#define XEM_MGTCR_PHY_ADDR_MASK	    0x3E000000UL	/* PHY address */ +#define XEM_MGTCR_PHY_ADDR_SHIFT    25	/* PHY address shift */ +#define XEM_MGTCR_REG_ADDR_MASK	    0x01F00000UL	/* Register address */ +#define XEM_MGTCR_REG_ADDR_SHIFT    20	/* Register addr shift */ +#define XEM_MGTCR_MII_ENABLE_MASK   0x00080000UL	/* Enable MII from EMAC */ +#define XEM_MGTCR_RD_ERROR_MASK	    0x00040000UL	/* MII mgmt read error */ + +/* + * MII Management Data Register (MGTDR) + */ +#define XEM_MGTDR_DATA_MASK	    0x0000FFFFUL	/* MII data */ + +/* + * Receive Packet Length Register (RPLR) + */ +#define XEM_RPLR_LENGTH_MASK	    0x0000FFFFUL	/* Receive packet length */ + +/* + * Transmit Packet Length Register (TPLR) + */ +#define XEM_TPLR_LENGTH_MASK	    0x0000FFFFUL	/* Transmit packet length */ + +/* + * Transmit Status Register (TSR) + */ +#define XEM_TSR_EXCESS_DEFERRAL_MASK 0x80000000UL	/* Transmit excess deferral */ +#define XEM_TSR_FIFO_UNDERRUN_MASK   0x40000000UL	/* Packet FIFO underrun */ +#define XEM_TSR_ATTEMPTS_MASK	     0x3E000000UL	/* Transmission attempts */ +#define XEM_TSR_LATE_COLLISION_MASK  0x01000000UL	/* Transmit late collision */ + +/* + * Receive Missed Frame Count (RMFC) + */ +#define XEM_RMFC_DATA_MASK	    0x0000FFFFUL + +/* + * Receive Collision Count (RCC) + */ +#define XEM_RCC_DATA_MASK	    0x0000FFFFUL + +/* + * Receive FCS Error Count (RFCSEC) + */ +#define XEM_RFCSEC_DATA_MASK	    0x0000FFFFUL + +/* + * Receive Alignment Error Count (RALN) + */ +#define XEM_RAEC_DATA_MASK	    0x0000FFFFUL + +/* + * Transmit Excess Deferral Count (TEDC) + */ +#define XEM_TEDC_DATA_MASK	    0x0000FFFFUL + +/* + * EMAC Interrupt Registers (Status and Enable) masks. These registers are + * part of the IPIF IP Interrupt registers + */ +#define XEM_EIR_XMIT_DONE_MASK	       0x00000001UL	/* Xmit complete */ +#define XEM_EIR_RECV_DONE_MASK	       0x00000002UL	/* Recv complete */ +#define XEM_EIR_XMIT_ERROR_MASK	       0x00000004UL	/* Xmit error */ +#define XEM_EIR_RECV_ERROR_MASK	       0x00000008UL	/* Recv error */ +#define XEM_EIR_XMIT_SFIFO_EMPTY_MASK  0x00000010UL	/* Xmit status fifo empty */ +#define XEM_EIR_RECV_LFIFO_EMPTY_MASK  0x00000020UL	/* Recv length fifo empty */ +#define XEM_EIR_XMIT_LFIFO_FULL_MASK   0x00000040UL	/* Xmit length fifo full */ +#define XEM_EIR_RECV_LFIFO_OVER_MASK   0x00000080UL	/* Recv length fifo +							 * overrun */ +#define XEM_EIR_RECV_LFIFO_UNDER_MASK  0x00000100UL	/* Recv length fifo +							 * underrun */ +#define XEM_EIR_XMIT_SFIFO_OVER_MASK   0x00000200UL	/* Xmit status fifo +							 * overrun */ +#define XEM_EIR_XMIT_SFIFO_UNDER_MASK  0x00000400UL	/* Transmit status fifo +							 * underrun */ +#define XEM_EIR_XMIT_LFIFO_OVER_MASK   0x00000800UL	/* Transmit length fifo +							 * overrun */ +#define XEM_EIR_XMIT_LFIFO_UNDER_MASK  0x00001000UL	/* Transmit length fifo +							 * underrun */ +#define XEM_EIR_XMIT_PAUSE_MASK	       0x00002000UL	/* Transmit pause pkt +							 * received */ +#define XEM_EIR_RECV_DFIFO_OVER_MASK   0x00004000UL	/* Receive data fifo +							 * overrun */ +#define XEM_EIR_RECV_MISSED_FRAME_MASK 0x00008000UL	/* Receive missed frame +							 * error */ +#define XEM_EIR_RECV_COLLISION_MASK    0x00010000UL	/* Receive collision +							 * error */ +#define XEM_EIR_RECV_FCS_ERROR_MASK    0x00020000UL	/* Receive FCS error */ +#define XEM_EIR_RECV_LEN_ERROR_MASK    0x00040000UL	/* Receive length field +							 * error */ +#define XEM_EIR_RECV_SHORT_ERROR_MASK  0x00080000UL	/* Receive short frame +							 * error */ +#define XEM_EIR_RECV_LONG_ERROR_MASK   0x00100000UL	/* Receive long frame +							 * error */ +#define XEM_EIR_RECV_ALIGN_ERROR_MASK  0x00200000UL	/* Receive alignment +							 * error */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/***************************************************************************** +* +* Low-level driver macros and functions. The list below provides signatures +* to help the user use the macros. +* +* u32 XEmac_mReadReg(u32 BaseAddress, int RegOffset) +* void XEmac_mWriteReg(u32 BaseAddress, int RegOffset, u32 Mask) +* +* void XEmac_mSetControlReg(u32 BaseAddress, u32 Mask) +* void XEmac_mSetMacAddress(u32 BaseAddress, u8 *AddressPtr) +* +* void XEmac_mEnable(u32 BaseAddress) +* void XEmac_mDisable(u32 BaseAddress) +* +* u32 XEmac_mIsTxDone(u32 BaseAddress) +* u32 XEmac_mIsRxEmpty(u32 BaseAddress) +* +* void XEmac_SendFrame(u32 BaseAddress, u8 *FramePtr, int Size) +* int XEmac_RecvFrame(u32 BaseAddress, u8 *FramePtr) +* +*****************************************************************************/ + +/****************************************************************************/ +/** +* +* Read the given register. +* +* @param    BaseAddress is the base address of the device +* @param    RegOffset is the register offset to be read +* +* @return   The 32-bit value of the register +* +* @note	    None. +* +*****************************************************************************/ +#define XEmac_mReadReg(BaseAddress, RegOffset) \ +		    XIo_In32((BaseAddress) + (RegOffset)) + +/****************************************************************************/ +/** +* +* Write the given register. +* +* @param    BaseAddress is the base address of the device +* @param    RegOffset is the register offset to be written +* @param    Data is the 32-bit value to write to the register +* +* @return   None. +* +* @note	    None. +* +*****************************************************************************/ +#define XEmac_mWriteReg(BaseAddress, RegOffset, Data) \ +		    XIo_Out32((BaseAddress) + (RegOffset), (Data)) + +/****************************************************************************/ +/** +* +* Set the contents of the control register. Use the XEM_ECR_* constants +* defined above to create the bit-mask to be written to the register. +* +* @param    BaseAddress is the base address of the device +* @param    Mask is the 16-bit value to write to the control register +* +* @return   None. +* +* @note	    None. +* +*****************************************************************************/ +#define XEmac_mSetControlReg(BaseAddress, Mask) \ +		    XIo_Out32((BaseAddress) + XEM_ECR_OFFSET, (Mask)) + +/****************************************************************************/ +/** +* +* Set the station address of the EMAC device. +* +* @param    BaseAddress is the base address of the device +* @param    AddressPtr is a pointer to a 6-byte MAC address +* +* @return   None. +* +* @note	    None. +* +*****************************************************************************/ +#define XEmac_mSetMacAddress(BaseAddress, AddressPtr)		    \ +{								    \ +    u32 MacAddr;						\ +								    \ +    MacAddr = ((AddressPtr)[0] << 8) | (AddressPtr)[1];		    \ +    XIo_Out32((BaseAddress) + XEM_SAH_OFFSET, MacAddr);		    \ +								    \ +    MacAddr = ((AddressPtr)[2] << 24) | ((AddressPtr)[3] << 16) |   \ +	      ((AddressPtr)[4] << 8) | (AddressPtr)[5];		    \ +								    \ +    XIo_Out32((BaseAddress) + XEM_SAL_OFFSET, MacAddr);		    \ +} + +/****************************************************************************/ +/** +* +* Enable the transmitter and receiver. Preserve the contents of the control +* register. +* +* @param    BaseAddress is the base address of the device +* +* @return   None. +* +* @note	    None. +* +*****************************************************************************/ +#define XEmac_mEnable(BaseAddress) \ +{ \ +    u32 Control; \ +    Control = XIo_In32((BaseAddress) + XEM_ECR_OFFSET); \ +    Control &= ~(XEM_ECR_XMIT_RESET_MASK | XEM_ECR_RECV_RESET_MASK); \ +    Control |= (XEM_ECR_XMIT_ENABLE_MASK | XEM_ECR_RECV_ENABLE_MASK); \ +    XIo_Out32((BaseAddress) + XEM_ECR_OFFSET, Control); \ +} + +/****************************************************************************/ +/** +* +* Disable the transmitter and receiver. Preserve the contents of the control +* register. +* +* @param    BaseAddress is the base address of the device +* +* @return   None. +* +* @note	    None. +* +*****************************************************************************/ +#define XEmac_mDisable(BaseAddress) \ +		XIo_Out32((BaseAddress) + XEM_ECR_OFFSET, \ +		    XIo_In32((BaseAddress) + XEM_ECR_OFFSET) & \ +		    ~(XEM_ECR_XMIT_ENABLE_MASK | XEM_ECR_RECV_ENABLE_MASK)) + +/****************************************************************************/ +/** +* +* Check to see if the transmission is complete. +* +* @param    BaseAddress is the base address of the device +* +* @return   TRUE if it is done, or FALSE if it is not. +* +* @note	    None. +* +*****************************************************************************/ +#define XEmac_mIsTxDone(BaseAddress) \ +	     (XIo_In32((BaseAddress) + XEM_ISR_OFFSET) & XEM_EIR_XMIT_DONE_MASK) + +/****************************************************************************/ +/** +* +* Check to see if the receive FIFO is empty. +* +* @param    BaseAddress is the base address of the device +* +* @return   TRUE if it is empty, or FALSE if it is not. +* +* @note	    None. +* +*****************************************************************************/ +#define XEmac_mIsRxEmpty(BaseAddress) \ +	  (!(XIo_In32((BaseAddress) + XEM_ISR_OFFSET) & XEM_EIR_RECV_DONE_MASK)) + +/****************************************************************************/ +/** +* +* Reset MII compliant PHY +* +* @param    BaseAddress is the base address of the device +* +* @return   None. +* +* @note	    None. +* +*****************************************************************************/ +#define XEmac_mPhyReset(BaseAddress) \ +{ \ +    u32 Control;				    \ +    Control = XIo_In32((BaseAddress) + XEM_ECR_OFFSET); \ +    Control &= ~XEM_ECR_PHY_ENABLE_MASK;		\ +    XIo_Out32((BaseAddress) + XEM_ECR_OFFSET, Control); \ +    Control |= XEM_ECR_PHY_ENABLE_MASK;			\ +    XIo_Out32((BaseAddress) + XEM_ECR_OFFSET, Control); \ +} + +/************************** Function Prototypes ******************************/ + +void XEmac_SendFrame(u32 BaseAddress, u8 * FramePtr, int Size); +int XEmac_RecvFrame(u32 BaseAddress, u8 * FramePtr); + +#endif				/* end of protection macro */ diff --git a/board/xilinx/xilinx_enet/xemac_options.c b/board/xilinx/xilinx_enet/xemac_options.c new file mode 100644 index 000000000..1f225f8f5 --- /dev/null +++ b/board/xilinx/xilinx_enet/xemac_options.c @@ -0,0 +1,318 @@ +/****************************************************************************** +* +*     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. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xemac_options.c +* +* Functions in this file handle configuration of the XEmac driver. +* +* <pre> +* MODIFICATION HISTORY: +* +* Ver   Who  Date     Changes +* ----- ---- -------- ----------------------------------------------- +* 1.00a rpm  07/31/01 First release +* 1.00b rpm  02/20/02 Repartitioned files and functions +* 1.00c rpm  12/05/02 New version includes support for simple DMA +* </pre> +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xbasic_types.h" +#include "xemac_i.h" +#include "xio.h" + +/************************** Constant Definitions *****************************/ + +#define XEM_MAX_IFG         32	/* Maximum Interframe gap value */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ + +/* + * A table of options and masks. This table maps the user-visible options with + * the control register masks. It is used in Set/GetOptions as an alternative + * to a series of if/else pairs. Note that the polled options does not have a + * corresponding entry in the control register, so it does not exist in the + * table. + */ +typedef struct { +	u32 Option; +	u32 Mask; +} OptionMap; + +static OptionMap OptionsTable[] = { +	{XEM_UNICAST_OPTION, XEM_ECR_UNICAST_ENABLE_MASK}, +	{XEM_BROADCAST_OPTION, XEM_ECR_BROAD_ENABLE_MASK}, +	{XEM_PROMISC_OPTION, XEM_ECR_PROMISC_ENABLE_MASK}, +	{XEM_FDUPLEX_OPTION, XEM_ECR_FULL_DUPLEX_MASK}, +	{XEM_LOOPBACK_OPTION, XEM_ECR_LOOPBACK_MASK}, +	{XEM_MULTICAST_OPTION, XEM_ECR_MULTI_ENABLE_MASK}, +	{XEM_FLOW_CONTROL_OPTION, XEM_ECR_PAUSE_FRAME_MASK}, +	{XEM_INSERT_PAD_OPTION, XEM_ECR_XMIT_PAD_ENABLE_MASK}, +	{XEM_INSERT_FCS_OPTION, XEM_ECR_XMIT_FCS_ENABLE_MASK}, +	{XEM_INSERT_ADDR_OPTION, XEM_ECR_XMIT_ADDR_INSERT_MASK}, +	{XEM_OVWRT_ADDR_OPTION, XEM_ECR_XMIT_ADDR_OVWRT_MASK}, +	{XEM_STRIP_PAD_FCS_OPTION, XEM_ECR_RECV_STRIP_ENABLE_MASK} +}; + +#define XEM_NUM_OPTIONS     (sizeof(OptionsTable) / sizeof(OptionMap)) + +/*****************************************************************************/ +/** +* +* Set Ethernet driver/device options.  The device must be stopped before +* calling this function.  The options are contained within a bit-mask with each +* bit representing an option (i.e., you can OR the options together). A one (1) +* in the bit-mask turns an option on, and a zero (0) turns the option off. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param OptionsFlag is a bit-mask representing the Ethernet options to turn on +*        or off. See xemac.h for a description of the available options. +* +* @return +* +* - XST_SUCCESS if the options were set successfully +* - XST_DEVICE_IS_STARTED if the device has not yet been stopped +* +* @note +* +* This function is not thread-safe and makes use of internal resources that are +* shared between the Start, Stop, and SetOptions functions, so if one task +* might be setting device options while another is trying to start the device, +* protection of this shared data (typically using a semaphore) is required. +* +******************************************************************************/ +XStatus +XEmac_SetOptions(XEmac * InstancePtr, u32 OptionsFlag) +{ +	u32 ControlReg; +	int Index; + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	if (InstancePtr->IsStarted == XCOMPONENT_IS_STARTED) { +		return XST_DEVICE_IS_STARTED; +	} + +	ControlReg = XIo_In32(InstancePtr->BaseAddress + XEM_ECR_OFFSET); + +	/* +	 * Loop through the options table, turning the option on or off +	 * depending on whether the bit is set in the incoming options flag. +	 */ +	for (Index = 0; Index < XEM_NUM_OPTIONS; Index++) { +		if (OptionsFlag & OptionsTable[Index].Option) { +			ControlReg |= OptionsTable[Index].Mask;	/* turn it on */ +		} else { +			ControlReg &= ~OptionsTable[Index].Mask;	/* turn it off */ +		} +	} + +	/* +	 * TODO: need to validate addr-overwrite only if addr-insert? +	 */ + +	/* +	 * Now write the control register. Leave it to the upper layers +	 * to restart the device. +	 */ +	XIo_Out32(InstancePtr->BaseAddress + XEM_ECR_OFFSET, ControlReg); + +	/* +	 * Check the polled option +	 */ +	if (OptionsFlag & XEM_POLLED_OPTION) { +		InstancePtr->IsPolled = TRUE; +	} else { +		InstancePtr->IsPolled = FALSE; +	} + +	return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Get Ethernet driver/device options. The 32-bit value returned is a bit-mask +* representing the options.  A one (1) in the bit-mask means the option is on, +* and a zero (0) means the option is off. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* +* @return +* +* The 32-bit value of the Ethernet options. The value is a bit-mask +* representing all options that are currently enabled. See xemac.h for a +* description of the available options. +* +* @note +* +* None. +* +******************************************************************************/ +u32 +XEmac_GetOptions(XEmac * InstancePtr) +{ +	u32 OptionsFlag = 0; +	u32 ControlReg; +	int Index; + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* +	 * Get the control register to determine which options are currently set. +	 */ +	ControlReg = XIo_In32(InstancePtr->BaseAddress + XEM_ECR_OFFSET); + +	/* +	 * Loop through the options table to determine which options are set +	 */ +	for (Index = 0; Index < XEM_NUM_OPTIONS; Index++) { +		if (ControlReg & OptionsTable[Index].Mask) { +			OptionsFlag |= OptionsTable[Index].Option; +		} +	} + +	if (InstancePtr->IsPolled) { +		OptionsFlag |= XEM_POLLED_OPTION; +	} + +	return OptionsFlag; +} + +/*****************************************************************************/ +/** +* +* Set the Interframe Gap (IFG), which is the time the MAC delays between +* transmitting frames.  There are two parts required.  The total interframe gap +* is the total of the two parts.  The values provided for the Part1 and Part2 +* parameters are multiplied by 4 to obtain the bit-time interval. The first +* part should be the first 2/3 of the total interframe gap. The MAC will reset +* the interframe gap timer if carrier sense becomes true during the period +* defined by interframe gap Part1. Part1 may be shorter than 2/3 the total and +* can be as small as zero. The second part should be the last 1/3 of the total +* interframe gap, but can be as large as the total interframe gap. The MAC +* will not reset the interframe gap timer if carrier sense becomes true during +* the period defined by interframe gap Part2. +* +* The device must be stopped before setting the interframe gap. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param Part1 is the interframe gap part 1 (which will be multiplied by 4 to +*        get the bit-time interval). +* @param Part2 is the interframe gap part 2 (which will be multiplied by 4 to +*        get the bit-time interval). +* +* @return +* +* - XST_SUCCESS if the interframe gap was set successfully +* - XST_DEVICE_IS_STARTED if the device has not been stopped +* +* @note +* +* None. +* +******************************************************************************/ +XStatus +XEmac_SetInterframeGap(XEmac * InstancePtr, u8 Part1, u8 Part2) +{ +	u32 Ifg; + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(Part1 < XEM_MAX_IFG); +	XASSERT_NONVOID(Part2 < XEM_MAX_IFG); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* +	 * Be sure device has been stopped +	 */ +	if (InstancePtr->IsStarted == XCOMPONENT_IS_STARTED) { +		return XST_DEVICE_IS_STARTED; +	} + +	Ifg = Part1 << XEM_IFGP_PART1_SHIFT; +	Ifg |= (Part2 << XEM_IFGP_PART2_SHIFT); +	XIo_Out32(InstancePtr->BaseAddress + XEM_IFGP_OFFSET, Ifg); + +	return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Get the interframe gap, parts 1 and 2. See the description of interframe gap +* above in XEmac_SetInterframeGap(). +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param Part1Ptr is a pointer to an 8-bit buffer into which the interframe gap +*        part 1 value will be copied. +* @param Part2Ptr is a pointer to an 8-bit buffer into which the interframe gap +*        part 2 value will be copied. +* +* @return +* +* None. The values of the interframe gap parts are copied into the +* output parameters. +* +******************************************************************************/ +void +XEmac_GetInterframeGap(XEmac * InstancePtr, u8 * Part1Ptr, u8 * Part2Ptr) +{ +	u32 Ifg; + +	XASSERT_VOID(InstancePtr != NULL); +	XASSERT_VOID(Part1Ptr != NULL); +	XASSERT_VOID(Part2Ptr != NULL); +	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	Ifg = XIo_In32(InstancePtr->BaseAddress + XEM_IFGP_OFFSET); +	*Part1Ptr = (Ifg & XEM_IFGP_PART1_MASK) >> XEM_IFGP_PART1_SHIFT; +	*Part2Ptr = (Ifg & XEM_IFGP_PART2_MASK) >> XEM_IFGP_PART2_SHIFT; +} diff --git a/board/xilinx/xilinx_enet/xemac_polled.c b/board/xilinx/xilinx_enet/xemac_polled.c new file mode 100644 index 000000000..23768bca7 --- /dev/null +++ b/board/xilinx/xilinx_enet/xemac_polled.c @@ -0,0 +1,482 @@ +/****************************************************************************** +* +*     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. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xemac_polled.c +* +* Contains functions used when the driver is in polled mode. Use the +* XEmac_SetOptions() function to put the driver into polled mode. +* +* <pre> +* MODIFICATION HISTORY: +* +* Ver   Who  Date     Changes +* ----- ---- -------- ----------------------------------------------- +* 1.00a rpm  07/31/01 First release +* 1.00b rpm  02/20/02 Repartitioned files and functions +* 1.00c rpm  12/05/02 New version includes support for simple DMA +* </pre> +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xbasic_types.h" +#include "xemac_i.h" +#include "xio.h" +#include "xipif_v1_23_b.h"	/* Uses v1.23b of the IPIF */ + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* +* Send an Ethernet frame in polled mode.  The device/driver must be in polled +* mode before calling this function. The driver writes the frame directly to +* the MAC's packet FIFO, then enters a loop checking the device status for +* completion or error. Statistics are updated if an error occurs. The buffer +* to be sent must be word-aligned. +* +* It is assumed that the upper layer software supplies a correctly formatted +* Ethernet frame, including the destination and source addresses, the +* type/length field, and the data field.  It is also assumed that upper layer +* software does not append FCS at the end of the frame. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param BufPtr is a pointer to a word-aligned buffer containing the Ethernet +*        frame to be sent. +* @param ByteCount is the size of the Ethernet frame. +* +* @return +* +* - XST_SUCCESS if the frame was sent successfully +* - XST_DEVICE_IS_STOPPED if the device has not yet been started +* - XST_NOT_POLLED if the device is not in polled mode +* - XST_FIFO_NO_ROOM if there is no room in the EMAC's length FIFO for this frame +* - XST_FIFO_ERROR if the FIFO was overrun or underrun. This error is critical +*   and requires the caller to reset the device. +* - XST_EMAC_COLLISION if the send failed due to excess deferral or late +*   collision +* +* @note +* +* There is the possibility that this function will not return if the hardware +* is broken (i.e., it never sets the status bit indicating that transmission is +* done). If this is of concern to the user, the user should provide protection +* from this problem - perhaps by using a different timer thread to monitor the +* PollSend thread. On a 10Mbps MAC, it takes about 1.21 msecs to transmit a +* maximum size Ethernet frame (1518 bytes). On a 100Mbps MAC, it takes about +* 121 usecs to transmit a maximum size Ethernet frame. +* +* @internal +* +* The EMAC uses FIFOs behind its length and status registers. For this reason, +* it is important to keep the length, status, and data FIFOs in sync when +* reading or writing to them. +* +******************************************************************************/ +XStatus +XEmac_PollSend(XEmac * InstancePtr, u8 * BufPtr, u32 ByteCount) +{ +	u32 IntrStatus; +	u32 XmitStatus; +	XStatus Result; + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(BufPtr != NULL); +	XASSERT_NONVOID(ByteCount > XEM_HDR_SIZE);	/* send at least 1 byte */ +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* +	 * Be sure the device is configured for polled mode and it is started +	 */ +	if (!InstancePtr->IsPolled) { +		return XST_NOT_POLLED; +	} + +	if (InstancePtr->IsStarted != XCOMPONENT_IS_STARTED) { +		return XST_DEVICE_IS_STOPPED; +	} + +	/* +	 * Check for overruns and underruns for the transmit status and length +	 * FIFOs and make sure the send packet FIFO is not deadlocked. Any of these +	 * conditions is bad enough that we do not want to continue. The upper layer +	 * software should reset the device to resolve the error. +	 */ +	IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress); + +	/* +	 * Overrun errors +	 */ +	if (IntrStatus & (XEM_EIR_XMIT_SFIFO_OVER_MASK | +			  XEM_EIR_XMIT_LFIFO_OVER_MASK)) { +		InstancePtr->Stats.XmitOverrunErrors++; +		InstancePtr->Stats.FifoErrors++; +		return XST_FIFO_ERROR; +	} + +	/* +	 * Underrun errors +	 */ +	if (IntrStatus & (XEM_EIR_XMIT_SFIFO_UNDER_MASK | +			  XEM_EIR_XMIT_LFIFO_UNDER_MASK)) { +		InstancePtr->Stats.XmitUnderrunErrors++; +		InstancePtr->Stats.FifoErrors++; +		return XST_FIFO_ERROR; +	} + +	if (XPF_V100B_IS_DEADLOCKED(&InstancePtr->SendFifo)) { +		InstancePtr->Stats.FifoErrors++; +		return XST_FIFO_ERROR; +	} + +	/* +	 * Before writing to the data FIFO, make sure the length FIFO is not +	 * full.  The data FIFO might not be full yet even though the length FIFO +	 * is. This avoids an overrun condition on the length FIFO and keeps the +	 * FIFOs in sync. +	 */ +	if (IntrStatus & XEM_EIR_XMIT_LFIFO_FULL_MASK) { +		/* +		 * Clear the latched LFIFO_FULL bit so next time around the most +		 * current status is represented +		 */ +		XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress, +				      XEM_EIR_XMIT_LFIFO_FULL_MASK); +		return XST_FIFO_NO_ROOM; +	} + +	/* +	 * This is a non-blocking write. The packet FIFO returns an error if there +	 * is not enough room in the FIFO for this frame. +	 */ +	Result = +	    XPacketFifoV100b_Write(&InstancePtr->SendFifo, BufPtr, ByteCount); +	if (Result != XST_SUCCESS) { +		return Result; +	} + +	/* +	 * Loop on the MAC's status to wait for any pause to complete. +	 */ +	IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress); + +	while ((IntrStatus & XEM_EIR_XMIT_PAUSE_MASK) != 0) { +		IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress); +		/* +		   * Clear the pause status from the transmit status register +		 */ +		XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress, +				      IntrStatus & XEM_EIR_XMIT_PAUSE_MASK); +	} + +	/* +	 * Set the MAC's transmit packet length register to tell it to transmit +	 */ +	XIo_Out32(InstancePtr->BaseAddress + XEM_TPLR_OFFSET, ByteCount); + +	/* +	 * Loop on the MAC's status to wait for the transmit to complete. The +	 * transmit status is in the FIFO when the XMIT_DONE bit is set. +	 */ +	do { +		IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress); +	} +	while ((IntrStatus & XEM_EIR_XMIT_DONE_MASK) == 0); + +	XmitStatus = XIo_In32(InstancePtr->BaseAddress + XEM_TSR_OFFSET); + +	InstancePtr->Stats.XmitFrames++; +	InstancePtr->Stats.XmitBytes += ByteCount; + +	/* +	 * Check for various errors, bump statistics, and return an error status. +	 */ + +	/* +	 * Overrun errors +	 */ +	if (IntrStatus & (XEM_EIR_XMIT_SFIFO_OVER_MASK | +			  XEM_EIR_XMIT_LFIFO_OVER_MASK)) { +		InstancePtr->Stats.XmitOverrunErrors++; +		InstancePtr->Stats.FifoErrors++; +		return XST_FIFO_ERROR; +	} + +	/* +	 * Underrun errors +	 */ +	if (IntrStatus & (XEM_EIR_XMIT_SFIFO_UNDER_MASK | +			  XEM_EIR_XMIT_LFIFO_UNDER_MASK)) { +		InstancePtr->Stats.XmitUnderrunErrors++; +		InstancePtr->Stats.FifoErrors++; +		return XST_FIFO_ERROR; +	} + +	/* +	 * Clear the interrupt status register of transmit statuses +	 */ +	XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress, +			      IntrStatus & XEM_EIR_XMIT_ALL_MASK); + +	/* +	 * Collision errors are stored in the transmit status register +	 * instead of the interrupt status register +	 */ +	if (XmitStatus & XEM_TSR_EXCESS_DEFERRAL_MASK) { +		InstancePtr->Stats.XmitExcessDeferral++; +		return XST_EMAC_COLLISION_ERROR; +	} + +	if (XmitStatus & XEM_TSR_LATE_COLLISION_MASK) { +		InstancePtr->Stats.XmitLateCollisionErrors++; +		return XST_EMAC_COLLISION_ERROR; +	} + +	return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Receive an Ethernet frame in polled mode. The device/driver must be in polled +* mode before calling this function. The driver receives the frame directly +* from the MAC's packet FIFO. This is a non-blocking receive, in that if there +* is no frame ready to be received at the device, the function returns with an +* error. The MAC's error status is not checked, so statistics are not updated +* for polled receive. The buffer into which the frame will be received must be +* word-aligned. +* +* @param InstancePtr is a pointer to the XEmac instance to be worked on. +* @param BufPtr is a pointer to a word-aligned buffer into which the received +*        Ethernet frame will be copied. +* @param ByteCountPtr is both an input and an output parameter. It is a pointer +*        to a 32-bit word that contains the size of the buffer on entry into the +*        function and the size the received frame on return from the function. +* +* @return +* +* - XST_SUCCESS if the frame was sent successfully +* - XST_DEVICE_IS_STOPPED if the device has not yet been started +* - XST_NOT_POLLED if the device is not in polled mode +* - XST_NO_DATA if there is no frame to be received from the FIFO +* - XST_BUFFER_TOO_SMALL if the buffer to receive the frame is too small for +*   the frame waiting in the FIFO. +* +* @note +* +* Input buffer must be big enough to hold the largest Ethernet frame. Buffer +* must also be 32-bit aligned. +* +* @internal +* +* The EMAC uses FIFOs behind its length and status registers. For this reason, +* it is important to keep the length, status, and data FIFOs in sync when +* reading or writing to them. +* +******************************************************************************/ +XStatus +XEmac_PollRecv(XEmac * InstancePtr, u8 * BufPtr, u32 * ByteCountPtr) +{ +	XStatus Result; +	u32 PktLength; +	u32 IntrStatus; + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(BufPtr != NULL); +	XASSERT_NONVOID(ByteCountPtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* +	 * Be sure the device is configured for polled mode and it is started +	 */ +	if (!InstancePtr->IsPolled) { +		return XST_NOT_POLLED; +	} + +	if (InstancePtr->IsStarted != XCOMPONENT_IS_STARTED) { +		return XST_DEVICE_IS_STOPPED; +	} + +	/* +	 * Make sure the buffer is big enough to hold the maximum frame size. +	 * We need to do this because as soon as we read the MAC's packet length +	 * register, which is actually a FIFO, we remove that length from the +	 * FIFO.  We do not want to read the length FIFO without also reading the +	 * data FIFO since this would get the FIFOs out of sync.  So we have to +	 * make this restriction. +	 */ +	if (*ByteCountPtr < XEM_MAX_FRAME_SIZE) { +		return XST_BUFFER_TOO_SMALL; +	} + +	/* +	 * First check for packet FIFO deadlock and return an error if it has +	 * occurred. A reset by the caller is necessary to correct this problem. +	 */ +	if (XPF_V100B_IS_DEADLOCKED(&InstancePtr->RecvFifo)) { +		InstancePtr->Stats.FifoErrors++; +		return XST_FIFO_ERROR; +	} + +	/* +	 * Get the interrupt status to know what happened (whether an error occurred +	 * and/or whether frames have been received successfully). When clearing the +	 * intr status register, clear only statuses that pertain to receive. +	 */ +	IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress); +	XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress, +			      IntrStatus & XEM_EIR_RECV_ALL_MASK); + +	/* +	 * Check receive errors and bump statistics so the caller will have a clue +	 * as to why data may not have been received. We continue on if an error +	 * occurred since there still may be frames that were received successfully. +	 */ +	if (IntrStatus & (XEM_EIR_RECV_LFIFO_OVER_MASK | +			  XEM_EIR_RECV_DFIFO_OVER_MASK)) { +		InstancePtr->Stats.RecvOverrunErrors++; +		InstancePtr->Stats.FifoErrors++; +	} + +	if (IntrStatus & XEM_EIR_RECV_LFIFO_UNDER_MASK) { +		InstancePtr->Stats.RecvUnderrunErrors++; +		InstancePtr->Stats.FifoErrors++; +	} + +	/* +	 * General receive errors +	 */ +	if (IntrStatus & XEM_EIR_RECV_ERROR_MASK) { +		if (IntrStatus & XEM_EIR_RECV_MISSED_FRAME_MASK) { +			InstancePtr->Stats.RecvMissedFrameErrors = +			    XIo_In32(InstancePtr->BaseAddress + +				     XEM_RMFC_OFFSET); +		} + +		if (IntrStatus & XEM_EIR_RECV_COLLISION_MASK) { +			InstancePtr->Stats.RecvCollisionErrors = +			    XIo_In32(InstancePtr->BaseAddress + XEM_RCC_OFFSET); +		} + +		if (IntrStatus & XEM_EIR_RECV_FCS_ERROR_MASK) { +			InstancePtr->Stats.RecvFcsErrors = +			    XIo_In32(InstancePtr->BaseAddress + +				     XEM_RFCSEC_OFFSET); +		} + +		if (IntrStatus & XEM_EIR_RECV_LEN_ERROR_MASK) { +			InstancePtr->Stats.RecvLengthFieldErrors++; +		} + +		if (IntrStatus & XEM_EIR_RECV_SHORT_ERROR_MASK) { +			InstancePtr->Stats.RecvShortErrors++; +		} + +		if (IntrStatus & XEM_EIR_RECV_LONG_ERROR_MASK) { +			InstancePtr->Stats.RecvLongErrors++; +		} + +		if (IntrStatus & XEM_EIR_RECV_ALIGN_ERROR_MASK) { +			InstancePtr->Stats.RecvAlignmentErrors = +			    XIo_In32(InstancePtr->BaseAddress + +				     XEM_RAEC_OFFSET); +		} +	} + +	/* +	 * Before reading from the length FIFO, make sure the length FIFO is not +	 * empty. We could cause an underrun error if we try to read from an +	 * empty FIFO. +	 */ +	if ((IntrStatus & XEM_EIR_RECV_DONE_MASK) == 0) { +		return XST_NO_DATA; +	} + +	/* +	 * Determine, from the MAC, the length of the next packet available +	 * in the data FIFO (there should be a non-zero length here) +	 */ +	PktLength = XIo_In32(InstancePtr->BaseAddress + XEM_RPLR_OFFSET); +	if (PktLength == 0) { +		return XST_NO_DATA; +	} + +	/* +	 * Write the RECV_DONE bit in the status register to clear it. This bit +	 * indicates the RPLR is non-empty, and we know it's set at this point. +	 * We clear it so that subsequent entry into this routine will reflect the +	 * current status. This is done because the non-empty bit is latched in the +	 * IPIF, which means it may indicate a non-empty condition even though +	 * there is something in the FIFO. +	 */ +	XIIF_V123B_WRITE_IISR(InstancePtr->BaseAddress, XEM_EIR_RECV_DONE_MASK); + +	/* +	 * We assume that the MAC never has a length bigger than the largest +	 * Ethernet frame, so no need to make another check here. +	 */ + +	/* +	 * This is a non-blocking read. The FIFO returns an error if there is +	 * not at least the requested amount of data in the FIFO. +	 */ +	Result = +	    XPacketFifoV100b_Read(&InstancePtr->RecvFifo, BufPtr, PktLength); +	if (Result != XST_SUCCESS) { +		return Result; +	} + +	InstancePtr->Stats.RecvFrames++; +	InstancePtr->Stats.RecvBytes += PktLength; + +	*ByteCountPtr = PktLength; + +	return XST_SUCCESS; +} diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c index 6549be61f..cd192b05b 100644 --- a/common/cmd_bdinfo.c +++ b/common/cmd_bdinfo.c @@ -59,13 +59,13 @@ int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	print_num ("immr_base",	    bd->bi_immr_base	);  #endif  	print_num ("bootflags",	    bd->bi_bootflags	); -#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_405EP) +#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_405EP) || defined(CONFIG_XILINX_ML300)  	print_str ("procfreq",	    strmhz(buf, bd->bi_procfreq));  	print_str ("plb_busfreq",	    strmhz(buf, bd->bi_plb_busfreq)); -#if defined(CONFIG_405GP) || defined(CONFIG_405EP) +#if defined(CONFIG_405GP) || defined(CONFIG_405EP) || defined(CONFIG_XILINX_ML300)  	print_str ("pci_busfreq",	    strmhz(buf, bd->bi_pci_busfreq));  #endif -#else	/* ! CONFIG_405GP, CONFIG_405CR, CONFIG_405EP */ +#else	/* ! CONFIG_405GP, CONFIG_405CR, CONFIG_405EP, CONFIG_XILINX_ML300 */  #if defined(CONFIG_8260) || defined(CONFIG_MPC8560)  	print_str ("vco",	    strmhz(buf, bd->bi_vco));  	print_str ("sccfreq",	    strmhz(buf, bd->bi_sccfreq)); @@ -76,7 +76,7 @@ int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	print_str ("cpmfreq",	    strmhz(buf, bd->bi_cpmfreq));  #endif  	print_str ("busfreq",	    strmhz(buf, bd->bi_busfreq)); -#endif /* CONFIG_405GP, CONFIG_405CR, CONFIG_405EP */ +#endif /* CONFIG_405GP, CONFIG_405CR, CONFIG_405EP, CONFIG_XILINX_ML300 */  	printf ("ethaddr     =");  	for (i=0; i<6; ++i) {  		printf ("%c%02X", i ? ':' : ' ', bd->bi_enetaddr[i]); diff --git a/cpu/arm925t/interrupts.c b/cpu/arm925t/interrupts.c index 7897184fc..00e8c18e1 100644 --- a/cpu/arm925t/interrupts.c +++ b/cpu/arm925t/interrupts.c @@ -237,7 +237,7 @@ void udelay (unsigned long usec)  	}  	tmp = get_timer (0);		/* get current timestamp */ -	if( (tmo + tmp) < tmp ) 	/* if setting this fordward will roll time stamp */ +	if( (tmo + tmp + 1) < tmp ) 	/* if setting this fordward will roll time stamp */  		reset_timer_masked ();	/* reset "advancing" timestamp to 0, set lastdec value */  	else  		tmo += tmp;		/* else, set advancing stamp wake up time */ diff --git a/cpu/arm926ejs/interrupts.c b/cpu/arm926ejs/interrupts.c index 4d6efebeb..616793380 100644 --- a/cpu/arm926ejs/interrupts.c +++ b/cpu/arm926ejs/interrupts.c @@ -229,7 +229,7 @@ void udelay (unsigned long usec)  	}  	tmp = get_timer (0);		/* get current timestamp */ -	if( (tmo + tmp) < tmp ) 	/* if setting this fordward will roll time stamp */ +	if( (tmo + tmp + 1) < tmp ) 	/* if setting this fordward will roll time stamp */  		reset_timer_masked ();	/* reset "advancing" timestamp to 0, set lastdec value */  	else  		tmo += tmp;		/* else, set advancing stamp wake up time */ diff --git a/cpu/nios/interrupts.c b/cpu/nios/interrupts.c index 450946bbc..443680582 100644 --- a/cpu/nios/interrupts.c +++ b/cpu/nios/interrupts.c @@ -30,6 +30,7 @@  #include <asm/ptrace.h>  #include <common.h>  #include <command.h> +#include <watchdog.h>  #ifdef CONFIG_STATUS_LED  #include <status_led.h>  #endif @@ -54,6 +55,7 @@ void reset_timer (void)  ulong get_timer (ulong base)  { +	WATCHDOG_RESET ();  	return (timestamp - base);  } diff --git a/cpu/nios/serial.c b/cpu/nios/serial.c index 61b26ab14..34257a2fe 100644 --- a/cpu/nios/serial.c +++ b/cpu/nios/serial.c @@ -23,6 +23,7 @@  #include <common.h> +#include <watchdog.h>  #include <nios-io.h> @@ -62,7 +63,7 @@ void serial_putc( char c )  	if (c == '\n')  		serial_putc('\r');  	while( (uart->status & NIOS_UART_TRDY) == 0 ) -		; +		WATCHDOG_RESET ();  	uart->txdata = (unsigned char)c;  } @@ -81,6 +82,6 @@ int serial_tstc( void )  int serial_getc( void )  {  	while( serial_tstc() == 0 ) -		; +		WATCHDOG_RESET ();  	return( uart->rxdata & 0x00ff );  } diff --git a/cpu/ppc4xx/speed.c b/cpu/ppc4xx/speed.c index dfd2a04d5..e776050bc 100644 --- a/cpu/ppc4xx/speed.c +++ b/cpu/ppc4xx/speed.c @@ -299,6 +299,10 @@ ulong get_OPB_freq (void)  	return sys_info.freqOPB;  } +#elif defined(CONFIG_XILINX_ML300) +extern void get_sys_info (sys_info_t * sysInfo); +extern ulong get_PCI_freq (void); +  #elif defined(CONFIG_405)  void get_sys_info (sys_info_t * sysInfo) { diff --git a/doc/README.ml300 b/doc/README.ml300 new file mode 100644 index 000000000..c9ef6e6c8 --- /dev/null +++ b/doc/README.ml300 @@ -0,0 +1,128 @@ +Xilinx ML300 platform +===================== + +0. Introduction +--------------- + +The Xilinx ML300 board is based on the Virtex-II Pro FPGA with +integrated IBM PowerPC 405 core. The board is normally booted from +System ACE CF. U-Boot is then run out of main memory. + +An FPGA is a configurable and thus very flexible device. To +accommodate for this flexibility this port of U-Boot includes the +required means to regenerate the drivers and configuration files if +you decide to change the hardware design. The required steps are +described below. + + +1. Requirements +--------------- + +To compile and run U-Boot on the Xilinx ML300 platform you need the +following items. + +- A Xilinx ML300 platform (see http://www.xilinx.com/ml300) +- EDK and ISE development tools (shipping with ML300) +- Parallel4 cable (shipping with ML300) +- The EDK reference design for ML300. You can get this as design #6 from +  http://www.xilinx.com/ise/embedded/edk_examples.htm +- A BOOTP/TFTP server + + +2. Quick Start +-------------- + +To compile and run U-Boot on ML300 follow the steps below. Make sure +to consult the documentation for U-Boot, EDK, and the EDK reference +design for ML300 if you have any questions. + +1. Implement the EDK reference design for ML300. You can use any of +   the project files, for example from a xygwin shell: +   $ xps -nw system_linux.xmp +   XPS% run init_bram +2. Configure and compile U-Boot. Change into the root directory of +   U-Boot and run: +   $ export CROSS_COMPILE=powerpc-eabi- +   $ make ml300_config +   $ make +3. Set up the ML300, connect the Parallel4 and the serial cable. Start +   a terminal on your host computer and set the communication +   parameters to 9600,8N1,no handshake. +4. Set up the BOOTP/TFTP server on your host machine. U-Boot is +   preconfigured to use a fixed HW MAC address of 00:0A:35:00:22:01. +5. Download the bitstream to the ML300. +6. Use XMD to download and run U-Boot on the ML300: +   $ xmd +   XMD% ppcconnect +   XMD% dow u-boot +   XMD% run + +You can now make an ACE file out of bitstream and U-Boot: +   $ xmd genace.tcl -jprog -board ml300 -hw  \ +     implementation/download.bit -elf u-boot -ace top.ace + +Put the ACE file onto the MicroDrive, for example into xilinx/myace, +and reboot ML300. + + +3. Generating a Custom BSP for U-Boot +------------------------------------- + +If you decide to change the EDK reference design for ML300 or if you +build a new design from scratch either with the Base System Builder in +XPS or all by hand you most likely will change the base addresses for +the Uart and the Ethernet peripheral. If you do so you will have two +options: + +1. Edit boards/xilinx/ml300/xparameters.h to reflect the changes you +   made to your hardware. +2. Use the MLD technology provided by Xilinx Platform Studio to make +   the changes automatically. To do so go to the root directory of the +   EDK reference design for ML300. Copy the Linux project file and the +   Linux software configuration file: +   $ cp system_linux.xmp system_uboot.xmp +   $ cp system_linux.mss system_uboot.mss + +   Edit system_uboot.xmp and and have it point to system_uboot.mss for +   the software configuration. + +   Then, copy the sw_services directory in +   boards/xilinx/ml300/sw_services to the root directory of the EDK +   reference design for ML300. +   $ cp -R <uboot dir>/boards/xilinx/ml300/sw_services <edk dir> + +   Modify system_uboot.mss. Look for the Linux library definition +   and change it to generate a BSP for U-Boot. An example, might look +   like this: + +   BEGIN LIBRARY +    PARAMETER LIBRARY_NAME = uboot +    PARAMETER LIBRARY_VER = 1.00.a +    PARAMETER CONNECTED_PERIPHS = (opb_uart16550_0,opb_ethernet_0) +    PARAMETER TARGET_DIR = <uboot dir> +   END + +   Now, you are ready to generate the Xilinx ML300 BSP for U-Boot: +   $ xps -nw system_uboot.xmp +   XPS% run libs + +   If all goes well the new configuration has been copied into the +   right places within the U-Boot source tree. Recompile U-Boot and +   run it on the ML300. + + +4. ToDo +------- + +- Add support for all other peripherals on ML300. +- Read the MAC address out of the IIC EEPROM. +- Store the bootargs in the IIC EEPROM. + + +5. References +------------- + +ML300:			http://www.xilinx.com/ml300 +EDK:			http://www.xilinx.com/edk +ISE:			http://www.xilinx.com/ise +Reference Design:	http://www.xilinx.com/ise/embedded/edk_examples.htm diff --git a/drivers/cfi_flash.c b/drivers/cfi_flash.c index 95179aeb6..d31b38f1b 100644 --- a/drivers/cfi_flash.c +++ b/drivers/cfi_flash.c @@ -46,7 +46,9 @@  #include <common.h>  #include <asm/processor.h> +#include <linux/byteorder/swab.h>  #ifdef	CFG_FLASH_CFI_DRIVER +  /*   * This file implements a Common Flash Interface (CFI) driver for U-Boot.   * The width of the port and the width of the chips are determined at initialization. @@ -164,31 +166,24 @@ typedef unsigned long flash_sect_t;  static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c);  static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf); -static void flash_write_cmd (flash_info_t * info, flash_sect_t sect, -			     uint offset, uchar cmd); +static void flash_write_cmd (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);  static void flash_unlock_seq (flash_info_t * info, flash_sect_t sect); -static int flash_isequal (flash_info_t * info, flash_sect_t sect, uint offset, -			  uchar cmd); -static int flash_isset (flash_info_t * info, flash_sect_t sect, uint offset, -			uchar cmd); -static int flash_toggle (flash_info_t * info, flash_sect_t sect, uint offset, -			 uchar cmd); +static int flash_isequal (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd); +static int flash_isset (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd); +static int flash_toggle (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);  static int flash_detect_cfi (flash_info_t * info);  static ulong flash_get_size (ulong base, int banknum); -static int flash_write_cfiword (flash_info_t * info, ulong dest, -				cfiword_t cword); +static int flash_write_cfiword (flash_info_t * info, ulong dest, cfiword_t cword);  static int flash_full_status_check (flash_info_t * info, flash_sect_t sector,  				    ulong tout, char *prompt);  #ifdef CFG_FLASH_USE_BUFFER_WRITE -static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp, -				  int len); +static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp, int len);  #endif  /*-----------------------------------------------------------------------   * create an address based on the offset and the port width   */ -inline uchar *flash_make_addr (flash_info_t * info, flash_sect_t sect, -			       uint offset) +inline uchar *flash_make_addr (flash_info_t * info, flash_sect_t sect, uint offset)  {  	return ((uchar *) (info->start[sect] + (offset * info->portwidth)));  } @@ -230,7 +225,6 @@ static void flash_printqry (flash_info_t * info, flash_sect_t sect)  		debug ("\n");  	}  } -  #endif @@ -286,7 +280,6 @@ ushort flash_read_ushort (flash_info_t * info, flash_sect_t sect, uint offset)   */  ulong flash_read_long (flash_info_t * info, flash_sect_t sect, uint offset)  { -  	uchar *addr;  	ulong retval; @@ -304,8 +297,7 @@ ulong flash_read_long (flash_info_t * info, flash_sect_t sect, uint offset)  #endif  #if defined(__LITTLE_ENDIAN)  	retval = (addr[0] << 16) | (addr[(info->portwidth)] << 24) | -		(addr[(2 * info->portwidth)]) | (addr[(3 * info->portwidth)] -						 << 8); +		(addr[(2 * info->portwidth)]) | (addr[(3 * info->portwidth)] << 8);  #else  	retval = (addr[(2 * info->portwidth) - 1] << 24) |  		(addr[(info->portwidth) - 1] << 16) | @@ -327,7 +319,8 @@ unsigned long flash_init (void)  		flash_info[i].flash_id = FLASH_UNKNOWN;  		size += flash_info[i].size = flash_get_size (bank_base[i], i);  		if (flash_info[i].flash_id == FLASH_UNKNOWN) { -			printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n", i, flash_info[i].size, flash_info[i].size << 20); +			printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n", +				i, flash_info[i].size, flash_info[i].size << 20);  		}  	} @@ -377,21 +370,16 @@ int flash_erase (flash_info_t * info, int s_first, int s_last)  			switch (info->vendor) {  			case CFI_CMDSET_INTEL_STANDARD:  			case CFI_CMDSET_INTEL_EXTENDED: -				flash_write_cmd (info, sect, 0, -						 FLASH_CMD_CLEAR_STATUS); -				flash_write_cmd (info, sect, 0, -						 FLASH_CMD_BLOCK_ERASE); -				flash_write_cmd (info, sect, 0, -						 FLASH_CMD_ERASE_CONFIRM); +				flash_write_cmd (info, sect, 0, FLASH_CMD_CLEAR_STATUS); +				flash_write_cmd (info, sect, 0, FLASH_CMD_BLOCK_ERASE); +				flash_write_cmd (info, sect, 0, FLASH_CMD_ERASE_CONFIRM);  				break;  			case CFI_CMDSET_AMD_STANDARD:  			case CFI_CMDSET_AMD_EXTENDED:  				flash_unlock_seq (info, sect); -				flash_write_cmd (info, sect, 0x555, -						 AMD_CMD_ERASE_START); +				flash_write_cmd (info, sect, 0x555, AMD_CMD_ERASE_START);  				flash_unlock_seq (info, sect); -				flash_write_cmd (info, sect, 0, -						 AMD_CMD_ERASE_SECTOR); +				flash_write_cmd (info, sect, 0, AMD_CMD_ERASE_SECTOR);  				break;  			default:  				debug ("Unkown flash vendor %d\n", @@ -425,7 +413,11 @@ void flash_print_info (flash_info_t * info)  		(info->portwidth << 3), (info->chipwidth << 3));  	printf ("  Size: %ld MB in %d Sectors\n",  		info->size >> 20, info->sector_count); -	printf (" Erase timeout %ld ms, write timeout %ld ms, buffer write timeout %ld ms, buffer size %d\n", info->erase_blk_tout, info->write_tout, info->buffer_write_tout, info->buffer_size); +	printf (" Erase timeout %ld ms, write timeout %ld ms, buffer write timeout %ld ms, buffer size %d\n", +		info->erase_blk_tout, +		info->write_tout, +		info->buffer_write_tout, +		info->buffer_size);  	printf ("  Sector Start Addresses:");  	for (i = 0; i < info->sector_count; ++i) { @@ -605,7 +597,6 @@ int flash_real_protect (flash_info_t * info, long sector, int prot)  			}  		}  	} -  	return retcode;  } @@ -706,16 +697,12 @@ static int flash_full_status_check (flash_info_t * info, flash_sect_t sector,  			retcode = ERR_INVAL;  			printf ("Flash %s error at address %lx\n", prompt,  				info->start[sector]); -			if (flash_isset -			    (info, sector, 0, -			     FLASH_STATUS_ECLBS | FLASH_STATUS_PSLBS)) { +			if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS | FLASH_STATUS_PSLBS)) {  				printf ("Command Sequence Error.\n"); -			} else if (flash_isset -				   (info, sector, 0, FLASH_STATUS_ECLBS)) { +			} else if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS)) {  				printf ("Block Erase Error.\n");  				retcode = ERR_NOT_ERASED; -			} else if (flash_isset -				   (info, sector, 0, FLASH_STATUS_PSLBS)) { +			} else if (flash_isset (info, sector, 0, FLASH_STATUS_PSLBS)) {  				printf ("Locking Error\n");  			}  			if (flash_isset (info, sector, 0, FLASH_STATUS_DPS)) { @@ -762,16 +749,28 @@ static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf)  	int i;  #if defined(__LITTLE_ENDIAN) -	ushort stmp; +	ushort stmpw; +	uint   stmpi;  #endif  	uchar *cp = (uchar *) cmdbuf;  	for (i = 0; i < info->portwidth; i++)  		*cp++ = ((i + 1) % info->chipwidth) ? '\0' : cmd;  #if defined(__LITTLE_ENDIAN) -	if (info->portwidth == 2) { -		stmp = *(ushort *) cmdbuf; -		*(ushort *) cmdbuf = swab16 (stmp); +	switch (info->portwidth) { +	case FLASH_CFI_8BIT: +		break; +	case FLASH_CFI_16BIT: +		stmpw = *(ushort *) cmdbuf; +		*(ushort *) cmdbuf = __swab16 (stmpw); +		break; +	case FLASH_CFI_32BIT: +		stmpi = *(uint *) cmdbuf; +		*(uint *) cmdbuf = __swab32 (stmpi); +		break; +	default: +		printf("WARNING: flash_make_cmd: unsuppported LittleEndian mode\n"); +		break;  	}  #endif  } @@ -779,8 +778,7 @@ static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf)  /*   * Write a proper sized command to the correct address   */ -static void flash_write_cmd (flash_info_t * info, flash_sect_t sect, -			     uint offset, uchar cmd) +static void flash_write_cmd (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd)  {  	volatile cfiptr_t addr; @@ -831,8 +829,7 @@ static void flash_unlock_seq (flash_info_t * info, flash_sect_t sect)  /*-----------------------------------------------------------------------   */ -static int flash_isequal (flash_info_t * info, flash_sect_t sect, uint offset, -			  uchar cmd) +static int flash_isequal (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd)  {  	cfiptr_t cptr;  	cfiword_t cword; @@ -877,8 +874,7 @@ static int flash_isequal (flash_info_t * info, flash_sect_t sect, uint offset,  /*-----------------------------------------------------------------------   */ -static int flash_isset (flash_info_t * info, flash_sect_t sect, uint offset, -			uchar cmd) +static int flash_isset (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd)  {  	cfiptr_t cptr;  	cfiword_t cword; @@ -908,8 +904,7 @@ static int flash_isset (flash_info_t * info, flash_sect_t sect, uint offset,  /*-----------------------------------------------------------------------   */ -static int flash_toggle (flash_info_t * info, flash_sect_t sect, uint offset, -			 uchar cmd) +static int flash_toggle (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd)  {  	cfiptr_t cptr;  	cfiword_t cword; @@ -953,27 +948,18 @@ static int flash_detect_cfi (flash_info_t * info)  		     info->chipwidth <= info->portwidth;  		     info->chipwidth <<= 1) {  			flash_write_cmd (info, 0, 0, FLASH_CMD_RESET); -			flash_write_cmd (info, 0, FLASH_OFFSET_CFI, -					 FLASH_CMD_CFI); -			if (flash_isequal -			    (info, 0, FLASH_OFFSET_CFI_RESP, 'Q') -			    && flash_isequal (info, 0, -					      FLASH_OFFSET_CFI_RESP + 1, 'R') -			    && flash_isequal (info, 0, -					      FLASH_OFFSET_CFI_RESP + 2, -					      'Y')) { -				info->interface = -					flash_read_ushort (info, 0, -							   FLASH_OFFSET_INTERFACE); +			flash_write_cmd (info, 0, FLASH_OFFSET_CFI, FLASH_CMD_CFI); +			if (flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP, 'Q') +			    && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R') +			    && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y')) { +				info->interface = flash_read_ushort (info, 0, FLASH_OFFSET_INTERFACE);  				debug ("device interface is %d\n",  				       info->interface);  				debug ("found port %d chip %d ",  				       info->portwidth, info->chipwidth);  				debug ("port %d bits chip %d bits\n", -				       info-> -				       portwidth << CFI_FLASH_SHIFT_WIDTH, -				       info-> -				       chipwidth << CFI_FLASH_SHIFT_WIDTH); +				       info->portwidth << CFI_FLASH_SHIFT_WIDTH, +				       info->chipwidth << CFI_FLASH_SHIFT_WIDTH);  				return 1;  			}  		} @@ -1001,9 +987,7 @@ static ulong flash_get_size (ulong base, int banknum)  	info->start[0] = base;  	if (flash_detect_cfi (info)) { -		info->vendor = -			flash_read_ushort (info, 0, -					   FLASH_OFFSET_PRIMARY_VENDOR); +		info->vendor = flash_read_ushort (info, 0, FLASH_OFFSET_PRIMARY_VENDOR);  #ifdef DEBUG  		flash_printqry (info, 0);  #endif @@ -1026,9 +1010,7 @@ static ulong flash_get_size (ulong base, int banknum)  		    && (info->chipwidth == FLASH_CFI_BY8)) {  			size_ratio >>= 1;  		} -		num_erase_regions = -			flash_read_uchar (info, -					  FLASH_OFFSET_NUM_ERASE_REGIONS); +		num_erase_regions = flash_read_uchar (info, FLASH_OFFSET_NUM_ERASE_REGIONS);  		debug ("size_ratio %d port %d bits chip %d bits\n",  		       size_ratio, info->portwidth << CFI_FLASH_SHIFT_WIDTH,  		       info->chipwidth << CFI_FLASH_SHIFT_WIDTH); @@ -1037,7 +1019,8 @@ static ulong flash_get_size (ulong base, int banknum)  		sector = base;  		for (i = 0; i < num_erase_regions; i++) {  			if (i > NUM_ERASE_REGIONS) { -				printf ("%d erase regions found, only %d used\n", num_erase_regions, NUM_ERASE_REGIONS); +				printf ("%d erase regions found, only %d used\n", +					num_erase_regions, NUM_ERASE_REGIONS);  				break;  			}  			tmp = flash_read_long (info, 0, @@ -1047,7 +1030,8 @@ static ulong flash_get_size (ulong base, int banknum)  				(tmp & 0xffff) ? ((tmp & 0xffff) * 256) : 128;  			tmp >>= 16;  			erase_region_count = (tmp & 0xffff) + 1; -			printf ("erase_region_count = %d erase_region_size = %d\n", erase_region_count, erase_region_size); +			printf ("erase_region_count = %d erase_region_size = %d\n", +				erase_region_count, erase_region_size);  			for (j = 0; j < erase_region_count; j++) {  				info->start[sect_cnt] = sector;  				sector += (erase_region_size * size_ratio); @@ -1061,29 +1045,14 @@ static ulong flash_get_size (ulong base, int banknum)  		info->sector_count = sect_cnt;  		/* multiply the size by the number of chips */ -		info->size = -			(1 << flash_read_uchar (info, FLASH_OFFSET_SIZE)) * -			size_ratio; -		info->buffer_size = -			(1 << -			 flash_read_ushort (info, 0, -					    FLASH_OFFSET_BUFFER_SIZE)); +		info->size = (1 << flash_read_uchar (info, FLASH_OFFSET_SIZE)) * size_ratio; +		info->buffer_size = (1 << flash_read_ushort (info, 0, FLASH_OFFSET_BUFFER_SIZE));  		tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_ETOUT); -		info->erase_blk_tout = -			(tmp * -			 (1 << -			  flash_read_uchar (info, FLASH_OFFSET_EMAX_TOUT))); +		info->erase_blk_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_EMAX_TOUT)));  		tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_WBTOUT); -		info->buffer_write_tout = -			(tmp * -			 (1 << -			  flash_read_uchar (info, FLASH_OFFSET_WBMAX_TOUT))); +		info->buffer_write_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_WBMAX_TOUT)));  		tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_WTOUT); -		info->write_tout = -			(tmp * -			 (1 << -			  flash_read_uchar (info, -					    FLASH_OFFSET_WMAX_TOUT))) / 1000; +		info->write_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_WMAX_TOUT))) / 1000;  		info->flash_id = FLASH_MAN_CFI;  	} diff --git a/include/configs/ml300.h b/include/configs/ml300.h new file mode 100644 index 000000000..d93925ee6 --- /dev/null +++ b/include/configs/ml300.h @@ -0,0 +1,154 @@ +/* + * ML300.h: ML300 specific config options + * + * http://www.xilinx.com/ml300 + * + * Derived from : ML2.h + * + *     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 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 products are not intended for use in life support appliances, + *     devices, or systems. Use in such applications is expressly prohibited. + * + * + *     (c) Copyright 2002 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. +  * + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* #define DEBUG */ +/* #define ET_DEBUG 1 */ + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_405		1	/* This is a PPC405 CPU		*/ +#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_NO_FLASH		1	/* no flash */ +#define CFG_ENV_SIZE		0x2000 +#define CONFIG_BAUDRATE		9600 +#define CONFIG_BOOTDELAY	3	/* autoboot after 3 seconds	*/ + +#define CONFIG_BOOTCOMMAND	"bootp" /* autoboot command	*/ + +#define CONFIG_BOOTARGS		"console=ttyS0,9600 ip=off " \ +				"root=/dev/xsysace/disc0/part3 rw" + +#define CONFIG_LOADS_ECHO	1	/* echo on for serial download	*/ +#define CFG_LOADS_BAUD_CHANGE	1	/* allow baudrate change	*/ + +#define REMOVE_COMMANDS	       (CFG_CMD_FLASH | CFG_CMD_LOADS | CFG_CMD_FAT | \ +				CFG_CMD_IMLS ) +#define CONFIG_COMMANDS	       ((CONFIG_CMD_DFL | CFG_CMD_NET) \ +				& ~REMOVE_COMMANDS) + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +/* #define CONFIG_SYS_CLK_FREQ XPAR_CORE_CLOCK_FREQ_HZ */ +/* 300000000 */ + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP		/* undef to save memory		*/ +#define CFG_PROMPT	"=> "	/* Monitor Command Prompt	*/ + +#define CFG_CBSIZE	256	/* Console I/O Buffer Size	*/ + +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16)	/* Print Buffer Size */ +#define CFG_MAXARGS	16	/* max number of command args	*/ +#define CFG_BARGSIZE	CFG_CBSIZE	/* Boot Argument Buffer Size	*/ + +#define CFG_MEMTEST_START	0x0400000	/* memtest works on	*/ +#define CFG_MEMTEST_END		0x0C00000	/* 4 ... 12 MB in DRAM	*/ + +#define CFG_DUART_CHAN		0 +#define CFG_NS16550_REG_SIZE -4 +#define CFG_NS16550 1 +#define CFG_INIT_CHAN1	 1 + +/* The following table includes the supported baudrates */ +#define CFG_BAUDRATE_TABLE  \ +    {300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400} + +#define CFG_LOAD_ADDR		0x400000	/* default load address */ +#define CFG_EXTBDINFO		1	/* To use extended board_into (bd_t) */ + +#define CFG_HZ		1000	/* decrementer freq: 1 ms ticks */ + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE		0x00000000 +#define CFG_MONITOR_BASE	0x04000000 +#define CFG_MONITOR_LEN		(192 * 1024)	/* Reserve 196 kB for Monitor	*/ +#define CFG_MALLOC_LEN		(128 * 1024)	/* Reserve 128 kB for malloc()	*/ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ		(8 << 20)	/* Initial Memory map for Linux */ + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_DCACHE_SIZE		16384	/* For IBM 405 CPUs	*/ +#define CFG_CACHELINE_SIZE	32	/* ...			*/ + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area (in DPRAM) + */ + +#define CFG_INIT_RAM_ADDR	0x800000  /* inside of SDRAM */ +#define CFG_INIT_RAM_END	0x2000	  /* End of used area in RAM */ +#define CFG_GBL_DATA_SIZE	128	  /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET    (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_SP_OFFSET	CFG_GBL_DATA_OFFSET + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD	0x01	/* Normal Power-On: Boot from FLASH	*/ +#define BOOTFLAG_WARM	0x02	/* Software reboot			*/ + +#endif				/* __CONFIG_H */ diff --git a/include/configs/omap1610h2.h b/include/configs/omap1610h2.h index 2eb65e208..7d232ca3c 100644 --- a/include/configs/omap1610h2.h +++ b/include/configs/omap1610h2.h @@ -73,7 +73,7 @@  #define CFG_NS16550_REG_SIZE	(-4)  #define CFG_NS16550_CLK	(48000000)		/* can be 12M/32Khz or 48Mhz */  #define CFG_NS16550_COM1	0xfffb0000	/* uart1, bluetooth uart */ -						 +  /*   * select serial console configuration   */ diff --git a/include/watchdog.h b/include/watchdog.h index 7180259d0..ac6ba8c09 100644 --- a/include/watchdog.h +++ b/include/watchdog.h @@ -31,6 +31,10 @@  #  error "Configuration error: CONFIG_HW_WATCHDOG and CONFIG_WATCHDOG can't be used together."  #endif +#if defined(__ASSEMBLY__) && defined(__NIOS__) +#  error "Configuration error: WATCHDOG_RESET inside assembler not supported for Nios platforms." +#endif +  /*   * Hardware watchdog   */ diff --git a/lib_nios/board.c b/lib_nios/board.c index fb477e94e..d6c02d8a4 100644 --- a/lib_nios/board.c +++ b/lib_nios/board.c @@ -139,13 +139,16 @@ void board_init (void)  	bd->bi_baudrate	= CONFIG_BAUDRATE;  	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { +		WATCHDOG_RESET ();  		if ((*init_fnc_ptr) () != 0) {  			hang ();  		}  	} +	WATCHDOG_RESET ();  	bd->bi_flashsize = flash_init(); +	WATCHDOG_RESET ();  	mem_malloc_init();  	malloc_bin_reloc();  	env_relocate(); @@ -157,12 +160,14 @@ void board_init (void)  		if (s) s = (*e) ? e + 1 : e;  	} +	WATCHDOG_RESET ();  	devices_init();  	jumptable_init();  	console_init_r();  	/*  	 */ +	WATCHDOG_RESET ();  	interrupt_init ();  #ifdef CONFIG_STATUS_LED diff --git a/lib_nios/time.c b/lib_nios/time.c index 765b9c198..25a233ea7 100644 --- a/lib_nios/time.c +++ b/lib_nios/time.c @@ -22,6 +22,7 @@   */  #include <common.h> +#include <watchdog.h>  extern void dly_clks( unsigned long ticks ); @@ -33,5 +34,6 @@ void udelay(unsigned long usec)  	 * cpu clocks.  	 */  	unsigned long cnt = (CONFIG_SYS_CLK_FREQ/1000000) * usec; +	WATCHDOG_RESET ();	/* trigger watchdog if needed */  	dly_clks (cnt);  } diff --git a/lib_ppc/board.c b/lib_ppc/board.c index 04a1b8bfa..a6305339a 100644 --- a/lib_ppc/board.c +++ b/lib_ppc/board.c @@ -515,6 +515,8 @@ void board_init_f (ulong bootflag)  #endif  	bd->bi_iic_fast[0] = 0;  	bd->bi_iic_fast[1] = 0; +#elif defined(CONFIG_XILINX_ML300) +	bd->bi_pci_busfreq = get_PCI_freq ();  #endif  #endif diff --git a/nios_config.mk b/nios_config.mk index 2e610eb7d..728f8bf6a 100644 --- a/nios_config.mk +++ b/nios_config.mk @@ -22,4 +22,4 @@  # MA 02111-1307 USA  # -PLATFORM_CPPFLAGS += -m32 -DCONFIG_NIOS -ffixed-g7 +PLATFORM_CPPFLAGS += -m32 -DCONFIG_NIOS -D__NIOS__ -ffixed-g7 |