diff options
| author | Ben Warren <biggerbadderben@gmail.com> | 2009-08-25 13:09:37 -0700 | 
|---|---|---|
| committer | Ben Warren <biggerbadderben@gmail.com> | 2009-08-25 13:35:54 -0700 | 
| commit | b1c0eaac110bc919e5b4e88821348e714493f266 (patch) | |
| tree | 83afd97b738803932cef748fd4de3e82e4ef259a /drivers/net/cs8900.c | |
| parent | d47628a6ecf80cd4584a50b6c795b90c985a48e5 (diff) | |
| download | olio-uboot-2014.01-b1c0eaac110bc919e5b4e88821348e714493f266.tar.xz olio-uboot-2014.01-b1c0eaac110bc919e5b4e88821348e714493f266.zip | |
Convert CS8900 Ethernet driver to CONFIG_NET_MULTI API
All in-tree boards that use this controller have CONFIG_NET_MULTI added
Also:
  - changed CONFIG_DRIVER_CS8900 to CONFIG_CS8900
  - changed CS8900_BASE to CONFIG_CS8900_BASE
  - changed CS8900_BUS?? to CONFIG_CS8900_BUS??
  - cleaned up line lengths
  - modified VCMA9 command function that accesses the device
  - removed MAC address initialization from lib_arm/board.c
