mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH] gianfar: prevent resource conflict
@ 2013-05-30 15:15 Renaud Barbier
  2013-06-01  9:20 ` Sascha Hauer
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Renaud Barbier @ 2013-05-30 15:15 UTC (permalink / raw)
  To: barebox

On eTSEC Ethernet devices, there are three memory regions to map.
These regions map registers to control the TSEC interfaces, PHY
access and TBI interface.

Depending on the port number and TSEC version, some of these resources
may be shared within an instance of the driver or between instances
of the driver.

Since dev_request_mem_region returns NULL to avoid resource conflicts if
a region is already mapped the TSEC driver fails to initialise when
these regions are shared. This patch works around this and makes
all three memory regions available to each instance.

Below is a description of TSEC Ethernet port mapping for port 1 to 3.
These ports are present in CPUs susch as the mpc8544 and P2020.

Each port has three set of registers:
* region 0 maps the TSEC registers.
* region 1 maps the PHY access registers always through port 1.
* region 2 maps the TBI interface registers.

The tables below shows how registers are mapped.
For instance, for TSEC version 1:
- port 2/register set 1 i.e p2/reg1 is the same region as
  port 1/register set 1 i.e p1/reg1. That is they share port 1
  register set 1 as the same region.
  As well is p3/reg1, p1/reg0 and p1/reg2 uses p1/reg1.

- port 2/register set 0 i.e p2/reg0 is not the same region as
  port 3/register set 0 i.e p3/reg0.
  That is p2/r0 and p3/r0 are two different regions.
  However, port 2/register 2 is the same as port 2/register 0.

TSEC version 1:
ports/registers  reg0    reg1    reg2
p1               p1/r1   p1/r1   p1/r1
p2               p2/r0   p1/r1   p2/r0
p3               p3/r0   p1/r1   p3/r0

TSEC version2:
ports/registers  reg0    reg1    reg2
p1               p1/r0   p1/r1   p1/r1
p2               p2/r0   p1/r1   p2/r2
p3               p3/r0   p1/r1   p3/r2

Signed-off-by: Renaud Barbier <renaud.barbier@ge.com>
---
 drivers/net/gianfar.c |   19 ++++++++++++++++++-
 1 files changed, 18 insertions(+), 1 deletions(-)

diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 96055bd..79113a8 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -28,6 +28,8 @@
 #define RX_BUF_CNT 	PKTBUFSRX
 #define BUF_ALIGN	8
 
+static void __iomem *phyregs;
+
 /*
  * Initialize required registers to appropriate values, zeroing
  * those we don't care about (unless zero is bad, in which case,
@@ -481,8 +483,23 @@ static int gfar_probe(struct device_d *dev)
 	edev = &priv->edev;
 
 	priv->regs = dev_request_mem_region(dev, 0);
-	priv->phyregs = dev_request_mem_region(dev, 1);
+	if (priv->regs == NULL)
+		priv->regs = phyregs;
+
+	if (phyregs == NULL) {
+		phyregs = dev_request_mem_region(dev, 1);
+		if (phyregs == NULL)
+			phyregs = priv->regs;
+	}
+	priv->phyregs = phyregs;
+
 	priv->phyregs_sgmii = dev_request_mem_region(dev, 2);
+	if (priv->phyregs_sgmii == NULL) {
+		if (IS_ENABLED(CONFIG_TSECV2))
+			priv->phyregs_sgmii = priv->phyregs;
+		else
+			priv->phyregs_sgmii = priv->regs;
+	}
 
 	priv->phyaddr = gfar_info->phyaddr;
 	priv->tbicr = gfar_info->tbicr;
-- 
1.7.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH] gianfar: prevent resource conflict
  2013-05-30 15:15 [PATCH] gianfar: prevent resource conflict Renaud Barbier
@ 2013-06-01  9:20 ` Sascha Hauer
  2013-06-03  9:31   ` Renaud Barbier
  2013-06-25 13:09 ` [PATCH v2 0/2] " Renaud Barbier
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 10+ messages in thread
From: Sascha Hauer @ 2013-06-01  9:20 UTC (permalink / raw)
  To: Renaud Barbier; +Cc: barebox

On Thu, May 30, 2013 at 04:15:35PM +0100, Renaud Barbier wrote:
> On eTSEC Ethernet devices, there are three memory regions to map.
> These regions map registers to control the TSEC interfaces, PHY
> access and TBI interface.
> 
> Depending on the port number and TSEC version, some of these resources
> may be shared within an instance of the driver or between instances
> of the driver.
> 
> Since dev_request_mem_region returns NULL to avoid resource conflicts if
> a region is already mapped the TSEC driver fails to initialise when
> these regions are shared. This patch works around this and makes
> all three memory regions available to each instance.
> 
> Below is a description of TSEC Ethernet port mapping for port 1 to 3.
> These ports are present in CPUs susch as the mpc8544 and P2020.
> 
> Each port has three set of registers:
> * region 0 maps the TSEC registers.
> * region 1 maps the PHY access registers always through port 1.
> * region 2 maps the TBI interface registers.
> 
> The tables below shows how registers are mapped.
> For instance, for TSEC version 1:
> - port 2/register set 1 i.e p2/reg1 is the same region as
>   port 1/register set 1 i.e p1/reg1. That is they share port 1
>   register set 1 as the same region.
>   As well is p3/reg1, p1/reg0 and p1/reg2 uses p1/reg1.
> 
> - port 2/register set 0 i.e p2/reg0 is not the same region as
>   port 3/register set 0 i.e p3/reg0.
>   That is p2/r0 and p3/r0 are two different regions.
>   However, port 2/register 2 is the same as port 2/register 0.
> 
> TSEC version 1:
> ports/registers  reg0    reg1    reg2
> p1               p1/r1   p1/r1   p1/r1
> p2               p2/r0   p1/r1   p2/r0
> p3               p3/r0   p1/r1   p3/r0
> 
> TSEC version2:
> ports/registers  reg0    reg1    reg2
> p1               p1/r0   p1/r1   p1/r1
> p2               p2/r0   p1/r1   p2/r2
> p3               p3/r0   p1/r1   p3/r2
> 
> Signed-off-by: Renaud Barbier <renaud.barbier@ge.com>
> ---
>  drivers/net/gianfar.c |   19 ++++++++++++++++++-
>  1 files changed, 18 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
> index 96055bd..79113a8 100644
> --- a/drivers/net/gianfar.c
> +++ b/drivers/net/gianfar.c
> @@ -28,6 +28,8 @@
>  #define RX_BUF_CNT 	PKTBUFSRX
>  #define BUF_ALIGN	8
>  
> +static void __iomem *phyregs;
> +
>  /*
>   * Initialize required registers to appropriate values, zeroing
>   * those we don't care about (unless zero is bad, in which case,
> @@ -481,8 +483,23 @@ static int gfar_probe(struct device_d *dev)
>  	edev = &priv->edev;
>  
>  	priv->regs = dev_request_mem_region(dev, 0);
> -	priv->phyregs = dev_request_mem_region(dev, 1);
> +	if (priv->regs == NULL)
> +		priv->regs = phyregs;

the first resource is for the ethernet registers and no phy registers,
right?

> +
> +	if (phyregs == NULL) {
> +		phyregs = dev_request_mem_region(dev, 1);
> +		if (phyregs == NULL)
> +			phyregs = priv->regs;
> +	}
> +	priv->phyregs = phyregs;
> +
>  	priv->phyregs_sgmii = dev_request_mem_region(dev, 2);
> +	if (priv->phyregs_sgmii == NULL) {
> +		if (IS_ENABLED(CONFIG_TSECV2))
> +			priv->phyregs_sgmii = priv->phyregs;
> +		else
> +			priv->phyregs_sgmii = priv->regs;
> +	}

I think you should really register the mdio buses as separate devices
since it's the mdio buses that are shared between the different
instances, not the registers. The following may be a starting point
(untested)



From 480a54380c42d56e1b5f16fb718fe2c4a1a38ab0 Mon Sep 17 00:00:00 2001
From: Sascha Hauer <s.hauer@pengutronix.de>
Date: Sat, 1 Jun 2013 11:16:37 +0200
Subject: [PATCH] net: gfar: register mdio buses as separate devices

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/ppc/boards/freescale-p2020rdb/p2020rdb.c |   2 +
 arch/ppc/mach-mpc85xx/eth-devices.c           |  32 +++----
 arch/ppc/mach-mpc85xx/include/mach/gianfar.h  |   2 +
 drivers/net/gianfar.c                         | 117 ++++++++++++++++++--------
 drivers/net/gianfar.h                         |   5 +-
 5 files changed, 103 insertions(+), 55 deletions(-)

diff --git a/arch/ppc/boards/freescale-p2020rdb/p2020rdb.c b/arch/ppc/boards/freescale-p2020rdb/p2020rdb.c
index edb9bcd..cc4af7f 100644
--- a/arch/ppc/boards/freescale-p2020rdb/p2020rdb.c
+++ b/arch/ppc/boards/freescale-p2020rdb/p2020rdb.c
@@ -65,6 +65,8 @@ static struct gfar_info_struct gfar_info[] = {
 		.phyaddr = 1,
 		.tbiana = 0,
 		.tbicr = 0,
+		.mdiobus = -1, /* FIXME */
+		.mdiobus_sgmii = -1, /* FIXME */
 	},
 };
 
