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

📄 tsi108_eth.c

📁 U-boot源码 ARM7启动代码
💻 C
📖 第 1 页 / 共 3 页
字号:
 *//* PHY Specific Status Register (MV1111_EXT_CTRL1_REG) */#define SPEC_STAT_SPEED_MASK	(3 << 14)#define SPEC_STAT_FULL_DUP	(1 << 13)#define SPEC_STAT_PAGE_RCVD	(1 << 12)#define SPEC_STAT_RESOLVED	(1 << 11)	/* Speed and Duplex Resolved */#define SPEC_STAT_LINK_UP	(1 << 10)#define SPEC_STAT_CABLE_LEN_MASK	(7 << 7)/* Cable Length (100/1000 modes only) */#define SPEC_STAT_MDIX		(1 << 6)#define SPEC_STAT_POLARITY	(1 << 1)#define SPEC_STAT_JABBER	(1 << 0)#define SPEED_1000		(2 << 14)#define SPEED_100		(1 << 14)#define SPEED_10		(0 << 14)#define TBI_ADDR	0x1E	/* Ten Bit Interface address *//* negotiated link parameters */#define LINK_SPEED_UNKNOWN	0#define LINK_SPEED_10		1#define LINK_SPEED_100		2#define LINK_SPEED_1000		3#define LINK_DUPLEX_UNKNOWN	0#define LINK_DUPLEX_HALF	1#define LINK_DUPLEX_FULL	2static unsigned int phy_address[] = { 8, 9 };#define vuint32 volatile u32/* TX/RX buffer descriptors. MUST be cache line aligned in memory. (32 byte) * This structure is accessed by the ethernet DMA engine which means it * MUST be in LITTLE ENDIAN format */struct dma_descriptor {	vuint32 start_addr0;	/* buffer address, least significant bytes. */	vuint32 start_addr1;	/* buffer address, most significant bytes. */	vuint32 next_descr_addr0;/* next descriptor address, least significant bytes.  Must be 64-bit aligned. */	vuint32 next_descr_addr1;/* next descriptor address, most significant bytes. */	vuint32 vlan_byte_count;/* VLAN tag(top 2 bytes) and byte countt (bottom 2 bytes). */	vuint32 config_status;	/* Configuration/Status. */	vuint32 reserved1;	/* reserved to make the descriptor cache line aligned. */	vuint32 reserved2;	/* reserved to make the descriptor cache line aligned. */};/* last next descriptor address flag */#define DMA_DESCR_LAST		(1 << 31)/* TX DMA descriptor config status bits */#define DMA_DESCR_TX_EOF	(1 <<  0)	/* end of frame */#define DMA_DESCR_TX_SOF	(1 <<  1)	/* start of frame */#define DMA_DESCR_TX_PFVLAN	(1 <<  2)#define DMA_DESCR_TX_HUGE	(1 <<  3)#define DMA_DESCR_TX_PAD	(1 <<  4)#define DMA_DESCR_TX_CRC	(1 <<  5)#define DMA_DESCR_TX_DESCR_INT	(1 << 14)#define DMA_DESCR_TX_RETRY_COUNT	0x000F0000#define DMA_DESCR_TX_ONE_COLLISION	(1 << 20)#define DMA_DESCR_TX_LATE_COLLISION	(1 << 24)#define DMA_DESCR_TX_UNDERRUN		(1 << 25)#define DMA_DESCR_TX_RETRY_LIMIT	(1 << 26)#define DMA_DESCR_TX_OK			(1 << 30)#define DMA_DESCR_TX_OWNER		(1 << 31)/* RX DMA descriptor status bits */#define DMA_DESCR_RX_EOF		(1 <<  0)#define DMA_DESCR_RX_SOF		(1 <<  1)#define DMA_DESCR_RX_VTF		(1 <<  2)#define DMA_DESCR_RX_FRAME_IS_TYPE	(1 <<  3)#define DMA_DESCR_RX_SHORT_FRAME	(1 <<  4)#define DMA_DESCR_RX_HASH_MATCH		(1 <<  7)#define DMA_DESCR_RX_BAD_FRAME		(1 <<  8)#define DMA_DESCR_RX_OVERRUN		(1 <<  9)#define DMA_DESCR_RX_MAX_FRAME_LEN	(1 << 11)#define DMA_DESCR_RX_CRC_ERROR		(1 << 12)#define DMA_DESCR_RX_DESCR_INT		(1 << 13)#define DMA_DESCR_RX_OWNER		(1 << 15)#define RX_BUFFER_SIZE	PKTSIZE#define NUM_RX_DESC	PKTBUFSRXstatic struct dma_descriptor tx_descriptor __attribute__ ((aligned(32)));static struct dma_descriptor rx_descr_array[NUM_RX_DESC]	__attribute__ ((aligned(32)));static struct dma_descriptor *rx_descr_current;static int tsi108_eth_probe (struct eth_device *dev, bd_t * bis);static int tsi108_eth_send (struct eth_device *dev,			   volatile void *packet, int length);static int tsi108_eth_recv (struct eth_device *dev);static void tsi108_eth_halt (struct eth_device *dev);static unsigned int read_phy (unsigned int base,			     unsigned int phy_addr, unsigned int phy_reg);static void write_phy (unsigned int base,		      unsigned int phy_addr,		      unsigned int phy_reg, unsigned int phy_data);#if TSI108_ETH_DEBUG > 100/* * print phy debug infomation */static void dump_phy_regs (unsigned int phy_addr){	int i;	printf ("PHY %d registers\n", phy_addr);	for (i = 0; i <= 30; i++) {		printf ("%2d  0x%04x\n", i, read_phy (ETH_BASE, phy_addr, i));	}	printf ("\n");}#else#define dump_phy_regs(base) do{}while(0)#endif#if TSI108_ETH_DEBUG > 100/* * print debug infomation */static void tx_diag_regs (unsigned int base){	int i;	unsigned long dummy;	printf ("TX diagnostics registers\n");	reg_TX_DIAGNOSTIC_ADDR(base) = 0x00 | TX_DIAGNOSTIC_ADDR_AI;	udelay (1000);	dummy = reg_TX_DIAGNOSTIC_DATA(base);	for (i = 0x00; i <= 0x05; i++) {		udelay (1000);		printf ("0x%02x  0x%08x\n", i, reg_TX_DIAGNOSTIC_DATA(base));	}	reg_TX_DIAGNOSTIC_ADDR(base) = 0x40 | TX_DIAGNOSTIC_ADDR_AI;	udelay (1000);	dummy = reg_TX_DIAGNOSTIC_DATA(base);	for (i = 0x40; i <= 0x47; i++) {		udelay (1000);		printf ("0x%02x  0x%08x\n", i, reg_TX_DIAGNOSTIC_DATA(base));	}	printf ("\n");}#else#define tx_diag_regs(base) do{}while(0)#endif#if TSI108_ETH_DEBUG > 100/* * print debug infomation */static void rx_diag_regs (unsigned int base){	int i;	unsigned long dummy;	printf ("RX diagnostics registers\n");	reg_RX_DIAGNOSTIC_ADDR(base) = 0x00 | RX_DIAGNOSTIC_ADDR_AI;	udelay (1000);	dummy = reg_RX_DIAGNOSTIC_DATA(base);	for (i = 0x00; i <= 0x05; i++) {		udelay (1000);		printf ("0x%02x  0x%08x\n", i, reg_RX_DIAGNOSTIC_DATA(base));	}	reg_RX_DIAGNOSTIC_ADDR(base) = 0x40 | RX_DIAGNOSTIC_ADDR_AI;	udelay (1000);	dummy = reg_RX_DIAGNOSTIC_DATA(base);	for (i = 0x08; i <= 0x0a; i++) {		udelay (1000);		printf ("0x%02x  0x%08x\n", i, reg_RX_DIAGNOSTIC_DATA(base));	}	printf ("\n");}#else#define rx_diag_regs(base) do{}while(0)#endif#if TSI108_ETH_DEBUG > 100/* * print debug infomation */static void debug_mii_regs (unsigned int base){	printf ("MII_MGMT_CONFIG     0x%08x\n", reg_MII_MGMT_CONFIG(base));	printf ("MII_MGMT_COMMAND    0x%08x\n", reg_MII_MGMT_COMMAND(base));	printf ("MII_MGMT_ADDRESS    0x%08x\n", reg_MII_MGMT_ADDRESS(base));	printf ("MII_MGMT_CONTROL    0x%08x\n", reg_MII_MGMT_CONTROL(base));	printf ("MII_MGMT_STATUS     0x%08x\n", reg_MII_MGMT_STATUS(base));	printf ("MII_MGMT_INDICATORS 0x%08x\n", reg_MII_MGMT_INDICATORS(base));	printf ("\n");}#else#define debug_mii_regs(base) do{}while(0)#endif/* * Wait until the phy bus is non-busy */static void phy_wait (unsigned int base, unsigned int condition){	int timeout;	timeout = 0;	while (reg_MII_MGMT_INDICATORS(base) & condition) {		udelay (10);		if (++timeout > 10000) {			printf ("ERROR: timeout waiting for phy bus (%d)\n",			       condition);			break;		}	}}/* * read phy register */static unsigned int read_phy (unsigned int base,			     unsigned int phy_addr, unsigned int phy_reg){	unsigned int value;	phy_wait (base, MII_MGMT_INDICATORS_BUSY);	reg_MII_MGMT_ADDRESS(base) = (phy_addr << 8) | phy_reg;	/* Ensure that the Read Cycle bit is cleared prior to next read cycle */	reg_MII_MGMT_COMMAND(base) = 0;	/* start the read */	reg_MII_MGMT_COMMAND(base) = MII_MGMT_COMMAND_READ_CYCLE;	/* wait for the read to complete */	phy_wait (base,		 MII_MGMT_INDICATORS_NOT_VALID | MII_MGMT_INDICATORS_BUSY);	value = reg_MII_MGMT_STATUS(base);	reg_MII_MGMT_COMMAND(base) = 0;	return value;}/* * write phy register */static void write_phy (unsigned int base,		      unsigned int phy_addr,		      unsigned int phy_reg, unsigned int phy_data){	phy_wait (base, MII_MGMT_INDICATORS_BUSY);	reg_MII_MGMT_ADDRESS(base) = (phy_addr << 8) | phy_reg;	/* Ensure that the Read Cycle bit is cleared prior to next cycle */	reg_MII_MGMT_COMMAND(base) = 0;	/* start the write */	reg_MII_MGMT_CONTROL(base) = phy_data;}/* * configure the marvell 88e1111 phy */static int marvell_88e_phy_config (struct eth_device *dev, int *speed,				  int *duplex){	unsigned long base;	unsigned long phy_addr;	unsigned int phy_status;	unsigned int phy_spec_status;	int timeout;	int phy_speed;	int phy_duplex;	unsigned int value;	phy_speed = LINK_SPEED_UNKNOWN;	phy_duplex = LINK_DUPLEX_UNKNOWN;	base = dev->iobase;	phy_addr = (unsigned long)dev->priv;	/* Take the PHY out of reset. */	write_phy (ETH_BASE, phy_addr, PHY_CTRL_REG, PHY_CTRL_RESET);	/* Wait for the reset process to complete. */	udelay (10);	timeout = 0;	while ((phy_status =		read_phy (ETH_BASE, phy_addr, PHY_CTRL_REG)) & PHY_CTRL_RESET) {		udelay (10);		if (++timeout > 10000) {			printf ("ERROR: timeout waiting for phy reset\n");			break;		}	}	/* TBI Configuration. */	write_phy (base, TBI_ADDR, TBI_CONTROL_2, TBI_CONTROL_2_G_MII_MODE |		  TBI_CONTROL_2_RECEIVE_CLOCK_SELECT);	/* Wait for the link to be established. */	timeout = 0;	do {		udelay (20000);		phy_status = read_phy (ETH_BASE, phy_addr, PHY_STATUS_REG);		if (++timeout > 100) {			debug_lev(1, "ERROR: unable to establish link!!!\n");			break;		}	} while ((phy_status & PHY_STAT_LINK_UP) == 0);	if ((phy_status & PHY_STAT_LINK_UP) == 0)		return 0;	value = 0;	phy_spec_status = read_phy (ETH_BASE, phy_addr, MV1111_SPEC_STAT_REG);	if (phy_spec_status & SPEC_STAT_RESOLVED) {		switch (phy_spec_status & SPEC_STAT_SPEED_MASK) {		case SPEED_1000:			phy_speed = LINK_SPEED_1000;			value |= PHY_CTRL_SPEED1;			break;		case SPEED_100:			phy_speed = LINK_SPEED_100;			value |= PHY_CTRL_SPEED0;			break;		case SPEED_10:			phy_speed = LINK_SPEED_10;			break;		}		if (phy_spec_status & SPEC_STAT_FULL_DUP) {			phy_duplex = LINK_DUPLEX_FULL;			value |= PHY_CTRL_FULL_DUPLEX;		} else			phy_duplex = LINK_DUPLEX_HALF;	}	/* set TBI speed */	write_phy (base, TBI_ADDR, PHY_CTRL_REG, value);	write_phy (base, TBI_ADDR, PHY_AN_ADV_REG, 0x0060);#if TSI108_ETH_DEBUG > 0

⌨️ 快捷键说明

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