All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v2 0/7] net/ethoc improvements
@ 2016-08-05 15:26 Max Filippov
  2016-08-05 15:26 ` [U-Boot] [PATCH v2 1/7] net/ethoc: add Kconfig entry for the driver Max Filippov
                   ` (6 more replies)
  0 siblings, 7 replies; 16+ messages in thread
From: Max Filippov @ 2016-08-05 15:26 UTC (permalink / raw)
  To: u-boot

Hello,

this series does the following improvements to the OpenCores 10/100 Mbps
driver:
- add Kconfig symbol for the driver;
- add DM_ETH support;
- add device tree support;
- add optional phylib support;
- add support for configurations with private packet memory;
- clean up virtual/physical address usage.

Changes v1->v2:
- rename ethoc_set_mac_address to ethoc_write_hwaddr_common;
- rename ethoc_recv_common to ethoc_is_new_packet_received;
- use positive logic with CONFIG_DM_ETH;
- return from DM ethoc_recv when ethoc_is_new_packet_received returns 0;
- use wait_for_bit in ethoc_mdio_read/ethoc_mdio_write;
- remove stray ioremap addition/removal across the series.

Max Filippov (7):
  net/ethoc: add Kconfig entry for the driver
  net/ethoc: use priv instead of dev internally
  net/ethoc: add CONFIG_DM_ETH support
  net/ethoc: support device tree
  net/ethoc: don't mix virtual and physical addresses
  net/ethoc: support private memory configurations
  net/ethoc: implement MDIO bus and support phylib

 configs/openrisc-generic_defconfig   |   2 +
 drivers/net/Kconfig                  |   5 +
 drivers/net/ethoc.c                  | 526 ++++++++++++++++++++++++++++-------
 include/configs/openrisc-generic.h   |   1 -
 include/dm/platform_data/net_ethoc.h |  21 ++
 5 files changed, 454 insertions(+), 101 deletions(-)
 create mode 100644 include/dm/platform_data/net_ethoc.h

-- 
2.1.4

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

* [U-Boot] [PATCH v2 1/7] net/ethoc: add Kconfig entry for the driver
  2016-08-05 15:26 [U-Boot] [PATCH v2 0/7] net/ethoc improvements Max Filippov
@ 2016-08-05 15:26 ` Max Filippov
  2016-08-15 20:33   ` [U-Boot] " Joe Hershberger
  2016-08-05 15:26 ` [U-Boot] [PATCH v2 2/7] net/ethoc: use priv instead of dev internally Max Filippov
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 16+ messages in thread
From: Max Filippov @ 2016-08-05 15:26 UTC (permalink / raw)
  To: u-boot

Add Kconfig entry for the driver, remove #define CONFIG_ETHOC from the
only board configuration that uses it and put it into that board's
defconfig.

Cc: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Acked-by: Joe Hershberger <joe.hershberger@ni.com>
---
 configs/openrisc-generic_defconfig | 2 ++
 drivers/net/Kconfig                | 5 +++++
 include/configs/openrisc-generic.h | 1 -
 3 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/configs/openrisc-generic_defconfig b/configs/openrisc-generic_defconfig
index 14923c0..5bc81cc 100644
--- a/configs/openrisc-generic_defconfig
+++ b/configs/openrisc-generic_defconfig
@@ -6,5 +6,7 @@ CONFIG_TARGET_OPENRISC_GENERIC=y
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
+CONFIG_NETDEVICES=y
+CONFIG_ETHOC=y
 CONFIG_SYS_NS16550=y
 # CONFIG_AUTOBOOT is not set
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 88d8e83..be3ed73 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -124,6 +124,11 @@ config ETH_DESIGNWARE
 	  100Mbit and 1 Gbit operation. You must enable CONFIG_PHYLIB to
 	  provide the PHY (physical media interface).
 
+config ETHOC
+	bool "OpenCores 10/100 Mbps Ethernet MAC"
+	help
+	  This MAC is present in OpenRISC and Xtensa XTFPGA boards.
+
 config MVPP2
 	bool "Marvell Armada 375 network interface support"
 	depends on ARMADA_375
diff --git a/include/configs/openrisc-generic.h b/include/configs/openrisc-generic.h
index 913256a..227c0ca 100644
--- a/include/configs/openrisc-generic.h
+++ b/include/configs/openrisc-generic.h
@@ -44,7 +44,6 @@
 /*
  * Ethernet
  */
-#define CONFIG_ETHOC
 #define CONFIG_SYS_ETHOC_BASE		0x92000000
 
 #define CONFIG_BOOTFILE			"boot.img"
-- 
2.1.4

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

* [U-Boot] [PATCH v2 2/7] net/ethoc: use priv instead of dev internally
  2016-08-05 15:26 [U-Boot] [PATCH v2 0/7] net/ethoc improvements Max Filippov
  2016-08-05 15:26 ` [U-Boot] [PATCH v2 1/7] net/ethoc: add Kconfig entry for the driver Max Filippov