diff --git a/arch/ppc/mach-mpc85xx/eth-devices.c b/arch/ppc/mach-mpc85xx/eth-devices.c
index c6e8f36..510e57c 100644
--- a/arch/ppc/mach-mpc85xx/eth-devices.c
+++ b/arch/ppc/mach-mpc85xx/eth-devices.c
@@ -22,28 +22,28 @@
 
 #include <common.h>
 #include <driver.h>
+#include <init.h>
 #include <mach/immap_85xx.h>
 #include <mach/gianfar.h>
 
-int fsl_eth_init(int num, struct gfar_info_struct *gf)
+static int fsl_phy_init(void)
 {
-	struct resource *res;
+	int i;
+
+	for (i = 0; i < 4; i++)
+		add_generic_device("gfar-phy", i, NULL,
+				MDIO_BASE_ADDR + i * 0x1000, 0x1000,
+				IORESOURCE_MEM, NULL);
+	return 0;
+}
 
-	res = xzalloc(3 * sizeof(struct resource));
-	/* TSEC interface registers */
-	res[0].start = GFAR_BASE_ADDR + ((num - 1) * 0x1000);
-	res[0].end = res[0].start + 0x1000 - 1;
-	res[0].flags = IORESOURCE_MEM;
-	/* External PHY access always through eTSEC1 */
-	res[1].start = MDIO_BASE_ADDR;
-	res[1].end = res[1].start + 0x1000 - 1;
-	res[1].flags = IORESOURCE_MEM;
-	/* Access to TBI/RTBI interface. */
-	res[2].start = MDIO_BASE_ADDR + ((num - 1) * 0x1000);
-	res[2].end = res[2].start + 0x1000 - 1;
-	res[2].flags = IORESOURCE_MEM;
+coredevice_initcall(fsl_phy_init);
 
-	add_generic_device_res("gfar", DEVICE_ID_DYNAMIC, res, 3, gf);
+int fsl_eth_init(int num, struct gfar_info_struct *gf)
+{
+	add_generic_device("gfar", num - 1, NULL,
+			GFAR_BASE_ADDR + (num - 1) * 0x1000, 0x1000,
+			IORESOURCE_MEM, gf);
 
 	return 0;
 }
diff --git a/arch/ppc/mach-mpc85xx/include/mach/gianfar.h b/arch/ppc/mach-mpc85xx/include/mach/gianfar.h
index ae31638..48dd945 100644
--- a/arch/ppc/mach-mpc85xx/include/mach/gianfar.h
+++ b/arch/ppc/mach-mpc85xx/include/mach/gianfar.h
@@ -26,6 +26,8 @@ struct gfar_info_struct {
 	unsigned int phyaddr;
 	unsigned int tbiana;
 	unsigned int tbicr;
+	unsigned int mdiobus; /* mdio bus number (0..3) */
+	unsigned int mdiobus_sgmii; /* mdio bus number for sgmii (0..3) */
 };
 
 int fsl_eth_init(int num, struct gfar_info_struct *gf);
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 96055bd..bb4931e 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -28,6 +28,14 @@
 #define RX_BUF_CNT 	PKTBUFSRX
 #define BUF_ALIGN	8
 
+struct gfar_phy {
+	void __iomem *regs;
+	struct device_d *dev;
+	struct mii_bus miibus;
+};
+
+static struct gfar_phy *phys[4];
+
 /*
  * Initialize required registers to appropriate values, zeroing
  * those we don't care about (unless zero is bad, in which case,
@@ -184,10 +192,11 @@ static int gfar_open(struct eth_device *edev)
 {
 	int ix;
 	struct gfar_private *priv = edev->priv;
+	struct gfar_phy *phy = phys[priv->mdiobus];
 	void __iomem *regs = priv->regs;
 	int ret;
 
-	ret = phy_device_connect(edev, &priv->miibus, priv->phyaddr,
+	ret = phy_device_connect(edev, &phy->miibus, priv->phyaddr,
 				 gfar_adjust_link, 0, PHY_INTERFACE_MODE_NA);
 	if (ret)
 		return ret;
@@ -255,17 +264,21 @@ static int gfar_set_ethaddr(struct eth_device *edev, unsigned char *mac)
 }
 
 /* Writes the given phy's reg with value, using the specified MDIO regs */
