[U-Boot] [PATCH v3 2/3] davinci: emac: add support for more than 1 PHYs

manjunath.hadli at ti.com manjunath.hadli at ti.com
Thu Oct 13 15:40:54 CEST 2011


From: Manjunath Hadli <manjunath.hadli at ti.com>

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 at ti.com>
Signed-off-by: Manjunath Hadli <manjunath.hadli at ti.com>
---
 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 52617a7..4ffd086 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);
 }
-- 
1.6.2.4



More information about the U-Boot mailing list