@ 2016-08-05 15:26 ` Max Filippov
  2016-08-15 20:33   ` [U-Boot] " Joe Hershberger
  2016-08-05 15:26 ` [U-Boot] [PATCH v2 3/7] net/ethoc: add CONFIG_DM_ETH support Max Filippov
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 16+ messages in thread
From: Max Filippov @ 2016-08-05 15:26 UTC (permalink / raw)
  To: u-boot

Don't use physical base address of registers directly, ioremap it first.
Save pointer in private struct ethoc and use that struct in all internal
functions.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Acked-by: Joe Hershberger <joe.hershberger@ni.com>
---
 drivers/net/ethoc.c | 111 ++++++++++++++++++++++++++--------------------------
 1 file changed, 56 insertions(+), 55 deletions(-)

diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index edb3c80..f5bd1ab 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -12,11 +12,10 @@
  */
 
 #include <common.h>
-#include <command.h>
+#include <linux/io.h>
 #include <malloc.h>
 #include <net.h>
 #include <miiphy.h>
-#include <asm/io.h>
 #include <asm/cache.h>
 
 /* register offsets */
@@ -162,6 +161,7 @@
 #define	ETHOC_BD_BASE		0x400
 #define	ETHOC_TIMEOUT		(HZ / 2)
 #define	ETHOC_MII_TIMEOUT	(1 + (HZ / 5))
+#define	ETHOC_IOSIZE		0x54
 
 /**
  * struct ethoc - driver-private device structure
@@ -177,6 +177,7 @@ struct ethoc {
 	u32 dty_tx;
 	u32 num_rx;
 	u32 cur_rx;
+	void __iomem *iobase;
 };
 
 /**
@@ -189,64 +190,64 @@ struct ethoc_bd {
 	u32 addr;
 };
 
-static inline u32 ethoc_read(struct eth_device *dev, size_t offset)
+static inline u32 ethoc_read(struct ethoc *priv, size_t offset)
 {
-	return readl(dev->iobase + offset);
+	return readl(priv->iobase + offset);
 }
 
-static inline void ethoc_write(struct eth_device *dev, size_t offset, u32 data)
+static inline void ethoc_write(struct ethoc *priv, size_t offset, u32 data)
 {
-	writel(data, dev->iobase + offset);
+	writel(data, priv->iobase + offset);
 }
 
-static inline void ethoc_read_bd(struct eth_device *dev, int index,
+static inline void ethoc_read_bd(struct ethoc *priv, int index,
 				 struct ethoc_bd *bd)
 {
 	size_t offset = ETHOC_BD_BASE + (index * sizeof(struct ethoc_bd));
-	bd->stat = ethoc_read(dev, offset + 0);
-	bd->addr = ethoc_read(dev, offset + 4);
+	bd->stat = ethoc_read(priv, offset + 0);
+	bd->addr = ethoc_read(priv, offset + 4);
 }
 
-static inline void ethoc_write_bd(struct eth_device *dev, int index,
+static inline void ethoc_write_bd(struct ethoc *priv, int index,
 				  const struct ethoc_bd *bd)
 {
 	size_t offset = ETHOC_BD_BASE + (index * sizeof(struct ethoc_bd));
-	ethoc_write(dev, offset + 0, bd->stat);
-	ethoc_write(dev, offset + 4, bd->addr);
+	ethoc_write(priv, offset + 0, bd->stat);
+	ethoc_write(priv, offset + 4, bd->addr);
 }
 
 static int ethoc_set_mac_address(struct eth_device *dev)
 {
+	struct ethoc *priv = (struct ethoc *)dev->priv;
 	u8 *mac = dev->enetaddr;
 
-	ethoc_write(dev, MAC_ADDR0, (mac[2] << 24) | (mac[3] << 16) |
+	ethoc_write(priv, MAC_ADDR0, (mac[2] << 24) | (mac[3] << 16) |
 		    (mac[4] << 8) | (mac[5] << 0));
-	ethoc_write(dev, MAC_ADDR1, (mac[0] << 8) | (mac[1] << 0));
+	ethoc_write(priv, MAC_ADDR1, (mac[0] << 8) | (mac[1] << 0));
 	return 0;
 }
 
-static inline void ethoc_ack_irq(struct eth_device *dev, u32 mask)
+static inline void ethoc_ack_irq(struct ethoc *priv, u32 mask)
 {
-	ethoc_write(dev, INT_SOURCE, mask);
+	ethoc_write(priv, INT_SOURCE, mask);
 }
 
-static inline void ethoc_enable_rx_and_tx(struct eth_device *dev)
+static inline void ethoc_enable_rx_and_tx(struct ethoc *priv)
 {
-	u32 mode = ethoc_read(dev, MODER);
+	u32 mode = ethoc_read(priv, MODER);
 	mode |= MODER_RXEN | MODER_TXEN;
-	ethoc_write(dev, MODER, mode);
+	ethoc_write(priv, MODER, mode);
 }
 
-static inline void ethoc_disable_rx_and_tx(struct eth_device *dev)
+static inline void ethoc_disable_rx_and_tx(struct ethoc *priv)
 {
-	u32 mode = ethoc_read(dev, MODER);
+	u32 mode = ethoc_read(priv, MODER);
 	mode &= ~(MODER_RXEN | MODER_TXEN);
-	ethoc_write(dev, MODER, mode);
+	ethoc_write(priv, MODER, mode);
 }
 
-static int ethoc_init_ring(struct eth_device *dev)
+static int ethoc_init_ring(struct ethoc *priv)
 {
-	struct ethoc *priv = (struct ethoc *)dev->priv;
 	struct ethoc_bd bd;
 	int i;
 
@@ -261,7 +262,7 @@ static int ethoc_init_ring(struct eth_device *dev)
 		if (i == priv->num_tx - 1)
 			bd.stat |= TX_BD_WRAP;
 
-		ethoc_write_bd(dev, i, &bd);
+		ethoc_write_bd(priv, i, &bd);
 	}
 
 	bd.stat = RX_BD_EMPTY | RX_BD_IRQ;
@@ -272,35 +273,35 @@ static int ethoc_init_ring(struct eth_device *dev)
 			bd.stat |= RX_BD_WRAP;
 
 		flush_dcache_range(bd.addr, bd.addr + PKTSIZE_ALIGN);
-		ethoc_write_bd(dev, priv->num_tx + i, &bd);
+		ethoc_write_bd(priv, priv->num_tx + i, &bd);
 	}
 
 	return 0;
 }
 
-static int ethoc_reset(struct eth_device *dev)
+static int ethoc_reset(struct ethoc *priv)
 {
 	u32 mode;
 
 	/* TODO: reset controller? */
 
-	ethoc_disable_rx_and_tx(dev);
+	ethoc_disable_rx_and_tx(priv);
 
 	/* TODO: setup registers */
 
 	/* enable FCS generation and automatic padding */
-	mode = ethoc_read(dev, MODER);
+	mode = ethoc_read(priv, MODER);
 	mode |= MODER_CRC | MODER_PAD;
-	ethoc_write(dev, MODER, mode);
+	ethoc_write(priv, MODER, mode);
 
 	/* set full-duplex mode */
-	mode = ethoc_read(dev, MODER);
+	mode = ethoc_read(priv, MODER);
 	mode |= MODER_FULLD;
-	ethoc_write(dev, MODER, mode);
-	ethoc_write(dev, IPGT, 0x15);
+	ethoc_write(priv, MODER, mode);
+	ethoc_write(priv, IPGT, 0x15);
 
-	ethoc_ack_irq(dev, INT_MASK_ALL);
-	ethoc_enable_rx_and_tx(dev);
+	ethoc_ack_irq(priv, INT_MASK_ALL);
+	ethoc_enable_rx_and_tx(priv);
 	return 0;
 }
 
@@ -311,9 +312,9 @@ static int ethoc_init(struct eth_device *dev, bd_t * bd)
 
 	priv->num_tx = 1;
 	priv->num_rx = PKTBUFSRX;
-	ethoc_write(dev, TX_BD_NUM, priv->num_tx);
-	ethoc_init_ring(dev);
-	ethoc_reset(dev);
+	ethoc_write(priv, TX_BD_NUM, priv->num_tx);
+	ethoc_init_ring(priv);
+	ethoc_reset(priv);
 
 	return 0;
 }
@@ -353,9 +354,8 @@ static int ethoc_update_rx_stats(struct ethoc_bd *bd)
 	return ret;
 }
 
-static int ethoc_rx(struct eth_device *dev, int limit)
+static int ethoc_rx(struct ethoc *priv, int limit)
 {
-	struct ethoc *priv = (struct ethoc *)dev->priv;
 	int count;
 
 	for (count = 0; count < limit; ++count) {
@@ -363,7 +363,7 @@ static int ethoc_rx(struct eth_device *dev, int limit)
 		struct ethoc_bd bd;
 
 		entry = priv->num_tx + (priv->cur_rx % priv->num_rx);
-		ethoc_read_bd(dev, entry, &bd);
+		ethoc_read_bd(priv, entry, &bd);
 		if (bd.stat & RX_BD_EMPTY)
 			break;
 
@@ -379,7 +379,7 @@ static int ethoc_rx(struct eth_device *dev, int limit)
 		flush_dcache_range(bd.addr, bd.addr + PKTSIZE_ALIGN);
 		bd.stat &= ~RX_BD_STATS;
 		bd.stat |= RX_BD_EMPTY;
-		ethoc_write_bd(dev, entry, &bd);
+		ethoc_write_bd(priv, entry, &bd);
 		priv->cur_rx++;
 	}
 
@@ -403,13 +403,12 @@ static int ethoc_update_tx_stats(struct ethoc_bd *bd)
 	return 0;
 }
 
-static void ethoc_tx(struct eth_device *dev)
+static void ethoc_tx(struct ethoc *priv)
 {
-	struct ethoc *priv = (struct ethoc *)dev->priv;
 	u32 entry = priv->dty_tx % priv->num_tx;
 	struct ethoc_bd bd;
 
-	ethoc_read_bd(dev, entry, &bd);
+	ethoc_read_bd(priv, entry, &bd);
 	if ((bd.stat & TX_BD_READY) == 0)
 		(void)ethoc_update_tx_stats(&bd);
 }
@@ -423,7 +422,7 @@ static int ethoc_send(struct eth_device *dev, void *packet, int length)
 	int tmo;
 
 	entry = priv->cur_tx % priv->num_tx;
-	ethoc_read_bd(dev, entry, &bd);
+	ethoc_read_bd(priv, entry, &bd);
 	if (unlikely(length < ETHOC_ZLEN))
 		bd.stat |= TX_BD_PAD;
 	else
@@ -433,22 +432,22 @@ static int ethoc_send(struct eth_device *dev, void *packet, int length)
 	flush_dcache_range(bd.addr, bd.addr + length);
 	bd.stat &= ~(TX_BD_STATS | TX_BD_LEN_MASK);
 	bd.stat |= TX_BD_LEN(length);
-	ethoc_write_bd(dev, entry, &bd);
+	ethoc_write_bd(priv, entry, &bd);
 
 	/* start transmit */
 	bd.stat |= TX_BD_READY;
-	ethoc_write_bd(dev, entry, &bd);
+	ethoc_write_bd(priv, entry, &bd);
 
 	/* wait for transfer to succeed */
 	tmo = get_timer(0) + 5 * CONFIG_SYS_HZ;
 	while (1) {
-		pending = ethoc_read(dev, INT_SOURCE);
-		ethoc_ack_irq(dev, pending & ~INT_MASK_RX);
+		pending = ethoc_read(priv, INT_SOURCE);
+		ethoc_ack_irq(priv, pending & ~INT_MASK_RX);
 		if (pending & INT_MASK_BUSY)
 			debug("%s(): packet dropped\n", __func__);
 
 		if (pending & INT_MASK_TX) {
-			ethoc_tx(dev);
+			ethoc_tx(priv);
 			break;
 		}
 		if (get_timer(0) >= tmo) {
@@ -463,20 +462,21 @@ static int ethoc_send(struct eth_device *dev, void *packet, int length)
 
 static void ethoc_halt(struct eth_device *dev)
 {
-	ethoc_disable_rx_and_tx(dev);
+	ethoc_disable_rx_and_tx(dev->priv);
 }
 
 static int ethoc_recv(struct eth_device *dev)
 {
+	struct ethoc *priv = (struct ethoc *)dev->priv;
 	u32 pending;
 
-	pending = ethoc_read(dev, INT_SOURCE);
-	ethoc_ack_irq(dev, pending);
+	pending = ethoc_read(priv, INT_SOURCE);
+	ethoc_ack_irq(priv, pending);
 	if (pending & INT_MASK_BUSY)
 		debug("%s(): packet dropped\n", __func__);
 	if (pending & INT_MASK_RX) {
 		debug("%s(): rx irq\n", __func__);
-		ethoc_rx(dev, PKTBUFSRX);
+		ethoc_rx(priv, PKTBUFSRX);
 	}
 
 	return 0;
@@ -505,6 +505,7 @@ int ethoc_initialize(u8 dev_num, int base_addr)
 	dev->recv = ethoc_recv;
 	dev->write_hwaddr = ethoc_set_mac_address;
 	sprintf(dev->name, "%s-%hu", "ETHOC", dev_num);
+	priv->iobase = ioremap(dev->iobase, ETHOC_IOSIZE);
 
 	eth_register(dev);
 	return 1;
-- 
2.1.4

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

* [U-Boot] [PATCH v2 3/7] net/ethoc: add CONFIG_DM_ETH support
  2016-08-05 15:26 [U-Boot] [PATCH v2 0/7] net/ethoc improvements Max Filippov
  2016-08-05 15:26 ` [U-Boot] [PATCH v2 1/7] net/ethoc: add Kconfig entry for the driver Max Filippov
  2016-08-05 15:26 ` [U-Boot] [PATCH v2 2/7] net/ethoc: use priv instead of dev internally Max Filippov
@ 2016-08-05 15:26 ` Max Filippov
  2016-08-15 20:33   ` [U-Boot] " Joe Hershberger
  2016-08-05 15:26 ` [U-Boot] [PATCH v2 4/7] net/ethoc: support device tree Max Filippov
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 16+ messages in thread
From: Max Filippov @ 2016-08-05 15:26 UTC (permalink / raw)
  To: u-boot

