Skip to contentSkip to conversation

Support for both FEC interfaces on i.MX28

PATCH Superseded Marek Vasut 2 participants 16 messages Sep 8, 2011 – Sep 9, 2011

Subsystems (3)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

cover Support for both FEC interfaces on i.MX28

This patchset introduces support for both FEC ethernet interfaces on the i.MX28 CPU and clears most of the FIXME's the the driver.

Marek Vasut (11):
FEC: Use proper accessor to read register in debug call
FEC: Use defined constant instead of magic number
FEC: Kill mode select FIXME's
FEC: Add RMII mode support
FEC: Allow selection of MII mode via CONFIG_FEC_XCV_TYPE
FEC: Abstract access to fec->eth in MII operations
FEC: Allow multiple FECes
FEC: Allow registering MII postconfiguration callback
FEC: Add timeout for chip reset
FEC: Squish "got MAC from fuse" message, make it debug()
FEC: Move imx_get_mac_from_fuse() definition to fec_mxc.h

 arch/arm/include/asm/arch-mx25/imx-regs.h |    1 -
 arch/arm/include/asm/arch-mx27/imx-regs.h |    1 -
 arch/arm/include/asm/arch-mx35/imx-regs.h |    2 -
 arch/arm/include/asm/arch-mx5/imx-regs.h  |    2 -
 drivers/net/fec_mxc.c                     |  170 +++++++++++++++++++----------
 drivers/net/fec_mxc.h                     |    9 ++-
 include/netdev.h                          |    7 +-
 7 files changed, 128 insertions(+), 64 deletions(-)
Signature · 1 line
1.7.5.4
#1 lore raw

PATCH 1/11 FEC: Use proper accessor to read register in debug call

Cc Ben Warren <[email protected]>
Cc Stefano Babic <[email protected]>
Cc Wolfgang Denk <[email protected]>
Cc Detlev Zundel <[email protected]>
---
 drivers/net/fec_mxc.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/net/fec_mxc.c +1 -1
index ab90afa..82fe1e4 100644
@@ -117,7 +117,7 @@ static void fec_mii_setspeed(struct fec_priv *fec)
 	writel((((imx_get_fecclk() / 1000000) + 2) / 5) << 1,
 			&fec->eth->mii_speed);
 	debug("fec_init: mii_speed %#lx\n",
-			fec->eth->mii_speed);
+			readl(&fec->eth->mii_speed));
 }
 static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr,
 		uint16_t data)
Signature · 1 line
1.7.5.4
#2 lore raw

PATCH 2/11 FEC: Use defined constant instead of magic number

In reply to Marek Vasut
Cc Ben Warren <[email protected]>
Cc Stefano Babic <[email protected]>
Cc Wolfgang Denk <[email protected]>
Cc Detlev Zundel <[email protected]>
---
 drivers/net/fec_mxc.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/net/fec_mxc.c +1 -1
index 82fe1e4..8e0d30a 100644
@@ -712,7 +712,7 @@ static int fec_probe(bd_t *bd)
 
 	/* Reset chip. */
 	writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_RESET, &fec->eth->ecntrl);
-	while (readl(&fec->eth->ecntrl) & 1)
+	while (readl(&fec->eth->ecntrl) & FEC_ECNTRL_RESET)
 		udelay(10);
 
 	/*
Signature · 1 line
1.7.5.4
#3 lore raw

PATCH 3/11 FEC: Kill mode select FIXME's

In reply to Marek Vasut
Cc Ben Warren <[email protected]>
Cc Stefano Babic <[email protected]>
Cc Wolfgang Denk <[email protected]>
Cc Detlev Zundel <[email protected]>
---
 drivers/net/fec_mxc.c |   26 ++++++++++++++------------
 1 files changed, 14 insertions(+), 12 deletions(-)
drivers/net/fec_mxc.c +14 -12
index 8e0d30a..bd76f97 100644
@@ -400,6 +400,7 @@ static int fec_init(struct eth_device *dev, bd_t* bd)
 {
 	uint32_t base;
 	struct fec_priv *fec = (struct fec_priv *)dev->priv;
+	uint32_t rcntrl;
 
 	/* Initialize MAC address */
 	fec_set_hwaddr(dev);
@@ -442,19 +443,19 @@ static int fec_init(struct eth_device *dev, bd_t* bd)
 	/*
 	 * Set FEC-Lite receive control register(R_CNTRL):
 	 */
-	if (fec->xcv_type == SEVENWIRE) {
-		/*
-		 * Frame length=1518; 7-wire mode
-		 */
-		writel(0x05ee0020, &fec->eth->r_cntrl);	/* FIXME 0x05ee0000 */
-	} else {
-		/*
-		 * Frame length=1518; MII mode;
-		 */
-		writel(0x05ee0024, &fec->eth->r_cntrl);	/* FIXME 0x05ee0004 */
 
+	/* Start with frame length = 1518, common for all modes. */
+	rcntrl = 1518 << FEC_RCNTRL_MAX_FL_SHIFT;
+	if (fec->xcv_type == SEVENWIRE)
+		rcntrl |= FEC_RCNTRL_FCE;
+	else	/* MII mode */
+		rcntrl |= FEC_RCNTRL_FCE | FEC_RCNTRL_MII_MODE;
+
+	writel(rcntrl, &fec->eth->r_cntrl);
+
+	if (fec->xcv_type == MII10 || fec->xcv_type == MII100)
 		fec_mii_setspeed(fec);
-	}
+
 	/*
 	 * Set Opcode/Pause Duration Register
 	 */
@@ -731,7 +732,8 @@ static int fec_probe(bd_t *bd)
 	/*
 	 * Frame length=1518; MII mode;
 	 */
-	writel(0x05ee0024, &fec->eth->r_cntrl);	/* FIXME 0x05ee0004 */
+	writel((1518 << FEC_RCNTRL_MAX_FL_SHIFT) | FEC_RCNTRL_FCE |
+		FEC_RCNTRL_MII_MODE, &fec->eth->r_cntrl);
 	fec_mii_setspeed(fec);
 
 	sprintf(edev->name, "FEC");
Signature · 1 line
1.7.5.4
#4 lore raw

PATCH 3/11 FEC: Kill mode select FIXME's

drivers/net/fec_mxc.c static int fec_init(struct eth_device *dev, bd_t* bd) · line 448

Quoted 2 lines · On Thursday, September 08, 2011 16:37:14 Marek Vasut wrote:
drivers/net/fec_mxc.c +2 -0
+	/* Start with frame length = 1518, common for all modes. */
+	rcntrl = 1518 << FEC_RCNTRL_MAX_FL_SHIFT;

you mean PKTSIZE ? ;)
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20110908/b787340d/attachment.pgp

#5 lore raw

PATCH 3/11 FEC: Kill mode select FIXME's

Quoted 6 lines · Mike Frysinger

drivers/net/fec_mxc.c static int fec_init(struct eth_device *dev, bd_t* bd) · line 448

Quoted 2 lines · On Thursday, September 08, 2011 16:37:14 Marek Vasut wrote:
drivers/net/fec_mxc.c +2 -0
+	/* Start with frame length = 1518, common for all modes. */
+	rcntrl = 1518 << FEC_RCNTRL_MAX_FL_SHIFT;

you mean PKTSIZE ? ;)
-mike

Fixed internally ... if there's anything else, let me know. I'll roll out the new series then.

#6 lore raw

PATCH 4/11 FEC: Add RMII mode support

In reply to Marek Vasut
Cc Ben Warren <[email protected]>
Cc Stefano Babic <[email protected]>
Cc Wolfgang Denk <[email protected]>
Cc Detlev Zundel <[email protected]>
---
 drivers/net/fec_mxc.c |    2 ++
 drivers/net/fec_mxc.h |    4 +++-
 2 files changed, 5 insertions(+), 1 deletions(-)
drivers/net/fec_mxc.c +2 -0
index bd76f97..2b269d6 100644
@@ -448,6 +448,8 @@ static int fec_init(struct eth_device *dev, bd_t* bd)
 	rcntrl = 1518 << FEC_RCNTRL_MAX_FL_SHIFT;
 	if (fec->xcv_type == SEVENWIRE)
 		rcntrl |= FEC_RCNTRL_FCE;
+	else if (fec->xcv_type == RMII)
+		rcntrl |= FEC_RCNTRL_RMII;
 	else	/* MII mode */
 		rcntrl |= FEC_RCNTRL_FCE | FEC_RCNTRL_MII_MODE;
 
