All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH] MII Bus BitBang Imlementation for MPC85xx FCC ports
@ 2009-09-19 15:39 Luigi 'Comio' Mantellini
  2009-09-19 15:39 ` [U-Boot] [PATCH] Add MII bus implementation for FCC ports (using bitbanging) Luigi 'Comio' Mantellini
  0 siblings, 1 reply; 4+ messages in thread
From: Luigi 'Comio' Mantellini @ 2009-09-19 15:39 UTC (permalink / raw)
  To: u-boot

From: Luigi 'Comio' Mantellini <luigi.mantellini@idf-hit.com>

This patch add a MII Bus support for FCC port using a simple bitbang implementation (derived from miiphy driver).
In order to enable mii bus, you need to define the following additional macros:

CONFIG_MPC85XX_BITBANGMII - Enable the mii bus support code
CONFIG_SYS_FCC1_MDIO      - Pin used for MDIO signal
CONFIG_SYS_FCC2_MDIO
CONFIG_SYS_FCC3_MDIO
CONFIG_SYS_FCC1_MDC       - Pin used for MDC signal
CONFIG_SYS_FCC2_MDC
CONFIG_SYS_FCC3_MDC
CONFIG_SYS_FCC1_PHYADDR   - Phy address
CONFIG_SYS_FCC2_PHYADDR
CONFIG_SYS_FCC3_PHYADDR

Notice that all Pins are refered to the Parallel IO Ports (A, B, C, D). The pin number is gived by the following formula:

AbsIoPin# = (Port#) * 32 + IoPin#
 
where:

Port# is 0 for port A, 1 for port B, etc...
IoPin# is the pin is a value from 0 to 31 refered to the port
AbsIoPin# is the value request bt *_MDIO and *_MDC macros.

Any feedback is welcome.

best regards,

luigi

Luigi 'Comio' Mantellini (1):
  [OLT] Add MII bus implementation for FCC ports (using bitbanging)

 cpu/mpc85xx/ether_fcc.c |  400 ++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 379 insertions(+), 21 deletions(-)

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [U-Boot] [PATCH] Add MII bus implementation for FCC ports (using bitbanging)
  2009-09-19 15:39 [U-Boot] [PATCH] MII Bus BitBang Imlementation for MPC85xx FCC ports Luigi 'Comio' Mantellini
@ 2009-09-19 15:39 ` Luigi 'Comio' Mantellini
  2009-09-21 17:33   ` Scott Wood
  0 siblings, 1 reply; 4+ messages in thread
From: Luigi 'Comio' Mantellini @ 2009-09-19 15:39 UTC (permalink / raw)
  To: u-boot

From: Luigi 'Comio' Mantellini <luigi.mantellini@idf-hit.com>

Signed-off-by: Luigi 'Comio' Mantellini <luigi.mantellini@idf-hit.com>
---
 cpu/mpc85xx/ether_fcc.c |  400 ++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 379 insertions(+), 21 deletions(-)

diff --git a/cpu/mpc85xx/ether_fcc.c b/cpu/mpc85xx/ether_fcc.c
index 5f1414d..7d8234e 100644
--- a/cpu/mpc85xx/ether_fcc.c
+++ b/cpu/mpc85xx/ether_fcc.c
@@ -1,5 +1,9 @@
 /*
  * MPC8560 FCC Fast Ethernet
+ *
+ * Copyright (c) 2009 Industrie Dial Face S.p.A.
+ * Luigi 'Comio' Mantellini <luigi.mantellini@idf-hit.com>
+ *
  * Copyright (c) 2003 Motorola,Inc.
  * Xianghua Xiao, (X.Xiao at motorola.com)
  *
@@ -55,7 +59,11 @@
 #if defined(CONFIG_ETHER_ON_FCC) && defined(CONFIG_CMD_NET) && \
 	defined(CONFIG_NET_MULTI)
 
-static struct ether_fcc_info_s
+extern int mpc85xx_init_phy(struct eth_device *dev);
+
+struct ether_fcc_info_s;
+
+struct ether_fcc_info_s
 {
 	int ether_index;
 	int proff_enet;
@@ -63,39 +71,60 @@ static struct ether_fcc_info_s
 	ulong cpm_cr_enet_page;
 	ulong cmxfcr_mask;
 	ulong cmxfcr_value;
-}
-	ether_fcc_info[] =
+#ifdef CONFIG_MPC85XX_BITBANGMII
+	int mdiopin;
+	int mdcpin;
+	uint phyaddr;
+#endif
+};
+
+static struct ether_fcc_info_s ether_fcc_info[] =
 {
 #ifdef CONFIG_ETHER_ON_FCC1
 {
-	0,
-	PROFF_FCC1,
-	CPM_CR_FCC1_SBLOCK,
-	CPM_CR_FCC1_PAGE,
-	CONFIG_SYS_CMXFCR_MASK1,
-	CONFIG_SYS_CMXFCR_VALUE1
+	.ether_index = 0,
+	.proff_enet = PROFF_FCC1,
+	.cpm_cr_enet_sblock = CPM_CR_FCC1_SBLOCK,
+	.cpm_cr_enet_page = CPM_CR_FCC1_PAGE,
+	.cmxfcr_mask = CONFIG_SYS_CMXFCR_MASK1,
+	.cmxfcr_value = CONFIG_SYS_CMXFCR_VALUE1,
+#ifdef CONFIG_MPC85XX_BITBANGMII
+	.mdiopin = CONFIG_SYS_FCC1_MDIO,
+	.mdcpin = CONFIG_SYS_FCC1_MDC,
+	.phyaddr = CONFIG_SYS_FCC1_PHYADDR
+#endif
 },
 #endif
 
 #ifdef CONFIG_ETHER_ON_FCC2
 {
-	1,
-	PROFF_FCC2,
-	CPM_CR_FCC2_SBLOCK,
-	CPM_CR_FCC2_PAGE,
-	CONFIG_SYS_CMXFCR_MASK2,
-	CONFIG_SYS_CMXFCR_VALUE2
+	.ether_index = 1,
+	.proff_enet = PROFF_FCC2,
+	.cpm_cr_enet_sblock = CPM_CR_FCC2_SBLOCK,
+	.cpm_cr_enet_page = CPM_CR_FCC2_PAGE,
+	.cmxfcr_mask = CONFIG_SYS_CMXFCR_MASK2,
+	.cmxfcr_value = CONFIG_SYS_CMXFCR_VALUE2,
+#ifdef CONFIG_MPC85XX_BITBANGMII
+	.mdiopin =CONFIG_SYS_FCC2_MDIO,
+	.mdcpin = CONFIG_SYS_FCC2_MDC,
+	.phyaddr = CONFIG_SYS_FCC2_PHYADDR
+#endif
 },
 #endif
 
 #ifdef CONFIG_ETHER_ON_FCC3
 {
-	2,
-	PROFF_FCC3,
-	CPM_CR_FCC3_SBLOCK,
-	CPM_CR_FCC3_PAGE,
-	CONFIG_SYS_CMXFCR_MASK3,
-	CONFIG_SYS_CMXFCR_VALUE3
+	.ether_index = 2,
+	.proff_enet = PROFF_FCC3,
+	.cpm_cr_enet_sblock = CPM_CR_FCC3_SBLOCK,
+	.cpm_cr_enet_page = CPM_CR_FCC3_PAGE,
+	.cmxfcr_mask = CONFIG_SYS_CMXFCR_MASK3,
+	.cmxfcr_value = CONFIG_SYS_CMXFCR_VALUE3,
+#ifdef CONFIG_MPC85XX_BITBANGMII
+	.mdiopin =CONFIG_SYS_FCC3_MDIO,
+	.mdcpin = CONFIG_SYS_FCC3_MDC,
+	.phyaddr = CONFIG_SYS_FCC3_PHYADDR
+#endif
 },
 #endif
 };
@@ -139,6 +168,329 @@ static RTXBD rtx __attribute__ ((aligned(8)));
 
 #undef ET_DEBUG
 
+#ifdef CONFIG_MPC85XX_BITBANGMII
+
+#include <asm/iopin_85xx.h>
+
+#define DECLARE_IOPIN(iopin, pin) \
+	iopin_t iopin; \
+	iopin.port = pin / 32; \
+	iopin.pin = pin % 32; \
+	iopin.flag = 0;
+
+static inline void mpc85xx_udelay(unsigned long delay)
+{
+	udelay(delay);
+}
+
+static void mpc85xx_mdio_active(int pin)
+{
+	DECLARE_IOPIN(iopin, pin);
+
+	iopin_set_act(&iopin);
+	iopin_set_gen(&iopin);
+	iopin_set_out(&iopin);
+	iopin_set_high(&iopin);
+}
+
+static inline void mpc85xx_mdc_active(int pin)
+{
+	DECLARE_IOPIN(iopin, pin);
+
+	iopin_set_act(&iopin);
+	iopin_set_gen(&iopin);
+	iopin_set_out(&iopin);
+	iopin_set_high(&iopin);
+}
+
+static void mpc85xx_mdio_tristate(int pin)
+{
+	DECLARE_IOPIN(iopin, pin);
+
+	iopin_set_odr(&iopin);
+	iopin_set_gen(&iopin);
+	iopin_set_in(&iopin);
+	iopin_set_high(&iopin);
+}
+
+static void mpc85xx_mdio_set(int pin, int value)
+{
+	DECLARE_IOPIN(iopin, pin);
+
+	if (value)
+		iopin_set_high(&iopin);
+	else
+		iopin_set_low(&iopin);
+}
+
+static inline void mpc85xx_mdc_set(int pin, int value)
+{
+	mpc85xx_mdio_set(pin, value);
+}
+
+static int mpc85xx_mdio_get(int pin)
+{
+	DECLARE_IOPIN(iopin, pin);
+
+	if (iopin_is_high(&iopin))
+		return 1;
+	else
+		return 0;
+}
+
+/*****************************************************************************
+ *
+ * Utility to send the preamble, address, and register (common to read
+ * and write).
+ */
+static void mpc85xx_miiphy_pre (struct ether_fcc_info_s *info, char read, unsigned char addr, unsigned char reg)
+{
+	int j;			/* counter */
+
+	int mdio = info->mdiopin;
+	int mdc  = info->mdcpin;
+
+	/*
+	 * Send a 32 bit preamble ('1's) with an extra '1' bit for good measure.
+	 * The IEEE spec says this is a PHY optional requirement.  The AMD
+	 * 79C874 requires one after power up and one after a MII communications
+	 * error.  This means that we are doing more preambles than we need,
+	 * but it is safer and will be much more robust.
+	 */
+
+	mpc85xx_mdio_active(mdio);
+	mpc85xx_mdc_active(mdc);
+	mpc85xx_mdio_set(mdio, 1);
+
+	for (j = 0; j < 32; j++) {
+		mpc85xx_mdc_set(mdc, 0);
+		mpc85xx_udelay(1);
+		mpc85xx_mdc_set(mdc, 1);
+		mpc85xx_udelay(1);
+	}
+
+	/* send the start bit (01) and the read opcode (10) or write (10) */
+	mpc85xx_mdc_set(mdc, 0);
+	mpc85xx_mdio_set(mdio, 0);
+	mpc85xx_udelay(1);
+	mpc85xx_mdc_set(mdc, 1);
+	mpc85xx_udelay(1);
+	mpc85xx_mdc_set(mdc, 0);
+	mpc85xx_mdio_set(mdio, 1);
+	mpc85xx_udelay(1);
+	mpc85xx_mdc_set(mdc, 1);
+	mpc85xx_udelay(1);
+	mpc85xx_mdc_set(mdc, 0);
+	mpc85xx_mdio_set(mdio, read);
+	mpc85xx_udelay(1);
+	mpc85xx_mdc_set(mdc, 1);
+	mpc85xx_udelay(1);
+	mpc85xx_mdc_set(mdc, 0);
+	mpc85xx_mdio_set(mdio, !read);
+	mpc85xx_udelay(1);
+	mpc85xx_mdc_set(mdc, 1);
+	mpc85xx_udelay(1);
+
+	/* send the PHY address */
+	for (j = 0; j < 5; j++) {
+		mpc85xx_mdc_set(mdc, 0);
+		if ((addr & 0x10) == 0) {
+			mpc85xx_mdio_set(mdio, 0);
+		} else {
+			mpc85xx_mdio_set(mdio, 1);
+		}
+		mpc85xx_udelay(1);
+		mpc85xx_mdc_set(mdc, 1);
+		mpc85xx_udelay(1);
+		addr <<= 1;
+	}
+
+	/* send the register address */
+	for (j = 0; j < 5; j++) {
+		mpc85xx_mdc_set(mdc, 0);
+		if ((reg & 0x10) == 0) {
+			mpc85xx_mdio_set(mdio, 0);
+		} else {
+			mpc85xx_mdio_set(mdio, 1);
+		}
+		mpc85xx_udelay(1);
+		mpc85xx_mdc_set(mdc, 1);
+		mpc85xx_udelay(1);
+		reg <<= 1;
+	}
+}
+
+/*****************************************************************************
+ *
+ * Read a MII PHY register.
+ *
+ * Returns:
+ *   0 on success
+ */
+int mpc85xx_bb_miiphy_read (char *devname, unsigned char addr,
+		unsigned char reg, unsigned short *value)
+{
+	short rdreg;		/* register working value */
+	int j;			/* counter */
+
+	struct eth_device *dev;
+	struct ether_fcc_info_s *info;
+
+	int mdio;
+	int mdc;
+
+	if ((value == NULL) || (devname == NULL)) {
+		puts("NULL value pointer\n");
+		return (-1);
+	}
+
+	dev = eth_get_dev_by_name(devname);
+
+	if (dev == NULL) {
+		puts("Unknown net device: ");
+		puts(devname);
+		puts("\n");
+		return (-1);
+	}
+
+	info = (struct ether_fcc_info_s *)(dev->priv);
+
+	mdio = info->mdiopin;
+	mdc = info->mdcpin;
+
+	mpc85xx_miiphy_pre (info, 1, addr, reg);
+
+	/* tri-state our MDIO I/O pin so we can read */
+	mpc85xx_mdc_set(mdc, 0);
+	mpc85xx_mdio_tristate(mdio);
+	mpc85xx_udelay(1);
+	mpc85xx_mdc_set(mdc, 1);
+	mpc85xx_udelay(1);
+
+	/* check the turnaround bit: the PHY should be driving it to zero */
+	if (mpc85xx_mdio_get(mdio) != 0) {
+		/* puts ("PHY didn't drive TA low\n"); */
+		for (j = 0; j < 32; j++) {
+			mpc85xx_mdc_set(mdc, 0);
+			mpc85xx_udelay(1);
+			mpc85xx_mdc_set(mdc, 1);
+			mpc85xx_udelay(1);
+		}
+		/* There is no PHY, set value to 0xFFFF and return */
+		*value = 0xFFFF;
+		return (-1);
+	}
+
+	mpc85xx_mdc_set(mdc, 0);
+	mpc85xx_udelay(1);
+
+	/* read 16 bits of register data, MSB first */
+	rdreg = 0;
+	for (j = 0; j < 16; j++) {
+		mpc85xx_mdc_set(mdc, 1);
+		mpc85xx_udelay(1);
+		rdreg <<= 1;
+		rdreg |= mpc85xx_mdio_get(mdio);
+		mpc85xx_mdc_set(mdc, 0);
+		mpc85xx_udelay(1);
+	}
+
+	mpc85xx_mdc_set(mdc,  1);
+	mpc85xx_udelay(1);
+	mpc85xx_mdc_set(mdc,  0);
+	mpc85xx_udelay(1);
+	mpc85xx_mdc_set(mdc,  1);
+	mpc85xx_udelay(1);
+
+	*value = rdreg;
+
+#ifdef ET_DEBUG
+	printf ("miiphy_read(0x%x) @ 0x%x = 0x%04x\n", reg, addr, *value);
+#endif
+
+	return 0;
+}
+
+
+/*****************************************************************************
+ *
+ * Write a MII PHY register.
+ *
+ * Returns:
+ *   0 on success
+ */
+int mpc85xx_bb_miiphy_write (char *devname, unsigned char addr,
+		unsigned char reg, unsigned short value)
+{
+	int j;			/* counter */
+
+	struct eth_device *dev;
+	struct ether_fcc_info_s *info;
+
+	int mdio;
+	int mdc;
+
+	if (devname == NULL) {
+		puts("NULL value pointer\n");
+		return (-1);
+	}
+
+	dev = eth_get_dev_by_name(devname);
+
+	if (dev == NULL) {
+		puts("Unknown net device: ");
+		puts(devname);
+		puts("\n");
+		return (-1);
+	}
+
+	info = (struct ether_fcc_info_s *)(dev->priv);
+
+	mdio = info->mdiopin;
+	mdc = info->mdcpin;
+
+	mpc85xx_miiphy_pre (info, 0, addr, reg);
+
+	/* send the turnaround (10) */
+	mpc85xx_mdc_set(mdc,  0);
+	mpc85xx_mdio_set(mdio, 1);
+	mpc85xx_udelay(1);
+	mpc85xx_mdc_set(mdc,  1);
+	mpc85xx_udelay(1);
+	mpc85xx_mdc_set(mdc,  0);
+	mpc85xx_mdio_set(mdio, 0);
+	mpc85xx_udelay(1);
+	mpc85xx_mdc_set(mdc,  1);
+	mpc85xx_udelay(1);
+
+	/* write 16 bits of register data, MSB first */
+	for (j = 0; j < 16; j++) {
+		mpc85xx_mdc_set(mdc,  0);
+		if ((value & 0x00008000) == 0) {
+			mpc85xx_mdio_set(mdio, 0);
+		} else {
+			mpc85xx_mdio_set(mdio, 1);
+		}
+		mpc85xx_udelay(1);
+		mpc85xx_mdc_set(mdc,  1);
+		mpc85xx_udelay(1);
+		value <<= 1;
+	}
+
+	/*
+	 * Tri-state the MDIO line.
+	 */
+	mpc85xx_mdio_tristate(mdio);
+	mpc85xx_mdc_set(mdc,  0);
+	mpc85xx_udelay(1);
+	mpc85xx_mdc_set(mdc,  1);
+	mpc85xx_udelay(1);
+
+	return 0;
+}
+
+#endif
+
 static int fec_send(struct eth_device* dev, volatile void *packet, int length)
 {
     int i = 0;
@@ -461,6 +813,12 @@ int fec_initialize(bd_t *bis)
 		miiphy_register(dev->name,
 				bb_miiphy_read,	bb_miiphy_write);
 #endif
+#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) \
+		&& defined(CONFIG_MPC85XX_BITBANGMII)
+		miiphy_register(dev->name,
+				mpc85xx_bb_miiphy_read,	mpc85xx_bb_miiphy_write);
+		mpc85xx_init_phy(dev);
+#endif
 	}
 
 	return 1;
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [U-Boot] [PATCH] Add MII bus implementation for FCC ports (using bitbanging)
  2009-09-19 15:39 ` [U-Boot] [PATCH] Add MII bus implementation for FCC ports (using bitbanging) Luigi 'Comio' Mantellini
@ 2009-09-21 17:33   ` Scott Wood
  0 siblings, 0 replies; 4+ messages in thread
From: Scott Wood @ 2009-09-21 17:33 UTC (permalink / raw)
  To: u-boot

On Sat, Sep 19, 2009 at 05:39:37PM +0200, Luigi 'Comio' Mantellini wrote:
> +/*****************************************************************************
> + *
> + * Utility to send the preamble, address, and register (common to read
> + * and write).
> + */
> +static void mpc85xx_miiphy_pre (struct ether_fcc_info_s *info, char read, unsigned char addr, unsigned char reg)
> +{
> +	int j;			/* counter */
> +
> +	int mdio = info->mdiopin;
> +	int mdc  = info->mdcpin;
> +
> +	/*
> +	 * Send a 32 bit preamble ('1's) with an extra '1' bit for good measure.
> +	 * The IEEE spec says this is a PHY optional requirement.  The AMD
> +	 * 79C874 requires one after power up and one after a MII communications
> +	 * error.  This means that we are doing more preambles than we need,
> +	 * but it is safer and will be much more robust.
> +	 */
> +
> +	mpc85xx_mdio_active(mdio);
> +	mpc85xx_mdc_active(mdc);
> +	mpc85xx_mdio_set(mdio, 1);
> +
> +	for (j = 0; j < 32; j++) {
> +		mpc85xx_mdc_set(mdc, 0);
> +		mpc85xx_udelay(1);
> +		mpc85xx_mdc_set(mdc, 1);
> +		mpc85xx_udelay(1);
> +	}
> +
> +	/* send the start bit (01) and the read opcode (10) or write (10) */
> +	mpc85xx_mdc_set(mdc, 0);
> +	mpc85xx_mdio_set(mdio, 0);
> +	mpc85xx_udelay(1);
> +	mpc85xx_mdc_set(mdc, 1);
> +	mpc85xx_udelay(1);
> +	mpc85xx_mdc_set(mdc, 0);
> +	mpc85xx_mdio_set(mdio, 1);
> +	mpc85xx_udelay(1);


Please do not duplicate this.  Use the existing code in
drivers/net/phy/miiphybb.c, refactoring it if necessary.

Also, please attribute and preserve copyrights when you copy large chunks
of code.

-Scott

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [U-Boot] [PATCH] MII Bus BitBang Imlementation for MPC85xx FCC ports
@ 2009-09-19 15:42 Luigi 'Comio' Mantellini
  0 siblings, 0 replies; 4+ messages in thread
From: Luigi 'Comio' Mantellini @ 2009-09-19 15:42 UTC (permalink / raw)
  To: u-boot

This patch add a MII Bus support for FCC port using a simple bitbang implementation (derived from miiphy driver).
In order to enable mii bus, you need to define the following additional macros:

CONFIG_MPC85XX_BITBANGMII - Enable the mii bus support code
CONFIG_SYS_FCC1_MDIO      - Pin used for MDIO signal
CONFIG_SYS_FCC2_MDIO
CONFIG_SYS_FCC3_MDIO
CONFIG_SYS_FCC1_MDC       - Pin used for MDC signal
CONFIG_SYS_FCC2_MDC
CONFIG_SYS_FCC3_MDC
CONFIG_SYS_FCC1_PHYADDR   - Phy address
CONFIG_SYS_FCC2_PHYADDR
CONFIG_SYS_FCC3_PHYADDR

Notice that all Pins are refered to the Parallel IO Ports (A, B, C, D). The pin number is gived by the following formula:

AbsIoPin# = (Port#) * 32 + IoPin#
 
where:

Port# is 0 for port A, 1 for port B, etc...
IoPin# is the pin is a value from 0 to 31 refered to the port
AbsIoPin# is the value request bt *_MDIO and *_MDC macros.

Any feedback is welcome.

best regards,

luigi

Luigi 'Comio' Mantellini (1):
  [OLT] Add MII bus implementation for FCC ports (using bitbanging)

 cpu/mpc85xx/ether_fcc.c |  400 ++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 379 insertions(+), 21 deletions(-)

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2009-09-21 17:33 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-09-19 15:39 [U-Boot] [PATCH] MII Bus BitBang Imlementation for MPC85xx FCC ports Luigi 'Comio' Mantellini
2009-09-19 15:39 ` [U-Boot] [PATCH] Add MII bus implementation for FCC ports (using bitbanging) Luigi 'Comio' Mantellini
2009-09-21 17:33   ` Scott Wood
2009-09-19 15:42 [U-Boot] [PATCH] MII Bus BitBang Imlementation for MPC85xx FCC ports Luigi 'Comio' Mantellini

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.