-static int gfar_local_mdio_write(void __iomem *phyregs, uint addr, uint reg,
+static int gfar_local_mdio_write(int mdiobus, uint addr, uint reg,
 				uint value)
 {
+	struct gfar_phy *phy = phys[mdiobus];
 	uint64_t start;
 
-	out_be32(phyregs + GFAR_MIIMADD_OFFSET, (addr << 8) | (reg & 0x1f));
-	out_be32(phyregs + GFAR_MIIMCON_OFFSET, value);
+	if (!phy)
+		return -ENODEV;
+
+	out_be32(phy->regs + GFAR_MIIMADD_OFFSET, (addr << 8) | (reg & 0x1f));
+	out_be32(phy->regs + GFAR_MIIMCON_OFFSET, value);
 
 	start = get_time_ns();
 	while (!is_timeout(start, 10 * MSECOND)) {
-		if (!(in_be32(phyregs + GFAR_MIIMMIND_OFFSET) &
+		if (!(in_be32(phy->regs + GFAR_MIIMMIND_OFFSET) &
 					GFAR_MIIMIND_BUSY))
 			return 0;
 	}
@@ -280,24 +293,28 @@ static int gfar_local_mdio_write(void __iomem *phyregs, uint addr, uint reg,
  * notvalid bit cleared), and the bus to cease activity (miimind
  * busy bit cleared), and then returns the value
  */
-static uint gfar_local_mdio_read(void __iomem *phyregs, uint phyid, uint regnum)
+static uint gfar_local_mdio_read(int mdiobus, uint phyid, uint regnum)
 {
+	struct gfar_phy *phy = phys[mdiobus];
 	uint64_t start;
 
+	if (!phy)
+		return -ENODEV;
+
 	/* Put the address of the phy, and the register number into MIIMADD */
-	out_be32(phyregs + GFAR_MIIMADD_OFFSET, (phyid << 8) | (regnum & 0x1f));
+	out_be32(phy->regs + GFAR_MIIMADD_OFFSET, (phyid << 8) | (regnum & 0x1f));
 
 	/* Clear the command register, and wait */
-	out_be32(phyregs + GFAR_MIIMCOM_OFFSET, 0);
+	out_be32(phy->regs + GFAR_MIIMCOM_OFFSET, 0);
 
 	/* Initiate a read command, and wait */
-	out_be32(phyregs + GFAR_MIIMCOM_OFFSET, GFAR_MIIM_READ_COMMAND);
+	out_be32(phy->regs + GFAR_MIIMCOM_OFFSET, GFAR_MIIM_READ_COMMAND);
 
 	start = get_time_ns();
 	while (!is_timeout(start, 10 * MSECOND)) {
-		if (!(in_be32(phyregs + GFAR_MIIMMIND_OFFSET) &
+		if (!(in_be32(phy->regs + GFAR_MIIMMIND_OFFSET) &
 			(GFAR_MIIMIND_NOTVALID | GFAR_MIIMIND_BUSY)))
-			return in_be32(phyregs + GFAR_MIIMSTAT_OFFSET);
+			return in_be32(phy->regs + GFAR_MIIMSTAT_OFFSET);
 	}
 
 	return -EIO;
@@ -305,13 +322,13 @@ static uint gfar_local_mdio_read(void __iomem *phyregs, uint phyid, uint regnum)
 
 static void gfar_configure_serdes(struct gfar_private *priv)
 {
-	gfar_local_mdio_write(priv->phyregs_sgmii,
+	gfar_local_mdio_write(priv->mdiobus_sgmii,
 			in_be32(priv->regs + GFAR_TBIPA_OFFSET), GFAR_TBI_ANA,
 			priv->tbiana);
-	gfar_local_mdio_write(priv->phyregs_sgmii,
+	gfar_local_mdio_write(priv->mdiobus_sgmii,
 			in_be32(priv->regs + GFAR_TBIPA_OFFSET),
 			GFAR_TBI_TBICON, GFAR_TBICON_CLK_SELECT);
-	gfar_local_mdio_write(priv->phyregs_sgmii,
+	gfar_local_mdio_write(priv->mdiobus_sgmii,
 			in_be32(priv->regs + GFAR_TBIPA_OFFSET), GFAR_TBI_CR,
 			priv->tbicr);
 }
@@ -320,29 +337,33 @@ static void gfar_configure_serdes(struct gfar_private *priv)
 static void gfar_init_phy(struct eth_device *dev)
 {
 	struct gfar_private *priv = dev->priv;
+	struct gfar_phy *phy = phys[priv->mdiobus];
 	void __iomem *regs = priv->regs;
 	uint64_t start;
 
+	if (!phy)
+		return;
+
 	/* Assign a Physical address to the TBI */
 	out_be32(regs + GFAR_TBIPA_OFFSET, GFAR_TBIPA_VALUE);
 
 	/* Reset MII (due to new addresses) */
-	out_be32(priv->phyregs + GFAR_MIIMCFG_OFFSET, GFAR_MIIMCFG_RESET);
-	out_be32(priv->phyregs + GFAR_MIIMCFG_OFFSET, GFAR_MIIMCFG_INIT_VALUE);
+	out_be32(phy->regs + GFAR_MIIMCFG_OFFSET, GFAR_MIIMCFG_RESET);
+	out_be32(phy->regs + GFAR_MIIMCFG_OFFSET, GFAR_MIIMCFG_INIT_VALUE);
 
 	start = get_time_ns();
 	while (!is_timeout(start, 10 * MSECOND)) {
-		if (!(in_be32(priv->phyregs + GFAR_MIIMMIND_OFFSET) &
+		if (!(in_be32(phy->regs + GFAR_MIIMMIND_OFFSET) &
 			GFAR_MIIMIND_BUSY))
 			break;
 	}
 
-	gfar_local_mdio_write(priv->phyregs, priv->phyaddr, GFAR_MIIM_CR,
+	gfar_local_mdio_write(priv->mdiobus, priv->phyaddr, GFAR_MIIM_CR,
 			GFAR_MIIM_CR_RST);
 
 	start = get_time_ns();
 	while (!is_timeout(start, 10 * MSECOND)) {
-		if (!(gfar_local_mdio_read(priv->phyregs, priv->phyaddr,
+		if (!(gfar_local_mdio_read(priv->mdiobus, priv->phyaddr,
 					GFAR_MIIM_CR) & GFAR_MIIM_CR_RST))
 			break;
 	}
@@ -433,13 +454,12 @@ static int gfar_recv(struct eth_device *edev)
 /* Read a MII PHY register. */
 static int gfar_miiphy_read(struct mii_bus *bus, int addr, int reg)
 {
-	struct device_d *dev = bus->parent;
-	struct gfar_private *priv = bus->priv;
+	struct gfar_phy *phy = bus->priv;
 	int ret;
 
-	ret = gfar_local_mdio_read(priv->phyregs, addr, reg);
+	ret = gfar_local_mdio_read(phy->dev->id, addr, reg);
 	if (ret == -EIO)
-		dev_err(dev, "Can't read PHY at address %d\n", addr);
+		dev_err(phy->dev, "Can't read PHY at address %d\n", addr);
 
 	return ret;
 }
@@ -448,15 +468,14 @@ static int gfar_miiphy_read(struct mii_bus *bus, int addr, int reg)
 static int gfar_miiphy_write(struct mii_bus *bus, int addr, int reg,
 				u16 value)
 {
-	struct device_d *dev = bus->parent;
-	struct gfar_private *priv = bus->priv;
+	struct gfar_phy *phy = bus->priv;
 	unsigned short val = value;
 	int ret;
 
-	ret = gfar_local_mdio_write(priv->phyregs, addr, reg, val);
+	ret = gfar_local_mdio_write(phy->dev->id, addr, reg, val);
 
 	if (ret)
-		dev_err(dev, "Can't write PHY at address %d\n", addr);
+		dev_err(phy->dev, "Can't write PHY at address %d\n", addr);
 
 	return 0;
 }
@@ -481,8 +500,12 @@ static int gfar_probe(struct device_d *dev)
 	edev = &priv->edev;
 
 	priv->regs = dev_request_mem_region(dev, 0);
-	priv->phyregs = dev_request_mem_region(dev, 1);
-	priv->phyregs_sgmii = dev_request_mem_region(dev, 2);
+	priv->mdiobus = gfar_info->mdiobus;
+	priv->mdiobus_sgmii = gfar_info->mdiobus_sgmii;
+
+	if (priv->mdiobus >= ARRAY_SIZE(phys) ||
+			priv->mdiobus_sgmii >= ARRAY_SIZE(phys))
+		return -EINVAL;
 
 	priv->phyaddr = gfar_info->phyaddr;
 	priv->tbicr = gfar_info->tbicr;
@@ -512,15 +535,8 @@ static int gfar_probe(struct device_d *dev)
 	udelay(2);
 	clrbits_be32(priv->regs + GFAR_MACCFG1_OFFSET, GFAR_MACCFG1_SOFT_RESET);
 
-	priv->miibus.read = gfar_miiphy_read;
-	priv->miibus.write = gfar_miiphy_write;
-	priv->miibus.priv = priv;
-	priv->miibus.parent = dev;
-
 	gfar_init_phy(edev);
 
-	mdiobus_register(&priv->miibus);
-
 	return eth_register(edev);
 }
 
@@ -529,3 +545,32 @@ static struct driver_d gfar_eth_driver = {
 	.probe = gfar_probe,
 };
 device_platform_driver(gfar_eth_driver);
+
+static int gfar_phy_probe(struct device_d *dev)
+{
+	struct gfar_phy *phy;
+	int ret;
+
+	phy = xzalloc(sizeof(*phy));
+	phy->dev = dev;
+	phy->regs = dev_request_mem_region(dev, 0);
+	if (!phy->regs)
+		return -ENOMEM;
+
+	phy->miibus.read = gfar_miiphy_read;
+	phy->miibus.write = gfar_miiphy_write;
+	phy->miibus.priv = phy;
+	phy->miibus.parent = dev;
+
+	ret = mdiobus_register(&phy->miibus);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static struct driver_d gfar_phy_driver = {
+	.name  = "gfar-phy",
+	.probe = gfar_phy_probe,
+};
+register_driver_macro(coredevice, platform, gfar_phy_driver);
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index b52cc5a..9094506 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -266,10 +266,9 @@ struct rxbd8 {
 struct gfar_private {
 	struct eth_device edev;
 	void __iomem *regs;
-	void __iomem *phyregs;
-	void __iomem *phyregs_sgmii;
+	int mdiobus;
+	int mdiobus_sgmii;
 	struct phy_info *phyinfo;
-	struct mii_bus miibus;
 	volatile struct txbd8 *txbd;
 	volatile struct rxbd8 *rxbd;
 	uint txidx;
-- 
1.8.2.rc2

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH] gianfar: prevent resource conflict
  2013-06-01  9:20 ` Sascha Hauer
@ 2013-06-03  9:31   ` Renaud Barbier
  2013-06-04 17:01     ` Renaud Barbier
  0 siblings, 1 reply; 10+ messages in thread
From: Renaud Barbier @ 2013-06-03  9:31 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox


>> ---
>>   drivers/net/gianfar.c |   19 ++++++++++++++++++-
>>   1 files changed, 18 insertions(+), 1 deletions(-)
>>
>> diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
>> index 96055bd..79113a8 100644
>> --- a/drivers/net/gianfar.c
>> +++ b/drivers/net/gianfar.c
>> @@ -28,6 +28,8 @@
>>   #define RX_BUF_CNT 	PKTBUFSRX
>>   #define BUF_ALIGN	8
>>
>> +static void __iomem *phyregs;
>> +
>>   /*
>>    * Initialize required registers to appropriate values, zeroing
>>    * those we don't care about (unless zero is bad, in which case,
>> @@ -481,8 +483,23 @@ static int gfar_probe(struct device_d *dev)
>>   	edev = &priv->edev;
>>
>>   	priv->regs = dev_request_mem_region(dev, 0);
>> -	priv->phyregs = dev_request_mem_region(dev, 1);
>> +	if (priv->regs == NULL)
>> +		priv->regs = phyregs;
>
> the first resource is for the ethernet registers and no phy registers,
> right?

Indeed

>
>> +
>> +	if (phyregs == NULL) {
>> +		phyregs = dev_request_mem_region(dev, 1);
>> +		if (phyregs == NULL)
>> +			phyregs = priv->regs;
>> +	}
>> +	priv->phyregs = phyregs;
>> +
>>   	priv->phyregs_sgmii = dev_request_mem_region(dev, 2);
>> +	if (priv->phyregs_sgmii == NULL) {
>> +		if (IS_ENABLED(CONFIG_TSECV2))
>> +			priv->phyregs_sgmii = priv->phyregs;
>> +		else
>> +			priv->phyregs_sgmii = priv->regs;
>> +	}
>
> I think you should really register the mdio buses as separate devices
> since it's the mdio buses that are shared between the different
> instances, not the registers. The following may be a starting point
> (untested)
>

Thanks.


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH] gianfar: prevent resource conflict
  2013-06-03  9:31   ` Renaud Barbier
@ 2013-06-04 17:01     ` Renaud Barbier
  2013-06-05  7:12       ` Sascha Hauer
  0 siblings, 1 reply; 10+ messages in thread
From: Renaud Barbier @ 2013-06-04 17:01 UTC (permalink / raw)
  To: Sascha Hauer, barebox

Hello Sacha,
I applied your patch and try it on our mpc8544 based board
with a few modification.
This board uses eTSEC1. This means all 3 regions have the same
base address.

I just did the following update to your patch.
It only maps the eTSEC registers and mdio bus registers.

  static int fsl_phy_init(void)
{
          add_generic_device("gfar-phy", 0, NULL, MDIO_BASE_ADDR, 0x1000,
                          IORESOURCE_MEM, NULL);
          return 0;
  }

  coredevice_initcall(fsl_phy_init);

   int fsl_eth_init(int num, struct gfar_info_struct *gf)
  {

          printf("FSL_ETH_INIT: num = %d, 0x%x\n", num - 1,
                          GFAR_BASE_ADDR + (num - 1) * 0x1000);
          add_generic_device("gfar", num - 1, NULL,
                          GFAR_BASE_ADDR + (num - 1) * 0x1000, 0x1000,
                          IORESOURCE_MEM, gf);

           return 0;
   }


I added a few debug messages in request_region and got:

barebox 2013.05.0-00706-g87df6ec-dirty #13 Tue Jun 4 17:17:34 BST 2013

Board: DA923RC

dev_request_mem_region:got resource
request_region:name = gfar-phy0, parent = 1ffa6494
request_region ok: 0xe0024000:0xe0024fff
gfar_phy_probe:phy->regs= e0024000, 0
gfar_phy_probe: id = 0
mdio_bus: miibus0: probed
...
FSL_ETH_INIT: num = 0, 0xe0024000
dev_request_mem_region:got resource
request_region:name = gfar0, parent = 1ffa6494
request_region: 0xe0024000:0xe0024fff conflicts with 0xe0024000:0xe0024fff
gfar_probe:priv->regs 00000000, 0
gfar_halt:regs = 00000000

Even though, two devices have been added, both have the same parent 
iomem and the same region is compared. A conflict is then detected.
When gfar_probe requests its Ethernet register region, NULL is returned.



_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH] gianfar: prevent resource conflict
  2013-06-04 17:01     ` Renaud Barbier
@ 2013-06-05  7:12       ` Sascha Hauer
  2013-06-05  9:05         ` Renaud Barbier
  0 siblings, 1 reply; 10+ messages in thread
From: Sascha Hauer @ 2013-06-05  7:12 UTC (permalink / raw)
  To: Renaud Barbier; +Cc: barebox

On Tue, Jun 04, 2013 at 06:01:29PM +0100, Renaud Barbier wrote:
> Hello Sacha,
> I applied your patch and try it on our mpc8544 based board
> with a few modification.
> This board uses eTSEC1. This means all 3 regions have the same
> base address.

I think I misunderstood the situation. I thought that the mdio register
space is separate from the network interface register space. So in
reality the mdio register space is inside the network register (the
TSEC) space, but one TSEC instance needs the mdio bus from the other
one, right?

If that's the case then it's probably best to register a phy driver for
each phy in a coredevice_initcall like I suggested and then use
dev_get_mem_region in the phy driver instead of dev_request_mem_region.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH] gianfar: prevent resource conflict
  2013-06-05  7:12       ` Sascha Hauer
@ 2013-06-05  9:05         ` Renaud Barbier
  0 siblings, 0 replies; 10+ messages in thread
From: Renaud Barbier @ 2013-06-05  9:05 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

On 05/06/2013 08:12, Sascha Hauer wrote:
> On Tue, Jun 04, 2013 at 06:01:29PM +0100, Renaud Barbier wrote:
>> Hello Sacha,
>> I applied your patch and try it on our mpc8544 based board
>> with a few modification.
>> This board uses eTSEC1. This means all 3 regions have the same
>> base address.
>
> I think I misunderstood the situation. I thought that the mdio register
> space is separate from the network interface register space. So in
> reality the mdio register space is inside the network register (the
> TSEC) space, but one TSEC instance needs the mdio bus from the other
> one, right?

Yes.
All eTSEC uses the eTSEC1 region to access the mdio bus for external 
PHYs. Port eTSEC1 3 regions (Ethernet reg, External phy access, TBI 
interface) are in fact just one region.

For eTSEC2, the Ethernet registers and TBI interface are mapped by the 
same region but are not the same as the other port regions.
The same applies for eTSEC3.

For TSEC version 2, the mapping is a bit different.

I will  implement your suggestions below.

>
> If that's the case then it's probably best to register a phy driver for
> each phy in a coredevice_initcall like I suggested and then use
> dev_get_mem_region in the phy driver instead of dev_request_mem_region.
>
> Sascha
>


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH v2 0/2] gianfar: prevent resource conflict
  2013-05-30 15:15 [PATCH] gianfar: prevent resource conflict Renaud Barbier
  2013-06-01  9:20 ` Sascha Hauer
@ 2013-06-25 13:09 ` Renaud Barbier
  2013-06-25 13:09 ` [PATCH 1/2] ppc: gianfar MDIO buses Renaud Barbier
  2013-06-25 13:10 ` [PATCH 2/2] P2020RDB: update build configuration Renaud Barbier
  3 siblings, 0 replies; 10+ messages in thread
From: Renaud Barbier @ 2013-06-25 13:09 UTC (permalink / raw)
  To: barebox

This patch v2 avoids resource conflicts between the gianfar port
instances by substituting dev_request_mem_region for
dev_get_mem_region.

In addition, it separates the MDIO buses from their Ethernet device
by creating MDIO bus devices to access the external bus and TBI
interfaces.

This patch is tested on the P2020RDB for which there are 3 MDIO buses:
- The main MDIO bus "gfar-mdio", linked to port eTSEC1 is used to
  connect external PHYs for all ports and map the internal TBI
  interface of eTSEC1.
- The MDIO buses "gfar-tpiphy" map TBI interface registers on all
  remaining ports.

Renaud Barbier (2):
  ppc: gianfar MDIO buses
  P2020RDB: update build configuration

 arch/ppc/boards/freescale-p2020rdb/p2020rdb.c |   13 ++-
 arch/ppc/configs/p2020rdb_defconfig           |    4 +-
 arch/ppc/mach-mpc85xx/eth-devices.c           |   44 +++++---
 arch/ppc/mach-mpc85xx/include/mach/gianfar.h  |    4 +
 drivers/net/gianfar.c                         |  146 +++++++++++++++++++------
 drivers/net/gianfar.h                         |   13 ++-
 6 files changed, 165 insertions(+), 59 deletions(-)


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 1/2] ppc: gianfar MDIO buses
  2013-05-30 15:15 [PATCH] gianfar: prevent resource conflict Renaud Barbier
  2013-06-01  9:20 ` Sascha Hauer
  2013-06-25 13:09 ` [PATCH v2 0/2] " Renaud Barbier
@ 2013-06-25 13:09 ` Renaud Barbier
  2013-06-26  6:44   ` Sascha Hauer
  2013-06-25 13:10 ` [PATCH 2/2] P2020RDB: update build configuration Renaud Barbier
  3 siblings, 1 reply; 10+ messages in thread
From: Renaud Barbier @ 2013-06-25 13:09 UTC (permalink / raw)
  To: barebox

This commit creates MDIO bus devices to separate the MDIO bus
abstraction from the Ethernet device initialisation.

It also updates the configuration of the P2020RDB ports.

Signed-off-by: Renaud Barbier <renaud.barbier@ge.com>
---
 arch/ppc/boards/freescale-p2020rdb/p2020rdb.c |   13 ++-
 arch/ppc/mach-mpc85xx/eth-devices.c           |   44 +++++---
 arch/ppc/mach-mpc85xx/include/mach/gianfar.h  |    4 +
 drivers/net/gianfar.c                         |  146 +++++++++++++++++++------
 drivers/net/gianfar.h                         |   13 ++-
 5 files changed, 162 insertions(+), 58 deletions(-)

diff --git a/arch/ppc/boards/freescale-p2020rdb/p2020rdb.c b/arch/ppc/boards/freescale-p2020rdb/p2020rdb.c
index edb9bcd..6426bd3 100644
--- a/arch/ppc/boards/freescale-p2020rdb/p2020rdb.c
+++ b/arch/ppc/boards/freescale-p2020rdb/p2020rdb.c
@@ -59,12 +59,19 @@
 #define SYSCLK_50	50000000
 #define SYSCLK_100	100000000
 
-/* Ethernet. Use eTSEC3 */
+/* Define attributes for eTSEC2 and eTSEC3 */
 static struct gfar_info_struct gfar_info[] = {
 	{
+		.phyaddr = 0,
+		.tbiana = 0x1a0,
+		.tbicr = 0x9140,
+		.mdiobus_tbi = 1,
+	},
+	{
 		.phyaddr = 1,
 		.tbiana = 0,
 		.tbicr = 0,
+		.mdiobus_tbi = 2,
 	},
 };
 
@@ -82,8 +89,8 @@ static int devices_init(void)
 	add_generic_device("i2c-fsl", 1, NULL, I2C2_BASE_ADDR,
 			0x100, IORESOURCE_MEM, &i2cplat);
 
-	/* eTSEC3 */
-	fsl_eth_init(3, &gfar_info[0]);
+	fsl_eth_init(2, &gfar_info[0]);
+	fsl_eth_init(3, &gfar_info[1]);
 
 	devfs_add_partition("nor0", 0xf80000, 0x80000, DEVFS_PARTITION_FIXED,
 			    "self0");
diff --git a/arch/ppc/mach-mpc85xx/eth-devices.c b/arch/ppc/mach-mpc85xx/eth-devices.c
index c6e8f36..611a578 100644
--- a/arch/ppc/mach-mpc85xx/eth-devices.c
+++ b/arch/ppc/mach-mpc85xx/eth-devices.c
@@ -22,28 +22,40 @@
 
 #include <common.h>
 #include <driver.h>
+#include <init.h>
 #include <mach/immap_85xx.h>
 #include <mach/gianfar.h>
 
-int fsl_eth_init(int num, struct gfar_info_struct *gf)
+static int fsl_phy_init(void)
 {
-	struct resource *res;
+	int i;
+	void __iomem *base  = IOMEM(GFAR_BASE_ADDR + GFAR_TBIPA_OFFSET);
+
+	/*
+	 * The TBI address must be initialised to enable the PHY to
+	 * link up after the MDIO reset.
+	 */
+	out_be32(base, GFAR_TBIPA_END);
+	/* All ports access external PHYs via the "gfar-mdio" device */
+	add_generic_device("gfar-mdio", 0, NULL, MDIO_BASE_ADDR,
+			0x1000, IORESOURCE_MEM, NULL);
 
-	res = xzalloc(3 * sizeof(struct resource));
-	/* TSEC interface registers */
-	res[0].start = GFAR_BASE_ADDR + ((num - 1) * 0x1000);
-	res[0].end = res[0].start + 0x1000 - 1;
-	res[0].flags = IORESOURCE_MEM;
-	/* External PHY access always through eTSEC1 */
-	res[1].start = MDIO_BASE_ADDR;
-	res[1].end = res[1].start + 0x1000 - 1;
-	res[1].flags = IORESOURCE_MEM;
-	/* Access to TBI/RTBI interface. */
-	res[2].start = MDIO_BASE_ADDR + ((num - 1) * 0x1000);
-	res[2].end = res[2].start + 0x1000 - 1;
-	res[2].flags = IORESOURCE_MEM;
+	for (i = 1; i < 3; i++) {
+		out_be32(base + (i * 0x1000), GFAR_TBIPA_END - i);
+		/* Use "gfar-tbiphy" devices to access internal PHY. */
+		add_generic_device("gfar-tbiphy", i, NULL,
+				MDIO_BASE_ADDR + (i * 0x1000),
+				0x1000, IORESOURCE_MEM, NULL);
+	}
+	return 0;
+}
 
-	add_generic_device_res("gfar", DEVICE_ID_DYNAMIC, res, 3, gf);
+coredevice_initcall(fsl_phy_init);
 
+int fsl_eth_init(int num, struct gfar_info_struct *gf)
+{
+	add_generic_device("gfar", DEVICE_ID_DYNAMIC, NULL,
+			GFAR_BASE_ADDR + ((num - 1) * 0x1000), 0x1000,
+			IORESOURCE_MEM, gf);
 	return 0;
 }
diff --git a/arch/ppc/mach-mpc85xx/include/mach/gianfar.h b/arch/ppc/mach-mpc85xx/include/mach/gianfar.h
index ae31638..6a7b9e9 100644
--- a/arch/ppc/mach-mpc85xx/include/mach/gianfar.h
+++ b/arch/ppc/mach-mpc85xx/include/mach/gianfar.h
@@ -22,10 +22,14 @@
  * Platform data for the Motorola Triple Speed Ethernet Controller
  */
 
+#define GFAR_TBIPA_OFFSET       0x030   /* TBI PHY address */
+#define GFAR_TBIPA_END		0x1f    /* Last valid PHY address */
+
 struct gfar_info_struct {
 	unsigned int phyaddr;
 	unsigned int tbiana;
 	unsigned int tbicr;
+	unsigned int mdiobus_tbi;
 };
 
 int fsl_eth_init(int num, struct gfar_info_struct *gf);
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 96055bd..f944c6c 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -184,10 +184,11 @@ static int gfar_open(struct eth_device *edev)
 {
 	int ix;
 	struct gfar_private *priv = edev->priv;
+	struct gfar_phy *phy = priv->gfar_mdio;
 	void __iomem *regs = priv->regs;
 	int ret;
 
-	ret = phy_device_connect(edev, &priv->miibus, priv->phyaddr,
+	ret = phy_device_connect(edev, &phy->miibus, priv->phyaddr,
 				 gfar_adjust_link, 0, PHY_INTERFACE_MODE_NA);
 	if (ret)
 		return ret;
@@ -305,44 +306,51 @@ static uint gfar_local_mdio_read(void __iomem *phyregs, uint phyid, uint regnum)
 
 static void gfar_configure_serdes(struct gfar_private *priv)
 {
-	gfar_local_mdio_write(priv->phyregs_sgmii,
+	struct gfar_phy *phy = priv->gfar_tbi;
+
+	gfar_local_mdio_write(phy->regs,
 			in_be32(priv->regs + GFAR_TBIPA_OFFSET), GFAR_TBI_ANA,
 			priv->tbiana);
-	gfar_local_mdio_write(priv->phyregs_sgmii,
+	gfar_local_mdio_write(phy->regs,
 			in_be32(priv->regs + GFAR_TBIPA_OFFSET),
 			GFAR_TBI_TBICON, GFAR_TBICON_CLK_SELECT);
-	gfar_local_mdio_write(priv->phyregs_sgmii,
+	gfar_local_mdio_write(phy->regs,
 			in_be32(priv->regs + GFAR_TBIPA_OFFSET), GFAR_TBI_CR,
 			priv->tbicr);
 }
 
-/* Reset the internal and external PHYs. */
-static void gfar_init_phy(struct eth_device *dev)
+static int gfar_bus_reset(struct mii_bus *bus)
 {
-	struct gfar_private *priv = dev->priv;
-	void __iomem *regs = priv->regs;
+	struct gfar_phy *phy = bus->priv;
 	uint64_t start;
 
-	/* Assign a Physical address to the TBI */
-	out_be32(regs + GFAR_TBIPA_OFFSET, GFAR_TBIPA_VALUE);
-
 	/* Reset MII (due to new addresses) */
-	out_be32(priv->phyregs + GFAR_MIIMCFG_OFFSET, GFAR_MIIMCFG_RESET);
-	out_be32(priv->phyregs + GFAR_MIIMCFG_OFFSET, GFAR_MIIMCFG_INIT_VALUE);
+	out_be32(phy->regs + GFAR_MIIMCFG_OFFSET, GFAR_MIIMCFG_RESET);
+	out_be32(phy->regs + GFAR_MIIMCFG_OFFSET, GFAR_MIIMCFG_INIT_VALUE);
 
 	start = get_time_ns();
 	while (!is_timeout(start, 10 * MSECOND)) {
-		if (!(in_be32(priv->phyregs + GFAR_MIIMMIND_OFFSET) &
+		if (!(in_be32(phy->regs + GFAR_MIIMMIND_OFFSET) &
 			GFAR_MIIMIND_BUSY))
 			break;
 	}
+	return 0;
+}
 
-	gfar_local_mdio_write(priv->phyregs, priv->phyaddr, GFAR_MIIM_CR,
+/* Reset the external PHYs. */
+static void gfar_init_phy(struct eth_device *dev)
+{
+	struct gfar_private *priv = dev->priv;
+	struct gfar_phy *phy = priv->gfar_mdio;
+	void __iomem *regs = priv->regs;
+	uint64_t start;
+
+	gfar_local_mdio_write(phy->regs, priv->phyaddr, GFAR_MIIM_CR,
 			GFAR_MIIM_CR_RST);
 
 	start = get_time_ns();
 	while (!is_timeout(start, 10 * MSECOND)) {
-		if (!(gfar_local_mdio_read(priv->phyregs, priv->phyaddr,
+		if (!(gfar_local_mdio_read(phy->regs, priv->phyaddr,
 					GFAR_MIIM_CR) & GFAR_MIIM_CR_RST))
 			break;
 	}
@@ -433,13 +441,12 @@ static int gfar_recv(struct eth_device *edev)
 /* Read a MII PHY register. */
 static int gfar_miiphy_read(struct mii_bus *bus, int addr, int reg)
 {
-	struct device_d *dev = bus->parent;
-	struct gfar_private *priv = bus->priv;
+	struct gfar_phy *phy = bus->priv;
 	int ret;
 
-	ret = gfar_local_mdio_read(priv->phyregs, addr, reg);
+	ret = gfar_local_mdio_read(phy->regs, addr, reg);
 	if (ret == -EIO)
-		dev_err(dev, "Can't read PHY at address %d\n", addr);
+		dev_err(phy->dev, "Can't read PHY at address %d\n", addr);
 
 	return ret;
 }
@@ -448,15 +455,14 @@ static int gfar_miiphy_read(struct mii_bus *bus, int addr, int reg)
 static int gfar_miiphy_write(struct mii_bus *bus, int addr, int reg,
 				u16 value)
 {
-	struct device_d *dev = bus->parent;
-	struct gfar_private *priv = bus->priv;
+	struct gfar_phy *phy = bus->priv;
 	unsigned short val = value;
 	int ret;
 
-	ret = gfar_local_mdio_write(priv->phyregs, addr, reg, val);
+	ret = gfar_local_mdio_write(phy->regs, addr, reg, val);
 
 	if (ret)
-		dev_err(dev, "Can't write PHY at address %d\n", addr);
+		dev_err(phy->dev, "Can't write PHY at address %d\n", addr);
 
 	return 0;
 }
@@ -470,7 +476,9 @@ static int gfar_probe(struct device_d *dev)
 	struct gfar_info_struct *gfar_info = dev->platform_data;
 	struct eth_device *edev;
 	struct gfar_private *priv;
+	struct device_d *mdev;
 	size_t size;
+	char devname[16];
 	char *p;
 
 	priv = xzalloc(sizeof(struct gfar_private));
@@ -480,14 +488,28 @@ static int gfar_probe(struct device_d *dev)
 
 	edev = &priv->edev;
 
-	priv->regs = dev_request_mem_region(dev, 0);
-	priv->phyregs = dev_request_mem_region(dev, 1);
-	priv->phyregs_sgmii = dev_request_mem_region(dev, 2);
-
+	priv->mdiobus_tbi = gfar_info->mdiobus_tbi;
+	priv->regs = dev_get_mem_region(dev, 0);
 	priv->phyaddr = gfar_info->phyaddr;
 	priv->tbicr = gfar_info->tbicr;
 	priv->tbiana = gfar_info->tbiana;
 
+	mdev = get_device_by_name("gfar-mdio0");
+	if (mdev == NULL) {
+		pr_err("gfar-mdio0 was not found\n");
+		return -ENODEV;
+	}
+	priv->gfar_mdio = mdev->priv;
+
+	if (priv->mdiobus_tbi != 0) {
+		sprintf(devname, "%s%d", "gfar-tbiphy", priv->mdiobus_tbi);
+		mdev = get_device_by_name(devname);
+		if (mdev == NULL) {
+			pr_err("%s was not found\n", devname);
+			return -ENODEV;
+		}
+	}
+	priv->gfar_tbi = mdev->priv;
 	/*
 	 * Allocate descriptors 64-bit aligned. Descriptors
 	 * are 8 bytes in size.
@@ -512,15 +534,8 @@ static int gfar_probe(struct device_d *dev)
 	udelay(2);
 	clrbits_be32(priv->regs + GFAR_MACCFG1_OFFSET, GFAR_MACCFG1_SOFT_RESET);
 
-	priv->miibus.read = gfar_miiphy_read;
-	priv->miibus.write = gfar_miiphy_write;
-	priv->miibus.priv = priv;
-	priv->miibus.parent = dev;
-
 	gfar_init_phy(edev);
 
-	mdiobus_register(&priv->miibus);
-
 	return eth_register(edev);
 }
 
@@ -529,3 +544,64 @@ static struct driver_d gfar_eth_driver = {
 	.probe = gfar_probe,
 };
 device_platform_driver(gfar_eth_driver);
+
+static int gfar_phy_probe(struct device_d *dev)
+{
+	struct gfar_phy *phy;
+	int ret;
+
+	phy = xzalloc(sizeof(*phy));
+	phy->dev = dev;
+	phy->regs = dev_get_mem_region(dev, 0);
+	if (!phy->regs)
+		return -ENOMEM;
+
+	phy->miibus.read = gfar_miiphy_read;
+	phy->miibus.write = gfar_miiphy_write;
+	phy->miibus.priv = phy;
+	phy->miibus.reset = gfar_bus_reset;
+	phy->miibus.parent = dev;
+	dev->priv = phy;
+
+	ret = mdiobus_register(&phy->miibus);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static struct driver_d gfar_phy_driver = {
+	.name  = "gfar-mdio",
+	.probe = gfar_phy_probe,
+};
+register_driver_macro(coredevice, platform, gfar_phy_driver);
+
+static int gfar_tbiphy_probe(struct device_d *dev)
+{
+	struct gfar_phy *phy;
+	int ret;
+
+	phy = xzalloc(sizeof(*phy));
+	phy->dev = dev;
+	phy->regs = dev_get_mem_region(dev, 0);
+	if (!phy->regs)
+		return -ENOMEM;
+
+	phy->miibus.read = gfar_miiphy_read;
+	phy->miibus.write = gfar_miiphy_write;
+	phy->miibus.priv = phy;
+	phy->miibus.parent = dev;
+	dev->priv = phy;
+
+	ret = mdiobus_register(&phy->miibus);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static struct driver_d gfar_tbiphy_driver = {
+	.name  = "gfar-tbiphy",
+	.probe = gfar_tbiphy_probe,
+};
+register_driver_macro(coredevice, platform, gfar_tbiphy_driver);
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index b52cc5a..1aac479 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -205,7 +205,6 @@ struct rxbd8 {
 #define GFAR_ECNTRL_OFFSET	0x020	/* Ethernet Control */
 #define GFAR_MINFLR_OFFSET	0x024	/* Minimum Frame Length */
 #define GFAR_DMACTRL_OFFSET	0x02c	/* DMA Control */
-#define GFAR_TBIPA_OFFSET	0x030	/* TBI PHY address */
 
 /* eTSEC transmit control and status register */
 #define GFAR_TSTAT_OFFSET	0x104	/* transmit status register */
@@ -263,13 +262,19 @@ struct rxbd8 {
 #define GFAR_ATTR_OFFSET	0xbf8	/* Default Attribute Register */
 #define GFAR_ATTRELI_OFFSET	0xbfc	/* Default Attribute Extract Len/Idx */
 
+struct gfar_phy {
+	void __iomem *regs;
+	struct device_d *dev;
+	struct mii_bus miibus;
+};
+
 struct gfar_private {
 	struct eth_device edev;
 	void __iomem *regs;
-	void __iomem *phyregs;
-	void __iomem *phyregs_sgmii;
+	int mdiobus_tbi;
+	struct gfar_phy *gfar_mdio;
+	struct gfar_phy *gfar_tbi;
 	struct phy_info *phyinfo;
-	struct mii_bus miibus;
 	volatile struct txbd8 *txbd;
 	volatile struct rxbd8 *rxbd;
 	uint txidx;
-- 
1.7.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 2/2] P2020RDB: update build configuration
  2013-05-30 15:15 [PATCH] gianfar: prevent resource conflict Renaud Barbier
                   ` (2 preceding siblings ...)
  2013-06-25 13:09 ` [PATCH 1/2] ppc: gianfar MDIO buses Renaud Barbier
@ 2013-06-25 13:10 ` Renaud Barbier
  3 siblings, 0 replies; 10+ messages in thread
From: Renaud Barbier @ 2013-06-25 13:10 UTC (permalink / raw)
  To: barebox

Update the P2020RDB build configuration to enable useful development
commands.

Signed-off-by: Renaud Barbier <renaud.barbier@ge.com>
---
 arch/ppc/configs/p2020rdb_defconfig |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/arch/ppc/configs/p2020rdb_defconfig b/arch/ppc/configs/p2020rdb_defconfig
index 7690327..0f77903 100644
--- a/arch/ppc/configs/p2020rdb_defconfig
+++ b/arch/ppc/configs/p2020rdb_defconfig
@@ -24,9 +24,11 @@ CONFIG_RELOCATABLE=y
 CONFIG_DRIVER_NET_GIANFAR=y
 CONFIG_NET=y
 CONFIG_NET_PING=y
+CONFIG_FS_TFTP=y
 CONFIG_NET_TFTP=y
+CONFIG_CMD_TFTP=y
 CONFIG_PING=y
-CONFIG_TFTP=y
 CONFIG_I2C=y
 CONFIG_I2C_IMX=y
 CONFIG_CMD_I2C=y
+CONFIG_CMD_MIITOOL=y
-- 
1.7.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH 1/2] ppc: gianfar MDIO buses
  2013-06-25 13:09 ` [PATCH 1/2] ppc: gianfar MDIO buses Renaud Barbier
@ 2013-06-26  6:44   ` Sascha Hauer
  0 siblings, 0 replies; 10+ messages in thread
From: Sascha Hauer @ 2013-06-26  6:44 UTC (permalink / raw)
  To: Renaud Barbier; +Cc: barebox

On Tue, Jun 25, 2013 at 02:09:59PM +0100, Renaud Barbier wrote:
> This commit creates MDIO bus devices to separate the MDIO bus
> abstraction from the Ethernet device initialisation.
> 
> It also updates the configuration of the P2020RDB ports.
> 
> Signed-off-by: Renaud Barbier <renaud.barbier@ge.com>

Applied, thanks

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

end of thread, other threads:[~2013-06-26  6:45 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-30 15:15 [PATCH] gianfar: prevent resource conflict Renaud Barbier
2013-06-01  9:20 ` Sascha Hauer
2013-06-03  9:31   ` Renaud Barbier
2013-06-04 17:01     ` Renaud Barbier
2013-06-05  7:12       ` Sascha Hauer
2013-06-05  9:05         ` Renaud Barbier
2013-06-25 13:09 ` [PATCH v2 0/2] " Renaud Barbier
2013-06-25 13:09 ` [PATCH 1/2] ppc: gianfar MDIO buses Renaud Barbier
2013-06-26  6:44   ` Sascha Hauer
2013-06-25 13:10 ` [PATCH 2/2] P2020RDB: update build configuration Renaud Barbier

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox