[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [MiNT] FEC Ethernet driver patch for Coldfires



Hi Alan,

next attempt. I've tried to follow all the valuable advice I got in response to my last submission (thanks to all who commented!), hopefully this time the FEC patch for the m548x Coldfire boards is as expected.

Cheers,
Markus


Am 17.02.2015 um 12:28 schrieb Alan Hourihane:
On 15/02/15 09:32, Markus Fröschle wrote:
Hi,

please find attached a patch to the Coldfire FEC ethernet driver.
While the Firebee functionality is untouched, it adds a machine
detection (evaluate MCH_ cookie) and initialisation of the Broadcom
bcm5222 ethernet PHY (instead of the am79c874 which is the
corresponding Firebee part) for the m548x eval boards if the machine
found is not a Firebee (Falcon).

Goal is to make the m548x eval board a "headless MiNT machine".

The patch could not be tested much (the m548x currently still dies too
soon in the MiNT boot process to really test anything but it seems to
initialise the FEC correctly). I have made sure that Firebee operation
is unaffected by this change.

The bcm5222.? files need to be added to the sys/sockets/xif/fec dir.
Hi Markus,

Thanks for the patches.

Can you address Vincents comments and re-send ?

Thanks!

Alan.






? fec.patch
? m548x.patch
Index: SRCFILES
===================================================================
RCS file: /mint/freemint/sys/sockets/xif/fec/SRCFILES,v
retrieving revision 1.1
diff -b -u -p -r1.1 SRCFILES
--- SRCFILES	11 Nov 2011 00:15:37 -0000	1.1
+++ SRCFILES	22 Feb 2015 08:10:15 -0000
@@ -4,6 +4,7 @@
 FECDMA_SRCS = \
     dma.c \
     am79c874.c \
+    bcm5222.c \
     fec.c
 
 COMMON_SRCS = \
Index: bcm5222.c
===================================================================
RCS file: bcm5222.c
diff -N bcm5222.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ bcm5222.c	22 Feb 2015 08:10:15 -0000
@@ -0,0 +1,172 @@
+/*
+ * File:        bcm5222.c
+ * Purpose:     Driver for the Micrel BCM5222 10/100 Ethernet PHY
+ *
+ * Notes:       This driver was written specifically for the M5475EVB
+ *              and M5485EVB.  These boards use the MII signals from
+ *              FEC0 to control the PHY.  Therefore the fec_ch parameter
+ *              is ignored when doing MII reads and writes.
+ */
+
+#include "buf.h"
+#include "inet4/if.h"
+#include "inet4/ifeth.h"
+#include "netinfo.h"
+#include "mint/sockio.h"
+
+
+
+#include "platform/board.h"
+#include "fec.h"
+#include "bcm5222.h"
+
+
+/*
+ * Initialize the BCM5222 PHY
+ *
+ * This function sets up the Auto-Negotiate Advertisement register
+ * within the PHY and then forces the PHY to auto-negotiate for
+ * it's settings.
+ *
+ * Params:
+ *  fec_ch      FEC channel
+ *  phy_addr    Address of the PHY.
+ *  speed       Desired speed (10BaseT or 100BaseTX)
+ *  duplex      Desired duplex (Full or Half)
+ *
+ * Return Value:
+ *  0 if MII commands fail
+ *  1 otherwise
+ */
+int bcm5222_init(uint8 fec_ch, uint8 phy_addr, uint8 speed, uint8 duplex)
+{
+	int timeout;
+	uint16 settings;
+
+	/* Initialize the MII interface */
+	fec_mii_init(fec_ch, SYSTEM_CLOCK);
+	KDEBUG(("PHY reset\r\n"));
+
+	/* Reset the PHY */
+	if (!fec_mii_write(fec_ch, phy_addr, BCM5222_CTRL, BCM5222_CTRL_RESET | BCM5222_CTRL_ANE))
+		return 0;
+
+	/* Wait for the PHY to reset */
+	for (timeout = 0; timeout < FEC_MII_TIMEOUT; timeout++)
+	{
+		fec_mii_read(fec_ch, phy_addr, BCM5222_CTRL, &settings);
+		if (!(settings & BCM5222_CTRL_RESET))
+			break;
+	}
+	if(timeout >= FEC_MII_TIMEOUT)
+		return 0;
+
+	KDEBUG(("PHY reset OK\r\n"));
+
+	settings = (BCM5222_AN_ADV_NEXT_PAGE | BCM5222_AN_ADV_PAUSE);
+
+	if (speed == FEC_MII_10BASE_T)
+		settings |= (uint16)((duplex == FEC_MII_FULL_DUPLEX)
+				? (BCM5222_AN_ADV_10BT_FDX | BCM5222_AN_ADV_10BT)
+				: BCM5222_AN_ADV_10BT);
+	else /* (speed == FEC_MII_100BASE_TX) */
+		settings = (uint16)((duplex == FEC_MII_FULL_DUPLEX)
+				? (BCM5222_AN_ADV_100BTX_FDX | BCM5222_AN_ADV_100BTX
+					| BCM5222_AN_ADV_10BT_FDX | BCM5222_AN_ADV_10BT)
+				: (BCM5222_AN_ADV_100BTX | BCM5222_AN_ADV_10BT));
+
+	/* Set the Auto-Negotiation Advertisement Register */
+	if (!fec_mii_write(fec_ch, phy_addr, BCM5222_AN_ADV, settings))
+		return 0;
+
+	KDEBUG(("PHY Enable Auto-Negotiation\r\n"));
+
+	/* Enable Auto-Negotiation */
+	if (!fec_mii_write(fec_ch, phy_addr, BCM5222_CTRL, (BCM5222_CTRL_ANE | BCM5222_CTRL_RESTART_AN)))
+		return 0;
+
+	KDEBUG(("PHY Wait for auto-negotiation to complete\r\n"));
+
+	/* Wait for auto-negotiation to complete */
+	for (timeout = 0; timeout < FEC_MII_TIMEOUT; timeout++)
+	{
+		if (!fec_mii_read(fec_ch, phy_addr, BCM5222_STAT, &settings))
+			return 0;
+		if (settings & BCM5222_STAT_AN_COMPLETE)
+			break;
+	}
+
+	if (timeout < FEC_MII_TIMEOUT)
+	{
+		KDEBUG(("PHY auto-negociation complete\r\n"));
+
+		/* Read Auxiliary Control/Status Register */
+		if (!fec_mii_read(fec_ch, phy_addr, BCM5222_ACSR, &settings))
+			return 0;
+	}
+	else
+	{
+		KDEBUG(("auto negotiation failed, PHY Set the default mode\r\n"));
+
+		/* Set the default mode (Full duplex, 100 Mbps) */
+		if (!fec_mii_write(fec_ch, phy_addr, BCM5222_ACSR, settings = (BCM5222_ACSR_100BTX | BCM5222_ACSR_FDX)))
+			return 0;
+	}
+
+	/* Set the proper duplex in the FEC now that we have auto-negotiated */
+	if (settings & BCM5222_ACSR_FDX)
+		fec_duplex(fec_ch, FEC_MII_FULL_DUPLEX);
+	else
+		fec_duplex(fec_ch, FEC_MII_HALF_DUPLEX);
+
+	KDEBUG(("PHY Mode: "));
+
+    if (settings & BCM5222_ACSR_100BTX)
+        KDEBUG(("100Mbps\r\n"));
+    else
+        KDEBUG(("10Mbps\r\n"));
+
+    if (settings & BCM5222_ACSR_FDX)
+        KDEBUG(("Full-duplex\r\n"));
+    else
+        KDEBUG(("Half-duplex\r\n"));
+
+    return 1;
+}
+
+void bcm5222_get_reg(uint16 *status0, uint16 *status1)
+{
+	fec_mii_read(0, 0x00, 0x00000000, &status0[0]);
+	fec_mii_read(0, 0x00, 0x00000001, &status0[1]);
+	fec_mii_read(0, 0x00, 0x00000004, &status0[4]);
+	fec_mii_read(0, 0x00, 0x00000005, &status0[5]);
+	fec_mii_read(0, 0x00, 0x00000006, &status0[6]);
+	fec_mii_read(0, 0x00, 0x00000007, &status0[7]);
+	fec_mii_read(0, 0x00, 0x00000008, &status0[8]);
+	fec_mii_read(0, 0x00, 0x00000010, &status0[16]);
+	fec_mii_read(0, 0x00, 0x00000011, &status0[17]);
+	fec_mii_read(0, 0x00, 0x00000012, &status0[18]);
+	fec_mii_read(0, 0x00, 0x00000013, &status0[19]);
+	fec_mii_read(0, 0x00, 0x00000018, &status0[24]);
+	fec_mii_read(0, 0x00, 0x00000019, &status0[25]);
+	fec_mii_read(0, 0x00, 0x0000001B, &status0[27]);
+	fec_mii_read(0, 0x00, 0x0000001C, &status0[28]);
+	fec_mii_read(0, 0x00, 0x0000001E, &status0[30]);
+	fec_mii_read(0, 0x01, 0x00000000, &status1[0]);
+	fec_mii_read(0, 0x01, 0x00000001, &status1[1]);
+	fec_mii_read(0, 0x01, 0x00000004, &status1[4]);
+	fec_mii_read(0, 0x01, 0x00000005, &status1[5]);
+	fec_mii_read(0, 0x01, 0x00000006, &status1[6]);
+	fec_mii_read(0, 0x01, 0x00000007, &status1[7]);
+	fec_mii_read(0, 0x01, 0x00000008, &status1[8]);
+	fec_mii_read(0, 0x01, 0x00000010, &status1[16]);
+	fec_mii_read(0, 0x01, 0x00000011, &status1[17]);
+	fec_mii_read(0, 0x01, 0x00000012, &status1[18]);
+	fec_mii_read(0, 0x01, 0x00000013, &status1[19]);
+	fec_mii_read(0, 0x01, 0x00000018, &status1[24]);
+	fec_mii_read(0, 0x01, 0x00000019, &status1[25]);
+	fec_mii_read(0, 0x01, 0x0000001B, &status1[27]);
+	fec_mii_read(0, 0x01, 0x0000001C, &status1[28]);
+	fec_mii_read(0, 0x01, 0x0000001E, &status1[30]);
+}
+
Index: bcm5222.h
===================================================================
RCS file: bcm5222.h
diff -N bcm5222.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ bcm5222.h	22 Feb 2015 08:10:15 -0000
@@ -0,0 +1,71 @@
+/*
+ * File:		bcm5222.h
+ * Purpose:		Driver for the BCM5222 10/100 Ethernet PHY
+ *
+ * Notes:
+ */
+
+#ifndef _BCM5222_H_
+#define _BCM5222_H_
+
+extern int bcm5222_init(uint8, uint8, uint8, uint8);
+extern void bcm5222_get_reg(uint16*, uint16*);
+
+/********************************************************************/
+
+/* MII Register Addresses */
+#define BCM5222_CTRL				(0x00)
+#define BCM5222_STAT				(0x01)
+#define BCM5222_PHY_ID1				(0x02)
+#define BCM5222_PHY_ID2				(0x03)
+#define BCM5222_AN_ADV				(0x04)
+#define BCM5222_AN_LINK_PAR			(0x05)
+#define BCM5222_AN_EXP				(0x06)
+#define BCM5222_AN_NPR				(0x07)
+#define BCM5222_LINK_NPA			(0x08)
+#define BCM5222_ACSR    			(0x18)
+
+/* Bit definitions and macros for BCM5222_CTRL */
+#define BCM5222_CTRL_RESET			(0x8000)
+#define BCM5222_CTRL_LOOP			(0x4000)
+#define BCM5222_CTRL_SPEED			(0x2000)
+#define BCM5222_CTRL_ANE			(0x1000)
+#define BCM5222_CTRL_PD				(0x0800)
+#define BCM5222_CTRL_ISOLATE		(0x0400)
+#define BCM5222_CTRL_RESTART_AN		(0x0200)
+#define BCM5222_CTRL_FDX			(0x0100)
+#define BCM5222_CTRL_COL_TEST		(0x0080)
+
+
+/* Bit definitions and macros for BCM5222_STAT */
+#define BCM5222_STAT_100BT4         (0x8000)
+#define BCM5222_STAT_100BTX_FDX     (0x4000)
+#define BCM5222_STAT_100BTX         (0x2000)
+#define BCM5222_STAT_10BT_FDX       (0x1000)
+#define BCM5222_STAT_10BT           (0x0800)
+#define BCM5222_STAT_NO_PREAMBLE    (0x0040)
+#define BCM5222_STAT_AN_COMPLETE    (0x0020)
+#define BCM5222_STAT_REMOTE_FAULT   (0x0010)
+#define BCM5222_STAT_AN_ABILITY     (0x0008)
+#define BCM5222_STAT_LINK           (0x0004)
+#define BCM5222_STAT_JABBER         (0x0002)
+#define BCM5222_STAT_EXTENDED       (0x0001)
+
+/* Bit definitions and macros for BCM5222_AN_ADV */
+#define BCM5222_AN_ADV_NEXT_PAGE    (0x8001)
+#define BCM5222_AN_ADV_REM_FAULT	(0x2001)
+#define BCM5222_AN_ADV_PAUSE		(0x0401)
+#define BCM5222_AN_ADV_100BT4		(0x0201)
+#define BCM5222_AN_ADV_100BTX_FDX	(0x0101)
+#define BCM5222_AN_ADV_100BTX		(0x0081)
+#define BCM5222_AN_ADV_10BT_FDX		(0x0041)
+#define BCM5222_AN_ADV_10BT		    (0x0021)
+#define BCM5222_AN_ADV_802_3		(0x0001)
+
+/* Bit definitions and macros for BCM5222_ACSR */
+#define BCM5222_ACSR_100BTX         (0x0002)
+#define BCM5222_ACSR_FDX            (0x0001)
+
+/********************************************************************/
+
+#endif /* _BCM5222_H_ */
Index: fec.c
===================================================================
RCS file: /mint/freemint/sys/sockets/xif/fec/fec.c,v
retrieving revision 1.4
diff -b -u -p -r1.4 fec.c
--- fec.c	5 Sep 2014 09:28:02 -0000	1.4
+++ fec.c	22 Feb 2015 08:10:16 -0000
@@ -19,13 +19,14 @@
 #include "ssystem.h"
 #include "arch/cpu.h"					// for cpushi (cache control)
 #include "util.h"
+#include "cookie.h"
 
 #include "platform/board.h"
 #include "platform/dma.h"
 
 #include "fec.h"
 #include "am79c874.h"
-
+#include "bcm5222.h"
 
 #ifndef MAX
 #define MAX(a,b) ((a)>(b)?(a):(b))
@@ -108,6 +109,21 @@ static long	fec_output	(struct netif *, 
 static long	fec_ioctl	(struct netif *, short, long);
 static long	fec_config	(struct netif *, struct ifopt *);
 
+extern uint32 mch_cookie( void );
+
+/*
+ * machine type detection
+ */
+uint32 mch_cookie( void )
+{
+	uint32 mch = 0;
+
+	if (s_system (S_GETCOOKIE, COOKIE__MCH, (long) &mch) != 0)
+		mch = 0;
+
+	return mch;
+}
+
 static unsigned char *board_get_ethaddr(unsigned char *ethaddr);
 
 unsigned char *board_get_ethaddr(unsigned char * ethaddr)
@@ -1158,8 +1174,9 @@ driver_init (void)
      */
     if_register (&if_fec[0]);
 
-    ksprintf (message, "%s v%d.%d  (%s%d - %02x:%02x:%02x:%02x:%02x:%02x)\r\n",
+    ksprintf (message, "%s (%s) v%d.%d  (%s%d - %02x:%02x:%02x:%02x:%02x:%02x)\r\n",
               FEC_DRIVER_DESC,
+              mch_cookie() == FALCON ? "Firebee" : "m548x",
               FEC_DRIVER_MAJOR_VERSION,
               FEC_DRIVER_MINOR_VERSION,
               FEC_DEVICE_NAME,
@@ -1204,18 +1221,21 @@ fec_open (struct netif *nif)
         fec_init(fi, mode, duplex, (const uint8 *)nif->hwlocal.adr.bytes);
 
         /* Initialize the PHY interface */
-        if( (mode == FEC_MODE_MII) && (am79c874_init(fi->ch, FEC_PHY(fi->ch), speed, duplex) == 0) )
+		 if( (mode == FEC_MODE_MII) && mch_cookie() == FALCON ? (am79c874_init(fi->ch, FEC_PHY(fi->ch), speed, duplex) == 0)  :
+															   (bcm5222_init(fi->ch, FEC_PHY(fi->ch), speed, duplex) == 0))
         {
             /* Flush the network buffers */
-            c_conws("am79c874_init failed!\r\n");
+	          c_conws("ethernet PHY init failed!\r\n");
             fec_buf_flush(fi);
             res = 1;
         }
         else
         {
             /* Enable the multi-channel DMA tasks */
+            KDEBUG(("starting multi-channel DMA tasks\r\n"));
             fec_rx_start(nif, (s8*)fi->rx_bd, fi->ch ? FEC1RX_DMA_PRI : FEC0RX_DMA_PRI);
             fec_tx_start(nif, (s8*)fi->tx_bd, fi->ch ? FEC1TX_DMA_PRI : FEC0TX_DMA_PRI);
+            KDEBUG(("enable network interface\r\n"));
             fec_enable(fi->ch);
         }
     }