Signed-off-by: Ben Warren <biggerbadderben@gmail.com>
Tested-by: Wolfgang Denk <wd@denx.de>
Acked-by: Wolfgang Denk <wd@denx.de>
Diffstat (limited to 'drivers/net/cs8900.c')
| -rw-r--r-- | drivers/net/cs8900.c | 272 | 
1 files changed, 160 insertions, 112 deletions
| diff --git a/drivers/net/cs8900.c b/drivers/net/cs8900.c index 5e2b3b080..587f7f62a 100644 --- a/drivers/net/cs8900.c +++ b/drivers/net/cs8900.c @@ -1,6 +1,9 @@  /*   * Cirrus Logic CS8900A Ethernet   * + * (C) 2009 Ben Warren , biggerbadderben@gmail.com + *     Converted to use CONFIG_NET_MULTI API + *   * (C) 2003 Wolfgang Denk, wd@denx.de   *     Extension to synchronize ethaddr environment variable   *     against value in EEPROM @@ -38,220 +41,229 @@  #include <common.h>  #include <command.h> -#include "cs8900.h" +#include <asm/io.h>  #include <net.h> +#include <malloc.h> +#include "cs8900.h"  #undef DEBUG  /* packet page register access functions */ -#ifdef CS8900_BUS32 +#ifdef CONFIG_CS8900_BUS32 + +#define REG_WRITE(v, a) writel((v),(a)) +#define REG_READ(a) readl((a)) +  /* we don't need 16 bit initialisation on 32 bit bus */  #define get_reg_init_bus(x) get_reg((x)) +  #else -static unsigned short get_reg_init_bus (int regno) + +#define REG_WRITE(v, a) writew((v),(a)) +#define REG_READ(a) readw((a)) + +static u16 get_reg_init_bus(struct eth_device *dev, int regno)  {  	/* force 16 bit busmode */ -	volatile unsigned char c; +	volatile u8 c; +	struct cs8900_priv *priv = (struct cs8900_priv *)(dev->priv); +	uint8_t volatile * const iob = (uint8_t volatile * const)dev->iobase; -	c = CS8900_BUS16_0; -	c = CS8900_BUS16_1; -	c = CS8900_BUS16_0; -	c = CS8900_BUS16_1; -	c = CS8900_BUS16_0; +	c = readb(iob); +	c = readb(iob + 1); +	c = readb(iob); +	c = readb(iob + 1); +	c = readb(iob); -	CS8900_PPTR = regno; -	return CS8900_PDATA; +	REG_WRITE(regno, &priv->regs->pptr); +	return REG_READ(&priv->regs->pdata);  }  #endif -static unsigned short get_reg (int regno) +static u16 get_reg(struct eth_device *dev, int regno)  { -	CS8900_PPTR = regno; -	return CS8900_PDATA; +	struct cs8900_priv *priv = (struct cs8900_priv *)(dev->priv); +	REG_WRITE(regno, &priv->regs->pptr); +	return REG_READ(&priv->regs->pdata);  } -static void put_reg (int regno, unsigned short val) +static void put_reg(struct eth_device *dev, int regno, u16 val)  { -	CS8900_PPTR = regno; -	CS8900_PDATA = val; +	struct cs8900_priv *priv = (struct cs8900_priv *)(dev->priv); +	REG_WRITE(regno, &priv->regs->pptr); +	REG_WRITE(val, &priv->regs->pdata);  } -static void eth_reset (void) +static void cs8900_reset(struct eth_device *dev)  {  	int tmo; -	unsigned short us; +	u16 us;  	/* reset NIC */ -	put_reg (PP_SelfCTL, get_reg (PP_SelfCTL) | PP_SelfCTL_Reset); +	put_reg(dev, PP_SelfCTL, get_reg(dev, PP_SelfCTL) | PP_SelfCTL_Reset);  	/* wait for 200ms */ -	udelay (200000); +	udelay(200000);  	/* Wait until the chip is reset */ -	tmo = get_timer (0) + 1 * CONFIG_SYS_HZ; -	while ((((us = get_reg_init_bus (PP_SelfSTAT)) & PP_SelfSTAT_InitD) == 0) -		   && tmo < get_timer (0)) +	tmo = get_timer(0) + 1 * CONFIG_SYS_HZ; +	while ((((us = get_reg_init_bus(dev, PP_SelfSTAT)) & +		PP_SelfSTAT_InitD) == 0) && tmo < get_timer(0))  		/*NOP*/;  } -static void eth_reginit (void) +static void cs8900_reginit(struct eth_device *dev)  {  	/* receive only error free packets addressed to this card */ -	put_reg (PP_RxCTL, PP_RxCTL_IA | PP_RxCTL_Broadcast | PP_RxCTL_RxOK); +	put_reg(dev, PP_RxCTL, +		PP_RxCTL_IA | PP_RxCTL_Broadcast | PP_RxCTL_RxOK);  	/* do not generate any interrupts on receive operations */ -	put_reg (PP_RxCFG, 0); +	put_reg(dev, PP_RxCFG, 0);  	/* do not generate any interrupts on transmit operations */ -	put_reg (PP_TxCFG, 0); +	put_reg(dev, PP_TxCFG, 0);  	/* do not generate any interrupts on buffer operations */ -	put_reg (PP_BufCFG, 0); +	put_reg(dev, PP_BufCFG, 0);  	/* enable transmitter/receiver mode */ -	put_reg (PP_LineCTL, PP_LineCTL_Rx | PP_LineCTL_Tx); +	put_reg(dev, PP_LineCTL, PP_LineCTL_Rx | PP_LineCTL_Tx);  } -void cs8900_get_enetaddr (void) +void cs8900_get_enetaddr(struct eth_device *dev)  {  	int i; -	uchar enetaddr[6]; - -	/* if the env is setup, then bail */ -	if (eth_getenv_enetaddr("ethaddr", enetaddr)) -		return;  	/* verify chip id */ -	if (get_reg_init_bus (PP_ChipID) != 0x630e) +	if (get_reg_init_bus(dev, PP_ChipID) != 0x630e)  		return; -	eth_reset (); -	if ((get_reg (PP_SelfSTAT) & (PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) == -			(PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) { +	cs8900_reset(dev); +	if ((get_reg(dev, PP_SelfSTAT) & +		(PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) == +		(PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) {  		/* Load the MAC from EEPROM */ -		for (i = 0; i < 6 / 2; i++) { -			unsigned int Addr; +		for (i = 0; i < 3; i++) { +			u32 Addr; -			Addr = get_reg (PP_IA + i * 2); -			enetaddr[i * 2] = Addr & 0xFF; -			enetaddr[i * 2 + 1] = Addr >> 8; +			Addr = get_reg(dev, PP_IA + i * 2); +			dev->enetaddr[i * 2] = Addr & 0xFF; +			dev->enetaddr[i * 2 + 1] = Addr >> 8;  		} - -		eth_setenv_enetaddr("ethaddr", enetaddr); -		debug("### Set environment from HW MAC addr = \"%pM\"\n", enetaddr);  	}  } -void eth_halt (void) +void cs8900_halt(struct eth_device *dev)  {  	/* disable transmitter/receiver mode */ -	put_reg (PP_LineCTL, 0); +	put_reg(dev, PP_LineCTL, 0);  	/* "shutdown" to show ChipID or kernel wouldn't find he cs8900 ... */ -	get_reg_init_bus (PP_ChipID); +	get_reg_init_bus(dev, PP_ChipID);  } -int eth_init (bd_t * bd) +static int cs8900_init(struct eth_device *dev, bd_t * bd)  { -	uchar enetaddr[6]; +	uchar *enetaddr = dev->enetaddr; +	u16 id;  	/* verify chip id */ -	if (get_reg_init_bus (PP_ChipID) != 0x630e) { -		printf ("CS8900 Ethernet chip not found?!\n"); -		return 0; +	id = get_reg_init_bus(dev, PP_ChipID); +	if (id != 0x630e) { +		printf ("CS8900 Ethernet chip not found: " +			"ID=0x%04x instead 0x%04x\n", id, 0x630e); +		return 1;  	} -	eth_reset (); +	cs8900_reset (dev);  	/* set the ethernet address */ -	eth_getenv_enetaddr("ethaddr", enetaddr); -	put_reg (PP_IA + 0, enetaddr[0] | (enetaddr[1] << 8)); -	put_reg (PP_IA + 2, enetaddr[2] | (enetaddr[3] << 8)); -	put_reg (PP_IA + 4, enetaddr[4] | (enetaddr[5] << 8)); +	put_reg(dev, PP_IA + 0, enetaddr[0] | (enetaddr[1] << 8)); +	put_reg(dev, PP_IA + 2, enetaddr[2] | (enetaddr[3] << 8)); +	put_reg(dev, PP_IA + 4, enetaddr[4] | (enetaddr[5] << 8)); -	eth_reginit (); +	cs8900_reginit(dev);  	return 0;  }  /* Get a data block via Ethernet */ -int eth_rx (void) +static int cs8900_recv(struct eth_device *dev)  {  	int i; -	unsigned short rxlen; -	unsigned short *addr; -	unsigned short status; +	u16 rxlen; +	u16 *addr; +	u16 status; -	status = get_reg (PP_RER); +	struct cs8900_priv *priv = (struct cs8900_priv *)(dev->priv); + +	status = get_reg(dev, PP_RER);  	if ((status & PP_RER_RxOK) == 0)  		return 0; -	status = CS8900_RTDATA;		/* stat */ -	rxlen = CS8900_RTDATA;		/* len */ +	status = REG_READ(&priv->regs->rtdata); +	rxlen = REG_READ(&priv->regs->rtdata); -#ifdef DEBUG  	if (rxlen > PKTSIZE_ALIGN + PKTALIGN) -		printf ("packet too big!\n"); -#endif -	for (addr = (unsigned short *) NetRxPackets[0], i = rxlen >> 1; i > 0; +		debug("packet too big!\n"); +	for (addr = (u16 *) NetRxPackets[0], i = rxlen >> 1; i > 0;  		 i--) -		*addr++ = CS8900_RTDATA; +		*addr++ = REG_READ(&priv->regs->rtdata);  	if (rxlen & 1) -		*addr++ = CS8900_RTDATA; +		*addr++ = REG_READ(&priv->regs->rtdata);  	/* Pass the packet up to the protocol layers. */  	NetReceive (NetRxPackets[0], rxlen); -  	return rxlen;  }  /* Send a data block via Ethernet. */ -int eth_send (volatile void *packet, int length) +static int cs8900_send(struct eth_device *dev, +			volatile void *packet, int length)  { -	volatile unsigned short *addr; +	volatile u16 *addr;  	int tmo; -	unsigned short s; +	u16 s; +	struct cs8900_priv *priv = (struct cs8900_priv *)(dev->priv);  retry:  	/* initiate a transmit sequence */ -	CS8900_TxCMD = PP_TxCmd_TxStart_Full; -	CS8900_TxLEN = length; +	REG_WRITE(PP_TxCmd_TxStart_Full, &priv->regs->txcmd); +	REG_WRITE(length, &priv->regs->txlen);  	/* Test to see if the chip has allocated memory for the packet */ -	if ((get_reg (PP_BusSTAT) & PP_BusSTAT_TxRDY) == 0) { +	if ((get_reg(dev, PP_BusSTAT) & PP_BusSTAT_TxRDY) == 0) {  		/* Oops... this should not happen! */ -#ifdef DEBUG -		printf ("cs: unable to send packet; retrying...\n"); -#endif -		for (tmo = get_timer (0) + 5 * CONFIG_SYS_HZ; get_timer (0) < tmo;) +		debug("cs: unable to send packet; retrying...\n"); +		for (tmo = get_timer(0) + 5 * CONFIG_SYS_HZ; +			get_timer(0) < tmo;)  			/*NOP*/; -		eth_reset (); -		eth_reginit (); +		cs8900_reset(dev); +		cs8900_reginit(dev);  		goto retry;  	}  	/* Write the contents of the packet */  	/* assume even number of bytes */  	for (addr = packet; length > 0; length -= 2) -		CS8900_RTDATA = *addr++; +		REG_WRITE(*addr++, &priv->regs->rtdata);  	/* wait for transfer to succeed */ -	tmo = get_timer (0) + 5 * CONFIG_SYS_HZ; -	while ((s = get_reg (PP_TER) & ~0x1F) == 0) { -		if (get_timer (0) >= tmo) +	tmo = get_timer(0) + 5 * CONFIG_SYS_HZ; +	while ((s = get_reg(dev, PP_TER) & ~0x1F) == 0) { +		if (get_timer(0) >= tmo)  			break;  	}  	/* nothing */ ; -	if ((s & (PP_TER_CRS | PP_TER_TxOK)) != PP_TER_TxOK) { -#ifdef DEBUG -		printf ("\ntransmission error %#x\n", s); -#endif +	if((s & (PP_TER_CRS | PP_TER_TxOK)) != PP_TER_TxOK) { +		debug("\ntransmission error %#x\n", s);  	}  	return 0;  } -static void cs8900_e2prom_ready(void) +static void cs8900_e2prom_ready(struct eth_device *dev)  { -	while (get_reg(PP_SelfSTAT) & SI_BUSY) +	while (get_reg(dev, PP_SelfSTAT) & SI_BUSY)  		;  } @@ -259,12 +271,13 @@ static void cs8900_e2prom_ready(void)  /* read a 16-bit word out of the EEPROM                    */  /***********************************************************/ -int cs8900_e2prom_read(unsigned char addr, unsigned short *value) +int cs8900_e2prom_read(struct eth_device *dev, +			u8 addr, u16 *value)  { -	cs8900_e2prom_ready(); -	put_reg(PP_EECMD, EEPROM_READ_CMD | addr); -	cs8900_e2prom_ready(); -	*value = get_reg(PP_EEData); +	cs8900_e2prom_ready(dev); +	put_reg(dev, PP_EECMD, EEPROM_READ_CMD | addr); +	cs8900_e2prom_ready(dev); +	*value = get_reg(dev, PP_EEData);  	return 0;  } @@ -274,16 +287,51 @@ int cs8900_e2prom_read(unsigned char addr, unsigned short *value)  /* write a 16-bit word into the EEPROM                     */  /***********************************************************/ -int cs8900_e2prom_write(unsigned char addr, unsigned short value) +int cs8900_e2prom_write(struct eth_device *dev, u8 addr, u16 value) +{ +	cs8900_e2prom_ready(dev); +	put_reg(dev, PP_EECMD, EEPROM_WRITE_EN); +	cs8900_e2prom_ready(dev); +	put_reg(dev, PP_EEData, value); +	put_reg(dev, PP_EECMD, EEPROM_WRITE_CMD | addr); +	cs8900_e2prom_ready(dev); +	put_reg(dev, PP_EECMD, EEPROM_WRITE_DIS); +	cs8900_e2prom_ready(dev); + +	return 0; +} + +int cs8900_initialize(u8 dev_num, int base_addr)  { -	cs8900_e2prom_ready(); -	put_reg(PP_EECMD, EEPROM_WRITE_EN); -	cs8900_e2prom_ready(); -	put_reg(PP_EEData, value); -	put_reg(PP_EECMD, EEPROM_WRITE_CMD | addr); -	cs8900_e2prom_ready(); -	put_reg(PP_EECMD, EEPROM_WRITE_DIS); -	cs8900_e2prom_ready(); +	struct eth_device *dev; +	struct cs8900_priv *priv; + +	dev = malloc(sizeof(*dev)); +	if (!dev) { +		free(dev); +		return 0; +	} +	memset(dev, 0, sizeof(*dev)); + +	priv = malloc(sizeof(*priv)); +	if (!priv) { +		free(priv); +		return 0; +	} +	memset(priv, 0, sizeof(*priv)); +	priv->regs = (struct cs8900_regs *)base_addr; + +	/* Load MAC address from EEPROM */ +	cs8900_get_enetaddr(dev); + +	dev->iobase = base_addr; +	dev->priv = priv; +	dev->init = cs8900_init; +	dev->halt = cs8900_halt; +	dev->send = cs8900_send; +	dev->recv = cs8900_recv; +	sprintf(dev->name, "%s-%hu", CS8900_DRIVERNAME, dev_num); +	eth_register(dev);  	return 0;  } |