Extract reusable parts from ethoc_init, ethoc_set_mac_address,
ethoc_send and ethoc_receive, move the rest under #ifdef CONFIG_DM_ETH.
Add U_BOOT_DRIVER, eth_ops structure and implement required methods.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Acked-by: Joe Hershberger <joe.hershberger@ni.com>
---
Changes v1->v2:
- rename ethoc_set_mac_address to ethoc_write_hwaddr_common;
- rename ethoc_recv_common to ethoc_is_new_packet_received;
- use positive logic with CONFIG_DM_ETH;
- return from DM ethoc_recv when ethoc_is_new_packet_received returns 0;
- remove stray ioremap addition.

 drivers/net/ethoc.c                  | 221 +++++++++++++++++++++++++++--------
 include/dm/platform_data/net_ethoc.h |  20 ++++
 2 files changed, 194 insertions(+), 47 deletions(-)
 create mode 100644 include/dm/platform_data/net_ethoc.h

diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index f5bd1ab..4846c58 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -5,13 +5,14 @@
  * Copyright (C) 2008-2009 Avionic Design GmbH
  *   Thierry Reding <thierry.reding@avionic-design.de>
  * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw>
+ * Copyright (C) 2016 Cadence Design Systems Inc.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * SPDX-License-Identifier:	GPL-2.0
  */
 
 #include <common.h>
+#include <dm/device.h>
+#include <dm/platform_data/net_ethoc.h>
 #include <linux/io.h>
 #include <malloc.h>
 #include <net.h>
@@ -216,11 +217,8 @@ static inline void ethoc_write_bd(struct ethoc *priv, int index,
 	ethoc_write(priv, offset + 4, bd->addr);
 }
 
-static int ethoc_set_mac_address(struct eth_device *dev)
+static int ethoc_write_hwaddr_common(struct ethoc *priv, u8 *mac)
 {
-	struct ethoc *priv = (struct ethoc *)dev->priv;
-	u8 *mac = dev->enetaddr;
-
 	ethoc_write(priv, MAC_ADDR0, (mac[2] << 24) | (mac[3] << 16) |
 		    (mac[4] << 8) | (mac[5] << 0));
 	ethoc_write(priv, MAC_ADDR1, (mac[0] << 8) | (mac[1] << 0));
@@ -305,11 +303,8 @@ static int ethoc_reset(struct ethoc *priv)
 	return 0;
 }
 
-static int ethoc_init(struct eth_device *dev, bd_t * bd)
+static int ethoc_init_common(struct ethoc *priv)
 {
-	struct ethoc *priv = (struct ethoc *)dev->priv;
-	printf("ethoc\n");
-
 	priv->num_tx = 1;
 	priv->num_rx = PKTBUFSRX;
 	ethoc_write(priv, TX_BD_NUM, priv->num_tx);
@@ -354,36 +349,43 @@ static int ethoc_update_rx_stats(struct ethoc_bd *bd)
 	return ret;
 }
 
