public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/7] net/ethoc improvements
@ 2016-08-02 11:31 Max Filippov
  2016-08-02 11:31 ` [U-Boot] [PATCH 1/7] net/ethoc: add Kconfig entry for the driver Max Filippov
                   ` (7 more replies)
  0 siblings, 8 replies; 20+ messages in thread
From: Max Filippov @ 2016-08-02 11:31 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.

Please review.

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                  | 522 ++++++++++++++++++++++++++++-------
 include/configs/openrisc-generic.h   |   1 -
 include/dm/platform_data/net_ethoc.h |  21 ++
 5 files changed, 450 insertions(+), 101 deletions(-)
 create mode 100644 include/dm/platform_data/net_ethoc.h

-- 
2.1.4

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

* [U-Boot] [PATCH 1/7] net/ethoc: add Kconfig entry for the driver
  2016-08-02 11:31 [U-Boot] [PATCH 0/7] net/ethoc improvements Max Filippov
@ 2016-08-02 11:31 ` Max Filippov
  2016-08-04 17:11   ` Joe Hershberger
  2016-08-02 11:31 ` [U-Boot] [PATCH 2/7] net/ethoc: use priv instead of dev internally Max Filippov
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 20+ messages in thread
From: Max Filippov @ 2016-08-02 11:31 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>
---
 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] 20+ messages in thread

* [U-Boot] [PATCH 2/7] net/ethoc: use priv instead of dev internally
  2016-08-02 11:31 [U-Boot] [PATCH 0/7] net/ethoc improvements Max Filippov
  2016-08-02 11:31 ` [U-Boot] [PATCH 1/7] net/ethoc: add Kconfig entry for the driver Max Filippov
@ 2016-08-02 11:31 ` Max Filippov
  2016-08-04 17:16   ` Joe Hershberger
  2016-08-02 11:31 ` [U-Boot] [PATCH 3/7] net/ethoc: add CONFIG_DM_ETH support Max Filippov
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 20+ messages in thread
From: Max Filippov @ 2016-08-02 11:31 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>
---
 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] 20+ messages in thread

* [U-Boot] [PATCH 3/7] net/ethoc: add CONFIG_DM_ETH support
  2016-08-02 11:31 [U-Boot] [PATCH 0/7] net/ethoc improvements Max Filippov
  2016-08-02 11:31 ` [U-Boot] [PATCH 1/7] net/ethoc: add Kconfig entry for the driver Max Filippov
  2016-08-02 11:31 ` [U-Boot] [PATCH 2/7] net/ethoc: use priv instead of dev internally Max Filippov
@ 2016-08-02 11:31 ` Max Filippov
  2016-08-04  1:16   ` Simon Glass
  2016-08-04 17:51   ` Joe Hershberger
  2016-08-02 11:31 ` [U-Boot] [PATCH 4/7] net/ethoc: support device tree Max Filippov
                   ` (4 subsequent siblings)
  7 siblings, 2 replies; 20+ messages in thread
From: Max Filippov @ 2016-08-02 11:31 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>
---
 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..0225595 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_set_mac_address(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_recv_common(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,47 @@ 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;
+}
+
+#ifndef CONFIG_DM_ETH
+
+static int ethoc_init(struct eth_device *dev, bd_t *bd)
+{
+	struct ethoc *priv = (struct ethoc *)dev->priv;
+
+	priv->iobase = ioremap(dev->iobase, ETHOC_IOSIZE);
+	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_set_mac_address(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 +510,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_recv_common(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 +549,91 @@ 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;
 }
+
+#else
+
+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_set_mac_address(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)
+		ethoc_recv_common(priv);
+
+	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),
+};
+
+#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] 20+ messages in thread

* [U-Boot] [PATCH 4/7] net/ethoc: support device tree
  2016-08-02 11:31 [U-Boot] [PATCH 0/7] net/ethoc improvements Max Filippov
                   ` (2 preceding siblings ...)
  2016-08-02 11:31 ` [U-Boot] [PATCH 3/7] net/ethoc: add CONFIG_DM_ETH support Max Filippov
@ 2016-08-02 11:31 ` Max Filippov
  2016-08-04 18:01   ` Joe Hershberger
  2016-08-02 11:31 ` [U-Boot] [PATCH 5/7] net/ethoc: don't mix virtual and physical addresses Max Filippov
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 20+ messages in thread
From: Max Filippov @ 2016-08-02 11:31 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>
---
 drivers/net/ethoc.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index 0225595..8cb15c7 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -600,6 +600,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);
@@ -626,9 +634,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] 20+ messages in thread

* [U-Boot] [PATCH 5/7] net/ethoc: don't mix virtual and physical addresses
  2016-08-02 11:31 [U-Boot] [PATCH 0/7] net/ethoc improvements Max Filippov
                   ` (3 preceding siblings ...)
  2016-08-02 11:31 ` [U-Boot] [PATCH 4/7] net/ethoc: support device tree Max Filippov
@ 2016-08-02 11:31 ` Max Filippov
  2016-08-04 18:08   ` Joe Hershberger
  2016-08-02 11:31 ` [U-Boot] [PATCH 6/7] net/ethoc: support private memory configurations Max Filippov
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 20+ messages in thread
From: Max Filippov @ 2016-08-02 11:31 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>
---
 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 8cb15c7..e25dd1b 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] 20+ messages in thread

* [U-Boot] [PATCH 6/7] net/ethoc: support private memory configurations
  2016-08-02 11:31 [U-Boot] [PATCH 0/7] net/ethoc improvements Max Filippov
                   ` (4 preceding siblings ...)
  2016-08-02 11:31 ` [U-Boot] [PATCH 5/7] net/ethoc: don't mix virtual and physical addresses Max Filippov
@ 2016-08-02 11:31 ` Max Filippov
  2016-08-04 19:43   ` Joe Hershberger
  2016-08-02 11:31 ` [U-Boot] [PATCH 7/7] net/ethoc: implement MDIO bus and support phylib Max Filippov
  2016-08-04 17:10 ` [U-Boot] [PATCH 0/7] net/ethoc improvements Joe Hershberger
  7 siblings, 1 reply; 20+ messages in thread
From: Max Filippov @ 2016-08-02 11:31 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>
---
 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 e25dd1b..fa623d5 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);
@@ -606,8 +633,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;
 }
 
@@ -617,6 +648,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] 20+ messages in thread

* [U-Boot] [PATCH 7/7] net/ethoc: implement MDIO bus and support phylib
  2016-08-02 11:31 [U-Boot] [PATCH 0/7] net/ethoc improvements Max Filippov
                   ` (5 preceding siblings ...)
  2016-08-02 11:31 ` [U-Boot] [PATCH 6/7] net/ethoc: support private memory configurations Max Filippov
@ 2016-08-02 11:31 ` Max Filippov
  2016-08-04 20:48   ` Joe Hershberger
  2016-08-04 17:10 ` [U-Boot] [PATCH 0/7] net/ethoc improvements Joe Hershberger
  7 siblings, 1 reply; 20+ messages in thread
From: Max Filippov @ 2016-08-02 11:31 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>
---
 drivers/net/ethoc.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 146 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index fa623d5..fe04396 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -181,6 +181,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
 };
 
 /**
@@ -319,13 +324,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,13 +532,119 @@ 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;
+	ulong tmo = get_timer(0);
+
+	ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(addr, reg));
+	ethoc_write(priv, MIICOMMAND, MIICOMMAND_READ);
+
+	while (get_timer(tmo) < CONFIG_SYS_HZ) {
+		u32 status = ethoc_read(priv, MIISTATUS);
+
+		if (!(status & MIISTATUS_BUSY)) {
+			u32 data = ethoc_read(priv, MIIRX_DATA);
+
+			/* reset MII command register */
+			ethoc_write(priv, MIICOMMAND, 0);
+			return data;
+		}
+	}
+	return -ETIMEDOUT;
+}
+
+static int ethoc_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
+			    u16 val)
+{
+	struct ethoc *priv = bus->priv;
+	ulong tmo = get_timer(0);
+
+	ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(addr, reg));
+	ethoc_write(priv, MIITX_DATA, val);
+	ethoc_write(priv, MIICOMMAND, MIICOMMAND_WRITE);
+
+	while (get_timer(tmo) < CONFIG_SYS_HZ) {
+		u32 stat = ethoc_read(priv, MIISTATUS);
+
+		if (!(stat & MIISTATUS_BUSY)) {
+			/* reset MII command register */
+			ethoc_write(priv, MIICOMMAND, 0);
+			return 0;
+		}
+	}
+	return -ETIMEDOUT;
+}
+
+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
+
 #ifndef CONFIG_DM_ETH
 
 static int ethoc_init(struct eth_device *dev, bd_t *bd)
 {
 	struct ethoc *priv = (struct ethoc *)dev->priv;
 
-	priv->iobase = ioremap(dev->iobase, ETHOC_IOSIZE);
 	return ethoc_init_common(priv);
 }
 
@@ -534,7 +663,7 @@ 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->priv);
+	ethoc_stop_common(dev->priv);
 }
 
 static int ethoc_recv(struct eth_device *dev)
@@ -584,6 +713,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;
 }
 
@@ -625,9 +758,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)
@@ -653,6 +784,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;
 }
 
@@ -660,6 +795,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;
 }
-- 
2.1.4

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

* [U-Boot] [PATCH 3/7] net/ethoc: add CONFIG_DM_ETH support
  2016-08-02 11:31 ` [U-Boot] [PATCH 3/7] net/ethoc: add CONFIG_DM_ETH support Max Filippov
@ 2016-08-04  1:16   ` Simon Glass
  2016-08-04 17:51   ` Joe Hershberger
  1 sibling, 0 replies; 20+ messages in thread
From: Simon Glass @ 2016-08-04  1:16 UTC (permalink / raw)
  To: u-boot

On 2 August 2016 at 05:31, Max Filippov <jcmvbkbc@gmail.com> wrote:
> 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>
> ---
>  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

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH 0/7] net/ethoc improvements
  2016-08-02 11:31 [U-Boot] [PATCH 0/7] net/ethoc improvements Max Filippov
                   ` (6 preceding siblings ...)
  2016-08-02 11:31 ` [U-Boot] [PATCH 7/7] net/ethoc: implement MDIO bus and support phylib Max Filippov
@ 2016-08-04 17:10 ` Joe Hershberger
  2016-08-04 17:26   ` Tom Rini
  7 siblings, 1 reply; 20+ messages in thread
From: Joe Hershberger @ 2016-08-04 17:10 UTC (permalink / raw)
  To: u-boot

Hi Tom,

On Tue, Aug 2, 2016 at 6:31 AM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> 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.
>
> Please review.
>
> 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

I'm gonna put these in my queue on PW if that's OK with you.

-Joe

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

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

On Tue, Aug 2, 2016 at 6:31 AM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> 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>

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

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

On Tue, Aug 2, 2016 at 6:31 AM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> 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>

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

* [U-Boot] [PATCH 0/7] net/ethoc improvements
  2016-08-04 17:10 ` [U-Boot] [PATCH 0/7] net/ethoc improvements Joe Hershberger
@ 2016-08-04 17:26   ` Tom Rini
  0 siblings, 0 replies; 20+ messages in thread
From: Tom Rini @ 2016-08-04 17:26 UTC (permalink / raw)
  To: u-boot

On Thu, Aug 04, 2016 at 12:10:33PM -0500, Joe Hershberger wrote:
> Hi Tom,
> 
> On Tue, Aug 2, 2016 at 6:31 AM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> > 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.
> >
> > Please review.
> >
> > 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
> 
> I'm gonna put these in my queue on PW if that's OK with you.

Sounds good, thanks.

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160804/d4c672ec/attachment.sig>

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

* [U-Boot] [PATCH 3/7] net/ethoc: add CONFIG_DM_ETH support
  2016-08-02 11:31 ` [U-Boot] [PATCH 3/7] net/ethoc: add CONFIG_DM_ETH support Max Filippov
  2016-08-04  1:16   ` Simon Glass
@ 2016-08-04 17:51   ` Joe Hershberger
  2016-08-05 14:06     ` Max Filippov
  1 sibling, 1 reply; 20+ messages in thread
From: Joe Hershberger @ 2016-08-04 17:51 UTC (permalink / raw)
  To: u-boot

On Tue, Aug 2, 2016 at 6:31 AM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> 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>

A few small nits below, but otherwise,

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

> ---
>  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..0225595 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_set_mac_address(struct ethoc *priv, u8 *mac)

Please use ethoc_write_hwaddr_common() instead.

>  {
> -       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_recv_common(struct ethoc *priv)

Please use a better name for this, something like ethoc_is_rx_pkt_rdy().

> +{
> +       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,47 @@ 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;
> +}
> +
> +#ifndef CONFIG_DM_ETH

Please use positive logic and reverse the order of these code snippets.

#ifdef CONFIG_DM_ETH
...
#else
...
#endif

> +
> +static int ethoc_init(struct eth_device *dev, bd_t *bd)
> +{
> +       struct ethoc *priv = (struct ethoc *)dev->priv;
> +
> +       priv->iobase = ioremap(dev->iobase, ETHOC_IOSIZE);
> +       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_set_mac_address(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 +510,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_recv_common(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 +549,91 @@ 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;
>  }
> +
> +#else
> +
> +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_set_mac_address(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)
> +               ethoc_recv_common(priv);

Kinda seems like you should skip the next call (especially when this
is renamed to be clearer). The code flow seems OK, though. Up to you.

> +
> +       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),
> +};
> +
> +#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 */

Thanks,
-Joe

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

* [U-Boot] [PATCH 4/7] net/ethoc: support device tree
  2016-08-02 11:31 ` [U-Boot] [PATCH 4/7] net/ethoc: support device tree Max Filippov
@ 2016-08-04 18:01   ` Joe Hershberger
  0 siblings, 0 replies; 20+ messages in thread
From: Joe Hershberger @ 2016-08-04 18:01 UTC (permalink / raw)
  To: u-boot

On Tue, Aug 2, 2016 at 6:31 AM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> 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>

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

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

On Tue, Aug 2, 2016 at 6:31 AM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> 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>

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

* [U-Boot] [PATCH 6/7] net/ethoc: support private memory configurations
  2016-08-02 11:31 ` [U-Boot] [PATCH 6/7] net/ethoc: support private memory configurations Max Filippov
@ 2016-08-04 19:43   ` Joe Hershberger
  0 siblings, 0 replies; 20+ messages in thread
From: Joe Hershberger @ 2016-08-04 19:43 UTC (permalink / raw)
  To: u-boot

On Tue, Aug 2, 2016 at 6:31 AM, Max Filippov <jcmvbkbc@gmail.com> wrote:
> 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>

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

* [U-Boot] [PATCH 7/7] net/ethoc: implement MDIO bus and support phylib
  2016-08-02 11:31 ` [U-Boot] [PATCH 7/7] net/ethoc: implement MDIO bus and support phylib Max Filippov
@ 2016-08-04 20:48   ` Joe Hershberger
  2016-08-05 14:36     ` Max Filippov
  0 siblings, 1 reply; 20+ messages in thread
From: Joe Hershberger @ 2016-08-04 20:48 UTC (permalink / raw)
  To: u-boot

Hi Max,

On Tue, Aug 2, 2016 at 6:31 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>
> ---
>  drivers/net/ethoc.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 146 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
> index fa623d5..fe04396 100644
> --- a/drivers/net/ethoc.c
> +++ b/drivers/net/ethoc.c
> @@ -181,6 +181,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
>  };
>
>  /**
> @@ -319,13 +324,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,13 +532,119 @@ 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;
> +       ulong tmo = get_timer(0);
> +
> +       ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(addr, reg));
> +       ethoc_write(priv, MIICOMMAND, MIICOMMAND_READ);
> +
> +       while (get_timer(tmo) < CONFIG_SYS_HZ) {
> +               u32 status = ethoc_read(priv, MIISTATUS);
> +
> +               if (!(status & MIISTATUS_BUSY)) {

It would be good to use wait_for_bit(). You could add a small helper
to this file that adds the iobase to the addr and then calls
wait_for_bit().

> +                       u32 data = ethoc_read(priv, MIIRX_DATA);
> +
> +                       /* reset MII command register */
> +                       ethoc_write(priv, MIICOMMAND, 0);
> +                       return data;
> +               }
> +       }
> +       return -ETIMEDOUT;
> +}
> +
> +static int ethoc_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
> +                           u16 val)
> +{
> +       struct ethoc *priv = bus->priv;
> +       ulong tmo = get_timer(0);
> +
> +       ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(addr, reg));
> +       ethoc_write(priv, MIITX_DATA, val);
> +       ethoc_write(priv, MIICOMMAND, MIICOMMAND_WRITE);
> +
> +       while (get_timer(tmo) < CONFIG_SYS_HZ) {
> +               u32 stat = ethoc_read(priv, MIISTATUS);
> +
> +               if (!(stat & MIISTATUS_BUSY)) {
> +                       /* reset MII command register */
> +                       ethoc_write(priv, MIICOMMAND, 0);
> +                       return 0;
> +               }
> +       }
> +       return -ETIMEDOUT;
> +}
> +
> +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
> +
>  #ifndef CONFIG_DM_ETH
>
>  static int ethoc_init(struct eth_device *dev, bd_t *bd)
>  {
>         struct ethoc *priv = (struct ethoc *)dev->priv;
>
> -       priv->iobase = ioremap(dev->iobase, ETHOC_IOSIZE);

Why? Is this an accident? At the very least it seems unrelated and
should be a separate patch.

>         return ethoc_init_common(priv);
>  }
>
> @@ -534,7 +663,7 @@ 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->priv);
> +       ethoc_stop_common(dev->priv);
>  }
>
>  static int ethoc_recv(struct eth_device *dev)
> @@ -584,6 +713,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;
>  }
>
> @@ -625,9 +758,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)
> @@ -653,6 +784,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;
>  }
>
> @@ -660,6 +795,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;
>  }
> --
> 2.1.4
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

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

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

On Thu, Aug 4, 2016 at 8:51 PM, Joe Hershberger
<joe.hershberger@gmail.com> wrote:
> On Tue, Aug 2, 2016 at 6:31 AM, Max Filippov <jcmvbkbc@gmail.com> wrote:
>> 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>
>
> A few small nits below, but otherwise,
>
> Acked-by: Joe Hershberger <joe.hershberger@ni.com>
>
>> diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
>> index f5bd1ab..0225595 100644
>> --- a/drivers/net/ethoc.c
>> +++ b/drivers/net/ethoc.c

[...]

>> @@ -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_set_mac_address(struct ethoc *priv, u8 *mac)
>
> Please use ethoc_write_hwaddr_common() instead.

Ok.

[...]

>> +static int ethoc_recv_common(struct ethoc *priv)
>
> Please use a better name for this, something like ethoc_is_rx_pkt_rdy().

It's a bit more complex than that, it would only return
1 if new packets arrived since its last invocation. When
it returns 0 there still may be received packets in the
RX queue. I'll call it ethoc_is_new_packet_received.

[...]

>> +#ifndef CONFIG_DM_ETH
>
> Please use positive logic and reverse the order of these code snippets.
>
> #ifdef CONFIG_DM_ETH
> ...
> #else
> ...
> #endif

Ok.

[...]

>> +static int ethoc_recv(struct udevice *dev, int flags, uchar **packetp)
>> +{
>> +       struct ethoc *priv = dev_get_priv(dev);
>> +
>> +       if (flags & ETH_RECV_CHECK_DEVICE)
>> +               ethoc_recv_common(priv);
>
> Kinda seems like you should skip the next call (especially when this
> is renamed to be clearer). The code flow seems OK, though. Up to you.

Ok.

-- 
Thanks.
-- Max

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

* [U-Boot] [PATCH 7/7] net/ethoc: implement MDIO bus and support phylib
  2016-08-04 20:48   ` Joe Hershberger
@ 2016-08-05 14:36     ` Max Filippov
  0 siblings, 0 replies; 20+ messages in thread
From: Max Filippov @ 2016-08-05 14:36 UTC (permalink / raw)
  To: u-boot

On Thu, Aug 4, 2016 at 11:48 PM, Joe Hershberger
<joe.hershberger@gmail.com> wrote:
> On Tue, Aug 2, 2016 at 6:31 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>

[...]

>> +static int ethoc_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
>> +{
>> +       struct ethoc *priv = bus->priv;
>> +       ulong tmo = get_timer(0);
>> +
>> +       ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(addr, reg));
>> +       ethoc_write(priv, MIICOMMAND, MIICOMMAND_READ);
>> +
>> +       while (get_timer(tmo) < CONFIG_SYS_HZ) {
>> +               u32 status = ethoc_read(priv, MIISTATUS);
>> +
>> +               if (!(status & MIISTATUS_BUSY)) {
>
> It would be good to use wait_for_bit(). You could add a small helper
> to this file that adds the iobase to the addr and then calls
> wait_for_bit().

Ok.

[...]

>>  static int ethoc_init(struct eth_device *dev, bd_t *bd)
>>  {
>>         struct ethoc *priv = (struct ethoc *)dev->priv;
>>
>> -       priv->iobase = ioremap(dev->iobase, ETHOC_IOSIZE);
>
> Why? Is this an accident? At the very least it seems unrelated and
> should be a separate patch.

Oops, right. I've been moving this bit around several times and
apparently haven't cleaned up all of its traces.

-- 
Thanks.
-- Max

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

end of thread, other threads:[~2016-08-05 14:36 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-08-02 11:31 [U-Boot] [PATCH 0/7] net/ethoc improvements Max Filippov
2016-08-02 11:31 ` [U-Boot] [PATCH 1/7] net/ethoc: add Kconfig entry for the driver Max Filippov
2016-08-04 17:11   ` Joe Hershberger
2016-08-02 11:31 ` [U-Boot] [PATCH 2/7] net/ethoc: use priv instead of dev internally Max Filippov
2016-08-04 17:16   ` Joe Hershberger
2016-08-02 11:31 ` [U-Boot] [PATCH 3/7] net/ethoc: add CONFIG_DM_ETH support Max Filippov
2016-08-04  1:16   ` Simon Glass
2016-08-04 17:51   ` Joe Hershberger
2016-08-05 14:06     ` Max Filippov
2016-08-02 11:31 ` [U-Boot] [PATCH 4/7] net/ethoc: support device tree Max Filippov
2016-08-04 18:01   ` Joe Hershberger
2016-08-02 11:31 ` [U-Boot] [PATCH 5/7] net/ethoc: don't mix virtual and physical addresses Max Filippov
2016-08-04 18:08   ` Joe Hershberger
2016-08-02 11:31 ` [U-Boot] [PATCH 6/7] net/ethoc: support private memory configurations Max Filippov
2016-08-04 19:43   ` Joe Hershberger
2016-08-02 11:31 ` [U-Boot] [PATCH 7/7] net/ethoc: implement MDIO bus and support phylib Max Filippov
2016-08-04 20:48   ` Joe Hershberger
2016-08-05 14:36     ` Max Filippov
2016-08-04 17:10 ` [U-Boot] [PATCH 0/7] net/ethoc improvements Joe Hershberger
2016-08-04 17:26   ` Tom Rini

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