diff options
Diffstat (limited to 'drivers/tsec.c')
| -rw-r--r-- | drivers/tsec.c | 110 | 
1 files changed, 96 insertions, 14 deletions
| diff --git a/drivers/tsec.c b/drivers/tsec.c index 129847870..fd21ed4ed 100644 --- a/drivers/tsec.c +++ b/drivers/tsec.c @@ -71,6 +71,7 @@ static struct tsec_info_struct tsec_info[] = {  #else  	{TSEC1_PHY_ADDR, TSEC_GIGABIT, TSEC1_PHYIDX},  #endif +#else  	{0, 0, 0},  #endif  #if defined(CONFIG_TSEC2) @@ -79,6 +80,7 @@ static struct tsec_info_struct tsec_info[] = {  #else  	{TSEC2_PHY_ADDR, TSEC_GIGABIT, TSEC2_PHYIDX},  #endif +#else  	{0, 0, 0},  #endif  #ifdef CONFIG_MPC85XX_FEC @@ -127,6 +129,9 @@ static int tsec_miiphy_write(char *devname, unsigned char addr,  			     unsigned char reg, unsigned short value);  static int tsec_miiphy_read(char *devname, unsigned char addr,  			    unsigned char reg, unsigned short *value); +#ifdef CONFIG_MCAST_TFTP +static int tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set); +#endif  /* Initialize device structure. Returns success if PHY   * initialization succeeded (i.e. if it recognizes the PHY) @@ -165,6 +170,9 @@ int tsec_initialize(bd_t * bis, int index, char *devname)  	dev->halt = tsec_halt;  	dev->send = tsec_send;  	dev->recv = tsec_recv; +#ifdef CONFIG_MCAST_TFTP +	dev->mcast = tsec_mcast_addr; +#endif  	/* Tell u-boot to get the addr from the env */  	for (i = 0; i < 6; i++) @@ -176,7 +184,7 @@ int tsec_initialize(bd_t * bis, int index, char *devname)  	priv->regs->maccfg1 |= MACCFG1_SOFT_RESET;  	priv->regs->maccfg1 &= ~(MACCFG1_SOFT_RESET); -#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) \ +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \  	&& !defined(BITBANGMII)  	miiphy_register(dev->name, tsec_miiphy_read, tsec_miiphy_write);  #endif @@ -296,9 +304,9 @@ static int init_phy(struct eth_device *dev)  	volatile tsec_t *regs = (volatile tsec_t *)(TSEC_BASE_ADDR);  	/* Assign a Physical address to the TBI */ -	regs->tbipa = TBIPA_VALUE; +	regs->tbipa = CFG_TBIPA_VALUE;  	regs = (volatile tsec_t *)(TSEC_BASE_ADDR + TSEC_SIZE); -	regs->tbipa = TBIPA_VALUE; +	regs->tbipa = CFG_TBIPA_VALUE;  	asm("sync");  	/* Reset MII (due to new addresses) */ @@ -898,6 +906,39 @@ static void tsec_halt(struct eth_device *dev)  		phy_run_commands(priv, priv->phyinfo->shutdown);  } +struct phy_info phy_info_M88E1149S = { +	0x1410ca, +	"Marvell 88E1149S", +	4, +	(struct phy_cmd[]){     /* config */ +		/* Reset and configure the PHY */ +		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, +		{0x1d, 0x1f, NULL}, +		{0x1e, 0x200c, NULL}, +		{0x1d, 0x5, NULL}, +		{0x1e, 0x0, NULL}, +		{0x1e, 0x100, NULL}, +		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, +		{MIIM_ANAR, MIIM_ANAR_INIT, NULL}, +		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, +		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, +		{miim_end,} +	}, +	(struct phy_cmd[]){     /* startup */ +		/* Status is read once to clear old link state */ +		{MIIM_STATUS, miim_read, NULL}, +		/* Auto-negotiate */ +		{MIIM_STATUS, miim_read, &mii_parse_sr}, +		/* Read the status */ +		{MIIM_88E1011_PHY_STATUS, miim_read, +		 &mii_parse_88E1011_psr}, +		{miim_end,} +	}, +	(struct phy_cmd[]){     /* shutdown */ +		{miim_end,} +	}, +}; +  /* The 5411 id is 0x206070, the 5421 is 0x2060e0 */  struct phy_info phy_info_BCM5461S = {  	0x02060c1,	/* 5461 ID */ @@ -993,11 +1034,6 @@ struct phy_info phy_info_M88E1111S = {  	(struct phy_cmd[]){	/* config */  			   /* Reset and configure the PHY */  			   {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, -			   {0x1d, 0x1f, NULL}, -			   {0x1e, 0x200c, NULL}, -			   {0x1d, 0x5, NULL}, -			   {0x1e, 0x0, NULL}, -			   {0x1e, 0x100, NULL},  			   {0x14, 0x0cd2, NULL}, /* Delay RGMII TX and RX */  			   {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},  			   {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, @@ -1037,14 +1073,16 @@ static struct phy_info phy_info_M88E1145 = {  	"Marvell 88E1145",  	4,  	(struct phy_cmd[]){	/* config */ +			   /* Reset the PHY */ +			   {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, +  			   /* Errata E0, E1 */  			   {29, 0x001b, NULL},  			   {30, 0x418f, NULL},  			   {29, 0x0016, NULL},  			   {30, 0xa2da, NULL}, -			   /* Reset and configure the PHY */ -			   {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, +			   /* Configure the PHY */  			   {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},  			   {MIIM_ANAR, MIIM_ANAR_INIT, NULL},  			   {MIIM_88E1011_PHY_SCR, MIIM_88E1011_PHY_MDI_X_AUTO, @@ -1321,6 +1359,7 @@ struct phy_info *phy_info[] = {  	&phy_info_M88E1011S,  	&phy_info_M88E1111S,  	&phy_info_M88E1145, +	&phy_info_M88E1149S,  	&phy_info_dm9161,  	&phy_info_lxt971,  	&phy_info_VSC8244, @@ -1351,8 +1390,10 @@ struct phy_info *get_phy_info(struct eth_device *dev)  	/* loop through all the known PHY types, and find one that */  	/* matches the ID we read from the PHY. */  	for (i = 0; phy_info[i]; i++) { -		if (phy_info[i]->id == (phy_ID >> phy_info[i]->shift)) +		if (phy_info[i]->id == (phy_ID >> phy_info[i]->shift)) {  			theInfo = phy_info[i]; +			break; +		}  	}  	if (theInfo == NULL) { @@ -1443,7 +1484,7 @@ static void relocate_cmds(void)  	relocated = 1;  } -#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) \ +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \  	&& !defined(BITBANGMII)  struct tsec_private *get_priv_for_phy(unsigned char phyaddr) @@ -1502,7 +1543,48 @@ static int tsec_miiphy_write(char *devname, unsigned char addr,  	return 0;  } -#endif /* defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) -		&& !defined(BITBANGMII) */ +#endif + +#ifdef CONFIG_MCAST_TFTP + +/* CREDITS: linux gianfar driver, slightly adjusted... thanx. */ + +/* Set the appropriate hash bit for the given addr */ + +/* The algorithm works like so: + * 1) Take the Destination Address (ie the multicast address), and + * do a CRC on it (little endian), and reverse the bits of the + * result. + * 2) Use the 8 most significant bits as a hash into a 256-entry + * table.  The table is controlled through 8 32-bit registers: + * gaddr0-7.  gaddr0's MSB is entry 0, and gaddr7's LSB is + * gaddr7.  This means that the 3 most significant bits in the + * hash index which gaddr register to use, and the 5 other bits + * indicate which bit (assuming an IBM numbering scheme, which + * for PowerPC (tm) is usually the case) in the tregister holds + * the entry. */ +static int +tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set) +{ + struct tsec_private *priv = privlist[1]; + volatile tsec_t *regs = priv->regs; + volatile u32  *reg_array, value; + u8 result, whichbit, whichreg; + +	result = (u8)((ether_crc(MAC_ADDR_LEN,mcast_mac) >> 24) & 0xff); +	whichbit = result & 0x1f;	/* the 5 LSB = which bit to set */ +	whichreg = result >> 5;		/* the 3 MSB = which reg to set it in */ +	value = (1 << (31-whichbit)); + +	reg_array = &(regs->hash.gaddr0); + +	if (set) { +		reg_array[whichreg] |= value; +	} else { +		reg_array[whichreg] &= ~value; +	} +	return 0; +} +#endif /* Multicast TFTP ? */  #endif /* CONFIG_TSEC_ENET */ |