-static int ethoc_rx(struct ethoc *priv, int limit)
+static int ethoc_rx_common(struct ethoc *priv, uchar **packetp)
 {
-	int count;
-
-	for (count = 0; count < limit; ++count) {
-		u32 entry;
-		struct ethoc_bd bd;
+	u32 entry;
+	struct ethoc_bd bd;
 
-		entry = priv->num_tx + (priv->cur_rx % priv->num_rx);
-		ethoc_read_bd(priv, entry, &bd);
-		if (bd.stat & RX_BD_EMPTY)
-			break;
+	entry = priv->num_tx + (priv->cur_rx % priv->num_rx);
+	ethoc_read_bd(priv, entry, &bd);
+	if (bd.stat & RX_BD_EMPTY)
+		return -EAGAIN;
+
+	debug("%s(): RX buffer %d, %x received\n",
+	      __func__, priv->cur_rx, bd.stat);
+	if (ethoc_update_rx_stats(&bd) == 0) {
+		int size = bd.stat >> 16;
+
+		size -= 4;	/* strip the CRC */
+		*packetp = (void *)bd.addr;
+		return size;
+	} else {
+		return 0;
+	}
+}
 
-		debug("%s(): RX buffer %d, %x received\n",
-		      __func__, priv->cur_rx, bd.stat);
-		if (ethoc_update_rx_stats(&bd) == 0) {
-			int size = bd.stat >> 16;
-			size -= 4;	/* strip the CRC */
-			net_process_received_packet((void *)bd.addr, size);
-		}
+static int ethoc_is_new_packet_received(struct ethoc *priv)
+{
+	u32 pending;
 
-		/* clear the buffer descriptor so it can be reused */
-		flush_dcache_range(bd.addr, bd.addr + PKTSIZE_ALIGN);
-		bd.stat &= ~RX_BD_STATS;
-		bd.stat |= RX_BD_EMPTY;
-		ethoc_write_bd(priv, entry, &bd);
-		priv->cur_rx++;
+	pending = ethoc_read(priv, INT_SOURCE);
+	ethoc_ack_irq(priv, pending);
+	if (pending & INT_MASK_BUSY)
+		debug("%s(): packet dropped\n", __func__);
+	if (pending & INT_MASK_RX) {
+		debug("%s(): rx irq\n", __func__);
+		return 1;
 	}
 
-	return count;
+	return 0;
 }
 
 static int ethoc_update_tx_stats(struct ethoc_bd *bd)
@@ -413,9 +415,8 @@ static void ethoc_tx(struct ethoc *priv)
 		(void)ethoc_update_tx_stats(&bd);
 }
 
-static int ethoc_send(struct eth_device *dev, void *packet, int length)
+static int ethoc_send_common(struct ethoc *priv, void *packet, int length)
 {
-	struct ethoc *priv = (struct ethoc *)dev->priv;
 	struct ethoc_bd bd;
 	u32 entry;
 	u32 pending;
@@ -460,6 +461,126 @@ static int ethoc_send(struct eth_device *dev, void *packet, int length)
 	return 0;
 }
 
+static int ethoc_free_pkt_common(struct ethoc *priv)
+{
+	u32 entry;
+	struct ethoc_bd bd;
+
+	entry = priv->num_tx + (priv->cur_rx % priv->num_rx);
+	ethoc_read_bd(priv, entry, &bd);
+
+	/* clear the buffer descriptor so it can be reused */
+	flush_dcache_range(bd.addr, bd.addr + PKTSIZE_ALIGN);
+	bd.stat &= ~RX_BD_STATS;
+	bd.stat |= RX_BD_EMPTY;
+	ethoc_write_bd(priv, entry, &bd);
+	priv->cur_rx++;
+
+	return 0;
+}
+
+#ifdef CONFIG_DM_ETH
+
+static int ethoc_write_hwaddr(struct udevice *dev)
+{
+	struct ethoc_eth_pdata *pdata = dev_get_platdata(dev);
+	struct ethoc *priv = dev_get_priv(dev);
+	u8 *mac = pdata->eth_pdata.enetaddr;
+
+	return ethoc_write_hwaddr_common(priv, mac);
+}
+
+static int ethoc_send(struct udevice *dev, void *packet, int length)
+{
+	return ethoc_send_common(dev_get_priv(dev), packet, length);
+}
+
+static int ethoc_free_pkt(struct udevice *dev, uchar *packet, int length)
+{
+	return ethoc_free_pkt_common(dev_get_priv(dev));
+}
+
+static int ethoc_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct ethoc *priv = dev_get_priv(dev);
+
+	if (flags & ETH_RECV_CHECK_DEVICE)
+		if (!ethoc_is_new_packet_received(priv))
+			return -EAGAIN;
+
+	return ethoc_rx_common(priv, packetp);
+}
+
+static int ethoc_start(struct udevice *dev)
+{
+	return ethoc_init_common(dev_get_priv(dev));
+}
+
+static void ethoc_stop(struct udevice *dev)
+{
+	struct ethoc *priv = dev_get_priv(dev);
+
+	ethoc_disable_rx_and_tx(priv);
+}
+
+static int ethoc_probe(struct udevice *dev)
+{
+	struct ethoc_eth_pdata *pdata = dev_get_platdata(dev);
+	struct ethoc *priv = dev_get_priv(dev);
+
+	priv->iobase = ioremap(pdata->eth_pdata.iobase, ETHOC_IOSIZE);
+	return 0;
+}
+
+static int ethoc_remove(struct udevice *dev)
+{
+	struct ethoc *priv = dev_get_priv(dev);
+
+	iounmap(priv->iobase);
+	return 0;
+}
+
+static const struct eth_ops ethoc_ops = {
+	.start		= ethoc_start,
+	.stop		= ethoc_stop,
+	.send		= ethoc_send,
+	.recv		= ethoc_recv,
+	.free_pkt	= ethoc_free_pkt,
+	.write_hwaddr	= ethoc_write_hwaddr,
+};
+
+U_BOOT_DRIVER(ethoc) = {
+	.name				= "ethoc",
+	.id				= UCLASS_ETH,
+	.probe				= ethoc_probe,
+	.remove				= ethoc_remove,
+	.ops				= &ethoc_ops,
+	.priv_auto_alloc_size		= sizeof(struct ethoc),
+	.platdata_auto_alloc_size	= sizeof(struct ethoc_eth_pdata),
+};
+
+#else
+
+static int ethoc_init(struct eth_device *dev, bd_t *bd)
+{
+	struct ethoc *priv = (struct ethoc *)dev->priv;
+
+	return ethoc_init_common(priv);
+}
+
+static int ethoc_write_hwaddr(struct eth_device *dev)
+{
+	struct ethoc *priv = (struct ethoc *)dev->priv;
+	u8 *mac = dev->enetaddr;
+
+	return ethoc_write_hwaddr_common(priv, mac);
+}
+
+static int ethoc_send(struct eth_device *dev, void *packet, int length)
+{
+	return ethoc_send_common(dev->priv, packet, length);
+}
+
 static void ethoc_halt(struct eth_device *dev)
 {
 	ethoc_disable_rx_and_tx(dev->priv);
@@ -468,17 +589,21 @@ static void ethoc_halt(struct eth_device *dev)
 static int ethoc_recv(struct eth_device *dev)
 {
 	struct ethoc *priv = (struct ethoc *)dev->priv;
-	u32 pending;
+	int count;
 
-	pending = ethoc_read(priv, INT_SOURCE);
-	ethoc_ack_irq(priv, pending);
-	if (pending & INT_MASK_BUSY)
-		debug("%s(): packet dropped\n", __func__);
-	if (pending & INT_MASK_RX) {
-		debug("%s(): rx irq\n", __func__);
-		ethoc_rx(priv, PKTBUFSRX);
-	}
+	if (!ethoc_is_new_packet_received(priv))
+		return 0;
+
+	for (count = 0; count < PKTBUFSRX; ++count) {
+		uchar *packetp;
+		int size = ethoc_rx_common(priv, &packetp);
 
+		if (size < 0)
+			break;
+		if (size > 0)
+			net_process_received_packet(packetp, size);
+		ethoc_free_pkt_common(priv);
+	}
 	return 0;
 }
 
@@ -503,10 +628,12 @@ int ethoc_initialize(u8 dev_num, int base_addr)
 	dev->halt = ethoc_halt;
 	dev->send = ethoc_send;
 	dev->recv = ethoc_recv;
-	dev->write_hwaddr = ethoc_set_mac_address;
+	dev->write_hwaddr = ethoc_write_hwaddr;
 	sprintf(dev->name, "%s-%hu", "ETHOC", dev_num);
 	priv->iobase = ioremap(dev->iobase, ETHOC_IOSIZE);
 
 	eth_register(dev);
 	return 1;
 }
+
+#endif
diff --git a/include/dm/platform_data/net_ethoc.h b/include/dm/platform_data/net_ethoc.h
new file mode 100644
index 0000000..1d8c73c
--- /dev/null
+++ b/include/dm/platform_data/net_ethoc.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2016 Cadence Design Systems Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef _ETHOC_H
+#define _ETHOC_H
+
+#include <net.h>
+
+#ifdef CONFIG_DM_ETH
+
+struct ethoc_eth_pdata {
+	struct eth_pdata eth_pdata;
+};
+
+#endif
+
+#endif /* _ETHOC_H */
-- 
2.1.4

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

* [U-Boot] [PATCH v2 4/7] net/ethoc: support device tree
  2016-08-05 15:26 [U-Boot] [PATCH v2 0/7] net/ethoc improvements Max Filippov
                   ` (2 preceding siblings ...)
  2016-08-05 15:26 ` [U-Boot] [PATCH v2 3/7] net/ethoc: add CONFIG_DM_ETH support Max Filippov
@ 2016-08-05 15:26 ` Max Filippov
  2016-08-15 20:33   ` [U-Boot] " Joe Hershberger
  2016-08-05 15:26 ` [U-Boot] [PATCH v2 5/7] net/ethoc: don't mix virtual and physical addresses Max Filippov
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 16+ messages in thread
From: Max Filippov @ 2016-08-05 15:26 UTC (permalink / raw)
  To: u-boot

Add .of_match table and .ofdata_to_platdata callback to allow for ethoc
device configuration from the device tree.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Acked-by: Joe Hershberger <joe.hershberger@ni.com>
---
 drivers/net/ethoc.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index 4846c58..a5c4b46 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -523,6 +523,14 @@ static void ethoc_stop(struct udevice *dev)
 	ethoc_disable_rx_and_tx(priv);
 }
 
+static int ethoc_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ethoc_eth_pdata *pdata = dev_get_platdata(dev);
+
+	pdata->eth_pdata.iobase = dev_get_addr(dev);
+	return 0;
+}
+
 static int ethoc_probe(struct udevice *dev)
 {
 	struct ethoc_eth_pdata *pdata = dev_get_platdata(dev);
@@ -549,9 +557,16 @@ static const struct eth_ops ethoc_ops = {
 	.write_hwaddr	= ethoc_write_hwaddr,
 };
 
+static const struct udevice_id ethoc_ids[] = {
+	{ .compatible = "opencores,ethoc" },
+	{ }
+};
+
 U_BOOT_DRIVER(ethoc) = {
 	.name				= "ethoc",
 	.id				= UCLASS_ETH,
+	.of_match			= ethoc_ids,
+	.ofdata_to_platdata		= ethoc_ofdata_to_platdata,
 	.probe				= ethoc_probe,
 	.remove				= ethoc_remove,
 	.ops				= &ethoc_ops,
-- 
2.1.4

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

* [U-Boot] [PATCH v2 5/7] net/ethoc: don't mix virtual and physical addresses
  2016-08-05 15:26 [U-Boot] [PATCH v2 0/7] net/ethoc improvements Max Filippov
                   ` (3 preceding siblings ...)
  2016-08-05 15:26 ` [U-Boot] [PATCH v2 4/7] net/ethoc: support device tree Max Filippov
@ 2016-08-05 15:26 ` Max Filippov
  2016-08-15 20:33   ` [U-Boot] " Joe Hershberger
  2016-08-05 15:26 ` [U-Boot] [PATCH v2 6/7] net/ethoc: support private memory configurations Max Filippov
  2016-08-05 15:26 ` [U-Boot] [PATCH v2 7/7] net/ethoc: implement MDIO bus and support phylib Max Filippov
  6 siblings, 1 reply; 16+ messages in thread
From: Max Filippov @ 2016-08-05 15:26 UTC (permalink / raw)
  To: u-boot

Addresses used in buffer descriptors and passed in platform data or
device tree are physical. Addresses used by CPU to access packet data
and registers are virtual. Don't mix these addresses and use virt_to_phys
for translation.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Acked-by: Joe Hershberger <joe.hershberger@ni.com>
---
 drivers/net/ethoc.c | 23 +++++++++++++----------
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index a5c4b46..198827f 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -255,6 +255,7 @@ static int ethoc_init_ring(struct ethoc *priv)
 
 	/* setup transmission buffers */
 	bd.stat = TX_BD_IRQ | TX_BD_CRC;
+	bd.addr = 0;
 
 	for (i = 0; i < priv->num_tx; i++) {
 		if (i == priv->num_tx - 1)
@@ -266,11 +267,12 @@ static int ethoc_init_ring(struct ethoc *priv)
 	bd.stat = RX_BD_EMPTY | RX_BD_IRQ;
 
 	for (i = 0; i < priv->num_rx; i++) {
-		bd.addr = (u32)net_rx_packets[i];
+		bd.addr = virt_to_phys(net_rx_packets[i]);
 		if (i == priv->num_rx - 1)
 			bd.stat |= RX_BD_WRAP;
 
-		flush_dcache_range(bd.addr, bd.addr + PKTSIZE_ALIGN);
+		flush_dcache_range((ulong)net_rx_packets[i],
+				   (ulong)net_rx_packets[i] + PKTSIZE_ALIGN);
 		ethoc_write_bd(priv, priv->num_tx + i, &bd);
 	}
 
@@ -351,10 +353,10 @@ static int ethoc_update_rx_stats(struct ethoc_bd *bd)
 
 static int ethoc_rx_common(struct ethoc *priv, uchar **packetp)
 {
-	u32 entry;
 	struct ethoc_bd bd;
+	u32 i = priv->cur_rx % priv->num_rx;
+	u32 entry = priv->num_tx + i;
 
-	entry = priv->num_tx + (priv->cur_rx % priv->num_rx);
 	ethoc_read_bd(priv, entry, &bd);
 	if (bd.stat & RX_BD_EMPTY)
 		return -EAGAIN;
@@ -365,7 +367,7 @@ static int ethoc_rx_common(struct ethoc *priv, uchar **packetp)
 		int size = bd.stat >> 16;
 
 		size -= 4;	/* strip the CRC */
-		*packetp = (void *)bd.addr;
+		*packetp = net_rx_packets[i];
 		return size;
 	} else {
 		return 0;
@@ -428,9 +430,9 @@ static int ethoc_send_common(struct ethoc *priv, void *packet, int length)
 		bd.stat |= TX_BD_PAD;
 	else
 		bd.stat &= ~TX_BD_PAD;
-	bd.addr = (u32)packet;
+	bd.addr = virt_to_phys(packet);
 
-	flush_dcache_range(bd.addr, bd.addr + length);
+	flush_dcache_range((ulong)packet, (ulong)packet + length);
 	bd.stat &= ~(TX_BD_STATS | TX_BD_LEN_MASK);
 	bd.stat |= TX_BD_LEN(length);
 	ethoc_write_bd(priv, entry, &bd);
@@ -463,14 +465,15 @@ static int ethoc_send_common(struct ethoc *priv, void *packet, int length)
 
 static int ethoc_free_pkt_common(struct ethoc *priv)
 {
-	u32 entry;
 	struct ethoc_bd bd;
+	u32 i = priv->cur_rx % priv->num_rx;
+	u32 entry = priv->num_tx + i;
 
-	entry = priv->num_tx + (priv->cur_rx % priv->num_rx);
 	ethoc_read_bd(priv, entry, &bd);
 
 	/* clear the buffer descriptor so it can be reused */
-	flush_dcache_range(bd.addr, bd.addr + PKTSIZE_ALIGN);
+	flush_dcache_range((ulong)net_rx_packets[i],
+			   (ulong)net_rx_packets[i] + PKTSIZE_ALIGN);
 	bd.stat &= ~RX_BD_STATS;
 	bd.stat |= RX_BD_EMPTY;
 	ethoc_write_bd(priv, entry, &bd);
-- 
2.1.4

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

* [U-Boot] [PATCH v2 6/7] net/ethoc: support private memory configurations
  2016-08-05 15:26 [U-Boot] [PATCH v2 0/7] net/ethoc improvements Max Filippov
                   ` (4 preceding siblings ...)
  2016-08-05 15:26 ` [U-Boot] [PATCH v2 5/7] net/ethoc: don't mix virtual and physical addresses Max Filippov
@ 2016-08-05 15:26 ` Max Filippov
  2016-08-15 20:33   ` [U-Boot] " Joe Hershberger
  2016-08-05 15:26 ` [U-Boot] [PATCH v2 7/7] net/ethoc: implement MDIO bus and support phylib Max Filippov
  6 siblings, 1 reply; 16+ messages in thread
From: Max Filippov @ 2016-08-05 15:26 UTC (permalink / raw)
  To: u-boot

The ethoc device can be configured to have a private memory region
instead of having access to the main memory. In that case egress packets
must be copied into that memory for transmission and pointers to that
memory need to be passed to net_process_received_packet or returned from
the recv callback.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Acked-by: Joe Hershberger <joe.hershberger@ni.com>
---
 drivers/net/ethoc.c                  | 46 ++++++++++++++++++++++++++++++++----
 include/dm/platform_data/net_ethoc.h |  1 +
 2 files changed, 42 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index 198827f..d825aaa 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -179,6 +179,8 @@ struct ethoc {
 	u32 num_rx;
 	u32 cur_rx;
 	void __iomem *iobase;
+	void __iomem *packet;
+	phys_addr_t packet_phys;
 };
 
 /**
@@ -247,6 +249,7 @@ static inline void ethoc_disable_rx_and_tx(struct ethoc *priv)
 static int ethoc_init_ring(struct ethoc *priv)
 {
 	struct ethoc_bd bd;
+	phys_addr_t addr = priv->packet_phys;
 	int i;
 
 	priv->cur_tx = 0;
@@ -258,6 +261,10 @@ static int ethoc_init_ring(struct ethoc *priv)
 	bd.addr = 0;
 
 	for (i = 0; i < priv->num_tx; i++) {
+		if (addr) {
+			bd.addr = addr;
+			addr += PKTSIZE_ALIGN;
+		}
 		if (i == priv->num_tx - 1)
 			bd.stat |= TX_BD_WRAP;
 
@@ -267,7 +274,12 @@ static int ethoc_init_ring(struct ethoc *priv)
 	bd.stat = RX_BD_EMPTY | RX_BD_IRQ;
 
 	for (i = 0; i < priv->num_rx; i++) {
-		bd.addr = virt_to_phys(net_rx_packets[i]);
+		if (addr) {
+			bd.addr = addr;
+			addr += PKTSIZE_ALIGN;
+		} else {
+			bd.addr = virt_to_phys(net_rx_packets[i]);
+		}
 		if (i == priv->num_rx - 1)
 			bd.stat |= RX_BD_WRAP;
 
@@ -367,7 +379,10 @@ static int ethoc_rx_common(struct ethoc *priv, uchar **packetp)
 		int size = bd.stat >> 16;
 
 		size -= 4;	/* strip the CRC */
-		*packetp = net_rx_packets[i];
+		if (priv->packet)
+			*packetp = priv->packet + entry * PKTSIZE_ALIGN;
+		else
+			*packetp = net_rx_packets[i];
 		return size;
 	} else {
 		return 0;
@@ -430,8 +445,15 @@ static int ethoc_send_common(struct ethoc *priv, void *packet, int length)
 		bd.stat |= TX_BD_PAD;
 	else
 		bd.stat &= ~TX_BD_PAD;
-	bd.addr = virt_to_phys(packet);
 
+	if (priv->packet) {
+		void *p = priv->packet + entry * PKTSIZE_ALIGN;
+
+		memcpy(p, packet, length);
+		packet = p;
+	} else {
+		bd.addr = virt_to_phys(packet);
+	}
 	flush_dcache_range((ulong)packet, (ulong)packet + length);
 	bd.stat &= ~(TX_BD_STATS | TX_BD_LEN_MASK);
 	bd.stat |= TX_BD_LEN(length);
@@ -468,12 +490,17 @@ static int ethoc_free_pkt_common(struct ethoc *priv)
 	struct ethoc_bd bd;
 	u32 i = priv->cur_rx % priv->num_rx;
 	u32 entry = priv->num_tx + i;
+	void *src;
 
 	ethoc_read_bd(priv, entry, &bd);
 
+	if (priv->packet)
+		src = priv->packet + entry * PKTSIZE_ALIGN;
+	else
+		src = net_rx_packets[i];
 	/* clear the buffer descriptor so it can be reused */
-	flush_dcache_range((ulong)net_rx_packets[i],
-			   (ulong)net_rx_packets[i] + PKTSIZE_ALIGN);
+	flush_dcache_range((ulong)src,
+			   (ulong)src + PKTSIZE_ALIGN);
 	bd.stat &= ~RX_BD_STATS;
 	bd.stat |= RX_BD_EMPTY;
 	ethoc_write_bd(priv, entry, &bd);
@@ -529,8 +556,12 @@ static void ethoc_stop(struct udevice *dev)
 static int ethoc_ofdata_to_platdata(struct udevice *dev)
 {
 	struct ethoc_eth_pdata *pdata = dev_get_platdata(dev);
+	fdt_addr_t addr;
 
 	pdata->eth_pdata.iobase = dev_get_addr(dev);
+	addr = dev_get_addr_index(dev, 1);
+	if (addr != FDT_ADDR_T_NONE)
+		pdata->packet_base = addr;
 	return 0;
 }
 
@@ -540,6 +571,11 @@ static int ethoc_probe(struct udevice *dev)
 	struct ethoc *priv = dev_get_priv(dev);
 
 	priv->iobase = ioremap(pdata->eth_pdata.iobase, ETHOC_IOSIZE);
+	if (pdata->packet_base) {
+		priv->packet_phys = pdata->packet_base;
+		priv->packet = ioremap(pdata->packet_base,
+				       (1 + PKTBUFSRX) * PKTSIZE_ALIGN);
+	}
 	return 0;
 }
 
diff --git a/include/dm/platform_data/net_ethoc.h b/include/dm/platform_data/net_ethoc.h
index 1d8c73c..3f94bde 100644
--- a/include/dm/platform_data/net_ethoc.h
+++ b/include/dm/platform_data/net_ethoc.h
@@ -13,6 +13,7 @@
 
 struct ethoc_eth_pdata {
 	struct eth_pdata eth_pdata;
+	phys_addr_t packet_base;
 };
 
 #endif
-- 
2.1.4

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

* [U-Boot] [PATCH v2 7/7] net/ethoc: implement MDIO bus and support phylib
  2016-08-05 15:26 [U-Boot] [PATCH v2 0/7] net/ethoc improvements Max Filippov
                   ` (5 preceding siblings ...)
  2016-08-05 15:26 ` [U-Boot] [PATCH v2 6/7] net/ethoc: support private memory configurations Max Filippov
@ 2016-08-05 15:26 ` Max Filippov
  2016-08-05 17:27   ` Joe Hershberger
  2016-08-15 20:33   ` [U-Boot] " Joe Hershberger
  6 siblings, 2 replies; 16+ messages in thread
From: Max Filippov @ 2016-08-05 15:26 UTC (permalink / raw)
  To: u-boot

Implement MDIO bus read/write functions, initialize the bus and scan for
the PHY when phylib is enabled. Limit PHY speeds to 10/100 Mbps.

Cc: Michal Simek <monstr@monstr.eu>
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
Changes v1->v2:
- use wait_for_bit in ethoc_mdio_read/ethoc_mdio_write;
- remove stray ioremap removal.

 drivers/net/ethoc.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 150 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index d825aaa..ad8c462 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -18,6 +18,7 @@
 #include <net.h>
 #include <miiphy.h>
 #include <asm/cache.h>
+#include <wait_bit.h>
 
 /* register offsets */
 #define	MODER		0x00
@@ -181,6 +182,11 @@ struct ethoc {
 	void __iomem *iobase;
 	void __iomem *packet;
 	phys_addr_t packet_phys;
+
+#ifdef CONFIG_PHYLIB
+	struct mii_dev *bus;
+	struct phy_device *phydev;
+#endif
 };
 
 /**
@@ -193,14 +199,19 @@ struct ethoc_bd {
 	u32 addr;
 };
 
+static inline u32 *ethoc_reg(struct ethoc *priv, size_t offset)
+{
+	return priv->iobase + offset;
+}
+
 static inline u32 ethoc_read(struct ethoc *priv, size_t offset)
 {
-	return readl(priv->iobase + offset);
+	return readl(ethoc_reg(priv, offset));
 }
 
 static inline void ethoc_write(struct ethoc *priv, size_t offset, u32 data)
 {
-	writel(data, priv->iobase + offset);
+	writel(data, ethoc_reg(priv, offset));
 }
 
 static inline void ethoc_read_bd(struct ethoc *priv, int index,
@@ -319,13 +330,31 @@ static int ethoc_reset(struct ethoc *priv)
 
 static int ethoc_init_common(struct ethoc *priv)
 {
+	int ret = 0;
+
 	priv->num_tx = 1;
 	priv->num_rx = PKTBUFSRX;
 	ethoc_write(priv, TX_BD_NUM, priv->num_tx);
 	ethoc_init_ring(priv);
 	ethoc_reset(priv);
 
-	return 0;
+#ifdef CONFIG_PHYLIB
+	ret = phy_startup(priv->phydev);
+	if (ret) {
+		printf("Could not initialize PHY %s\n",
+		       priv->phydev->dev->name);
+		return ret;
+	}
+#endif
+	return ret;
+}
+
+static void ethoc_stop_common(struct ethoc *priv)
+{
+	ethoc_disable_rx_and_tx(priv);
+#ifdef CONFIG_PHYLIB
+	phy_shutdown(priv->phydev);
+#endif
 }
 
 static int ethoc_update_rx_stats(struct ethoc_bd *bd)
@@ -509,6 +538,110 @@ static int ethoc_free_pkt_common(struct ethoc *priv)
 	return 0;
 }
 
+#ifdef CONFIG_PHYLIB
+
+static int ethoc_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
+{
+	struct ethoc *priv = bus->priv;
+	int rc;
+
+	ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(addr, reg));
+	ethoc_write(priv, MIICOMMAND, MIICOMMAND_READ);
+
+	rc = wait_for_bit(__func__, ethoc_reg(priv, MIISTATUS),
+			  MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false);
+
+	if (rc == 0) {
+		u32 data = ethoc_read(priv, MIIRX_DATA);
+
+		/* reset MII command register */
+		ethoc_write(priv, MIICOMMAND, 0);
+		return data;
+	}
+	return rc;
+}
+
+static int ethoc_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
+			    u16 val)
+{
+	struct ethoc *priv = bus->priv;
+	int rc;
+
+	ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(addr, reg));
+	ethoc_write(priv, MIITX_DATA, val);
+	ethoc_write(priv, MIICOMMAND, MIICOMMAND_WRITE);
+
+	rc = wait_for_bit(__func__, ethoc_reg(priv, MIISTATUS),
+			  MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false);
+
+	if (rc == 0) {
+		/* reset MII command register */
+		ethoc_write(priv, MIICOMMAND, 0);
+	}
+	return rc;
+}
+
+static int ethoc_mdio_init(const char *name, struct ethoc *priv)
+{
+	struct mii_dev *bus = mdio_alloc();
+	int ret;
+
+	if (!bus) {
+		printf("Failed to allocate MDIO bus\n");
+		return -ENOMEM;
+	}
+
+	bus->read = ethoc_mdio_read;
+	bus->write = ethoc_mdio_write;
+	snprintf(bus->name, sizeof(bus->name), "%s", name);
+	bus->priv = priv;
+
+	ret = mdio_register(bus);
+	if (ret < 0)
+		return ret;
+
+	priv->bus = miiphy_get_dev_by_name(name);
+	return 0;
+}
+
+static int ethoc_phy_init(struct ethoc *priv, void *dev)
+{
+	struct phy_device *phydev;
+	int mask = 0xffffffff;
+
+#ifdef CONFIG_PHY_ADDR
+	mask = 1 << CONFIG_PHY_ADDR;
+#endif
+
+	phydev = phy_find_by_mask(priv->bus, mask, PHY_INTERFACE_MODE_MII);
+	if (!phydev)
+		return -ENODEV;
+
+	phy_connect_dev(phydev, dev);
+
+	phydev->supported &= PHY_BASIC_FEATURES;
+	phydev->advertising = phydev->supported;
+
+	priv->phydev = phydev;
+	phy_config(phydev);
+
+	return 0;
+}
+
+#else
+
+static inline int ethoc_mdio_init(const char *name, struct ethoc *priv)
+{
+	return 0;
+}
+
+static inline int ethoc_phy_init(struct ethoc *priv, void *dev)
+{
+	return 0;
+}
+
+#endif
+
 #ifdef CONFIG_DM_ETH
 
 static int ethoc_write_hwaddr(struct udevice *dev)
@@ -548,9 +681,7 @@ static int ethoc_start(struct udevice *dev)
 
 static void ethoc_stop(struct udevice *dev)
 {
-	struct ethoc *priv = dev_get_priv(dev);
-
-	ethoc_disable_rx_and_tx(priv);
+	ethoc_stop_common(dev_get_priv(dev));
 }
 
 static int ethoc_ofdata_to_platdata(struct udevice *dev)
@@ -576,6 +707,10 @@ static int ethoc_probe(struct udevice *dev)
 		priv->packet = ioremap(pdata->packet_base,
 				       (1 + PKTBUFSRX) * PKTSIZE_ALIGN);
 	}
+
+	ethoc_mdio_init(dev->name, priv);
+	ethoc_phy_init(priv, dev);
+
 	return 0;
 }
 
@@ -583,6 +718,11 @@ static int ethoc_remove(struct udevice *dev)
 {
 	struct ethoc *priv = dev_get_priv(dev);
 
+#ifdef CONFIG_PHYLIB
+	free(priv->phydev);
+	mdio_unregister(priv->bus);
+	mdio_free(priv->bus);
+#endif
 	iounmap(priv->iobase);
 	return 0;
 }
@@ -687,6 +827,10 @@ int ethoc_initialize(u8 dev_num, int base_addr)
 	priv->iobase = ioremap(dev->iobase, ETHOC_IOSIZE);
 
 	eth_register(dev);
+
+	ethoc_mdio_init(dev->name, priv);
+	ethoc_phy_init(priv, dev);
+
 	return 1;
 }
 
-- 
2.1.4

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

* [U-Boot] [PATCH v2 7/7] net/ethoc: implement MDIO bus and support phylib
  2016-08-05 15:26 ` [U-Boot] [PATCH v2 7/7] net/ethoc: implement MDIO bus and support phylib Max Filippov
@ 2016-08-05 17:27   ` Joe Hershberger
  2016-08-15 20:33   ` [U-Boot] " Joe Hershberger
  1 sibling, 0 replies; 16+ messages in thread
From: Joe Hershberger @ 2016-08-05 17:27 UTC (permalink / raw)
  To: u-boot

On Fri, Aug 5, 2016 at 10:26 AM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> Implement MDIO bus read/write functions, initialize the bus and scan for
> the PHY when phylib is enabled. Limit PHY speeds to 10/100 Mbps.
>
> Cc: Michal Simek <monstr@monstr.eu>
> Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>

Acked-by: Joe Hershberger <joe.hershberger@ni.com>

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

* [U-Boot] net/ethoc: add Kconfig entry for the driver
  2016-08-05 15:26 ` [U-Boot] [PATCH v2 1/7] net/ethoc: add Kconfig entry for the driver Max Filippov
@ 2016-08-15 20:33   ` Joe Hershberger
  0 siblings, 0 replies; 16+ messages in thread
From: Joe Hershberger @ 2016-08-15 20:33 UTC (permalink / raw)
  To: u-boot

Hi Max,

https://patchwork.ozlabs.org/patch/656236/ was applied to u-boot-net.git.

Thanks!
-Joe

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

* [U-Boot] net/ethoc: use priv instead of dev internally
  2016-08-05 15:26 ` [U-Boot] [PATCH v2 2/7] net/ethoc: use priv instead of dev internally Max Filippov
@ 2016-08-15 20:33   ` Joe Hershberger
  0 siblings, 0 replies; 16+ messages in thread
From: Joe Hershberger @ 2016-08-15 20:33 UTC (permalink / raw)
  To: u-boot

Hi Max,

https://patchwork.ozlabs.org/patch/656238/ was applied to u-boot-net.git.

Thanks!
-Joe

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

* [U-Boot] net/ethoc: add CONFIG_DM_ETH support
  2016-08-05 15:26 ` [U-Boot] [PATCH v2 3/7] net/ethoc: add CONFIG_DM_ETH support Max Filippov
@ 2016-08-15 20:33   ` Joe Hershberger
  0 siblings, 0 replies; 16+ messages in thread
From: Joe Hershberger @ 2016-08-15 20:33 UTC (permalink / raw)
  To: u-boot

Hi Max,

https://patchwork.ozlabs.org/patch/656240/ was applied to u-boot-net.git.

Thanks!
-Joe

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

* [U-Boot] net/ethoc: support device tree
  2016-08-05 15:26 ` [U-Boot] [PATCH v2 4/7] net/ethoc: support device tree Max Filippov
@ 2016-08-15 20:33   ` Joe Hershberger
  0 siblings, 0 replies; 16+ messages in thread
From: Joe Hershberger @ 2016-08-15 20:33 UTC (permalink / raw)
  To: u-boot

Hi Max,

https://patchwork.ozlabs.org/patch/656241/ was applied to u-boot-net.git.

Thanks!
-Joe

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

* [U-Boot] net/ethoc: don't mix virtual and physical addresses
  2016-08-05 15:26 ` [U-Boot] [PATCH v2 5/7] net/ethoc: don't mix virtual and physical addresses Max Filippov
@ 2016-08-15 20:33   ` Joe Hershberger
  0 siblings, 0 replies; 16+ messages in thread
From: Joe Hershberger @ 2016-08-15 20:33 UTC (permalink / raw)
  To: u-boot

Hi Max,

https://patchwork.ozlabs.org/patch/656242/ was applied to u-boot-net.git.

Thanks!
-Joe

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

* [U-Boot] net/ethoc: support private memory configurations
  2016-08-05 15:26 ` [U-Boot] [PATCH v2 6/7] net/ethoc: support private memory configurations Max Filippov
@ 2016-08-15 20:33   ` Joe Hershberger
  0 siblings, 0 replies; 16+ messages in thread
From: Joe Hershberger @ 2016-08-15 20:33 UTC (permalink / raw)
  To: u-boot

Hi Max,

https://patchwork.ozlabs.org/patch/656237/ was applied to u-boot-net.git.

Thanks!
-Joe

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

* [U-Boot] net/ethoc: implement MDIO bus and support phylib
  2016-08-05 15:26 ` [U-Boot] [PATCH v2 7/7] net/ethoc: implement MDIO bus and support phylib Max Filippov
  2016-08-05 17:27   ` Joe Hershberger
@ 2016-08-15 20:33   ` Joe Hershberger
  1 sibling, 0 replies; 16+ messages in thread
From: Joe Hershberger @ 2016-08-15 20:33 UTC (permalink / raw)
  To: u-boot

Hi Max,

https://patchwork.ozlabs.org/patch/656239/ was applied to u-boot-net.git.

Thanks!
-Joe

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

end of thread, other threads:[~2016-08-15 20:33 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-05 15:26 [U-Boot] [PATCH v2 0/7] net/ethoc improvements Max Filippov
2016-08-05 15:26 ` [U-Boot] [PATCH v2 1/7] net/ethoc: add Kconfig entry for the driver Max Filippov
2016-08-15 20:33   ` [U-Boot] " Joe Hershberger
2016-08-05 15:26 ` [U-Boot] [PATCH v2 2/7] net/ethoc: use priv instead of dev internally Max Filippov
2016-08-15 20:33   ` [U-Boot] " Joe Hershberger
2016-08-05 15:26 ` [U-Boot] [PATCH v2 3/7] net/ethoc: add CONFIG_DM_ETH support Max Filippov
2016-08-15 20:33   ` [U-Boot] " Joe Hershberger
2016-08-05 15:26 ` [U-Boot] [PATCH v2 4/7] net/ethoc: support device tree Max Filippov
2016-08-15 20:33   ` [U-Boot] " Joe Hershberger
2016-08-05 15:26 ` [U-Boot] [PATCH v2 5/7] net/ethoc: don't mix virtual and physical addresses Max Filippov
2016-08-15 20:33   ` [U-Boot] " Joe Hershberger
2016-08-05 15:26 ` [U-Boot] [PATCH v2 6/7] net/ethoc: support private memory configurations Max Filippov
2016-08-15 20:33   ` [U-Boot] " Joe Hershberger
2016-08-05 15:26 ` [U-Boot] [PATCH v2 7/7] net/ethoc: implement MDIO bus and support phylib Max Filippov
2016-08-05 17:27   ` Joe Hershberger
2016-08-15 20:33   ` [U-Boot] " Joe Hershberger

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.