⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inca-ip_sw.c

📁 F:worksip2440a board可启动u-boot-like.tar.gz F:worksip2440a board可启动u-boot-like.tar.gz
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * INCA-IP internal switch ethernet driver. * * (C) Copyright 2003-2004 * 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 <common.h>#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) \	&& defined(CONFIG_INCA_IP_SWITCH)#include <malloc.h>#include <net.h>#include <asm/inca-ip.h>#include <asm/addrspace.h>#define NUM_RX_DESC	PKTBUFSRX#define NUM_TX_DESC	3#define TOUT_LOOP	1000000#define DELAY	udelay(10000)  /* Sometimes the store word instruction hangs while writing to one   * of the Switch registers. Moving the instruction into a separate   * function somehow makes the problem go away.   */static void SWORD(volatile u32 * reg, u32 value){	*reg = value;}#define DMA_WRITE_REG(reg, value) *((volatile u32 *)reg) = (u32)value;#define DMA_READ_REG(reg, value)    value = (u32)*((volatile u32*)reg)#define SW_WRITE_REG(reg, value)   \	SWORD(reg, value);\	DELAY;\	SWORD(reg, value);#define SW_READ_REG(reg, value)	   \	value = (u32)*((volatile u32*)reg);\	DELAY;\	value = (u32)*((volatile u32*)reg);#define INCA_DMA_TX_POLLING_TIME	0x07#define INCA_DMA_RX_POLLING_TIME	0x07#define INCA_DMA_TX_HOLD		0x80000000#define INCA_DMA_TX_EOP			0x40000000#define INCA_DMA_TX_SOP			0x20000000#define INCA_DMA_TX_ICPT		0x10000000#define INCA_DMA_TX_IEOP		0x08000000#define INCA_DMA_RX_C			0x80000000#define INCA_DMA_RX_SOP			0x40000000#define INCA_DMA_RX_EOP			0x20000000#define INCA_SWITCH_PHY_SPEED_10H	0x1#define INCA_SWITCH_PHY_SPEED_10F	0x5#define INCA_SWITCH_PHY_SPEED_100H	0x2#define INCA_SWITCH_PHY_SPEED_100F	0x6/************************ Auto MDIX settings ************************/#define INCA_IP_AUTO_MDIX_LAN_PORTS_DIR		INCA_IP_Ports_P1_DIR#define INCA_IP_AUTO_MDIX_LAN_PORTS_ALTSEL	INCA_IP_Ports_P1_ALTSEL#define INCA_IP_AUTO_MDIX_LAN_PORTS_OUT		INCA_IP_Ports_P1_OUT#define INCA_IP_AUTO_MDIX_LAN_GPIO_PIN_RXTX	16#define WAIT_SIGNAL_RETRIES			100#define WAIT_LINK_RETRIES			100#define LINK_RETRY_DELAY			2000  /* ms *//********************************************************************/typedef struct{	union {		struct {			volatile u32 HOLD		:1;			volatile u32 ICpt		:1;			volatile u32 IEop		:1;			volatile u32 offset		:3;			volatile u32 reserved0		:4;			volatile u32 NFB		:22;		}field;		volatile u32 word;	}params;	volatile u32 nextRxDescPtr;	volatile u32 RxDataPtr;	union {		struct {			volatile u32 C			:1;			volatile u32 Sop		:1;			volatile u32 Eop		:1;			volatile u32 reserved3		:12;			volatile u32 NBT		:17;		}field;		volatile u32 word;	}status;} inca_rx_descriptor_t;typedef struct{	union {		struct {			volatile u32 HOLD		:1;			volatile u32 Eop		:1;			volatile u32 Sop		:1;			volatile u32 ICpt		:1;			volatile u32 IEop		:1;			volatile u32 reserved0		:5;			volatile u32 NBA		:22;		}field;		volatile u32 word;	}params;	volatile u32 nextTxDescPtr;	volatile u32 TxDataPtr;	volatile u32 C			:1;	volatile u32 reserved3		:31;} inca_tx_descriptor_t;static inca_rx_descriptor_t rx_ring[NUM_RX_DESC] __attribute__ ((aligned(16)));static inca_tx_descriptor_t tx_ring[NUM_TX_DESC] __attribute__ ((aligned(16)));static int tx_new, rx_new, tx_hold, rx_hold;static int tx_old_hold = -1;static int initialized	= 0;static int inca_switch_init(struct eth_device *dev, bd_t * bis);static int inca_switch_send(struct eth_device *dev, volatile void *packet, int length);static int inca_switch_recv(struct eth_device *dev);static void inca_switch_halt(struct eth_device *dev);static void inca_init_switch_chip(void);static void inca_dma_init(void);static int inca_amdix(void);int inca_switch_initialize(bd_t * bis){	struct eth_device *dev;#if 0	printf("Entered inca_switch_initialize()\n");#endif	if (!(dev = (struct eth_device *) malloc (sizeof *dev))) {		printf("Failed to allocate memory\n");		return 0;	}	memset(dev, 0, sizeof(*dev));	inca_dma_init();	inca_init_switch_chip();#if defined(CONFIG_INCA_IP_SWITCH_AMDIX)	inca_amdix();#endif	sprintf(dev->name, "INCA-IP Switch");	dev->init = inca_switch_init;	dev->halt = inca_switch_halt;	dev->send = inca_switch_send;	dev->recv = inca_switch_recv;	eth_register(dev);#if 0	printf("Leaving inca_switch_initialize()\n");#endif	return 1;}static int inca_switch_init(struct eth_device *dev, bd_t * bis){	int i;	u32 v, regValue;	u16 wTmp;#if 0	printf("Entering inca_switch_init()\n");#endif	/* Set MAC address.	 */	wTmp = (u16)dev->enetaddr[0];	regValue = (wTmp << 8) | dev->enetaddr[1];	SW_WRITE_REG(INCA_IP_Switch_PMAC_SA1, regValue);	wTmp = (u16)dev->enetaddr[2];	regValue = (wTmp << 8) | dev->enetaddr[3];	regValue = regValue << 16;	wTmp = (u16)dev->enetaddr[4];	regValue |= (wTmp<<8) | dev->enetaddr[5];	SW_WRITE_REG(INCA_IP_Switch_PMAC_SA2, regValue);	/* Initialize the descriptor rings.	 */	for (i = 0; i < NUM_RX_DESC; i++) {		inca_rx_descriptor_t * rx_desc = KSEG1ADDR(&rx_ring[i]);		memset(rx_desc, 0, sizeof(rx_ring[i]));		/* Set maximum size of receive buffer.		 */		rx_desc->params.field.NFB = PKTSIZE_ALIGN;		/* Set the offset of the receive buffer. Zero means		 * that the offset mechanism is not used.		 */		rx_desc->params.field.offset = 0;		/* Check if it is the last descriptor.		 */		if (i == (NUM_RX_DESC - 1)) {			/* Let the last descriptor point to the first			 * one.			 */			rx_desc->nextRxDescPtr = KSEG1ADDR((u32)rx_ring);		} else {			/* Set the address of the next descriptor.			 */			rx_desc->nextRxDescPtr = (u32)KSEG1ADDR(&rx_ring[i+1]);		}		rx_desc->RxDataPtr = (u32)KSEG1ADDR(NetRxPackets[i]);	}#if 0	printf("rx_ring = 0x%08X 0x%08X\n", (u32)rx_ring, (u32)&rx_ring[0]);	printf("tx_ring = 0x%08X 0x%08X\n", (u32)tx_ring, (u32)&tx_ring[0]);#endif	for (i = 0; i < NUM_TX_DESC; i++) {		inca_tx_descriptor_t * tx_desc = KSEG1ADDR(&tx_ring[i]);		memset(tx_desc, 0, sizeof(tx_ring[i]));		tx_desc->params.word	   = 0;		tx_desc->params.field.HOLD = 1;		tx_desc->C		   = 1;			/* Check if it is the last descriptor.			 */		if (i == (NUM_TX_DESC - 1)) {				/* Let the last descriptor point to the				 * first one.				 */			tx_desc->nextTxDescPtr = KSEG1ADDR((u32)tx_ring);		} else {				/* Set the address of the next descriptor.				 */			tx_desc->nextTxDescPtr = (u32)KSEG1ADDR(&tx_ring[i+1]);		}	}	/* Initialize RxDMA.	 */	DMA_READ_REG(INCA_IP_DMA_DMA_RXISR, v);#if 0	printf("RX status = 0x%08X\n", v);#endif	/* Writing to the FRDA of CHANNEL.	 */	DMA_WRITE_REG(INCA_IP_DMA_DMA_RXFRDA0, (u32)rx_ring);	/* Writing to the COMMAND REG.	 */	DMA_WRITE_REG(INCA_IP_DMA_DMA_RXCCR0, INCA_IP_DMA_DMA_RXCCR0_INIT);	/* Initialize TxDMA.	 */	DMA_READ_REG(INCA_IP_DMA_DMA_TXISR, v);#if 0	printf("TX status = 0x%08X\n", v);#endif	/* Writing to the FRDA of CHANNEL.	 */	DMA_WRITE_REG(INCA_IP_DMA_DMA_TXFRDA0, (u32)tx_ring);	tx_new = rx_new = 0;	tx_hold = NUM_TX_DESC - 1;	rx_hold = NUM_RX_DESC - 1;#if 0	rx_ring[rx_hold].params.field.HOLD = 1;#endif	/* enable spanning tree forwarding, enable the CPU port */	/* ST_PT:	 *	CPS (CPU port status)	0x3 (forwarding)	 *	LPS (LAN port status)	0x3 (forwarding)	 *	PPS (PC port status)	0x3 (forwarding)	 */	SW_WRITE_REG(INCA_IP_Switch_ST_PT,0x3f);#if 0	printf("Leaving inca_switch_init()\n");#endif	return 0;}static int inca_switch_send(struct eth_device *dev, volatile void *packet, int length){	int		       i;	int		       res	= -1;	u32		       command;	u32		       regValue;	inca_tx_descriptor_t * tx_desc	= KSEG1ADDR(&tx_ring[tx_new]);#if 0	printf("Entered inca_switch_send()\n");#endif	if (length <= 0) {		printf ("%s: bad packet size: %d\n", dev->name, length);		goto Done;	}	for(i = 0; tx_desc->C == 0; i++) {		if (i >= TOUT_LOOP) {			printf("%s: tx error buffer not ready\n", dev->name);			goto Done;		}	}	if (tx_old_hold >= 0) {		KSEG1ADDR(&tx_ring[tx_old_hold])->params.field.HOLD = 1;	}	tx_old_hold = tx_hold;	tx_desc->params.word =			(INCA_DMA_TX_SOP | INCA_DMA_TX_EOP | INCA_DMA_TX_HOLD);	tx_desc->C = 0;	tx_desc->TxDataPtr = (u32)packet;	tx_desc->params.field.NBA = length;	KSEG1ADDR(&tx_ring[tx_hold])->params.field.HOLD = 0;	tx_hold = tx_new;	tx_new	= (tx_new + 1) % NUM_TX_DESC;	if (! initialized) {		command = INCA_IP_DMA_DMA_TXCCR0_INIT;		initialized = 1;	} else {		command = INCA_IP_DMA_DMA_TXCCR0_HR;	}	DMA_READ_REG(INCA_IP_DMA_DMA_TXCCR0, regValue);	regValue |= command;#if 0	printf("regValue = 0x%x\n", regValue);#endif	DMA_WRITE_REG(INCA_IP_DMA_DMA_TXCCR0, regValue);#if 1	for(i = 0; KSEG1ADDR(&tx_ring[tx_hold])->C == 0; i++) {		if (i >= TOUT_LOOP) {			printf("%s: tx buffer not ready\n", dev->name);			goto Done;		}	}#endif	res = length;Done:#if 0

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -