diff options
| author | Manjunath Hadli <manjunath.hadli@ti.com> | 2011-10-13 03:40:54 +0000 | 
|---|---|---|
| committer | Albert ARIBAUD <albert.u.boot@aribaud.net> | 2011-10-27 21:56:36 +0200 | 
| commit | 062fe7d332c28ede25626f448681e43d76bb312e (patch) | |
| tree | 51a7d26eaf8ae57cc73b98d21bfe8582eb276d4b /drivers/net/davinci_emac.c | |
| parent | cc4bd47f4f8d11af50ab56caa9ece29ac13fc5c3 (diff) | |
| download | olio-uboot-2014.01-062fe7d332c28ede25626f448681e43d76bb312e.tar.xz olio-uboot-2014.01-062fe7d332c28ede25626f448681e43d76bb312e.zip | |
davinci: emac: add support for more than 1 PHYs
add support for more than 1 PHYs. Many of the davinci platforms have more
than 1 PHYs on thier board. This patch extends support in davinci emac
driver for upto 3 PHYs.
Signed-off-by: Sudhakar Rajashekhara <sudhakar.raj@ti.com>
Signed-off-by: Manjunath Hadli <manjunath.hadli@ti.com>
Signed-off-by: Sandeep Paulraj <s-paulraj@ti.com>
Diffstat (limited to 'drivers/net/davinci_emac.c')
| -rw-r--r-- | drivers/net/davinci_emac.c | 165 | 
1 files changed, 100 insertions, 65 deletions
| diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 52617a7fb..4ffd08657 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -80,10 +80,15 @@ static int			emac_rx_queue_active = 0;  /* Receive packet buffers */  static unsigned char		emac_rx_buffers[EMAC_MAX_RX_BUFFERS * (EMAC_MAX_ETHERNET_PKT_SIZE + EMAC_PKT_ALIGN)]; +#define MAX_PHY		3 +  /* PHY address for a discovered PHY (0xff - not found) */ -static volatile u_int8_t	active_phy_addr = 0xff; +static u_int8_t	active_phy_addr[MAX_PHY] = { 0xff, 0xff, 0xff }; + +/* number of PHY found active */ +static u_int8_t	num_phy; -phy_t				phy; +phy_t				phy[MAX_PHY];  static int davinci_eth_set_mac_addr(struct eth_device *dev)  { @@ -147,27 +152,30 @@ static int davinci_eth_phy_detect(void)  {  	u_int32_t	phy_act_state;  	int		i; +	int		j; +	unsigned int	count = 0; + +	active_phy_addr[0] = 0xff; +	active_phy_addr[1] = 0xff; +	active_phy_addr[2] = 0xff; -	active_phy_addr = 0xff; +	udelay(1000); +	phy_act_state = readl(&adap_mdio->ALIVE); -	phy_act_state = readl(&adap_mdio->ALIVE) & EMAC_MDIO_PHY_MASK;  	if (phy_act_state == 0) -		return(0);				/* No active PHYs */ +		return 0;		/* No active PHYs */  	debug_emac("davinci_eth_phy_detect(), ALIVE = 0x%08x\n", phy_act_state); -	for (i = 0; i < 32; i++) { +	for (i = 0, j = 0; i < 32; i++)  		if (phy_act_state & (1 << i)) { -			if (phy_act_state & ~(1 << i)) -				return(0);		/* More than one PHY */ -			else { -				active_phy_addr = i; -				return(1); -			} +			count++; +			active_phy_addr[j++] = i;  		} -	} -	return(0);	/* Just to make GCC happy */ +	num_phy = count; + +	return count;  } @@ -236,7 +244,18 @@ static int gen_is_phy_connected(int phy_addr)  {  	u_int16_t	dummy; -	return(davinci_eth_phy_read(phy_addr, MII_PHYSID1, &dummy)); +	return davinci_eth_phy_read(phy_addr, MII_PHYSID1, &dummy); +} + +static int get_active_phy(void) +{ +	int i; + +	for (i = 0; i < num_phy; i++) +		if (phy[i].get_link_speed(active_phy_addr[i])) +			return i; + +	return -1;	/* Return error if no link */  }  static int gen_get_link_speed(int phy_addr) @@ -362,6 +381,7 @@ static int davinci_eth_open(struct eth_device *dev, bd_t *bis)  	dv_reg_p		addr;  	u_int32_t		clkdiv, cnt;  	volatile emac_desc	*rx_desc; +	int			index;  	debug_emac("+ emac_open\n"); @@ -460,7 +480,8 @@ static int davinci_eth_open(struct eth_device *dev, bd_t *bis)  	/* We need to wait for MDIO to start */  	udelay(1000); -	if (!phy.get_link_speed(active_phy_addr)) +	index = get_active_phy(); +	if (index == -1)  		return(0);  	emac_gigabit_enable(); @@ -559,12 +580,12 @@ static int davinci_eth_send_packet (struct eth_device *dev,  					volatile void *packet, int length)  {  	int ret_status = -1; - +	int index;  	tx_send_loop = 0; -	/* Return error if no link */ -	if (!phy.get_link_speed (active_phy_addr)) { -		printf ("WARN: emac_send_packet: No link\n"); +	index = get_active_phy(); +	if (index == -1) { +		printf(" WARN: emac_send_packet: No link\n");  		return (ret_status);  	} @@ -588,7 +609,7 @@ static int davinci_eth_send_packet (struct eth_device *dev,  	/* Wait for packet to complete or link down */  	while (1) { -		if (!phy.get_link_speed (active_phy_addr)) { +		if (!phy[index].get_link_speed(active_phy_addr[index])) {  			davinci_eth_ch_teardown (EMAC_CH_TX);  			return (ret_status);  		} @@ -685,6 +706,7 @@ int davinci_emac_initialize(void)  	u_int32_t	phy_id;  	u_int16_t	tmp;  	int		i; +	int		ret;  	struct eth_device *dev;  	dev = malloc(sizeof *dev); @@ -712,7 +734,7 @@ int davinci_emac_initialize(void)  	for (i = 0; i < 256; i++) {  		if (readl(&adap_mdio->ALIVE))  			break; -		udelay(10); +		udelay(1000);  	}  	if (i >= 256) { @@ -720,64 +742,77 @@ int davinci_emac_initialize(void)  		return(0);  	} -	/* Find if a PHY is connected and get it's address */ -	if (!davinci_eth_phy_detect()) +	/* Find if PHY(s) is/are connected */ +	ret = davinci_eth_phy_detect(); +	if (!ret)  		return(0); +	else +		printf(" %d ETH PHY detected\n", ret);  	/* Get PHY ID and initialize phy_ops for a detected PHY */ -	if (!davinci_eth_phy_read(active_phy_addr, MII_PHYSID1, &tmp)) { -		active_phy_addr = 0xff; -		return(0); -	} +	for (i = 0; i < num_phy; i++) { +		if (!davinci_eth_phy_read(active_phy_addr[i], MII_PHYSID1, +							&tmp)) { +			active_phy_addr[i] = 0xff; +			continue; +		} -	phy_id = (tmp << 16) & 0xffff0000; +		phy_id = (tmp << 16) & 0xffff0000; -	if (!davinci_eth_phy_read(active_phy_addr, MII_PHYSID2, &tmp)) { -		active_phy_addr = 0xff; -		return(0); -	} +		if (!davinci_eth_phy_read(active_phy_addr[i], MII_PHYSID2, +							&tmp)) { +			active_phy_addr[i] = 0xff; +			continue; +		} -	phy_id |= tmp & 0x0000ffff; +		phy_id |= tmp & 0x0000ffff; -	switch (phy_id) { -	case PHY_KSZ8873: -		sprintf(phy.name, "KSZ8873 @ 0x%02x", active_phy_addr); -		phy.init = ksz8873_init_phy; -		phy.is_phy_connected = ksz8873_is_phy_connected; -		phy.get_link_speed = ksz8873_get_link_speed; -		phy.auto_negotiate = ksz8873_auto_negotiate; -		break; +		switch (phy_id) { +		case PHY_KSZ8873: +			sprintf(phy[i].name, "KSZ8873 @ 0x%02x", +						active_phy_addr[i]); +			phy[i].init = ksz8873_init_phy; +			phy[i].is_phy_connected = ksz8873_is_phy_connected; +			phy[i].get_link_speed = ksz8873_get_link_speed; +			phy[i].auto_negotiate = ksz8873_auto_negotiate; +			break;  		case PHY_LXT972: -			sprintf(phy.name, "LXT972 @ 0x%02x", active_phy_addr); -			phy.init = lxt972_init_phy; -			phy.is_phy_connected = lxt972_is_phy_connected; -			phy.get_link_speed = lxt972_get_link_speed; -			phy.auto_negotiate = lxt972_auto_negotiate; +			sprintf(phy[i].name, "LXT972 @ 0x%02x", +						active_phy_addr[i]); +			phy[i].init = lxt972_init_phy; +			phy[i].is_phy_connected = lxt972_is_phy_connected; +			phy[i].get_link_speed = lxt972_get_link_speed; +			phy[i].auto_negotiate = lxt972_auto_negotiate;  			break;  		case PHY_DP83848: -			sprintf(phy.name, "DP83848 @ 0x%02x", active_phy_addr); -			phy.init = dp83848_init_phy; -			phy.is_phy_connected = dp83848_is_phy_connected; -			phy.get_link_speed = dp83848_get_link_speed; -			phy.auto_negotiate = dp83848_auto_negotiate; +			sprintf(phy[i].name, "DP83848 @ 0x%02x", +						active_phy_addr[i]); +			phy[i].init = dp83848_init_phy; +			phy[i].is_phy_connected = dp83848_is_phy_connected; +			phy[i].get_link_speed = dp83848_get_link_speed; +			phy[i].auto_negotiate = dp83848_auto_negotiate;  			break;  		case PHY_ET1011C: -			sprintf(phy.name, "ET1011C @ 0x%02x", active_phy_addr); -			phy.init = gen_init_phy; -			phy.is_phy_connected = gen_is_phy_connected; -			phy.get_link_speed = et1011c_get_link_speed; -			phy.auto_negotiate = gen_auto_negotiate; +			sprintf(phy[i].name, "ET1011C @ 0x%02x", +						active_phy_addr[i]); +			phy[i].init = gen_init_phy; +			phy[i].is_phy_connected = gen_is_phy_connected; +			phy[i].get_link_speed = et1011c_get_link_speed; +			phy[i].auto_negotiate = gen_auto_negotiate;  			break;  		default: -			sprintf(phy.name, "GENERIC @ 0x%02x", active_phy_addr); -			phy.init = gen_init_phy; -			phy.is_phy_connected = gen_is_phy_connected; -			phy.get_link_speed = gen_get_link_speed; -			phy.auto_negotiate = gen_auto_negotiate; -	} +			sprintf(phy[i].name, "GENERIC @ 0x%02x", +						active_phy_addr[i]); +			phy[i].init = gen_init_phy; +			phy[i].is_phy_connected = gen_is_phy_connected; +			phy[i].get_link_speed = gen_get_link_speed; +			phy[i].auto_negotiate = gen_auto_negotiate; +		} -	debug("Ethernet PHY: %s\n", phy.name); +		debug("Ethernet PHY: %s\n", phy.name); -	miiphy_register(phy.name, davinci_mii_phy_read, davinci_mii_phy_write); +		miiphy_register(phy[i].name, davinci_mii_phy_read, +						davinci_mii_phy_write); +	}  	return(1);  } |