diff options
| author | Stefan Roese <sr@denx.de> | 2007-12-11 11:34:54 +0100 | 
|---|---|---|
| committer | Stefan Roese <sr@denx.de> | 2007-12-11 11:34:54 +0100 | 
| commit | 9caeaadf508cd0e11ac5dfc56ab0f72e3b89a105 (patch) | |
| tree | 1afcc9c20c04e19870ab5e2996104877695c54a3 /drivers/net/rtl8019.c | |
| parent | 7cfc12a7dcfdb350e2ab76db4dafcc30f7e77c2b (diff) | |
| parent | 41be969f4957115ed7b1fe8b890bfaee99d7a7a2 (diff) | |
| download | olio-uboot-2014.01-9caeaadf508cd0e11ac5dfc56ab0f72e3b89a105.tar.xz olio-uboot-2014.01-9caeaadf508cd0e11ac5dfc56ab0f72e3b89a105.zip | |
Merge commit 'u-boot/master' into for-1.3.1
Conflicts:
	drivers/rtc/Makefile
Diffstat (limited to 'drivers/net/rtl8019.c')
| -rw-r--r-- | drivers/net/rtl8019.c | 282 | 
1 files changed, 282 insertions, 0 deletions
| diff --git a/drivers/net/rtl8019.c b/drivers/net/rtl8019.c new file mode 100644 index 000000000..409a69f02 --- /dev/null +++ b/drivers/net/rtl8019.c @@ -0,0 +1,282 @@ +/* + * Realtek 8019AS Ethernet + * (C) Copyright 2002-2003 + * Xue Ligong(lgxue@hotmail.com),Wang Kehao, ESLAB, whut.edu.cn + * + * 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 + */ + +/* + * This code works in 8bit mode. + * If you need to work in 16bit mode, PLS change it! + */ + +#include <common.h> +#include <command.h> +#include "rtl8019.h" +#include <net.h> + +#ifdef CONFIG_DRIVER_RTL8019 + +#if defined(CONFIG_CMD_NET) + + +/* packet page register access functions */ + + +static unsigned char get_reg (unsigned int regno) +{ +	return (*(unsigned char *) regno); +} + + +static void put_reg (unsigned int regno, unsigned char val) +{ +	*(volatile unsigned char *) regno = val; +} + +static void eth_reset (void) +{ +	unsigned char ucTemp; + +	/* reset NIC */ +	ucTemp = get_reg (RTL8019_RESET); +	put_reg (RTL8019_RESET, ucTemp); +	put_reg (RTL8019_INTERRUPTSTATUS, 0xff); +	udelay (2000);		/* wait for 2ms */ +} + +void rtl8019_get_enetaddr (uchar * addr) +{ +	unsigned char i; +	unsigned char temp; + +	eth_reset (); + +	put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMARD); +	put_reg (RTL8019_DATACONFIGURATION, 0x48); +	put_reg (RTL8019_REMOTESTARTADDRESS0, 0x00); +	put_reg (RTL8019_REMOTESTARTADDRESS1, 0x00); +	put_reg (RTL8019_REMOTEBYTECOUNT0, 12); +	put_reg (RTL8019_REMOTEBYTECOUNT1, 0x00); +	put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMARD); +	printf ("MAC: "); +	for (i = 0; i < 6; i++) { +		temp = get_reg (RTL8019_DMA_DATA); +		*addr++ = temp; +		temp = get_reg (RTL8019_DMA_DATA); +		printf ("%x:", temp); +	} + +	while ((!get_reg (RTL8019_INTERRUPTSTATUS) & 0x40)); +	printf ("\b \n"); +	put_reg (RTL8019_REMOTEBYTECOUNT0, 0x00); +	put_reg (RTL8019_REMOTEBYTECOUNT1, 0x00); +	put_reg (RTL8019_COMMAND, RTL8019_PAGE0); +} + + +void eth_halt (void) +{ +	put_reg (RTL8019_COMMAND, 0x01); +} + +int eth_init (bd_t * bd) +{ +	eth_reset (); +	put_reg (RTL8019_COMMAND, RTL8019_PAGE0STOP); +	put_reg (RTL8019_DATACONFIGURATION, 0x48); +	put_reg (RTL8019_REMOTEBYTECOUNT0, 0x00); +	put_reg (RTL8019_REMOTEBYTECOUNT1, 0x00); +	put_reg (RTL8019_RECEIVECONFIGURATION, 0x00);	/*00; */ +	put_reg (RTL8019_TRANSMITPAGE, RTL8019_TPSTART); +	put_reg (RTL8019_TRANSMITCONFIGURATION, 0x02); +	put_reg (RTL8019_PAGESTART, RTL8019_PSTART); +	put_reg (RTL8019_BOUNDARY, RTL8019_PSTART); +	put_reg (RTL8019_PAGESTOP, RTL8019_PSTOP); +	put_reg (RTL8019_INTERRUPTSTATUS, 0xff); +	put_reg (RTL8019_INTERRUPTMASK, 0x11);	/*b; */ +	put_reg (RTL8019_COMMAND, RTL8019_PAGE1STOP); +	put_reg (RTL8019_PHYSICALADDRESS0, bd->bi_enetaddr[0]); +	put_reg (RTL8019_PHYSICALADDRESS1, bd->bi_enetaddr[1]); +	put_reg (RTL8019_PHYSICALADDRESS2, bd->bi_enetaddr[2]); +	put_reg (RTL8019_PHYSICALADDRESS3, bd->bi_enetaddr[3]); +	put_reg (RTL8019_PHYSICALADDRESS4, bd->bi_enetaddr[4]); +	put_reg (RTL8019_PHYSICALADDRESS5, bd->bi_enetaddr[5]); +	put_reg (RTL8019_MULTIADDRESS0, 0x00); +	put_reg (RTL8019_MULTIADDRESS1, 0x00); +	put_reg (RTL8019_MULTIADDRESS2, 0x00); +	put_reg (RTL8019_MULTIADDRESS3, 0x00); +	put_reg (RTL8019_MULTIADDRESS4, 0x00); +	put_reg (RTL8019_MULTIADDRESS5, 0x00); +	put_reg (RTL8019_MULTIADDRESS6, 0x00); +	put_reg (RTL8019_MULTIADDRESS7, 0x00); +	put_reg (RTL8019_CURRENT, RTL8019_PSTART); +	put_reg (RTL8019_COMMAND, RTL8019_PAGE0); +	put_reg (RTL8019_TRANSMITCONFIGURATION, 0xe0);	/*58; */ + +	return 0; +} + + +static unsigned char nic_to_pc (void) +{ +	unsigned char rec_head_status; +	unsigned char next_packet_pointer; +	unsigned char packet_length0; +	unsigned char packet_length1; +	unsigned short rxlen = 0; +	unsigned int i = 4; +	unsigned char current_point; +	unsigned char *addr; + +	/* +	 * The RTL8019's first 4B is packet status,page of next packet +	 * and packet length(2B).So we receive the fist 4B. +	 */ +	put_reg (RTL8019_REMOTESTARTADDRESS1, get_reg (RTL8019_BOUNDARY)); +	put_reg (RTL8019_REMOTESTARTADDRESS0, 0x00); +	put_reg (RTL8019_REMOTEBYTECOUNT1, 0x00); +	put_reg (RTL8019_REMOTEBYTECOUNT0, 0x04); + +	put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMARD); + +	rec_head_status = get_reg (RTL8019_DMA_DATA); +	next_packet_pointer = get_reg (RTL8019_DMA_DATA); +	packet_length0 = get_reg (RTL8019_DMA_DATA); +	packet_length1 = get_reg (RTL8019_DMA_DATA); + +	put_reg (RTL8019_COMMAND, RTL8019_PAGE0); +	/*Packet length is in two 8bit registers */ +	rxlen = packet_length1; +	rxlen = (((rxlen << 8) & 0xff00) + packet_length0); +	rxlen -= 4; + +	if (rxlen > PKTSIZE_ALIGN + PKTALIGN) +		printf ("packet too big!\n"); + +	/*Receive the packet */ +	put_reg (RTL8019_REMOTESTARTADDRESS0, 0x04); +	put_reg (RTL8019_REMOTESTARTADDRESS1, get_reg (RTL8019_BOUNDARY)); + +	put_reg (RTL8019_REMOTEBYTECOUNT0, (rxlen & 0xff)); +	put_reg (RTL8019_REMOTEBYTECOUNT1, ((rxlen >> 8) & 0xff)); + + +	put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMARD); + +	for (addr = (unsigned char *) NetRxPackets[0], i = rxlen; i > 0; i--) +		*addr++ = get_reg (RTL8019_DMA_DATA); +	/* Pass the packet up to the protocol layers. */ +	NetReceive (NetRxPackets[0], rxlen); + +	while (!(get_reg (RTL8019_INTERRUPTSTATUS)) & 0x40);	/* wait for the op. */ + +	/* +	 * To test whether the packets are all received,get the +	 * location of current point +	 */ +	put_reg (RTL8019_COMMAND, RTL8019_PAGE1); +	current_point = get_reg (RTL8019_CURRENT); +	put_reg (RTL8019_COMMAND, RTL8019_PAGE0); +	put_reg (RTL8019_BOUNDARY, next_packet_pointer); +	return current_point; +} + +/* Get a data block via Ethernet */ +extern int eth_rx (void) +{ +	unsigned char temp, current_point; + +	put_reg (RTL8019_COMMAND, RTL8019_PAGE0); + +	while (1) { +		temp = get_reg (RTL8019_INTERRUPTSTATUS); + +		if (temp & 0x90) { +			/*overflow */ +			put_reg (RTL8019_COMMAND, RTL8019_PAGE0STOP); +			udelay (2000); +			put_reg (RTL8019_REMOTEBYTECOUNT0, 0); +			put_reg (RTL8019_REMOTEBYTECOUNT1, 0); +			put_reg (RTL8019_TRANSMITCONFIGURATION, 2); +			do { +				current_point = nic_to_pc (); +			} while (get_reg (RTL8019_BOUNDARY) != current_point); + +			put_reg (RTL8019_TRANSMITCONFIGURATION, 0xe0); +		} + +		if (temp & 0x1) { +			/*packet received */ +			do { +				put_reg (RTL8019_INTERRUPTSTATUS, 0x01); +				current_point = nic_to_pc (); +			} while (get_reg (RTL8019_BOUNDARY) != current_point); +		} + +		if (!(temp & 0x1)) +			return 0; +		/* done and exit. */ +	} +} + +/* Send a data block via Ethernet. */ +extern int eth_send (volatile void *packet, int length) +{ +	volatile unsigned char *p; +	unsigned int pn; + +	pn = length; +	p = (volatile unsigned char *) packet; + +	while (get_reg (RTL8019_COMMAND) == RTL8019_TRANSMIT); + +	put_reg (RTL8019_REMOTESTARTADDRESS0, 0); +	put_reg (RTL8019_REMOTESTARTADDRESS1, RTL8019_TPSTART); +	put_reg (RTL8019_REMOTEBYTECOUNT0, (pn & 0xff)); +	put_reg (RTL8019_REMOTEBYTECOUNT1, ((pn >> 8) & 0xff)); + +	put_reg (RTL8019_COMMAND, RTL8019_REMOTEDMAWR); +	while (pn > 0) { +		put_reg (RTL8019_DMA_DATA, *p++); +		pn--; +	} + +	pn = length; + +	while (pn < 60) {	/*Padding */ +		put_reg (RTL8019_DMA_DATA, 0); +		pn++; +	} + +	while (!(get_reg (RTL8019_INTERRUPTSTATUS)) & 0x40); + +	put_reg (RTL8019_INTERRUPTSTATUS, 0x40); +	put_reg (RTL8019_TRANSMITPAGE, RTL8019_TPSTART); +	put_reg (RTL8019_TRANSMITBYTECOUNT0, (pn & 0xff)); +	put_reg (RTL8019_TRANSMITBYTECOUNT1, ((pn >> 8 & 0xff))); +	put_reg (RTL8019_COMMAND, RTL8019_TRANSMIT); + +	return 0; +} + +#endif /* COMMANDS & CFG_NET */ + +#endif /* CONFIG_DRIVER_RTL8019 */ |