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

sjhill at realitydiluted.com sjhill at realitydiluted.com
Tue Nov 8 14:17:27 CET 2005


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__ */





More information about the U-Boot mailing list