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

📄 smc911x.c

📁 uboot详细解读可用启动引导LINUX2.6内核
💻 C
📖 第 1 页 / 共 2 页
字号:
#define MII_DATA		0x07	  /* R/W mask 0x0000FFFFUL */#define FLOW			0x08	  /* R/W */#define FLOW_FCPT			0xFFFF0000#define FLOW_FCPASS			0x00000004#define FLOW_FCEN			0x00000002#define FLOW_FCBSY			0x00000001#define VLAN1			0x09	  /* R/W mask 0x0000FFFFUL */#define VLAN1_VTI1			0x0000ffff#define VLAN2			0x0A	  /* R/W mask 0x0000FFFFUL */#define VLAN2_VTI2			0x0000ffff#define WUFF			0x0B	  /* WO */#define WUCSR			0x0C	  /* R/W */#define WUCSR_GUE			0x00000200#define WUCSR_WUFR			0x00000040#define WUCSR_MPR			0x00000020#define WUCSR_WAKE_EN			0x00000004#define WUCSR_MPEN			0x00000002/* Chip ID values */#define CHIP_9115	0x115#define CHIP_9116	0x116#define CHIP_9117	0x117#define CHIP_9118	0x118#define CHIP_9215	0x115a#define CHIP_9216	0x116a#define CHIP_9217	0x117a#define CHIP_9218	0x118astruct chip_id {	u16 id;	char *name;};static const struct chip_id chip_ids[] =  {	{ CHIP_9115, "LAN9115" },	{ CHIP_9116, "LAN9116" },	{ CHIP_9117, "LAN9117" },	{ CHIP_9118, "LAN9118" },	{ CHIP_9215, "LAN9215" },	{ CHIP_9216, "LAN9216" },	{ CHIP_9217, "LAN9217" },	{ CHIP_9218, "LAN9218" },	{ 0, NULL },};#define DRIVERNAME "smc911x"u32 smc911x_get_mac_csr(u8 reg){	while (reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)		;	reg_write(MAC_CSR_CMD, MAC_CSR_CMD_CSR_BUSY | MAC_CSR_CMD_R_NOT_W | reg);	while (reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)		;	return reg_read(MAC_CSR_DATA);}void smc911x_set_mac_csr(u8 reg, u32 data){	while (reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)		;	reg_write(MAC_CSR_DATA, data);	reg_write(MAC_CSR_CMD, MAC_CSR_CMD_CSR_BUSY | reg);	while (reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)		;}static int smx911x_handle_mac_address(bd_t *bd){	unsigned long addrh, addrl;	unsigned char *m = bd->bi_enetaddr;	/* if the environment has a valid mac address then use it */	if ((m[0] | m[1] | m[2] | m[3] | m[4] | m[5])) {		addrl = m[0] | m[1] << 8 | m[2] << 16 | m[3] << 24;		addrh = m[4] | m[5] << 8;		smc911x_set_mac_csr(ADDRH, addrh);		smc911x_set_mac_csr(ADDRL, addrl);	} else {		/* if not, try to get one from the eeprom */		addrh = smc911x_get_mac_csr(ADDRH);		addrl = smc911x_get_mac_csr(ADDRL);		m[0] = (addrl       ) & 0xff;		m[1] = (addrl >>  8 ) & 0xff;		m[2] = (addrl >> 16 ) & 0xff;		m[3] = (addrl >> 24 ) & 0xff;		m[4] = (addrh       ) & 0xff;		m[5] = (addrh >>  8 ) & 0xff;		/* we get 0xff when there is no eeprom connected */		if ((m[0] & m[1] & m[2] & m[3] & m[4] & m[5]) == 0xff) {			printf(DRIVERNAME ": no valid mac address in environment "				"and no eeprom found\n");			return -1;		}	}	printf(DRIVERNAME ": MAC %02x:%02x:%02x:%02x:%02x:%02x\n",		m[0], m[1], m[2], m[3], m[4], m[5]);	return 0;}static int smc911x_miiphy_read(u8 phy, u8 reg, u16 *val){	while (smc911x_get_mac_csr(MII_ACC) & MII_ACC_MII_BUSY)		;	smc911x_set_mac_csr(MII_ACC, phy << 11 | reg << 6 | MII_ACC_MII_BUSY);	while (smc911x_get_mac_csr(MII_ACC) & MII_ACC_MII_BUSY)		;	*val = smc911x_get_mac_csr(MII_DATA);	return 0;}static int smc911x_miiphy_write(u8 phy, u8 reg, u16  val){	while (smc911x_get_mac_csr(MII_ACC) & MII_ACC_MII_BUSY)		;	smc911x_set_mac_csr(MII_DATA, val);	smc911x_set_mac_csr(MII_ACC,		phy << 11 | reg << 6 | MII_ACC_MII_BUSY | MII_ACC_MII_WRITE);	while (smc911x_get_mac_csr(MII_ACC) & MII_ACC_MII_BUSY)		;	return 0;}static int smc911x_phy_reset(void){	u32 reg;	reg = reg_read(PMT_CTRL);	reg &= ~0xfffff030;	reg |= PMT_CTRL_PHY_RST;	reg_write(PMT_CTRL, reg);	mdelay(100);	return 0;}static void smc911x_phy_configure(void){	int timeout;	u16 status;	smc911x_phy_reset();	smc911x_miiphy_write(1, PHY_BMCR, PHY_BMCR_RESET);	mdelay(1);	smc911x_miiphy_write(1, PHY_ANAR, 0x01e1);	smc911x_miiphy_write(1, PHY_BMCR, PHY_BMCR_AUTON | PHY_BMCR_RST_NEG);	timeout = 5000;	do {		mdelay(1);		if ((timeout--) == 0)			goto err_out;		if (smc911x_miiphy_read(1, PHY_BMSR, &status) != 0)			goto err_out;	} while (!(status & PHY_BMSR_LS));	printf(DRIVERNAME ": phy initialized\n");	return;err_out:	printf(DRIVERNAME ": autonegotiation timed out\n");}static void smc911x_reset(void){	int timeout;	/* Take out of PM setting first */	if (reg_read(PMT_CTRL) & PMT_CTRL_READY) {		/* Write to the bytetest will take out of powerdown */		reg_write(BYTE_TEST, 0x0);		timeout = 10;		while (timeout-- && !(reg_read(PMT_CTRL) & PMT_CTRL_READY))			udelay(10);		if (!timeout) {			printf(DRIVERNAME				": timeout waiting for PM restore\n");			return;		}	}	/* Disable interrupts */	reg_write(INT_EN, 0);	reg_write(HW_CFG, HW_CFG_SRST);	timeout = 1000;	while (timeout-- && reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY)		udelay(10);	if (!timeout) {		printf(DRIVERNAME ": reset timeout\n");		return;	}	/* Reset the FIFO level and flow control settings */	smc911x_set_mac_csr(FLOW, FLOW_FCPT | FLOW_FCEN);	reg_write(AFC_CFG, 0x0050287F);	/* Set to LED outputs */	reg_write(GPIO_CFG, 0x70070000);}static void smc911x_enable(void){	/* Enable TX */	reg_write(HW_CFG, 8 << 16 | HW_CFG_SF);	reg_write(GPT_CFG, GPT_CFG_TIMER_EN | 10000);	reg_write(TX_CFG, TX_CFG_TX_ON);	/* no padding to start of packets */	reg_write(RX_CFG, 0);	smc911x_set_mac_csr(MAC_CR, MAC_CR_TXEN | MAC_CR_RXEN | MAC_CR_HBDIS);}int eth_init(bd_t *bd){	unsigned long val, i;	printf(DRIVERNAME ": initializing\n");	val = reg_read(BYTE_TEST);	if (val != 0x87654321) {		printf(DRIVERNAME ": Invalid chip endian 0x%08lx\n", val);		goto err_out;	}	val = reg_read(ID_REV) >> 16;	for (i = 0; chip_ids[i].id != 0; i++) {		if (chip_ids[i].id == val) break;	}	if (!chip_ids[i].id) {		printf(DRIVERNAME ": Unknown chip ID %04lx\n", val);		goto err_out;	}	printf(DRIVERNAME ": detected %s controller\n", chip_ids[i].name);	smc911x_reset();	/* Configure the PHY, initialize the link state */	smc911x_phy_configure();	if (smx911x_handle_mac_address(bd))		goto err_out;	/* Turn on Tx + Rx */	smc911x_enable();	return 0;err_out:	return -1;}int eth_send(volatile void *packet, int length){	u32 *data = (u32*)packet;	u32 tmplen;	u32 status;	reg_write(TX_DATA_FIFO, TX_CMD_A_INT_FIRST_SEG | TX_CMD_A_INT_LAST_SEG | length);	reg_write(TX_DATA_FIFO, length);	tmplen = (length + 3) / 4;	while (tmplen--)		reg_write(TX_DATA_FIFO, *data++);	/* wait for transmission */	while (!((reg_read(TX_FIFO_INF) & TX_FIFO_INF_TSUSED) >> 16));	/* get status. Ignore 'no carrier' error, it has no meaning for	 * full duplex operation	 */	status = reg_read(TX_STATUS_FIFO) & (TX_STS_LOC | TX_STS_LATE_COLL |		TX_STS_MANY_COLL | TX_STS_MANY_DEFER | TX_STS_UNDERRUN);	if (!status)		return 0;	printf(DRIVERNAME ": failed to send packet: %s%s%s%s%s\n",		status & TX_STS_LOC ? "TX_STS_LOC " : "",		status & TX_STS_LATE_COLL ? "TX_STS_LATE_COLL " : "",		status & TX_STS_MANY_COLL ? "TX_STS_MANY_COLL " : "",		status & TX_STS_MANY_DEFER ? "TX_STS_MANY_DEFER " : "",		status & TX_STS_UNDERRUN ? "TX_STS_UNDERRUN" : "");	return -1;}void eth_halt(void){	smc911x_reset();}int eth_rx(void){	u32 *data = (u32 *)NetRxPackets[0];	u32 pktlen, tmplen;	u32 status;	if ((reg_read(RX_FIFO_INF) & RX_FIFO_INF_RXSUSED) >> 16) {		status = reg_read(RX_STATUS_FIFO);		pktlen = (status & RX_STS_PKT_LEN) >> 16;		reg_write(RX_CFG, 0);		tmplen = (pktlen + 2+ 3) / 4;		while (tmplen--)			*data++ = reg_read(RX_DATA_FIFO);		if (status & RX_STS_ES)			printf(DRIVERNAME				": dropped bad packet. Status: 0x%08x\n",				status);		else			NetReceive(NetRxPackets[0], pktlen);	}	return 0;}

⌨️ 快捷键说明

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