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

📄 greth.c

📁 uboot详细解读可用启动引导LINUX2.6内核
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Gaisler.com GRETH 10/100/1000 Ethernet MAC driver * * Driver use polling mode (no Interrupt) * * (C) Copyright 2007 * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com * * 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>#include <command.h>#include <net.h>#include <malloc.h>#include <asm/processor.h>#include <ambapp.h>#include <asm/leon.h>/* #define DEBUG */#include "greth.h"/* Default to 3s timeout on autonegotiation */#ifndef GRETH_PHY_TIMEOUT_MS#define GRETH_PHY_TIMEOUT_MS 3000#endif/* ByPass Cache when reading regs */#define GRETH_REGLOAD(addr)		SPARC_NOCACHE_READ(addr)/* Write-through cache ==> no bypassing needed on writes */#define GRETH_REGSAVE(addr,data)	(*(unsigned int *)(addr) = (data))#define GRETH_REGORIN(addr,data) GRETH_REGSAVE(addr,GRETH_REGLOAD(addr)|data)#define GRETH_REGANDIN(addr,data) GRETH_REGSAVE(addr,GRETH_REGLOAD(addr)&data)#define GRETH_RXBD_CNT 4#define GRETH_TXBD_CNT 1#define GRETH_RXBUF_SIZE 1540#define GRETH_BUF_ALIGN 4#define GRETH_RXBUF_EFF_SIZE \	( (GRETH_RXBUF_SIZE&~(GRETH_BUF_ALIGN-1))+GRETH_BUF_ALIGN )typedef struct {	greth_regs *regs;	int irq;	struct eth_device *dev;	/* Hardware info */	unsigned char phyaddr;	int gbit_mac;	/* Current operating Mode */	int gb;			/* GigaBit */	int fd;			/* Full Duplex */	int sp;			/* 10/100Mbps speed (1=100,0=10) */	int auto_neg;		/* Auto negotiate done */	unsigned char hwaddr[6];	/* MAC Address */	/* Descriptors */	greth_bd *rxbd_base, *rxbd_max;	greth_bd *txbd_base, *txbd_max;	greth_bd *rxbd_curr;	/* rx buffers in rx descriptors */	void *rxbuf_base;	/* (GRETH_RXBUF_SIZE+ALIGNBYTES) * GRETH_RXBD_CNT */	/* unused for gbit_mac, temp buffer for sending packets with unligned	 * start.	 * Pointer to packet allocated with malloc.	 */	void *txbuf;	struct {		/* rx status */		unsigned int rx_packets,		    rx_crc_errors, rx_frame_errors, rx_length_errors, rx_errors;		/* tx stats */		unsigned int tx_packets,		    tx_latecol_errors,		    tx_underrun_errors, tx_limit_errors, tx_errors;	} stats;} greth_priv;/* Read MII register 'addr' from core 'regs' */static int read_mii(int addr, volatile greth_regs * regs){	while (GRETH_REGLOAD(&regs->mdio) & GRETH_MII_BUSY) {	}	GRETH_REGSAVE(&regs->mdio, (0 << 11) | ((addr & 0x1F) << 6) | 2);	while (GRETH_REGLOAD(&regs->mdio) & GRETH_MII_BUSY) {	}	if (!(GRETH_REGLOAD(&regs->mdio) & GRETH_MII_NVALID)) {		return (GRETH_REGLOAD(&regs->mdio) >> 16) & 0xFFFF;	} else {		return -1;	}}static void write_mii(int addr, int data, volatile greth_regs * regs){	while (GRETH_REGLOAD(&regs->mdio) & GRETH_MII_BUSY) {	}	GRETH_REGSAVE(&regs->mdio,		      ((data & 0xFFFF) << 16) | (0 << 11) | ((addr & 0x1F) << 6)		      | 1);	while (GRETH_REGLOAD(&regs->mdio) & GRETH_MII_BUSY) {	}}/* init/start hardware and allocate descriptor buffers for rx side * */int greth_init(struct eth_device *dev, bd_t * bis){	int i;	greth_priv *greth = dev->priv;	greth_regs *regs = greth->regs;#ifdef DEBUG	printf("greth_init\n");#endif	GRETH_REGSAVE(&regs->control, 0);	if (!greth->rxbd_base) {		/* allocate descriptors */		greth->rxbd_base = (greth_bd *)		    memalign(0x1000, GRETH_RXBD_CNT * sizeof(greth_bd));		greth->txbd_base = (greth_bd *)		    memalign(0x1000, GRETH_RXBD_CNT * sizeof(greth_bd));		/* allocate buffers to all descriptors  */		greth->rxbuf_base =		    malloc(GRETH_RXBUF_EFF_SIZE * GRETH_RXBD_CNT);	}	/* initate rx decriptors */	for (i = 0; i < GRETH_RXBD_CNT; i++) {		greth->rxbd_base[i].addr = (unsigned int)		    greth->rxbuf_base + (GRETH_RXBUF_EFF_SIZE * i);		/* enable desciptor & set wrap bit if last descriptor */		if (i >= (GRETH_RXBD_CNT - 1)) {			greth->rxbd_base[i].stat = GRETH_BD_EN | GRETH_BD_WR;		} else {			greth->rxbd_base[i].stat = GRETH_BD_EN;		}	}	/* initiate indexes */	greth->rxbd_curr = greth->rxbd_base;	greth->rxbd_max = greth->rxbd_base + (GRETH_RXBD_CNT - 1);	greth->txbd_max = greth->txbd_base + (GRETH_TXBD_CNT - 1);	/*	 * greth->txbd_base->addr = 0;	 * greth->txbd_base->stat = GRETH_BD_WR;	 */	/* initate tx decriptors */	for (i = 0; i < GRETH_TXBD_CNT; i++) {		greth->txbd_base[i].addr = 0;		/* enable desciptor & set wrap bit if last descriptor */		if (i >= (GRETH_RXBD_CNT - 1)) {			greth->txbd_base[i].stat = GRETH_BD_WR;		} else {			greth->txbd_base[i].stat = 0;		}	}	/**** SET HARDWARE REGS ****/	/* Set pointer to tx/rx descriptor areas */	GRETH_REGSAVE(&regs->rx_desc_p, (unsigned int)&greth->rxbd_base[0]);	GRETH_REGSAVE(&regs->tx_desc_p, (unsigned int)&greth->txbd_base[0]);	/* Enable Transmitter, GRETH will now scan descriptors for packets	 * to transmitt */#ifdef DEBUG	printf("greth_init: enabling receiver\n");#endif	GRETH_REGORIN(&regs->control, GRETH_RXEN);	return 0;}/* Initiate PHY to a relevant speed * return: *  - 0 = success *  - 1 = timeout/fail */int greth_init_phy(greth_priv * dev, bd_t * bis){	greth_regs *regs = dev->regs;	int tmp, tmp1, tmp2, i;	unsigned int start, timeout;	/* X msecs to ticks */	timeout = usec2ticks(GRETH_PHY_TIMEOUT_MS * 1000);	/* Get system timer0 current value	 * Total timeout is 5s	 */	start = get_timer(0);	/* get phy control register default values */	while ((tmp = read_mii(0, regs)) & 0x8000) {		if (get_timer(start) > timeout)			return 1;	/* Fail */	}	/* reset PHY and wait for completion */	write_mii(0, 0x8000 | tmp, regs);	while (((tmp = read_mii(0, regs))) & 0x8000) {		if (get_timer(start) > timeout)			return 1;	/* Fail */	}	/* Check if PHY is autoneg capable and then determine operating	 * mode, otherwise force it to 10 Mbit halfduplex	 */	dev->gb = 0;	dev->fd = 0;	dev->sp = 0;	dev->auto_neg = 0;	if (!((tmp >> 12) & 1)) {		write_mii(0, 0, regs);	} else {		/* wait for auto negotiation to complete and then check operating mode */		dev->auto_neg = 1;		i = 0;		while (!(((tmp = read_mii(1, regs)) >> 5) & 1)) {			if (get_timer(start) > timeout) {				printf("Auto negotiation timed out. "				       "Selecting default config\n");				tmp = read_mii(0, regs);				dev->gb = ((tmp >> 6) & 1)				    && !((tmp >> 13) & 1);				dev->sp = !((tmp >> 6) & 1)				    && ((tmp >> 13) & 1);				dev->fd = (tmp >> 8) & 1;				goto auto_neg_done;			}		}		if ((tmp >> 8) & 1) {			tmp1 = read_mii(9, regs);			tmp2 = read_mii(10, regs);			if ((tmp1 & GRETH_MII_EXTADV_1000FD) &&			    (tmp2 & GRETH_MII_EXTPRT_1000FD)) {				dev->gb = 1;				dev->fd = 1;			}			if ((tmp1 & GRETH_MII_EXTADV_1000HD) &&			    (tmp2 & GRETH_MII_EXTPRT_1000HD)) {				dev->gb = 1;				dev->fd = 0;			}		}		if ((dev->gb == 0) || ((dev->gb == 1) && (dev->gbit_mac == 0))) {			tmp1 = read_mii(4, regs);			tmp2 = read_mii(5, regs);			if ((tmp1 & GRETH_MII_100TXFD) &&			    (tmp2 & GRETH_MII_100TXFD)) {				dev->sp = 1;				dev->fd = 1;			}			if ((tmp1 & GRETH_MII_100TXHD) &&			    (tmp2 & GRETH_MII_100TXHD)) {				dev->sp = 1;				dev->fd = 0;			}			if ((tmp1 & GRETH_MII_10FD) && (tmp2 & GRETH_MII_10FD)) {				dev->fd = 1;			}			if ((dev->gb == 1) && (dev->gbit_mac == 0)) {				dev->gb = 0;				dev->fd = 0;				write_mii(0, dev->sp << 13, regs);			}		}	}      auto_neg_done:#ifdef DEBUG	printf("%s GRETH Ethermac at [0x%x] irq %d. Running \		%d Mbps %s duplex\n", dev->gbit_mac ? "10/100/1000" : "10/100", (unsigned int)(regs), (unsigned int)(dev->irq), dev->gb ? 1000 : (dev->sp ? 100 : 10), dev->fd ? "full" : "half");#endif	/* Read out PHY info if extended registers are available */	if (tmp & 1) {		tmp1 = read_mii(2, regs);		tmp2 = read_mii(3, regs);		tmp1 = (tmp1 << 6) | ((tmp2 >> 10) & 0x3F);		tmp = tmp2 & 0xF;		tmp2 = (tmp2 >> 4) & 0x3F;#ifdef DEBUG		printf("PHY: Vendor %x   Device %x    Revision %d\n", tmp1,		       tmp2, tmp);#endif	} else {		printf("PHY info not available\n");	}	/* set speed and duplex bits in control register */	GRETH_REGORIN(&regs->control,

⌨️ 快捷键说明

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