[U-Boot-Users] Re: U-Boot and 64260 ethernet controller.

Arun arun at rassit.com
Tue Nov 8 15:44:17 CET 2005


hai Steve,

The major changes related to ethernet we did whas to specify the  
appropriate PHY address to the GT mii reg read/write functions so that the  
ethernet is initialized properly and communication starts and also the MAC  
address accordinly.
also you can run some applications like etherreal or sniffer to see all  
ethernet acitivity


Regards
Arun Kumar



On Tue, 08 Nov 2005 07:17:27 -0600, <sjhill at realitydiluted.com> wrote:

> Greetings Arun.
>
> Thank you so much for your reply. I have attached the hacked
> up driver, which is my current code. There is some special set
> up code due to the fact that we are using an AMD PHY with some
> errata. Regardless, I can set the IP address, do a ping and see
> an ARP go out, but the hardware will not receive any data. Any
> ideas you have would be great.
>
> -Steve
>
> /**************************************************************************
> Etherboot -  BOOTP/TFTP Bootstrap Program
> Skeleton NIC driver for Etherboot
> ***************************************************************************/
>
> /*
>  * 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, or (at
>  * your option) any later version.
>  */
>
> /*
>  * This file is a modified version from the Galileo polled mode
>  * network driver for the ethernet contained within the GT64260
>  * chip. It has been modified to fit into the U-Boot framework, from
>  * the original (etherboot) setup.  Also, additional cleanup and features
>  * were added.
>  *
>  * - Josh Huber <huber at mclx.com>
>  */
>
> #include <local.h>
> #include <common.h>
> #include <malloc.h>
> #include <galileo/gt64260R.h>
> #include <galileo/core.h>
> #include <asm/cache.h>
> #include <miiphy.h>
> #include <net.h>
> #include <local.h>
>
> #include "eth.h"
> #include "eth_addrtbl.h"
>
> #if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI)
>
> #define GT6426x_ETH_BUF_SIZE	1536
>
> /* if you like verbose output, turn this on! */
> #define DEBUG
>
> /* Restart autoneg if we detect link is up on phy init. */
>
> /*
>  * The GT doc's say that after Rst is deasserted, and the PHY
>  * reports autoneg complete, it runs through its autoneg
>  * procedures. This doesn't seem to be the case for MII
>  * PHY's. To work around this check for link up && autoneg
>  * complete when initilizing the port. If they are both set,
>  * then restart PHY autoneg. Of course, it may be something
>  * completly different.
>  */
> #ifdef CONFIG_ETHER_PORT_MII
> # define RESTART_AUTONEG
> #endif
>
> /* do this if you dont want to use snooping */
> #define USE_SOFTWARE_CACHE_MANAGEMENT
>
> #ifdef USE_SOFTWARE_CACHE_MANAGEMENT
> #define FLUSH_DCACHE(a,b)                 
> if(dcache_status()){clean_dcache_range((u32)(a),(u32)(b));}
> #define FLUSH_AND_INVALIDATE_DCACHE(a,b)  
> if(dcache_status()){flush_dcache_range((u32)(a),(u32)(b));}
> #define INVALIDATE_DCACHE(a,b)            
> if(dcache_status()){invalidate_dcache_range((u32)(a),(u32)(b));}
> #else
> /* bummer - w/o flush, nothing works, even with snooping - FIXME */
> /* #define FLUSH_DCACHE(a,b) */
> #define FLUSH_DCACHE(a,b)                 
> if(dcache_status()){clean_dcache_range((u32)(a),(u32)(b));}
> #define FLUSH_AND_INVALIDATE_DCACHE(a,b)
> #define INVALIDATE_DCACHE(a,b)
> #endif
> struct eth_dev_s {
> 	eth0_tx_desc_single *eth_tx_desc;
> 	eth0_rx_desc_single *eth_rx_desc;
> 	char *eth_tx_buffer;
> 	char *eth_rx_buffer[NR];
> 	int tdn, rdn;
> 	int dev;
> 	unsigned int reg_base;
> };
>
>
> static const char ether_port_phy_addr[3]={1,-1,3};
>
>
> static inline unsigned short
> miiphy_read_ret(unsigned short phy, unsigned short reg)
> {
>     unsigned short val;
>     miiphy_read(phy,reg,&val);
>     return val;
> }
>
>
> /**************************************************************************
> RESET - Reset adapter
> ***************************************************************************/
> void
> gt6426x_eth_reset(void *v)
> {
> 	/*  we should do something here...
> 	struct eth_device *wp = (struct eth_device *)v;
> 	struct eth_dev_s *p = wp->priv;
> 	*/
>
> 	printf ("RESET\n");
> 	/* put the card in its initial state */
> }
>
> static void gt6426x_handle_SMI(struct eth_dev_s *p, unsigned int icr)
> {
> #ifdef DEBUG
>     printf("SMI interrupt: ");
> #endif
>
>     if(icr&0x10000000) {
> #ifdef DEBUG
> 	unsigned int psr;
> 	psr = GTREGREAD(ETHERNET0_PORT_STATUS_REGISTER + p->reg_base);
> 	printf("PHY state change:\n"
> 	       "  GT:%s:%s:%s:%s\n",
> 		(psr & 1) ? "100" : " 10",
> 		(psr & 8) ? " Link" : "nLink",
> 		(psr & 2) ? "FD" : "HD",
> 		(psr & 4) ? " FC" : "nFC");
> #endif /* DEBUG */
> 	GT_REG_WRITE(ETHERNET0_SDMA_COMMAND_REGISTER + p->reg_base,
>                 ((1 << 23) | (1 << 24)));
> 	icr &= ~0x10000000;
> 	GT_REG_WRITE(ETHERNET0_INTERRUPT_CAUSE_REGISTER + p->reg_base, icr);
>     }
>
>     if(icr&0x20000000) {
> #ifdef DEBUG
> 	printf("SMI done\n");
> #endif
> 	icr &= ~0x20000000;
> 	GT_REG_WRITE(ETHERNET0_INTERRUPT_CAUSE_REGISTER + p->reg_base, icr);
>     }
> }
>
> static int
> gt6426x_eth_receive(struct eth_dev_s *p,unsigned int icr)
> {
> 	int eth_len=0;
> 	char *eth_data;
>
> 	eth0_rx_desc_single *rx=&p->eth_rx_desc[(p->rdn)];
>
> 	INVALIDATE_DCACHE((unsigned int)rx,(unsigned int)(rx+1));
> 	FLUSH_DCACHE((unsigned int)rx,(unsigned int)(rx+1));
> 	sync();
>
> 	if (rx->command_status & 0x80000000)
> 		return 0; /* No packet received */
>
> 	eth_len = (unsigned int)
> 		(rx->buff_size_byte_count) & 0x0000ffff;
> 	eth_data = (char *) p->eth_rx_buffer[p->rdn];
>
> #ifdef DEBUG
> 	if (eth_len) {
> 		printf ("%s: Recived %d byte Packet @ 0x%p\n",
> 			__FUNCTION__, eth_len, eth_data);
> 	}
> #endif
> 	/*
> 	 * packet is now in:
> 	 * eth0_rx_buffer[RDN_ETH0];
> 	 */
>
> 	/* let the upper layer handle the packet */
> 	NetReceive (eth_data, eth_len);
>
> 	rx->buff_size_byte_count = GT6426x_ETH_BUF_SIZE<<16;
>
>
> 	/* GT96100 Owner */
> 	rx->command_status = 0x80000000;
>
> 	FLUSH_DCACHE((unsigned int)rx,(unsigned int)(rx+1));
>
> 	p->rdn ++;
> 	if (p->rdn == NR) {p->rdn = 0;}
>
> 	sync();
>
> 	/* Start Rx*/
> 	GT_REG_WRITE (ETHERNET0_SDMA_COMMAND_REGISTER + p->reg_base,  
> 0x00000080);
>
> #ifdef DEBUG
> 	{
> 	    int i;
> 	    for (i=0;i<12;i++) {
> 		printf(" %02x", eth_data[i]);
> 	    }
> 	}
> 	printf(": %d bytes\n", eth_len);
> #endif
> 	INVALIDATE_DCACHE((unsigned int)eth_data,
> 		(unsigned int)eth_data+eth_len);
> 	return eth_len;
> }
>
> /**************************************************************************
> POLL - look for an rx frame, handle other conditions
> ***************************************************************************/
> int
> gt6426x_eth_poll(void *v)
> {
> 	struct eth_device *wp = (struct eth_device *)v;
> 	struct eth_dev_s *p = wp->priv;
> 	unsigned int icr = GTREGREAD(ETHERNET0_INTERRUPT_CAUSE_REGISTER +
> 		p->reg_base);
>
> 	if(icr) {
> #ifdef DEBUG
> 	    printf("poll got ICR %08x\n", icr);
> #endif
> 	    /* SMI done or PHY state change*/
> 	    if(icr&0x30000000) gt6426x_handle_SMI(p, icr);
> 	    GT_REG_WRITE(ETHERNET0_INTERRUPT_CAUSE_REGISTER +p->reg_base, 0);
> 	}
> 	/* always process. We aren't using RX interrupts */
> 	return gt6426x_eth_receive(p, icr);
> }
>
> /**************************************************************************
> TRANSMIT - Transmit a frame
> ***************************************************************************/
> int
> gt6426x_eth_transmit(void *v, volatile char *p, unsigned int s)
> {
> 	struct eth_device *wp = (struct eth_device *)v;
> 	struct eth_dev_s *dev = (struct eth_dev_s *)wp->priv;
> #ifdef DEBUG
> 	unsigned int old_command_stat,old_psr;
> #endif
> 	eth0_tx_desc_single *tx=&dev->eth_tx_desc[dev->tdn];
>
> 	/* wait for tx to be ready */
> 	INVALIDATE_DCACHE((unsigned int)tx,(unsigned int)(tx+1));
> 	while (tx->command_status & 0x80000000) {
> 	    int i;
> 	    for(i=0;i<1000;i++);
> 			INVALIDATE_DCACHE((unsigned int)tx,(unsigned int)(tx+1));
> 	}
>
> 	sync();
> 	GT_REG_WRITE (ETHERNET0_CURRENT_TX_DESCRIPTOR_POINTER0 + dev->reg_base,
> 		      (unsigned int)tx);
>
> #ifdef DEBUG
> 	printf("copying to tx_buffer [%p], length %x, desc = %p\n",
> 	       dev->eth_tx_buffer, s, dev->eth_tx_desc);
> #endif
> 	memcpy(dev->eth_tx_buffer, (char *) p, s);
>
> 	tx->buff_pointer = dev->eth_tx_buffer;
> 	tx->bytecount_reserved = ((__u16)s) << 16;
> 	sync();
>
> 	/*    31 - own
> 	 *    22 - gencrc
> 	 * 18:16 - pad, last, first */
> 	tx->command_status = (1<<31) | (1<<22) | (7<<16);
> #if 0
> 	/* FEr #18 */
> 	tx->next_desc = NULL;
> #else
> 	tx->next_desc =
> 		(struct eth0_tx_desc_struct *)
> 		&dev->eth_tx_desc[(dev->tdn+1)%NT].bytecount_reserved;
>
> 	/* cpu owned */
> 	dev->eth_tx_desc[(dev->tdn+1)%NT].command_status = (7<<16);	/* pad,  
> last, first */
> 	sync();
> #endif
>
> #ifdef DEBUG
> 	old_command_stat=tx->command_status,
> 	old_psr=GTREGREAD(ETHERNET0_PORT_STATUS_REGISTER + dev->reg_base);
> 	sync();
> #endif
>
> 	FLUSH_DCACHE((unsigned int)tx,
> 		(unsigned int)&dev->eth_tx_desc[(dev->tdn+2)%NT]);
>
> 	FLUSH_DCACHE((unsigned int)dev->eth_tx_buffer,(unsigned  
> int)dev->eth_tx_buffer+s);
>
> 	sync();
> 	//GT_REG_WRITE(ETHERNET0_SDMA_COMMAND_REGISTER + dev->reg_base,  
> 0x01000000);
> 	GT_REG_WRITE(ETHERNET0_SDMA_COMMAND_REGISTER + dev->reg_base,
>                 ((1 << 23) | (1 << 24)));
>
> #ifdef DEBUG
> 	{
> 	    unsigned int command_stat=0;
> 	    printf("cmd_stat: %08x PSR: %08x\n", old_command_stat, old_psr);
> 	    /* wait for tx to be ready */
> 	    do {
> 		unsigned int psr=GTREGREAD(ETHERNET0_PORT_STATUS_REGISTER  
> + dev->reg_base);
> 	sync();
> 		command_stat=tx->command_status;
> 		if(command_stat!=old_command_stat || psr !=old_psr) {
> 		    printf("cmd_stat: %08x PSR: %08x\n", command_stat, psr);
> 		    old_command_stat = command_stat;
> 		    old_psr = psr;
> 		}
> 		/* gt6426x_eth0_poll(); */
> FLUSH_DCACHE((unsigned int)tx, (unsigned  
> int)&dev->eth_tx_desc[(dev->tdn+2)%NT]);
> FLUSH_DCACHE((unsigned int)dev->eth_tx_buffer,(unsigned  
> int)dev->eth_tx_buffer+s);
> 	INVALIDATE_DCACHE((unsigned int)tx,(unsigned int)(tx+1));
> 	    } while (command_stat & 0x80000000);
>
> 	    printf("sent %d byte frame\n", s);
>
> 	    if((command_stat & (3<<15)) == 3) {
> 		printf("frame had error (stat=%08x)\n", command_stat);
> 	    }
> 	}
> #endif
> 	return 0;
> }
>
> /**************************************************************************
> DISABLE - Turn off ethernet interface
> ***************************************************************************/
> void
> gt6426x_eth_disable(void *v)
> {
> 	struct eth_device *wp = (struct eth_device *)v;
> 	struct eth_dev_s *p = (struct eth_dev_s *)wp->priv;
>
> 	GT_REG_WRITE(ETHERNET0_SDMA_COMMAND_REGISTER + p->reg_base, 0x80008000);
> }
>
> /**************************************************************************
> MII utilities - write: write to an MII register via SMI
> ***************************************************************************/
> int
> miiphy_write(unsigned char phy, unsigned char reg,
>     unsigned short data)
> {
>     unsigned int temp= (reg<<21) | (phy<<16) | data;
>
>     while(GTREGREAD(ETHERNET_SMI_REGISTER) & (1<<28));	/* wait for !Busy  
> */
>
>     GT_REG_WRITE(ETHERNET_SMI_REGISTER, temp);
>     return 0;
> }
>
> /**************************************************************************
> MII utilities - read: read from an MII register via SMI
> ***************************************************************************/
> int
> miiphy_read(unsigned char phy, unsigned char reg,
> 			unsigned short *val)
> {
>     unsigned int temp= (reg<<21) | (phy<<16) | 1<<26;
>
>     while(GTREGREAD(ETHERNET_SMI_REGISTER) & (1<<28));	/* wait for !Busy  
> */
>
>     GT_REG_WRITE(ETHERNET_SMI_REGISTER, temp);
>
>     while(1) {
> 	temp=GTREGREAD(ETHERNET_SMI_REGISTER);
> 	if(temp & (1<<27)) break;		/* wait for ReadValid */
>     }
>     *val = temp & 0xffff;
>
>     return 0;
> }
>
> #ifdef DEBUG
> /**************************************************************************
> MII utilities - dump mii registers
> ***************************************************************************/
> static void
> gt6426x_dump_mii(bd_t *bis, unsigned short phy)
> {
> 	printf("mii reg 0 - 3:   %04x %04x %04x %04x\n",
> 		miiphy_read_ret(phy, 0x0),
> 		miiphy_read_ret(phy, 0x1),
> 		miiphy_read_ret(phy, 0x2),
> 		miiphy_read_ret(phy, 0x3)
> 		);
> 	printf("        4 - 7:   %04x %04x %04x %04x\n",
> 		miiphy_read_ret(phy, 0x4),
> 		miiphy_read_ret(phy, 0x5),
> 		miiphy_read_ret(phy, 0x6),
> 		miiphy_read_ret(phy, 0x7)
> 		);
> 	printf("        8:       %04x\n",
> 		miiphy_read_ret(phy, 0x8)
> 		);
> 	printf("        16-19:   %04x %04x %04x %04x\n",
> 		miiphy_read_ret(phy, 0x10),
> 		miiphy_read_ret(phy, 0x11),
> 		miiphy_read_ret(phy, 0x12),
> 		miiphy_read_ret(phy, 0x13)
> 		);
> 	printf("        20,30:   %04x %04x\n",
> 		miiphy_read_ret(phy, 20),
> 		miiphy_read_ret(phy, 30)
> 		);
> }
> #endif
>
> #ifdef RESTART_AUTONEG
>
> /* If link is up && autoneg compleate, and if
>  * GT and PHY disagree about link capabilitys,
>  * restart autoneg - something screwy with FD/HD
>  * unless we do this. */
> static void
> check_phy_state(struct eth_dev_s *p)
> {
> 	int bmsr = miiphy_read_ret(ether_port_phy_addr[p->dev], PHY_BMSR);
> 	int psr = GTREGREAD(ETHERNET0_PORT_STATUS_REGISTER + p->reg_base);
>
> 	if ((psr & 1<<3) && (bmsr & PHY_BMSR_LS)) {
> 		int nego = miiphy_read_ret(ether_port_phy_addr[p->dev],
> 			PHY_ANAR) & miiphy_read_ret(ether_port_phy_addr[p->dev],
> 			 PHY_ANLPAR);
> 		int want;
>
> 		if (nego & PHY_ANLPAR_TXFD) {
> 			want = 0x3;
> 			printf("MII: 100Base-TX, Full Duplex\n");
> 		} else if (nego & PHY_ANLPAR_TX) {
> 			want = 0x1;
> 			printf("MII: 100Base-TX, Half Duplex\n");
> 		} else if (nego & PHY_ANLPAR_10FD) {
> 			want = 0x2;
> 			printf("MII: 10Base-T, Full Duplex\n");
> 		} else if (nego & PHY_ANLPAR_10) {
> 			want = 0x0;
> 			printf("MII: 10Base-T, Half Duplex\n");
> 		} else {
> 			printf("MII: Unknown link-foo! %x\n", nego);
> 			return;
> 		}
>
> 		if ((psr & 0x3) != want) {
> 			printf("MII: GT thinks %x, PHY thinks %x, restarting autoneg..\n",
> 					psr & 0x3, want);
> 			miiphy_write(ether_port_phy_addr[p->dev],0,
> 					miiphy_read_ret(ether_port_phy_addr[p->dev],0) | (1<<9));
> 			udelay(10000);	/* the EVB's GT takes a while to notice phy
> 					   went down and up */
> 		}
> 	}
> }
> #endif
>
> /**************************************************************************
> PROBE - Look for an adapter, this routine's visible to the outside
> ***************************************************************************/
> int
> gt6426x_eth_probe(void *v, bd_t *bis)
> {
> 	struct eth_device *wp = (struct eth_device *)v;
> 	struct eth_dev_s *p = (struct eth_dev_s *)wp->priv;
> 	int dev = p->dev;
> 	unsigned int reg_base = p->reg_base;
> 	unsigned long temp;
> 	int i;
>
> 	if (( dev < 0 ) || ( dev >= GAL_ETH_DEVS ))
> 	{	/* This should never happen */
> 		printf("%s: Invalid device %d\n", __FUNCTION__, dev );
> 		return 0;
> 	}
>
> #ifdef DEBUG
> 	printf ("%s: initializing %s\n", __FUNCTION__, wp->name );
> 	printf ("\nCOMM_CONTROL = %08x , COMM_CONF = %08x\n",
> 		GTREGREAD(COMM_UNIT_ARBITER_CONTROL),
> 		GTREGREAD(COMM_UNIT_ARBITER_CONFIGURATION_REGISTER));
> #endif
>
> 	/* clear MIB counters */
> 	for(i=0;i<255; i++)
> 	    temp=GTREGREAD(ETHERNET0_MIB_COUNTER_BASE + reg_base + i);
>
> 	/* 13:12 -   10: 4x64bit burst	(cache line size = 32 bytes)
> 	 *    9  -    1: RIFB - interrupt on frame boundaries only
> 	 *  6:7  -   00: big endian rx and tx
> 	 *  5:2  - 1111: 15 retries */
> 	GT_REG_WRITE(ETHERNET0_SDMA_CONFIGURATION_REGISTER + reg_base,
> 		(2<<12) | (1<<9) | (0xf<<2) );			/* 2440 */
>
> #ifndef USE_SOFTWARE_CACHE_MANAGEMENT
> 	/* enable rx/tx desc/buffer cache snoop */
> 	GT_REG_READ(ETHERNET_0_ADDRESS_CONTROL_LOW + dev*0x20,
> 		&temp);						/* f200 */
> 	temp|= (1<<6)| (1<<14)| (1<<22)| (1<<30);
> 	GT_REG_WRITE(ETHERNET_0_ADDRESS_CONTROL_LOW + dev*0x20,
> 		temp);
> #endif
>
> 	/* 31  28 27  24 23  20 19  16
> 	 *  0000   0000   0001   1100 	[001c]
> 	 * 15  12 11  8   7  4   3  0
> 	 *  0000   1111   1100   0000	[0fc0]
> 	 *    20 - 0=MII      1=RMII
> 	 *    19 - 0=autoneg  1=disable autoneg
> 	 *    18 - 1=100Mb    0=10Mb
> 	 * 15:14 - framesize 1536 (GT6426x_ETH_BUF_SIZE)
> 	 *    11 - 0=force link pass  1=do not force link pass
> 	 *    10 - 0=fctl autoneg     1=disable fctl autoneg
> 	 *     9 - 0=dupl autoneg     1=disable dupl autoneg
> 	 *     8 - 0=no pkt override  1=pkt override
> 	 *   7:6 - 00=lowest priority 11=highest priority
> 	 */
>  	temp = 0x001c0fc0;
>
> 	/* 2408 */
> 	GT_REG_WRITE(ETHERNET0_PORT_CONFIGURATION_EXTEND_REGISTER + reg_base,
> 	     temp);
>
> 	/* 31  28 27  24 23  20 19  16
> 	 *  0000   0000   0000   0000 	[0000]
> 	 * 15  12 11  8   7  4   3  0
> 	 *  1100   0000   1000   0001	[c081]
> 	 *    15 - 0=half duplex   1=full duplex
> 	 *    14 - 0=enable hash   1=disable hash
> 	 *     7 - 0=disable port  1=enable port
> 	 *     0 - 0=normal mode   1=promiscuous mode
> 	 */
>  	temp = 0x0000c081;
>
> #ifdef CONFIG_GT_USE_MAC_HASH_TABLE
> 	temp &= ~(1<<0);	/* disable promiscuous mode */
> 	temp &= ~(1<<14);	/* enable hash table */
> 	temp |= (1<<12);	/* hash size 1/2k */
> #endif
>
> 	/* 2400 */
> 	GT_REG_WRITE(ETHERNET0_PORT_CONFIGURATION_REGISTER + reg_base, temp);
>
> #ifdef RESTART_AUTONEG
> 	check_phy_state(p);
> #endif
>
> 	printf("%s: Waiting for link up..\n", wp->name);
> 	temp = 10 * 1000;
> 	/* wait for link back up */
> 	while(!(GTREGREAD(ETHERNET0_PORT_STATUS_REGISTER + reg_base) & 8)
> 			&& (--temp > 0)){
> 	    udelay(1000);	/* wait 1 ms */
> 	}
> 	if ( temp == 0) {
> 		printf("%s: Failed!\n", wp->name);
> 		return (0);
> 	}
>
> 	printf("%s: OK!\n", wp->name);
>
> 	p->tdn = 0;
> 	p->rdn = 0;
> 	p->eth_tx_desc[p->tdn].command_status = 0;
>
> 	/* Initialize Rx Side */
> 	for (temp = 0; temp < NR; temp++) {
> 		p->eth_rx_desc[temp].buff_pointer = p->eth_rx_buffer[temp];
> 		p->eth_rx_desc[temp].buff_size_byte_count = GT6426x_ETH_BUF_SIZE<<16;
>
> 		/* GT96100 Owner */
> 		p->eth_rx_desc[temp].command_status = 0x80000000;
> 		p->eth_rx_desc[temp].next_desc =
> 			(struct eth0_rx_desc_struct *)
> 			&p->eth_rx_desc[(temp+1)%NR].buff_size_byte_count;
> 	}
>
> 	FLUSH_DCACHE((unsigned int)&p->eth_tx_desc[0],
> 		     (unsigned int)&p->eth_tx_desc[NR]);
> 	FLUSH_DCACHE((unsigned int)&p->eth_rx_desc[0],
> 		     (unsigned int)&p->eth_rx_desc[NR]);
>
> 	GT_REG_WRITE(ETHERNET0_CURRENT_TX_DESCRIPTOR_POINTER0 + reg_base,
> 		      (unsigned int) p->eth_tx_desc);
> 	GT_REG_WRITE(ETHERNET0_FIRST_RX_DESCRIPTOR_POINTER0 + reg_base,
> 		      (unsigned int) p->eth_rx_desc);
> 	GT_REG_WRITE(ETHERNET0_CURRENT_RX_DESCRIPTOR_POINTER0 + reg_base,
> 		      (unsigned int) p->eth_rx_desc);
>
> #ifdef DEBUG
> 	printf ("\nRx descriptor pointer is %08x %08x\n",
> 		GTREGREAD(ETHERNET0_FIRST_RX_DESCRIPTOR_POINTER0 + reg_base),
> 		GTREGREAD(ETHERNET0_CURRENT_RX_DESCRIPTOR_POINTER0 + reg_base));
> 	printf ("\n\n%08x %08x\n",
> 		(unsigned int)p->eth_rx_desc,p->eth_rx_desc[0].command_status);
>
> 	printf ("Descriptor dump:\n");
> 	printf ("cmd status: %08x\n",p->eth_rx_desc[0].command_status);
> 	printf ("byte_count: %08x\n",p->eth_rx_desc[0].buff_size_byte_count);
> 	printf ("buff_ptr: %08x\n",(unsigned  
> int)p->eth_rx_desc[0].buff_pointer);
> 	printf ("next_desc: %08x\n\n",(unsigned  
> int)p->eth_rx_desc[0].next_desc);
> 	printf ("%08x\n",*(unsigned int *) ((unsigned int)p->eth_rx_desc  
> + 0x0));
> 	printf ("%08x\n",*(unsigned int *) ((unsigned int)p->eth_rx_desc  
> + 0x4));
> 	printf ("%08x\n",*(unsigned int *) ((unsigned int)p->eth_rx_desc  
> + 0x8));
> 	printf ("%08x\n\n",
> 		*(unsigned int *) ((unsigned int)p->eth_rx_desc + 0xc));
> #endif
>
> #ifdef DEBUG
> 	gt6426x_dump_mii(bis,ether_port_phy_addr[p->dev]);
> #endif
>
> #ifdef CONFIG_GT_USE_MAC_HASH_TABLE
> 	{
> 		unsigned int hashtable_base;
> 	    u8 *b = (u8 *)(wp->enetaddr);
> 		u32 macH, macL;
>
> 		/* twist the MAC up into the way the discovery wants it */
> 		macH= (b[0]<<8) | b[1];
> 	    macL= (b[2]<<24) | (b[3]<<16) | (b[4]<<8) | b[5];
>
> 	    /* mode 0, size 0x800 */
> 	    hashtable_base =initAddressTable(dev,0,1);
>
> 	    if(!hashtable_base) {
> 			printf("initAddressTable failed\n");
> 			return 0;
> 	    }
>
> 	    addAddressTableEntry(dev, macH, macL, 1, 0);
> 	    GT_REG_WRITE(ETHERNET0_HASH_TABLE_POINTER_REGISTER + reg_base,
> 		    hashtable_base);
> 	}
> #endif
>
> 	/* Start Rx*/
> 	GT_REG_WRITE(ETHERNET0_SDMA_COMMAND_REGISTER + reg_base, 0x00000080);
> 	printf("%s: gt6426x eth device %d init success \n", wp->name, dev );
> 	return 1;
> }
>
> /* enter all the galileo ethernet devs into MULTI-BOOT */
> void
> gt6426x_eth_initialize(bd_t *bis)
> {
> 	struct eth_device *dev;
> 	struct eth_dev_s *p;
> 	int devnum, x, temp;
> 	char *s, *e, buf[64];
>
> #ifdef DEBUG
> 	printf( "\n%s\n", __FUNCTION__ );
> #endif
>
> 	/* Redefine PHY addresses */
> 	GT_REG_WRITE(ETHERNET_PHY_ADDRESS_REGISTER,		/* 2000 */
> 		((3 << 10) | (0 << 5) | 1));
>
> 	/* Set up routing registers */
> 	GT_REG_WRITE(MAIN_ROUTING_REGISTER, 0x7ffe38);		/* b400 */
>
> 	/* MPSC0, MPSC1, RMII */
> 	GT_REG_WRITE(SERIAL_PORT_MULTIPLEX, 0x1102);		/* f010 */
>
> 	for (devnum = 0; devnum < GAL_ETH_DEVS; devnum++) {
> 		dev = calloc(sizeof(*dev), 1);
> 		if (!dev) {
> 			printf( "%s: gal_enet%d allocation failure, %s\n",
> 					__FUNCTION__, devnum, "eth_device structure");
> 			return;
> 		}
>
> 		/* Initialize PHY to be:
> 		 *			   100Mb
> 		 *			   Full duplex
> 		 *			   Autonegotation disabled
> 		 *			   Normal operation
> 		 */
> 		miiphy_write(ether_port_phy_addr[devnum], PHY_BMCR,
> 			(PHY_BMCR_100MB | PHY_BMCR_DPLX));
>
> 		/* must be less than NAMESIZE (16) */
> 		sprintf(dev->name, "gal_enet%d", devnum);
>
> #ifdef DEBUG
> 		printf( "Initializing %s\n", dev->name );
> #endif
>
> 		/* Extract the MAC address from the environment */
> 		switch (devnum)
> 		{
> 			case 0: s = "ethaddr"; break;
>
> 			case 1: s = "eth1addr";	break;
>
> 			case 2: s = "eth2addr";	break;
>
> 			default: /* this should never happen */
> 				printf( "%s: Invalid device number %d\n",
> 						__FUNCTION__, devnum );
> 				return;
> 		}
>
> 		temp = getenv_r (s, buf, sizeof(buf));
> 		s = (temp > 0) ? buf : NULL;
>
> #ifdef DEBUG
> 		printf ("Setting MAC %d to %s\n", devnum, s );
> #endif
> 		for (x = 0; x < 6; ++x) {
> 			dev->enetaddr[x] = s ? simple_strtoul(s, &e, 16) : 0;
> 			if (s)
> 				s = (*e) ? e+1 : e;
> 		}
>
> 		dev->init = (void*)gt6426x_eth_probe;
> 		dev->halt = (void*)gt6426x_eth_reset;
> 		dev->send = (void*)gt6426x_eth_transmit;
> 		dev->recv = (void*)gt6426x_eth_poll;
>
> 		dev->priv = calloc( sizeof(*p), 1 );
> 		p = (struct eth_dev_s *) dev->priv;
> 		if (!p)
> 		{
> 			printf( "%s: %s allocation failure, %s\n",
> 					__FUNCTION__, dev->name, "Private Device Structure");
> 			free(dev);
> 			return;
> 		}
>
> 		p->dev = devnum;
> 		p->tdn=0;
> 		p->rdn=0;
> 		p->reg_base = devnum * ETHERNET_PORTS_DIFFERENCE_OFFSETS;
>
> 		p->eth_tx_desc =
> 			(eth0_tx_desc_single *)
> 			(((unsigned int) malloc(sizeof (eth0_tx_desc_single) *
> 						(NT+1)) & 0xfffffff0) + 0x10);
> 		if (!p)
> 		{
> 			printf( "%s: %s allocation failure, %s\n",
> 					__FUNCTION__, dev->name, "Tx Descriptor");
> 			free(dev);
> 			return;
> 		}
>
> 		p->eth_rx_desc =
> 			(eth0_rx_desc_single *)
> 			(((unsigned int) malloc(sizeof (eth0_rx_desc_single) *
> 						(NR+1)) & 0xfffffff0) + 0x10);
> 		if (!p->eth_rx_desc)
> 		{
> 			printf( "%s: %s allocation failure, %s\n",
> 					__FUNCTION__, dev->name, "Rx Descriptor");
> 			free(dev);
> 			free(p);
> 			return;
> 		}
>
> 		p->eth_tx_buffer =
> 			(char *) (((unsigned int) malloc(GT6426x_ETH_BUF_SIZE) & 0xfffffff0)  
> + 0x10);
> 		if (!p->eth_tx_buffer)
> 		{
> 			printf( "%s: %s allocation failure, %s\n",
> 					__FUNCTION__, dev->name, "Tx Bufffer");
> 			free(dev);
> 			free(p);
> 			free(p->eth_rx_desc);
> 			return;
> 		}
>
> 		for (temp = 0 ; temp < NR ; temp ++) {
> 			p->eth_rx_buffer[temp] =
> 				(char *)
> 				(((unsigned int) malloc(GT6426x_ETH_BUF_SIZE) & 0xfffffff0) + 0x10);
> 			if (!p->eth_rx_buffer[temp])
> 			{
> 				printf( "%s: %s allocation failure, %s\n",
> 						__FUNCTION__, dev->name, "Rx Buffers");
> 				free(dev);
> 				free(p);
> 				free(p->eth_tx_buffer);
> 				free(p->eth_rx_desc);
> 				free(p->eth_tx_desc);
> 				while (temp >= 0)
> 					free(p->eth_rx_buffer[--temp]);
> 				return;
> 			}
> 		}
>
>
> 		eth_register(dev);
> 	}
> }
> #endif /* CFG_CMD_NET && CONFIG_NET_MULTI */
> /*
>  * (C) Copyright 2001
>  * Josh Huber <huber at mclx.com>, Mission Critical Linux, Inc.
>  *
>  * 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
>  */
>
> /*
>  * eth.h - header file for the polled mode GT ethernet driver
>  */
>
> #ifndef __GT6426x_ETH_H__
> #define __GT6426x_ETH_H__
>
> #include <asm/types.h>
> #include <asm/io.h>
> #include <asm/byteorder.h>
> #include <common.h>
>
> typedef struct eth0_tx_desc_struct {
> 	volatile __u32 bytecount_reserved;
> 	volatile __u32 command_status;
> 	volatile struct eth0_tx_desc_struct * next_desc;
> 	/* Note - the following will not work for 64 bit addressing */
> 	volatile unsigned char * buff_pointer;
> } eth0_tx_desc_single;
>
> typedef struct eth0_rx_desc_struct {
>   volatile __u32 buff_size_byte_count;
>   volatile __u32 command_status;
>   volatile struct eth0_rx_desc_struct * next_desc;
>   volatile unsigned char * buff_pointer;
> } eth0_rx_desc_single;
>
> #define NT 20 /* Number of Transmit buffers */
> #define NR 20 /* Number of Receive buffers */
> #define MAX_BUFF_SIZE (1536+2*CACHE_LINE_SIZE) /* 1600 */
> #define ETHERNET_PORTS_DIFFERENCE_OFFSETS 0x400
>
> unsigned long TDN_ETH0 , RDN_ETH0; /* Rx/Tx current Descriptor Number*/
> unsigned int EVB64260_ETH0_irq;
>
> #define CLOSED 0
> #define OPENED 1
>
> #define PORT_ETH0 0
>
> extern eth0_tx_desc_single *eth0_tx_desc;
> extern eth0_rx_desc_single *eth0_rx_desc;
> extern char *eth0_tx_buffer;
> extern char *eth0_rx_buffer[NR];
> extern char *eth_data;
>
> extern int gt6426x_eth_poll(void *v);
> extern int gt6426x_eth_transmit(void *v, volatile char *p, unsigned int  
> s);
> extern void gt6426x_eth_disable(void *v);
> extern int gt6426x_eth_probe(void *v, bd_t *bis);
>
> #endif  /* __GT64260x_ETH_H__ */
>



-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/m2/





More information about the U-Boot mailing list