drivers/net/fec_mxc.h +3 -1
index 1ba5161..f16f9db 100644
@@ -194,6 +194,7 @@ struct ethernet_regs {
 #define FEC_RCNTRL_PROM			0x00000008
 #define FEC_RCNTRL_BC_REJ		0x00000010
 #define FEC_RCNTRL_FCE			0x00000020
+#define FEC_RCNTRL_RMII			0x00000100
 
 #define FEC_TCNTRL_GTS			0x00000001
 #define FEC_TCNTRL_HBC			0x00000002
@@ -257,7 +258,8 @@ struct fec_bd {
 enum xceiver_type {
 	SEVENWIRE,	/* 7-wire       */
 	MII10,		/* MII 10Mbps   */
-	MII100		/* MII 100Mbps  */
+	MII100,		/* MII 100Mbps  */
+	RMII		/* RMII */
 };
 
 /**
Signature · 1 line
1.7.5.4
#7 lore raw

PATCH 5/11 FEC: Allow selection of MII mode via CONFIG_FEC_XCV_TYPE

In reply to Marek Vasut

The default is MII100, which was hardcoded previously in the driver.

Cc Ben Warren <[email protected]>
Cc Stefano Babic <[email protected]>
Cc Wolfgang Denk <[email protected]>
Cc Detlev Zundel <[email protected]>
---
 drivers/net/fec_mxc.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)
drivers/net/fec_mxc.c +5 -1
index 2b269d6..d75f40c 100644
@@ -38,6 +38,10 @@ DECLARE_GLOBAL_DATA_PTR;
 #error "CONFIG_MII has to be defined!"
 #endif
 
+#ifndef	CONFIG_FEC_XCV_TYPE
+#define	CONFIG_FEC_XCV_TYPE	MII100
+#endif
+
 #undef DEBUG
 
 struct nbuf {
@@ -711,7 +715,7 @@ static int fec_probe(bd_t *bd)
 	fec->eth = (struct ethernet_regs *)IMX_FEC_BASE;
 	fec->bd = bd;
 
-	fec->xcv_type = MII100;
+	fec->xcv_type = CONFIG_FEC_XCV_TYPE;
 
 	/* Reset chip. */
 	writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_RESET, &fec->eth->ecntrl);
Signature · 1 line
1.7.5.4
#8 lore raw

PATCH 5/11 FEC: Allow selection of MII mode via CONFIG_FEC_XCV_TYPE

Quoted 14 lines · On Thursday, September 08, 2011 16:37:16 Marek Vasut wrote:
drivers/net/fec_mxc.c +4 -0
@@ -38,6 +38,10 @@ DECLARE_GLOBAL_DATA_PTR;
 #error "CONFIG_MII has to be defined!"
 #endif
 
+#ifndef	CONFIG_FEC_XCV_TYPE
+#define	CONFIG_FEC_XCV_TYPE	MII100
+#endif
+
 #undef DEBUG
 
 struct nbuf {

drivers/net/fec_mxc.c static int fec_probe(bd_t *bd) · line 718

Quoted 5 lines
drivers/net/fec_mxc.c +1 -1
@@ -711,7 +715,7 @@ static int fec_probe(bd_t *bd)
 	fec->eth = (struct ethernet_regs *)IMX_FEC_BASE;
 	fec->bd = bd;
 
-	fec->xcv_type = MII100;
+	fec->xcv_type = CONFIG_FEC_XCV_TYPE;

shouldnt this be a parameter to fec_probe() ?
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20110908/67eb6f61/attachment.pgp

#9 lore raw

PATCH 5/11 FEC: Allow selection of MII mode via CONFIG_FEC_XCV_TYPE

Quoted 19 lines · Mike Frysinger
Quoted 18 lines · On Thursday, September 08, 2011 16:37:16 Marek Vasut wrote:
drivers/net/fec_mxc.c +4 -0
@@ -38,6 +38,10 @@ DECLARE_GLOBAL_DATA_PTR;
 
 #error "CONFIG_MII has to be defined!"
 #endif
 
+#ifndef	CONFIG_FEC_XCV_TYPE
+#define	CONFIG_FEC_XCV_TYPE	MII100
+#endif
+
 
 #undef DEBUG

struct nbuf {

drivers/net/fec_mxc.c +0 -0
@@ -711,7 +715,7 @@ static int fec_probe(bd_t *bd)
 
Quoted 8 lines

drivers/net/fec_mxc.c static int fec_probe(bd_t *bd) · line 718

Quoted 5 lines
drivers/net/fec_mxc.c +1 -1
 	fec->eth = (struct ethernet_regs *)IMX_FEC_BASE;
 	fec->bd = bd;
 
-	fec->xcv_type = MII100;
+	fec->xcv_type = CONFIG_FEC_XCV_TYPE;

shouldnt this be a parameter to fec_probe() ?
-mike

We plan to add a driver model eventually. Until then, let's not polute this more than necessary.

#10 lore raw

PATCH 6/11 FEC: Abstract access to fec->eth in MII operations

In reply to Marek Vasut
Cc Ben Warren <[email protected]>
Cc Stefano Babic <[email protected]>
Cc Wolfgang Denk <[email protected]>
Cc Detlev Zundel <[email protected]>
---
 drivers/net/fec_mxc.c |   18 ++++++++++--------
 1 files changed, 10 insertions(+), 8 deletions(-)
drivers/net/fec_mxc.c +10 -8
index d75f40c..6f56a7a 100644
@@ -71,6 +71,7 @@ static int fec_miiphy_read(const char *dev, uint8_t phyAddr, uint8_t regAddr,
 {
 	struct eth_device *edev = eth_get_dev_by_name(dev);
 	struct fec_priv *fec = (struct fec_priv *)edev->priv;
+	struct ethernet_regs *eth = fec->eth;
 
 	uint32_t reg;		/* convenient holder for the PHY register */
 	uint32_t phy;		/* convenient holder for the PHY */
@@ -80,18 +81,18 @@ static int fec_miiphy_read(const char *dev, uint8_t phyAddr, uint8_t regAddr,
 	 * reading from any PHY's register is done by properly
 	 * programming the FEC's MII data register.
 	 */
-	writel(FEC_IEVENT_MII, &fec->eth->ievent);
+	writel(FEC_IEVENT_MII, &eth->ievent);
 	reg = regAddr << FEC_MII_DATA_RA_SHIFT;
 	phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
 
 	writel(FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA |
-			phy | reg, &fec->eth->mii_data);
+			phy | reg, &eth->mii_data);
 
 	/*
 	 * wait for the related interrupt
 	 */
 	start = get_timer(0);
-	while (!(readl(&fec->eth->ievent) & FEC_IEVENT_MII)) {
+	while (!(readl(&eth->ievent) & FEC_IEVENT_MII)) {
 		if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) {
 			printf("Read MDIO failed...\n");
 			return -1;
@@ -101,12 +102,12 @@ static int fec_miiphy_read(const char *dev, uint8_t phyAddr, uint8_t regAddr,
 	/*
 	 * clear mii interrupt bit
 	 */
-	writel(FEC_IEVENT_MII, &fec->eth->ievent);
+	writel(FEC_IEVENT_MII, &eth->ievent);
 
 	/*
 	 * it's now safe to read the PHY's register
 	 */
-	*retVal = readl(&fec->eth->mii_data);
+	*retVal = readl(&eth->mii_data);
 	debug("fec_miiphy_read: phy: %02x reg:%02x val:%#x\n", phyAddr,
 			regAddr, *retVal);
 	return 0;
@@ -128,6 +129,7 @@ static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr,
 {
 	struct eth_device *edev = eth_get_dev_by_name(dev);
 	struct fec_priv *fec = (struct fec_priv *)edev->priv;
+	struct ethernet_regs *eth = fec->eth;
 
 	uint32_t reg;		/* convenient holder for the PHY register */
 	uint32_t phy;		/* convenient holder for the PHY */
@@ -137,13 +139,13 @@ static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr,
 	phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
 
 	writel(FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR |
-		FEC_MII_DATA_TA | phy | reg | data, &fec->eth->mii_data);
+		FEC_MII_DATA_TA | phy | reg | data, &eth->mii_data);
 
 	/*
 	 * wait for the MII interrupt
 	 */
 	start = get_timer(0);
-	while (!(readl(&fec->eth->ievent) & FEC_IEVENT_MII)) {
+	while (!(readl(&eth->ievent) & FEC_IEVENT_MII)) {
 		if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) {
 			printf("Write MDIO failed...\n");
 			return -1;
@@ -153,7 +155,7 @@ static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr,
 	/*
 	 * clear MII interrupt bit
 	 */
-	writel(FEC_IEVENT_MII, &fec->eth->ievent);
+	writel(FEC_IEVENT_MII, &eth->ievent);
 	debug("fec_miiphy_write: phy: %02x reg:%02x val:%#x\n", phyAddr,
 			regAddr, data);
 
Signature · 1 line
1.7.5.4
#11 lore raw

PATCH 7/11 FEC: Allow multiple FECes

In reply to Marek Vasut

This patch allows user to register multiple FEC controllers. To preserve compatibility with older boards, the mxcfec_register() call is still in place. To use multiple controllers, new macro is in place, the mxcfec_register_multi(), which takes more arguments. The syntax is:

mxcfec_register_multi(bd, FEC ID, FEC PHY ID on the MII bus, base address);

To disable the fecmxc_register() compatibility stuff, define the macro CONFIG_FEC_MXC_MULTI. This will remove the requirement for defining IMX_FEC_BASE and CONFIG_FEC_MXC_PHYADDR.

Cc Ben Warren <[email protected]>
Cc Stefano Babic <[email protected]>
Cc Wolfgang Denk <[email protected]>
Cc Detlev Zundel <[email protected]>
---
 drivers/net/fec_mxc.c |   79 ++++++++++++++++++++++++++++++------------------
 drivers/net/fec_mxc.h |    2 +
 include/netdev.h      |    2 +-
 3 files changed, 52 insertions(+), 31 deletions(-)
drivers/net/fec_mxc.c +49 -30
index 6f56a7a..44b7919 100644
@@ -51,18 +51,6 @@ struct nbuf {
 	uint8_t head[16];	/**< MAC header(6 + 6 + 2) + 2(aligned) */
 };
 
-struct fec_priv gfec = {
-	.eth       = (struct ethernet_regs *)IMX_FEC_BASE,
-	.xcv_type  = MII100,
-	.rbd_base  = NULL,
-	.rbd_index = 0,
-	.tbd_base  = NULL,
-	.tbd_index = 0,
-	.bd        = NULL,
-	.rdb_ptr   = NULL,
-	.base_ptr  = NULL,
-};
-
 /*
  * MII-interface related functions
  */
@@ -164,26 +152,27 @@ static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr,
 
 static int miiphy_restart_aneg(struct eth_device *dev)
 {
+	struct fec_priv *fec = (struct fec_priv *)dev->priv;
+
 	/*
 	 * Wake up from sleep if necessary
 	 * Reset PHY, then delay 300ns
 	 */
 #ifdef CONFIG_MX27
-	miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, MII_DCOUNTER, 0x00FF);
+	miiphy_write(dev->name, fec->phy_id, MII_DCOUNTER, 0x00FF);
 #endif
-	miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, MII_BMCR,
+	miiphy_write(dev->name, fec->phy_id, MII_BMCR,
 			BMCR_RESET);
 	udelay(1000);
 
 	/*
 	 * Set the auto-negotiation advertisement register bits
 	 */
-	miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, MII_ADVERTISE,
+	miiphy_write(dev->name, fec->phy_id, MII_ADVERTISE,
 			LPA_100FULL | LPA_100HALF | LPA_10FULL |
 			LPA_10HALF | PHY_ANLPAR_PSB_802_3);
-	miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, MII_BMCR,
+	miiphy_write(dev->name, fec->phy_id, MII_BMCR,
 			BMCR_ANENABLE | BMCR_ANRESTART);
-
 	return 0;
 }
 
@@ -191,6 +180,7 @@ static int miiphy_wait_aneg(struct eth_device *dev)
 {
 	uint32_t start;
 	uint16_t status;
+	struct fec_priv *fec = (struct fec_priv *)dev->priv;
 
 	/*
 	 * Wait for AN completion
@@ -202,7 +192,7 @@ static int miiphy_wait_aneg(struct eth_device *dev)
 			return -1;
 		}
 
-		if (miiphy_read(dev->name, CONFIG_FEC_MXC_PHYADDR,
+		if (miiphy_read(dev->name, fec->phy_id,
 					MII_BMSR, &status)) {
 			printf("%s: Autonegotiation failed. status: 0x%04x\n",
 					dev->name, status);
@@ -390,8 +380,8 @@ static int fec_open(struct eth_device *edev)
 #endif
 
 	miiphy_wait_aneg(edev);
-	miiphy_speed(edev->name, CONFIG_FEC_MXC_PHYADDR);
-	miiphy_duplex(edev->name, CONFIG_FEC_MXC_PHYADDR);
+	miiphy_speed(edev->name, fec->phy_id);
+	miiphy_duplex(edev->name, fec->phy_id);
 
 	/*
 	 * Enable SmartDMA receive task
@@ -406,7 +396,9 @@ static int fec_init(struct eth_device *dev, bd_t* bd)
 {
 	uint32_t base;
 	struct fec_priv *fec = (struct fec_priv *)dev->priv;
+	uint32_t mib_ptr = (uint32_t)&fec->eth->rmon_t_drop;
 	uint32_t rcntrl;
+	int i;
 
 	/* Initialize MAC address */
 	fec_set_hwaddr(dev);
@@ -477,9 +469,8 @@ static int fec_init(struct eth_device *dev, bd_t* bd)
 
 
 	/* clear MIB RAM */
-	long *mib_ptr = (long *)(IMX_FEC_BASE + 0x200);
-	while (mib_ptr <= (long *)(IMX_FEC_BASE + 0x2FC))
-		*mib_ptr++ = 0;
+	for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4)
+		writel(0, i);
 
 	/* FIFO receive start register */
 	writel(0x520, &fec->eth->r_fstart);
@@ -513,7 +504,7 @@ static int fec_init(struct eth_device *dev, bd_t* bd)
  */
 static void fec_halt(struct eth_device *dev)
 {
-	struct fec_priv *fec = &gfec;
+	struct fec_priv *fec = (struct fec_priv *)dev->priv;
 	int counter = 0xffff;
 
 	/*
@@ -694,19 +685,28 @@ static int fec_recv(struct eth_device *dev)
 	return len;
 }
 
-static int fec_probe(bd_t *bd)
+static int fec_probe(bd_t *bd, int dev_id, int phy_id, uint32_t base_addr)
 {
 	struct eth_device *edev;
-	struct fec_priv *fec = &gfec;
+	struct fec_priv *fec;
 	unsigned char ethaddr[6];
 
 	/* create and fill edev struct */
 	edev = (struct eth_device *)malloc(sizeof(struct eth_device));
 	if (!edev) {
-		puts("fec_mxc: not enough malloc memory\n");
+		puts("fec_mxc: not enough malloc memory for eth_device\n");
+		return -ENOMEM;
+	}
+
+	fec = (struct fec_priv *)malloc(sizeof(struct fec_priv));
+	if (!fec) {
+		puts("fec_mxc: not enough malloc memory for fec_priv\n");
 		return -ENOMEM;
 	}
+
 	memset(edev, 0, sizeof(*edev));
+	memset(fec, 0, sizeof(*fec));
+
 	edev->priv = fec;
 	edev->init = fec_init;
 	edev->send = fec_send;
@@ -714,7 +714,7 @@ static int fec_probe(bd_t *bd)
 	edev->halt = fec_halt;
 	edev->write_hwaddr = fec_set_hwaddr;
 
-	fec->eth = (struct ethernet_regs *)IMX_FEC_BASE;
+	fec->eth = (struct ethernet_regs *)base_addr;
 	fec->bd = bd;
 
 	fec->xcv_type = CONFIG_FEC_XCV_TYPE;
@@ -744,7 +744,14 @@ static int fec_probe(bd_t *bd)
 		FEC_RCNTRL_MII_MODE, &fec->eth->r_cntrl);
 	fec_mii_setspeed(fec);
 
-	sprintf(edev->name, "FEC");
+	if (dev_id == -1) {
+		sprintf(edev->name, "FEC");
+		fec->dev_id = 0;
+	} else {
+		sprintf(edev->name, "FEC%i", dev_id);
+		fec->dev_id = dev_id;
+	}
+	fec->phy_id = phy_id;
 
 	miiphy_register(edev->name, fec_miiphy_read, fec_miiphy_write);
 
@@ -758,12 +765,24 @@ static int fec_probe(bd_t *bd)
 	return 0;
 }
 
+#ifndef	CONFIG_FEC_MXC_MULTI
 int fecmxc_initialize(bd_t *bd)
 {
 	int lout = 1;
 
 	debug("eth_init: fec_probe(bd)\n");
-	lout = fec_probe(bd);
+	lout = fec_probe(bd, -1, CONFIG_FEC_MXC_PHYADDR, IMX_FEC_BASE);
+
+	return lout;
+}
+#endif
+
+int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr)
+{
+	int lout = 1;
+
+	debug("eth_init: fec_probe(bd, %i, %i) @ %08x\n", dev_id, phy_id, addr);
+	lout = fec_probe(bd, dev_id, phy_id, addr);
 
 	return lout;
 }
drivers/net/fec_mxc.h +2 -0
index f16f9db..e436c22 100644
@@ -275,6 +275,8 @@ struct fec_priv {
 	bd_t *bd;
 	void *rdb_ptr;
 	void *base_ptr;
+	int dev_id;
+	int phy_id;
 };
 
 /**
include/netdev.h +1 -1
index 6f0a971..6e70341 100644
@@ -61,6 +61,7 @@ int ethoc_initialize(u8 dev_num, int base_addr);
 int eth_3com_initialize (bd_t * bis);
 int fec_initialize (bd_t *bis);
 int fecmxc_initialize (bd_t *bis);
+int fecmxc_initialize_multi(bd_t *bis, int dev_id, int phy_id, uint32_t addr);
 int ftgmac100_initialize(bd_t *bits);
 int ftmac100_initialize(bd_t *bits);
 int greth_initialize(bd_t *bis);
@@ -93,7 +94,6 @@ int uli526x_initialize(bd_t *bis);
 int xilinx_emaclite_initialize (bd_t *bis, int base_addr);
 int sh_eth_initialize(bd_t *bis);
 int dm9000_initialize(bd_t *bis);
-int fecmxc_initialize(bd_t *bis);
 
 /* Boards with PCI network controllers can call this from their board_eth_init()
  * function to initialize whatever's on board.
Signature · 1 line
1.7.5.4
#12 lore raw

PATCH 8/11 FEC: Allow registering MII postconfiguration callback

In reply to Marek Vasut
Cc Ben Warren <[email protected]>
Cc Stefano Babic <[email protected]>
Cc Wolfgang Denk <[email protected]>
Cc Detlev Zundel <[email protected]>
---
 drivers/net/fec_mxc.c |   14 +++++++++++++-
 drivers/net/fec_mxc.h |    1 +
 include/netdev.h      |    5 +++++
 3 files changed, 19 insertions(+), 1 deletions(-)
drivers/net/fec_mxc.c +13 -1
index 44b7919..989e7b4 100644
@@ -153,6 +153,7 @@ static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr,
 static int miiphy_restart_aneg(struct eth_device *dev)
 {
 	struct fec_priv *fec = (struct fec_priv *)dev->priv;
+	int ret = 0;
 
 	/*
 	 * Wake up from sleep if necessary
@@ -173,7 +174,11 @@ static int miiphy_restart_aneg(struct eth_device *dev)
 			LPA_10HALF | PHY_ANLPAR_PSB_802_3);
 	miiphy_write(dev->name, fec->phy_id, MII_BMCR,
 			BMCR_ANENABLE | BMCR_ANRESTART);
-	return 0;
+
+	if (fec->mii_postcall)
+		ret = fec->mii_postcall(fec->phy_id);
+
+	return ret;
 }
 
 static int miiphy_wait_aneg(struct eth_device *dev)
@@ -786,3 +791,10 @@ int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr)
 
 	return lout;
 }
+
+int fecmxc_register_mii_postcall(struct eth_device *dev, int (*cb)(int))
+{
+	struct fec_priv *fec = (struct fec_priv *)dev->priv;
+	fec->mii_postcall = cb;
+	return 0;
+}
drivers/net/fec_mxc.h +1 -0
index e436c22..1a20388 100644
@@ -277,6 +277,7 @@ struct fec_priv {
 	void *base_ptr;
 	int dev_id;
 	int phy_id;
+	int (*mii_postcall)(int);
 };
 
 /**
include/netdev.h +5 -0
index 6e70341..1e7f5c1 100644
@@ -184,4 +184,9 @@ struct mv88e61xx_config {
 int mv88e61xx_switch_initialize(struct mv88e61xx_config *swconfig);
 #endif /* CONFIG_MV88E61XX_SWITCH */
 
+/*
+ * Allow FEC to fine-tune MII configuration on boards which require this.
+ */
+int fecmxc_register_mii_postcall(struct eth_device *dev, int (*cb)(int));
+
 #endif /* _NETDEV_H_ */
Signature · 1 line
1.7.5.4
#13 lore raw

PATCH 9/11 FEC: Add timeout for chip reset

In reply to Marek Vasut
Cc Ben Warren <[email protected]>
Cc Stefano Babic <[email protected]>
Cc Wolfgang Denk <[email protected]>
Cc Detlev Zundel <[email protected]>
---
 drivers/net/fec_mxc.c |   25 +++++++++++++++++++++----
 1 files changed, 21 insertions(+), 4 deletions(-)
drivers/net/fec_mxc.c +21 -4
index 989e7b4..4518457 100644
@@ -695,18 +695,22 @@ static int fec_probe(bd_t *bd, int dev_id, int phy_id, uint32_t base_addr)
 	struct eth_device *edev;
 	struct fec_priv *fec;
 	unsigned char ethaddr[6];
+	uint32_t start;
+	int ret = 0;
 
 	/* create and fill edev struct */
 	edev = (struct eth_device *)malloc(sizeof(struct eth_device));
 	if (!edev) {
 		puts("fec_mxc: not enough malloc memory for eth_device\n");
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto err1;
 	}
 
 	fec = (struct fec_priv *)malloc(sizeof(struct fec_priv));
 	if (!fec) {
 		puts("fec_mxc: not enough malloc memory for fec_priv\n");
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto err2;
 	}
 
 	memset(edev, 0, sizeof(*edev));
@@ -726,8 +730,14 @@ static int fec_probe(bd_t *bd, int dev_id, int phy_id, uint32_t base_addr)
 
 	/* Reset chip. */
 	writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_RESET, &fec->eth->ecntrl);
-	while (readl(&fec->eth->ecntrl) & FEC_ECNTRL_RESET)
+	start = get_timer(0);
+	while (readl(&fec->eth->ecntrl) & FEC_ECNTRL_RESET) {
+		if (get_timer(start) > (CONFIG_SYS_HZ * 5)) {
+			printf("FEC MXC: Timeout reseting chip\n");
+			goto err3;
+		}
 		udelay(10);
+	}
 
 	/*
 	 * Set interrupt mask register
@@ -767,7 +777,14 @@ static int fec_probe(bd_t *bd, int dev_id, int phy_id, uint32_t base_addr)
 		memcpy(edev->enetaddr, ethaddr, 6);
 	}
 
-	return 0;
+	return ret;
+
+err3:
+	free(fec);
+err2:
+	free(edev);
+err1:
+	return ret;
 }
 
 #ifndef	CONFIG_FEC_MXC_MULTI
Signature · 1 line
1.7.5.4
#14 lore raw

PATCH 10/11 FEC: Squish "got MAC from fuse" message, make it debug()

In reply to Marek Vasut
Cc Ben Warren <[email protected]>
Cc Stefano Babic <[email protected]>
Cc Wolfgang Denk <[email protected]>
Cc Detlev Zundel <[email protected]>
---
 drivers/net/fec_mxc.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/net/fec_mxc.c +1 -1
index 4518457..fe0253e 100644
@@ -773,7 +773,7 @@ static int fec_probe(bd_t *bd, int dev_id, int phy_id, uint32_t base_addr)
 	eth_register(edev);
 
 	if (fec_get_hwaddr(edev, ethaddr) == 0) {
-		printf("got MAC address from fuse: %pM\n", ethaddr);
+		debug("got MAC address from fuse: %pM\n", ethaddr);
 		memcpy(edev->enetaddr, ethaddr, 6);
 	}
 
Signature · 1 line
1.7.5.4
#15 lore raw

PATCH 11/11 FEC: Move imx_get_mac_from_fuse() definition to fec_mxc.h

In reply to Marek Vasut
Cc Ben Warren <[email protected]>
Cc Stefano Babic <[email protected]>
Cc Wolfgang Denk <[email protected]>
Cc Detlev Zundel <[email protected]>
---
 arch/arm/include/asm/arch-mx25/imx-regs.h |    1 -
 arch/arm/include/asm/arch-mx27/imx-regs.h |    1 -
 arch/arm/include/asm/arch-mx35/imx-regs.h |    2 --
 arch/arm/include/asm/arch-mx5/imx-regs.h  |    2 --
 drivers/net/fec_mxc.h                     |    2 ++
 5 files changed, 2 insertions(+), 6 deletions(-)
arch/arm/include/asm/arch-mx25/imx-regs.h +0 -1
index 9e30f7c..c6efca6 100644
@@ -36,7 +36,6 @@
 #ifndef __ASSEMBLY__
 #ifdef CONFIG_FEC_MXC
 extern void mx25_fec_init_pins(void);
-extern void imx_get_mac_from_fuse(unsigned char *mac);
 #endif
 
 /* Clock Control Module (CCM) registers */
arch/arm/include/asm/arch-mx27/imx-regs.h +0 -1
index b4b2fe6..83ab216 100644
@@ -34,7 +34,6 @@ extern void mx27_uart1_init_pins(void);
 
 #ifdef CONFIG_FEC_MXC
 extern void mx27_fec_init_pins(void);
-extern void imx_get_mac_from_fuse(unsigned char *mac);
 #endif /* CONFIG_FEC_MXC */
 
 #ifdef CONFIG_MXC_MMC
arch/arm/include/asm/arch-mx35/imx-regs.h +0 -2
index e741fb0..0c566f2 100644
@@ -178,8 +178,6 @@
 #if !(defined(__KERNEL_STRICT_NAMES) || defined(__ASSEMBLY__))
 #include <asm/types.h>
 
-extern void imx_get_mac_from_fuse(unsigned char *mac);
-
 enum mxc_main_clocks {
 	CPU_CLK,
 	AHB_CLK,
arch/arm/include/asm/arch-mx5/imx-regs.h +0 -2
index a4e680b..098c300 100644
@@ -282,8 +282,6 @@
 #if !(defined(__KERNEL_STRICT_NAMES) || defined(__ASSEMBLY__))
 #include <asm/types.h>
 
-extern void imx_get_mac_from_fuse(unsigned char *mac);
-
 #define __REG(x)	(*((volatile u32 *)(x)))
 #define __REG16(x)	(*((volatile u16 *)(x)))
 #define __REG8(x)	(*((volatile u8 *)(x)))
drivers/net/fec_mxc.h +2 -0
index 1a20388..8b26645 100644
@@ -32,6 +32,8 @@
 #ifndef __FEC_MXC_H
 #define __FEC_MXC_H
 
+void imx_get_mac_from_fuse(unsigned char *mac);
+
 /**
  * Layout description of the FEC
  */
Signature · 1 line
1.7.5.4