All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v7 0/5] dma: add channels support
@ 2018-11-10 21:06 Grygorii Strashko
  2018-11-10 21:06 ` [U-Boot] [PATCH v7 1/5] dma: move dma_ops to dma-uclass.h Grygorii Strashko
                   ` (5 more replies)
  0 siblings, 6 replies; 145+ messages in thread
From: Grygorii Strashko @ 2018-11-10 21:06 UTC (permalink / raw)
  To: u-boot

Hi All,

This series is the next try to add DMA channels support for DMA controllers
which last version was posted by Álvaro Fernández Rojas [1].
i've kept version numbering.

Comparing to the original post I've added few changes:
 - added possibility to pass DMA driver/channel's specific data per each transfer
 using additional parameter "metadata" in dma_send/dma_receive() API.
 For example, port number for network packets to be directed to the
 specific port on multi port ethernet controllers.
 - added new dma_prepare_rcv_buf() API which allows to implement zero-copy
 DEV_TO_MEM transfer using DMA streaming channels which is usual case
 for Networking.
 - added dma-uclass test
 - removed unused function dma_get_by_index_platdata()
 - updated comments

Hence, originally DMA channels support was introduced to add support for
"bmips: add bcm6348-enet support" - that series can be easily updated following
DMA channels API changes (if still actual).

Patches 5-6 - Here I'm providing DMA and networking drivers for the new
TI AM65x SoC [2] as an illustration of DMA channels API usage only. Unfortunately,
those drivers are still under development so NOT-FOR-MERGE (!will not build!)
- we'd like code/bindings to be accepted in LKML first.
Full sources can be found at [3].

[1] https://patchwork.ozlabs.org/cover/881642/
[2] http://www.ti.com/lit/ug/spruid7b/spruid7b.pdf
[3] git at git.ti.com:~gragst/ti-u-boot/gragsts-ti-u-boot.git
    branch: master-am6-dma-wip
===

A DMA is a feature of computer systems that allows certain hardware
subsystems to access main system memory, independent of the CPU.
DMA channels are typically generated externally to the HW module
consuming them, by an entity this API calls a DMA provider. This API
provides a standard means for drivers to enable and disable DMAs, and to
copy, send and receive data using DMA.

DMA channel API:
 dma_get_by_index()
 dma_get_by_name()
 dma_request()
 dma_free()
 dma_enable()
 dma_disable()
 dma_prepare_rcv_buf()
 dma_receive()
 dma_send()

A driver that implements UCLASS_DMA is a DMA provider. A provider will
often implement multiple separate DMAs channels, since the hardware it manages
often has this capability. dma_uclass.h describes the interface which
DMA providers must implement.

DMA consumers/clients are the HW modules driven by the DMA channels. 

DMA consumer DMA_MEM_TO_DEV (transmit) usage example (based on networking).
Note. In u-boot dma_send() is sync operation always - it'll start transfer and
will poll for it to complete:
- get/request dma channel
	struct dma dma_tx;
	ret = dma_get_by_name(common->dev, "tx0", &dma_tx);
	if (ret) ...

- enable dma channel
	ret = dma_enable(&dma_tx);
	if (ret) ...

- dma transmit DMA_MEM_TO_DEV.
	struct ti_drv_packet_data packet_data;
	
	packet_data.opt1 = val1;
	packet_data.opt2 = val2;
	ret = dma_send(&dma_tx, packet, length, &packet_data);
	if (ret) ..

DMA consumer DMA_DEV_TO_MEM (receive) usage example (based on networking).
Note. dma_receive() is sync operation always - it'll start transfer
(if required) and will poll for it to complete (or for any previously
configured dev2mem transfer to complete):
- get/request dma channel
	struct dma dma_rx;
	ret = dma_get_by_name(common->dev, "rx0", &dma_rx);
	if (ret) ...

- enable dma channel
	ret = dma_enable(&dma_rx);
	if (ret) ...

- dma receive DMA_DEV_TO_MEM.
	struct ti_drv_packet_data packet_data;
	
	len = dma_receive(&dma_rx, (void **)packet, &packet_data);
	if (ret < 0) ...

DMA consumer DMA_DEV_TO_MEM (receive) zero-copy usage example (based on
networking). Networking subsystem allows to configure and use few receive
buffers (dev2mem), as Networking RX DMA channels usually implemented
as streaming interface
- get/request dma channel
	struct dma dma_rx;
	ret = dma_get_by_name(common->dev, "rx0", &dma_rx);
	if (ret) ...
	
	for (i = 0; i < RX_DESC_NUM; i++) {
		ret = dma_prepare_rcv_buf(&dma_rx,
					  net_rx_packets[i],
					  RX_BUF_SIZE);
		if (ret) ...
	}

- enable dma channel
	ret = dma_enable(&dma_rx);
	if (ret) ...

- dma receive DMA_DEV_TO_MEM.
	struct ti_drv_packet_data packet_data;
	void *packet;
	
	len = dma_receive(&dma_rx, &packet, &packet_data);
	if (ret < 0) ..
	
	/* packet - points on buffer prepared by dma_prepare_rcv_buf().
	   process packet*/
	
	- return buffer back to DAM channel
	ret = dma_prepare_rcv_buf(&dma_rx,
				  net_rx_packets[rx_next],
				  RX_BUF_SIZE);

changes in v7:
 - copyright fixed as suggested by Tom Rini
 - added "Reviewed-by" tags

v1: http://patchwork.ozlabs.org/cover/987948/

Grygorii Strashko (2):
  test: dma: add dma-uclass test
  net: ethernet: ti: introduce am654 gigabit eth switch subsystem driver

Vignesh R (1):
  dma: ti: add driver to K3 UDMA

Álvaro Fernández Rojas (2):
  dma: move dma_ops to dma-uclass.h
  dma: add channels support

 arch/sandbox/dts/test.dts         |    8 +
 configs/sandbox_defconfig         |    3 +
 drivers/dma/Kconfig               |   16 +
 drivers/dma/Makefile              |    3 +
 drivers/dma/dma-uclass.c          |  183 +++-
 drivers/dma/sandbox-dma-test.c    |  282 +++++++
 drivers/dma/ti-edma3.c            |    2 +-
 drivers/dma/ti/Kconfig            |   14 +
 drivers/dma/ti/Makefile           |    3 +
 drivers/dma/ti/k3-udma-hwdef.h    |  184 ++++
 drivers/dma/ti/k3-udma.c          | 1679 +++++++++++++++++++++++++++++++++++++
 drivers/net/Kconfig               |    8 +
 drivers/net/Makefile              |    1 +
 drivers/net/am65-cpsw-nuss.c      |  962 +++++++++++++++++++++
 include/dma-uclass.h              |  128 +++
 include/dma.h                     |  282 ++++++-
 include/dt-bindings/dma/k3-udma.h |   26 +
 include/linux/soc/ti/ti-udma.h    |   24 +
 test/dm/Makefile                  |    1 +
 test/dm/dma.c                     |  123 +++
 20 files changed, 3902 insertions(+), 30 deletions(-)
 create mode 100644 drivers/dma/sandbox-dma-test.c
 create mode 100644 drivers/dma/ti/Kconfig
 create mode 100644 drivers/dma/ti/Makefile
 create mode 100644 drivers/dma/ti/k3-udma-hwdef.h
 create mode 100644 drivers/dma/ti/k3-udma.c
 create mode 100644 drivers/net/am65-cpsw-nuss.c
 create mode 100644 include/dma-uclass.h
 create mode 100644 include/dt-bindings/dma/k3-udma.h
 create mode 100644 include/linux/soc/ti/ti-udma.h
 create mode 100644 test/dm/dma.c

-- 
2.10.5

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

* [U-Boot] [PATCH v7 1/5] dma: move dma_ops to dma-uclass.h
  2018-11-10 21:06 [U-Boot] [PATCH v7 0/5] dma: add channels support Grygorii Strashko
@ 2018-11-10 21:06 ` Grygorii Strashko
  2018-11-10 21:06 ` [U-Boot] [PATCH v7 2/5] dma: add channels support Grygorii Strashko
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 145+ messages in thread
From: Grygorii Strashko @ 2018-11-10 21:06 UTC (permalink / raw)
  To: u-boot

From: Álvaro Fernández Rojas <noltari@gmail.com>

Move dma_ops to a separate header file, following other uclass
implementations. While doing so, this patch also improves dma_ops
documentation.

Reviewed-by: Tom Rini <trini@konsulko.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
 drivers/dma/dma-uclass.c |  2 +-
 drivers/dma/ti-edma3.c   |  2 +-
 include/dma-uclass.h     | 39 +++++++++++++++++++++++++++++++++++++++
 include/dma.h            | 22 ----------------------
 4 files changed, 41 insertions(+), 24 deletions(-)
 create mode 100644 include/dma-uclass.h

diff --git a/drivers/dma/dma-uclass.c b/drivers/dma/dma-uclass.c
index a33f7d5..6c3506c 100644
--- a/drivers/dma/dma-uclass.c
+++ b/drivers/dma/dma-uclass.c
@@ -9,10 +9,10 @@
  */
 
 #include <common.h>
-#include <dma.h>
 #include <dm.h>
 #include <dm/uclass-internal.h>
 #include <dm/device-internal.h>
+#include <dma-uclass.h>
 #include <errno.h>
 
 int dma_get_device(u32 transfer_type, struct udevice **devp)
diff --git a/drivers/dma/ti-edma3.c b/drivers/dma/ti-edma3.c
index 2131e10..7e11b13 100644
--- a/drivers/dma/ti-edma3.c
+++ b/drivers/dma/ti-edma3.c
@@ -11,7 +11,7 @@
 #include <asm/io.h>
 #include <common.h>
 #include <dm.h>
-#include <dma.h>
+#include <dma-uclass.h>
 #include <asm/omap_common.h>
 #include <asm/ti-common/ti-edma3.h>
 
diff --git a/include/dma-uclass.h b/include/dma-uclass.h
new file mode 100644
index 0000000..7bec5d3
--- /dev/null
+++ b/include/dma-uclass.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ * Copyright (C) 2015 Texas Instruments Incorporated <www.ti.com>
+ * Written by Mugunthan V N <mugunthanvnm@ti.com>
+ *
+ */
+
+#ifndef _DMA_UCLASS_H
+#define _DMA_UCLASS_H
+
+/* See dma.h for background documentation. */
+
+#include <dma.h>
+
+/*
+ * struct dma_ops - Driver model DMA operations
+ *
+ * The uclass interface is implemented by all DMA devices which use
+ * driver model.
+ */
+struct dma_ops {
+	/**
+	 * transfer() - Issue a DMA transfer. The implementation must
+	 *   wait until the transfer is done.
+	 *
+	 * @dev: The DMA device
+	 * @direction: direction of data transfer (should be one from
+	 *   enum dma_direction)
+	 * @dst: The destination pointer.
+	 * @src: The source pointer.
+	 * @len: Length of the data to be copied (number of bytes).
+	 * @return zero on success, or -ve error code.
+	 */
+	int (*transfer)(struct udevice *dev, int direction, void *dst,
+			void *src, size_t len);
+};
+
+#endif /* _DMA_UCLASS_H */
diff --git a/include/dma.h b/include/dma.h
index 50e9652..97fa0cf 100644
--- a/include/dma.h
+++ b/include/dma.h
@@ -27,28 +27,6 @@ enum dma_direction {
 #define DMA_SUPPORTS_DEV_TO_DEV	BIT(3)
 
 /*
- * struct dma_ops - Driver model DMA operations
- *
- * The uclass interface is implemented by all DMA devices which use
- * driver model.
- */
-struct dma_ops {
-	/*
-	 * Get the current timer count
-	 *
-	 * @dev: The DMA device
-	 * @direction: direction of data transfer should be one from
-		       enum dma_direction
-	 * @dst: Destination pointer
-	 * @src: Source pointer
-	 * @len: Length of the data to be copied.
-	 * @return: 0 if OK, -ve on error
-	 */
-	int (*transfer)(struct udevice *dev, int direction, void *dst,
-			void *src, size_t len);
-};
-
-/*
  * struct dma_dev_priv - information about a device used by the uclass
  *
  * @supported: mode of transfers that DMA can support, should be
-- 
2.10.5

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

* [U-Boot] [PATCH v7 2/5] dma: add channels support
  2018-11-10 21:06 [U-Boot] [PATCH v7 0/5] dma: add channels support Grygorii Strashko
  2018-11-10 21:06 ` [U-Boot] [PATCH v7 1/5] dma: move dma_ops to dma-uclass.h Grygorii Strashko
@ 2018-11-10 21:06 ` Grygorii Strashko
  2018-11-13 19:53   ` Simon Glass
  2018-11-10 21:06 ` [U-Boot] [PATCH v7 3/5] test: dma: add dma-uclass test Grygorii Strashko
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 145+ messages in thread
From: Grygorii Strashko @ 2018-11-10 21:06 UTC (permalink / raw)
  To: u-boot

From: Álvaro Fernández Rojas <noltari@gmail.com>

This adds channels support for dma controllers that have multiple channels
which can transfer data to/from different devices (enet, usb...).

DMA channle API:
 dma_get_by_index()
 dma_get_by_name()
 dma_request()
 dma_free()
 dma_enable()
 dma_disable()
 dma_prepare_rcv_buf()
 dma_receive()
 dma_send()

Reviewed-by: Tom Rini <trini@konsulko.com>
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
[grygorii.strashko at ti.com: drop unused dma_get_by_index_platdata(),
 add metadata to send/receive ops, add dma_prepare_rcv_buf(),
 minor clean up]
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
 drivers/dma/Kconfig      |   7 ++
 drivers/dma/dma-uclass.c | 181 ++++++++++++++++++++++++++++++++-
 include/dma-uclass.h     |  91 ++++++++++++++++-
 include/dma.h            | 260 ++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 532 insertions(+), 7 deletions(-)

diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 4ee6afa..b9b85c6 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -12,6 +12,13 @@ config DMA
 	  buses that is used to transfer data to and from memory.
 	  The uclass interface is defined in include/dma.h.
 
+config DMA_CHANNELS
+	bool "Enable DMA channels support"
+	depends on DMA
+	help
+	  Enable channels support for DMA. Some DMA controllers have multiple
+	  channels which can either transfer data to/from different devices.
+
 config TI_EDMA3
 	bool "TI EDMA3 driver"
 	help
diff --git a/drivers/dma/dma-uclass.c b/drivers/dma/dma-uclass.c
index 6c3506c..9c961cf 100644
--- a/drivers/dma/dma-uclass.c
+++ b/drivers/dma/dma-uclass.c
@@ -2,19 +2,192 @@
 /*
  * Direct Memory Access U-Class driver
  *
- * (C) Copyright 2015
- *     Texas Instruments Incorporated, <www.ti.com>
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ * Copyright (C) 2015 - 2018 Texas Instruments Incorporated <www.ti.com>
+ * Written by Mugunthan V N <mugunthanvnm@ti.com>
  *
  * Author: Mugunthan V N <mugunthanvnm@ti.com>
  */
 
 #include <common.h>
 #include <dm.h>
-#include <dm/uclass-internal.h>
-#include <dm/device-internal.h>
+#include <dm/read.h>
 #include <dma-uclass.h>
+#include <dt-structs.h>
 #include <errno.h>
 
+#ifdef CONFIG_DMA_CHANNELS
+static inline struct dma_ops *dma_dev_ops(struct udevice *dev)
+{
+	return (struct dma_ops *)dev->driver->ops;
+}
+
+# if CONFIG_IS_ENABLED(OF_CONTROL)
+static int dma_of_xlate_default(struct dma *dma,
+				struct ofnode_phandle_args *args)
+{
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (args->args_count > 1) {
+		pr_err("Invaild args_count: %d\n", args->args_count);
+		return -EINVAL;
+	}
+
+	if (args->args_count)
+		dma->id = args->args[0];
+	else
+		dma->id = 0;
+
+	return 0;
+}
+
+int dma_get_by_index(struct udevice *dev, int index, struct dma *dma)
+{
+	int ret;
+	struct ofnode_phandle_args args;
+	struct udevice *dev_dma;
+	const struct dma_ops *ops;
+
+	debug("%s(dev=%p, index=%d, dma=%p)\n", __func__, dev, index, dma);
+
+	assert(dma);
+	dma->dev = NULL;
+
+	ret = dev_read_phandle_with_args(dev, "dmas", "#dma-cells", 0, index,
+					 &args);
+	if (ret) {
+		pr_err("%s: dev_read_phandle_with_args failed: err=%d\n",
+		       __func__, ret);
+		return ret;
+	}
+
+	ret = uclass_get_device_by_ofnode(UCLASS_DMA, args.node, &dev_dma);
+	if (ret) {
+		pr_err("%s: uclass_get_device_by_ofnode failed: err=%d\n",
+		       __func__, ret);
+		return ret;
+	}
+
+	dma->dev = dev_dma;
+
+	ops = dma_dev_ops(dev_dma);
+
+	if (ops->of_xlate)
+		ret = ops->of_xlate(dma, &args);
+	else
+		ret = dma_of_xlate_default(dma, &args);
+	if (ret) {
+		pr_err("of_xlate() failed: %d\n", ret);
+		return ret;
+	}
+
+	return dma_request(dev_dma, dma);
+}
+
+int dma_get_by_name(struct udevice *dev, const char *name, struct dma *dma)
+{
+	int index;
+
+	debug("%s(dev=%p, name=%s, dma=%p)\n", __func__, dev, name, dma);
+	dma->dev = NULL;
+
+	index = dev_read_stringlist_search(dev, "dma-names", name);
+	if (index < 0) {
+		pr_err("dev_read_stringlist_search() failed: %d\n", index);
+		return index;
+	}
+
+	return dma_get_by_index(dev, index, dma);
+}
+# endif /* OF_CONTROL */
+
+int dma_request(struct udevice *dev, struct dma *dma)
+{
+	struct dma_ops *ops = dma_dev_ops(dev);
+
+	debug("%s(dev=%p, dma=%p)\n", __func__, dev, dma);
+
+	dma->dev = dev;
+
+	if (!ops->request)
+		return 0;
+
+	return ops->request(dma);
+}
+
+int dma_free(struct dma *dma)
+{
+	struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (!ops->free)
+		return 0;
+
+	return ops->free(dma);
+}
+
+int dma_enable(struct dma *dma)
+{
+	struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (!ops->enable)
+		return -ENOSYS;
+
+	return ops->enable(dma);
+}
+
+int dma_disable(struct dma *dma)
+{
+	struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (!ops->disable)
+		return -ENOSYS;
+
+	return ops->disable(dma);
+}
+
+int dma_prepare_rcv_buf(struct dma *dma, void *dst, size_t size)
+{
+	struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (!ops->prepare_rcv_buf)
+		return -1;
+
+	return ops->prepare_rcv_buf(dma, dst, size);
+}
+
+int dma_receive(struct dma *dma, void **dst, void *metadata)
+{
+	struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (!ops->receive)
+		return -ENOSYS;
+
+	return ops->receive(dma, dst, metadata);
+}
+
+int dma_send(struct dma *dma, void *src, size_t len, void *metadata)
+{
+	struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (!ops->send)
+		return -ENOSYS;
+
+	return ops->send(dma, src, len, metadata);
+}
+#endif /* CONFIG_DMA_CHANNELS */
+
 int dma_get_device(u32 transfer_type, struct udevice **devp)
 {
 	struct udevice *dev;
diff --git a/include/dma-uclass.h b/include/dma-uclass.h
index 7bec5d3..16fc879 100644
--- a/include/dma-uclass.h
+++ b/include/dma-uclass.h
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
- * Copyright (C) 2015 Texas Instruments Incorporated <www.ti.com>
+ * Copyright (C) 2015 - 2018 Texas Instruments Incorporated <www.ti.com>
  * Written by Mugunthan V N <mugunthanvnm@ti.com>
  *
  */
@@ -13,6 +13,8 @@
 
 #include <dma.h>
 
+struct ofnode_phandle_args;
+
 /*
  * struct dma_ops - Driver model DMA operations
  *
@@ -20,6 +22,93 @@
  * driver model.
  */
 struct dma_ops {
+#ifdef CONFIG_DMA_CHANNELS
+	/**
+	 * of_xlate - Translate a client's device-tree (OF) DMA specifier.
+	 *
+	 * The DMA core calls this function as the first step in implementing
+	 * a client's dma_get_by_*() call.
+	 *
+	 * If this function pointer is set to NULL, the DMA core will use a
+	 * default implementation, which assumes #dma-cells = <1>, and that
+	 * the DT cell contains a simple integer DMA Channel.
+	 *
+	 * At present, the DMA API solely supports device-tree. If this
+	 * changes, other xxx_xlate() functions may be added to support those
+	 * other mechanisms.
+	 *
+	 * @dma: The dma struct to hold the translation result.
+	 * @args:	The dma specifier values from device tree.
+	 * @return 0 if OK, or a negative error code.
+	 */
+	int (*of_xlate)(struct dma *dma,
+			struct ofnode_phandle_args *args);
+	/**
+	 * request - Request a translated DMA.
+	 *
+	 * The DMA core calls this function as the second step in
+	 * implementing a client's dma_get_by_*() call, following a successful
+	 * xxx_xlate() call, or as the only step in implementing a client's
+	 * dma_request() call.
+	 *
+	 * @dma: The DMA struct to request; this has been filled in by
+	 *   a previoux xxx_xlate() function call, or by the caller of
+	 *   dma_request().
+	 * @return 0 if OK, or a negative error code.
+	 */
+	int (*request)(struct dma *dma);
+	/**
+	 * free - Free a previously requested dma.
+	 *
+	 * This is the implementation of the client dma_free() API.
+	 *
+	 * @dma: The DMA to free.
+	 * @return 0 if OK, or a negative error code.
+	 */
+	int (*free)(struct dma *dma);
+	/**
+	 * enable() - Enable a DMA Channel.
+	 *
+	 * @dma: The DMA Channel to manipulate.
+	 * @return zero on success, or -ve error code.
+	 */
+	int (*enable)(struct dma *dma);
+	/**
+	 * disable() - Disable a DMA Channel.
+	 *
+	 * @dma: The DMA Channel to manipulate.
+	 * @return zero on success, or -ve error code.
+	 */
+	int (*disable)(struct dma *dma);
+	/**
+	 * add_rcv_buf() - Prepare/Add receive DMA buffer.
+	 *
+	 * @dma: The DMA Channel to manipulate.
+	 * @dst: The receive buffer pointer.
+	 * @size: The receive buffer size
+	 * @return zero on success, or -ve error code.
+	 */
+	int (*prepare_rcv_buf)(struct dma *dma, void *dst, size_t size);
+	/**
+	 * receive() - Receive a DMA transfer.
+	 *
+	 * @dma: The DMA Channel to manipulate.
+	 * @dst: The destination pointer.
+	 * @metadata: DMA driver's specific data
+	 * @return zero on success, or -ve error code.
+	 */
+	int (*receive)(struct dma *dma, void **dst, void *metadata);
+	/**
+	 * send() - Send a DMA transfer.
+	 *
+	 * @dma: The DMA Channel to manipulate.
+	 * @src: The source pointer.
+	 * @len: Length of the data to be sent (number of bytes).
+	 * @metadata: DMA driver's specific data
+	 * @return zero on success, or -ve error code.
+	 */
+	int (*send)(struct dma *dma, void *src, size_t len, void *metadata);
+#endif /* CONFIG_DMA_CHANNELS */
 	/**
 	 * transfer() - Issue a DMA transfer. The implementation must
 	 *   wait until the transfer is done.
diff --git a/include/dma.h b/include/dma.h
index 97fa0cf..d1c3d0d 100644
--- a/include/dma.h
+++ b/include/dma.h
@@ -1,12 +1,17 @@
 /* SPDX-License-Identifier: GPL-2.0+ */
 /*
- * (C) Copyright 2015
- *     Texas Instruments Incorporated, <www.ti.com>
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ * Copyright (C) 2015 - 2018 Texas Instruments Incorporated <www.ti.com>
+ * Written by Mugunthan V N <mugunthanvnm@ti.com>
+ *
  */
 
 #ifndef _DMA_H_
 #define _DMA_H_
 
+#include <linux/errno.h>
+#include <linux/types.h>
+
 /*
  * enum dma_direction - dma transfer direction indicator
  * @DMA_MEM_TO_MEM: Memcpy mode
@@ -36,6 +41,257 @@ struct dma_dev_priv {
 	u32 supported;
 };
 
+#ifdef CONFIG_DMA_CHANNELS
+/**
+ * A DMA is a feature of computer systems that allows certain hardware
+ * subsystems to access main system memory, independent of the CPU.
+ * DMA channels are typically generated externally to the HW module
+ * consuming them, by an entity this API calls a DMA provider. This API
+ * provides a standard means for drivers to enable and disable DMAs, and to
+ * copy, send and receive data using DMA.
+ *
+ * A driver that implements UCLASS_DMA is a DMA provider. A provider will
+ * often implement multiple separate DMAs, since the hardware it manages
+ * often has this capability. dma_uclass.h describes the interface which
+ * DMA providers must implement.
+ *
+ * DMA consumers/clients are the HW modules driven by the DMA channels. This
+ * header file describes the API used by drivers for those HW modules.
+ *
+ * DMA consumer DMA_MEM_TO_DEV (transmit) usage example (based on networking).
+ * Note. dma_send() is sync operation always -  it'll start transfer and will
+ * poll for it to complete:
+ *	- get/request dma channel
+ *	struct dma dma_tx;
+ *	ret = dma_get_by_name(common->dev, "tx0", &dma_tx);
+ *	if (ret) ...
+ *
+ *	- enable dma channel
+ *	ret = dma_enable(&dma_tx);
+ *	if (ret) ...
+ *
+ *	- dma transmit DMA_MEM_TO_DEV.
+ *	struct ti_drv_packet_data packet_data;
+ *
+ *	packet_data.opt1 = val1;
+ *	packet_data.opt2 = val2;
+ *	ret = dma_send(&dma_tx, packet, length, &packet_data);
+ *	if (ret) ..
+ *
+ * DMA consumer DMA_DEV_TO_MEM (receive) usage example (based on networking).
+ * Note. dma_receive() is sync operation always - it'll start transfer
+ * (if required) and will poll for it to complete (or for any previously
+ * configured dev2mem transfer to complete):
+ *	- get/request dma channel
+ *	struct dma dma_rx;
+ *	ret = dma_get_by_name(common->dev, "rx0", &dma_rx);
+ *	if (ret) ...
+ *
+ *	- enable dma channel
+ *	ret = dma_enable(&dma_rx);
+ *	if (ret) ...
+ *
+ *	- dma receive DMA_DEV_TO_MEM.
+ *	struct ti_drv_packet_data packet_data;
+ *
+ *	len = dma_receive(&dma_rx, (void **)packet, &packet_data);
+ *	if (ret < 0) ...
+ *
+ * DMA consumer DMA_DEV_TO_MEM (receive) zero-copy usage example (based on
+ * networking). Networking subsystem allows to configure and use few receive
+ * buffers (dev2mem), as Networking RX DMA channels usually implemented
+ * as streaming interface
+ *	- get/request dma channel
+ *	struct dma dma_rx;
+ *	ret = dma_get_by_name(common->dev, "rx0", &dma_rx);
+ *	if (ret) ...
+ *
+ *	for (i = 0; i < RX_DESC_NUM; i++) {
+ *		ret = dma_prepare_rcv_buf(&dma_rx,
+ *					  net_rx_packets[i],
+ *					  RX_BUF_SIZE);
+ *		if (ret) ...
+ *	}
+ *
+ *	- enable dma channel
+ *	ret = dma_enable(&dma_rx);
+ *	if (ret) ...
+ *
+ *	- dma receive DMA_DEV_TO_MEM.
+ *	struct ti_drv_packet_data packet_data;
+ *
+ *	len = dma_receive(&dma_rx, (void **)packet, &packet_data);
+ *	if (ret < 0) ..
+ *
+ *	-- process packet --
+ *
+ *	- return buffer back to DAM channel
+ *	ret = dma_prepare_rcv_buf(&dma_rx,
+ *				  net_rx_packets[rx_next],
+ *				  RX_BUF_SIZE);
+ */
+
+struct udevice;
+
+/**
+ * struct dma - A handle to (allowing control of) a single DMA.
+ *
+ * Clients provide storage for DMA handles. The content of the structure is
+ * managed solely by the DMA API and DMA drivers. A DMA struct is
+ * initialized by "get"ing the DMA struct. The DMA struct is passed to all
+ * other DMA APIs to identify which DMA channel to operate upon.
+ *
+ * @dev: The device which implements the DMA channel.
+ * @id: The DMA channel ID within the provider.
+ *
+ * Currently, the DMA API assumes that a single integer ID is enough to
+ * identify and configure any DMA channel for any DMA provider. If this
+ * assumption becomes invalid in the future, the struct could be expanded to
+ * either (a) add more fields to allow DMA providers to store additional
+ * information, or (b) replace the id field with an opaque pointer, which the
+ * provider would dynamically allocated during its .of_xlate op, and process
+ * during is .request op. This may require the addition of an extra op to clean
+ * up the allocation.
+ */
+struct dma {
+	struct udevice *dev;
+	/*
+	 * Written by of_xlate. We assume a single id is enough for now. In the
+	 * future, we might add more fields here.
+	 */
+	unsigned long id;
+};
+
+# if CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(DMA)
+/**
+ * dma_get_by_index - Get/request a DMA by integer index.
+ *
+ * This looks up and requests a DMA. The index is relative to the client
+ * device; each device is assumed to have n DMAs associated with it somehow,
+ * and this function finds and requests one of them. The mapping of client
+ * device DMA indices to provider DMAs may be via device-tree properties,
+ * board-provided mapping tables, or some other mechanism.
+ *
+ * @dev:	The client device.
+ * @index:	The index of the DMA to request, within the client's list of
+ *		DMA channels.
+ * @dma:	A pointer to a DMA struct to initialize.
+ * @return 0 if OK, or a negative error code.
+ */
+int dma_get_by_index(struct udevice *dev, int index, struct dma *dma);
+
+/**
+ * dma_get_by_name - Get/request a DMA by name.
+ *
+ * This looks up and requests a DMA. The name is relative to the client
+ * device; each device is assumed to have n DMAs associated with it somehow,
+ * and this function finds and requests one of them. The mapping of client
+ * device DMA names to provider DMAs may be via device-tree properties,
+ * board-provided mapping tables, or some other mechanism.
+ *
+ * @dev:	The client device.
+ * @name:	The name of the DMA to request, within the client's list of
+ *		DMA channels.
+ * @dma:	A pointer to a DMA struct to initialize.
+ * @return 0 if OK, or a negative error code.
+ */
+int dma_get_by_name(struct udevice *dev, const char *name, struct dma *dma);
+# else
+static inline int dma_get_by_index(struct udevice *dev, int index,
+				   struct dma *dma)
+{
+	return -ENOSYS;
+}
+
+static inline int dma_get_by_name(struct udevice *dev, const char *name,
+				  struct dma *dma)
+{
+	return -ENOSYS;
+}
+# endif
+
+/**
+ * dma_request - Request a DMA by provider-specific ID.
+ *
+ * This requests a DMA using a provider-specific ID. Generally, this function
+ * should not be used, since dma_get_by_index/name() provide an interface that
+ * better separates clients from intimate knowledge of DMA providers.
+ * However, this function may be useful in core SoC-specific code.
+ *
+ * @dev: The DMA provider device.
+ * @dma: A pointer to a DMA struct to initialize. The caller must
+ *	 have already initialized any field in this struct which the
+ *	 DMA provider uses to identify the DMA channel.
+ * @return 0 if OK, or a negative error code.
+ */
+int dma_request(struct udevice *dev, struct dma *dma);
+
+/**
+ * dma_free - Free a previously requested DMA.
+ *
+ * @dma: A DMA struct that was previously successfully requested by
+ *	 dma_request/get_by_*().
+ * @return 0 if OK, or a negative error code.
+ */
+int dma_free(struct dma *dma);
+
+/**
+ * dma_enable() - Enable (turn on) a DMA channel.
+ *
+ * @dma: A DMA struct that was previously successfully requested by
+ *	 dma_request/get_by_*().
+ * @return zero on success, or -ve error code.
+ */
+int dma_enable(struct dma *dma);
+
+/**
+ * dma_disable() - Disable (turn off) a DMA channel.
+ *
+ * @dma: A DMA struct that was previously successfully requested by
+ *	 dma_request/get_by_*().
+ * @return zero on success, or -ve error code.
+ */
+int dma_disable(struct dma *dma);
+
+/**
+ * dma_prepare_rcv_buf() - Prepare/add receive DMA buffer.
+ *
+ * It allows to implement zero-copy async DMA_DEV_TO_MEM (receive) transactions
+ * if supported by DMA providers.
+ *
+ * @dma: A DMA struct that was previously successfully requested by
+ *	 dma_request/get_by_*().
+ * @dst: The receive buffer pointer.
+ * @size: The receive buffer size
+ * @return zero on success, or -ve error code.
+ */
+int dma_prepare_rcv_buf(struct dma *dma, void *dst, size_t size);
+
+/**
+ * dma_receive() - Receive a DMA transfer.
+ *
+ * @dma: A DMA struct that was previously successfully requested by
+ *	 dma_request/get_by_*().
+ * @dst: The destination pointer.
+ * @metadata: DMA driver's channel specific data
+ * @return length of received data on success, or zero - no data,
+ * or -ve error code.
+ */
+int dma_receive(struct dma *dma, void **dst, void *metadata);
+
+/**
+ * dma_send() - Send a DMA transfer.
+ *
+ * @dma: A DMA struct that was previously successfully requested by
+ *	 dma_request/get_by_*().
+ * @src: The source pointer.
+ * @len: Length of the data to be sent (number of bytes).
+ * @metadata: DMA driver's channel specific data
+ * @return zero on success, or -ve error code.
+ */
+int dma_send(struct dma *dma, void *src, size_t len, void *metadata);
+#endif /* CONFIG_DMA_CHANNELS */
+
 /*
  * dma_get_device - get a DMA device which supports transfer
  * type of transfer_type
-- 
2.10.5

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

* [U-Boot] [PATCH v7 3/5] test: dma: add dma-uclass test
  2018-11-10 21:06 [U-Boot] [PATCH v7 0/5] dma: add channels support Grygorii Strashko
  2018-11-10 21:06 ` [U-Boot] [PATCH v7 1/5] dma: move dma_ops to dma-uclass.h Grygorii Strashko
  2018-11-10 21:06 ` [U-Boot] [PATCH v7 2/5] dma: add channels support Grygorii Strashko
@ 2018-11-10 21:06 ` Grygorii Strashko
  2018-11-13 19:53   ` Simon Glass
  2018-11-10 21:06 ` [U-Boot] [NOT-FOR-MERGE-PATCH PATCH v7 4/5] dma: ti: add driver to K3 UDMA Grygorii Strashko
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 145+ messages in thread
From: Grygorii Strashko @ 2018-11-10 21:06 UTC (permalink / raw)
  To: u-boot

Add a sandbox DMA driver implementation (provider) and corresponding DM
test.

Reviewed-by: Tom Rini <trini@konsulko.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
 arch/sandbox/dts/test.dts      |   8 ++
 configs/sandbox_defconfig      |   3 +
 drivers/dma/Kconfig            |   7 +
 drivers/dma/Makefile           |   1 +
 drivers/dma/sandbox-dma-test.c | 282 +++++++++++++++++++++++++++++++++++++++++
 test/dm/Makefile               |   1 +
 test/dm/dma.c                  | 123 ++++++++++++++++++
 7 files changed, 425 insertions(+)
 create mode 100644 drivers/dma/sandbox-dma-test.c
 create mode 100644 test/dm/dma.c

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 57e0dd7..b721007 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -712,6 +712,14 @@
 	sandbox_tee {
 		compatible = "sandbox,tee";
 	};
+
+	dma: dma {
+		compatible = "sandbox,dma";
+		#dma-cells = <1>;
+
+		dmas = <&dma 0>, <&dma 1>, <&dma 2>;
+		dma-names = "m2m", "tx0", "rx0";
+	};
 };
 
 #include "sandbox_pmic.dtsi"
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 2ce336f..7cdc01c 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -217,3 +217,6 @@ CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
 CONFIG_UT_ENV=y
 CONFIG_UT_OVERLAY=y
+CONFIG_DMA=y
+CONFIG_DMA_CHANNELS=y
+CONFIG_SANDBOX_DMA=y
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index b9b85c6..8a4162e 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -19,6 +19,13 @@ config DMA_CHANNELS
 	  Enable channels support for DMA. Some DMA controllers have multiple
 	  channels which can either transfer data to/from different devices.
 
+config SANDBOX_DMA
+	bool "Enable the sandbox DMA test driver"
+	depends on DMA && DMA_CHANNELS && SANDBOX
+	help
+	  Enable support for a test DMA uclass implementation. It stimulates
+	  DMA transfer by simple copying data between channels.
+
 config TI_EDMA3
 	bool "TI EDMA3 driver"
 	help
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 4eaef8a..aff31f9 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_DMA) += dma-uclass.o
 obj-$(CONFIG_FSLDMAFEC) += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o
 obj-$(CONFIG_APBH_DMA) += apbh_dma.o
 obj-$(CONFIG_FSL_DMA) += fsl_dma.o
+obj-$(CONFIG_SANDBOX_DMA) += sandbox-dma-test.o
 obj-$(CONFIG_TI_KSNAV) += keystone_nav.o keystone_nav_cfg.o
 obj-$(CONFIG_TI_EDMA3) += ti-edma3.o
 obj-$(CONFIG_DMA_LPC32XX) += lpc32xx_dma.o
diff --git a/drivers/dma/sandbox-dma-test.c b/drivers/dma/sandbox-dma-test.c
new file mode 100644
index 0000000..b958ec4
--- /dev/null
+++ b/drivers/dma/sandbox-dma-test.c
@@ -0,0 +1,282 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Direct Memory Access U-Class Simulation driver
+ *
+ * Copyright (C) 2018 Texas Instruments Incorporated <www.ti.com>
+ *
+ * Author: Grygorii Strashko <grygorii.strashko@ti.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/read.h>
+#include <dma-uclass.h>
+#include <dt-structs.h>
+#include <errno.h>
+
+#define SANDBOX_DMA_CH_CNT 3
+#define SANDBOX_DMA_BUF_SIZE 1024
+
+struct sandbox_dma_chan {
+	struct sandbox_dma_dev *ud;
+	char name[20];
+	u32 id;
+	enum dma_direction dir;
+	bool in_use;
+	bool enabled;
+};
+
+struct sandbox_dma_dev {
+	struct device *dev;
+	u32 ch_count;
+	struct sandbox_dma_chan channels[SANDBOX_DMA_CH_CNT];
+	uchar   buf[SANDBOX_DMA_BUF_SIZE];
+	uchar	*buf_rx;
+	size_t	data_len;
+	u32	meta;
+};
+
+static int sandbox_dma_transfer(struct udevice *dev, int direction,
+				void *dst, void *src, size_t len)
+{
+	memcpy(dst, src, len);
+
+	return 0;
+}
+
+static int sandbox_dma_of_xlate(struct dma *dma,
+				struct ofnode_phandle_args *args)
+{
+	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
+	struct sandbox_dma_chan *uc;
+
+	debug("%s(dma id=%u)\n", __func__, args->args[0]);
+
+	if (args->args[0] >= SANDBOX_DMA_CH_CNT)
+		return -EINVAL;
+
+	dma->id = args->args[0];
+
+	uc = &ud->channels[dma->id];
+
+	if (dma->id == 1)
+		uc->dir = DMA_MEM_TO_DEV;
+	else if (dma->id == 2)
+		uc->dir = DMA_DEV_TO_MEM;
+	else
+		uc->dir = DMA_MEM_TO_MEM;
+	debug("%s(dma id=%lu dir=%d)\n", __func__, dma->id, uc->dir);
+
+	return 0;
+}
+
+static int sandbox_dma_request(struct dma *dma)
+{
+	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
+	struct sandbox_dma_chan *uc;
+
+	if (dma->id >= SANDBOX_DMA_CH_CNT)
+		return -EINVAL;
+
+	uc = &ud->channels[dma->id];
+	if (uc->in_use)
+		return -EBUSY;
+
+	uc->in_use = true;
+	debug("%s(dma id=%lu in_use=%d)\n", __func__, dma->id, uc->in_use);
+
+	return 0;
+}
+
+static int sandbox_dma_free(struct dma *dma)
+{
+	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
+	struct sandbox_dma_chan *uc;
+
+	if (dma->id >= SANDBOX_DMA_CH_CNT)
+		return -EINVAL;
+
+	uc = &ud->channels[dma->id];
+	if (!uc->in_use)
+		return -EINVAL;
+
+	uc->in_use = false;
+	ud->buf_rx = NULL;
+	ud->data_len = 0;
+	debug("%s(dma id=%lu in_use=%d)\n", __func__, dma->id, uc->in_use);
+
+	return 0;
+}
+
+static int sandbox_dma_enable(struct dma *dma)
+{
+	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
+	struct sandbox_dma_chan *uc;
+
+	if (dma->id >= SANDBOX_DMA_CH_CNT)
+		return -EINVAL;
+
+	uc = &ud->channels[dma->id];
+	if (!uc->in_use)
+		return -EINVAL;
+	if (uc->enabled)
+		return -EINVAL;
+
+	uc->enabled = true;
+	debug("%s(dma id=%lu enabled=%d)\n", __func__, dma->id, uc->enabled);
+
+	return 0;
+}
+
+static int sandbox_dma_disable(struct dma *dma)
+{
+	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
+	struct sandbox_dma_chan *uc;
+
+	if (dma->id >= SANDBOX_DMA_CH_CNT)
+		return -EINVAL;
+
+	uc = &ud->channels[dma->id];
+	if (!uc->in_use)
+		return -EINVAL;
+	if (!uc->enabled)
+		return -EINVAL;
+
+	uc->enabled = false;
+	debug("%s(dma id=%lu enabled=%d)\n", __func__, dma->id, uc->enabled);
+
+	return 0;
+}
+
+static int sandbox_dma_send(struct dma *dma,
+			    void *src, size_t len, void *metadata)
+{
+	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
+	struct sandbox_dma_chan *uc;
+
+	if (dma->id >= SANDBOX_DMA_CH_CNT)
+		return -EINVAL;
+	if (!src || !metadata)
+		return -EINVAL;
+
+	debug("%s(dma id=%lu)\n", __func__, dma->id);
+
+	uc = &ud->channels[dma->id];
+	if (uc->dir != DMA_MEM_TO_DEV)
+		return -EINVAL;
+	if (!uc->in_use)
+		return -EINVAL;
+	if (!uc->enabled)
+		return -EINVAL;
+	if (len >= SANDBOX_DMA_BUF_SIZE)
+		return -EINVAL;
+
+	memcpy(ud->buf, src, len);
+	ud->data_len = len;
+	ud->meta = *((u32 *)metadata);
+
+	debug("%s(dma id=%lu len=%zu meta=%08x)\n",
+	      __func__, dma->id, len, ud->meta);
+
+	return 0;
+}
+
+static int sandbox_dma_receive(struct dma *dma, void **dst, void *metadata)
+{
+	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
+	struct sandbox_dma_chan *uc;
+
+	if (dma->id >= SANDBOX_DMA_CH_CNT)
+		return -EINVAL;
+	if (!dst || !metadata)
+		return -EINVAL;
+
+	uc = &ud->channels[dma->id];
+	if (uc->dir != DMA_DEV_TO_MEM)
+		return -EINVAL;
+	if (!uc->in_use)
+		return -EINVAL;
+	if (!uc->enabled)
+		return -EINVAL;
+	if (!ud->data_len)
+		return 0;
+
+	if (ud->buf_rx) {
+		memcpy(ud->buf_rx, ud->buf, ud->data_len);
+		*dst = ud->buf_rx;
+	} else {
+		memcpy(*dst, ud->buf, ud->data_len);
+	}
+
+	*((u32 *)metadata) = ud->meta;
+
+	debug("%s(dma id=%lu len=%zu meta=%08x %p)\n",
+	      __func__, dma->id, ud->data_len, ud->meta, *dst);
+
+	return ud->data_len;
+}
+
+static int sandbox_dma_add_rcv_buf(struct dma *dma, void *dst, size_t size)
+{
+	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
+
+	ud->buf_rx = dst;
+
+	return 0;
+}
+
+static const struct dma_ops sandbox_dma_ops = {
+	.transfer	= sandbox_dma_transfer,
+	.of_xlate	= sandbox_dma_of_xlate,
+	.request	= sandbox_dma_request,
+	.free		= sandbox_dma_free,
+	.enable		= sandbox_dma_enable,
+	.disable	= sandbox_dma_disable,
+	.send		= sandbox_dma_send,
+	.receive	= sandbox_dma_receive,
+	.add_rcv_buf	= sandbox_dma_add_rcv_buf,
+};
+
+static int sandbox_dma_probe(struct udevice *dev)
+{
+	struct dma_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct sandbox_dma_dev *ud = dev_get_priv(dev);
+	int i, ret = 0;
+
+	uc_priv->supported = DMA_SUPPORTS_MEM_TO_MEM |
+			     DMA_SUPPORTS_MEM_TO_DEV |
+			     DMA_SUPPORTS_DEV_TO_MEM;
+
+	ud->ch_count = SANDBOX_DMA_CH_CNT;
+	ud->buf_rx = NULL;
+	ud->meta = 0;
+	ud->data_len = 0;
+
+	pr_err("Number of channels: %u\n", ud->ch_count);
+
+	for (i = 0; i < ud->ch_count; i++) {
+		struct sandbox_dma_chan *uc = &ud->channels[i];
+
+		uc->ud = ud;
+		uc->id = i;
+		sprintf(uc->name, "DMA chan%d\n", i);
+		uc->in_use = false;
+		uc->enabled = false;
+	}
+
+	return ret;
+}
+
+static const struct udevice_id sandbox_dma_ids[] = {
+	{ .compatible = "sandbox,dma" },
+	{ }
+};
+
+U_BOOT_DRIVER(sandbox_dma) = {
+	.name	= "sandbox-dma",
+	.id	= UCLASS_DMA,
+	.of_match = sandbox_dma_ids,
+	.ops	= &sandbox_dma_ops,
+	.probe = sandbox_dma_probe,
+	.priv_auto_alloc_size = sizeof(struct sandbox_dma_dev),
+};
diff --git a/test/dm/Makefile b/test/dm/Makefile
index b490cf2..afc6664 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -53,4 +53,5 @@ obj-$(CONFIG_MISC) += misc.o
 obj-$(CONFIG_DM_SERIAL) += serial.o
 obj-$(CONFIG_CPU) += cpu.o
 obj-$(CONFIG_TEE) += tee.o
+obj-$(CONFIG_DMA) += dma.o
 endif
diff --git a/test/dm/dma.c b/test/dm/dma.c
new file mode 100644
index 0000000..6f19d61
--- /dev/null
+++ b/test/dm/dma.c
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Direct Memory Access U-Class tests
+ *
+ * Copyright (C) 2018 Texas Instruments Incorporated <www.ti.com>
+ * Grygorii Strashko <grygorii.strashko@ti.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/test.h>
+#include <dma.h>
+#include <test/ut.h>
+
+static int dm_test_dma_m2m(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	struct dma dma_m2m;
+	u8 src_buf[512];
+	u8 dst_buf[512];
+	size_t len = 512;
+	int i;
+
+	ut_assertok(uclass_get_device_by_name(UCLASS_DMA, "dma", &dev));
+	ut_assertok(dma_get_by_name(dev, "m2m", &dma_m2m));
+
+	memset(dst_buf, 0, len);
+	for (i = 0; i < len; i++)
+		src_buf[i] = i;
+
+	ut_assertok(dma_memcpy(dst_buf, src_buf, len));
+
+	ut_assertok(memcmp(src_buf, dst_buf, len));
+	return 0;
+}
+DM_TEST(dm_test_dma_m2m, DM_TESTF_SCAN_FDT);
+
+static int dm_test_dma(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	struct dma dma_tx, dma_rx;
+	u8 src_buf[512];
+	u8 dst_buf[512];
+	void *dst_ptr;
+	size_t len = 512;
+	u32 meta1, meta2;
+	int i;
+
+	ut_assertok(uclass_get_device_by_name(UCLASS_DMA, "dma", &dev));
+
+	ut_assertok(dma_get_by_name(dev, "tx0", &dma_tx));
+	ut_assertok(dma_get_by_name(dev, "rx0", &dma_rx));
+
+	ut_assertok(dma_enable(&dma_tx));
+	ut_assertok(dma_enable(&dma_rx));
+
+	memset(dst_buf, 0, len);
+	for (i = 0; i < len; i++)
+		src_buf[i] = i;
+	meta1 = 0xADADDEAD;
+	meta2 = 0;
+	dst_ptr = &dst_buf;
+
+	ut_assertok(dma_send(&dma_tx, src_buf, len, &meta1));
+
+	ut_asserteq(len, dma_receive(&dma_rx, &dst_ptr, &meta2));
+	ut_asserteq(0xADADDEAD, meta2);
+
+	ut_assertok(dma_disable(&dma_tx));
+	ut_assertok(dma_disable(&dma_rx));
+
+	ut_assertok(dma_free(&dma_tx));
+	ut_assertok(dma_free(&dma_rx));
+	ut_assertok(memcmp(src_buf, dst_buf, len));
+
+	return 0;
+}
+DM_TEST(dm_test_dma, DM_TESTF_SCAN_FDT);
+
+static int dm_test_dma_rx(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	struct dma dma_tx, dma_rx;
+	u8 src_buf[512];
+	u8 dst_buf[512];
+	void *dst_ptr;
+	size_t len = 512;
+	u32 meta1, meta2;
+	int i;
+
+	ut_assertok(uclass_get_device_by_name(UCLASS_DMA, "dma", &dev));
+
+	ut_assertok(dma_get_by_name(dev, "tx0", &dma_tx));
+	ut_assertok(dma_get_by_name(dev, "rx0", &dma_rx));
+
+	ut_assertok(dma_enable(&dma_tx));
+	ut_assertok(dma_enable(&dma_rx));
+
+	memset(dst_buf, 0, len);
+	for (i = 0; i < len; i++)
+		src_buf[i] = i;
+	meta1 = 0xADADDEAD;
+	meta2 = 0;
+	dst_ptr = NULL;
+
+	ut_assertok(dma_add_rcv_buf(&dma_tx, dst_buf, len));
+
+	ut_assertok(dma_send(&dma_tx, src_buf, len, &meta1));
+
+	ut_asserteq(len, dma_receive(&dma_rx, &dst_ptr, &meta2));
+	ut_asserteq(0xADADDEAD, meta2);
+	ut_asserteq_ptr(dst_buf, dst_ptr);
+
+	ut_assertok(dma_disable(&dma_tx));
+	ut_assertok(dma_disable(&dma_rx));
+
+	ut_assertok(dma_free(&dma_tx));
+	ut_assertok(dma_free(&dma_rx));
+	ut_assertok(memcmp(src_buf, dst_buf, len));
+
+	return 0;
+}
+DM_TEST(dm_test_dma_rx, DM_TESTF_SCAN_FDT);
-- 
2.10.5

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

* [U-Boot] [NOT-FOR-MERGE-PATCH PATCH v7 4/5] dma: ti: add driver to K3 UDMA
  2018-11-10 21:06 [U-Boot] [PATCH v7 0/5] dma: add channels support Grygorii Strashko
                   ` (2 preceding siblings ...)
  2018-11-10 21:06 ` [U-Boot] [PATCH v7 3/5] test: dma: add dma-uclass test Grygorii Strashko
@ 2018-11-10 21:06 ` Grygorii Strashko
  2018-11-10 21:06 ` [U-Boot] [NOT-FOR-MERGE-PATCH PATCH v7 5/5] net: ethernet: ti: introduce am654 gigabit eth switch subsystem driver Grygorii Strashko
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
  5 siblings, 0 replies; 145+ messages in thread
From: Grygorii Strashko @ 2018-11-10 21:06 UTC (permalink / raw)
  To: u-boot

From: Vignesh R <vigneshr@ti.com>

Add support for K3 AM65x UDMA with only support pktmode MEM_TO_MEM
transfers and DEV_TO_MEM/MEM_TO_DEV through DMA channels.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
 drivers/dma/Kconfig               |    2 +
 drivers/dma/Makefile              |    2 +
 drivers/dma/ti/Kconfig            |   14 +
 drivers/dma/ti/Makefile           |    3 +
 drivers/dma/ti/k3-udma-hwdef.h    |  184 ++++
 drivers/dma/ti/k3-udma.c          | 1679 +++++++++++++++++++++++++++++++++++++
 include/dt-bindings/dma/k3-udma.h |   26 +
 include/linux/soc/ti/ti-udma.h    |   24 +
 8 files changed, 1934 insertions(+)
 create mode 100644 drivers/dma/ti/Kconfig
 create mode 100644 drivers/dma/ti/Makefile
 create mode 100644 drivers/dma/ti/k3-udma-hwdef.h
 create mode 100644 drivers/dma/ti/k3-udma.c
 create mode 100644 include/dt-bindings/dma/k3-udma.h
 create mode 100644 include/linux/soc/ti/ti-udma.h

diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 8a4162e..306261c 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -48,4 +48,6 @@ config APBH_DMA_BURST8
 
 endif
 
+source "drivers/dma/ti/Kconfig"
+
 endmenu # menu "DMA Support"
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index aff31f9..ef2865a 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -12,3 +12,5 @@ obj-$(CONFIG_SANDBOX_DMA) += sandbox-dma-test.o
 obj-$(CONFIG_TI_KSNAV) += keystone_nav.o keystone_nav_cfg.o
 obj-$(CONFIG_TI_EDMA3) += ti-edma3.o
 obj-$(CONFIG_DMA_LPC32XX) += lpc32xx_dma.o
+
+obj-y += ti/
diff --git a/drivers/dma/ti/Kconfig b/drivers/dma/ti/Kconfig
new file mode 100644
index 0000000..3d54983
--- /dev/null
+++ b/drivers/dma/ti/Kconfig
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+if ARCH_K3
+
+config TI_K3_NAVSS_UDMA
+        bool "Texas Instruments UDMA"
+        depends on ARCH_K3
+        select DMA
+        select TI_K3_NAVSS_RINGACC
+        select TI_K3_NAVSS_PSILCFG
+        default n
+        help
+          Support for UDMA used in K3 devices.
+endif
diff --git a/drivers/dma/ti/Makefile b/drivers/dma/ti/Makefile
new file mode 100644
index 0000000..de2f9ac
--- /dev/null
+++ b/drivers/dma/ti/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-$(CONFIG_TI_K3_NAVSS_UDMA) += k3-udma.o
diff --git a/drivers/dma/ti/k3-udma-hwdef.h b/drivers/dma/ti/k3-udma-hwdef.h
new file mode 100644
index 0000000..c88399a
--- /dev/null
+++ b/drivers/dma/ti/k3-udma-hwdef.h
@@ -0,0 +1,184 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ *  Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com
+ *
+ *
+ * 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.
+ *
+ */
+
+#ifndef K3_NAVSS_UDMA_HWDEF_H_
+#define K3_NAVSS_UDMA_HWDEF_H_
+
+#define UDMA_PSIL_DST_THREAD_ID_OFFSET 0x8000
+
+/* Global registers */
+#define UDMA_REV_REG			0x0
+#define UDMA_PERF_CTL_REG		0x4
+#define UDMA_EMU_CTL_REG		0x8
+#define UDMA_PSIL_TO_REG		0x10
+#define UDMA_UTC_CTL_REG		0x1c
+#define UDMA_CAP_REG(i)			(0x20 + (i * 4))
+#define UDMA_RX_FLOW_ID_FW_OES_REG	0x80
+#define UDMA_RX_FLOW_ID_FW_STATUS_REG	0x88
+
+/* RX Flow regs */
+#define UDMA_RFLOW_RFA_REG		0x0
+#define UDMA_RFLOW_RFB_REG		0x4
+#define UDMA_RFLOW_RFC_REG		0x8
+#define UDMA_RFLOW_RFD_REG		0xc
+#define UDMA_RFLOW_RFE_REG		0x10
+#define UDMA_RFLOW_RFF_REG		0x14
+#define UDMA_RFLOW_RFG_REG		0x18
+#define UDMA_RFLOW_RFH_REG		0x1c
+
+#define UDMA_RFLOW_REG(x) (UDMA_RFLOW_RF##x##_REG)
+
+/* TX chan regs */
+#define UDMA_TCHAN_TCFG_REG		0x0
+#define UDMA_TCHAN_TCREDIT_REG		0x4
+#define UDMA_TCHAN_TCQ_REG		0x14
+#define UDMA_TCHAN_TOES_REG(i)		(0x20 + (i) * 4)
+#define UDMA_TCHAN_TEOES_REG		0x60
+#define UDMA_TCHAN_TPRI_CTRL_REG	0x64
+#define UDMA_TCHAN_THREAD_ID_REG	0x68
+#define UDMA_TCHAN_TFIFO_DEPTH_REG	0x70
+#define UDMA_TCHAN_TST_SCHED_REG	0x80
+
+/* RX chan regs */
+#define UDMA_RCHAN_RCFG_REG		0x0
+#define UDMA_RCHAN_RCQ_REG		0x14
+#define UDMA_RCHAN_ROES_REG(i)		(0x20 + (i) * 4)
+#define UDMA_RCHAN_REOES_REG		0x60
+#define UDMA_RCHAN_RPRI_CTRL_REG	0x64
+#define UDMA_RCHAN_THREAD_ID_REG	0x68
+#define UDMA_RCHAN_RST_SCHED_REG	0x80
+#define UDMA_RCHAN_RFLOW_RNG_REG	0xf0
+
+/* TX chan RT regs */
+#define UDMA_TCHAN_RT_CTL_REG		0x0
+#define UDMA_TCHAN_RT_SWTRIG_REG	0x8
+#define UDMA_TCHAN_RT_STDATA_REG	0x80
+
+#define UDMA_TCHAN_RT_PEERn_REG(i)	(0x200 + (i * 0x4))
+#define UDMA_TCHAN_RT_PEER_STATIC_TR_XY_REG	\
+	UDMA_TCHAN_RT_PEERn_REG(0)	/* PSI-L: 0x400 */
+#define UDMA_TCHAN_RT_PEER_STATIC_TR_Z_REG	\
+	UDMA_TCHAN_RT_PEERn_REG(1)	/* PSI-L: 0x401 */
+#define UDMA_TCHAN_RT_PEER_BCNT_REG		\
+	UDMA_TCHAN_RT_PEERn_REG(4)	/* PSI-L: 0x404 */
+#define UDMA_TCHAN_RT_PEER_RT_EN_REG		\
+	UDMA_TCHAN_RT_PEERn_REG(8)	/* PSI-L: 0x408 */
+
+#define UDMA_TCHAN_RT_PCNT_REG		0x400
+#define UDMA_TCHAN_RT_BCNT_REG		0x408
+#define UDMA_TCHAN_RT_SBCNT_REG		0x410
+
+/* RX chan RT regs */
+#define UDMA_RCHAN_RT_CTL_REG		0x0
+#define UDMA_RCHAN_RT_SWTRIG_REG	0x8
+#define UDMA_RCHAN_RT_STDATA_REG	0x80
+
+#define UDMA_RCHAN_RT_PEERn_REG(i)	(0x200 + (i * 0x4))
+#define UDMA_RCHAN_RT_PEER_STATIC_TR_XY_REG	\
+	UDMA_RCHAN_RT_PEERn_REG(0)	/* PSI-L: 0x400 */
+#define UDMA_RCHAN_RT_PEER_STATIC_TR_Z_REG	\
+	UDMA_RCHAN_RT_PEERn_REG(1)	/* PSI-L: 0x401 */
+#define UDMA_RCHAN_RT_PEER_BCNT_REG		\
+	UDMA_RCHAN_RT_PEERn_REG(4)	/* PSI-L: 0x404 */
+#define UDMA_RCHAN_RT_PEER_RT_EN_REG		\
+	UDMA_RCHAN_RT_PEERn_REG(8)	/* PSI-L: 0x408 */
+
+#define UDMA_RCHAN_RT_PCNT_REG		0x400
+#define UDMA_RCHAN_RT_BCNT_REG		0x408
+#define UDMA_RCHAN_RT_SBCNT_REG		0x410
+
+/* UDMA_TCHAN_TCFG_REG/UDMA_RCHAN_RCFG_REG */
+#define UDMA_CHAN_CFG_PAUSE_ON_ERR		BIT(31)
+#define UDMA_TCHAN_CFG_FILT_EINFO		BIT(30)
+#define UDMA_TCHAN_CFG_FILT_PSWORDS		BIT(29)
+#define UDMA_CHAN_CFG_ATYPE_MASK		GENMASK(25, 24)
+#define UDMA_CHAN_CFG_ATYPE_SHIFT		24
+#define UDMA_CHAN_CFG_CHAN_TYPE_MASK		GENMASK(19, 16)
+#define UDMA_CHAN_CFG_CHAN_TYPE_SHIFT		16
+/*
+ * PBVR - using pass by value rings
+ * PBRR - using pass by reference rings
+ * 3RDP - Third Party DMA
+ * BC - Block Copy
+ * SB - single buffer packet mode enabled
+ */
+#define UDMA_CHAN_CFG_CHAN_TYPE_PACKET_PBRR \
+	(2 << UDMA_CHAN_CFG_CHAN_TYPE_SHIFT)
+#define UDMA_CHAN_CFG_CHAN_TYPE_PACKET_SB_PBRR \
+	(3 << UDMA_CHAN_CFG_CHAN_TYPE_SHIFT)
+#define UDMA_CHAN_CFG_CHAN_TYPE_3RDP_PBRR \
+	(10 << UDMA_CHAN_CFG_CHAN_TYPE_SHIFT)
+#define UDMA_CHAN_CFG_CHAN_TYPE_3RDP_PBVR \
+	(11 << UDMA_CHAN_CFG_CHAN_TYPE_SHIFT)
+#define UDMA_CHAN_CFG_CHAN_TYPE_3RDP_BC_PBRR \
+	(12 << UDMA_CHAN_CFG_CHAN_TYPE_SHIFT)
+#define UDMA_RCHAN_CFG_IGNORE_SHORT		BIT(15)
+#define UDMA_RCHAN_CFG_IGNORE_LONG		BIT(14)
+#define UDMA_TCHAN_CFG_SUPR_TDPKT		BIT(8)
+#define UDMA_CHAN_CFG_FETCH_SIZE_MASK		GENMASK(6, 0)
+#define UDMA_CHAN_CFG_FETCH_SIZE_SHIFT		0
+
+/* UDMA_TCHAN_RT_CTL_REG/UDMA_RCHAN_RT_CTL_REG */
+#define UDMA_CHAN_RT_CTL_EN	BIT(31)
+#define UDMA_CHAN_RT_CTL_TDOWN	BIT(30)
+#define UDMA_CHAN_RT_CTL_PAUSE	BIT(29)
+#define UDMA_CHAN_RT_CTL_FTDOWN	BIT(28)
+#define UDMA_CHAN_RT_CTL_ERROR	BIT(0)
+
+/* UDMA_TCHAN_RT_PEER_RT_EN_REG/UDMA_RCHAN_RT_PEER_RT_EN_REG (PSI-L: 0x408) */
+#define UDMA_PEER_RT_EN_ENABLE		BIT(31)
+#define UDMA_PEER_RT_EN_TEARDOWN	BIT(30)
+#define UDMA_PEER_RT_EN_PAUSE		BIT(29)
+#define UDMA_PEER_RT_EN_FLUSH		BIT(28)
+#define UDMA_PEER_RT_EN_IDLE		BIT(1)
+
+/* RX Flow reg RFA */
+#define UDMA_RFLOW_RFA_EINFO			BIT(30)
+#define UDMA_RFLOW_RFA_PSINFO			BIT(29)
+#define UDMA_RFLOW_RFA_ERR_HANDLING		BIT(28)
+#define UDMA_RFLOW_RFA_DESC_TYPE_MASK		GENMASK(27, 26)
+#define UDMA_RFLOW_RFA_DESC_TYPE_SHIFT		26
+#define UDMA_RFLOW_RFA_PS_LOC			BIT(25)
+#define UDMA_RFLOW_RFA_SOP_OFF_MASK		GENMASK(24, 16)
+#define UDMA_RFLOW_RFA_SOP_OFF_SHIFT		16
+#define UDMA_RFLOW_RFA_DEST_QNUM_MASK		GENMASK(15, 0)
+#define UDMA_RFLOW_RFA_DEST_QNUM_SHIFT		0
+
+/* RX Flow reg RFC */
+#define UDMA_RFLOW_RFC_SRC_TAG_HI_SEL_SHIFT	28
+#define UDMA_RFLOW_RFC_SRC_TAG_LO_SEL_SHIFT	24
+#define UDMA_RFLOW_RFC_DST_TAG_HI_SEL_SHIFT	20
+#define UDMA_RFLOW_RFC_DST_TAG_LO_SE_SHIFT	16
+
+/*
+ * UDMA_TCHAN_RT_PEER_STATIC_TR_XY_REG /
+ * UDMA_RCHAN_RT_PEER_STATIC_TR_XY_REG
+ */
+#define PDMA_STATIC_TR_X_MASK		GENMASK(26, 24)
+#define PDMA_STATIC_TR_X_SHIFT		(24)
+#define PDMA_STATIC_TR_Y_MASK		GENMASK(11, 0)
+#define PDMA_STATIC_TR_Y_SHIFT		(0)
+
+#define PDMA_STATIC_TR_Y(x)	\
+	(((x) << PDMA_STATIC_TR_Y_SHIFT) & PDMA_STATIC_TR_Y_MASK)
+#define PDMA_STATIC_TR_X(x)	\
+	(((x) << PDMA_STATIC_TR_X_SHIFT) & PDMA_STATIC_TR_X_MASK)
+
+/*
+ * UDMA_TCHAN_RT_PEER_STATIC_TR_Z_REG /
+ * UDMA_RCHAN_RT_PEER_STATIC_TR_Z_REG
+ */
+#define PDMA_STATIC_TR_Z_MASK		GENMASK(11, 0)
+#define PDMA_STATIC_TR_Z_SHIFT		(0)
+#define PDMA_STATIC_TR_Z(x)	\
+	(((x) << PDMA_STATIC_TR_Z_SHIFT) & PDMA_STATIC_TR_Z_MASK)
+
+#endif /* K3_NAVSS_UDMA_HWDEF_H_ */
diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c
new file mode 100644
index 0000000..a5c15b1
--- /dev/null
+++ b/drivers/dma/ti/k3-udma.c
@@ -0,0 +1,1679 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *  Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com
+ *  Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
+ */
+#define pr_fmt(fmt) "udma: " fmt
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/bitops.h>
+#include <malloc.h>
+#include <asm/dma-mapping.h>
+#include <dm.h>
+#include <dm/read.h>
+#include <dm/of_access.h>
+#include <dma.h>
+#include <dma-uclass.h>
+#include <linux/delay.h>
+#include <dt-bindings/dma/k3-udma.h>
+#include <linux/soc/ti/k3-navss-ringacc.h>
+#include <linux/soc/ti/cppi5.h>
+#include <linux/soc/ti/ti-udma.h>
+#include <linux/soc/ti/ti_sci_protocol.h>
+
+#include "k3-udma-hwdef.h"
+
+#define RINGACC_RING_USE_PROXY (0)
+
+struct udma_chan;
+
+enum udma_mmr {
+	MMR_GCFG = 0,
+	MMR_RCHANRT,
+	MMR_TCHANRT,
+	MMR_LAST,
+};
+
+static const char * const mmr_names[] = {
+	"gcfg", "rchanrt", "tchanrt"
+};
+
+struct udma_tchan {
+	void __iomem *reg_rt;
+
+	int id;
+	struct k3_nav_ring *t_ring; /* Transmit ring */
+	struct k3_nav_ring *tc_ring; /* Transmit Completion ring */
+};
+
+struct udma_rchan {
+	void __iomem *reg_rt;
+
+	int id;
+	struct k3_nav_ring *fd_ring; /* Free Descriptor ring */
+	struct k3_nav_ring *r_ring; /* Receive ring*/
+};
+
+struct udma_rflow {
+	int id;
+};
+
+struct udma_dev {
+	struct device *dev;
+	void __iomem *mmrs[MMR_LAST];
+
+	struct k3_nav_ringacc *ringacc;
+
+	u32 features;
+
+	int tchan_cnt;
+	int echan_cnt;
+	int rchan_cnt;
+	int rflow_cnt;
+	unsigned long *tchan_map;
+	unsigned long *rchan_map;
+	unsigned long *rflow_map;
+
+	struct udma_tchan *tchans;
+	struct udma_rchan *rchans;
+	struct udma_rflow *rflows;
+
+	struct udma_chan *channels;
+	u32 psil_base;
+
+	u32 ch_count;
+	const struct ti_sci_handle *tisci;
+	const struct ti_sci_rm_udmap_ops *tisci_udmap_ops;
+	const struct ti_sci_rm_psil_ops *tisci_psil_ops;
+	u32  tisci_dev_id;
+	u32  tisci_navss_dev_id;
+};
+
+struct udma_chan {
+	struct udma_dev *ud;
+	char name[20];
+
+	struct udma_tchan *tchan;
+	struct udma_rchan *rchan;
+	struct udma_rflow *rflow;
+
+	u32 bcnt; /* number of bytes completed since the start of the channel */
+
+	bool pkt_mode; /* TR or packet */
+	bool needs_epib; /* EPIB is needed for the communication or not */
+	u32 psd_size; /* size of Protocol Specific Data */
+	u32 metadata_size; /* (needs_epib ? 16:0) + psd_size */
+	int slave_thread_id;
+	u32 src_thread;
+	u32 dst_thread;
+	u32 static_tr_type;
+
+	u32 id;
+	enum dma_direction dir;
+
+	struct knav_udmap_host_desc_t *desc_tx;
+	u32 hdesc_size;
+	bool in_use;
+	void	*desc_rx;
+	u32	num_rx_bufs;
+	u32	desc_rx_cur;
+
+};
+
+#define UDMA_CH_1000(ch)		(ch * 0x1000)
+#define UDMA_CH_100(ch)			(ch * 0x100)
+#define UDMA_CH_40(ch)			(ch * 0x40)
+
+#ifdef PKTBUFSRX
+#define UDMA_RX_DESC_NUM PKTBUFSRX
+#else
+#define UDMA_RX_DESC_NUM 4
+#endif
+
+#ifdef K3_UDMA_DEBUG
+#define	k3_udma_dbg(arg...) pr_err(arg)
+#define	k3_udma_dev_dbg(dev, arg...) dev_err(dev, arg)
+static void k3_udma_print_buf(ulong addr, const void *data, uint width,
+			      uint count, uint linelen)
+{
+	print_buffer(addr, data, width, count, linelen);
+}
+#else
+#define	k3_udma_dbg(arg...)
+#define	k3_udma_dev_dbg(arg...)
+static void k3_udma_print_buf(ulong addr, const void *data, uint width,
+			      uint count, uint linelen)
+{}
+#endif
+
+/* Generic register access functions */
+static inline u32 udma_read(void __iomem *base, int reg)
+{
+	u32 v;
+
+	v = __raw_readl(base + reg);
+	k3_udma_dbg("READL(32): v(%08X)<--reg(%p)\n", v, base + reg);
+	return v;
+}
+
+static inline void udma_write(void __iomem *base, int reg, u32 val)
+{
+	k3_udma_dbg("WRITEL(32): v(%08X)-->reg(%p)\n", val, base + reg);
+	__raw_writel(val, base + reg);
+}
+
+static inline void udma_update_bits(void __iomem *base, int reg,
+				    u32 mask, u32 val)
+{
+	u32 tmp, orig;
+
+	orig = udma_read(base, reg);
+	tmp = orig & ~mask;
+	tmp |= (val & mask);
+
+	if (tmp != orig)
+		udma_write(base, reg, tmp);
+}
+
+/* TCHANRT */
+static inline u32 udma_tchanrt_read(struct udma_tchan *tchan, int reg)
+{
+	if (!tchan)
+		return 0;
+	return udma_read(tchan->reg_rt, reg);
+}
+
+static inline void udma_tchanrt_write(struct udma_tchan *tchan,
+				      int reg, u32 val)
+{
+	if (!tchan)
+		return;
+	udma_write(tchan->reg_rt, reg, val);
+}
+
+/* RCHANRT */
+static inline u32 udma_rchanrt_read(struct udma_rchan *rchan, int reg)
+{
+	if (!rchan)
+		return 0;
+	return udma_read(rchan->reg_rt, reg);
+}
+
+static inline void udma_rchanrt_write(struct udma_rchan *rchan,
+				      int reg, u32 val)
+{
+	if (!rchan)
+		return;
+	udma_write(rchan->reg_rt, reg, val);
+}
+
+static inline int udma_navss_psil_pair(struct udma_dev *ud, u32 src_thread,
+				       u32 dst_thread)
+{
+	dst_thread |= UDMA_PSIL_DST_THREAD_ID_OFFSET;
+	return ud->tisci_psil_ops->pair(ud->tisci,
+					ud->tisci_navss_dev_id,
+					src_thread, dst_thread);
+}
+
+static inline int udma_navss_psil_unpair(struct udma_dev *ud, u32 src_thread,
+					 u32 dst_thread)
+{
+	dst_thread |= UDMA_PSIL_DST_THREAD_ID_OFFSET;
+	return ud->tisci_psil_ops->unpair(ud->tisci,
+					  ud->tisci_navss_dev_id,
+					  src_thread, dst_thread);
+}
+
+static inline char *udma_get_dir_text(enum dma_direction dir)
+{
+	switch (dir) {
+	case DMA_DEV_TO_MEM:
+		return "DEV_TO_MEM";
+	case DMA_MEM_TO_DEV:
+		return "MEM_TO_DEV";
+	case DMA_MEM_TO_MEM:
+		return "MEM_TO_MEM";
+	case DMA_DEV_TO_DEV:
+		return "DEV_TO_DEV";
+	default:
+		break;
+	}
+
+	return "invalid";
+}
+
+static inline bool udma_is_chan_running(struct udma_chan *uc)
+{
+	u32 trt_ctl = 0;
+	u32 rrt_ctl = 0;
+
+	switch (uc->dir) {
+	case DMA_DEV_TO_MEM:
+		rrt_ctl = udma_rchanrt_read(uc->rchan, UDMA_RCHAN_RT_CTL_REG);
+		k3_udma_dbg("%s: rrt_ctl: 0x%08x (peer: 0x%08x)\n",
+			    __func__, rrt_ctl,
+			    udma_rchanrt_read(uc->rchan,
+					      UDMA_RCHAN_RT_PEER_RT_EN_REG));
+		break;
+	case DMA_MEM_TO_DEV:
+		trt_ctl = udma_tchanrt_read(uc->tchan, UDMA_TCHAN_RT_CTL_REG);
+		k3_udma_dbg("%s: trt_ctl: 0x%08x (peer: 0x%08x)\n",
+			    __func__, trt_ctl,
+			    udma_tchanrt_read(uc->tchan,
+					      UDMA_TCHAN_RT_PEER_RT_EN_REG));
+		break;
+	case DMA_MEM_TO_MEM:
+		trt_ctl = udma_tchanrt_read(uc->tchan, UDMA_TCHAN_RT_CTL_REG);
+		rrt_ctl = udma_rchanrt_read(uc->rchan, UDMA_RCHAN_RT_CTL_REG);
+		break;
+	default:
+		break;
+	}
+
+	if (trt_ctl & UDMA_CHAN_RT_CTL_EN || rrt_ctl & UDMA_CHAN_RT_CTL_EN)
+		return true;
+
+	return false;
+}
+
+static int udma_pop_from_ring(struct udma_chan *uc, dma_addr_t *addr)
+{
+	struct k3_nav_ring *ring = NULL;
+	int ret = -ENOENT;
+
+	switch (uc->dir) {
+	case DMA_DEV_TO_MEM:
+		ring = uc->rchan->r_ring;
+		break;
+	case DMA_MEM_TO_DEV:
+		ring = uc->tchan->tc_ring;
+		break;
+	case DMA_MEM_TO_MEM:
+		ring = uc->rchan->r_ring;
+		break;
+	default:
+		break;
+	}
+
+	if (ring && k3_nav_ringacc_ring_get_occ(ring))
+		ret = k3_nav_ringacc_ring_pop(ring, addr);
+
+	return ret;
+}
+
+static void udma_reset_rings(struct udma_chan *uc)
+{
+	struct k3_nav_ring *ring1 = NULL;
+	struct k3_nav_ring *ring2 = NULL;
+
+	switch (uc->dir) {
+	case DMA_DEV_TO_MEM:
+		ring1 = uc->rchan->fd_ring;
+		ring2 = uc->rchan->r_ring;
+		break;
+	case DMA_MEM_TO_DEV:
+		ring1 = uc->tchan->t_ring;
+		ring2 = uc->tchan->tc_ring;
+		break;
+	case DMA_MEM_TO_MEM:
+		ring1 = uc->tchan->t_ring;
+		ring2 = uc->tchan->tc_ring;
+		break;
+	default:
+		break;
+	}
+
+	if (ring1)
+		k3_nav_ringacc_ring_reset_dma(ring1, 0);
+	if (ring2)
+		k3_nav_ringacc_ring_reset(ring2);
+}
+
+static void udma_reset_counters(struct udma_chan *uc)
+{
+	u32 val;
+
+	if (uc->tchan) {
+		val = udma_tchanrt_read(uc->tchan, UDMA_TCHAN_RT_BCNT_REG);
+		udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_BCNT_REG, val);
+
+		val = udma_tchanrt_read(uc->tchan, UDMA_TCHAN_RT_SBCNT_REG);
+		udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_SBCNT_REG, val);
+
+		val = udma_tchanrt_read(uc->tchan, UDMA_TCHAN_RT_PCNT_REG);
+		udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_PCNT_REG, val);
+
+		val = udma_tchanrt_read(uc->tchan, UDMA_TCHAN_RT_PEER_BCNT_REG);
+		udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_PEER_BCNT_REG, val);
+	}
+
+	if (uc->rchan) {
+		val = udma_rchanrt_read(uc->rchan, UDMA_RCHAN_RT_BCNT_REG);
+		udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_BCNT_REG, val);
+
+		val = udma_rchanrt_read(uc->rchan, UDMA_RCHAN_RT_SBCNT_REG);
+		udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_SBCNT_REG, val);
+
+		val = udma_rchanrt_read(uc->rchan, UDMA_RCHAN_RT_PCNT_REG);
+		udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_PCNT_REG, val);
+
+		val = udma_rchanrt_read(uc->rchan, UDMA_RCHAN_RT_PEER_BCNT_REG);
+		udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_PEER_BCNT_REG, val);
+	}
+
+	uc->bcnt = 0;
+}
+
+static inline int udma_stop_hard(struct udma_chan *uc)
+{
+	k3_udma_dbg("%s: ENTER (chan%d)\n", __func__, uc->id);
+
+	switch (uc->dir) {
+	case DMA_DEV_TO_MEM:
+		udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_PEER_RT_EN_REG, 0);
+		udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_CTL_REG, 0);
+		break;
+	case DMA_MEM_TO_DEV:
+		udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_CTL_REG, 0);
+		udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_PEER_RT_EN_REG, 0);
+		break;
+	case DMA_MEM_TO_MEM:
+		udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_CTL_REG, 0);
+		udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_CTL_REG, 0);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int udma_start(struct udma_chan *uc)
+{
+	/* Channel is already running, no need to proceed further */
+	if (udma_is_chan_running(uc))
+		goto out;
+
+	k3_udma_dbg("%s: chan:%d dir:%s (static_tr_type: %d)\n",
+		    __func__, uc->id, udma_get_dir_text(uc->dir),
+		    uc->static_tr_type);
+
+	/* Make sure that we clear the teardown bit, if it is set */
+	udma_stop_hard(uc);
+
+	/* Reset all counters */
+	udma_reset_counters(uc);
+
+	switch (uc->dir) {
+	case DMA_DEV_TO_MEM:
+		udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_CTL_REG,
+				   UDMA_CHAN_RT_CTL_EN);
+
+		/* Enable remote */
+		udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_PEER_RT_EN_REG,
+				   UDMA_PEER_RT_EN_ENABLE);
+
+		k3_udma_dbg("%s(rx): RT_CTL:0x%08x PEER RT_ENABLE:0x%08x\n",
+			    __func__,
+			    udma_rchanrt_read(uc->rchan,
+					      UDMA_RCHAN_RT_CTL_REG),
+			    udma_rchanrt_read(uc->rchan,
+					      UDMA_RCHAN_RT_PEER_RT_EN_REG));
+		break;
+	case DMA_MEM_TO_DEV:
+		/* Enable remote */
+		udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_PEER_RT_EN_REG,
+				   UDMA_PEER_RT_EN_ENABLE);
+
+		udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_CTL_REG,
+				   UDMA_CHAN_RT_CTL_EN);
+
+		k3_udma_dbg("%s(tx): RT_CTL:0x%08x PEER RT_ENABLE:0x%08x\n",
+			    __func__,
+			    udma_rchanrt_read(uc->rchan,
+					      UDMA_TCHAN_RT_CTL_REG),
+			    udma_rchanrt_read(uc->rchan,
+					      UDMA_TCHAN_RT_PEER_RT_EN_REG));
+		break;
+	case DMA_MEM_TO_MEM:
+		udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_CTL_REG,
+				   UDMA_CHAN_RT_CTL_EN);
+		udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_CTL_REG,
+				   UDMA_CHAN_RT_CTL_EN);
+
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	k3_udma_dbg("%s: DONE chan:%d\n", __func__, uc->id);
+out:
+	return 0;
+}
+
+static inline void udma_stop_mem2dev(struct udma_chan *uc, bool sync)
+{
+	int i = 0;
+	u32 val;
+
+	udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_CTL_REG,
+			   UDMA_CHAN_RT_CTL_EN |
+			   UDMA_CHAN_RT_CTL_TDOWN);
+
+	val = udma_tchanrt_read(uc->tchan, UDMA_TCHAN_RT_CTL_REG);
+
+	while (sync && (val & UDMA_CHAN_RT_CTL_EN)) {
+		val = udma_tchanrt_read(uc->tchan, UDMA_TCHAN_RT_CTL_REG);
+		udelay(1);
+		if (i > 1000) {
+			printf(" %s TIMEOUT !\n", __func__);
+			break;
+		}
+		i++;
+	}
+
+	val = udma_tchanrt_read(uc->tchan, UDMA_TCHAN_RT_PEER_RT_EN_REG);
+	if (val & UDMA_PEER_RT_EN_ENABLE)
+		printf("%s: peer not stopped TIMEOUT !\n", __func__);
+}
+
+static inline void udma_stop_dev2mem(struct udma_chan *uc, bool sync)
+{
+	int i = 0;
+	u32 val;
+
+	udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_PEER_RT_EN_REG,
+			   UDMA_PEER_RT_EN_ENABLE |
+			   UDMA_PEER_RT_EN_TEARDOWN);
+
+	val = udma_rchanrt_read(uc->rchan, UDMA_RCHAN_RT_CTL_REG);
+
+	while (sync && (val & UDMA_CHAN_RT_CTL_EN)) {
+		val = udma_rchanrt_read(uc->rchan, UDMA_RCHAN_RT_CTL_REG);
+		udelay(1);
+		if (i > 1000) {
+			printf("%s TIMEOUT !\n", __func__);
+			break;
+		}
+		i++;
+	}
+
+	val = udma_rchanrt_read(uc->rchan, UDMA_RCHAN_RT_PEER_RT_EN_REG);
+	if (val & UDMA_PEER_RT_EN_ENABLE)
+		printf("%s: peer not stopped TIMEOUT !\n", __func__);
+}
+
+static inline int udma_stop(struct udma_chan *uc)
+{
+	k3_udma_dbg("%s: chan:%d dir:%s\n",
+		    __func__, uc->id, udma_get_dir_text(uc->dir));
+
+	switch (uc->dir) {
+	case DMA_DEV_TO_MEM:
+		udma_stop_dev2mem(uc, true);
+		break;
+	case DMA_MEM_TO_DEV:
+		udma_stop_mem2dev(uc, true);
+		break;
+	case DMA_MEM_TO_MEM:
+		udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_CTL_REG, 0);
+		udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_CTL_REG, 0);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void udma_poll_completion(struct udma_chan *uc, dma_addr_t *paddr)
+{
+	int i = 1;
+
+	while (udma_pop_from_ring(uc, paddr)) {
+		udelay(1);
+		if (!(i % 1000000))
+			printf(".");
+		i++;
+	}
+}
+
+#define UDMA_RESERVE_RESOURCE(res)					\
+static struct udma_##res *__udma_reserve_##res(struct udma_dev *ud,	\
+					       int id)			\
+{									\
+	if (id >= 0) {							\
+		if (test_bit(id, ud->res##_map)) {			\
+			dev_err(ud->dev, "res##%d is in use\n", id);	\
+			return ERR_PTR(-ENOENT);			\
+		}							\
+	} else {							\
+		id = find_first_zero_bit(ud->res##_map, ud->res##_cnt); \
+		if (id == ud->res##_cnt) {				\
+			return ERR_PTR(-ENOENT);			\
+		}							\
+	}								\
+									\
+	__set_bit(id, ud->res##_map);					\
+	return &ud->res##s[id];						\
+}
+
+UDMA_RESERVE_RESOURCE(tchan);
+UDMA_RESERVE_RESOURCE(rchan);
+UDMA_RESERVE_RESOURCE(rflow);
+
+static int udma_get_tchan(struct udma_chan *uc)
+{
+	struct udma_dev *ud = uc->ud;
+
+	if (uc->tchan) {
+		dev_dbg(ud->dev, "chan%d: already have tchan%d allocated\n",
+			uc->id, uc->tchan->id);
+		return 0;
+	}
+
+	uc->tchan = __udma_reserve_tchan(ud, -1);
+	if (IS_ERR(uc->tchan))
+		return PTR_ERR(uc->tchan);
+
+	k3_udma_dbg("chan%d: got tchan%d\n", uc->id, uc->tchan->id);
+
+	if (udma_is_chan_running(uc)) {
+		dev_warn(ud->dev, "chan%d: tchan%d is running!\n", uc->id,
+			 uc->tchan->id);
+		udma_stop(uc);
+		if (udma_is_chan_running(uc))
+			dev_err(ud->dev, "chan%d: won't stop!\n", uc->id);
+	}
+
+	return 0;
+}
+
+static int udma_get_rchan(struct udma_chan *uc)
+{
+	struct udma_dev *ud = uc->ud;
+
+	if (uc->rchan) {
+		dev_dbg(ud->dev, "chan%d: already have rchan%d allocated\n",
+			uc->id, uc->rchan->id);
+		return 0;
+	}
+
+	uc->rchan = __udma_reserve_rchan(ud, -1);
+	if (IS_ERR(uc->rchan))
+		return PTR_ERR(uc->rchan);
+
+	k3_udma_dbg("chan%d: got rchan%d\n", uc->id, uc->rchan->id);
+
+	if (udma_is_chan_running(uc)) {
+		dev_warn(ud->dev, "chan%d: rchan%d is running!\n", uc->id,
+			 uc->rchan->id);
+		udma_stop(uc);
+		if (udma_is_chan_running(uc))
+			dev_err(ud->dev, "chan%d: won't stop!\n", uc->id);
+	}
+
+	return 0;
+}
+
+static int udma_get_chan_pair(struct udma_chan *uc)
+{
+	struct udma_dev *ud = uc->ud;
+	int chan_id, end;
+
+	if ((uc->tchan && uc->rchan) && uc->tchan->id == uc->rchan->id) {
+		dev_info(ud->dev, "chan%d: already have %d pair allocated\n",
+			 uc->id, uc->tchan->id);
+		return 0;
+	}
+
+	if (uc->tchan) {
+		dev_err(ud->dev, "chan%d: already have tchan%d allocated\n",
+			uc->id, uc->tchan->id);
+		return -EBUSY;
+	} else if (uc->rchan) {
+		dev_err(ud->dev, "chan%d: already have rchan%d allocated\n",
+			uc->id, uc->rchan->id);
+		return -EBUSY;
+	}
+
+	/* Can be optimized, but let's have it like this for now */
+	end = min(ud->tchan_cnt, ud->rchan_cnt);
+	for (chan_id = 0; chan_id < end; chan_id++) {
+		if (!test_bit(chan_id, ud->tchan_map) &&
+		    !test_bit(chan_id, ud->rchan_map))
+			break;
+	}
+
+	if (chan_id == end)
+		return -ENOENT;
+
+	__set_bit(chan_id, ud->tchan_map);
+	__set_bit(chan_id, ud->rchan_map);
+	uc->tchan = &ud->tchans[chan_id];
+	uc->rchan = &ud->rchans[chan_id];
+
+	k3_udma_dbg("chan%d: got t/rchan%d pair\n", uc->id, chan_id);
+
+	if (udma_is_chan_running(uc)) {
+		dev_warn(ud->dev, "chan%d: t/rchan%d pair is running!\n",
+			 uc->id, chan_id);
+		udma_stop(uc);
+		if (udma_is_chan_running(uc))
+			dev_err(ud->dev, "chan%d: won't stop!\n", uc->id);
+	}
+
+	return 0;
+}
+
+static int udma_get_rflow(struct udma_chan *uc, int flow_id)
+{
+	struct udma_dev *ud = uc->ud;
+
+	if (uc->rflow) {
+		dev_dbg(ud->dev, "chan%d: already have rflow%d allocated\n",
+			uc->id, uc->rflow->id);
+		return 0;
+	}
+
+	if (!uc->rchan)
+		dev_warn(ud->dev, "chan%d: does not have rchan??\n", uc->id);
+
+	uc->rflow = __udma_reserve_rflow(ud, flow_id);
+	if (IS_ERR(uc->rflow))
+		return PTR_ERR(uc->rflow);
+
+	k3_udma_dbg("chan%d: got rflow%d\n", uc->id, uc->rflow->id);
+	return 0;
+}
+
+static void udma_put_rchan(struct udma_chan *uc)
+{
+	struct udma_dev *ud = uc->ud;
+
+	if (uc->rchan) {
+		dev_dbg(ud->dev, "chan%d: put rchan%d\n", uc->id,
+			uc->rchan->id);
+		__clear_bit(uc->rchan->id, ud->rchan_map);
+		uc->rchan = NULL;
+	}
+}
+
+static void udma_put_tchan(struct udma_chan *uc)
+{
+	struct udma_dev *ud = uc->ud;
+
+	if (uc->tchan) {
+		dev_dbg(ud->dev, "chan%d: put tchan%d\n", uc->id,
+			uc->tchan->id);
+		__clear_bit(uc->tchan->id, ud->tchan_map);
+		uc->tchan = NULL;
+	}
+}
+
+static void udma_put_rflow(struct udma_chan *uc)
+{
+	struct udma_dev *ud = uc->ud;
+
+	if (uc->rflow) {
+		dev_dbg(ud->dev, "chan%d: put rflow%d\n", uc->id,
+			uc->rflow->id);
+		__clear_bit(uc->rflow->id, ud->rflow_map);
+		uc->rflow = NULL;
+	}
+}
+
+static void udma_free_tx_resources(struct udma_chan *uc)
+{
+	if (!uc->tchan)
+		return;
+
+	k3_nav_ringacc_ring_free(uc->tchan->t_ring);
+	k3_nav_ringacc_ring_free(uc->tchan->tc_ring);
+	uc->tchan->t_ring = NULL;
+	uc->tchan->tc_ring = NULL;
+
+	udma_put_tchan(uc);
+}
+
+static int udma_alloc_tx_resources(struct udma_chan *uc)
+{
+	struct k3_nav_ring_cfg ring_cfg;
+	struct udma_dev *ud = uc->ud;
+	int ret;
+
+	ret = udma_get_tchan(uc);
+	if (ret)
+		return ret;
+
+	uc->tchan->t_ring = k3_nav_ringacc_request_ring(
+				ud->ringacc, uc->tchan->id,
+				RINGACC_RING_USE_PROXY);
+	if (!uc->tchan->t_ring) {
+		ret = -EBUSY;
+		goto err_tx_ring;
+	}
+
+	uc->tchan->tc_ring = k3_nav_ringacc_request_ring(
+				ud->ringacc, -1, RINGACC_RING_USE_PROXY);
+	if (!uc->tchan->tc_ring) {
+		ret = -EBUSY;
+		goto err_txc_ring;
+	}
+
+	memset(&ring_cfg, 0, sizeof(ring_cfg));
+	ring_cfg.size = 16;
+	ring_cfg.elm_size = K3_NAV_RINGACC_RING_ELSIZE_8;
+	ring_cfg.mode = K3_NAV_RINGACC_RING_MODE_MESSAGE;
+
+	ret = k3_nav_ringacc_ring_cfg(uc->tchan->t_ring, &ring_cfg);
+	ret |= k3_nav_ringacc_ring_cfg(uc->tchan->tc_ring, &ring_cfg);
+
+	if (ret)
+		goto err_ringcfg;
+
+	return 0;
+
+err_ringcfg:
+	k3_nav_ringacc_ring_free(uc->tchan->tc_ring);
+	uc->tchan->tc_ring = NULL;
+err_txc_ring:
+	k3_nav_ringacc_ring_free(uc->tchan->t_ring);
+	uc->tchan->t_ring = NULL;
+err_tx_ring:
+	udma_put_tchan(uc);
+
+	return ret;
+}
+
+static void udma_free_rx_resources(struct udma_chan *uc)
+{
+	if (!uc->rchan)
+		return;
+
+	k3_nav_ringacc_ring_free(uc->rchan->fd_ring);
+	k3_nav_ringacc_ring_free(uc->rchan->r_ring);
+	uc->rchan->fd_ring = NULL;
+	uc->rchan->r_ring = NULL;
+
+	udma_put_rflow(uc);
+	udma_put_rchan(uc);
+}
+
+static int udma_alloc_rx_resources(struct udma_chan *uc)
+{
+	struct k3_nav_ring_cfg ring_cfg;
+	struct udma_dev *ud = uc->ud;
+	int fd_ring_id;
+	int ret;
+
+	ret = udma_get_rchan(uc);
+	if (ret)
+		return ret;
+
+	ret = udma_get_rflow(uc, uc->rchan->id);
+	if (ret) {
+		ret = -EBUSY;
+		goto err_rflow;
+	}
+
+	if (uc->dir == DMA_MEM_TO_MEM)
+		fd_ring_id = -1;
+	else
+		fd_ring_id = ud->tchan_cnt + ud->echan_cnt + uc->rchan->id;
+
+	uc->rchan->fd_ring = k3_nav_ringacc_request_ring(
+				ud->ringacc, fd_ring_id,
+				RINGACC_RING_USE_PROXY);
+	if (!uc->rchan->fd_ring) {
+		ret = -EBUSY;
+		goto err_rx_ring;
+	}
+
+	uc->rchan->r_ring = k3_nav_ringacc_request_ring(
+				ud->ringacc, -1, RINGACC_RING_USE_PROXY);
+	if (!uc->rchan->r_ring) {
+		ret = -EBUSY;
+		goto err_rxc_ring;
+	}
+
+	memset(&ring_cfg, 0, sizeof(ring_cfg));
+	ring_cfg.size = 16;
+	ring_cfg.elm_size = K3_NAV_RINGACC_RING_ELSIZE_8;
+	ring_cfg.mode = K3_NAV_RINGACC_RING_MODE_MESSAGE;
+
+	ret = k3_nav_ringacc_ring_cfg(uc->rchan->fd_ring, &ring_cfg);
+	ret |= k3_nav_ringacc_ring_cfg(uc->rchan->r_ring, &ring_cfg);
+
+	if (ret)
+		goto err_ringcfg;
+
+	return 0;
+
+err_ringcfg:
+	k3_nav_ringacc_ring_free(uc->rchan->r_ring);
+	uc->rchan->r_ring = NULL;
+err_rxc_ring:
+	k3_nav_ringacc_ring_free(uc->rchan->fd_ring);
+	uc->rchan->fd_ring = NULL;
+err_rx_ring:
+	udma_put_rflow(uc);
+err_rflow:
+	udma_put_rchan(uc);
+
+	return ret;
+}
+
+static int udma_alloc_tchan_sci_req(struct udma_chan *uc)
+{
+	struct udma_dev *ud = uc->ud;
+	int tc_ring = k3_nav_ringacc_get_ring_id(uc->tchan->tc_ring);
+	struct ti_sci_msg_rm_udmap_tx_ch_cfg req;
+	u32 mode;
+	int ret;
+
+	if (uc->pkt_mode)
+		mode = TI_SCI_RM_UDMAP_CHAN_TYPE_PKT_PBRR;
+	else
+		mode = TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_PBRR;
+
+	req.valid_params = TI_SCI_MSG_VALUE_RM_UDMAP_CH_CHAN_TYPE_VALID |
+			TI_SCI_MSG_VALUE_RM_UDMAP_CH_FETCH_SIZE_VALID |
+			TI_SCI_MSG_VALUE_RM_UDMAP_CH_CQ_QNUM_VALID;
+	req.nav_id = ud->tisci_dev_id;
+	req.index = uc->tchan->id;
+	req.tx_chan_type = mode;
+	req.tx_fetch_size = 16;
+	req.txcq_qnum = tc_ring;
+
+	ret = ud->tisci_udmap_ops->tx_ch_cfg(ud->tisci, &req);
+	if (ret)
+		dev_err(ud->dev, "tisci tx alloc failed %d\n", ret);
+
+	return ret;
+}
+
+static int udma_alloc_rchan_sci_req(struct udma_chan *uc)
+{
+	struct udma_dev *ud = uc->ud;
+	int fd_ring = k3_nav_ringacc_get_ring_id(uc->rchan->fd_ring);
+	int rx_ring = k3_nav_ringacc_get_ring_id(uc->rchan->r_ring);
+	struct ti_sci_msg_rm_udmap_rx_ch_cfg req = { 0 };
+	struct ti_sci_msg_rm_udmap_flow_cfg flow_req = { 0 };
+	u32 mode;
+	int ret;
+
+	if (uc->pkt_mode)
+		mode = TI_SCI_RM_UDMAP_CHAN_TYPE_PKT_PBRR;
+	else
+		mode = TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_PBRR;
+
+	req.valid_params = TI_SCI_MSG_VALUE_RM_UDMAP_CH_FETCH_SIZE_VALID |
+			TI_SCI_MSG_VALUE_RM_UDMAP_CH_CQ_QNUM_VALID |
+			TI_SCI_MSG_VALUE_RM_UDMAP_CH_CHAN_TYPE_VALID;
+	req.nav_id = ud->tisci_dev_id;
+	req.index = uc->rchan->id;
+	req.rx_fetch_size = 16;
+	req.rxcq_qnum = rx_ring;
+	if (uc->rflow->id != uc->rchan->id) {
+		req.flowid_start = uc->rflow->id;
+		req.flowid_cnt = 1;
+		req.valid_params |=
+			TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_FLOWID_START_VALID |
+			TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_FLOWID_CNT_VALID;
+	}
+	req.rx_chan_type = mode;
+
+	ret = ud->tisci_udmap_ops->rx_ch_cfg(ud->tisci, &req);
+	if (ret) {
+		dev_err(ud->dev, "tisci rx %u cfg failed %d\n",
+			uc->rchan->id, ret);
+		return ret;
+	}
+
+	flow_req.valid_params =
+			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_EINFO_PRESENT_VALID |
+			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_PSINFO_PRESENT_VALID |
+			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_ERROR_HANDLING_VALID |
+			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DESC_TYPE_VALID |
+			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_QNUM_VALID |
+			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_SRC_TAG_HI_SEL_VALID |
+			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_SRC_TAG_LO_SEL_VALID |
+			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_TAG_HI_SEL_VALID |
+			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_TAG_LO_SEL_VALID |
+			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ0_SZ0_QNUM_VALID |
+			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ1_QNUM_VALID |
+			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ2_QNUM_VALID |
+			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ3_QNUM_VALID |
+			TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_PS_LOCATION_VALID;
+
+	flow_req.nav_id = ud->tisci_dev_id;
+	flow_req.flow_index = uc->rflow->id;
+
+	if (uc->needs_epib)
+		flow_req.rx_einfo_present = 1;
+	else
+		flow_req.rx_einfo_present = 0;
+
+	if (uc->psd_size)
+		flow_req.rx_psinfo_present = 1;
+	else
+		flow_req.rx_psinfo_present = 0;
+
+	flow_req.rx_error_handling = 0;
+	flow_req.rx_desc_type = 0;
+	flow_req.rx_dest_qnum = rx_ring;
+	flow_req.rx_src_tag_hi_sel = 2;
+	flow_req.rx_src_tag_lo_sel = 4;
+	flow_req.rx_dest_tag_hi_sel = 5;
+	flow_req.rx_dest_tag_lo_sel = 4;
+	flow_req.rx_fdq0_sz0_qnum = fd_ring;
+	flow_req.rx_fdq1_qnum = fd_ring;
+	flow_req.rx_fdq2_qnum = fd_ring;
+	flow_req.rx_fdq3_qnum = fd_ring;
+	flow_req.rx_ps_location = 0;
+
+	ret = ud->tisci_udmap_ops->rx_flow_cfg(ud->tisci, &flow_req);
+	if (ret)
+		dev_err(ud->dev, "tisci rx %u flow %u cfg failed %d\n",
+			uc->rchan->id, uc->rflow->id, ret);
+
+	return ret;
+}
+
+static int udma_alloc_chan_resources(struct udma_chan *uc)
+{
+	struct udma_dev *ud = uc->ud;
+	int ret;
+
+	k3_udma_dbg("%s: chan:%d as %s\n",
+		    __func__, uc->id, udma_get_dir_text(uc->dir));
+
+	switch (uc->dir) {
+	case DMA_MEM_TO_MEM:
+		/* Non synchronized - mem to mem type of transfer */
+		ret = udma_get_chan_pair(uc);
+		if (ret)
+			return ret;
+
+		ret = udma_alloc_tx_resources(uc);
+		if (ret)
+			goto err_free_res;
+
+		ret = udma_alloc_rx_resources(uc);
+		if (ret)
+			goto err_free_res;
+
+		uc->src_thread = ud->psil_base + uc->tchan->id;
+		uc->dst_thread = (ud->psil_base + uc->rchan->id) | 0x8000;
+		uc->pkt_mode = true;
+		break;
+	case DMA_MEM_TO_DEV:
+		/* Slave transfer synchronized - mem to dev (TX) trasnfer */
+		ret = udma_alloc_tx_resources(uc);
+		if (ret)
+			goto err_free_res;
+
+		uc->src_thread = ud->psil_base + uc->tchan->id;
+		uc->dst_thread = uc->slave_thread_id;
+		if (!(uc->dst_thread & 0x8000))
+			uc->dst_thread |= 0x8000;
+
+		break;
+	case DMA_DEV_TO_MEM:
+		/* Slave transfer synchronized - dev to mem (RX) trasnfer */
+		ret = udma_alloc_rx_resources(uc);
+		if (ret)
+			goto err_free_res;
+
+		uc->src_thread = uc->slave_thread_id;
+		uc->dst_thread = (ud->psil_base + uc->rchan->id) | 0x8000;
+
+		break;
+	default:
+		/* Can not happen */
+		k3_udma_dbg("%s: chan:%d invalid direction (%u)\n",
+			    __func__, uc->id, uc->dir);
+		return -EINVAL;
+	}
+
+	/* We have channel indexes and rings */
+	if (uc->dir == DMA_MEM_TO_MEM) {
+		ret = udma_alloc_tchan_sci_req(uc);
+		if (ret)
+			goto err_free_res;
+
+		ret = udma_alloc_rchan_sci_req(uc);
+		if (ret)
+			goto err_free_res;
+	} else {
+		/* Slave transfer */
+		if (uc->dir == DMA_MEM_TO_DEV) {
+			ret = udma_alloc_tchan_sci_req(uc);
+			if (ret)
+				goto err_free_res;
+		} else {
+			ret = udma_alloc_rchan_sci_req(uc);
+			if (ret)
+				goto err_free_res;
+		}
+	}
+
+	/* PSI-L pairing */
+	ret = udma_navss_psil_pair(ud, uc->src_thread, uc->dst_thread);
+	if (ret) {
+		dev_err(ud->dev, "k3_nav_psil_request_link fail\n");
+		goto err_free_res;
+	}
+
+	return 0;
+
+err_free_res:
+	udma_free_tx_resources(uc);
+	udma_free_rx_resources(uc);
+	uc->slave_thread_id = -1;
+	return ret;
+}
+
+static void udma_free_chan_resources(struct udma_chan *uc)
+{
+	/* Some configuration to UDMA-P channel: disable, reset, whatever */
+
+	/* Release PSI-L pairing */
+	udma_navss_psil_unpair(uc->ud, uc->src_thread, uc->dst_thread);
+
+	/* Reset the rings for a new start */
+	udma_reset_rings(uc);
+	udma_free_tx_resources(uc);
+	udma_free_rx_resources(uc);
+
+	uc->slave_thread_id = -1;
+	uc->dir = DMA_MEM_TO_MEM;
+}
+
+static int udma_get_mmrs(struct udevice *dev)
+{
+	struct udma_dev *ud = dev_get_priv(dev);
+	int i;
+
+	for (i = 0; i < MMR_LAST; i++) {
+		ud->mmrs[i] = (uint32_t *)devfdt_get_addr_name(dev,
+				mmr_names[i]);
+		if (!ud->mmrs[i])
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
+#define UDMA_MAX_CHANNELS	192
+
+static int udma_probe(struct udevice *dev)
+{
+	struct dma_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct udma_dev *ud = dev_get_priv(dev);
+	int i, ret;
+	u32 cap2, cap3;
+	struct udevice *tmp;
+	struct udevice *tisci_dev = NULL;
+
+	ret = udma_get_mmrs(dev);
+	if (ret)
+		return ret;
+
+	ret = uclass_get_device_by_phandle(UCLASS_MISC, dev,
+					   "ti,ringacc", &tmp);
+	ud->ringacc = dev_get_priv(tmp);
+	if (IS_ERR(ud->ringacc))
+		return PTR_ERR(ud->ringacc);
+
+	ud->ch_count = dev_read_u32_default(dev, "dma-channels", 0);
+	if (!ud->ch_count) {
+		dev_info(dev, "Missing dma-channels property, using %u.\n",
+			 UDMA_MAX_CHANNELS);
+		ud->ch_count = UDMA_MAX_CHANNELS;
+	}
+
+	ud->psil_base = dev_read_u32_default(dev, "ti,psil-base", 0);
+	if (!ud->psil_base) {
+		dev_info(dev,
+			 "Missing ti,psil-base property, using %d.\n", ret);
+		return -EINVAL;
+	}
+
+	ret = uclass_get_device_by_name(UCLASS_FIRMWARE, "dmsc", &tisci_dev);
+	if (ret) {
+		debug("TISCI RA RM get failed (%d)\n", ret);
+		ud->tisci = NULL;
+		return 0;
+	}
+	ud->tisci = (struct ti_sci_handle *)
+			 (ti_sci_get_handle_from_sysfw(tisci_dev));
+
+	ret = dev_read_u32_default(dev, "ti,sci", 0);
+	if (!ret) {
+		dev_err(dev, "TISCI RA RM disabled\n");
+		ud->tisci = NULL;
+	}
+
+	if (ud->tisci) {
+		ofnode navss_ofnode = ofnode_get_parent(dev_ofnode(dev));
+
+		ud->tisci_dev_id = -1;
+		ret = dev_read_u32(dev, "ti,sci-dev-id", &ud->tisci_dev_id);
+		if (ret) {
+			dev_err(dev, "ti,sci-dev-id read failure %d\n", ret);
+			return ret;
+		}
+
+		ud->tisci_navss_dev_id = -1;
+		ret = ofnode_read_u32(navss_ofnode, "ti,sci-dev-id",
+				      &ud->tisci_navss_dev_id);
+		if (ret) {
+			dev_err(dev, "navss sci-dev-id read failure %d\n", ret);
+			return ret;
+		}
+
+		ud->tisci_udmap_ops = &ud->tisci->ops.rm_udmap_ops;
+		ud->tisci_psil_ops = &ud->tisci->ops.rm_psil_ops;
+	}
+
+	cap2 = udma_read(ud->mmrs[MMR_GCFG], 0x28);
+	cap3 = udma_read(ud->mmrs[MMR_GCFG], 0x2c);
+
+	ud->rflow_cnt = cap3 & 0x3fff;
+	ud->tchan_cnt = cap2 & 0x1ff;
+	ud->echan_cnt = (cap2 >> 9) & 0x1ff;
+	ud->rchan_cnt = (cap2 >> 18) & 0x1ff;
+	if ((ud->tchan_cnt + ud->rchan_cnt) != ud->ch_count) {
+		dev_info(dev,
+			 "Channel count mismatch: %u != tchan(%u) + rchan(%u)\n",
+			 ud->ch_count, ud->tchan_cnt, ud->rchan_cnt);
+		ud->ch_count  = ud->tchan_cnt + ud->rchan_cnt;
+	}
+
+	dev_info(dev,
+		 "Number of channels: %u (tchan: %u, echan: %u, rchan: %u dev-id %u)\n",
+		 ud->ch_count, ud->tchan_cnt, ud->echan_cnt, ud->rchan_cnt,
+		 ud->tisci_dev_id);
+	dev_info(dev, "Number of rflows: %u\n", ud->rflow_cnt);
+
+	ud->channels = devm_kcalloc(dev, ud->ch_count, sizeof(*ud->channels),
+				    GFP_KERNEL);
+	ud->tchan_map = devm_kcalloc(dev, BITS_TO_LONGS(ud->tchan_cnt),
+				     sizeof(unsigned long), GFP_KERNEL);
+	ud->tchans = devm_kcalloc(dev, ud->tchan_cnt,
+				  sizeof(*ud->tchans), GFP_KERNEL);
+	ud->rchan_map = devm_kcalloc(dev, BITS_TO_LONGS(ud->rchan_cnt),
+				     sizeof(unsigned long), GFP_KERNEL);
+	ud->rchans = devm_kcalloc(dev, ud->rchan_cnt,
+				  sizeof(*ud->rchans), GFP_KERNEL);
+	ud->rflow_map = devm_kcalloc(dev, BITS_TO_LONGS(ud->rflow_cnt),
+				     sizeof(unsigned long), GFP_KERNEL);
+	ud->rflows = devm_kcalloc(dev, ud->rflow_cnt,
+				  sizeof(*ud->rflows), GFP_KERNEL);
+
+	if (!ud->channels || !ud->tchan_map || !ud->rchan_map ||
+	    !ud->rflow_map || !ud->tchans || !ud->rchans || !ud->rflows)
+		return -ENOMEM;
+
+	for (i = 0; i < ud->tchan_cnt; i++) {
+		struct udma_tchan *tchan = &ud->tchans[i];
+
+		tchan->id = i;
+		tchan->reg_rt = ud->mmrs[MMR_TCHANRT] + UDMA_CH_1000(i);
+	}
+
+	for (i = 0; i < ud->rchan_cnt; i++) {
+		struct udma_rchan *rchan = &ud->rchans[i];
+
+		rchan->id = i;
+		rchan->reg_rt = ud->mmrs[MMR_RCHANRT] + UDMA_CH_1000(i);
+	}
+
+	for (i = 0; i < ud->rflow_cnt; i++) {
+		struct udma_rflow *rflow = &ud->rflows[i];
+
+		rflow->id = i;
+	}
+
+	for (i = 0; i < ud->ch_count; i++) {
+		struct udma_chan *uc = &ud->channels[i];
+
+		uc->ud = ud;
+		uc->id = i;
+		uc->slave_thread_id = -1;
+		uc->tchan = NULL;
+		uc->rchan = NULL;
+		uc->dir = DMA_MEM_TO_MEM;
+		sprintf(uc->name, "UDMA chan%d\n", i);
+		if (!i)
+			uc->in_use = true;
+	}
+
+	k3_udma_dbg("UDMA(rev: 0x%08x) CAP0-3: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
+		    udma_read(ud->mmrs[MMR_GCFG], 0),
+		    udma_read(ud->mmrs[MMR_GCFG], 0x20),
+		    udma_read(ud->mmrs[MMR_GCFG], 0x24),
+		    udma_read(ud->mmrs[MMR_GCFG], 0x28),
+		    udma_read(ud->mmrs[MMR_GCFG], 0x2c));
+
+	uc_priv->supported = DMA_SUPPORTS_MEM_TO_MEM | DMA_SUPPORTS_MEM_TO_DEV;
+
+	return ret;
+}
+
+static void udma_fill_rxfdq_ring(struct udma_chan *uc, void *src,
+				 void *dst, size_t len)
+{
+	dma_addr_t dma_dst = (dma_addr_t)dst;
+	unsigned long dummy;
+	struct knav_udmap_host_desc_t *desc_rx;
+
+	desc_rx = dma_alloc_coherent(sizeof(*desc_rx), &dummy);
+	memset(desc_rx, 0, sizeof(*desc_rx));
+
+	knav_udmap_hdesc_init(desc_rx, 0, 0);
+	knav_udmap_hdesc_set_pktlen(desc_rx, len);
+	knav_udmap_hdesc_attach_buf(desc_rx, dma_dst, len, dma_dst, len);
+
+	flush_dcache_range((u64)desc_rx,
+			   ALIGN((u64)desc_rx + sizeof(*desc_rx),
+				 ARCH_DMA_MINALIGN));
+	k3_nav_ringacc_ring_push(uc->rchan->fd_ring, &desc_rx);
+}
+
+static void udma_push_tx_ring(struct udma_chan *uc, void *src,
+			      void *dst, size_t len)
+{
+	u32 tc_ring_id = k3_nav_ringacc_get_ring_id(uc->tchan->tc_ring);
+	dma_addr_t dma_src = (dma_addr_t)src;
+	unsigned long dummy;
+	struct knav_udmap_host_desc_t *desc_tx;
+
+	desc_tx = dma_alloc_coherent(sizeof(*desc_tx), &dummy);
+	memset(desc_tx, 0, sizeof(*desc_tx));
+
+	knav_udmap_hdesc_init(desc_tx, 0, 0);
+	knav_udmap_hdesc_set_pktlen(desc_tx, len);
+	knav_udmap_hdesc_attach_buf(desc_tx, dma_src, len, dma_src, len);
+	knav_udmap_hdesc_set_pktids(&desc_tx->hdr, uc->id, 0x3fff);
+	knav_udmap_desc_set_retpolicy(&desc_tx->hdr, 0, tc_ring_id);
+
+	flush_dcache_range((u64)desc_tx,
+			   ALIGN((u64)desc_tx + sizeof(*desc_tx),
+				 ARCH_DMA_MINALIGN));
+	k3_nav_ringacc_ring_push(uc->tchan->t_ring, &desc_tx);
+}
+
+static int udma_transfer(struct udevice *dev, int direction,
+			 void *dst, void *src, size_t len)
+{
+	struct udma_dev *ud = dev_get_priv(dev);
+	/* Hard code to channel 0 for now */
+	struct udma_chan *uc = &ud->channels[0];
+	dma_addr_t paddr;
+	int ret;
+
+	ret = udma_alloc_chan_resources(uc);
+	if (ret)
+		return ret;
+	udma_fill_rxfdq_ring(uc, src, dst, len);
+
+	udma_start(uc);
+	udma_push_tx_ring(uc, src, dst, len);
+	udma_poll_completion(uc, &paddr);
+	udma_stop(uc);
+
+	udma_free_chan_resources(uc);
+	return 0;
+}
+
+static int udma_request(struct dma *dma)
+{
+	struct udma_dev *ud = dev_get_priv(dma->dev);
+	struct udma_chan *uc;
+	unsigned long dummy;
+	int ret;
+
+	if (dma->id >= (ud->rchan_cnt + ud->tchan_cnt)) {
+		dev_err(dma->dev, "invalid dma ch_id %lu\n", dma->id);
+		return -EINVAL;
+	}
+
+	uc = &ud->channels[dma->id];
+	ret = udma_alloc_chan_resources(uc);
+	if (ret) {
+		dev_err(dma->dev, "alloc dma res failed %d\n", ret);
+		return -EINVAL;
+	}
+
+	uc->hdesc_size = knav_udmap_hdesc_calc_size(
+				uc->needs_epib, uc->psd_size, 0);
+	uc->hdesc_size = ALIGN(uc->hdesc_size, ARCH_DMA_MINALIGN);
+
+	if (uc->dir == DMA_MEM_TO_DEV) {
+		uc->desc_tx = dma_alloc_coherent(uc->hdesc_size, &dummy);
+		memset(uc->desc_tx, 0, uc->hdesc_size);
+	} else {
+		uc->desc_rx = dma_alloc_coherent(
+				uc->hdesc_size * UDMA_RX_DESC_NUM, &dummy);
+		memset(uc->desc_rx, 0, uc->hdesc_size * UDMA_RX_DESC_NUM);
+	}
+
+	uc->in_use = true;
+	uc->desc_rx_cur = 0;
+	uc->num_rx_bufs = 0;
+
+	return 0;
+}
+
+static int udma_free(struct dma *dma)
+{
+	struct udma_dev *ud = dev_get_priv(dma->dev);
+	struct udma_chan *uc;
+
+	if (dma->id >= (ud->rchan_cnt + ud->tchan_cnt)) {
+		dev_err(dma->dev, "invalid dma ch_id %lu\n", dma->id);
+		return -EINVAL;
+	}
+	uc = &ud->channels[dma->id];
+
+	if (udma_is_chan_running(uc))
+		udma_stop(uc);
+	udma_free_chan_resources(uc);
+
+	uc->in_use = false;
+
+	return 0;
+}
+
+static int udma_enable(struct dma *dma)
+{
+	struct udma_dev *ud = dev_get_priv(dma->dev);
+	struct udma_chan *uc;
+	int ret;
+
+	if (dma->id >= (ud->rchan_cnt + ud->tchan_cnt)) {
+		dev_err(dma->dev, "invalid dma ch_id %lu\n", dma->id);
+		return -EINVAL;
+	}
+	uc = &ud->channels[dma->id];
+
+	ret = udma_start(uc);
+
+	return ret;
+}
+
+static int udma_disable(struct dma *dma)
+{
+	struct udma_dev *ud = dev_get_priv(dma->dev);
+	struct udma_chan *uc;
+	int ret = 0;
+
+	if (dma->id >= (ud->rchan_cnt + ud->tchan_cnt)) {
+		dev_err(dma->dev, "invalid dma ch_id %lu\n", dma->id);
+		return -EINVAL;
+	}
+	uc = &ud->channels[dma->id];
+
+	if (udma_is_chan_running(uc))
+		ret = udma_stop(uc);
+	else
+		dev_err(dma->dev, "%s not running\n", __func__);
+
+	return ret;
+}
+
+static int udma_send(struct dma *dma, void *src, size_t len, void *metadata)
+{
+	struct udma_dev *ud = dev_get_priv(dma->dev);
+	struct knav_udmap_host_desc_t *desc_tx;
+	dma_addr_t dma_src = (dma_addr_t)src;
+	struct ti_udma_drv_packet_data packet_data = { 0 };
+	dma_addr_t paddr;
+	struct udma_chan *uc;
+	u32 tc_ring_id;
+	int ret;
+
+	if (!metadata)
+		packet_data = *((struct ti_udma_drv_packet_data *)metadata);
+
+	if (dma->id >= (ud->rchan_cnt + ud->tchan_cnt)) {
+		dev_err(dma->dev, "invalid dma ch_id %lu\n", dma->id);
+		return -EINVAL;
+	}
+	uc = &ud->channels[dma->id];
+
+	if (uc->dir != DMA_MEM_TO_DEV)
+		return -EINVAL;
+
+	tc_ring_id = k3_nav_ringacc_get_ring_id(uc->tchan->tc_ring);
+
+	desc_tx = uc->desc_tx;
+
+	knav_udmap_hdesc_reset_hbdesc(desc_tx);
+
+	knav_udmap_hdesc_init(
+		desc_tx,
+		uc->needs_epib ? KNAV_UDMAP_INFO0_HDESC_EPIB_PRESENT : 0,
+		uc->psd_size);
+	knav_udmap_hdesc_set_pktlen(desc_tx, len);
+	knav_udmap_hdesc_attach_buf(desc_tx, dma_src, len, dma_src, len);
+	knav_udmap_hdesc_set_pktids(&desc_tx->hdr, uc->id, 0x3fff);
+	knav_udmap_desc_set_retpolicy(&desc_tx->hdr, 0, tc_ring_id);
+	/* pass below information from caller */
+	knav_udmap_hdesc_set_pkttype(desc_tx, packet_data.pkt_type);
+	knav_udmap_desc_set_tags_ids(&desc_tx->hdr, 0, packet_data.dest_tag);
+
+	k3_udma_print_buf((ulong)desc_tx, desc_tx, 4, uc->hdesc_size / 4, 0);
+
+	flush_dcache_range((u64)dma_src,
+			   ALIGN((u64)dma_src + len,
+				 ARCH_DMA_MINALIGN));
+
+	flush_dcache_range((u64)desc_tx,
+			   ALIGN((u64)desc_tx + uc->hdesc_size,
+				 ARCH_DMA_MINALIGN));
+	ret = k3_nav_ringacc_ring_push(uc->tchan->t_ring, &uc->desc_tx);
+	if (ret) {
+		dev_err(dma->dev, "TX dma push fail ch_id %lu %d\n",
+			dma->id, ret);
+		return ret;
+	}
+
+	udma_poll_completion(uc, &paddr);
+
+	desc_tx = (struct knav_udmap_host_desc_t *)paddr;
+
+	return 0;
+}
+
+static int udma_receive(struct dma *dma, void **dst, void *metadata)
+{
+	struct udma_dev *ud = dev_get_priv(dma->dev);
+	struct knav_udmap_host_desc_t *desc_rx;
+	dma_addr_t buf_dma;
+	struct udma_chan *uc;
+	u32 buf_dma_len, pkt_len;
+	u32 port_id = 0;
+	int ret;
+
+	k3_udma_dev_dbg(dma->dev, "%s\n", __func__);
+
+	if (dma->id >= (ud->rchan_cnt + ud->tchan_cnt)) {
+		dev_err(dma->dev, "invalid dma ch_id %lu\n", dma->id);
+		return -EINVAL;
+	}
+	uc = &ud->channels[dma->id];
+
+	if (uc->dir != DMA_DEV_TO_MEM)
+		return -EINVAL;
+	if (!uc->num_rx_bufs)
+		return -EINVAL;
+
+	ret = k3_nav_ringacc_ring_pop(uc->rchan->r_ring, &desc_rx);
+	if (ret && ret != -ENODATA) {
+		dev_err(dma->dev, "rx dma fail ch_id:%lu %d\n", dma->id, ret);
+		return ret;
+	} else if (ret == -ENODATA) {
+		return 0;
+	}
+
+	k3_udma_print_buf((ulong)desc_rx, desc_rx, 4, uc->hdesc_size / 4, 0);
+
+	/* invalidate cache data */
+	invalidate_dcache_range((ulong)desc_rx,
+				(ulong)(desc_rx + uc->hdesc_size));
+
+	knav_udmap_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len);
+	pkt_len = knav_udmap_hdesc_get_pktlen(desc_rx);
+
+	/* invalidate cache data */
+	invalidate_dcache_range((ulong)buf_dma,
+				(ulong)(buf_dma + buf_dma_len));
+
+	knav_udmap_desc_get_tags_ids(&desc_rx->hdr, &port_id, NULL);
+	k3_udma_dev_dbg(dma->dev, "%s rx port_id:%d\n", __func__, port_id);
+
+	*dst = (void *)buf_dma;
+	uc->num_rx_bufs--;
+
+	return pkt_len;
+}
+
+static int udma_of_xlate(struct dma *dma, struct ofnode_phandle_args *args)
+{
+	struct udma_dev *ud = dev_get_priv(dma->dev);
+	struct udma_chan *uc = &ud->channels[0];
+	ofnode chconf_node, slave_node;
+	char prop[50];
+	u32 val;
+
+	for (val = 0; val < ud->ch_count; val++) {
+		uc = &ud->channels[val];
+		if (!uc->in_use)
+			break;
+	}
+
+	if (val == ud->ch_count)
+		return -EBUSY;
+
+	uc->dir = DMA_DEV_TO_MEM;
+	if (args->args[2] == UDMA_DIR_TX)
+		uc->dir = DMA_MEM_TO_DEV;
+
+	slave_node = ofnode_get_by_phandle(args->args[0]);
+	if (!ofnode_valid(slave_node)) {
+		dev_err(ud->dev, "slave node is missing\n");
+		return -EINVAL;
+	}
+
+	snprintf(prop, sizeof(prop), "ti,psil-config%u", args->args[1]);
+	chconf_node = ofnode_find_subnode(slave_node, prop);
+	if (!ofnode_valid(chconf_node)) {
+		dev_err(ud->dev, "Channel configuration node is missing\n");
+		return -EINVAL;
+	}
+
+	if (!ofnode_read_u32(chconf_node, "linux,udma-mode", &val)) {
+		if (val == UDMA_PKT_MODE)
+			uc->pkt_mode = true;
+	}
+
+	if (!ofnode_read_u32(chconf_node, "statictr-type", &val))
+		uc->static_tr_type = val;
+
+	uc->needs_epib = ofnode_read_bool(chconf_node, "ti,needs-epib");
+	if (!ofnode_read_u32(chconf_node, "ti,psd-size", &val))
+		uc->psd_size = val;
+	uc->metadata_size = (uc->needs_epib ? 16 : 0) + uc->psd_size;
+
+	if (ofnode_read_u32(slave_node, "ti,psil-base", &val)) {
+		dev_err(ud->dev, "ti,psil-base is missing\n");
+		return -EINVAL;
+	}
+
+	uc->slave_thread_id = val + args->args[1];
+
+	dma->id = uc->id;
+	k3_udma_dbg("Allocated dma chn:%lu epib:%d psdata:%u meta:%u thread_id:%x\n",
+		    dma->id, uc->needs_epib,
+		    uc->psd_size, uc->metadata_size,
+		    uc->slave_thread_id);
+
+	return 0;
+}
+
+int udma_prepare_rcv_buf(struct dma *dma, void *dst, size_t size)
+{
+	struct udma_dev *ud = dev_get_priv(dma->dev);
+	struct knav_udmap_host_desc_t *desc_rx;
+	dma_addr_t dma_dst;
+	struct udma_chan *uc;
+	u32 desc_num;
+
+	if (dma->id >= (ud->rchan_cnt + ud->tchan_cnt)) {
+		dev_err(dma->dev, "invalid dma ch_id %lu\n", dma->id);
+		return -EINVAL;
+	}
+	uc = &ud->channels[dma->id];
+
+	if (uc->dir != DMA_DEV_TO_MEM)
+		return -EINVAL;
+
+	if (uc->num_rx_bufs >= UDMA_RX_DESC_NUM)
+		return -EINVAL;
+
+	desc_num = uc->desc_rx_cur % UDMA_RX_DESC_NUM;
+	desc_rx = uc->desc_rx + (desc_num * uc->hdesc_size);
+	dma_dst = (dma_addr_t)dst;
+
+	knav_udmap_hdesc_reset_hbdesc(desc_rx);
+
+	knav_udmap_hdesc_init(desc_rx,
+			      uc->needs_epib ?
+			      KNAV_UDMAP_INFO0_HDESC_EPIB_PRESENT : 0,
+			      uc->psd_size);
+	knav_udmap_hdesc_set_pktlen(desc_rx, size);
+	knav_udmap_hdesc_attach_buf(desc_rx, dma_dst, size, dma_dst, size);
+
+	flush_dcache_range((u64)desc_rx,
+			   ALIGN((u64)desc_rx + uc->hdesc_size,
+				 ARCH_DMA_MINALIGN));
+
+	k3_nav_ringacc_ring_push(uc->rchan->fd_ring, &desc_rx);
+
+	uc->num_rx_bufs++;
+	uc->desc_rx_cur++;
+
+	return 0;
+}
+
+static const struct dma_ops udma_ops = {
+	.transfer	= udma_transfer,
+	.of_xlate	= udma_of_xlate,
+	.request	= udma_request,
+	.free		= udma_free,
+	.enable		= udma_enable,
+	.disable	= udma_disable,
+	.send		= udma_send,
+	.receive	= udma_receive,
+	.prepare_rcv_buf = udma_prepare_rcv_buf,
+};
+
+static const struct udevice_id udma_ids[] = {
+	{ .compatible = "ti,k3-navss-udmap" },
+	{ }
+};
+
+U_BOOT_DRIVER(ti_edma3) = {
+	.name	= "ti-udma",
+	.id	= UCLASS_DMA,
+	.of_match = udma_ids,
+	.ops	= &udma_ops,
+	.probe	= udma_probe,
+	.priv_auto_alloc_size = sizeof(struct udma_dev),
+};
diff --git a/include/dt-bindings/dma/k3-udma.h b/include/dt-bindings/dma/k3-udma.h
new file mode 100644
index 0000000..89ba6a9
--- /dev/null
+++ b/include/dt-bindings/dma/k3-udma.h
@@ -0,0 +1,26 @@
+#ifndef __DT_TI_UDMA_H
+#define __DT_TI_UDMA_H
+
+#define UDMA_TR_MODE		0
+#define UDMA_PKT_MODE		1
+
+#define UDMA_DIR_TX		0
+#define UDMA_DIR_RX		1
+
+#define PSIL_STATIC_TR_NONE	0
+#define PSIL_STATIC_TR_XY	1
+#define PSIL_STATIC_TR_MCAN	2
+
+#define UDMA_PDMA_TR_XY(id)				\
+	ti,psil-config##id {				\
+		linux,udma-mode = <UDMA_TR_MODE>;	\
+		statictr-type = <PSIL_STATIC_TR_XY>;	\
+	}
+
+#define UDMA_PDMA_PKT_XY(id)				\
+	ti,psil-config##id {				\
+		linux,udma-mode = <UDMA_PKT_MODE>;	\
+		statictr-type = <PSIL_STATIC_TR_XY>;	\
+	}
+
+#endif /* __DT_TI_UDMA_H */
diff --git a/include/linux/soc/ti/ti-udma.h b/include/linux/soc/ti/ti-udma.h
new file mode 100644
index 0000000..e9d4226
--- /dev/null
+++ b/include/linux/soc/ti/ti-udma.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *  Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com
+ *  Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
+ */
+
+#ifndef __TI_UDMA_H
+#define __TI_UDMA_H
+
+/**
+ * struct ti_udma_drv_packet_data - TI UDMA transfer specific data
+ *
+ * @pkt_type: Packet Type - specific for each DMA client HW
+ * @dest_tag: Destination tag The source pointer.
+ *
+ * TI UDMA transfer specific data passed as part of DMA transfer to
+ * the DMA client HW in UDMA descriptors.
+ */
+struct ti_udma_drv_packet_data {
+	u32	pkt_type;
+	u32	dest_tag;
+};
+
+#endif /* __TI_UDMA_H */
-- 
2.10.5

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

* [U-Boot] [NOT-FOR-MERGE-PATCH PATCH v7 5/5] net: ethernet: ti: introduce am654 gigabit eth switch subsystem driver
  2018-11-10 21:06 [U-Boot] [PATCH v7 0/5] dma: add channels support Grygorii Strashko
                   ` (3 preceding siblings ...)
  2018-11-10 21:06 ` [U-Boot] [NOT-FOR-MERGE-PATCH PATCH v7 4/5] dma: ti: add driver to K3 UDMA Grygorii Strashko
@ 2018-11-10 21:06 ` Grygorii Strashko
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
  5 siblings, 0 replies; 145+ messages in thread
From: Grygorii Strashko @ 2018-11-10 21:06 UTC (permalink / raw)
  To: u-boot

Add new driver for the TI AM65x SoC Gigabit Ethernet Switch subsystem (CPSW
NUSS). It has two ports and provides Ethernet packet communication for the
device and can be configured as an Ethernet switch. CPSW NUSS features: the
Reduced Gigabit Media Independent Interface (RGMII), Reduced Media
Independent Interface (RMII), and the Management Data Input/Output (MDIO)
interface for physical layer device (PHY) management. The TI AM65x SoC has
integrated two-port Gigabit Ethernet Switch subsystem into device MCU
domain named MCU_CPSW0. One Ethernet port (port 1) with selectable RGMII
and RMII interfaces and an internal Communications Port Programming
Interface (CPPI) port (Host port 0).

Host Port 0 CPPI Packet Streaming Interface interface supports 8 TX
channels and on RX channels operating by TI am654 NAVSS Unified DMA
Peripheral Root Complex (UDMA-P) controller.

Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
 drivers/net/Kconfig          |   8 +
 drivers/net/Makefile         |   1 +
 drivers/net/am65-cpsw-nuss.c | 962 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 971 insertions(+)
 create mode 100644 drivers/net/am65-cpsw-nuss.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index e2d5b97..3a45732 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -316,6 +316,14 @@ config SH_ETHER
 	help
 	  This driver supports the Ethernet for Renesas SH and ARM SoCs.
 
+config TI_AM65_CPSW_NUSS
+	bool "TI K3 AM65x MCU CPSW Nuss Ethernet controller driver"
+	depends on ARCH_K3
+	select PHYLIB
+	help
+	  This driver supports TI K3 MCU CPSW Nuss Ethernet controller
+	  in Texas Instruments K3 AM65x SoCs.
+
 config XILINX_AXIEMAC
 	depends on DM_ETH && (MICROBLAZE || ARCH_ZYNQ || ARCH_ZYNQMP)
 	select PHYLIB
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 8e33d7a..073fb3e 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -57,6 +57,7 @@ obj-$(CONFIG_SMC91111) += smc91111.o
 obj-$(CONFIG_SMC911X) += smc911x.o
 obj-$(CONFIG_TSEC_ENET) += tsec.o fsl_mdio.o
 obj-$(CONFIG_FMAN_ENET) += fsl_mdio.o
+obj-$(CONFIG_TI_AM65_CPSW_NUSS) += am65-cpsw-nuss.o
 obj-$(CONFIG_ULI526X) += uli526x.o
 obj-$(CONFIG_VSC7385_ENET) += vsc7385.o
 obj-$(CONFIG_XILINX_AXIEMAC) += xilinx_axi_emac.o
diff --git a/drivers/net/am65-cpsw-nuss.c b/drivers/net/am65-cpsw-nuss.c
new file mode 100644
index 0000000..e2761c9
--- /dev/null
+++ b/drivers/net/am65-cpsw-nuss.c
@@ -0,0 +1,962 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Texas Instruments K3 AM65 Ethernet Switch SubSystem Driver
+ *
+ * Copyright (C) 2018, Texas Instruments, Incorporated
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <clk.h>
+#include <dm.h>
+#include <dm/lists.h>
+#include <dma-uclass.h>
+#include <dm/of_access.h>
+#include <miiphy.h>
+#include <net.h>
+#include <phy.h>
+#include <power-domain.h>
+#include <linux/soc/ti/ti-udma.h>
+
+#define AM65_CPSW_CPSWNU_MAX_PORTS 2
+
+#define AM65_CPSW_SS_BASE		0x0
+#define AM65_CPSW_SGMII_BASE	0x100
+#define AM65_CPSW_MDIO_BASE	0xf00
+#define AM65_CPSW_XGMII_BASE	0x2100
+#define AM65_CPSW_CPSW_NU_BASE	0x20000
+#define AM65_CPSW_CPSW_NU_ALE_BASE 0x1e000
+
+#define AM65_CPSW_CPSW_NU_PORTS_OFFSET	0x1000
+#define AM65_CPSW_CPSW_NU_PORT_MACSL_OFFSET	0x330
+
+#define AM65_CPSW_MDIO_BUS_FREQ_DEF 1000000
+
+#define AM65_CPSW_CTL_REG			0x4
+#define AM65_CPSW_STAT_PORT_EN_REG	0x14
+#define AM65_CPSW_PTYPE_REG		0x18
+
+#define AM65_CPSW_CTL_REG_P0_ENABLE			BIT(2)
+#define AM65_CPSW_CTL_REG_P0_TX_CRC_REMOVE		BIT(13)
+#define AM65_CPSW_CTL_REG_P0_RX_PAD			BIT(14)
+
+#define AM65_CPSW_P0_FLOW_ID_REG			0x8
+#define AM65_CPSW_PN_RX_MAXLEN_REG		0x24
+#define AM65_CPSW_PN_REG_SA_L			0x308
+#define AM65_CPSW_PN_REG_SA_H			0x30c
+
+#define AM65_CPSW_ALE_CTL_REG			0x8
+#define AM65_CPSW_ALE_CTL_REG_ENABLE		BIT(31)
+#define AM65_CPSW_ALE_CTL_REG_RESET_TBL		BIT(30)
+#define AM65_CPSW_ALE_CTL_REG_BYPASS		BIT(4)
+#define AM65_CPSW_ALE_PN_CTL_REG(x)		(0x40 + (x) * 4)
+#define AM65_CPSW_ALE_PN_CTL_REG_MODE_FORWARD	0x3
+#define AM65_CPSW_ALE_PN_CTL_REG_MAC_ONLY	BIT(11)
+
+#define AM65_CPSW_MACSL_CTL_REG			0x0
+#define AM65_CPSW_MACSL_CTL_REG_IFCTL_A		BIT(15)
+#define AM65_CPSW_MACSL_CTL_REG_GIG		BIT(7)
+#define AM65_CPSW_MACSL_CTL_REG_GMII_EN		BIT(5)
+#define AM65_CPSW_MACSL_CTL_REG_LOOPBACK	BIT(1)
+#define AM65_CPSW_MACSL_CTL_REG_FULL_DUPLEX	BIT(0)
+#define AM65_CPSW_MACSL_RESET_REG		0x8
+#define AM65_CPSW_MACSL_RESET_REG_RESET		BIT(0)
+#define AM65_CPSW_MACSL_STATUS_REG		0x4
+#define AM65_CPSW_MACSL_RESET_REG_PN_IDLE	BIT(31)
+#define AM65_CPSW_MACSL_RESET_REG_PN_E_IDLE	BIT(30)
+#define AM65_CPSW_MACSL_RESET_REG_PN_P_IDLE	BIT(29)
+#define AM65_CPSW_MACSL_RESET_REG_PN_TX_IDLE	BIT(28)
+#define AM65_CPSW_MACSL_RESET_REG_IDLE_MASK \
+	(AM65_CPSW_MACSL_RESET_REG_PN_IDLE | \
+	 AM65_CPSW_MACSL_RESET_REG_PN_E_IDLE | \
+	 AM65_CPSW_MACSL_RESET_REG_PN_P_IDLE | \
+	 AM65_CPSW_MACSL_RESET_REG_PN_TX_IDLE)
+
+#define AM65_CPSW_CPPI_PKT_TYPE			0x7
+
+struct am65_cpsw_port {
+	fdt_addr_t	port_base;
+	fdt_addr_t	macsl_base;
+	bool		disabled;
+	u32		mac_control;
+};
+
+struct am65_cpsw_common {
+	struct udevice		*dev;
+	fdt_addr_t		ss_base;
+	fdt_addr_t		cpsw_base;
+	fdt_addr_t		mdio_base;
+	fdt_addr_t		ale_base;
+	fdt_addr_t		gmii_sel;
+	fdt_addr_t		mac_efuse;
+
+	struct clk		fclk;
+	struct power_domain	pwrdmn;
+
+	u32			port_num;
+	struct am65_cpsw_port	ports[AM65_CPSW_CPSWNU_MAX_PORTS];
+	u32			rflow_id_base;
+
+	struct mii_dev		*bus;
+	int			mdio_div;
+	u32			bus_freq;
+
+	struct dma		dma_tx;
+	struct dma		dma_rx;
+	u32			rx_next;
+	u32			rx_pend;
+	bool			started;
+};
+
+struct am65_cpsw_priv {
+	struct udevice		*dev;
+	struct am65_cpsw_common	*cpsw_common;
+	u32			port_id;
+
+	struct phy_device	*phydev;
+	bool			has_phy;
+	ofnode			phy_node;
+	u32			phy_addr;
+};
+
+#ifdef PKTSIZE_ALIGN
+#define UDMA_RX_BUF_SIZE PKTSIZE_ALIGN
+#else
+#define UDMA_RX_BUF_SIZE ALIGN(1522, ARCH_DMA_MINALIGN)
+#endif
+
+#ifdef PKTBUFSRX
+#define UDMA_RX_DESC_NUM PKTBUFSRX
+#else
+#define UDMA_RX_DESC_NUM 4
+#endif
+
+#ifdef AM65_CPSW_DEBUG
+#define	am65_cpsw_dbg(arg...) pr_err(arg)
+#define	am65_cpsw_dev_dbg(dev, arg...) dev_err(dev, arg)
+static void am65_cpsw_print_buf(ulong addr, const void *data, uint width,
+				uint count, uint linelen)
+{
+	print_buffer(addr, data, width, count, linelen);
+}
+#else
+#define	am65_cpsw_dbg(arg...)
+#define	am65_cpsw_dev_dbg(arg...)
+static void am65_cpsw_print_buf(ulong addr, const void *data, uint width,
+				uint count, uint linelen)
+{}
+#endif
+
+#define mac_hi(mac)	(((mac)[0] << 0) | ((mac)[1] << 8) |    \
+			 ((mac)[2] << 16) | ((mac)[3] << 24))
+#define mac_lo(mac)	(((mac)[4] << 0) | ((mac)[5] << 8))
+
+static void am65_cpsw_set_sl_mac(struct am65_cpsw_port *slave,
+				 unsigned char *addr)
+{
+	writel(mac_hi(addr),
+	       slave->port_base + AM65_CPSW_PN_REG_SA_H);
+	writel(mac_lo(addr),
+	       slave->port_base + AM65_CPSW_PN_REG_SA_L);
+}
+
+int am65_cpsw_macsl_reset(struct am65_cpsw_port *slave)
+{
+	u32 i = 100;
+
+	/* Set the soft reset bit */
+	writel(AM65_CPSW_MACSL_RESET_REG_RESET,
+	       slave->macsl_base + AM65_CPSW_MACSL_RESET_REG);
+
+	while ((readl(slave->macsl_base + AM65_CPSW_MACSL_RESET_REG) &
+		AM65_CPSW_MACSL_RESET_REG_RESET) && i--)
+		cpu_relax();
+
+	/* Timeout on the reset */
+	return i;
+}
+
+static int am65_cpsw_macsl_wait_for_idle(struct am65_cpsw_port *slave)
+{
+	u32 i = 100;
+
+	while ((readl(slave->macsl_base + AM65_CPSW_MACSL_STATUS_REG) &
+		AM65_CPSW_MACSL_RESET_REG_IDLE_MASK) && i--)
+		cpu_relax();
+
+	return i;
+}
+
+static int am65_cpsw_update_link(struct am65_cpsw_priv *priv)
+{
+	struct am65_cpsw_common	*common = priv->cpsw_common;
+	struct am65_cpsw_port *port = &common->ports[priv->port_id];
+	struct phy_device *phy = priv->phydev;
+	u32 mac_control = 0;
+
+	if (phy->link) { /* link up */
+		mac_control = /*AM65_CPSW_MACSL_CTL_REG_LOOPBACK |*/
+			      AM65_CPSW_MACSL_CTL_REG_GMII_EN;
+		if (phy->speed == 1000)
+			mac_control |= AM65_CPSW_MACSL_CTL_REG_GIG;
+		if (phy->duplex == DUPLEX_FULL)
+			mac_control |= AM65_CPSW_MACSL_CTL_REG_FULL_DUPLEX;
+		if (phy->speed == 100)
+			mac_control |= AM65_CPSW_MACSL_CTL_REG_IFCTL_A;
+	}
+
+	if (mac_control == port->mac_control)
+		goto out;
+
+	if (mac_control) {
+		printf("link up on port %d, speed %d, %s duplex\n",
+		       priv->port_id, phy->speed,
+		       (phy->duplex == DUPLEX_FULL) ? "full" : "half");
+	} else {
+		printf("link down on port %d\n", priv->port_id);
+	}
+
+	writel(mac_control, port->macsl_base + AM65_CPSW_MACSL_CTL_REG);
+	port->mac_control = mac_control;
+
+out:
+	return phy->link;
+}
+
+#define AM65_GMII_SEL_MODE_MII		0
+#define AM65_GMII_SEL_MODE_RMII		1
+#define AM65_GMII_SEL_MODE_RGMII	2
+
+#define AM65_GMII_SEL_RGMII_IDMODE	BIT(4)
+
+static void am65_cpsw_gmii_sel_k3(struct am65_cpsw_priv *priv,
+				  phy_interface_t phy_mode, int slave)
+{
+	struct am65_cpsw_common	*common = priv->cpsw_common;
+	u32 reg;
+	u32 mode = 0;
+	bool rgmii_id = false;
+
+	reg = readl(common->gmii_sel);
+
+	am65_cpsw_dev_dbg(common->dev, "old gmii_sel: %08x\n", reg);
+
+	switch (phy_mode) {
+	case PHY_INTERFACE_MODE_RMII:
+		mode = AM65_GMII_SEL_MODE_RMII;
+		break;
+
+	case PHY_INTERFACE_MODE_RGMII:
+		mode = AM65_GMII_SEL_MODE_RGMII;
+		break;
+
+	case PHY_INTERFACE_MODE_RGMII_ID:
+	case PHY_INTERFACE_MODE_RGMII_RXID:
+	case PHY_INTERFACE_MODE_RGMII_TXID:
+		mode = AM65_GMII_SEL_MODE_RGMII;
+		rgmii_id = true;
+		break;
+
+	default:
+		dev_warn(common->dev,
+			 "Unsupported PHY mode: %u. Defaulting to MII.\n",
+			 phy_mode);
+		/* fallthrough */
+	case PHY_INTERFACE_MODE_MII:
+		mode = AM65_GMII_SEL_MODE_MII;
+		break;
+	};
+
+	if (rgmii_id)
+		mode |= AM65_GMII_SEL_RGMII_IDMODE;
+
+	reg = mode;
+	am65_cpsw_dev_dbg(common->dev,
+			  "gmii_sel PHY mode: %u, new gmii_sel: %08x\n",
+			  phy_mode, reg);
+	writel(reg, common->gmii_sel);
+
+	reg = readl(common->gmii_sel);
+	if (reg != mode)
+		dev_err(common->dev,
+			"gmii_sel PHY mode NOT SET!: requested: %08x, gmii_sel: %08x\n",
+			mode, reg);
+}
+
+static int am65_cpsw_start(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct am65_cpsw_priv *priv = dev_get_priv(dev);
+	struct am65_cpsw_common	*common = priv->cpsw_common;
+	struct am65_cpsw_port *port = &common->ports[priv->port_id];
+	struct am65_cpsw_port *port0 = &common->ports[0];
+	int ret, i;
+
+	am65_cpsw_dev_dbg(dev, "%s\n", __func__);
+
+	ret = power_domain_on(&common->pwrdmn);
+	if (ret) {
+		dev_err(dev, "power_domain_on() failed %d\n", ret);
+		goto out;
+	}
+
+	ret = clk_enable(&common->fclk);
+	if (ret) {
+		dev_err(dev, "clk enabled failed %d\n", ret);
+		goto err_off_pwrdm;
+	}
+
+	common->rx_next = 0;
+	common->rx_pend = 0;
+	ret = dma_get_by_name(common->dev, "tx0", &common->dma_tx);
+	if (ret) {
+		dev_err(dev, "TX dma get failed %d\n", ret);
+		goto err_off_clk;
+	}
+	ret = dma_get_by_name(common->dev, "rx", &common->dma_rx);
+	if (ret) {
+		dev_err(dev, "RX dma get failed %d\n", ret);
+		goto err_free_tx;
+	}
+
+	for (i = 0; i < UDMA_RX_DESC_NUM; i++) {
+		ret = dma_prepare_rcv_buf(&common->dma_rx,
+					  net_rx_packets[i],
+					  UDMA_RX_BUF_SIZE);
+		if (ret) {
+			dev_err(dev, "RX dma add buf failed %d\n", ret);
+			goto err_free_tx;
+		}
+	}
+
+	ret = dma_enable(&common->dma_tx);
+	if (ret) {
+		dev_err(dev, "TX dma_enable failed %d\n", ret);
+		goto err_free_rx;
+	}
+	ret = dma_enable(&common->dma_rx);
+	if (ret) {
+		dev_err(dev, "RX dma_enable failed %d\n", ret);
+		goto err_dis_tx;
+	}
+
+	/* Control register */
+	writel(AM65_CPSW_CTL_REG_P0_ENABLE |
+	       AM65_CPSW_CTL_REG_P0_TX_CRC_REMOVE |
+	       AM65_CPSW_CTL_REG_P0_RX_PAD,
+	       common->cpsw_base + AM65_CPSW_CTL_REG);
+
+	/* disable priority elevation */
+	writel(0, common->cpsw_base + AM65_CPSW_PTYPE_REG);
+
+	/* enable statistics */
+	writel(BIT(0) | BIT(priv->port_id),
+	       common->cpsw_base + AM65_CPSW_STAT_PORT_EN_REG);
+
+	/* Port 0  length register */
+	writel(PKTSIZE_ALIGN, port0->port_base + AM65_CPSW_PN_RX_MAXLEN_REG);
+
+	/* set base flow_id */
+	writel(common->rflow_id_base,
+	       port0->port_base + AM65_CPSW_P0_FLOW_ID_REG);
+
+	/* Reset and enable the ALE */
+	writel(AM65_CPSW_ALE_CTL_REG_ENABLE | AM65_CPSW_ALE_CTL_REG_RESET_TBL |
+	       AM65_CPSW_ALE_CTL_REG_BYPASS,
+	       common->ale_base + AM65_CPSW_ALE_CTL_REG);
+
+	/* port 0 put into forward mode */
+	writel(AM65_CPSW_ALE_PN_CTL_REG_MODE_FORWARD,
+	       common->ale_base + AM65_CPSW_ALE_PN_CTL_REG(0));
+
+	/* PORT x configuration */
+
+	/* Port x Max length register */
+	writel(PKTSIZE_ALIGN, port->port_base + AM65_CPSW_PN_RX_MAXLEN_REG);
+
+	/* Port x set mac */
+	am65_cpsw_set_sl_mac(port, pdata->enetaddr);
+
+	/* Port x ALE: mac_only, Forwarding */
+	writel(AM65_CPSW_ALE_PN_CTL_REG_MAC_ONLY |
+	       AM65_CPSW_ALE_PN_CTL_REG_MODE_FORWARD,
+	       common->ale_base + AM65_CPSW_ALE_PN_CTL_REG(priv->port_id));
+
+	port->mac_control = 0;
+	if (!am65_cpsw_macsl_reset(port)) {
+		dev_err(dev, "mac_sl reset failed\n");
+		ret = -EFAULT;
+		goto err_dis_rx;
+	}
+
+	ret = phy_startup(priv->phydev);
+	if (ret) {
+		dev_err(dev, "phy_startup failed\n");
+		goto err_dis_rx;
+	}
+
+	ret = am65_cpsw_update_link(priv);
+	if (!ret) {
+		ret = -ENODEV;
+		goto err_phy_shutdown;
+	}
+
+	common->started = true;
+	am65_cpsw_dev_dbg(dev, "%s end\n", __func__);
+
+	return 0;
+
+err_phy_shutdown:
+	phy_shutdown(priv->phydev);
+err_dis_rx:
+	/* disable ports */
+	writel(0, common->ale_base + AM65_CPSW_ALE_PN_CTL_REG(priv->port_id));
+	writel(0, common->ale_base + AM65_CPSW_ALE_PN_CTL_REG(0));
+	if (!am65_cpsw_macsl_wait_for_idle(port))
+		dev_err(dev, "mac_sl idle timeout\n");
+	writel(0, port->macsl_base + AM65_CPSW_MACSL_CTL_REG);
+	writel(0, common->ale_base + AM65_CPSW_ALE_CTL_REG);
+	writel(0, common->cpsw_base + AM65_CPSW_CTL_REG);
+
+	dma_disable(&common->dma_rx);
+err_dis_tx:
+	dma_disable(&common->dma_tx);
+err_free_rx:
+	dma_free(&common->dma_rx);
+err_free_tx:
+	dma_free(&common->dma_tx);
+err_off_clk:
+	clk_disable(&common->fclk);
+err_off_pwrdm:
+	power_domain_off(&common->pwrdmn);
+out:
+	am65_cpsw_dev_dbg(dev, "%s end error\n", __func__);
+
+	return ret;
+}
+
+static int am65_cpsw_send(struct udevice *dev, void *packet, int length)
+{
+	struct am65_cpsw_priv *priv = dev_get_priv(dev);
+	struct am65_cpsw_common	*common = priv->cpsw_common;
+	struct ti_udma_drv_packet_data packet_data;
+	int ret;
+
+	am65_cpsw_dev_dbg(dev, "%s\n", __func__);
+
+	am65_cpsw_print_buf((ulong)packet, packet, 1, length, 0);
+
+	packet_data.pkt_type = AM65_CPSW_CPPI_PKT_TYPE;
+	packet_data.dest_tag = priv->port_id;
+	ret = dma_send(&common->dma_tx, packet, length, &packet_data);
+	if (ret) {
+		dev_err(dev, "TX dma_send failed %d\n", ret);
+		return ret;
+	}
+
+	am65_cpsw_dev_dbg(dev, "%s end\n", __func__);
+
+	return 0;
+}
+
+static int am65_cpsw_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct am65_cpsw_priv *priv = dev_get_priv(dev);
+	struct am65_cpsw_common	*common = priv->cpsw_common;
+	int ret;
+
+	/* try to receive a new packet */
+	ret = dma_receive(&common->dma_rx, (void **)packetp, NULL);
+	if (ret > 0)
+		am65_cpsw_print_buf((ulong)(*packetp),
+				    *packetp, 1, ret, 0);
+
+	return ret;
+}
+
+static int am65_cpsw_free_pkt(struct udevice *dev, uchar *packet, int length)
+{
+	struct am65_cpsw_priv *priv = dev_get_priv(dev);
+	struct am65_cpsw_common	*common = priv->cpsw_common;
+	int ret;
+
+	if (length > 0) {
+		u32 pkt = common->rx_next % UDMA_RX_DESC_NUM;
+
+		am65_cpsw_dev_dbg(dev, "%s length:%d pkt:%u\n",
+				  __func__, length, pkt);
+
+		ret = dma_prepare_rcv_buf(&common->dma_rx,
+					  net_rx_packets[pkt],
+					  UDMA_RX_BUF_SIZE);
+		if (ret)
+			dev_err(dev, "RX dma free_pkt failed %d\n", ret);
+		common->rx_next++;
+
+	}
+
+	return 0;
+}
+
+static void am65_cpsw_stop(struct udevice *dev)
+{
+	struct am65_cpsw_priv *priv = dev_get_priv(dev);
+	struct am65_cpsw_common *common = priv->cpsw_common;
+	struct am65_cpsw_port *port = &common->ports[priv->port_id];
+
+	if (!common->started)
+		return;
+
+	phy_shutdown(priv->phydev);
+
+	writel(0, common->ale_base + AM65_CPSW_ALE_PN_CTL_REG(priv->port_id));
+	writel(0, common->ale_base + AM65_CPSW_ALE_PN_CTL_REG(0));
+	if (!am65_cpsw_macsl_wait_for_idle(port))
+		dev_err(dev, "mac_sl idle timeout\n");
+	writel(0, port->macsl_base + AM65_CPSW_MACSL_CTL_REG);
+	writel(0, common->ale_base + AM65_CPSW_ALE_CTL_REG);
+	writel(0, common->cpsw_base + AM65_CPSW_CTL_REG);
+
+	dma_disable(&common->dma_tx);
+	dma_free(&common->dma_tx);
+
+	dma_disable(&common->dma_rx);
+	dma_free(&common->dma_rx);
+
+	common->started = false;
+}
+
+static int am65_cpsw_read_rom_hwaddr(struct udevice *dev)
+{
+	struct am65_cpsw_priv *priv = dev_get_priv(dev);
+	struct am65_cpsw_common *common = priv->cpsw_common;
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	u32 mac_hi, mac_lo;
+
+	if (common->mac_efuse == FDT_ADDR_T_NONE)
+		return -1;
+
+	mac_lo = readl(common->mac_efuse);
+	mac_hi = readl(common->mac_efuse + 4);
+	pdata->enetaddr[0] = (mac_hi >> 8) & 0xff;
+	pdata->enetaddr[1] = mac_hi & 0xff;
+	pdata->enetaddr[2] = (mac_lo >> 24) & 0xff;
+	pdata->enetaddr[3] = (mac_lo >> 16) & 0xff;
+	pdata->enetaddr[4] = (mac_lo >> 8) & 0xff;
+	pdata->enetaddr[5] = mac_lo & 0xff;
+
+	return 0;
+}
+
+static const struct eth_ops am65_cpsw_ops = {
+	.start		= am65_cpsw_start,
+	.send		= am65_cpsw_send,
+	.recv		= am65_cpsw_recv,
+	.free_pkt	= am65_cpsw_free_pkt,
+	.stop		= am65_cpsw_stop,
+	.read_rom_hwaddr = am65_cpsw_read_rom_hwaddr,
+};
+
+#define PHY_REG_MASK		0x1f
+#define PHY_ID_MASK		0x1f
+
+#define MDIO_CONTROL_MAX_DIV	0xffff
+
+#define MDIO_TIMEOUT            100 /* msecs */
+struct cpsw_mdio_regs {
+	u32	version;
+	u32	control;
+#define CONTROL_IDLE		BIT(31)
+#define CONTROL_ENABLE		BIT(30)
+
+	u32	alive;
+	u32	link;
+	u32	linkintraw;
+	u32	linkintmasked;
+	u32	__reserved_0[2];
+	u32	userintraw;
+	u32	userintmasked;
+	u32	userintmaskset;
+	u32	userintmaskclr;
+	u32	__reserved_1[20];
+
+	struct {
+		u32		access;
+		u32		physel;
+#define USERACCESS_GO		BIT(31)
+#define USERACCESS_WRITE	BIT(30)
+#define USERACCESS_ACK		BIT(29)
+#define USERACCESS_READ		(0)
+#define USERACCESS_DATA		(0xffff)
+	} user[0];
+};
+
+/* wait until hardware is ready for another user access */
+static inline u32 am65_cpsw_mdio_wait_for_user_access(
+			struct cpsw_mdio_regs *mdio_regs)
+{
+	u32 reg = 0;
+	int timeout = MDIO_TIMEOUT;
+
+	while (timeout-- &&
+	       ((reg = __raw_readl(&mdio_regs->user[0].access)) &
+	       USERACCESS_GO))
+		udelay(10);
+
+	if (timeout == -1) {
+		printf("wait_for_user_access Timeout\n");
+		return -ETIMEDOUT;
+	}
+
+	return reg;
+}
+
+static int am65_cpsw_mdio_read(struct mii_dev *bus, int phy_id,
+			       int dev_addr, int phy_reg)
+{
+	struct am65_cpsw_common *cpsw_common = bus->priv;
+	struct cpsw_mdio_regs *mdio_regs;
+	int data;
+	u32 reg;
+
+	mdio_regs = (struct cpsw_mdio_regs *)cpsw_common->mdio_base;
+
+	if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
+		return -EINVAL;
+
+	am65_cpsw_mdio_wait_for_user_access(mdio_regs);
+	reg = (USERACCESS_GO | USERACCESS_READ | (phy_reg << 21) |
+	       (phy_id << 16));
+	__raw_writel(reg, &mdio_regs->user[0].access);
+	reg = am65_cpsw_mdio_wait_for_user_access(mdio_regs);
+
+	data = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -1;
+	return data;
+}
+
+static int am65_cpsw_mdio_write(struct mii_dev *bus, int phy_id, int dev_addr,
+				int phy_reg, u16 data)
+{
+	struct am65_cpsw_common *cpsw_common = bus->priv;
+	struct cpsw_mdio_regs *mdio_regs;
+	u32 reg;
+
+	mdio_regs = (struct cpsw_mdio_regs *)cpsw_common->mdio_base;
+
+	if ((phy_reg & ~PHY_REG_MASK) || (phy_id & ~PHY_ID_MASK))
+		return -EINVAL;
+
+	am65_cpsw_mdio_wait_for_user_access(mdio_regs);
+	reg = (USERACCESS_GO | USERACCESS_WRITE | (phy_reg << 21) |
+		   (phy_id << 16) | (data & USERACCESS_DATA));
+	__raw_writel(reg, &mdio_regs->user[0].access);
+	am65_cpsw_mdio_wait_for_user_access(mdio_regs);
+
+	return 0;
+}
+
+static int am65_cpsw_mdio_init(struct udevice *dev)
+{
+	struct am65_cpsw_priv *priv = dev_get_priv(dev);
+	struct am65_cpsw_common	*cpsw_common = priv->cpsw_common;
+	struct mii_dev *bus;
+	struct cpsw_mdio_regs *mdio_regs;
+
+	if (!priv->has_phy || cpsw_common->bus)
+		return 0;
+
+	bus = mdio_alloc();
+	if (!bus)
+		return -ENOMEM;
+
+	mdio_regs = (struct cpsw_mdio_regs *)cpsw_common->mdio_base;
+
+	/* set enable and clock divider */
+	writel(cpsw_common->mdio_div | CONTROL_ENABLE, &mdio_regs->control);
+
+	/*
+	 * wait for scan logic to settle:
+	 * the scan time consists of (a) a large fixed component, and (b) a
+	 * small component that varies with the mii bus frequency.  These
+	 * were estimated using measurements at 1.1 and 2.2 MHz on tnetv107x
+	 * silicon.  Since the effect of (b) was found to be largely
+	 * negligible, we keep things simple here.
+	 */
+	udelay(1000);
+
+	bus->read = am65_cpsw_mdio_read;
+	bus->write = am65_cpsw_mdio_write;
+	strcpy(bus->name, dev->name);
+	bus->priv = cpsw_common;
+
+	if (mdio_register(bus))
+		return -EINVAL;
+	cpsw_common->bus = miiphy_get_dev_by_name(dev->name);
+
+	return 0;
+}
+
+static int am65_cpsw_phy_init(struct udevice *dev)
+{
+	struct am65_cpsw_priv *priv = dev_get_priv(dev);
+	struct am65_cpsw_common *cpsw_common = priv->cpsw_common;
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct phy_device *phydev;
+	u32 supported = PHY_GBIT_FEATURES;
+	int ret;
+
+	am65_cpsw_dev_dbg(dev, "%s\n", __func__);
+
+	phydev = phy_connect(cpsw_common->bus,
+			     priv->phy_addr,
+			     priv->dev,
+			     pdata->phy_interface);
+
+	if (!phydev) {
+		dev_err(dev, "phy_connect() failed\n");
+		return -ENODEV;
+	}
+
+	phydev->supported &= supported;
+	if (pdata->max_speed) {
+		ret = phy_set_supported(phydev, pdata->max_speed);
+		if (ret)
+			return ret;
+	}
+	phydev->advertising = phydev->supported;
+
+#ifdef CONFIG_DM_ETH
+	if (ofnode_valid(priv->phy_node))
+		phydev->node = priv->phy_node;
+#endif
+
+	priv->phydev = phydev;
+	ret = phy_config(phydev);
+	if (ret < 0)
+		pr_err("phy_config() failed: %d", ret);
+
+	am65_cpsw_dev_dbg(dev, "%s end\n", __func__);
+	return ret;
+}
+
+static int am65_cpsw_ofdata_parse_phy(struct udevice *dev, ofnode port_np)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct am65_cpsw_priv *priv = dev_get_priv(dev);
+	struct ofnode_phandle_args out_args;
+	const char *phy_mode;
+	int ret = 0;
+
+	phy_mode = ofnode_read_string(port_np, "phy-mode");
+	if (phy_mode) {
+		pdata->phy_interface =
+				phy_get_interface_by_name(phy_mode);
+		if (pdata->phy_interface == -1) {
+			dev_err(dev, "Invalid PHY mode '%s', port %u\n",
+				phy_mode, priv->port_id);
+			ret = -EINVAL;
+			goto out;
+		}
+	}
+
+	ofnode_read_u32(port_np, "max-speed", (u32 *)&pdata->max_speed);
+	if (pdata->max_speed)
+		dev_err(dev, "Port %u speed froced to %uMbit\n",
+			priv->port_id, pdata->max_speed);
+
+	priv->has_phy  = true;
+	ret = ofnode_parse_phandle_with_args(port_np, "phy-handle",
+					     NULL, 0, 0, &out_args);
+	if (ret) {
+		dev_err(dev, "can't parse phy-handle port %u (%d)\n",
+			priv->port_id, ret);
+		priv->has_phy  = false;
+		ret = 0;
+	}
+
+	priv->phy_node = out_args.node;
+	priv->phy_addr = PHY_REG_MASK + 1;
+	if (priv->has_phy) {
+		ret = ofnode_read_u32(priv->phy_node, "reg", &priv->phy_addr);
+		if (ret) {
+			dev_err(dev, "failed to get phy_addr port %u (%d)\n",
+				priv->port_id, ret);
+			goto out;
+		}
+	}
+
+out:
+	return ret;
+}
+
+static int am65_cpsw_probe_cpsw(struct udevice *dev)
+{
+	struct am65_cpsw_priv *priv = dev_get_priv(dev);
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct am65_cpsw_common *cpsw_common;
+	ofnode ports_np, node;
+	int ret, i;
+
+	priv->dev = dev;
+
+	cpsw_common = calloc(1, sizeof(*priv->cpsw_common));
+	if (!cpsw_common)
+		return -ENOMEM;
+	priv->cpsw_common = cpsw_common;
+
+	cpsw_common->dev = dev;
+	cpsw_common->ss_base = dev_read_addr(dev);
+	if (cpsw_common->ss_base == FDT_ADDR_T_NONE)
+		return -EINVAL;
+	cpsw_common->mac_efuse = devfdt_get_addr_name(dev, "mac_efuse");
+	/* no err check - optional */
+
+	ret = power_domain_get_by_index(dev, &cpsw_common->pwrdmn, 0);
+	if (ret) {
+		dev_err(dev, "failed to get pwrdmn: %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_get_by_name(dev, "fck", &cpsw_common->fclk);
+	if (ret) {
+		power_domain_free(&cpsw_common->pwrdmn);
+		dev_err(dev, "failed to get clock %d\n", ret);
+		return ret;
+	}
+
+	cpsw_common->cpsw_base = cpsw_common->ss_base + AM65_CPSW_CPSW_NU_BASE;
+	cpsw_common->ale_base = cpsw_common->cpsw_base +
+				AM65_CPSW_CPSW_NU_ALE_BASE;
+	cpsw_common->mdio_base = cpsw_common->ss_base + AM65_CPSW_MDIO_BASE;
+
+	cpsw_common->rflow_id_base = 0;
+	cpsw_common->rflow_id_base =
+			dev_read_u32_default(dev, "ti,rx-flow-id-base",
+					     cpsw_common->rflow_id_base);
+
+	ports_np = dev_read_subnode(dev, "ports");
+	if (!ofnode_valid(ports_np)) {
+		ret = -ENOENT;
+		goto out;
+	}
+
+	ofnode_for_each_subnode(node, ports_np) {
+		const char *node_name;
+		u32 port_id;
+		bool disabled;
+
+		node_name = ofnode_get_name(node);
+
+		disabled = !ofnode_is_available(node);
+
+		ret = ofnode_read_u32(node, "reg", &port_id);
+		if (ret) {
+			dev_err(dev, "%s: failed to get port_id (%d)\n",
+				node_name, ret);
+			goto out;
+		}
+
+		if (port_id >= AM65_CPSW_CPSWNU_MAX_PORTS) {
+			dev_err(dev, "%s: invalid port_id (%d)\n",
+				node_name, port_id);
+			ret = -EINVAL;
+			goto out;
+		}
+		cpsw_common->port_num++;
+
+		if (!port_id)
+			continue;
+
+		priv->port_id = port_id;
+		cpsw_common->ports[port_id].disabled = disabled;
+		if (disabled)
+			continue;
+
+		ret = am65_cpsw_ofdata_parse_phy(dev, node);
+		if (ret)
+			goto out;
+	}
+
+	for (i = 0; i < AM65_CPSW_CPSWNU_MAX_PORTS; i++) {
+		struct am65_cpsw_port *port = &cpsw_common->ports[i];
+
+		port->port_base = cpsw_common->cpsw_base +
+				  AM65_CPSW_CPSW_NU_PORTS_OFFSET +
+				  (i * AM65_CPSW_CPSW_NU_PORTS_OFFSET);
+		port->macsl_base = port->port_base +
+				   AM65_CPSW_CPSW_NU_PORT_MACSL_OFFSET;
+	}
+
+	node = dev_read_subnode(dev, "cpsw-phy-sel");
+	if (!ofnode_valid(node)) {
+		dev_err(dev, "can't find cpsw-phy-se\n");
+		ret = -ENOENT;
+		goto out;
+	}
+
+	cpsw_common->gmii_sel = ofnode_get_addr(node);
+	if (cpsw_common->gmii_sel == FDT_ADDR_T_NONE) {
+		dev_err(dev, "failed to get gmii_sel base\n");
+		goto out;
+	}
+
+	node = dev_read_subnode(dev, "mdio");
+	if (!ofnode_valid(node)) {
+		dev_err(dev, "can't find mdio\n");
+		ret = -ENOENT;
+		goto out;
+	}
+
+	cpsw_common->bus_freq =
+			dev_read_u32_default(dev, "bus_freq",
+					     AM65_CPSW_MDIO_BUS_FREQ_DEF);
+
+	/* calc mdio div using fclk freq */
+	cpsw_common->mdio_div = clk_get_rate(&cpsw_common->fclk);
+	cpsw_common->mdio_div = (cpsw_common->mdio_div /
+				 cpsw_common->bus_freq) - 1;
+	if (cpsw_common->mdio_div > MDIO_CONTROL_MAX_DIV)
+		cpsw_common->mdio_div = MDIO_CONTROL_MAX_DIV;
+
+	am65_cpsw_gmii_sel_k3(priv, pdata->phy_interface, priv->port_id);
+
+	ret = am65_cpsw_mdio_init(dev);
+	if (ret)
+		goto out;
+
+	ret = am65_cpsw_phy_init(dev);
+	if (ret)
+		goto out;
+
+	dev_info(dev, "K3 CPSW: nuss_ver: 0x%08X cpsw_ver: 0x%08X ale_ver: 0x%08X Ports:%u rflow_id_base:%u mdio_freq:%u\n",
+		 readl(cpsw_common->ss_base),
+		 readl(cpsw_common->cpsw_base),
+		 readl(cpsw_common->ale_base),
+		 cpsw_common->port_num,
+		 cpsw_common->rflow_id_base,
+		 cpsw_common->bus_freq);
+
+out:
+	clk_free(&cpsw_common->fclk);
+	power_domain_free(&cpsw_common->pwrdmn);
+	am65_cpsw_dev_dbg(dev, "%s end %d\n", __func__, ret);
+	return ret;
+}
+
+static const struct udevice_id am65_cpsw_nuss_ids[] = {
+	{ .compatible = "ti,am654-cpsw-nuss" },
+	{ }
+};
+
+U_BOOT_DRIVER(am65_cpsw_nuss_slave) = {
+	.name	= "am65_cpsw_nuss_slave",
+	.id	= UCLASS_ETH,
+	.of_match = am65_cpsw_nuss_ids,
+	.probe	= am65_cpsw_probe_cpsw,
+	.ops	= &am65_cpsw_ops,
+	.priv_auto_alloc_size = sizeof(struct am65_cpsw_priv),
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+	.flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
-- 
2.10.5

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

* [U-Boot] [PATCH v7 3/5] test: dma: add dma-uclass test
  2018-11-10 21:06 ` [U-Boot] [PATCH v7 3/5] test: dma: add dma-uclass test Grygorii Strashko
@ 2018-11-13 19:53   ` Simon Glass
  0 siblings, 0 replies; 145+ messages in thread
From: Simon Glass @ 2018-11-13 19:53 UTC (permalink / raw)
  To: u-boot

On 10 November 2018 at 13:06, Grygorii Strashko
<grygorii.strashko@ti.com> wrote:
> Add a sandbox DMA driver implementation (provider) and corresponding DM
> test.
>
> Reviewed-by: Tom Rini <trini@konsulko.com>
> Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
> ---
>  arch/sandbox/dts/test.dts      |   8 ++
>  configs/sandbox_defconfig      |   3 +
>  drivers/dma/Kconfig            |   7 +
>  drivers/dma/Makefile           |   1 +
>  drivers/dma/sandbox-dma-test.c | 282 +++++++++++++++++++++++++++++++++++++++++
>  test/dm/Makefile               |   1 +
>  test/dm/dma.c                  | 123 ++++++++++++++++++
>  7 files changed, 425 insertions(+)
>  create mode 100644 drivers/dma/sandbox-dma-test.c
>  create mode 100644 test/dm/dma.c

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

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

* [U-Boot] [PATCH v7 2/5] dma: add channels support
  2018-11-10 21:06 ` [U-Boot] [PATCH v7 2/5] dma: add channels support Grygorii Strashko
@ 2018-11-13 19:53   ` Simon Glass
  0 siblings, 0 replies; 145+ messages in thread
From: Simon Glass @ 2018-11-13 19:53 UTC (permalink / raw)
  To: u-boot

On 10 November 2018 at 13:06, Grygorii Strashko
<grygorii.strashko@ti.com> wrote:
> From: Álvaro Fernández Rojas <noltari@gmail.com>
>
> This adds channels support for dma controllers that have multiple channels
> which can transfer data to/from different devices (enet, usb...).
>
> DMA channle API:
>  dma_get_by_index()
>  dma_get_by_name()
>  dma_request()
>  dma_free()
>  dma_enable()
>  dma_disable()
>  dma_prepare_rcv_buf()
>  dma_receive()
>  dma_send()
>
> Reviewed-by: Tom Rini <trini@konsulko.com>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> [grygorii.strashko at ti.com: drop unused dma_get_by_index_platdata(),
>  add metadata to send/receive ops, add dma_prepare_rcv_buf(),
>  minor clean up]
> Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
> ---
>  drivers/dma/Kconfig      |   7 ++
>  drivers/dma/dma-uclass.c | 181 ++++++++++++++++++++++++++++++++-
>  include/dma-uclass.h     |  91 ++++++++++++++++-
>  include/dma.h            | 260 ++++++++++++++++++++++++++++++++++++++++++++++-
>  4 files changed, 532 insertions(+), 7 deletions(-)

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

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

* [U-Boot] [PATCH v8 00/31] dma: add channels support
  2018-11-10 21:06 [U-Boot] [PATCH v7 0/5] dma: add channels support Grygorii Strashko
                   ` (4 preceding siblings ...)
  2018-11-10 21:06 ` [U-Boot] [NOT-FOR-MERGE-PATCH PATCH v7 5/5] net: ethernet: ti: introduce am654 gigabit eth switch subsystem driver Grygorii Strashko
@ 2018-11-26 18:00 ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 01/31] dma: move dma_ops to dma-uclass.h Álvaro Fernández Rojas
                     ` (33 more replies)
  5 siblings, 34 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

In order to add bcm6348-enet support, dma-uclass must be extended to support
dma channels and reworked to operate like the other dm uclass (clk, reset...).

===

A DMA is a feature of computer systems that allows certain hardware
subsystems to access main system memory, independent of the CPU.
DMA channels are typically generated externally to the HW module
consuming them, by an entity this API calls a DMA provider. This API
provides a standard means for drivers to enable and disable DMAs, and to
copy, send and receive data using DMA.

DMA channel API:
 dma_get_by_index()
 dma_get_by_name()
 dma_request()
 dma_free()
 dma_enable()
 dma_disable()
 dma_prepare_rcv_buf()
 dma_receive()
 dma_send()

A driver that implements UCLASS_DMA is a DMA provider. A provider will
often implement multiple separate DMAs channels, since the hardware it manages
often has this capability. dma_uclass.h describes the interface which
DMA providers must implement.

DMA consumers/clients are the HW modules driven by the DMA channels. 

DMA consumer DMA_MEM_TO_DEV (transmit) usage example (based on networking).
Note. In u-boot dma_send() is sync operation always - it'll start transfer and
will poll for it to complete:
- get/request dma channel
	struct dma dma_tx;
	ret = dma_get_by_name(common->dev, "tx0", &dma_tx);
	if (ret) ...

- enable dma channel
	ret = dma_enable(&dma_tx);
	if (ret) ...

- dma transmit DMA_MEM_TO_DEV.
	struct ti_drv_packet_data packet_data;
	
	packet_data.opt1 = val1;
	packet_data.opt2 = val2;
	ret = dma_send(&dma_tx, packet, length, &packet_data);
	if (ret) ..

DMA consumer DMA_DEV_TO_MEM (receive) usage example (based on networking).
Note. dma_receive() is sync operation always - it'll start transfer
(if required) and will poll for it to complete (or for any previously
configured dev2mem transfer to complete):
- get/request dma channel
	struct dma dma_rx;
	ret = dma_get_by_name(common->dev, "rx0", &dma_rx);
	if (ret) ...

- enable dma channel
	ret = dma_enable(&dma_rx);
	if (ret) ...

- dma receive DMA_DEV_TO_MEM.
	struct ti_drv_packet_data packet_data;
	
	len = dma_receive(&dma_rx, (void **)packet, &packet_data);
	if (ret < 0) ...

DMA consumer DMA_DEV_TO_MEM (receive) zero-copy usage example (based on
networking). Networking subsystem allows to configure and use few receive
buffers (dev2mem), as Networking RX DMA channels usually implemented
as streaming interface
- get/request dma channel
	struct dma dma_rx;
	ret = dma_get_by_name(common->dev, "rx0", &dma_rx);
	if (ret) ...
	
	for (i = 0; i < RX_DESC_NUM; i++) {
		ret = dma_prepare_rcv_buf(&dma_rx,
					  net_rx_packets[i],
					  RX_BUF_SIZE);
		if (ret) ...
	}

- enable dma channel
	ret = dma_enable(&dma_rx);
	if (ret) ...

- dma receive DMA_DEV_TO_MEM.
	struct ti_drv_packet_data packet_data;
	void *packet;
	
	len = dma_receive(&dma_rx, &packet, &packet_data);
	if (ret < 0) ..
	
	/* packet - points on buffer prepared by dma_prepare_rcv_buf().
	   process packet*/
	
	- return buffer back to DAM channel
	ret = dma_prepare_rcv_buf(&dma_rx,
				  net_rx_packets[rx_next],
				  RX_BUF_SIZE);

===

v8: Adopt changes introduced by Grygorii Strashko:
 - Sync with latest u-boot.
 - Introduce bcm6368-enet driver support.
v7: From Grygorii Strashko:
 - copyright fixed as suggested by Tom Rini
 - added "Reviewed-by" tags
v6: From Grygorii Strashko:
 - added possibility to pass DMA driver/channel's specific data per each
 transfer using additional parameter "metadata" in dma_send/dma_receive() API.
 For example, port number for network packets to be directed to the
 specific port on multi port ethernet controllers.
 - added new dma_prepare_rcv_buf() API which allows to implement zero-copy
 DEV_TO_MEM transfer using DMA streaming channels which is usual case
 for Networking.
 - added dma-uclass test
 - removed unused function dma_get_by_index_platdata()
 - updated comments
v5: Fix issues reported by Grygorii Strashko and other fixes:
 - Fix build of ti-edma3.
 - Remove unused bcm6348-iudma defines.
 - Increment bcm6348-iudma rx descriptors.
 - Fix bcm6348-iudma flow control issues.
 - bcm6348-iudma error checking now depends on hw.
 - Remove unneeded bcm6348-iudma interrupts.
 - Receive as much packets as possible from bcm6348-eth and cache them in
 net_rx_packets. This is needed in order to fix flow control issues.
v4: Fix issues reported by Grygorii Strashko and other fixes:
 - Remove usage of net_rx_packets as buffer from bcm6348-iudma.
 - Allocate dynamic rx buffer on bcm6348-iudma.
 - Copy received dma buffer to net_rx_packets in order to avoid possible
 dma overwrites.
 - Check dma errors and discard invalid packets.
 - Reset dma rx channel when sending a new packet to prevent flow control
 issues.
 - Fix packet casting on bcm6348_eth_recv/send.
v3: Introduce changes reported by Simon Glass:
 - Improve dma-uclass.h documentation.
 - Switch to live tree API.
v2: Introduce changes reported by Vignesh:
 - Respect current dma implementation.
 - Let dma_memcpy find a compatible dma device.
Other changes:
 - Fix bcm6348-iudma rx burst config.

Grygorii Strashko (1):
  test: dma: add dma-uclass test

Álvaro Fernández Rojas (30):
  dma: move dma_ops to dma-uclass.h
  dma: add channels support
  dma: add bcm6348-iudma support
  bmips: bcm6338: add bcm6348-iudma support
  bmips: bcm6348: add bcm6348-iudma support
  bmips: bcm6358: add bcm6348-iudma support
  bmips: bcm6368: add bcm6348-iudma support
  bmips: bcm6328: add bcm6348-iudma support
  bmips: bcm6362: add bcm6348-iudma support
  bmips: bcm63268: add bcm6348-iudma support
  bmips: bcm6318: add bcm6348-iudma support
  net: add support for bcm6348-enet
  bmips: bcm6338: add support for bcm6348-enet
  bmips: enable f at st1704 enet support
  bmips: bcm6348: add support for bcm6348-enet
  bmips: enable ct-5361 enet support
  bmips: bcm6358: add support for bcm6348-enet
  bmips: enable hg556a enet support
  bmips: enable nb4-ser enet support
  net: add support for bcm6368-enet
  bmips: bcm6368: add support for bcm6368-enet
  bmips: enable wap-5813n enet support
  bmips: bcm6328: add support for bcm6368-enet
  bmips: enable ar-5387un enet support
  bmips: bcm6362: add support for bcm6368-enet
  bmips: enable dgnd3700v2 enet support
  bmips: bcm63268: add support for bcm6368-enet
  bmips: enable vr-3032u enet support
  bmips: bcm6318: add support for bcm6368-enet
  bmips: enable ar-5315u enet support

 arch/mips/dts/brcm,bcm6318.dtsi           |  38 ++
 arch/mips/dts/brcm,bcm63268.dtsi          |  38 ++
 arch/mips/dts/brcm,bcm6328.dtsi           |  30 ++
 arch/mips/dts/brcm,bcm6338.dtsi           |  29 ++
 arch/mips/dts/brcm,bcm6348.dtsi           |  42 +++
 arch/mips/dts/brcm,bcm6358.dtsi           |  46 +++
 arch/mips/dts/brcm,bcm6362.dtsi           |  32 ++
 arch/mips/dts/brcm,bcm6368.dtsi           |  32 ++
 arch/mips/dts/comtrend,ar-5315u.dts       |  32 ++
 arch/mips/dts/comtrend,ar-5387un.dts      |  32 ++
 arch/mips/dts/comtrend,ct-5361.dts        |  12 +
 arch/mips/dts/comtrend,vr-3032u.dts       |  32 ++
 arch/mips/dts/comtrend,wap-5813n.dts      |  14 +
 arch/mips/dts/huawei,hg556a.dts           |  12 +
 arch/mips/dts/netgear,dgnd3700v2.dts      |  14 +
 arch/mips/dts/sagem,f at st1704.dts          |  12 +
 arch/mips/dts/sfr,nb4-ser.dts             |  24 ++
 arch/sandbox/dts/test.dts                 |   8 +
 configs/comtrend_ar5315u_ram_defconfig    |   7 +-
 configs/comtrend_ar5387un_ram_defconfig   |   7 +-
 configs/comtrend_ct5361_ram_defconfig     |   8 +-
 configs/comtrend_vr3032u_ram_defconfig    |   7 +-
 configs/comtrend_wap5813n_ram_defconfig   |   8 +-
 configs/huawei_hg556a_ram_defconfig       |   8 +-
 configs/netgear_dgnd3700v2_ram_defconfig  |   8 +-
 configs/sagem_f@st1704_ram_defconfig      |   8 +-
 configs/sandbox_defconfig                 |   3 +
 configs/sfr_nb4-ser_ram_defconfig         |   8 +-
 drivers/dma/Kconfig                       |  23 ++
 drivers/dma/Makefile                      |   2 +
 drivers/dma/bcm6348-iudma.c               | 533 ++++++++++++++++++++++++++
 drivers/dma/dma-uclass.c                  | 183 ++++++++-
 drivers/dma/sandbox-dma-test.c            | 282 ++++++++++++++
 drivers/dma/ti-edma3.c                    |   2 +-
 drivers/net/Kconfig                       |  18 +
 drivers/net/Makefile                      |   2 +
 drivers/net/bcm6348-eth.c                 | 576 ++++++++++++++++++++++++++++
 drivers/net/bcm6368-eth.c                 | 604 ++++++++++++++++++++++++++++++
 include/configs/bmips_common.h            |   5 +-
 include/dma-uclass.h                      | 128 +++++++
 include/dma.h                             | 282 ++++++++++++--
 include/dt-bindings/clock/bcm6318-clock.h |  11 +
 include/dt-bindings/dma/bcm6318-dma.h     |  15 +
 include/dt-bindings/dma/bcm63268-dma.h    |  15 +
 include/dt-bindings/dma/bcm6328-dma.h     |  15 +
 include/dt-bindings/dma/bcm6338-dma.h     |  15 +
 include/dt-bindings/dma/bcm6348-dma.h     |  17 +
 include/dt-bindings/dma/bcm6358-dma.h     |  17 +
 include/dt-bindings/dma/bcm6362-dma.h     |  15 +
 include/dt-bindings/dma/bcm6368-dma.h     |  15 +
 test/dm/Makefile                          |   1 +
 test/dm/dma.c                             | 123 ++++++
 52 files changed, 3410 insertions(+), 40 deletions(-)
 create mode 100644 drivers/dma/bcm6348-iudma.c
 create mode 100644 drivers/dma/sandbox-dma-test.c
 create mode 100644 drivers/net/bcm6348-eth.c
 create mode 100644 drivers/net/bcm6368-eth.c
 create mode 100644 include/dma-uclass.h
 create mode 100644 include/dt-bindings/dma/bcm6318-dma.h
 create mode 100644 include/dt-bindings/dma/bcm63268-dma.h
 create mode 100644 include/dt-bindings/dma/bcm6328-dma.h
 create mode 100644 include/dt-bindings/dma/bcm6338-dma.h
 create mode 100644 include/dt-bindings/dma/bcm6348-dma.h
 create mode 100644 include/dt-bindings/dma/bcm6358-dma.h
 create mode 100644 include/dt-bindings/dma/bcm6362-dma.h
 create mode 100644 include/dt-bindings/dma/bcm6368-dma.h
 create mode 100644 test/dm/dma.c

-- 
2.11.0

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

* [U-Boot] [PATCH v8 01/31] dma: move dma_ops to dma-uclass.h
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 02/31] dma: add channels support Álvaro Fernández Rojas
                     ` (32 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Move dma_ops to a separate header file, following other uclass
implementations. While doing so, this patch also improves dma_ops
documentation.

Reviewed-by: Tom Rini <trini@konsulko.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
 v8: no changes
 v7: From Grygorii Strashko:
  - copyright fixed as suggested by Tom Rini
  - added "Reviewed-by" tags
 v6: no changes
 v5: fix build of ti-edma3 (reported by Grygorii Strashko) and remove unneeded
 dma.h include
 v4: no changes
 v3: Introduce changes reported by Simon Glass:
  - Improve dma-uclass.h documentation.
  - Switch to live tree API.

 drivers/dma/dma-uclass.c |  2 +-
 drivers/dma/ti-edma3.c   |  2 +-
 include/dma-uclass.h     | 39 +++++++++++++++++++++++++++++++++++++++
 include/dma.h            | 22 ----------------------
 4 files changed, 41 insertions(+), 24 deletions(-)
 create mode 100644 include/dma-uclass.h

diff --git a/drivers/dma/dma-uclass.c b/drivers/dma/dma-uclass.c
index a33f7d52da..6c3506c302 100644
--- a/drivers/dma/dma-uclass.c
+++ b/drivers/dma/dma-uclass.c
@@ -9,10 +9,10 @@
  */
 
 #include <common.h>
-#include <dma.h>
 #include <dm.h>
 #include <dm/uclass-internal.h>
 #include <dm/device-internal.h>
+#include <dma-uclass.h>
 #include <errno.h>
 
 int dma_get_device(u32 transfer_type, struct udevice **devp)
diff --git a/drivers/dma/ti-edma3.c b/drivers/dma/ti-edma3.c
index 2131e10a40..7e11b13e45 100644
--- a/drivers/dma/ti-edma3.c
+++ b/drivers/dma/ti-edma3.c
@@ -11,7 +11,7 @@
 #include <asm/io.h>
 #include <common.h>
 #include <dm.h>
-#include <dma.h>
+#include <dma-uclass.h>
 #include <asm/omap_common.h>
 #include <asm/ti-common/ti-edma3.h>
 
diff --git a/include/dma-uclass.h b/include/dma-uclass.h
new file mode 100644
index 0000000000..7bec5d3399
--- /dev/null
+++ b/include/dma-uclass.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ * Copyright (C) 2015 Texas Instruments Incorporated <www.ti.com>
+ * Written by Mugunthan V N <mugunthanvnm@ti.com>
+ *
+ */
+
+#ifndef _DMA_UCLASS_H
+#define _DMA_UCLASS_H
+
+/* See dma.h for background documentation. */
+
+#include <dma.h>
+
+/*
+ * struct dma_ops - Driver model DMA operations
+ *
+ * The uclass interface is implemented by all DMA devices which use
+ * driver model.
+ */
+struct dma_ops {
+	/**
+	 * transfer() - Issue a DMA transfer. The implementation must
+	 *   wait until the transfer is done.
+	 *
+	 * @dev: The DMA device
+	 * @direction: direction of data transfer (should be one from
+	 *   enum dma_direction)
+	 * @dst: The destination pointer.
+	 * @src: The source pointer.
+	 * @len: Length of the data to be copied (number of bytes).
+	 * @return zero on success, or -ve error code.
+	 */
+	int (*transfer)(struct udevice *dev, int direction, void *dst,
+			void *src, size_t len);
+};
+
+#endif /* _DMA_UCLASS_H */
diff --git a/include/dma.h b/include/dma.h
index 50e965241c..97fa0cf695 100644
--- a/include/dma.h
+++ b/include/dma.h
@@ -27,28 +27,6 @@ enum dma_direction {
 #define DMA_SUPPORTS_DEV_TO_DEV	BIT(3)
 
 /*
- * struct dma_ops - Driver model DMA operations
- *
- * The uclass interface is implemented by all DMA devices which use
- * driver model.
- */
-struct dma_ops {
-	/*
-	 * Get the current timer count
-	 *
-	 * @dev: The DMA device
-	 * @direction: direction of data transfer should be one from
-		       enum dma_direction
-	 * @dst: Destination pointer
-	 * @src: Source pointer
-	 * @len: Length of the data to be copied.
-	 * @return: 0 if OK, -ve on error
-	 */
-	int (*transfer)(struct udevice *dev, int direction, void *dst,
-			void *src, size_t len);
-};
-
-/*
  * struct dma_dev_priv - information about a device used by the uclass
  *
  * @supported: mode of transfers that DMA can support, should be
-- 
2.11.0

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

* [U-Boot] [PATCH v8 02/31] dma: add channels support
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 01/31] dma: move dma_ops to dma-uclass.h Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 03/31] test: dma: add dma-uclass test Álvaro Fernández Rojas
                     ` (31 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

This adds channels support for dma controllers that have multiple channels
which can transfer data to/from different devices (enet, usb...).

DMA channle API:
 dma_get_by_index()
 dma_get_by_name()
 dma_request()
 dma_free()
 dma_enable()
 dma_disable()
 dma_prepare_rcv_buf()
 dma_receive()
 dma_send()

Reviewed-by: Tom Rini <trini@konsulko.com>
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
[grygorii.strashko at ti.com: drop unused dma_get_by_index_platdata(),
 add metadata to send/receive ops, add dma_prepare_rcv_buf(),
 minor clean up]
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 v8: no changes
 v7: From Grygorii Strashko:
  - copyright fixed as suggested by Tom Rini
  - added "Reviewed-by" tags
 v6: From Grygorii Strashko:
  - added possibility to pass DMA driver/channel's specific data per each
  transfer using additional parameter "metadata" in dma_send/dma_receive() API.
  For example, port number for network packets to be directed to the
  specific port on multi port ethernet controllers.
  - added new dma_prepare_rcv_buf() API which allows to implement zero-copy
  DEV_TO_MEM transfer using DMA streaming channels which is usual case
  for Networking.
  - removed unused function dma_get_by_index_platdata()
  - updated comments
 v5: remove unneeded dma.h include
 v4: no changes
 v3: Introduce changes reported by Simon Glass:
  - Improve dma-uclass.h documentation.
  - Switch to live tree API.

 drivers/dma/Kconfig      |   7 ++
 drivers/dma/dma-uclass.c | 181 ++++++++++++++++++++++++++++++++-
 include/dma-uclass.h     |  91 ++++++++++++++++-
 include/dma.h            | 260 ++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 532 insertions(+), 7 deletions(-)

diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 4ee6afad35..b9b85c65fc 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -12,6 +12,13 @@ config DMA
 	  buses that is used to transfer data to and from memory.
 	  The uclass interface is defined in include/dma.h.
 
+config DMA_CHANNELS
+	bool "Enable DMA channels support"
+	depends on DMA
+	help
+	  Enable channels support for DMA. Some DMA controllers have multiple
+	  channels which can either transfer data to/from different devices.
+
 config TI_EDMA3
 	bool "TI EDMA3 driver"
 	help
diff --git a/drivers/dma/dma-uclass.c b/drivers/dma/dma-uclass.c
index 6c3506c302..9c961cf1e2 100644
--- a/drivers/dma/dma-uclass.c
+++ b/drivers/dma/dma-uclass.c
@@ -2,19 +2,192 @@
 /*
  * Direct Memory Access U-Class driver
  *
- * (C) Copyright 2015
- *     Texas Instruments Incorporated, <www.ti.com>
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ * Copyright (C) 2015 - 2018 Texas Instruments Incorporated <www.ti.com>
+ * Written by Mugunthan V N <mugunthanvnm@ti.com>
  *
  * Author: Mugunthan V N <mugunthanvnm@ti.com>
  */
 
 #include <common.h>
 #include <dm.h>
-#include <dm/uclass-internal.h>
-#include <dm/device-internal.h>
+#include <dm/read.h>
 #include <dma-uclass.h>
+#include <dt-structs.h>
 #include <errno.h>
 
+#ifdef CONFIG_DMA_CHANNELS
+static inline struct dma_ops *dma_dev_ops(struct udevice *dev)
+{
+	return (struct dma_ops *)dev->driver->ops;
+}
+
+# if CONFIG_IS_ENABLED(OF_CONTROL)
+static int dma_of_xlate_default(struct dma *dma,
+				struct ofnode_phandle_args *args)
+{
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (args->args_count > 1) {
+		pr_err("Invaild args_count: %d\n", args->args_count);
+		return -EINVAL;
+	}
+
+	if (args->args_count)
+		dma->id = args->args[0];
+	else
+		dma->id = 0;
+
+	return 0;
+}
+
+int dma_get_by_index(struct udevice *dev, int index, struct dma *dma)
+{
+	int ret;
+	struct ofnode_phandle_args args;
+	struct udevice *dev_dma;
+	const struct dma_ops *ops;
+
+	debug("%s(dev=%p, index=%d, dma=%p)\n", __func__, dev, index, dma);
+
+	assert(dma);
+	dma->dev = NULL;
+
+	ret = dev_read_phandle_with_args(dev, "dmas", "#dma-cells", 0, index,
+					 &args);
+	if (ret) {
+		pr_err("%s: dev_read_phandle_with_args failed: err=%d\n",
+		       __func__, ret);
+		return ret;
+	}
+
+	ret = uclass_get_device_by_ofnode(UCLASS_DMA, args.node, &dev_dma);
+	if (ret) {
+		pr_err("%s: uclass_get_device_by_ofnode failed: err=%d\n",
+		       __func__, ret);
+		return ret;
+	}
+
+	dma->dev = dev_dma;
+
+	ops = dma_dev_ops(dev_dma);
+
+	if (ops->of_xlate)
+		ret = ops->of_xlate(dma, &args);
+	else
+		ret = dma_of_xlate_default(dma, &args);
+	if (ret) {
+		pr_err("of_xlate() failed: %d\n", ret);
+		return ret;
+	}
+
+	return dma_request(dev_dma, dma);
+}
+
+int dma_get_by_name(struct udevice *dev, const char *name, struct dma *dma)
+{
+	int index;
+
+	debug("%s(dev=%p, name=%s, dma=%p)\n", __func__, dev, name, dma);
+	dma->dev = NULL;
+
+	index = dev_read_stringlist_search(dev, "dma-names", name);
+	if (index < 0) {
+		pr_err("dev_read_stringlist_search() failed: %d\n", index);
+		return index;
+	}
+
+	return dma_get_by_index(dev, index, dma);
+}
+# endif /* OF_CONTROL */
+
+int dma_request(struct udevice *dev, struct dma *dma)
+{
+	struct dma_ops *ops = dma_dev_ops(dev);
+
+	debug("%s(dev=%p, dma=%p)\n", __func__, dev, dma);
+
+	dma->dev = dev;
+
+	if (!ops->request)
+		return 0;
+
+	return ops->request(dma);
+}
+
+int dma_free(struct dma *dma)
+{
+	struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (!ops->free)
+		return 0;
+
+	return ops->free(dma);
+}
+
+int dma_enable(struct dma *dma)
+{
+	struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (!ops->enable)
+		return -ENOSYS;
+
+	return ops->enable(dma);
+}
+
+int dma_disable(struct dma *dma)
+{
+	struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (!ops->disable)
+		return -ENOSYS;
+
+	return ops->disable(dma);
+}
+
+int dma_prepare_rcv_buf(struct dma *dma, void *dst, size_t size)
+{
+	struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (!ops->prepare_rcv_buf)
+		return -1;
+
+	return ops->prepare_rcv_buf(dma, dst, size);
+}
+
+int dma_receive(struct dma *dma, void **dst, void *metadata)
+{
+	struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (!ops->receive)
+		return -ENOSYS;
+
+	return ops->receive(dma, dst, metadata);
+}
+
+int dma_send(struct dma *dma, void *src, size_t len, void *metadata)
+{
+	struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (!ops->send)
+		return -ENOSYS;
+
+	return ops->send(dma, src, len, metadata);
+}
+#endif /* CONFIG_DMA_CHANNELS */
+
 int dma_get_device(u32 transfer_type, struct udevice **devp)
 {
 	struct udevice *dev;
diff --git a/include/dma-uclass.h b/include/dma-uclass.h
index 7bec5d3399..16fc879a5c 100644
--- a/include/dma-uclass.h
+++ b/include/dma-uclass.h
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
- * Copyright (C) 2015 Texas Instruments Incorporated <www.ti.com>
+ * Copyright (C) 2015 - 2018 Texas Instruments Incorporated <www.ti.com>
  * Written by Mugunthan V N <mugunthanvnm@ti.com>
  *
  */
@@ -13,6 +13,8 @@
 
 #include <dma.h>
 
+struct ofnode_phandle_args;
+
 /*
  * struct dma_ops - Driver model DMA operations
  *
@@ -20,6 +22,93 @@
  * driver model.
  */
 struct dma_ops {
+#ifdef CONFIG_DMA_CHANNELS
+	/**
+	 * of_xlate - Translate a client's device-tree (OF) DMA specifier.
+	 *
+	 * The DMA core calls this function as the first step in implementing
+	 * a client's dma_get_by_*() call.
+	 *
+	 * If this function pointer is set to NULL, the DMA core will use a
+	 * default implementation, which assumes #dma-cells = <1>, and that
+	 * the DT cell contains a simple integer DMA Channel.
+	 *
+	 * At present, the DMA API solely supports device-tree. If this
+	 * changes, other xxx_xlate() functions may be added to support those
+	 * other mechanisms.
+	 *
+	 * @dma: The dma struct to hold the translation result.
+	 * @args:	The dma specifier values from device tree.
+	 * @return 0 if OK, or a negative error code.
+	 */
+	int (*of_xlate)(struct dma *dma,
+			struct ofnode_phandle_args *args);
+	/**
+	 * request - Request a translated DMA.
+	 *
+	 * The DMA core calls this function as the second step in
+	 * implementing a client's dma_get_by_*() call, following a successful
+	 * xxx_xlate() call, or as the only step in implementing a client's
+	 * dma_request() call.
+	 *
+	 * @dma: The DMA struct to request; this has been filled in by
+	 *   a previoux xxx_xlate() function call, or by the caller of
+	 *   dma_request().
+	 * @return 0 if OK, or a negative error code.
+	 */
+	int (*request)(struct dma *dma);
+	/**
+	 * free - Free a previously requested dma.
+	 *
+	 * This is the implementation of the client dma_free() API.
+	 *
+	 * @dma: The DMA to free.
+	 * @return 0 if OK, or a negative error code.
+	 */
+	int (*free)(struct dma *dma);
+	/**
+	 * enable() - Enable a DMA Channel.
+	 *
+	 * @dma: The DMA Channel to manipulate.
+	 * @return zero on success, or -ve error code.
+	 */
+	int (*enable)(struct dma *dma);
+	/**
+	 * disable() - Disable a DMA Channel.
+	 *
+	 * @dma: The DMA Channel to manipulate.
+	 * @return zero on success, or -ve error code.
+	 */
+	int (*disable)(struct dma *dma);
+	/**
+	 * add_rcv_buf() - Prepare/Add receive DMA buffer.
+	 *
+	 * @dma: The DMA Channel to manipulate.
+	 * @dst: The receive buffer pointer.
+	 * @size: The receive buffer size
+	 * @return zero on success, or -ve error code.
+	 */
+	int (*prepare_rcv_buf)(struct dma *dma, void *dst, size_t size);
+	/**
+	 * receive() - Receive a DMA transfer.
+	 *
+	 * @dma: The DMA Channel to manipulate.
+	 * @dst: The destination pointer.
+	 * @metadata: DMA driver's specific data
+	 * @return zero on success, or -ve error code.
+	 */
+	int (*receive)(struct dma *dma, void **dst, void *metadata);
+	/**
+	 * send() - Send a DMA transfer.
+	 *
+	 * @dma: The DMA Channel to manipulate.
+	 * @src: The source pointer.
+	 * @len: Length of the data to be sent (number of bytes).
+	 * @metadata: DMA driver's specific data
+	 * @return zero on success, or -ve error code.
+	 */
+	int (*send)(struct dma *dma, void *src, size_t len, void *metadata);
+#endif /* CONFIG_DMA_CHANNELS */
 	/**
 	 * transfer() - Issue a DMA transfer. The implementation must
 	 *   wait until the transfer is done.
diff --git a/include/dma.h b/include/dma.h
index 97fa0cf695..d1c3d0df7d 100644
--- a/include/dma.h
+++ b/include/dma.h
@@ -1,12 +1,17 @@
 /* SPDX-License-Identifier: GPL-2.0+ */
 /*
- * (C) Copyright 2015
- *     Texas Instruments Incorporated, <www.ti.com>
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ * Copyright (C) 2015 - 2018 Texas Instruments Incorporated <www.ti.com>
+ * Written by Mugunthan V N <mugunthanvnm@ti.com>
+ *
  */
 
 #ifndef _DMA_H_
 #define _DMA_H_
 
+#include <linux/errno.h>
+#include <linux/types.h>
+
 /*
  * enum dma_direction - dma transfer direction indicator
  * @DMA_MEM_TO_MEM: Memcpy mode
@@ -36,6 +41,257 @@ struct dma_dev_priv {
 	u32 supported;
 };
 
+#ifdef CONFIG_DMA_CHANNELS
+/**
+ * A DMA is a feature of computer systems that allows certain hardware
+ * subsystems to access main system memory, independent of the CPU.
+ * DMA channels are typically generated externally to the HW module
+ * consuming them, by an entity this API calls a DMA provider. This API
+ * provides a standard means for drivers to enable and disable DMAs, and to
+ * copy, send and receive data using DMA.
+ *
+ * A driver that implements UCLASS_DMA is a DMA provider. A provider will
+ * often implement multiple separate DMAs, since the hardware it manages
+ * often has this capability. dma_uclass.h describes the interface which
+ * DMA providers must implement.
+ *
+ * DMA consumers/clients are the HW modules driven by the DMA channels. This
+ * header file describes the API used by drivers for those HW modules.
+ *
+ * DMA consumer DMA_MEM_TO_DEV (transmit) usage example (based on networking).
+ * Note. dma_send() is sync operation always -  it'll start transfer and will
+ * poll for it to complete:
+ *	- get/request dma channel
+ *	struct dma dma_tx;
+ *	ret = dma_get_by_name(common->dev, "tx0", &dma_tx);
+ *	if (ret) ...
+ *
+ *	- enable dma channel
+ *	ret = dma_enable(&dma_tx);
+ *	if (ret) ...
+ *
+ *	- dma transmit DMA_MEM_TO_DEV.
+ *	struct ti_drv_packet_data packet_data;
+ *
+ *	packet_data.opt1 = val1;
+ *	packet_data.opt2 = val2;
+ *	ret = dma_send(&dma_tx, packet, length, &packet_data);
+ *	if (ret) ..
+ *
+ * DMA consumer DMA_DEV_TO_MEM (receive) usage example (based on networking).
+ * Note. dma_receive() is sync operation always - it'll start transfer
+ * (if required) and will poll for it to complete (or for any previously
+ * configured dev2mem transfer to complete):
+ *	- get/request dma channel
+ *	struct dma dma_rx;
+ *	ret = dma_get_by_name(common->dev, "rx0", &dma_rx);
+ *	if (ret) ...
+ *
+ *	- enable dma channel
+ *	ret = dma_enable(&dma_rx);
+ *	if (ret) ...
+ *
+ *	- dma receive DMA_DEV_TO_MEM.
+ *	struct ti_drv_packet_data packet_data;
+ *
+ *	len = dma_receive(&dma_rx, (void **)packet, &packet_data);
+ *	if (ret < 0) ...
+ *
+ * DMA consumer DMA_DEV_TO_MEM (receive) zero-copy usage example (based on
+ * networking). Networking subsystem allows to configure and use few receive
+ * buffers (dev2mem), as Networking RX DMA channels usually implemented
+ * as streaming interface
+ *	- get/request dma channel
+ *	struct dma dma_rx;
+ *	ret = dma_get_by_name(common->dev, "rx0", &dma_rx);
+ *	if (ret) ...
+ *
+ *	for (i = 0; i < RX_DESC_NUM; i++) {
+ *		ret = dma_prepare_rcv_buf(&dma_rx,
+ *					  net_rx_packets[i],
+ *					  RX_BUF_SIZE);
+ *		if (ret) ...
+ *	}
+ *
+ *	- enable dma channel
+ *	ret = dma_enable(&dma_rx);
+ *	if (ret) ...
+ *
+ *	- dma receive DMA_DEV_TO_MEM.
+ *	struct ti_drv_packet_data packet_data;
+ *
+ *	len = dma_receive(&dma_rx, (void **)packet, &packet_data);
+ *	if (ret < 0) ..
+ *
+ *	-- process packet --
+ *
+ *	- return buffer back to DAM channel
+ *	ret = dma_prepare_rcv_buf(&dma_rx,
+ *				  net_rx_packets[rx_next],
+ *				  RX_BUF_SIZE);
+ */
+
+struct udevice;
+
+/**
+ * struct dma - A handle to (allowing control of) a single DMA.
+ *
+ * Clients provide storage for DMA handles. The content of the structure is
+ * managed solely by the DMA API and DMA drivers. A DMA struct is
+ * initialized by "get"ing the DMA struct. The DMA struct is passed to all
+ * other DMA APIs to identify which DMA channel to operate upon.
+ *
+ * @dev: The device which implements the DMA channel.
+ * @id: The DMA channel ID within the provider.
+ *
+ * Currently, the DMA API assumes that a single integer ID is enough to
+ * identify and configure any DMA channel for any DMA provider. If this
+ * assumption becomes invalid in the future, the struct could be expanded to
+ * either (a) add more fields to allow DMA providers to store additional
+ * information, or (b) replace the id field with an opaque pointer, which the
+ * provider would dynamically allocated during its .of_xlate op, and process
+ * during is .request op. This may require the addition of an extra op to clean
+ * up the allocation.
+ */
+struct dma {
+	struct udevice *dev;
+	/*
+	 * Written by of_xlate. We assume a single id is enough for now. In the
+	 * future, we might add more fields here.
+	 */
+	unsigned long id;
+};
+
+# if CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(DMA)
+/**
+ * dma_get_by_index - Get/request a DMA by integer index.
+ *
+ * This looks up and requests a DMA. The index is relative to the client
+ * device; each device is assumed to have n DMAs associated with it somehow,
+ * and this function finds and requests one of them. The mapping of client
+ * device DMA indices to provider DMAs may be via device-tree properties,
+ * board-provided mapping tables, or some other mechanism.
+ *
+ * @dev:	The client device.
+ * @index:	The index of the DMA to request, within the client's list of
+ *		DMA channels.
+ * @dma:	A pointer to a DMA struct to initialize.
+ * @return 0 if OK, or a negative error code.
+ */
+int dma_get_by_index(struct udevice *dev, int index, struct dma *dma);
+
+/**
+ * dma_get_by_name - Get/request a DMA by name.
+ *
+ * This looks up and requests a DMA. The name is relative to the client
+ * device; each device is assumed to have n DMAs associated with it somehow,
+ * and this function finds and requests one of them. The mapping of client
+ * device DMA names to provider DMAs may be via device-tree properties,
+ * board-provided mapping tables, or some other mechanism.
+ *
+ * @dev:	The client device.
+ * @name:	The name of the DMA to request, within the client's list of
+ *		DMA channels.
+ * @dma:	A pointer to a DMA struct to initialize.
+ * @return 0 if OK, or a negative error code.
+ */
+int dma_get_by_name(struct udevice *dev, const char *name, struct dma *dma);
+# else
+static inline int dma_get_by_index(struct udevice *dev, int index,
+				   struct dma *dma)
+{
+	return -ENOSYS;
+}
+
+static inline int dma_get_by_name(struct udevice *dev, const char *name,
+				  struct dma *dma)
+{
+	return -ENOSYS;
+}
+# endif
+
+/**
+ * dma_request - Request a DMA by provider-specific ID.
+ *
+ * This requests a DMA using a provider-specific ID. Generally, this function
+ * should not be used, since dma_get_by_index/name() provide an interface that
+ * better separates clients from intimate knowledge of DMA providers.
+ * However, this function may be useful in core SoC-specific code.
+ *
+ * @dev: The DMA provider device.
+ * @dma: A pointer to a DMA struct to initialize. The caller must
+ *	 have already initialized any field in this struct which the
+ *	 DMA provider uses to identify the DMA channel.
+ * @return 0 if OK, or a negative error code.
+ */
+int dma_request(struct udevice *dev, struct dma *dma);
+
+/**
+ * dma_free - Free a previously requested DMA.
+ *
+ * @dma: A DMA struct that was previously successfully requested by
+ *	 dma_request/get_by_*().
+ * @return 0 if OK, or a negative error code.
+ */
+int dma_free(struct dma *dma);
+
+/**
+ * dma_enable() - Enable (turn on) a DMA channel.
+ *
+ * @dma: A DMA struct that was previously successfully requested by
+ *	 dma_request/get_by_*().
+ * @return zero on success, or -ve error code.
+ */
+int dma_enable(struct dma *dma);
+
+/**
+ * dma_disable() - Disable (turn off) a DMA channel.
+ *
+ * @dma: A DMA struct that was previously successfully requested by
+ *	 dma_request/get_by_*().
+ * @return zero on success, or -ve error code.
+ */
+int dma_disable(struct dma *dma);
+
+/**
+ * dma_prepare_rcv_buf() - Prepare/add receive DMA buffer.
+ *
+ * It allows to implement zero-copy async DMA_DEV_TO_MEM (receive) transactions
+ * if supported by DMA providers.
+ *
+ * @dma: A DMA struct that was previously successfully requested by
+ *	 dma_request/get_by_*().
+ * @dst: The receive buffer pointer.
+ * @size: The receive buffer size
+ * @return zero on success, or -ve error code.
+ */
+int dma_prepare_rcv_buf(struct dma *dma, void *dst, size_t size);
+
+/**
+ * dma_receive() - Receive a DMA transfer.
+ *
+ * @dma: A DMA struct that was previously successfully requested by
+ *	 dma_request/get_by_*().
+ * @dst: The destination pointer.
+ * @metadata: DMA driver's channel specific data
+ * @return length of received data on success, or zero - no data,
+ * or -ve error code.
+ */
+int dma_receive(struct dma *dma, void **dst, void *metadata);
+
+/**
+ * dma_send() - Send a DMA transfer.
+ *
+ * @dma: A DMA struct that was previously successfully requested by
+ *	 dma_request/get_by_*().
+ * @src: The source pointer.
+ * @len: Length of the data to be sent (number of bytes).
+ * @metadata: DMA driver's channel specific data
+ * @return zero on success, or -ve error code.
+ */
+int dma_send(struct dma *dma, void *src, size_t len, void *metadata);
+#endif /* CONFIG_DMA_CHANNELS */
+
 /*
  * dma_get_device - get a DMA device which supports transfer
  * type of transfer_type
-- 
2.11.0

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

* [U-Boot] [PATCH v8 03/31] test: dma: add dma-uclass test
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 01/31] dma: move dma_ops to dma-uclass.h Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 02/31] dma: add channels support Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 04/31] dma: add bcm6348-iudma support Álvaro Fernández Rojas
                     ` (30 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

From: Grygorii Strashko <grygorii.strashko@ti.com>

Add a sandbox DMA driver implementation (provider) and corresponding DM
test.

Reviewed-by: Tom Rini <trini@konsulko.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Acked-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: sync with latest u-boot
 v7: From Grygorii Strashko:
  - no changes
 v6: From Grygorii Strashko:
  - added dma-uclass test

 arch/sandbox/dts/test.dts      |   8 ++
 configs/sandbox_defconfig      |   3 +
 drivers/dma/Kconfig            |   7 +
 drivers/dma/Makefile           |   1 +
 drivers/dma/sandbox-dma-test.c | 282 +++++++++++++++++++++++++++++++++++++++++
 test/dm/Makefile               |   1 +
 test/dm/dma.c                  | 123 ++++++++++++++++++
 7 files changed, 425 insertions(+)
 create mode 100644 drivers/dma/sandbox-dma-test.c
 create mode 100644 test/dm/dma.c

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 2c6b422312..e5932d5a34 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -731,6 +731,14 @@
 	pinctrl {
 		compatible = "sandbox,pinctrl";
 	};
+
+	dma: dma {
+		compatible = "sandbox,dma";
+		#dma-cells = <1>;
+
+		dmas = <&dma 0>, <&dma 1>, <&dma 2>;
+		dma-names = "m2m", "tx0", "rx0";
+	};
 };
 
 #include "sandbox_pmic.dtsi"
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 5a744f4791..0e5e6f687e 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -215,3 +215,6 @@ CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
 CONFIG_UT_ENV=y
 CONFIG_UT_OVERLAY=y
+CONFIG_DMA=y
+CONFIG_DMA_CHANNELS=y
+CONFIG_SANDBOX_DMA=y
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index b9b85c65fc..8a4162eccd 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -19,6 +19,13 @@ config DMA_CHANNELS
 	  Enable channels support for DMA. Some DMA controllers have multiple
 	  channels which can either transfer data to/from different devices.
 
+config SANDBOX_DMA
+	bool "Enable the sandbox DMA test driver"
+	depends on DMA && DMA_CHANNELS && SANDBOX
+	help
+	  Enable support for a test DMA uclass implementation. It stimulates
+	  DMA transfer by simple copying data between channels.
+
 config TI_EDMA3
 	bool "TI EDMA3 driver"
 	help
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 4eaef8ac65..aff31f986a 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_DMA) += dma-uclass.o
 obj-$(CONFIG_FSLDMAFEC) += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o
 obj-$(CONFIG_APBH_DMA) += apbh_dma.o
 obj-$(CONFIG_FSL_DMA) += fsl_dma.o
+obj-$(CONFIG_SANDBOX_DMA) += sandbox-dma-test.o
 obj-$(CONFIG_TI_KSNAV) += keystone_nav.o keystone_nav_cfg.o
 obj-$(CONFIG_TI_EDMA3) += ti-edma3.o
 obj-$(CONFIG_DMA_LPC32XX) += lpc32xx_dma.o
diff --git a/drivers/dma/sandbox-dma-test.c b/drivers/dma/sandbox-dma-test.c
new file mode 100644
index 0000000000..b958ec4d23
--- /dev/null
+++ b/drivers/dma/sandbox-dma-test.c
@@ -0,0 +1,282 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Direct Memory Access U-Class Simulation driver
+ *
+ * Copyright (C) 2018 Texas Instruments Incorporated <www.ti.com>
+ *
+ * Author: Grygorii Strashko <grygorii.strashko@ti.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/read.h>
+#include <dma-uclass.h>
+#include <dt-structs.h>
+#include <errno.h>
+
+#define SANDBOX_DMA_CH_CNT 3
+#define SANDBOX_DMA_BUF_SIZE 1024
+
+struct sandbox_dma_chan {
+	struct sandbox_dma_dev *ud;
+	char name[20];
+	u32 id;
+	enum dma_direction dir;
+	bool in_use;
+	bool enabled;
+};
+
+struct sandbox_dma_dev {
+	struct device *dev;
+	u32 ch_count;
+	struct sandbox_dma_chan channels[SANDBOX_DMA_CH_CNT];
+	uchar   buf[SANDBOX_DMA_BUF_SIZE];
+	uchar	*buf_rx;
+	size_t	data_len;
+	u32	meta;
+};
+
+static int sandbox_dma_transfer(struct udevice *dev, int direction,
+				void *dst, void *src, size_t len)
+{
+	memcpy(dst, src, len);
+
+	return 0;
+}
+
+static int sandbox_dma_of_xlate(struct dma *dma,
+				struct ofnode_phandle_args *args)
+{
+	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
+	struct sandbox_dma_chan *uc;
+
+	debug("%s(dma id=%u)\n", __func__, args->args[0]);
+
+	if (args->args[0] >= SANDBOX_DMA_CH_CNT)
+		return -EINVAL;
+
+	dma->id = args->args[0];
+
+	uc = &ud->channels[dma->id];
+
+	if (dma->id == 1)
+		uc->dir = DMA_MEM_TO_DEV;
+	else if (dma->id == 2)
+		uc->dir = DMA_DEV_TO_MEM;
+	else
+		uc->dir = DMA_MEM_TO_MEM;
+	debug("%s(dma id=%lu dir=%d)\n", __func__, dma->id, uc->dir);
+
+	return 0;
+}
+
+static int sandbox_dma_request(struct dma *dma)
+{
+	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
+	struct sandbox_dma_chan *uc;
+
+	if (dma->id >= SANDBOX_DMA_CH_CNT)
+		return -EINVAL;
+
+	uc = &ud->channels[dma->id];
+	if (uc->in_use)
+		return -EBUSY;
+
+	uc->in_use = true;
+	debug("%s(dma id=%lu in_use=%d)\n", __func__, dma->id, uc->in_use);
+
+	return 0;
+}
+
+static int sandbox_dma_free(struct dma *dma)
+{
+	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
+	struct sandbox_dma_chan *uc;
+
+	if (dma->id >= SANDBOX_DMA_CH_CNT)
+		return -EINVAL;
+
+	uc = &ud->channels[dma->id];
+	if (!uc->in_use)
+		return -EINVAL;
+
+	uc->in_use = false;
+	ud->buf_rx = NULL;
+	ud->data_len = 0;
+	debug("%s(dma id=%lu in_use=%d)\n", __func__, dma->id, uc->in_use);
+
+	return 0;
+}
+
+static int sandbox_dma_enable(struct dma *dma)
+{
+	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
+	struct sandbox_dma_chan *uc;
+
+	if (dma->id >= SANDBOX_DMA_CH_CNT)
+		return -EINVAL;
+
+	uc = &ud->channels[dma->id];
+	if (!uc->in_use)
+		return -EINVAL;
+	if (uc->enabled)
+		return -EINVAL;
+
+	uc->enabled = true;
+	debug("%s(dma id=%lu enabled=%d)\n", __func__, dma->id, uc->enabled);
+
+	return 0;
+}
+
+static int sandbox_dma_disable(struct dma *dma)
+{
+	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
+	struct sandbox_dma_chan *uc;
+
+	if (dma->id >= SANDBOX_DMA_CH_CNT)
+		return -EINVAL;
+
+	uc = &ud->channels[dma->id];
+	if (!uc->in_use)
+		return -EINVAL;
+	if (!uc->enabled)
+		return -EINVAL;
+
+	uc->enabled = false;
+	debug("%s(dma id=%lu enabled=%d)\n", __func__, dma->id, uc->enabled);
+
+	return 0;
+}
+
+static int sandbox_dma_send(struct dma *dma,
+			    void *src, size_t len, void *metadata)
+{
+	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
+	struct sandbox_dma_chan *uc;
+
+	if (dma->id >= SANDBOX_DMA_CH_CNT)
+		return -EINVAL;
+	if (!src || !metadata)
+		return -EINVAL;
+
+	debug("%s(dma id=%lu)\n", __func__, dma->id);
+
+	uc = &ud->channels[dma->id];
+	if (uc->dir != DMA_MEM_TO_DEV)
+		return -EINVAL;
+	if (!uc->in_use)
+		return -EINVAL;
+	if (!uc->enabled)
+		return -EINVAL;
+	if (len >= SANDBOX_DMA_BUF_SIZE)
+		return -EINVAL;
+
+	memcpy(ud->buf, src, len);
+	ud->data_len = len;
+	ud->meta = *((u32 *)metadata);
+
+	debug("%s(dma id=%lu len=%zu meta=%08x)\n",
+	      __func__, dma->id, len, ud->meta);
+
+	return 0;
+}
+
+static int sandbox_dma_receive(struct dma *dma, void **dst, void *metadata)
+{
+	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
+	struct sandbox_dma_chan *uc;
+
+	if (dma->id >= SANDBOX_DMA_CH_CNT)
+		return -EINVAL;
+	if (!dst || !metadata)
+		return -EINVAL;
+
+	uc = &ud->channels[dma->id];
+	if (uc->dir != DMA_DEV_TO_MEM)
+		return -EINVAL;
+	if (!uc->in_use)
+		return -EINVAL;
+	if (!uc->enabled)
+		return -EINVAL;
+	if (!ud->data_len)
+		return 0;
+
+	if (ud->buf_rx) {
+		memcpy(ud->buf_rx, ud->buf, ud->data_len);
+		*dst = ud->buf_rx;
+	} else {
+		memcpy(*dst, ud->buf, ud->data_len);
+	}
+
+	*((u32 *)metadata) = ud->meta;
+
+	debug("%s(dma id=%lu len=%zu meta=%08x %p)\n",
+	      __func__, dma->id, ud->data_len, ud->meta, *dst);
+
+	return ud->data_len;
+}
+
+static int sandbox_dma_add_rcv_buf(struct dma *dma, void *dst, size_t size)
+{
+	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
+
+	ud->buf_rx = dst;
+
+	return 0;
+}
+
+static const struct dma_ops sandbox_dma_ops = {
+	.transfer	= sandbox_dma_transfer,
+	.of_xlate	= sandbox_dma_of_xlate,
+	.request	= sandbox_dma_request,
+	.free		= sandbox_dma_free,
+	.enable		= sandbox_dma_enable,
+	.disable	= sandbox_dma_disable,
+	.send		= sandbox_dma_send,
+	.receive	= sandbox_dma_receive,
+	.add_rcv_buf	= sandbox_dma_add_rcv_buf,
+};
+
+static int sandbox_dma_probe(struct udevice *dev)
+{
+	struct dma_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct sandbox_dma_dev *ud = dev_get_priv(dev);
+	int i, ret = 0;
+
+	uc_priv->supported = DMA_SUPPORTS_MEM_TO_MEM |
+			     DMA_SUPPORTS_MEM_TO_DEV |
+			     DMA_SUPPORTS_DEV_TO_MEM;
+
+	ud->ch_count = SANDBOX_DMA_CH_CNT;
+	ud->buf_rx = NULL;
+	ud->meta = 0;
+	ud->data_len = 0;
+
+	pr_err("Number of channels: %u\n", ud->ch_count);
+
+	for (i = 0; i < ud->ch_count; i++) {
+		struct sandbox_dma_chan *uc = &ud->channels[i];
+
+		uc->ud = ud;
+		uc->id = i;
+		sprintf(uc->name, "DMA chan%d\n", i);
+		uc->in_use = false;
+		uc->enabled = false;
+	}
+
+	return ret;
+}
+
+static const struct udevice_id sandbox_dma_ids[] = {
+	{ .compatible = "sandbox,dma" },
+	{ }
+};
+
+U_BOOT_DRIVER(sandbox_dma) = {
+	.name	= "sandbox-dma",
+	.id	= UCLASS_DMA,
+	.of_match = sandbox_dma_ids,
+	.ops	= &sandbox_dma_ops,
+	.probe = sandbox_dma_probe,
+	.priv_auto_alloc_size = sizeof(struct sandbox_dma_dev),
+};
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 213e0fda94..757dd0c45b 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -54,4 +54,5 @@ obj-$(CONFIG_DM_SERIAL) += serial.o
 obj-$(CONFIG_CPU) += cpu.o
 obj-$(CONFIG_TEE) += tee.o
 obj-$(CONFIG_VIRTIO_SANDBOX) += virtio.o
+obj-$(CONFIG_DMA) += dma.o
 endif
diff --git a/test/dm/dma.c b/test/dm/dma.c
new file mode 100644
index 0000000000..6f19d6180c
--- /dev/null
+++ b/test/dm/dma.c
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Direct Memory Access U-Class tests
+ *
+ * Copyright (C) 2018 Texas Instruments Incorporated <www.ti.com>
+ * Grygorii Strashko <grygorii.strashko@ti.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/test.h>
+#include <dma.h>
+#include <test/ut.h>
+
+static int dm_test_dma_m2m(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	struct dma dma_m2m;
+	u8 src_buf[512];
+	u8 dst_buf[512];
+	size_t len = 512;
+	int i;
+
+	ut_assertok(uclass_get_device_by_name(UCLASS_DMA, "dma", &dev));
+	ut_assertok(dma_get_by_name(dev, "m2m", &dma_m2m));
+
+	memset(dst_buf, 0, len);
+	for (i = 0; i < len; i++)
+		src_buf[i] = i;
+
+	ut_assertok(dma_memcpy(dst_buf, src_buf, len));
+
+	ut_assertok(memcmp(src_buf, dst_buf, len));
+	return 0;
+}
+DM_TEST(dm_test_dma_m2m, DM_TESTF_SCAN_FDT);
+
+static int dm_test_dma(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	struct dma dma_tx, dma_rx;
+	u8 src_buf[512];
+	u8 dst_buf[512];
+	void *dst_ptr;
+	size_t len = 512;
+	u32 meta1, meta2;
+	int i;
+
+	ut_assertok(uclass_get_device_by_name(UCLASS_DMA, "dma", &dev));
+
+	ut_assertok(dma_get_by_name(dev, "tx0", &dma_tx));
+	ut_assertok(dma_get_by_name(dev, "rx0", &dma_rx));
+
+	ut_assertok(dma_enable(&dma_tx));
+	ut_assertok(dma_enable(&dma_rx));
+
+	memset(dst_buf, 0, len);
+	for (i = 0; i < len; i++)
+		src_buf[i] = i;
+	meta1 = 0xADADDEAD;
+	meta2 = 0;
+	dst_ptr = &dst_buf;
+
+	ut_assertok(dma_send(&dma_tx, src_buf, len, &meta1));
+
+	ut_asserteq(len, dma_receive(&dma_rx, &dst_ptr, &meta2));
+	ut_asserteq(0xADADDEAD, meta2);
+
+	ut_assertok(dma_disable(&dma_tx));
+	ut_assertok(dma_disable(&dma_rx));
+
+	ut_assertok(dma_free(&dma_tx));
+	ut_assertok(dma_free(&dma_rx));
+	ut_assertok(memcmp(src_buf, dst_buf, len));
+
+	return 0;
+}
+DM_TEST(dm_test_dma, DM_TESTF_SCAN_FDT);
+
+static int dm_test_dma_rx(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	struct dma dma_tx, dma_rx;
+	u8 src_buf[512];
+	u8 dst_buf[512];
+	void *dst_ptr;
+	size_t len = 512;
+	u32 meta1, meta2;
+	int i;
+
+	ut_assertok(uclass_get_device_by_name(UCLASS_DMA, "dma", &dev));
+
+	ut_assertok(dma_get_by_name(dev, "tx0", &dma_tx));
+	ut_assertok(dma_get_by_name(dev, "rx0", &dma_rx));
+
+	ut_assertok(dma_enable(&dma_tx));
+	ut_assertok(dma_enable(&dma_rx));
+
+	memset(dst_buf, 0, len);
+	for (i = 0; i < len; i++)
+		src_buf[i] = i;
+	meta1 = 0xADADDEAD;
+	meta2 = 0;
+	dst_ptr = NULL;
+
+	ut_assertok(dma_add_rcv_buf(&dma_tx, dst_buf, len));
+
+	ut_assertok(dma_send(&dma_tx, src_buf, len, &meta1));
+
+	ut_asserteq(len, dma_receive(&dma_rx, &dst_ptr, &meta2));
+	ut_asserteq(0xADADDEAD, meta2);
+	ut_asserteq_ptr(dst_buf, dst_ptr);
+
+	ut_assertok(dma_disable(&dma_tx));
+	ut_assertok(dma_disable(&dma_rx));
+
+	ut_assertok(dma_free(&dma_tx));
+	ut_assertok(dma_free(&dma_rx));
+	ut_assertok(memcmp(src_buf, dst_buf, len));
+
+	return 0;
+}
+DM_TEST(dm_test_dma_rx, DM_TESTF_SCAN_FDT);
-- 
2.11.0

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

* [U-Boot] [PATCH v8 04/31] dma: add bcm6348-iudma support
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (2 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 03/31] test: dma: add dma-uclass test Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 05/31] bmips: bcm6338: " Álvaro Fernández Rojas
                     ` (29 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

BCM6348 IUDMA controller is present on multiple BMIPS (BCM63xx) SoCs.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: Introduce changes from Grygorii Strashko
 v5: Several fixes and improvements:
  - Remove unused defines.
  - Increment rx descriptors.
  - Fix flow control issues.
  - Error checking now depends on hw.
  - Remove unneeded interrupts.
 v4: Fix issues reported by Grygorii Strashko and other fixes:
  - Remove usage of net_rx_packets as buffer.
  - Allocate dynamic rx buffer.
  - Check dma errors and discard invalid packets.
 v3: no changes
 v2: Fix dma rx burst config and select DMA_CHANNELS.

 drivers/dma/Kconfig         |   9 +
 drivers/dma/Makefile        |   1 +
 drivers/dma/bcm6348-iudma.c | 533 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 543 insertions(+)
 create mode 100644 drivers/dma/bcm6348-iudma.c

diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 8a4162eccd..1820676d7a 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -26,6 +26,15 @@ config SANDBOX_DMA
 	  Enable support for a test DMA uclass implementation. It stimulates
 	  DMA transfer by simple copying data between channels.
 
+config BCM6348_IUDMA
+	bool "BCM6348 IUDMA driver"
+	depends on ARCH_BMIPS
+	select DMA_CHANNELS
+	help
+	  Enable the BCM6348 IUDMA driver.
+	  This driver support data transfer from devices to
+	  memory and from memory to devices.
+
 config TI_EDMA3
 	bool "TI EDMA3 driver"
 	help
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index aff31f986a..b5f9147e0a 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_DMA) += dma-uclass.o
 
 obj-$(CONFIG_FSLDMAFEC) += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o
 obj-$(CONFIG_APBH_DMA) += apbh_dma.o
+obj-$(CONFIG_BCM6348_IUDMA) += bcm6348-iudma.o
 obj-$(CONFIG_FSL_DMA) += fsl_dma.o
 obj-$(CONFIG_SANDBOX_DMA) += sandbox-dma-test.o
 obj-$(CONFIG_TI_KSNAV) += keystone_nav.o keystone_nav_cfg.o
diff --git a/drivers/dma/bcm6348-iudma.c b/drivers/dma/bcm6348-iudma.c
new file mode 100644
index 0000000000..ef938bc3cd
--- /dev/null
+++ b/drivers/dma/bcm6348-iudma.c
@@ -0,0 +1,533 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/dma/bcm63xx-iudma.c:
+ *	Copyright (C) 2015 Simon Arlott <simon@fire.lp0.eu>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c:
+ *	Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ *
+ * Derived from bcm963xx_4.12L.06B_consumer/shared/opensource/include/bcm963xx/63268_map_part.h:
+ *	Copyright (C) 2000-2010 Broadcom Corporation
+ *
+ * Derived from bcm963xx_4.12L.06B_consumer/bcmdrivers/opensource/net/enet/impl4/bcmenet.c:
+ *	Copyright (C) 2010 Broadcom Corporation
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dma-uclass.h>
+#include <memalign.h>
+#include <reset.h>
+#include <asm/io.h>
+
+#define DMA_RX_DESC	6
+#define DMA_TX_DESC	1
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define ALIGN_END_ADDR(type, ptr, size)	\
+	((unsigned long)(ptr) + roundup((size) * sizeof(type), \
+	 ARCH_DMA_MINALIGN))
+
+/* DMA Channels */
+#define DMA_CHAN_FLOWC(x)		((x) >> 1)
+#define DMA_CHAN_MAX			16
+#define DMA_CHAN_SIZE			0x10
+#define DMA_CHAN_TOUT			500
+
+/* DMA Global Configuration register */
+#define DMA_CFG_REG			0x00
+#define  DMA_CFG_ENABLE_SHIFT		0
+#define  DMA_CFG_ENABLE_MASK		(1 << DMA_CFG_ENABLE_SHIFT)
+#define  DMA_CFG_FLOWC_ENABLE(x)	BIT(DMA_CHAN_FLOWC(x) + 1)
+#define  DMA_CFG_NCHANS_SHIFT		24
+#define  DMA_CFG_NCHANS_MASK		(0xf << DMA_CFG_NCHANS_SHIFT)
+
+/* DMA Global Flow Control registers */
+#define DMA_FLOWC_THR_LO_REG(x)		(0x04 + DMA_CHAN_FLOWC(x) * 0x0c)
+#define DMA_FLOWC_THR_HI_REG(x)		(0x08 + DMA_CHAN_FLOWC(x) * 0x0c)
+#define DMA_FLOWC_ALLOC_REG(x)		(0x0c + DMA_CHAN_FLOWC(x) * 0x0c)
+#define  DMA_FLOWC_ALLOC_FORCE_SHIFT	31
+#define  DMA_FLOWC_ALLOC_FORCE_MASK	(1 << DMA_FLOWC_ALLOC_FORCE_SHIFT)
+
+/* DMA Global Reset register */
+#define DMA_RST_REG			0x34
+#define  DMA_RST_CHAN_SHIFT		0
+#define  DMA_RST_CHAN_MASK(x)		(1 << x)
+
+/* DMA Channel Configuration register */
+#define DMAC_CFG_REG(x)			(DMA_CHAN_SIZE * (x) + 0x00)
+#define  DMAC_CFG_ENABLE_SHIFT		0
+#define  DMAC_CFG_ENABLE_MASK		(1 << DMAC_CFG_ENABLE_SHIFT)
+#define  DMAC_CFG_PKT_HALT_SHIFT	1
+#define  DMAC_CFG_PKT_HALT_MASK		(1 << DMAC_CFG_PKT_HALT_SHIFT)
+#define  DMAC_CFG_BRST_HALT_SHIFT	2
+#define  DMAC_CFG_BRST_HALT_MASK	(1 << DMAC_CFG_BRST_HALT_SHIFT)
+
+/* DMA Channel Max Burst Length register */
+#define DMAC_BURST_REG(x)		(DMA_CHAN_SIZE * (x) + 0x0c)
+
+/* DMA SRAM Descriptor Ring Start register */
+#define DMAS_RSTART_REG(x)		(DMA_CHAN_SIZE * (x) + 0x00)
+
+/* DMA SRAM State/Bytes done/ring offset register */
+#define DMAS_STATE_DATA_REG(x)		(DMA_CHAN_SIZE * (x) + 0x04)
+
+/* DMA SRAM Buffer Descriptor status and length register */
+#define DMAS_DESC_LEN_STATUS_REG(x)	(DMA_CHAN_SIZE * (x) + 0x08)
+
+/* DMA SRAM Buffer Descriptor status and length register */
+#define DMAS_DESC_BASE_BUFPTR_REG(x)	(DMA_CHAN_SIZE * (x) + 0x0c)
+
+struct bcm6348_dma_desc {
+	uint16_t length;
+
+	uint16_t status;
+#define DMAD_ST_CRC_SHIFT		8
+#define DMAD_ST_CRC_MASK		(1 << DMAD_ST_CRC_SHIFT)
+#define DMAD_ST_WRAP_SHIFT		12
+#define DMAD_ST_WRAP_MASK		(1 << DMAD_ST_WRAP_SHIFT)
+#define DMAD_ST_SOP_SHIFT		13
+#define DMAD_ST_SOP_MASK		(1 << DMAD_ST_SOP_SHIFT)
+#define DMAD_ST_EOP_SHIFT		14
+#define DMAD_ST_EOP_MASK		(1 << DMAD_ST_EOP_SHIFT)
+#define DMAD_ST_OWN_SHIFT		15
+#define DMAD_ST_OWN_MASK		(1 << DMAD_ST_OWN_SHIFT)
+
+#define DMAD6348_ST_OV_ERR_SHIFT	0
+#define DMAD6348_ST_OV_ERR_MASK		(1 << DMAD6348_ST_OV_ERR_SHIFT)
+#define DMAD6348_ST_CRC_ERR_SHIFT	1
+#define DMAD6348_ST_CRC_ERR_MASK	(1 << DMAD6348_ST_CRC_ERR_SHIFT)
+#define DMAD6348_ST_RX_ERR_SHIFT	2
+#define DMAD6348_ST_RX_ERR_MASK		(1 << DMAD6348_ST_RX_ERR_SHIFT)
+#define DMAD6348_ST_OS_ERR_SHIFT	4
+#define DMAD6348_ST_OS_ERR_MASK		(1 << DMAD6348_ST_OS_ERR_SHIFT)
+#define DMAD6348_ST_UN_ERR_SHIFT	9
+#define DMAD6348_ST_UN_ERR_MASK		(1 << DMAD6348_ST_UN_ERR_SHIFT)
+
+	uint32_t address;
+} __attribute__((aligned(1)));
+
+struct bcm6348_chan_priv {
+	void __iomem *dma_buff;
+	void __iomem *dma_ring;
+	uint8_t dma_ring_size;
+	uint8_t desc_id;
+};
+
+struct bcm6348_iudma_hw {
+	uint16_t err_mask;
+};
+
+struct bcm6348_iudma_priv {
+	const struct bcm6348_iudma_hw *hw;
+	void __iomem *base;
+	void __iomem *chan;
+	void __iomem *sram;
+	struct bcm6348_chan_priv **ch_priv;
+	uint8_t n_channels;
+};
+
+static inline bool bcm6348_iudma_chan_is_rx(uint8_t ch)
+{
+	return !(ch & 1);
+}
+
+static void bcm6348_iudma_chan_stop(struct bcm6348_iudma_priv *priv,
+				    uint8_t ch)
+{
+	unsigned int timeout = DMA_CHAN_TOUT;
+
+	do {
+		uint32_t cfg, halt;
+
+		if (timeout > DMA_CHAN_TOUT / 2)
+			halt = DMAC_CFG_PKT_HALT_MASK;
+		else
+			halt = DMAC_CFG_BRST_HALT_MASK;
+
+		/* try to stop dma channel */
+		writel_be(halt, priv->chan + DMAC_CFG_REG(ch));
+		mb();
+
+		/* check if channel was stopped */
+		cfg = readl_be(priv->chan + DMAC_CFG_REG(ch));
+		if (!(cfg & DMAC_CFG_ENABLE_MASK))
+			break;
+
+		udelay(1);
+	} while (--timeout);
+
+	if (!timeout)
+		pr_err("unable to stop channel %u\n", ch);
+
+	/* reset dma channel */
+	setbits_be32(priv->base + DMA_RST_REG, DMA_RST_CHAN_MASK(ch));
+	mb();
+	clrbits_be32(priv->base + DMA_RST_REG, DMA_RST_CHAN_MASK(ch));
+}
+
+static int bcm6348_iudma_disable(struct dma *dma)
+{
+	struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+
+	bcm6348_iudma_chan_stop(priv, dma->id);
+
+	if (bcm6348_iudma_chan_is_rx(dma->id))
+		writel_be(DMA_FLOWC_ALLOC_FORCE_MASK,
+			  DMA_FLOWC_ALLOC_REG(dma->id));
+
+	return 0;
+}
+
+static int bcm6348_iudma_enable(struct dma *dma)
+{
+	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+	struct bcm6348_dma_desc *dma_desc;
+	void __iomem *dma_buff = ch_priv->dma_buff;
+	uint8_t i;
+
+	/* init dma rings */
+	dma_desc = ch_priv->dma_ring;
+	for (i = 0; i < ch_priv->dma_ring_size; i++) {
+		if (bcm6348_iudma_chan_is_rx(dma->id)) {
+			dma_desc->status = DMAD_ST_OWN_MASK;
+			dma_desc->length = PKTSIZE_ALIGN;
+			dma_desc->address = virt_to_phys(dma_buff);
+			dma_buff += PKTSIZE_ALIGN;
+		} else {
+			dma_desc->status = 0;
+			dma_desc->length = 0;
+			dma_desc->address = 0;
+		}
+
+		if (i == ch_priv->dma_ring_size - 1)
+			dma_desc->status |= DMAD_ST_WRAP_MASK;
+
+		dma_desc++;
+	}
+
+	/* init to first descriptor */
+	ch_priv->desc_id = 0;
+
+	/* force cache writeback */
+	flush_dcache_range((ulong)ch_priv->dma_ring,
+		ALIGN_END_ADDR(struct bcm6348_dma_desc, ch_priv->dma_ring,
+			       ch_priv->dma_ring_size));
+
+	/* clear sram */
+	writel_be(0, priv->sram + DMAS_STATE_DATA_REG(dma->id));
+	writel_be(0, priv->sram + DMAS_DESC_LEN_STATUS_REG(dma->id));
+	writel_be(0, priv->sram + DMAS_DESC_BASE_BUFPTR_REG(dma->id));
+
+	/* set dma ring start */
+	writel_be(virt_to_phys(ch_priv->dma_ring),
+		  priv->sram + DMAS_RSTART_REG(dma->id));
+
+	/* set flow control */
+	if (bcm6348_iudma_chan_is_rx(dma->id)) {
+		u32 val;
+
+		setbits_be32(priv->base + DMA_CFG_REG,
+			     DMA_CFG_FLOWC_ENABLE(dma->id));
+
+		val = ch_priv->dma_ring_size / 3;
+		writel_be(val, priv->base + DMA_FLOWC_THR_LO_REG(dma->id));
+
+		val = (ch_priv->dma_ring_size * 2) / 3;
+		writel_be(val, priv->base + DMA_FLOWC_THR_HI_REG(dma->id));
+
+		writel_be(0, priv->base + DMA_FLOWC_ALLOC_REG(dma->id));
+	}
+
+	/* set dma max burst */
+	writel_be(ch_priv->dma_ring_size,
+		  priv->chan + DMAC_BURST_REG(dma->id));
+
+	setbits_be32(priv->chan + DMAC_CFG_REG(dma->id), DMAC_CFG_ENABLE_MASK);
+
+	return 0;
+}
+
+static int bcm6348_iudma_request(struct dma *dma)
+{
+	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+	struct bcm6348_chan_priv *ch_priv;
+
+	/* check if channel is valid */
+	if (dma->id >= priv->n_channels)
+		return -ENODEV;
+
+	/* alloc channel private data */
+	priv->ch_priv[dma->id] = calloc(1, sizeof(struct bcm6348_chan_priv));
+	if (!priv->ch_priv[dma->id])
+		return -ENOMEM;
+	ch_priv = priv->ch_priv[dma->id];
+
+	/* alloc dma ring */
+	if (bcm6348_iudma_chan_is_rx(dma->id))
+		ch_priv->dma_ring_size = DMA_RX_DESC;
+	else
+		ch_priv->dma_ring_size = DMA_TX_DESC;
+
+	ch_priv->dma_ring =
+		malloc_cache_aligned(sizeof(struct bcm6348_dma_desc) *
+				     ch_priv->dma_ring_size);
+	if (!ch_priv->dma_ring)
+		return -ENOMEM;
+
+	if (bcm6348_iudma_chan_is_rx(dma->id)) {
+		ch_priv->dma_buff =
+			malloc_cache_aligned(PKTSIZE_ALIGN *
+					     ch_priv->dma_ring_size);
+		if (!ch_priv->dma_buff)
+			return -ENOMEM;
+	} else {
+		ch_priv->dma_buff = NULL;
+	}
+
+	return 0;
+}
+
+static int bcm6348_iudma_receive(struct dma *dma, void **dst, void *metadata)
+{
+	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+	const struct bcm6348_iudma_hw *hw = priv->hw;
+	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+	struct bcm6348_dma_desc *dma_desc;
+	void __iomem *dma_buff;
+	int ret;
+
+	/* get dma ring descriptor address */
+	dma_desc = ch_priv->dma_ring;
+	dma_desc += ch_priv->desc_id;
+
+	/* invalidate cache data */
+	invalidate_dcache_range((ulong)dma_desc,
+		ALIGN_END_ADDR(struct bcm6348_dma_desc, dma_desc, 1));
+
+	/* check dma own */
+	if (dma_desc->status & DMAD_ST_OWN_MASK)
+		return -EAGAIN;
+
+	/* check pkt */
+	if (!(dma_desc->status & DMAD_ST_EOP_MASK) ||
+	    !(dma_desc->status & DMAD_ST_SOP_MASK) ||
+	    (dma_desc->status & hw->err_mask)) {
+		pr_err("invalid pkt received (ch=%ld) (st=%04x)\n",
+		       dma->id, dma_desc->status);
+		ret = -EAGAIN;
+	} else {
+		uint16_t length;
+
+		/* get dma buff descriptor address */
+		dma_buff = phys_to_virt(dma_desc->address);
+
+		/* invalidate cache data */
+		invalidate_dcache_range((ulong)dma_buff,
+					(ulong)(dma_buff + PKTSIZE_ALIGN));
+
+		/* remove crc */
+		length = dma_desc->length - 4;
+
+		/* copy data */
+		memcpy(*dst, dma_buff, length);
+
+		ret = length;
+	}
+
+	/* reinit dma descriptor */
+	dma_desc->length = PKTSIZE_ALIGN;
+	dma_desc->status = (dma_desc->status & DMAD_ST_WRAP_MASK) |
+			   DMAD_ST_OWN_MASK;
+
+	/* flush cache */
+	flush_dcache_range((ulong)dma_desc,
+		ALIGN_END_ADDR(struct bcm6348_dma_desc, dma_desc, 1));
+
+	/* enable dma */
+	setbits_be32(priv->chan + DMAC_CFG_REG(dma->id), DMAC_CFG_ENABLE_MASK);
+
+	/* increment dma descriptor */
+	ch_priv->desc_id = (ch_priv->desc_id + 1) % ch_priv->dma_ring_size;
+
+	return ret;
+}
+
+static int bcm6348_iudma_send(struct dma *dma, void *src, size_t len,
+			      void *metadata)
+{
+	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+	struct bcm6348_dma_desc *dma_desc;
+	uint16_t val;
+
+	/* get dma ring descriptor address */
+	dma_desc = ch_priv->dma_ring;
+	dma_desc += ch_priv->desc_id;
+
+	dma_desc->address = virt_to_phys(src);
+
+	/* config dma descriptor */
+	val = (DMAD_ST_OWN_MASK |
+	       DMAD_ST_EOP_MASK |
+	       DMAD_ST_CRC_MASK |
+	       DMAD_ST_SOP_MASK);
+	if (ch_priv->desc_id == ch_priv->dma_ring_size - 1)
+		val |= DMAD_ST_WRAP_MASK;
+
+	dma_desc->length = len;
+	dma_desc->status = val;
+
+	/* flush cache */
+	flush_dcache_range((ulong)src, (ulong)src + PKTSIZE_ALIGN);
+
+	/* flush cache */
+	flush_dcache_range((ulong)dma_desc,
+		ALIGN_END_ADDR(struct bcm6348_dma_desc, dma_desc, 1));
+
+	/* enable dma */
+	setbits_be32(priv->chan + DMAC_CFG_REG(dma->id), DMAC_CFG_ENABLE_MASK);
+
+	/* poll dma status */
+	do {
+		/* invalidate cache */
+		invalidate_dcache_range((ulong)dma_desc,
+			ALIGN_END_ADDR(struct bcm6348_dma_desc, dma_desc, 1));
+
+		if (!(dma_desc->status & DMAD_ST_OWN_MASK))
+			break;
+	} while(1);
+
+	/* increment dma descriptor */
+	ch_priv->desc_id = (ch_priv->desc_id + 1) % ch_priv->dma_ring_size;
+
+	return 0;
+}
+
+static const struct dma_ops bcm6348_iudma_ops = {
+	.disable = bcm6348_iudma_disable,
+	.enable = bcm6348_iudma_enable,
+	.request = bcm6348_iudma_request,
+	.receive = bcm6348_iudma_receive,
+	.send = bcm6348_iudma_send,
+};
+
+static const struct bcm6348_iudma_hw bcm6348_hw = {
+	.err_mask = (DMAD6348_ST_OV_ERR_MASK |
+		     DMAD6348_ST_CRC_ERR_MASK |
+		     DMAD6348_ST_RX_ERR_MASK |
+		     DMAD6348_ST_OS_ERR_MASK |
+		     DMAD6348_ST_UN_ERR_MASK),
+};
+
+static const struct bcm6348_iudma_hw bcm6368_hw = {
+	.err_mask = 0,
+};
+
+static const struct udevice_id bcm6348_iudma_ids[] = {
+	{
+		.compatible = "brcm,bcm6348-iudma",
+		.data = (ulong)&bcm6348_hw,
+	}, {
+		.compatible = "brcm,bcm6368-iudma",
+		.data = (ulong)&bcm6368_hw,
+	}, { /* sentinel */ }
+};
+
+static int bcm6348_iudma_probe(struct udevice *dev)
+{
+	struct dma_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct bcm6348_iudma_priv *priv = dev_get_priv(dev);
+	const struct bcm6348_iudma_hw *hw =
+		(const struct bcm6348_iudma_hw *)dev_get_driver_data(dev);
+	fdt_addr_t addr;
+	uint8_t ch;
+	int i;
+
+	uc_priv->supported = (DMA_SUPPORTS_DEV_TO_MEM |
+			      DMA_SUPPORTS_MEM_TO_DEV);
+	priv->hw = hw;
+
+	/* try to enable clocks */
+	for (i = 0; ; i++) {
+		struct clk clk;
+		int ret;
+
+		ret = clk_get_by_index(dev, i, &clk);
+		if (ret < 0)
+			break;
+		if (clk_enable(&clk))
+			pr_err("failed to enable clock %d\n", i);
+		clk_free(&clk);
+	}
+
+	/* try to perform resets */
+	for (i = 0; ; i++) {
+		struct reset_ctl reset;
+		int ret;
+
+		ret = reset_get_by_index(dev, i, &reset);
+		if (ret < 0)
+			break;
+		if (reset_deassert(&reset))
+			pr_err("failed to deassert reset %d\n", i);
+		reset_free(&reset);
+	}
+
+	/* dma global base address */
+	addr = devfdt_get_addr_name(dev, "dma");
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+	priv->base = ioremap(addr, 0);
+
+	/* dma channels base address */
+	addr = devfdt_get_addr_name(dev, "dma-channels");
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+	priv->chan = ioremap(addr, 0);
+
+	/* dma sram base address */
+	addr = devfdt_get_addr_name(dev, "dma-sram");
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+	priv->sram = ioremap(addr, 0);
+
+	/* disable dma controller */
+	clrbits_be32(priv->base + DMA_CFG_REG, DMA_CFG_ENABLE_MASK);
+
+	/* get number of channels */
+	priv->n_channels = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
+					   "dma-channels", 8);
+	if (priv->n_channels > DMA_CHAN_MAX)
+		return -EINVAL;
+
+	/* alloc channel private data pointers */
+	priv->ch_priv = calloc(priv->n_channels,
+			       sizeof(struct bcm6348_chan_priv*));
+	if (!priv->ch_priv)
+		return -ENOMEM;
+
+	/* stop dma channels */
+	for (ch = 0; ch < priv->n_channels; ch++)
+		bcm6348_iudma_chan_stop(priv, ch);
+
+	/* enable dma controller */
+	setbits_be32(priv->base + DMA_CFG_REG, DMA_CFG_ENABLE_MASK);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(bcm6348_iudma) = {
+	.name = "bcm6348_iudma",
+	.id = UCLASS_DMA,
+	.of_match = bcm6348_iudma_ids,
+	.ops = &bcm6348_iudma_ops,
+	.priv_auto_alloc_size = sizeof(struct bcm6348_iudma_priv),
+	.probe = bcm6348_iudma_probe,
+};
-- 
2.11.0

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

* [U-Boot] [PATCH v8 05/31] bmips: bcm6338: add bcm6348-iudma support
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (3 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 04/31] dma: add bcm6348-iudma support Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 06/31] bmips: bcm6348: " Álvaro Fernández Rojas
                     ` (28 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6338.dtsi       | 14 ++++++++++++++
 include/dt-bindings/dma/bcm6338-dma.h | 15 +++++++++++++++
 2 files changed, 29 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6338-dma.h

diff --git a/arch/mips/dts/brcm,bcm6338.dtsi b/arch/mips/dts/brcm,bcm6338.dtsi
index bbd58cf803..990355481c 100644
--- a/arch/mips/dts/brcm,bcm6338.dtsi
+++ b/arch/mips/dts/brcm,bcm6338.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6338-clock.h>
+#include <dt-bindings/dma/bcm6338-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/reset/bcm6338-reset.h>
 #include "skeleton.dtsi"
@@ -130,5 +131,18 @@
 			reg = <0xfffe3100 0x38>;
 			u-boot,dm-pre-reloc;
 		};
+
+		iudma: dma-controller at fffe2400 {
+			compatible = "brcm,bcm6348-iudma";
+			reg = <0xfffe2400 0x1c>,
+			      <0xfffe2500 0x60>,
+			      <0xfffe2600 0x60>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <6>;
+			resets = <&periph_rst BCM6338_RST_DMAMEM>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6338-dma.h b/include/dt-bindings/dma/bcm6338-dma.h
new file mode 100644
index 0000000000..5dd66239b4
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6338-dma.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6338_H
+#define __DT_BINDINGS_DMA_BCM6338_H
+
+#define BCM6338_DMA_ENET_RX	0
+#define BCM6338_DMA_ENET_TX	1
+
+#endif /* __DT_BINDINGS_DMA_BCM6338_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v8 06/31] bmips: bcm6348: add bcm6348-iudma support
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (4 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 05/31] bmips: bcm6338: " Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 07/31] bmips: bcm6358: " Álvaro Fernández Rojas
                     ` (27 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6348.dtsi       | 16 ++++++++++++++++
 include/dt-bindings/dma/bcm6348-dma.h | 17 +++++++++++++++++
 2 files changed, 33 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6348-dma.h

diff --git a/arch/mips/dts/brcm,bcm6348.dtsi b/arch/mips/dts/brcm,bcm6348.dtsi
index cc80bbc808..875de232ca 100644
--- a/arch/mips/dts/brcm,bcm6348.dtsi
+++ b/arch/mips/dts/brcm,bcm6348.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6348-clock.h>
+#include <dt-bindings/dma/bcm6348-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/reset/bcm6348-reset.h>
 #include "skeleton.dtsi"
@@ -159,5 +160,20 @@
 			reg = <0xfffe2300 0x38>;
 			u-boot,dm-pre-reloc;
 		};
+
+		iudma: dma-controller at fffe7000 {
+			compatible = "brcm,bcm6348-iudma";
+			reg = <0xfffe7000 0x1c>,
+			      <0xfffe7100 0x40>,
+			      <0xfffe7200 0x40>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <4>;
+			clocks = <&periph_clk BCM6348_CLK_ENET>;
+			resets = <&periph_rst BCM6348_RST_ENET>,
+				 <&periph_rst BCM6348_RST_DMAMEM>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6348-dma.h b/include/dt-bindings/dma/bcm6348-dma.h
new file mode 100644
index 0000000000..a1d3a6456d
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6348-dma.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6348_H
+#define __DT_BINDINGS_DMA_BCM6348_H
+
+#define BCM6348_DMA_ENET0_RX	0
+#define BCM6348_DMA_ENET0_TX	1
+#define BCM6348_DMA_ENET1_RX	2
+#define BCM6348_DMA_ENET1_TX	3
+
+#endif /* __DT_BINDINGS_DMA_BCM6348_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v8 07/31] bmips: bcm6358: add bcm6348-iudma support
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (5 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 06/31] bmips: bcm6348: " Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 08/31] bmips: bcm6368: " Álvaro Fernández Rojas
                     ` (26 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6358.dtsi       | 18 ++++++++++++++++++
 include/dt-bindings/dma/bcm6358-dma.h | 17 +++++++++++++++++
 2 files changed, 35 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6358-dma.h

diff --git a/arch/mips/dts/brcm,bcm6358.dtsi b/arch/mips/dts/brcm,bcm6358.dtsi
index 0617b46e92..5605723e83 100644
--- a/arch/mips/dts/brcm,bcm6358.dtsi
+++ b/arch/mips/dts/brcm,bcm6358.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6358-clock.h>
+#include <dt-bindings/dma/bcm6358-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/reset/bcm6358-reset.h>
 #include "skeleton.dtsi"
@@ -190,5 +191,22 @@
 
 			status = "disabled";
 		};
+
+		iudma: dma-controller at fffe5000 {
+			compatible = "brcm,bcm6348-iudma";
+			reg = <0xfffe5000 0x24>,
+			      <0xfffe5100 0x80>,
+			      <0xfffe5200 0x80>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <8>;
+			clocks = <&periph_clk BCM6358_CLK_EMUSB>,
+				 <&periph_clk BCM6358_CLK_USBSU>,
+				 <&periph_clk BCM6358_CLK_EPHY>;
+			resets = <&periph_rst BCM6358_RST_ENET>,
+				 <&periph_rst BCM6358_RST_EPHY>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6358-dma.h b/include/dt-bindings/dma/bcm6358-dma.h
new file mode 100644
index 0000000000..3b1fcf8540
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6358-dma.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6358_H
+#define __DT_BINDINGS_DMA_BCM6358_H
+
+#define BCM6358_DMA_ENET0_RX	0
+#define BCM6358_DMA_ENET0_TX	1
+#define BCM6358_DMA_ENET1_RX	2
+#define BCM6358_DMA_ENET1_TX	3
+
+#endif /* __DT_BINDINGS_DMA_BCM6358_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v8 08/31] bmips: bcm6368: add bcm6348-iudma support
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (6 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 07/31] bmips: bcm6358: " Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 09/31] bmips: bcm6328: " Álvaro Fernández Rojas
                     ` (25 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6368.dtsi       | 13 +++++++++++++
 include/dt-bindings/dma/bcm6368-dma.h | 15 +++++++++++++++
 2 files changed, 28 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6368-dma.h

diff --git a/arch/mips/dts/brcm,bcm6368.dtsi b/arch/mips/dts/brcm,bcm6368.dtsi
index 65d769ab4f..30047f6360 100644
--- a/arch/mips/dts/brcm,bcm6368.dtsi
+++ b/arch/mips/dts/brcm,bcm6368.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6368-clock.h>
+#include <dt-bindings/dma/bcm6368-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/reset/bcm6368-reset.h>
 #include "skeleton.dtsi"
@@ -192,5 +193,17 @@
 
 			status = "disabled";
 		};
+
+		iudma: dma-controller at 10006800 {
+			compatible = "brcm,bcm6368-iudma";
+			reg = <0x10006800 0x80>,
+			      <0x10006a00 0x80>,
+			      <0x10006c00 0x80>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <8>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6368-dma.h b/include/dt-bindings/dma/bcm6368-dma.h
new file mode 100644
index 0000000000..45ffb89e0a
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6368-dma.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6368_H
+#define __DT_BINDINGS_DMA_BCM6368_H
+
+#define BCM6368_DMA_ENETSW_RX	0
+#define BCM6368_DMA_ENETSW_TX	1
+
+#endif /* __DT_BINDINGS_DMA_BCM6368_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v8 09/31] bmips: bcm6328: add bcm6348-iudma support
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (7 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 08/31] bmips: bcm6368: " Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 10/31] bmips: bcm6362: " Álvaro Fernández Rojas
                     ` (24 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6328.dtsi       | 13 +++++++++++++
 include/dt-bindings/dma/bcm6328-dma.h | 15 +++++++++++++++
 2 files changed, 28 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6328-dma.h

diff --git a/arch/mips/dts/brcm,bcm6328.dtsi b/arch/mips/dts/brcm,bcm6328.dtsi
index e00a2950e2..6fa49e22bb 100644
--- a/arch/mips/dts/brcm,bcm6328.dtsi
+++ b/arch/mips/dts/brcm,bcm6328.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6328-clock.h>
+#include <dt-bindings/dma/bcm6328-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/power-domain/bcm6328-power-domain.h>
 #include <dt-bindings/reset/bcm6328-reset.h>
@@ -187,5 +188,17 @@
 			reg = <0x10003000 0x864>;
 			u-boot,dm-pre-reloc;
 		};
+
+		iudma: dma-controller at 1000d800 {
+			compatible = "brcm,bcm6368-iudma";
+			reg = <0x1000d800 0x80>,
+			      <0x1000da00 0x80>,
+			      <0x1000dc00 0x80>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <8>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6328-dma.h b/include/dt-bindings/dma/bcm6328-dma.h
new file mode 100644
index 0000000000..508a5dc523
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6328-dma.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6328_H
+#define __DT_BINDINGS_DMA_BCM6328_H
+
+#define BCM6328_DMA_ENETSW_RX	0
+#define BCM6328_DMA_ENETSW_TX	1
+
+#endif /* __DT_BINDINGS_DMA_BCM6328_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v8 10/31] bmips: bcm6362: add bcm6348-iudma support
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (8 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 09/31] bmips: bcm6328: " Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 11/31] bmips: bcm63268: " Álvaro Fernández Rojas
                     ` (23 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6362.dtsi       | 13 +++++++++++++
 include/dt-bindings/dma/bcm6362-dma.h | 15 +++++++++++++++
 2 files changed, 28 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6362-dma.h

diff --git a/arch/mips/dts/brcm,bcm6362.dtsi b/arch/mips/dts/brcm,bcm6362.dtsi
index 3047b82b21..94e7de096d 100644
--- a/arch/mips/dts/brcm,bcm6362.dtsi
+++ b/arch/mips/dts/brcm,bcm6362.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6362-clock.h>
+#include <dt-bindings/dma/bcm6362-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/power-domain/bcm6362-power-domain.h>
 #include <dt-bindings/reset/bcm6362-reset.h>
@@ -211,5 +212,17 @@
 			reg = <0x10003000 0x864>;
 			u-boot,dm-pre-reloc;
 		};
+
+		iudma: dma-controller at 1000d800 {
+			compatible = "brcm,bcm6368-iudma";
+			reg = <0x1000d800 0x80>,
+			      <0x1000da00 0x80>,
+			      <0x1000dc00 0x80>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <8>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6362-dma.h b/include/dt-bindings/dma/bcm6362-dma.h
new file mode 100644
index 0000000000..b90b3ffeb6
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6362-dma.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6362_H
+#define __DT_BINDINGS_DMA_BCM6362_H
+
+#define BCM6362_DMA_ENETSW_RX	0
+#define BCM6362_DMA_ENETSW_TX	1
+
+#endif /* __DT_BINDINGS_DMA_BCM6362_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v8 11/31] bmips: bcm63268: add bcm6348-iudma support
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (9 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 10/31] bmips: bcm6362: " Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 12/31] bmips: bcm6318: " Álvaro Fernández Rojas
                     ` (22 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm63268.dtsi       | 13 +++++++++++++
 include/dt-bindings/dma/bcm63268-dma.h | 15 +++++++++++++++
 2 files changed, 28 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm63268-dma.h

diff --git a/arch/mips/dts/brcm,bcm63268.dtsi b/arch/mips/dts/brcm,bcm63268.dtsi
index 62c440e675..c7ad83c306 100644
--- a/arch/mips/dts/brcm,bcm63268.dtsi
+++ b/arch/mips/dts/brcm,bcm63268.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm63268-clock.h>
+#include <dt-bindings/dma/bcm63268-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/power-domain/bcm63268-power-domain.h>
 #include <dt-bindings/reset/bcm63268-reset.h>
@@ -217,5 +218,17 @@
 			reg = <0x10003000 0x894>;
 			u-boot,dm-pre-reloc;
 		};
+
+		iudma: dma-controller at 1000d800 {
+			compatible = "brcm,bcm6368-iudma";
+			reg = <0x1000d800 0x80>,
+			      <0x1000da00 0x80>,
+			      <0x1000dc00 0x80>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <8>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm63268-dma.h b/include/dt-bindings/dma/bcm63268-dma.h
new file mode 100644
index 0000000000..d5d7453be1
--- /dev/null
+++ b/include/dt-bindings/dma/bcm63268-dma.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM63268_H
+#define __DT_BINDINGS_DMA_BCM63268_H
+
+#define BCM63268_DMA_ENETSW_RX	0
+#define BCM63268_DMA_ENETSW_TX	1
+
+#endif /* __DT_BINDINGS_DMA_BCM63268_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v8 12/31] bmips: bcm6318: add bcm6348-iudma support
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (10 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 11/31] bmips: bcm63268: " Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 13/31] net: add support for bcm6348-enet Álvaro Fernández Rojas
                     ` (21 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6318.dtsi       | 19 +++++++++++++++++++
 include/dt-bindings/dma/bcm6318-dma.h | 15 +++++++++++++++
 2 files changed, 34 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6318-dma.h

diff --git a/arch/mips/dts/brcm,bcm6318.dtsi b/arch/mips/dts/brcm,bcm6318.dtsi
index f75988be12..d04b7cbb01 100644
--- a/arch/mips/dts/brcm,bcm6318.dtsi
+++ b/arch/mips/dts/brcm,bcm6318.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6318-clock.h>
+#include <dt-bindings/dma/bcm6318-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/power-domain/bcm6318-power-domain.h>
 #include <dt-bindings/reset/bcm6318-reset.h>
@@ -54,6 +55,12 @@
 			reg = <0x10000004 0x4>;
 			#clock-cells = <1>;
 		};
+
+		ubus_clk: ubus-clk {
+			compatible = "brcm,bcm6345-clk";
+			reg = <0x10000008 0x4>;
+			#clock-cells = <1>;
+		};
 	};
 
 	ubus {
@@ -182,5 +189,17 @@
 
 			status = "disabled";
 		};
+
+		iudma: dma-controller at 10088000 {
+			compatible = "brcm,bcm6368-iudma";
+			reg = <0x10088000 0x80>,
+			      <0x10088200 0x80>,
+			      <0x10088400 0x80>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <8>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6318-dma.h b/include/dt-bindings/dma/bcm6318-dma.h
new file mode 100644
index 0000000000..c039391395
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6318-dma.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6318_H
+#define __DT_BINDINGS_DMA_BCM6318_H
+
+#define BCM6318_DMA_ENETSW_RX	0
+#define BCM6318_DMA_ENETSW_TX	1
+
+#endif /* __DT_BINDINGS_DMA_BCM6318_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v8 13/31] net: add support for bcm6348-enet
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (11 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 12/31] bmips: bcm6318: " Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 14/31] bmips: bcm6338: " Álvaro Fernández Rojas
                     ` (20 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: Introduce changes from Grygorii Strashko
 v5: Receive as much packets as possible from bcm6348-eth and cache them in
 net_rx_packets. This is needed in order to fix flow control issues.
 v4: Fix issues reported by Grygorii Strashko and other fixes:
  - Copy received dma buffer to net_rx_packets in order to avoid possible
  dma overwrites.
  - Reset dma rx channel when sending a new packet to prevent flow control
  issues.
  - Fix packet casting on bcm6348_eth_recv/send.
 v3: no changes
 v2: select DMA_CHANNELS.

 drivers/net/Kconfig            |  10 +
 drivers/net/Makefile           |   1 +
 drivers/net/bcm6348-eth.c      | 576 +++++++++++++++++++++++++++++++++++++++++
 include/configs/bmips_common.h |   5 +-
 4 files changed, 591 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/bcm6348-eth.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 8fb365fc5d..2b7cec8804 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -72,6 +72,16 @@ config BCM_SF2_ETH_GMAC
 	  by the BCM_SF2_ETH driver.
 	  Say Y to any bcmcygnus based platforms.
 
+config BCM6348_ETH
+	bool "BCM6348 EMAC support"
+	depends on DM_ETH && ARCH_BMIPS
+	select DMA
+	select DMA_CHANNELS
+	select MII
+	select PHYLIB
+	help
+	  This driver supports the BCM6348 Ethernet MAC.
+
 config DWC_ETH_QOS
 	bool "Synopsys DWC Ethernet QOS device support"
 	depends on DM_ETH
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 99056aa041..2647d4dd23 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -6,6 +6,7 @@
 obj-$(CONFIG_ALTERA_TSE) += altera_tse.o
 obj-$(CONFIG_AG7XXX) += ag7xxx.o
 obj-$(CONFIG_ARMADA100_FEC) += armada100_fec.o
+obj-$(CONFIG_BCM6348_ETH) += bcm6348-eth.o
 obj-$(CONFIG_DRIVER_AT91EMAC) += at91_emac.o
 obj-$(CONFIG_DRIVER_AX88180) += ax88180.o
 obj-$(CONFIG_BCM_SF2_ETH) += bcm-sf2-eth.o
diff --git a/drivers/net/bcm6348-eth.c b/drivers/net/bcm6348-eth.c
new file mode 100644
index 0000000000..27c812ff4a
--- /dev/null
+++ b/drivers/net/bcm6348-eth.c
@@ -0,0 +1,576 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c:
+ *	Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dma.h>
+#include <miiphy.h>
+#include <net.h>
+#include <phy.h>
+#include <reset.h>
+#include <wait_bit.h>
+#include <asm/io.h>
+
+#define ETH_RX_DESC			PKTBUFSRX
+#define ETH_MAX_MTU_SIZE		1518
+#define ETH_TIMEOUT			100
+#define ETH_TX_WATERMARK		32
+
+/* ETH Receiver Configuration register */
+#define ETH_RXCFG_REG			0x00
+#define ETH_RXCFG_ENFLOW_SHIFT		5
+#define ETH_RXCFG_ENFLOW_MASK		(1 << ETH_RXCFG_ENFLOW_SHIFT)
+
+/* ETH Receive Maximum Length register */
+#define ETH_RXMAXLEN_REG		0x04
+#define ETH_RXMAXLEN_SHIFT		0
+#define ETH_RXMAXLEN_MASK		(0x7ff << ETH_RXMAXLEN_SHIFT)
+
+/* ETH Transmit Maximum Length register */
+#define ETH_TXMAXLEN_REG		0x08
+#define ETH_TXMAXLEN_SHIFT		0
+#define ETH_TXMAXLEN_MASK		(0x7ff << ETH_TXMAXLEN_SHIFT)
+
+/* MII Status/Control register */
+#define MII_SC_REG			0x10
+#define MII_SC_MDCFREQDIV_SHIFT		0
+#define MII_SC_MDCFREQDIV_MASK		(0x7f << MII_SC_MDCFREQDIV_SHIFT)
+#define MII_SC_PREAMBLE_EN_SHIFT	7
+#define MII_SC_PREAMBLE_EN_MASK		(1 << MII_SC_PREAMBLE_EN_SHIFT)
+
+/* MII Data register */
+#define MII_DAT_REG			0x14
+#define MII_DAT_DATA_SHIFT		0
+#define MII_DAT_DATA_MASK		(0xffff << MII_DAT_DATA_SHIFT)
+#define MII_DAT_TA_SHIFT		16
+#define MII_DAT_TA_MASK			(0x3 << MII_DAT_TA_SHIFT)
+#define MII_DAT_REG_SHIFT		18
+#define MII_DAT_REG_MASK		(0x1f << MII_DAT_REG_SHIFT)
+#define MII_DAT_PHY_SHIFT		23
+#define MII_DAT_PHY_MASK		(0x1f << MII_DAT_PHY_SHIFT)
+#define MII_DAT_OP_SHIFT		28
+#define MII_DAT_OP_WRITE		(0x5 << MII_DAT_OP_SHIFT)
+#define MII_DAT_OP_READ			(0x6 << MII_DAT_OP_SHIFT)
+
+/* ETH Interrupts Mask register */
+#define ETH_IRMASK_REG			0x18
+
+/* ETH Interrupts register */
+#define ETH_IR_REG			0x1c
+#define ETH_IR_MII_SHIFT		0
+#define ETH_IR_MII_MASK			(1 << ETH_IR_MII_SHIFT)
+
+/* ETH Control register */
+#define ETH_CTL_REG			0x2c
+#define ETH_CTL_ENABLE_SHIFT		0
+#define ETH_CTL_ENABLE_MASK		(1 << ETH_CTL_ENABLE_SHIFT)
+#define ETH_CTL_DISABLE_SHIFT		1
+#define ETH_CTL_DISABLE_MASK		(1 << ETH_CTL_DISABLE_SHIFT)
+#define ETH_CTL_RESET_SHIFT		2
+#define ETH_CTL_RESET_MASK		(1 << ETH_CTL_RESET_SHIFT)
+#define ETH_CTL_EPHY_SHIFT		3
+#define ETH_CTL_EPHY_MASK		(1 << ETH_CTL_EPHY_SHIFT)
+
+/* ETH Transmit Control register */
+#define ETH_TXCTL_REG			0x30
+#define ETH_TXCTL_FD_SHIFT		0
+#define ETH_TXCTL_FD_MASK		(1 << ETH_TXCTL_FD_SHIFT)
+
+/* ETH Transmit Watermask register */
+#define ETH_TXWMARK_REG			0x34
+#define ETH_TXWMARK_WM_SHIFT		0
+#define ETH_TXWMARK_WM_MASK		(0x3f << ETH_TXWMARK_WM_SHIFT)
+
+/* MIB Control register */
+#define MIB_CTL_REG			0x38
+#define MIB_CTL_RDCLEAR_SHIFT		0
+#define MIB_CTL_RDCLEAR_MASK		(1 << MIB_CTL_RDCLEAR_SHIFT)
+
+/* ETH Perfect Match registers */
+#define ETH_PM_CNT			4
+#define ETH_PML_REG(x)			(0x58 + (x) * 0x8)
+#define ETH_PMH_REG(x)			(0x5c + (x) * 0x8)
+#define ETH_PMH_VALID_SHIFT		16
+#define ETH_PMH_VALID_MASK		(1 << ETH_PMH_VALID_SHIFT)
+
+/* MIB Counters registers */
+#define MIB_REG_CNT			55
+#define MIB_REG(x)			(0x200 + (x) * 4)
+
+/* ETH data */
+struct bcm6348_eth_priv {
+	void __iomem *base;
+	/* RX */
+	uint8_t rx_desc;
+	uint8_t rx_pend;
+	int rx_ret[ETH_RX_DESC];
+	/* DMA */
+	struct dma rx_dma;
+	struct dma tx_dma;
+	/* PHY */
+	int phy_id;
+	struct phy_device *phy_dev;
+};
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void bcm6348_eth_mac_disable(struct bcm6348_eth_priv *priv)
+{
+	/* disable emac */
+	clrsetbits_be32(priv->base + ETH_CTL_REG, ETH_CTL_ENABLE_MASK,
+			ETH_CTL_DISABLE_MASK);
+
+	/* wait until emac is disabled */
+	if (wait_for_bit_be32(priv->base + ETH_CTL_REG,
+			      ETH_CTL_DISABLE_MASK, false,
+			      ETH_TIMEOUT, false))
+		pr_err("error disabling emac\n");
+}
+
+static void bcm6348_eth_mac_enable(struct bcm6348_eth_priv *priv)
+{
+	setbits_be32(priv->base + ETH_CTL_REG, ETH_CTL_ENABLE_MASK);
+}
+
+static void bcm6348_eth_mac_reset(struct bcm6348_eth_priv *priv)
+{
+	/* reset emac */
+	writel_be(ETH_CTL_RESET_MASK, priv->base + ETH_CTL_REG);
+	wmb();
+
+	/* wait until emac is reset */
+	if (wait_for_bit_be32(priv->base + ETH_CTL_REG,
+			      ETH_CTL_RESET_MASK, false,
+			      ETH_TIMEOUT, false))
+		pr_err("error resetting emac\n");
+}
+
+static int bcm6348_eth_free_pkt(struct udevice *dev, uchar *packet, int len)
+{
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+
+	/* sanity check */
+	if (packet != net_rx_packets[priv->rx_pend]) {
+		pr_err("rx_pend %d: packet is not matched,\n", priv->rx_pend);
+		return -EAGAIN;
+	}
+
+	/* free pending packet */
+	priv->rx_ret[priv->rx_pend] = 0;
+	priv->rx_pend = (priv->rx_pend + 1) % ETH_RX_DESC;
+
+	return 0;
+}
+
+static int _bcm6348_eth_recv(struct bcm6348_eth_priv *priv)
+{
+	uint8_t pkt = priv->rx_desc;
+
+	/* check if packet is free */
+	if (priv->rx_ret[pkt] > 0)
+		return -EAGAIN;
+
+	/* try to receive a new packet */
+	priv->rx_ret[pkt] = dma_receive(&priv->rx_dma,
+					(void **)&net_rx_packets[pkt],
+					NULL);
+	if (priv->rx_ret[pkt] > 0)
+		priv->rx_desc = (priv->rx_desc + 1) % ETH_RX_DESC;
+
+	return priv->rx_ret[pkt];
+}
+
+static int bcm6348_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+	uint8_t pkt_cnt = 0;
+	int ret;
+
+	/* try to receive packets */
+	while (_bcm6348_eth_recv(priv) > 0)
+		pkt_cnt++;
+
+	if (pkt_cnt)
+		debug("%s: received %u packet(s)\n", __func__, pkt_cnt);
+
+	/* return current packet */
+	ret = priv->rx_ret[priv->rx_pend];
+	if (ret > 0)
+		*packetp = net_rx_packets[priv->rx_pend];
+
+	return ret;
+}
+
+static int bcm6348_eth_send(struct udevice *dev, void *packet, int length)
+{
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+
+	/* reset dma rx channel */
+	dma_disable(&priv->rx_dma);
+	dma_enable(&priv->rx_dma);
+
+	return dma_send(&priv->tx_dma, (void *)packet, length, NULL);
+}
+
+static int bcm6348_eth_adjust_link(struct udevice *dev,
+				   struct phy_device *phydev)
+{
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+
+	/* mac duplex parameters */
+	if (phydev->duplex)
+		setbits_be32(priv->base + ETH_TXCTL_REG, ETH_TXCTL_FD_MASK);
+	else
+		clrbits_be32(priv->base + ETH_TXCTL_REG, ETH_TXCTL_FD_MASK);
+
+	/* rx flow control (pause frame handling) */
+	if (phydev->pause)
+		setbits_be32(priv->base + ETH_RXCFG_REG,
+			     ETH_RXCFG_ENFLOW_MASK);
+	else
+		clrbits_be32(priv->base + ETH_RXCFG_REG,
+			     ETH_RXCFG_ENFLOW_MASK);
+
+	return 0;
+}
+
+static int bcm6348_eth_start(struct udevice *dev)
+{
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+	int ret, i;
+
+	priv->rx_desc = 0;
+	priv->rx_pend = 0;
+	for (i = 0; i < ETH_RX_DESC; i++)
+		priv->rx_ret[i] = 0;
+
+	/* enable dma rx channel */
+	dma_enable(&priv->rx_dma);
+
+	/* enable dma tx channel */
+	dma_enable(&priv->tx_dma);
+
+	ret = phy_startup(priv->phy_dev);
+	if (ret) {
+		pr_err("could not initialize phy\n");
+		return ret;
+	}
+
+	if (!priv->phy_dev->link) {
+		pr_err("no phy link\n");
+		return -EIO;
+	}
+
+	bcm6348_eth_adjust_link(dev, priv->phy_dev);
+
+	/* zero mib counters */
+	for (i = 0; i < MIB_REG_CNT; i++)
+		writel_be(0, MIB_REG(i));
+
+	/* enable rx flow control */
+	setbits_be32(priv->base + ETH_RXCFG_REG, ETH_RXCFG_ENFLOW_MASK);
+
+	/* set max rx/tx length */
+	writel_be((ETH_MAX_MTU_SIZE << ETH_RXMAXLEN_SHIFT) &
+		  ETH_RXMAXLEN_MASK, priv->base + ETH_RXMAXLEN_REG);
+	writel_be((ETH_MAX_MTU_SIZE << ETH_TXMAXLEN_SHIFT) &
+		   ETH_TXMAXLEN_MASK, priv->base + ETH_TXMAXLEN_REG);
+
+	/* set correct transmit fifo watermark */
+	writel_be((ETH_TX_WATERMARK << ETH_TXWMARK_WM_SHIFT) &
+		  ETH_TXWMARK_WM_MASK, priv->base + ETH_TXWMARK_REG);
+
+	/* enable emac */
+	bcm6348_eth_mac_enable(priv);
+
+	/* clear interrupts */
+	writel_be(0, priv->base + ETH_IRMASK_REG);
+
+	return 0;
+}
+
+static void bcm6348_eth_stop(struct udevice *dev)
+{
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+
+	/* disable dma rx channel */
+	dma_disable(&priv->rx_dma);
+
+	/* disable dma tx channel */
+	dma_disable(&priv->tx_dma);
+
+	/* disable emac */
+	bcm6348_eth_mac_disable(priv);
+}
+
+static int bcm6348_eth_write_hwaddr(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+	bool running = false;
+
+	/* check if emac is running */
+	if (readl_be(priv->base + ETH_CTL_REG) & ETH_CTL_ENABLE_MASK)
+		running = true;
+
+	/* disable emac */
+	if (running)
+		bcm6348_eth_mac_disable(priv);
+
+	/* set mac address */
+	writel_be((pdata->enetaddr[2] << 24) | (pdata->enetaddr[3]) << 16 |
+		  (pdata->enetaddr[4]) << 8 | (pdata->enetaddr[5]),
+		  priv->base + ETH_PML_REG(0));
+	writel_be((pdata->enetaddr[1]) | (pdata->enetaddr[0] << 8) |
+		  ETH_PMH_VALID_MASK, priv->base + ETH_PMH_REG(0));
+
+	/* enable emac */
+	if (running)
+		bcm6348_eth_mac_enable(priv);
+
+	return 0;
+}
+
+static const struct eth_ops bcm6348_eth_ops = {
+	.free_pkt = bcm6348_eth_free_pkt,
+	.recv = bcm6348_eth_recv,
+	.send = bcm6348_eth_send,
+	.start = bcm6348_eth_start,
+	.stop = bcm6348_eth_stop,
+	.write_hwaddr = bcm6348_eth_write_hwaddr,
+};
+
+static const struct udevice_id bcm6348_eth_ids[] = {
+	{ .compatible = "brcm,bcm6348-enet", },
+	{ /* sentinel */ }
+};
+
+static int bcm6348_mdio_op(void __iomem *base, uint32_t data)
+{
+	/* make sure mii interrupt status is cleared */
+	writel_be(ETH_IR_MII_MASK, base + ETH_IR_REG);
+
+	/* issue mii op */
+	writel_be(data, base + MII_DAT_REG);
+
+	/* wait until emac is disabled */
+	return wait_for_bit_be32(base + ETH_IR_REG,
+				 ETH_IR_MII_MASK, true,
+				 ETH_TIMEOUT, false);
+}
+
+static int bcm6348_mdio_read(struct mii_dev *bus, int addr, int devaddr,
+			     int reg)
+{
+	void __iomem *base = bus->priv;
+	uint32_t val;
+
+	val = MII_DAT_OP_READ;
+	val |= (reg << MII_DAT_REG_SHIFT) & MII_DAT_REG_MASK;
+	val |= (0x2 << MII_DAT_TA_SHIFT) & MII_DAT_TA_MASK;
+	val |= (addr << MII_DAT_PHY_SHIFT) & MII_DAT_PHY_MASK;
+
+	if (bcm6348_mdio_op(base, val)) {
+		pr_err("%s: timeout\n", __func__);
+		return -EINVAL;
+	}
+
+	val = readl_be(base + MII_DAT_REG) & MII_DAT_DATA_MASK;
+	val >>= MII_DAT_DATA_SHIFT;
+
+	return val;
+}
+
+static int bcm6348_mdio_write(struct mii_dev *bus, int addr, int dev_addr,
+			      int reg, u16 value)
+{
+	void __iomem *base = bus->priv;
+	uint32_t val;
+
+	val = MII_DAT_OP_WRITE;
+	val |= (reg << MII_DAT_REG_SHIFT) & MII_DAT_REG_MASK;
+	val |= (0x2 << MII_DAT_TA_SHIFT) & MII_DAT_TA_MASK;
+	val |= (addr << MII_DAT_PHY_SHIFT) & MII_DAT_PHY_MASK;
+	val |= (value << MII_DAT_DATA_SHIFT) & MII_DAT_DATA_MASK;
+
+	if (bcm6348_mdio_op(base, val)) {
+		pr_err("%s: timeout\n", __func__);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int bcm6348_mdio_init(const char *name, void __iomem *base)
+{
+	struct mii_dev *bus;
+
+	bus = mdio_alloc();
+	if (!bus) {
+		pr_err("%s: failed to allocate MDIO bus\n", __func__);
+		return -ENOMEM;
+	}
+
+	bus->read = bcm6348_mdio_read;
+	bus->write = bcm6348_mdio_write;
+	bus->priv = base;
+	snprintf(bus->name, sizeof(bus->name), "%s", name);
+
+	return mdio_register(bus);
+}
+
+static int bcm6348_phy_init(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+	struct mii_dev *bus;
+
+	/* get mii bus */
+	bus = miiphy_get_dev_by_name(dev->name);
+
+	/* phy connect */
+	priv->phy_dev = phy_connect(bus, priv->phy_id, dev,
+				    pdata->phy_interface);
+	if (!priv->phy_dev) {
+		pr_err("%s: no phy device\n", __func__);
+		return -ENODEV;
+	}
+
+	priv->phy_dev->supported = (SUPPORTED_10baseT_Half |
+				    SUPPORTED_10baseT_Full |
+				    SUPPORTED_100baseT_Half |
+				    SUPPORTED_100baseT_Full |
+				    SUPPORTED_Autoneg |
+				    SUPPORTED_Pause |
+				    SUPPORTED_MII);
+	priv->phy_dev->advertising = priv->phy_dev->supported;
+
+	/* phy config */
+	phy_config(priv->phy_dev);
+
+	return 0;
+}
+
+static int bcm6348_eth_probe(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+	void *blob = (void *)gd->fdt_blob;
+	int node = dev_of_offset(dev);
+	const char *phy_mode;
+	fdt_addr_t addr;
+	int phy_node, ret, i;
+
+	/* get base address */
+	addr = devfdt_get_addr(dev);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	/* get phy mode */
+	pdata->phy_interface = PHY_INTERFACE_MODE_NONE;
+	phy_mode = fdt_getprop(blob, node, "phy-mode", NULL);
+	if (phy_mode)
+		pdata->phy_interface = phy_get_interface_by_name(phy_mode);
+	if (pdata->phy_interface == PHY_INTERFACE_MODE_NONE)
+		return -ENODEV;
+
+	/* get phy */
+	phy_node = fdtdec_lookup_phandle(blob, node, "phy");
+	if (phy_node >= 0)
+		priv->phy_id = fdtdec_get_int(blob, phy_node, "reg", -1);
+	else
+		return -EINVAL;
+
+	/* get dma channels */
+	ret = dma_get_by_name(dev, "tx", &priv->tx_dma);
+	if (ret)
+		return -EINVAL;
+
+	ret = dma_get_by_name(dev, "rx", &priv->rx_dma);
+	if (ret)
+		return -EINVAL;
+
+	/* try to enable clocks */
+	for (i = 0; ; i++) {
+		struct clk clk;
+		int ret;
+
+		ret = clk_get_by_index(dev, i, &clk);
+		if (ret < 0)
+			break;
+		if (clk_enable(&clk))
+			pr_err("failed to enable clock %d\n", i);
+		clk_free(&clk);
+	}
+
+	/* try to perform resets */
+	for (i = 0; ; i++) {
+		struct reset_ctl reset;
+		int ret;
+
+		ret = reset_get_by_index(dev, i, &reset);
+		if (ret < 0)
+			break;
+		if (reset_deassert(&reset))
+			pr_err("failed to deassert reset %d\n", i);
+		reset_free(&reset);
+	}
+
+	/* get base addr */
+	priv->base = ioremap(addr, 0);
+	pdata->iobase = (phys_addr_t) priv->base;
+
+	/* disable emac */
+	bcm6348_eth_mac_disable(priv);
+
+	/* reset emac */
+	bcm6348_eth_mac_reset(priv);
+
+	/* select correct mii interface */
+	if (pdata->phy_interface == PHY_INTERFACE_MODE_INTERNAL)
+		clrbits_be32(priv->base + ETH_CTL_REG, ETH_CTL_EPHY_MASK);
+	else
+		setbits_be32(priv->base + ETH_CTL_REG, ETH_CTL_EPHY_MASK);
+
+	/* turn on mdc clock */
+	writel_be((0x1f << MII_SC_MDCFREQDIV_SHIFT) |
+		  MII_SC_PREAMBLE_EN_MASK, priv->base + MII_SC_REG);
+
+	/* set mib counters to not clear when read */
+	clrbits_be32(priv->base + MIB_CTL_REG, MIB_CTL_RDCLEAR_MASK);
+
+	/* initialize perfect match registers */
+	for (i = 0; i < ETH_PM_CNT; i++) {
+		writel_be(0, priv->base + ETH_PML_REG(i));
+		writel_be(0, priv->base + ETH_PMH_REG(i));
+	}
+
+	/* init mii bus */
+	ret = bcm6348_mdio_init(dev->name, priv->base);
+	if (ret)
+		return ret;
+
+	/* init phy */
+	ret = bcm6348_phy_init(dev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+U_BOOT_DRIVER(bcm6348_eth) = {
+	.name = "bcm6348_eth",
+	.id = UCLASS_ETH,
+	.of_match = bcm6348_eth_ids,
+	.ops = &bcm6348_eth_ops,
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+	.priv_auto_alloc_size = sizeof(struct bcm6348_eth_priv),
+	.probe = bcm6348_eth_probe,
+};
diff --git a/include/configs/bmips_common.h b/include/configs/bmips_common.h
index 39ca2e0bf3..65aa9c77cc 100644
--- a/include/configs/bmips_common.h
+++ b/include/configs/bmips_common.h
@@ -6,6 +6,9 @@
 #ifndef __CONFIG_BMIPS_COMMON_H
 #define __CONFIG_BMIPS_COMMON_H
 
+/* ETH */
+#define CONFIG_PHY_RESET_DELAY		20
+
 /* UART */
 #define CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200, \
 					  230400, 500000, 1500000 }
@@ -16,7 +19,7 @@
 
 /* Memory usage */
 #define CONFIG_SYS_MAXARGS		24
-#define CONFIG_SYS_MALLOC_LEN		(1024 * 1024)
+#define CONFIG_SYS_MALLOC_LEN		(2 * 1024 * 1024)
 #define CONFIG_SYS_BOOTPARAMS_LEN	(128 * 1024)
 #define CONFIG_SYS_CBSIZE		512
 
-- 
2.11.0

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

* [U-Boot] [PATCH v8 14/31] bmips: bcm6338: add support for bcm6348-enet
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (12 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 13/31] net: add support for bcm6348-enet Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 15/31] bmips: enable f@st1704 enet support Álvaro Fernández Rojas
                     ` (19 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6338.dtsi | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6338.dtsi b/arch/mips/dts/brcm,bcm6338.dtsi
index 990355481c..c547e949dd 100644
--- a/arch/mips/dts/brcm,bcm6338.dtsi
+++ b/arch/mips/dts/brcm,bcm6338.dtsi
@@ -144,5 +144,20 @@
 			dma-channels = <6>;
 			resets = <&periph_rst BCM6338_RST_DMAMEM>;
 		};
+
+		enet: ethernet at fffe2800 {
+			compatible = "brcm,bcm6348-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xfffe2800 0x2dc>;
+			clocks = <&periph_clk BCM6338_CLK_ENET>;
+			resets = <&periph_rst BCM6338_RST_ENET>;
+			dmas = <&iudma BCM6338_DMA_ENET_RX>,
+			       <&iudma BCM6338_DMA_ENET_TX>;
+			dma-names = "rx",
+				    "tx";
+
+			status = "disabled";
+		};
 	};
 };
-- 
2.11.0

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

* [U-Boot] [PATCH v8 15/31] bmips: enable f@st1704 enet support
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (13 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 14/31] bmips: bcm6338: " Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 16/31] bmips: bcm6348: add support for bcm6348-enet Álvaro Fernández Rojas
                     ` (18 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/sagem,f at st1704.dts     | 12 ++++++++++++
 configs/sagem_f at st1704_ram_defconfig |  8 +++++++-
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/sagem,f at st1704.dts b/arch/mips/dts/sagem,f at st1704.dts
index 5300f8b6df..ec6846dd9f 100644
--- a/arch/mips/dts/sagem,f at st1704.dts
+++ b/arch/mips/dts/sagem,f at st1704.dts
@@ -39,6 +39,18 @@
 	};
 };
 
+&enet {
+	status = "okay";
+	phy = <&enetphy>;
+	phy-mode = "mii";
+
+	enetphy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio {
 	status = "okay";
 };
diff --git a/configs/sagem_f at st1704_ram_defconfig b/configs/sagem_f at st1704_ram_defconfig
index 91a966327a..8c36f5dbf8 100644
--- a/configs/sagem_f at st1704_ram_defconfig
+++ b/configs/sagem_f at st1704_ram_defconfig
@@ -27,11 +27,14 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="sagem,f at st1704"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
@@ -40,6 +43,9 @@ CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_SPI_FLASH_MTD=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6348_ETH=y
 CONFIG_DM_RESET=y
 CONFIG_RESET_BCM6345=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
-- 
2.11.0

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

* [U-Boot] [PATCH v8 16/31] bmips: bcm6348: add support for bcm6348-enet
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (14 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 15/31] bmips: enable f@st1704 enet support Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 17/31] bmips: enable ct-5361 enet support Álvaro Fernández Rojas
                     ` (17 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6348.dtsi | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6348.dtsi b/arch/mips/dts/brcm,bcm6348.dtsi
index 875de232ca..79e7bd892b 100644
--- a/arch/mips/dts/brcm,bcm6348.dtsi
+++ b/arch/mips/dts/brcm,bcm6348.dtsi
@@ -161,6 +161,32 @@
 			u-boot,dm-pre-reloc;
 		};
 
+		enet0: ethernet at fffe6000 {
+			compatible = "brcm,bcm6348-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xfffe6000 0x2dc>;
+			dmas = <&iudma BCM6348_DMA_ENET0_RX>,
+			       <&iudma BCM6348_DMA_ENET0_TX>;
+			dma-names = "rx",
+				    "tx";
+
+			status = "disabled";
+		};
+
+		enet1: ethernet at fffe6800 {
+			compatible = "brcm,bcm6348-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xfffe6800 0x2dc>;
+			dmas = <&iudma BCM6348_DMA_ENET1_RX>,
+			       <&iudma BCM6348_DMA_ENET1_TX>;
+			dma-names = "rx",
+				    "tx";
+
+			status = "disabled";
+		};
+
 		iudma: dma-controller at fffe7000 {
 			compatible = "brcm,bcm6348-iudma";
 			reg = <0xfffe7000 0x1c>,
-- 
2.11.0

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

* [U-Boot] [PATCH v8 17/31] bmips: enable ct-5361 enet support
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (15 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 16/31] bmips: bcm6348: add support for bcm6348-enet Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 18/31] bmips: bcm6358: add support for bcm6348-enet Álvaro Fernández Rojas
                     ` (16 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/comtrend,ct-5361.dts    | 12 ++++++++++++
 configs/comtrend_ct5361_ram_defconfig |  8 +++++++-
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/comtrend,ct-5361.dts b/arch/mips/dts/comtrend,ct-5361.dts
index 25747ca95d..f6b8a94e25 100644
--- a/arch/mips/dts/comtrend,ct-5361.dts
+++ b/arch/mips/dts/comtrend,ct-5361.dts
@@ -34,6 +34,18 @@
 	};
 };
 
+&enet1 {
+	status = "okay";
+	phy = <&enet1phy>;
+	phy-mode = "mii";
+
+	enet1phy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
diff --git a/configs/comtrend_ct5361_ram_defconfig b/configs/comtrend_ct5361_ram_defconfig
index 82f2070713..6297e78fd9 100644
--- a/configs/comtrend_ct5361_ram_defconfig
+++ b/configs/comtrend_ct5361_ram_defconfig
@@ -25,11 +25,14 @@ CONFIG_CMD_LICENSE=y
 CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="comtrend,ct-5361"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
@@ -40,6 +43,9 @@ CONFIG_FLASH_CFI_DRIVER=y
 CONFIG_CFI_FLASH=y
 CONFIG_SYS_FLASH_PROTECTION=y
 CONFIG_SYS_FLASH_CFI=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6348_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6348_USBH_PHY=y
 CONFIG_DM_RESET=y
-- 
2.11.0

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

* [U-Boot] [PATCH v8 18/31] bmips: bcm6358: add support for bcm6348-enet
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (16 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 17/31] bmips: enable ct-5361 enet support Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 19/31] bmips: enable hg556a enet support Álvaro Fernández Rojas
                     ` (15 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6358.dtsi | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6358.dtsi b/arch/mips/dts/brcm,bcm6358.dtsi
index 5605723e83..5e9c9ad769 100644
--- a/arch/mips/dts/brcm,bcm6358.dtsi
+++ b/arch/mips/dts/brcm,bcm6358.dtsi
@@ -192,6 +192,34 @@
 			status = "disabled";
 		};
 
+		enet0: ethernet at fffe4000 {
+			compatible = "brcm,bcm6348-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xfffe4000 0x2dc>;
+			clocks = <&periph_clk BCM6358_CLK_ENET0>;
+			dmas = <&iudma BCM6358_DMA_ENET0_RX>,
+			       <&iudma BCM6358_DMA_ENET0_TX>;
+			dma-names = "rx",
+				    "tx";
+
+			status = "disabled";
+		};
+
+		enet1: ethernet at fffe4800 {
+			compatible = "brcm,bcm6348-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xfffe4800 0x2dc>;
+			clocks = <&periph_clk BCM6358_CLK_ENET1>;
+			dmas = <&iudma BCM6358_DMA_ENET1_RX>,
+			       <&iudma BCM6358_DMA_ENET1_TX>;
+			dma-names = "rx",
+				    "tx";
+
+			status = "disabled";
+		};
+
 		iudma: dma-controller at fffe5000 {
 			compatible = "brcm,bcm6348-iudma";
 			reg = <0xfffe5000 0x24>,
-- 
2.11.0

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

* [U-Boot] [PATCH v8 19/31] bmips: enable hg556a enet support
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (17 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 18/31] bmips: bcm6358: add support for bcm6348-enet Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 20/31] bmips: enable nb4-ser " Álvaro Fernández Rojas
                     ` (14 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/huawei,hg556a.dts     | 12 ++++++++++++
 configs/huawei_hg556a_ram_defconfig |  8 +++++++-
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/huawei,hg556a.dts b/arch/mips/dts/huawei,hg556a.dts
index 60455c2ff8..6a7fc1df4b 100644
--- a/arch/mips/dts/huawei,hg556a.dts
+++ b/arch/mips/dts/huawei,hg556a.dts
@@ -93,6 +93,18 @@
 	status = "okay";
 };
 
+&enet1 {
+	status = "okay";
+	phy = <&enet1phy>;
+	phy-mode = "mii";
+
+	enet1phy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
diff --git a/configs/huawei_hg556a_ram_defconfig b/configs/huawei_hg556a_ram_defconfig
index 6bb14ba736..d4e6144319 100644
--- a/configs/huawei_hg556a_ram_defconfig
+++ b/configs/huawei_hg556a_ram_defconfig
@@ -25,11 +25,14 @@ CONFIG_CMD_LICENSE=y
 CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="huawei,hg556a"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
@@ -40,6 +43,9 @@ CONFIG_FLASH_CFI_DRIVER=y
 CONFIG_CFI_FLASH=y
 CONFIG_SYS_FLASH_PROTECTION=y
 CONFIG_SYS_FLASH_CFI=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6348_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6358_USBH_PHY=y
 CONFIG_DM_RESET=y
-- 
2.11.0

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

* [U-Boot] [PATCH v8 20/31] bmips: enable nb4-ser enet support
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (18 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 19/31] bmips: enable hg556a enet support Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 21/31] net: add support for bcm6368-enet Álvaro Fernández Rojas
                     ` (13 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/sfr,nb4-ser.dts     | 24 ++++++++++++++++++++++++
 configs/sfr_nb4-ser_ram_defconfig |  8 +++++++-
 2 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/sfr,nb4-ser.dts b/arch/mips/dts/sfr,nb4-ser.dts
index bdc6f8ae45..dfbc4148dc 100644
--- a/arch/mips/dts/sfr,nb4-ser.dts
+++ b/arch/mips/dts/sfr,nb4-ser.dts
@@ -53,6 +53,30 @@
 	status = "okay";
 };
 
+&enet0 {
+	status = "okay";
+	phy = <&enet0phy>;
+	phy-mode = "internal";
+
+	enet0phy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
+&enet1 {
+	status = "okay";
+	phy = <&enet1phy>;
+	phy-mode = "mii";
+
+	enet1phy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
diff --git a/configs/sfr_nb4-ser_ram_defconfig b/configs/sfr_nb4-ser_ram_defconfig
index 12adfb01e7..39622875b1 100644
--- a/configs/sfr_nb4-ser_ram_defconfig
+++ b/configs/sfr_nb4-ser_ram_defconfig
@@ -26,11 +26,14 @@ CONFIG_CMD_LICENSE=y
 CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="sfr,nb4-ser"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
@@ -42,6 +45,9 @@ CONFIG_FLASH_CFI_DRIVER=y
 CONFIG_CFI_FLASH=y
 CONFIG_SYS_FLASH_PROTECTION=y
 CONFIG_SYS_FLASH_CFI=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6348_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6358_USBH_PHY=y
 CONFIG_DM_RESET=y
-- 
2.11.0

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

* [U-Boot] [PATCH v8 21/31] net: add support for bcm6368-enet
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (19 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 20/31] bmips: enable nb4-ser " Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 22/31] bmips: bcm6368: " Álvaro Fernández Rojas
                     ` (12 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: introduce bcm6368-enet driver

 drivers/net/Kconfig       |   8 +
 drivers/net/Makefile      |   1 +
 drivers/net/bcm6368-eth.c | 604 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 613 insertions(+)
 create mode 100644 drivers/net/bcm6368-eth.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 2b7cec8804..7044c6adf3 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -82,6 +82,14 @@ config BCM6348_ETH
 	help
 	  This driver supports the BCM6348 Ethernet MAC.
 
+config BCM6368_ETH
+	bool "BCM6368 EMAC support"
+	depends on DM_ETH && ARCH_BMIPS
+	select DMA
+	select MII
+	help
+	  This driver supports the BCM6368 Ethernet MAC.
+
 config DWC_ETH_QOS
 	bool "Synopsys DWC Ethernet QOS device support"
 	depends on DM_ETH
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 2647d4dd23..0dbfa03306 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_ALTERA_TSE) += altera_tse.o
 obj-$(CONFIG_AG7XXX) += ag7xxx.o
 obj-$(CONFIG_ARMADA100_FEC) += armada100_fec.o
 obj-$(CONFIG_BCM6348_ETH) += bcm6348-eth.o
+obj-$(CONFIG_BCM6368_ETH) += bcm6368-eth.o
 obj-$(CONFIG_DRIVER_AT91EMAC) += at91_emac.o
 obj-$(CONFIG_DRIVER_AX88180) += ax88180.o
 obj-$(CONFIG_BCM_SF2_ETH) += bcm-sf2-eth.o
diff --git a/drivers/net/bcm6368-eth.c b/drivers/net/bcm6368-eth.c
new file mode 100644
index 0000000000..ff2a8b1e78
--- /dev/null
+++ b/drivers/net/bcm6368-eth.c
@@ -0,0 +1,604 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c:
+ *	Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dma.h>
+#include <miiphy.h>
+#include <net.h>
+#include <reset.h>
+#include <wait_bit.h>
+#include <asm/io.h>
+
+#define ETH_PORT_STR			"brcm,enetsw-port"
+
+#define ETH_ZLEN			60
+#define ETH_TIMEOUT			100
+
+#define ETH_MAX_PORT			8
+#define ETH_RGMII_PORT0			4
+
+/* Port traffic control */
+#define ETH_PTCTRL_REG(x)		(0x0 + (x))
+#define ETH_PTCTRL_RXDIS_SHIFT		0
+#define ETH_PTCTRL_RXDIS_MASK		(1 << ETH_PTCTRL_RXDIS_SHIFT)
+#define ETH_PTCTRL_TXDIS_SHIFT		1
+#define ETH_PTCTRL_TXDIS_MASK		(1 << ETH_PTCTRL_TXDIS_SHIFT)
+
+/* Switch mode register */
+#define ETH_SWMODE_REG			0xb
+#define ETH_SWMODE_FWD_EN_SHIFT		1
+#define ETH_SWMODE_FWD_EN_MASK		(1 << ETH_SWMODE_FWD_EN_SHIFT)
+
+/* IMP override Register */
+#define ETH_IMPOV_REG			0xe
+#define ETH_IMPOV_LINKUP_SHIFT		0
+#define ETH_IMPOV_LINKUP_MASK		(1 << ETH_IMPOV_LINKUP_SHIFT)
+#define ETH_IMPOV_FDX_SHIFT		1
+#define ETH_IMPOV_FDX_MASK		(1 << ETH_IMPOV_FDX_SHIFT)
+#define ETH_IMPOV_100_SHIFT		2
+#define ETH_IMPOV_100_MASK		(1 << ETH_IMPOV_100_SHIFT)
+#define ETH_IMPOV_1000_SHIFT		3
+#define ETH_IMPOV_1000_MASK		(1 << ETH_IMPOV_1000_SHIFT)
+#define ETH_IMPOV_RXFLOW_SHIFT		4
+#define ETH_IMPOV_RXFLOW_MASK		(1 << ETH_IMPOV_RXFLOW_SHIFT)
+#define ETH_IMPOV_TXFLOW_SHIFT		5
+#define ETH_IMPOV_TXFLOW_MASK		(1 << ETH_IMPOV_TXFLOW_SHIFT)
+#define ETH_IMPOV_FORCE_SHIFT		7
+#define ETH_IMPOV_FORCE_MASK		(1 << ETH_IMPOV_FORCE_SHIFT)
+
+/* Port override Register */
+#define ETH_PORTOV_REG(x)		(0x58 + (x))
+#define ETH_PORTOV_LINKUP_SHIFT		0
+#define ETH_PORTOV_LINKUP_MASK		(1 << ETH_PORTOV_LINKUP_SHIFT)
+#define ETH_PORTOV_FDX_SHIFT		1
+#define ETH_PORTOV_FDX_MASK		(1 << ETH_PORTOV_FDX_SHIFT)
+#define ETH_PORTOV_100_SHIFT		2
+#define ETH_PORTOV_100_MASK		(1 << ETH_PORTOV_100_SHIFT)
+#define ETH_PORTOV_1000_SHIFT		3
+#define ETH_PORTOV_1000_MASK		(1 << ETH_PORTOV_1000_SHIFT)
+#define ETH_PORTOV_RXFLOW_SHIFT		4
+#define ETH_PORTOV_RXFLOW_MASK		(1 << ETH_PORTOV_RXFLOW_SHIFT)
+#define ETH_PORTOV_TXFLOW_SHIFT		5
+#define ETH_PORTOV_TXFLOW_MASK		(1 << ETH_PORTOV_TXFLOW_SHIFT)
+#define ETH_PORTOV_ENABLE_SHIFT		6
+#define ETH_PORTOV_ENABLE_MASK		(1 << ETH_PORTOV_ENABLE_SHIFT)
+
+/* Port RGMII control register */
+#define ETH_RGMII_CTRL_REG(x)		(0x60 + (x))
+#define ETH_RGMII_CTRL_GMII_CLK_EN	(1 << 7)
+#define ETH_RGMII_CTRL_MII_OVERRIDE_EN	(1 << 6)
+#define ETH_RGMII_CTRL_MII_MODE_MASK	(3 << 4)
+#define ETH_RGMII_CTRL_RGMII_MODE	(0 << 4)
+#define ETH_RGMII_CTRL_MII_MODE		(1 << 4)
+#define ETH_RGMII_CTRL_RVMII_MODE	(2 << 4)
+#define ETH_RGMII_CTRL_TIMING_SEL_EN	(1 << 0)
+
+/* Port RGMII timing register */
+#define ENETSW_RGMII_TIMING_REG(x)	(0x68 + (x))
+
+/* MDIO control register */
+#define MII_SC_REG			0xb0
+#define MII_SC_EXT_SHIFT		16
+#define MII_SC_EXT_MASK			(1 << MII_SC_EXT_SHIFT)
+#define MII_SC_REG_SHIFT		20
+#define MII_SC_PHYID_SHIFT		25
+#define MII_SC_RD_SHIFT			30
+#define MII_SC_RD_MASK			(1 << MII_SC_RD_SHIFT)
+#define MII_SC_WR_SHIFT			31
+#define MII_SC_WR_MASK			(1 << MII_SC_WR_SHIFT)
+
+/* MDIO data register */
+#define MII_DAT_REG			0xb4
+
+/* Global Management Configuration Register */
+#define ETH_GMCR_REG			0x200
+#define ETH_GMCR_RST_MIB_SHIFT		0
+#define ETH_GMCR_RST_MIB_MASK		(1 << ETH_GMCR_RST_MIB_SHIFT)
+
+/* Jumbo control register port mask register */
+#define ETH_JMBCTL_PORT_REG		0x4004
+
+/* Jumbo control mib good frame register */
+#define ETH_JMBCTL_MAXSIZE_REG		0x4008
+
+struct bcm_enetsw_port {
+	bool used;
+	int phy_id;
+
+	bool bypass_link;
+	int force_speed;
+	bool force_duplex_full;
+
+	const char *name;
+};
+
+/* ETH data */
+struct bcm6368_eth_priv {
+	struct udevice *dev;
+	void __iomem *base;
+	/* DMA */
+	struct dma rx_dma;
+	struct dma tx_dma;
+	/* Ports */
+	uint8_t num_ports;
+	struct bcm_enetsw_port used_ports[ETH_MAX_PORT];
+	int sw_port_link[ETH_MAX_PORT];
+	bool rgmii_override;
+	bool rgmii_timing;
+	/* PHY */
+	int phy_id;
+};
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static inline bool bcm_enet_port_is_rgmii(int portid)
+{
+	return portid >= ETH_RGMII_PORT0;
+}
+
+static int bcm6368_mdio_read(struct bcm6368_eth_priv *priv, uint8_t ext,
+			     int phy_id, int reg)
+{
+	uint32_t val;
+
+	writel_be(0, priv->base + MII_SC_REG);
+
+	val = MII_SC_RD_MASK |
+	      (phy_id << MII_SC_PHYID_SHIFT) |
+	      (reg << MII_SC_REG_SHIFT);
+
+	if (ext)
+		val |= MII_SC_EXT_MASK;
+
+	writel_be(val, priv->base + MII_SC_REG);
+	udelay(50);
+
+	return readw_be(priv->base + MII_DAT_REG);
+}
+
+static int bcm6368_mdio_write(struct bcm6368_eth_priv *priv, uint8_t ext,
+			      int phy_id, int reg, u16 data)
+{
+	uint32_t val;
+
+	writel_be(0, priv->base + MII_SC_REG);
+
+	val = MII_SC_WR_MASK |
+	      (phy_id << MII_SC_PHYID_SHIFT) |
+	      (reg << MII_SC_REG_SHIFT);
+
+	if (ext)
+		val |= MII_SC_EXT_MASK;
+
+	val |= data;
+
+	writel_be(val, priv->base + MII_SC_REG);
+	udelay(50);
+
+	return 0;
+}
+
+static int bcm6368_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+
+	return dma_receive(&priv->rx_dma, (void *)packetp, NULL);
+}
+
+static int bcm6368_eth_send(struct udevice *dev, void *packet, int length)
+{
+	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+
+	/* reset dma rx channel */
+	dma_disable(&priv->rx_dma);
+	dma_enable(&priv->rx_dma);
+
+	length = max(length, ETH_ZLEN);
+
+	return dma_send(&priv->tx_dma, (void **)packet, length, NULL);
+}
+
+static int bcm6368_eth_adjust_link(struct bcm6368_eth_priv *priv)
+{
+	unsigned int i;
+
+	for (i = 0; i < priv->num_ports; i++) {
+		struct bcm_enetsw_port *port;
+		int val, j, up, advertise, lpa, speed, duplex, media;
+		int external_phy = bcm_enet_port_is_rgmii(i);
+		u8 override;
+
+		port = &priv->used_ports[i];
+		if (!port->used)
+			continue;
+
+		if (port->bypass_link)
+			continue;
+
+		/* dummy read to clear */
+		for (j = 0; j < 2; j++)
+			val = bcm6368_mdio_read(priv, external_phy,
+						   port->phy_id, MII_BMSR);
+
+		if (val == 0xffff)
+			continue;
+
+		up = (val & BMSR_LSTATUS) ? 1 : 0;
+		if (!(up ^ priv->sw_port_link[i]))
+			continue;
+
+		priv->sw_port_link[i] = up;
+
+		/* link changed */
+		if (!up) {
+			dev_info(&priv->pdev->dev, "link DOWN on %s\n",
+				 port->name);
+			writeb_be(ETH_PORTOV_ENABLE_MASK,
+				      priv->base + ETH_PORTOV_REG(i));
+			writeb_be(ETH_PTCTRL_RXDIS_MASK |
+				      ETH_PTCTRL_TXDIS_MASK,
+				      priv->base + ETH_PTCTRL_REG(i));
+			continue;
+		}
+
+		advertise = bcm6368_mdio_read(priv, external_phy,
+						 port->phy_id, MII_ADVERTISE);
+
+		lpa = bcm6368_mdio_read(priv, external_phy, port->phy_id,
+					   MII_LPA);
+
+		/* figure out media and duplex from advertise and LPA values */
+		media = mii_nway_result(lpa & advertise);
+		duplex = (media & ADVERTISE_FULL) ? 1 : 0;
+
+		if (media & (ADVERTISE_100FULL | ADVERTISE_100HALF))
+			speed = 100;
+		else
+			speed = 10;
+
+		if (val & BMSR_ESTATEN) {
+			advertise = bcm6368_mdio_read(priv, external_phy,
+						port->phy_id, MII_CTRL1000);
+
+			lpa = bcm6368_mdio_read(priv, external_phy,
+						port->phy_id, MII_STAT1000);
+
+			if (advertise & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)
+					&& lpa & (LPA_1000FULL | LPA_1000HALF)) {
+				speed = 1000;
+				duplex = (lpa & LPA_1000FULL);
+			}
+		}
+
+		pr_alert("link UP on %s, %dMbps, %s-duplex\n",
+			 port->name, speed, duplex ? "full" : "half");
+
+		override = ETH_PORTOV_ENABLE_MASK |
+			ETH_PORTOV_LINKUP_MASK;
+
+		if (speed == 1000)
+			override |= ETH_PORTOV_1000_MASK;
+		else if (speed == 100)
+			override |= ETH_PORTOV_100_MASK;
+		if (duplex)
+			override |= ETH_PORTOV_FDX_MASK;
+
+		writeb_be(override, priv->base + ETH_PORTOV_REG(i));
+		writeb_be(0, priv->base + ETH_PTCTRL_REG(i));
+	}
+
+	return 0;
+}
+
+static int bcm6368_eth_start(struct udevice *dev)
+{
+	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+	int i;
+	u32 val;
+
+	/* disable all ports */
+	for (i = 0; i < priv->num_ports; i++) {
+		writeb_be(ETH_PORTOV_ENABLE_MASK,
+			      priv->base + ETH_PORTOV_REG(i));
+		writeb_be(ETH_PTCTRL_RXDIS_MASK |
+			      ETH_PTCTRL_TXDIS_MASK,
+			      priv->base + ETH_PTCTRL_REG(i));
+
+		priv->sw_port_link[i] = 0;
+	}
+
+	/* enable external ports */
+	for (i = ETH_RGMII_PORT0; i < priv->num_ports; i++) {
+		u8 rgmii_ctrl;
+
+		if (!priv->used_ports[i].used)
+			continue;
+
+		rgmii_ctrl = readb_be(priv->base + ETH_RGMII_CTRL_REG(i));
+		rgmii_ctrl |= ETH_RGMII_CTRL_GMII_CLK_EN;
+		if (priv->rgmii_override)
+			rgmii_ctrl |= ETH_RGMII_CTRL_MII_OVERRIDE_EN;
+		if (priv->rgmii_timing)
+			rgmii_ctrl |= ETH_RGMII_CTRL_TIMING_SEL_EN;
+		writeb_be(rgmii_ctrl, priv->base + ETH_RGMII_CTRL_REG(i));
+	}
+
+	/* reset mib */
+	val = readb_be(priv->base + ETH_GMCR_REG);
+	val |= ETH_GMCR_RST_MIB_MASK;
+	writeb_be(val, priv->base + ETH_GMCR_REG);
+	mdelay(1);
+	val &= ~ETH_GMCR_RST_MIB_MASK;
+	writeb_be(val, priv->base + ETH_GMCR_REG);
+	mdelay(1);
+
+	/* force CPU port state */
+	val = readb_be(priv->base + ETH_IMPOV_REG);
+	val |= ETH_IMPOV_FORCE_MASK | ETH_IMPOV_LINKUP_MASK;
+	writeb_be(val, priv->base + ETH_IMPOV_REG);
+
+	/* enable switch forward engine */
+	val = readb_be(priv->base + ETH_SWMODE_REG);
+	val |= ETH_SWMODE_FWD_EN_MASK;
+	writeb_be(val, priv->base + ETH_SWMODE_REG);
+
+	/* enable jumbo on all ports */
+	writel_be(0x1ff, priv->base + ETH_JMBCTL_PORT_REG);
+	writew_be(9728, priv->base + ETH_JMBCTL_MAXSIZE_REG);
+
+	/* enable dma rx channel */
+	dma_enable(&priv->rx_dma);
+
+	/* enable dma tx channel */
+	dma_enable(&priv->tx_dma);
+
+	/* apply override config for bypass_link ports here. */
+	for (i = 0; i < priv->num_ports; i++) {
+		struct bcm_enetsw_port *port;
+		u8 override;
+		port = &priv->used_ports[i];
+		if (!port->used)
+			continue;
+
+		if (!port->bypass_link)
+			continue;
+
+		override = ETH_PORTOV_ENABLE_MASK |
+			ETH_PORTOV_LINKUP_MASK;
+
+		switch (port->force_speed) {
+		case 1000:
+			override |= ETH_PORTOV_1000_MASK;
+			break;
+		case 100:
+			override |= ETH_PORTOV_100_MASK;
+			break;
+		case 10:
+			break;
+		default:
+			pr_warn("invalid forced speed on port %s: assume 10\n",
+			       port->name);
+			break;
+		}
+
+		if (port->force_duplex_full)
+			override |= ETH_PORTOV_FDX_MASK;
+
+		writeb_be(override, priv->base + ETH_PORTOV_REG(i));
+		writeb_be(0, priv->base + ETH_PTCTRL_REG(i));
+	}
+
+	bcm6368_eth_adjust_link(priv);
+
+	return 0;
+}
+
+static void bcm6368_eth_stop(struct udevice *dev)
+{
+	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+
+	/* disable dma rx channel */
+	dma_disable(&priv->rx_dma);
+
+	/* disable dma tx channel */
+	dma_disable(&priv->tx_dma);
+}
+
+static const struct eth_ops bcm6368_eth_ops = {
+	.recv = bcm6368_eth_recv,
+	.send = bcm6368_eth_send,
+	.start = bcm6368_eth_start,
+	.stop = bcm6368_eth_stop,
+};
+
+static const struct udevice_id bcm6368_eth_ids[] = {
+	{ .compatible = "brcm,bcm6368-enet", },
+	{ /* sentinel */ }
+};
+
+static bool bcm6368_phy_is_external(struct bcm6368_eth_priv *priv,
+				       int phy_id)
+{
+	uint8_t i;
+
+	for (i = 0; i < priv->num_ports; ++i) {
+		if (!priv->used_ports[i].used)
+			continue;
+		if (priv->used_ports[i].phy_id == phy_id)
+			return bcm_enet_port_is_rgmii(i);
+	}
+
+	return true;
+}
+
+static int bcm6368_mii_mdio_read(struct mii_dev *bus, int addr, int devaddr,
+				 int reg)
+{
+	struct bcm6368_eth_priv *priv = bus->priv;
+	bool ext = bcm6368_phy_is_external(priv, addr);
+
+	return bcm6368_mdio_read(priv, ext, addr, reg);
+}
+
+static int bcm6368_mii_mdio_write(struct mii_dev *bus, int addr, int devaddr,
+				  int reg, u16 data)
+{
+	struct bcm6368_eth_priv *priv = bus->priv;
+	bool ext = bcm6368_phy_is_external(priv, addr);
+
+	return bcm6368_mdio_write(priv, ext, addr, reg, data);
+}
+
+static int bcm6368_mdio_init(const char *name, struct bcm6368_eth_priv *priv)
+{
+	struct mii_dev *bus;
+
+	bus = mdio_alloc();
+	if (!bus) {
+		pr_err("%s: failed to allocate MDIO bus\n", __func__);
+		return -ENOMEM;
+	}
+
+	bus->read = bcm6368_mii_mdio_read;
+	bus->write = bcm6368_mii_mdio_write;
+	bus->priv = priv;
+	snprintf(bus->name, sizeof(bus->name), "%s", name);
+
+	return mdio_register(bus);
+}
+
+static int bcm6368_eth_probe(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+	void *blob = (void *)gd->fdt_blob;
+	fdt_addr_t addr;
+	int node = dev_of_offset(dev);
+	int ret, i;
+	unsigned int num_ports;
+
+	/* get base address */
+	addr = devfdt_get_addr(dev);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	/* get number of ports */
+	num_ports = fdtdec_get_uint(gd->fdt_blob, node, "brcm,num-ports",
+				    ETH_MAX_PORT);
+	if (!num_ports || num_ports > ETH_MAX_PORT)
+		return -EINVAL;
+
+	/* get dma channels */
+	ret = dma_get_by_name(dev, "tx", &priv->tx_dma);
+	if (ret)
+		return -EINVAL;
+
+	ret = dma_get_by_name(dev, "rx", &priv->rx_dma);
+	if (ret)
+		return -EINVAL;
+
+	/* try to enable clocks */
+	for (i = 0; ; i++) {
+		struct clk clk;
+		int ret;
+
+		ret = clk_get_by_index(dev, i, &clk);
+		if (ret < 0)
+			break;
+		if (clk_enable(&clk))
+			pr_err("failed to enable clock %d\n", i);
+		clk_free(&clk);
+	}
+
+	/* try to perform resets */
+	for (i = 0; ; i++) {
+		struct reset_ctl reset;
+		int ret;
+
+		ret = reset_get_by_index(dev, i, &reset);
+		if (ret < 0)
+			break;
+		if (reset_deassert(&reset))
+			pr_err("failed to deassert reset %d\n", i);
+		reset_free(&reset);
+	}
+
+	/* set priv data */
+	priv->dev = dev;
+
+	priv->base = ioremap(addr, 0);
+	pdata->iobase = (phys_addr_t) priv->base;
+
+	priv->num_ports = num_ports;
+
+	if (fdtdec_get_bool(gd->fdt_blob, i, "brcm,rgmii-override"))
+		priv->rgmii_override = true;
+	if (fdtdec_get_bool(gd->fdt_blob, i, "brcm,rgmii-timing"))
+		priv->rgmii_timing = true;
+
+	/* get ports */
+	for (i = fdt_first_subnode(blob, node);
+	     i > 0;
+	     i = fdt_next_subnode(blob, i)) {
+		const char *comp;
+		const char *label;
+		unsigned int p;
+		int phy_id;
+		int speed;
+
+		comp = fdt_getprop(blob, i, "compatible", NULL);
+		if (!comp || memcmp(comp, ETH_PORT_STR, sizeof(ETH_PORT_STR)))
+			continue;
+
+		p = fdtdec_get_uint(gd->fdt_blob, i, "reg",
+				      ETH_MAX_PORT);
+		if (p >= num_ports)
+			return -EINVAL;
+
+		label = fdt_getprop(blob, i, "label", NULL);
+		if (!label) {
+			debug("%s: node %s has no label\n", __func__,
+			      fdt_get_name(blob, i, NULL));
+			return -EINVAL;
+		}
+
+		phy_id = fdtdec_get_int(gd->fdt_blob, i, "brcm,phy-id", -1);
+
+		priv->used_ports[p].used = true;
+		priv->used_ports[p].name = label;
+		priv->used_ports[p].phy_id = phy_id;
+
+		if (fdtdec_get_bool(gd->fdt_blob, i, "full-duplex"))
+			priv->used_ports[p].force_duplex_full = true;
+		if (fdtdec_get_bool(gd->fdt_blob, i, "bypass-link"))
+			priv->used_ports[p].bypass_link = true;
+		speed = fdtdec_get_int(gd->fdt_blob, i, "speed", 0);
+		if (speed)
+			priv->used_ports[p].force_speed = speed;
+	}
+
+	/* init mii bus */
+	ret = bcm6368_mdio_init(dev->name, priv);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+U_BOOT_DRIVER(bcm6368_eth) = {
+	.name = "bcm6368_eth",
+	.id = UCLASS_ETH,
+	.of_match = bcm6368_eth_ids,
+	.ops = &bcm6368_eth_ops,
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+	.priv_auto_alloc_size = sizeof(struct bcm6368_eth_priv),
+	.probe = bcm6368_eth_probe,
+};
-- 
2.11.0

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

* [U-Boot] [PATCH v8 22/31] bmips: bcm6368: add support for bcm6368-enet
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (20 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 21/31] net: add support for bcm6368-enet Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 23/31] bmips: enable wap-5813n enet support Álvaro Fernández Rojas
                     ` (11 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6368.dtsi | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6368.dtsi b/arch/mips/dts/brcm,bcm6368.dtsi
index 30047f6360..89590d6ff9 100644
--- a/arch/mips/dts/brcm,bcm6368.dtsi
+++ b/arch/mips/dts/brcm,bcm6368.dtsi
@@ -205,5 +205,24 @@
 			#dma-cells = <1>;
 			dma-channels = <8>;
 		};
+
+		enet: ethernet at 10f00000 {
+			compatible = "brcm,bcm6368-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x10f00000 0x10000>;
+			clocks = <&periph_clk BCM6368_CLK_SWPKT_USB>,
+				 <&periph_clk BCM6368_CLK_SWPKT_SAR>,
+				 <&periph_clk BCM6368_CLK_ROBOSW>;
+			resets = <&periph_rst BCM6368_RST_SWITCH>,
+				 <&periph_rst BCM6368_RST_EPHY>;
+			dmas = <&iudma BCM6368_DMA_ENETSW_RX>,
+			       <&iudma BCM6368_DMA_ENETSW_TX>;
+			dma-names = "rx",
+				    "tx";
+			brcm,num-ports = <6>;
+
+			status = "disabled";
+		};
 	};
 };
-- 
2.11.0

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

* [U-Boot] [PATCH v8 23/31] bmips: enable wap-5813n enet support
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (21 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 22/31] bmips: bcm6368: " Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 24/31] bmips: bcm6328: add support for bcm6368-enet Álvaro Fernández Rojas
                     ` (10 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: introduce bcm6368-enet driver

 arch/mips/dts/comtrend,wap-5813n.dts    | 14 ++++++++++++++
 configs/comtrend_wap5813n_ram_defconfig |  8 +++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/comtrend,wap-5813n.dts b/arch/mips/dts/comtrend,wap-5813n.dts
index bd41dab9f8..7e835b28d2 100644
--- a/arch/mips/dts/comtrend,wap-5813n.dts
+++ b/arch/mips/dts/comtrend,wap-5813n.dts
@@ -54,6 +54,20 @@
 	status = "okay";
 };
 
+&enet {
+	status = "okay";
+
+	port at 4 {
+		compatible = "brcm,enetsw-port";
+		reg = <4>;
+		label = "rgmii";
+		brcm,phy-id = <0xff>;
+		speed = <1000>;
+		full-duplex;
+		bypass-link;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
diff --git a/configs/comtrend_wap5813n_ram_defconfig b/configs/comtrend_wap5813n_ram_defconfig
index 987e4c3fbc..fd5107bb7d 100644
--- a/configs/comtrend_wap5813n_ram_defconfig
+++ b/configs/comtrend_wap5813n_ram_defconfig
@@ -25,11 +25,14 @@ CONFIG_CMD_LICENSE=y
 CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="comtrend,wap-5813n"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
@@ -40,6 +43,9 @@ CONFIG_FLASH_CFI_DRIVER=y
 CONFIG_CFI_FLASH=y
 CONFIG_SYS_FLASH_PROTECTION=y
 CONFIG_SYS_FLASH_CFI=y
+CONFIG_DM_ETH=y
+CONFIG_PHY_GIGE=y
+CONFIG_BCM6368_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6368_USBH_PHY=y
 CONFIG_DM_RESET=y
-- 
2.11.0

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

* [U-Boot] [PATCH v8 24/31] bmips: bcm6328: add support for bcm6368-enet
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (22 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 23/31] bmips: enable wap-5813n enet support Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 25/31] bmips: enable ar-5387un enet support Álvaro Fernández Rojas
                     ` (9 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6328.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6328.dtsi b/arch/mips/dts/brcm,bcm6328.dtsi
index 6fa49e22bb..50beed4171 100644
--- a/arch/mips/dts/brcm,bcm6328.dtsi
+++ b/arch/mips/dts/brcm,bcm6328.dtsi
@@ -200,5 +200,22 @@
 			#dma-cells = <1>;
 			dma-channels = <8>;
 		};
+
+		enet: ethernet at 10e00000 {
+			compatible = "brcm,bcm6368-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x10e00000 0x10000>;
+			clocks = <&periph_clk BCM6328_CLK_ROBOSW>;
+			resets = <&periph_rst BCM6328_RST_ENETSW>,
+				 <&periph_rst BCM6328_RST_EPHY>;
+			dmas = <&iudma BCM6328_DMA_ENETSW_RX>,
+			       <&iudma BCM6328_DMA_ENETSW_TX>;
+			dma-names = "rx",
+				    "tx";
+			brcm,num-ports = <5>;
+
+			status = "disabled";
+		};
 	};
 };
-- 
2.11.0

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

* [U-Boot] [PATCH v8 25/31] bmips: enable ar-5387un enet support
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (23 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 24/31] bmips: bcm6328: add support for bcm6368-enet Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 26/31] bmips: bcm6362: add support for bcm6368-enet Álvaro Fernández Rojas
                     ` (8 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: introduce bcm6368-enet driver

 arch/mips/dts/comtrend,ar-5387un.dts    | 32 ++++++++++++++++++++++++++++++++
 configs/comtrend_ar5387un_ram_defconfig |  7 ++++++-
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/comtrend,ar-5387un.dts b/arch/mips/dts/comtrend,ar-5387un.dts
index e993b5cd89..03e3851ab1 100644
--- a/arch/mips/dts/comtrend,ar-5387un.dts
+++ b/arch/mips/dts/comtrend,ar-5387un.dts
@@ -24,6 +24,38 @@
 	status = "okay";
 };
 
+&enet {
+	status = "okay";
+
+	port at 0 {
+		compatible = "brcm,enetsw-port";
+		reg = <0>;
+		label = "fe1";
+		brcm,phy-id = <1>;
+	};
+
+	port at 1 {
+		compatible = "brcm,enetsw-port";
+		reg = <1>;
+		label = "fe2";
+		brcm,phy-id = <2>;
+	};
+
+	port at 2 {
+		compatible = "brcm,enetsw-port";
+		reg = <2>;
+		label = "fe3";
+		brcm,phy-id = <3>;
+	};
+
+	port at 3 {
+		compatible = "brcm,enetsw-port";
+		reg = <3>;
+		label = "fe4";
+		brcm,phy-id = <4>;
+	};
+};
+
 &leds {
 	status = "okay";
 
diff --git a/configs/comtrend_ar5387un_ram_defconfig b/configs/comtrend_ar5387un_ram_defconfig
index f129870ca0..5ba401a441 100644
--- a/configs/comtrend_ar5387un_ram_defconfig
+++ b/configs/comtrend_ar5387un_ram_defconfig
@@ -28,11 +28,14 @@ CONFIG_CMD_MEMINFO=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="comtrend,ar-5387un"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_LED=y
 CONFIG_LED_BCM6328=y
@@ -41,6 +44,8 @@ CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_MACRONIX=y
 CONFIG_SPI_FLASH_MTD=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6368_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6368_USBH_PHY=y
 CONFIG_POWER_DOMAIN=y
-- 
2.11.0

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

* [U-Boot] [PATCH v8 26/31] bmips: bcm6362: add support for bcm6368-enet
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (24 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 25/31] bmips: enable ar-5387un enet support Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 27/31] bmips: enable dgnd3700v2 enet support Álvaro Fernández Rojas
                     ` (7 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6362.dtsi | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6362.dtsi b/arch/mips/dts/brcm,bcm6362.dtsi
index 94e7de096d..c77b80a4cc 100644
--- a/arch/mips/dts/brcm,bcm6362.dtsi
+++ b/arch/mips/dts/brcm,bcm6362.dtsi
@@ -224,5 +224,24 @@
 			#dma-cells = <1>;
 			dma-channels = <8>;
 		};
+
+		enet: ethernet at 10e00000 {
+			compatible = "brcm,bcm6368-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x10e00000 0x10000>;
+			clocks = <&periph_clk BCM6362_CLK_SWPKT_USB>,
+				 <&periph_clk BCM6362_CLK_SWPKT_SAR>,
+				 <&periph_clk BCM6362_CLK_ROBOSW>;
+			resets = <&periph_rst BCM6362_RST_ENETSW>,
+				 <&periph_rst BCM6362_RST_EPHY>;
+			dmas = <&iudma BCM6362_DMA_ENETSW_RX>,
+			       <&iudma BCM6362_DMA_ENETSW_TX>;
+			dma-names = "rx",
+				    "tx";
+			brcm,num-ports = <6>;
+
+			status = "disabled";
+		};
 	};
 };
-- 
2.11.0

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

* [U-Boot] [PATCH v8 27/31] bmips: enable dgnd3700v2 enet support
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (25 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 26/31] bmips: bcm6362: add support for bcm6368-enet Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 28/31] bmips: bcm63268: add support for bcm6368-enet Álvaro Fernández Rojas
                     ` (6 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: introduce bcm6368-enet driver

 arch/mips/dts/netgear,dgnd3700v2.dts     | 14 ++++++++++++++
 configs/netgear_dgnd3700v2_ram_defconfig |  8 +++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/netgear,dgnd3700v2.dts b/arch/mips/dts/netgear,dgnd3700v2.dts
index 322d1567ff..2b72491f0b 100644
--- a/arch/mips/dts/netgear,dgnd3700v2.dts
+++ b/arch/mips/dts/netgear,dgnd3700v2.dts
@@ -43,6 +43,20 @@
 	status = "okay";
 };
 
+&enet {
+	status = "okay";
+
+	port at 4 {
+		compatible = "brcm,enetsw-port";
+		reg = <4>;
+		label = "rgmii";
+		brcm,phy-id = <0xff>;
+		speed = <1000>;
+		full-duplex;
+		bypass-link;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
diff --git a/configs/netgear_dgnd3700v2_ram_defconfig b/configs/netgear_dgnd3700v2_ram_defconfig
index 1abc869856..0f3914fe7e 100644
--- a/configs/netgear_dgnd3700v2_ram_defconfig
+++ b/configs/netgear_dgnd3700v2_ram_defconfig
@@ -27,17 +27,23 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
-# CONFIG_CMD_NET is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="netgear,dgnd3700v2"
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
 CONFIG_LED_BCM6328=y
 CONFIG_LED_BLINK=y
 CONFIG_LED_GPIO=y
+CONFIG_DM_ETH=y
+CONFIG_PHY_GIGE=y
+CONFIG_BCM6368_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6368_USBH_PHY=y
 CONFIG_POWER_DOMAIN=y
-- 
2.11.0

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

* [U-Boot] [PATCH v8 28/31] bmips: bcm63268: add support for bcm6368-enet
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (26 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 27/31] bmips: enable dgnd3700v2 enet support Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 29/31] bmips: enable vr-3032u enet support Álvaro Fernández Rojas
                     ` (5 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm63268.dtsi | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm63268.dtsi b/arch/mips/dts/brcm,bcm63268.dtsi
index c7ad83c306..f8a72ef535 100644
--- a/arch/mips/dts/brcm,bcm63268.dtsi
+++ b/arch/mips/dts/brcm,bcm63268.dtsi
@@ -230,5 +230,30 @@
 			#dma-cells = <1>;
 			dma-channels = <8>;
 		};
+
+		enet: ethernet at 10700000 {
+			compatible = "brcm,bcm6368-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x10700000 0x10000>;
+			clocks = <&periph_clk BCM63268_CLK_GMAC>,
+				 <&periph_clk BCM63268_CLK_ROBOSW>,
+				 <&periph_clk BCM63268_CLK_ROBOSW250>,
+				 <&timer_clk BCM63268_TCLK_EPHY1>,
+				 <&timer_clk BCM63268_TCLK_EPHY2>,
+				 <&timer_clk BCM63268_TCLK_EPHY3>,
+				 <&timer_clk BCM63268_TCLK_GPHY>;
+			resets = <&periph_rst BCM63268_RST_ENETSW>,
+				 <&periph_rst BCM63268_RST_EPHY>,
+				 <&periph_rst BCM63268_RST_GPHY>;
+			dmas = <&iudma BCM63268_DMA_ENETSW_RX>,
+			       <&iudma BCM63268_DMA_ENETSW_TX>;
+			dma-names = "rx",
+				    "tx";
+			brcm,rgmii-override;
+			brcm,rgmii-timing;
+
+			status = "disabled";
+		};
 	};
 };
-- 
2.11.0

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

* [U-Boot] [PATCH v8 29/31] bmips: enable vr-3032u enet support
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (27 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 28/31] bmips: bcm63268: add support for bcm6368-enet Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 30/31] bmips: bcm6318: add support for bcm6368-enet Álvaro Fernández Rojas
                     ` (4 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: introduce bcm6368-enet driver

 arch/mips/dts/comtrend,vr-3032u.dts    | 32 ++++++++++++++++++++++++++++++++
 configs/comtrend_vr3032u_ram_defconfig |  7 ++++++-
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/comtrend,vr-3032u.dts b/arch/mips/dts/comtrend,vr-3032u.dts
index 8c6a4a1eac..512cb52de3 100644
--- a/arch/mips/dts/comtrend,vr-3032u.dts
+++ b/arch/mips/dts/comtrend,vr-3032u.dts
@@ -24,6 +24,38 @@
 	status = "okay";
 };
 
+&enet {
+	status = "okay";
+
+	port at 0 {
+		compatible = "brcm,enetsw-port";
+		reg = <0>;
+		label = "fe2";
+		brcm,phy-id = <1>;
+	};
+
+	port at 1 {
+		compatible = "brcm,enetsw-port";
+		reg = <1>;
+		label = "fe3";
+		brcm,phy-id = <2>;
+	};
+
+	port at 2 {
+		compatible = "brcm,enetsw-port";
+		reg = <2>;
+		label = "fe4";
+		brcm,phy-id = <3>;
+	};
+
+	port at 3 {
+		compatible = "brcm,enetsw-port";
+		reg = <3>;
+		label = "fe1";
+		brcm,phy-id = <4>;
+	};
+};
+
 &leds {
 	status = "okay";
 	brcm,serial-leds;
diff --git a/configs/comtrend_vr3032u_ram_defconfig b/configs/comtrend_vr3032u_ram_defconfig
index 1689eecec1..47f53998e1 100644
--- a/configs/comtrend_vr3032u_ram_defconfig
+++ b/configs/comtrend_vr3032u_ram_defconfig
@@ -26,15 +26,20 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="comtrend,vr-3032u"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_LED=y
 CONFIG_LED_BCM6328=y
 CONFIG_LED_BLINK=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6368_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6368_USBH_PHY=y
 CONFIG_POWER_DOMAIN=y
-- 
2.11.0

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

* [U-Boot] [PATCH v8 30/31] bmips: bcm6318: add support for bcm6368-enet
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (28 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 29/31] bmips: enable vr-3032u enet support Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 31/31] bmips: enable ar-5315u enet support Álvaro Fernández Rojas
                     ` (3 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6318.dtsi           | 19 +++++++++++++++++++
 include/dt-bindings/clock/bcm6318-clock.h | 11 +++++++++++
 2 files changed, 30 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6318.dtsi b/arch/mips/dts/brcm,bcm6318.dtsi
index d04b7cbb01..d678dab242 100644
--- a/arch/mips/dts/brcm,bcm6318.dtsi
+++ b/arch/mips/dts/brcm,bcm6318.dtsi
@@ -190,6 +190,25 @@
 			status = "disabled";
 		};
 
+		enet: ethernet at 10080000 {
+			compatible = "brcm,bcm6368-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x10080000 0x8000>;
+			clocks = <&periph_clk BCM6318_CLK_ROBOSW250>,
+				 <&periph_clk BCM6318_CLK_ROBOSW025>,
+				 <&ubus_clk BCM6318_UCLK_ROBOSW>;
+			resets = <&periph_rst BCM6318_RST_ENETSW>,
+				 <&periph_rst BCM6318_RST_EPHY>;
+			dmas = <&iudma BCM6318_DMA_ENETSW_RX>,
+			       <&iudma BCM6318_DMA_ENETSW_TX>;
+			dma-names = "rx",
+				    "tx";
+			brcm,num-ports = <5>;
+
+			status = "disabled";
+		};
+
 		iudma: dma-controller at 10088000 {
 			compatible = "brcm,bcm6368-iudma";
 			reg = <0x10088000 0x80>,
diff --git a/include/dt-bindings/clock/bcm6318-clock.h b/include/dt-bindings/clock/bcm6318-clock.h
index d5e13c5c2d..3f10448cef 100644
--- a/include/dt-bindings/clock/bcm6318-clock.h
+++ b/include/dt-bindings/clock/bcm6318-clock.h
@@ -33,4 +33,15 @@
 #define BCM6318_CLK_AFE		29
 #define BCM6318_CLK_QPROC	30
 
+#define BCM6318_UCLK_ADSL	0
+#define BCM6318_UCLK_ARB	1
+#define BCM6318_UCLK_MIPS	2
+#define BCM6318_UCLK_PCIE	3
+#define BCM6318_UCLK_PERIPH	4
+#define BCM6318_UCLK_PHYMIPS	5
+#define BCM6318_UCLK_ROBOSW	6
+#define BCM6318_UCLK_SAR	7
+#define BCM6318_UCLK_SDR	8
+#define BCM6318_UCLK_USB	9
+
 #endif /* __DT_BINDINGS_CLOCK_BCM6318_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v8 31/31] bmips: enable ar-5315u enet support
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (29 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 30/31] bmips: bcm6318: add support for bcm6368-enet Álvaro Fernández Rojas
@ 2018-11-26 18:00   ` Álvaro Fernández Rojas
  2018-11-26 23:15   ` [U-Boot] [PATCH v8 00/31] dma: add channels support Tom Rini
                     ` (2 subsequent siblings)
  33 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-26 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v8: introduce bcm6368-enet driver

 arch/mips/dts/comtrend,ar-5315u.dts    | 32 ++++++++++++++++++++++++++++++++
 configs/comtrend_ar5315u_ram_defconfig |  7 ++++++-
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/comtrend,ar-5315u.dts b/arch/mips/dts/comtrend,ar-5315u.dts
index 45570189d0..eb60aaa8d5 100644
--- a/arch/mips/dts/comtrend,ar-5315u.dts
+++ b/arch/mips/dts/comtrend,ar-5315u.dts
@@ -24,6 +24,38 @@
 	status = "okay";
 };
 
+&enet {
+	status = "okay";
+
+	port at 0 {
+		compatible = "brcm,enetsw-port";
+		reg = <0>;
+		label = "fe4";
+		brcm,phy-id = <1>;
+	};
+
+	port at 1 {
+		compatible = "brcm,enetsw-port";
+		reg = <1>;
+		label = "fe3";
+		brcm,phy-id = <2>;
+	};
+
+	port at 2 {
+		compatible = "brcm,enetsw-port";
+		reg = <2>;
+		label = "fe2";
+		brcm,phy-id = <3>;
+	};
+
+	port at 3 {
+		compatible = "brcm,enetsw-port";
+		reg = <3>;
+		label = "fe1";
+		brcm,phy-id = <4>;
+	};
+};
+
 &leds {
 	status = "okay";
 
diff --git a/configs/comtrend_ar5315u_ram_defconfig b/configs/comtrend_ar5315u_ram_defconfig
index d9ef52e68d..1b8e4e43c4 100644
--- a/configs/comtrend_ar5315u_ram_defconfig
+++ b/configs/comtrend_ar5315u_ram_defconfig
@@ -28,11 +28,14 @@ CONFIG_CMD_MEMINFO=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="comtrend,ar-5315u"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_LED=y
 CONFIG_LED_BCM6328=y
@@ -41,6 +44,8 @@ CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_SPI_FLASH_MTD=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6368_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6318_USBH_PHY=y
 CONFIG_BCM6328_POWER_DOMAIN=y
-- 
2.11.0

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

* [U-Boot] [PATCH v8 00/31] dma: add channels support
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (30 preceding siblings ...)
  2018-11-26 18:00   ` [U-Boot] [PATCH v8 31/31] bmips: enable ar-5315u enet support Álvaro Fernández Rojas
@ 2018-11-26 23:15   ` Tom Rini
  2018-11-28 18:17   ` [U-Boot] [PATCH v9 0/3] " Álvaro Fernández Rojas
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
  33 siblings, 0 replies; 145+ messages in thread
From: Tom Rini @ 2018-11-26 23:15 UTC (permalink / raw)
  To: u-boot

On Mon, Nov 26, 2018 at 07:00:08PM +0100, Álvaro Fernández Rojas wrote:

> In order to add bcm6348-enet support, dma-uclass must be extended to support
> dma channels and reworked to operate like the other dm uclass (clk, reset...).
> 
> ===
> 
> A DMA is a feature of computer systems that allows certain hardware
> subsystems to access main system memory, independent of the CPU.
> DMA channels are typically generated externally to the HW module
> consuming them, by an entity this API calls a DMA provider. This API
> provides a standard means for drivers to enable and disable DMAs, and to
> copy, send and receive data using DMA.
> 
> DMA channel API:
>  dma_get_by_index()
>  dma_get_by_name()
>  dma_request()
>  dma_free()
>  dma_enable()
>  dma_disable()
>  dma_prepare_rcv_buf()
>  dma_receive()
>  dma_send()
> 
> A driver that implements UCLASS_DMA is a DMA provider. A provider will
> often implement multiple separate DMAs channels, since the hardware it manages
> often has this capability. dma_uclass.h describes the interface which
> DMA providers must implement.
> 
> DMA consumers/clients are the HW modules driven by the DMA channels. 
> 
> DMA consumer DMA_MEM_TO_DEV (transmit) usage example (based on networking).
> Note. In u-boot dma_send() is sync operation always - it'll start transfer and
> will poll for it to complete:
> - get/request dma channel
> 	struct dma dma_tx;
> 	ret = dma_get_by_name(common->dev, "tx0", &dma_tx);
> 	if (ret) ...
> 
> - enable dma channel
> 	ret = dma_enable(&dma_tx);
> 	if (ret) ...
> 
> - dma transmit DMA_MEM_TO_DEV.
> 	struct ti_drv_packet_data packet_data;
> 	
> 	packet_data.opt1 = val1;
> 	packet_data.opt2 = val2;
> 	ret = dma_send(&dma_tx, packet, length, &packet_data);
> 	if (ret) ..
> 
> DMA consumer DMA_DEV_TO_MEM (receive) usage example (based on networking).
> Note. dma_receive() is sync operation always - it'll start transfer
> (if required) and will poll for it to complete (or for any previously
> configured dev2mem transfer to complete):
> - get/request dma channel
> 	struct dma dma_rx;
> 	ret = dma_get_by_name(common->dev, "rx0", &dma_rx);
> 	if (ret) ...
> 
> - enable dma channel
> 	ret = dma_enable(&dma_rx);
> 	if (ret) ...
> 
> - dma receive DMA_DEV_TO_MEM.
> 	struct ti_drv_packet_data packet_data;
> 	
> 	len = dma_receive(&dma_rx, (void **)packet, &packet_data);
> 	if (ret < 0) ...
> 
> DMA consumer DMA_DEV_TO_MEM (receive) zero-copy usage example (based on
> networking). Networking subsystem allows to configure and use few receive
> buffers (dev2mem), as Networking RX DMA channels usually implemented
> as streaming interface
> - get/request dma channel
> 	struct dma dma_rx;
> 	ret = dma_get_by_name(common->dev, "rx0", &dma_rx);
> 	if (ret) ...
> 	
> 	for (i = 0; i < RX_DESC_NUM; i++) {
> 		ret = dma_prepare_rcv_buf(&dma_rx,
> 					  net_rx_packets[i],
> 					  RX_BUF_SIZE);
> 		if (ret) ...
> 	}
> 
> - enable dma channel
> 	ret = dma_enable(&dma_rx);
> 	if (ret) ...
> 
> - dma receive DMA_DEV_TO_MEM.
> 	struct ti_drv_packet_data packet_data;
> 	void *packet;
> 	
> 	len = dma_receive(&dma_rx, &packet, &packet_data);
> 	if (ret < 0) ..
> 	
> 	/* packet - points on buffer prepared by dma_prepare_rcv_buf().
> 	   process packet*/
> 	
> 	- return buffer back to DAM channel
> 	ret = dma_prepare_rcv_buf(&dma_rx,
> 				  net_rx_packets[rx_next],
> 				  RX_BUF_SIZE);
> 

Can you please split this into 2 parts, the generic DMA portion, and the
bcm6368-enet/etc part?  Thanks!

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

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

* [U-Boot] [PATCH v9 0/3] dma: add channels support
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (31 preceding siblings ...)
  2018-11-26 23:15   ` [U-Boot] [PATCH v8 00/31] dma: add channels support Tom Rini
@ 2018-11-28 18:17   ` Álvaro Fernández Rojas
  2018-11-28 18:17     ` [U-Boot] [PATCH v9 1/3] dma: move dma_ops to dma-uclass.h Álvaro Fernández Rojas
                       ` (3 more replies)
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
  33 siblings, 4 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:17 UTC (permalink / raw)
  To: u-boot

In order to add bcm6348-enet support, dma-uclass must be extended to support
dma channels and reworked to operate like the other dm uclass (clk, reset...).

===

A DMA is a feature of computer systems that allows certain hardware
subsystems to access main system memory, independent of the CPU.
DMA channels are typically generated externally to the HW module
consuming them, by an entity this API calls a DMA provider. This API
provides a standard means for drivers to enable and disable DMAs, and to
copy, send and receive data using DMA.

DMA channel API:
 dma_get_by_index()
 dma_get_by_name()
 dma_request()
 dma_free()
 dma_enable()
 dma_disable()
 dma_prepare_rcv_buf()
 dma_receive()
 dma_send()

A driver that implements UCLASS_DMA is a DMA provider. A provider will
often implement multiple separate DMAs channels, since the hardware it manages
often has this capability. dma_uclass.h describes the interface which
DMA providers must implement.

DMA consumers/clients are the HW modules driven by the DMA channels. 

DMA consumer DMA_MEM_TO_DEV (transmit) usage example (based on networking).
Note. In u-boot dma_send() is sync operation always - it'll start transfer and
will poll for it to complete:
- get/request dma channel
	struct dma dma_tx;
	ret = dma_get_by_name(common->dev, "tx0", &dma_tx);
	if (ret) ...

- enable dma channel
	ret = dma_enable(&dma_tx);
	if (ret) ...

- dma transmit DMA_MEM_TO_DEV.
	struct ti_drv_packet_data packet_data;
	
	packet_data.opt1 = val1;
	packet_data.opt2 = val2;
	ret = dma_send(&dma_tx, packet, length, &packet_data);
	if (ret) ..

DMA consumer DMA_DEV_TO_MEM (receive) usage example (based on networking).
Note. dma_receive() is sync operation always - it'll start transfer
(if required) and will poll for it to complete (or for any previously
configured dev2mem transfer to complete):
- get/request dma channel
	struct dma dma_rx;
	ret = dma_get_by_name(common->dev, "rx0", &dma_rx);
	if (ret) ...

- enable dma channel
	ret = dma_enable(&dma_rx);
	if (ret) ...

- dma receive DMA_DEV_TO_MEM.
	struct ti_drv_packet_data packet_data;
	
	len = dma_receive(&dma_rx, (void **)packet, &packet_data);
	if (ret < 0) ...

DMA consumer DMA_DEV_TO_MEM (receive) zero-copy usage example (based on
networking). Networking subsystem allows to configure and use few receive
buffers (dev2mem), as Networking RX DMA channels usually implemented
as streaming interface
- get/request dma channel
	struct dma dma_rx;
	ret = dma_get_by_name(common->dev, "rx0", &dma_rx);
	if (ret) ...
	
	for (i = 0; i < RX_DESC_NUM; i++) {
		ret = dma_prepare_rcv_buf(&dma_rx,
					  net_rx_packets[i],
					  RX_BUF_SIZE);
		if (ret) ...
	}

- enable dma channel
	ret = dma_enable(&dma_rx);
	if (ret) ...

- dma receive DMA_DEV_TO_MEM.
	struct ti_drv_packet_data packet_data;
	void *packet;
	
	len = dma_receive(&dma_rx, &packet, &packet_data);
	if (ret < 0) ..
	
	/* packet - points on buffer prepared by dma_prepare_rcv_buf().
	   process packet*/
	
	- return buffer back to DAM channel
	ret = dma_prepare_rcv_buf(&dma_rx,
				  net_rx_packets[rx_next],
				  RX_BUF_SIZE);

===

v9: Separate generic dma channels support from bmips enet support
v8: Sync with latest u-boot.
v7: From Grygorii Strashko:
 - copyright fixed as suggested by Tom Rini
 - added "Reviewed-by" tags
v6: From Grygorii Strashko:
 - added possibility to pass DMA driver/channel's specific data per each
 transfer using additional parameter "metadata" in dma_send/dma_receive() API.
 For example, port number for network packets to be directed to the
 specific port on multi port ethernet controllers.
 - added new dma_prepare_rcv_buf() API which allows to implement zero-copy
 DEV_TO_MEM transfer using DMA streaming channels which is usual case
 for Networking.
 - added dma-uclass test
 - removed unused function dma_get_by_index_platdata()
 - updated comments
v5: Fix build of ti-edma3.
v4: No changes
v3: Introduce changes reported by Simon Glass:
 - Improve dma-uclass.h documentation.
 - Switch to live tree API.
v2: Introduce changes reported by Vignesh:
 - Respect current dma implementation.
 - Let dma_memcpy find a compatible dma device.

Grygorii Strashko (1):
  test: dma: add dma-uclass test

Álvaro Fernández Rojas (2):
  dma: move dma_ops to dma-uclass.h
  dma: add channels support

 arch/sandbox/dts/test.dts      |   8 ++
 configs/sandbox_defconfig      |   3 +
 drivers/dma/Kconfig            |  14 ++
 drivers/dma/Makefile           |   1 +
 drivers/dma/dma-uclass.c       | 183 +++++++++++++++++++++++++-
 drivers/dma/sandbox-dma-test.c | 282 +++++++++++++++++++++++++++++++++++++++++
 drivers/dma/ti-edma3.c         |   2 +-
 include/dma-uclass.h           | 128 +++++++++++++++++++
 include/dma.h                  | 282 +++++++++++++++++++++++++++++++++++++----
 test/dm/Makefile               |   1 +
 test/dm/dma.c                  | 123 ++++++++++++++++++
 11 files changed, 997 insertions(+), 30 deletions(-)
 create mode 100644 drivers/dma/sandbox-dma-test.c
 create mode 100644 include/dma-uclass.h
 create mode 100644 test/dm/dma.c

-- 
2.11.0

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

* [U-Boot] [PATCH v9 1/3] dma: move dma_ops to dma-uclass.h
  2018-11-28 18:17   ` [U-Boot] [PATCH v9 0/3] " Álvaro Fernández Rojas
@ 2018-11-28 18:17     ` Álvaro Fernández Rojas
  2018-12-07 20:33       ` [U-Boot] [U-Boot,v9,1/3] " Tom Rini
  2018-11-28 18:17     ` [U-Boot] [PATCH v9 2/3] dma: add channels support Álvaro Fernández Rojas
                       ` (2 subsequent siblings)
  3 siblings, 1 reply; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:17 UTC (permalink / raw)
  To: u-boot

Move dma_ops to a separate header file, following other uclass
implementations. While doing so, this patch also improves dma_ops
documentation.

Reviewed-by: Tom Rini <trini@konsulko.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
---
 v9: no changes
 v8: no changes
 v7: From Grygorii Strashko:
  - copyright fixed as suggested by Tom Rini
  - added "Reviewed-by" tags
 v6: no changes
 v5: fix build of ti-edma3 (reported by Grygorii Strashko) and remove unneeded
 dma.h include
 v4: no changes
 v3: Introduce changes reported by Simon Glass:
  - Improve dma-uclass.h documentation.
  - Switch to live tree API.

 drivers/dma/dma-uclass.c |  2 +-
 drivers/dma/ti-edma3.c   |  2 +-
 include/dma-uclass.h     | 39 +++++++++++++++++++++++++++++++++++++++
 include/dma.h            | 22 ----------------------
 4 files changed, 41 insertions(+), 24 deletions(-)
 create mode 100644 include/dma-uclass.h

diff --git a/drivers/dma/dma-uclass.c b/drivers/dma/dma-uclass.c
index a33f7d52da..6c3506c302 100644
--- a/drivers/dma/dma-uclass.c
+++ b/drivers/dma/dma-uclass.c
@@ -9,10 +9,10 @@
  */
 
 #include <common.h>
-#include <dma.h>
 #include <dm.h>
 #include <dm/uclass-internal.h>
 #include <dm/device-internal.h>
+#include <dma-uclass.h>
 #include <errno.h>
 
 int dma_get_device(u32 transfer_type, struct udevice **devp)
diff --git a/drivers/dma/ti-edma3.c b/drivers/dma/ti-edma3.c
index 2131e10a40..7e11b13e45 100644
--- a/drivers/dma/ti-edma3.c
+++ b/drivers/dma/ti-edma3.c
@@ -11,7 +11,7 @@
 #include <asm/io.h>
 #include <common.h>
 #include <dm.h>
-#include <dma.h>
+#include <dma-uclass.h>
 #include <asm/omap_common.h>
 #include <asm/ti-common/ti-edma3.h>
 
diff --git a/include/dma-uclass.h b/include/dma-uclass.h
new file mode 100644
index 0000000000..7bec5d3399
--- /dev/null
+++ b/include/dma-uclass.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ * Copyright (C) 2015 Texas Instruments Incorporated <www.ti.com>
+ * Written by Mugunthan V N <mugunthanvnm@ti.com>
+ *
+ */
+
+#ifndef _DMA_UCLASS_H
+#define _DMA_UCLASS_H
+
+/* See dma.h for background documentation. */
+
+#include <dma.h>
+
+/*
+ * struct dma_ops - Driver model DMA operations
+ *
+ * The uclass interface is implemented by all DMA devices which use
+ * driver model.
+ */
+struct dma_ops {
+	/**
+	 * transfer() - Issue a DMA transfer. The implementation must
+	 *   wait until the transfer is done.
+	 *
+	 * @dev: The DMA device
+	 * @direction: direction of data transfer (should be one from
+	 *   enum dma_direction)
+	 * @dst: The destination pointer.
+	 * @src: The source pointer.
+	 * @len: Length of the data to be copied (number of bytes).
+	 * @return zero on success, or -ve error code.
+	 */
+	int (*transfer)(struct udevice *dev, int direction, void *dst,
+			void *src, size_t len);
+};
+
+#endif /* _DMA_UCLASS_H */
diff --git a/include/dma.h b/include/dma.h
index 50e965241c..97fa0cf695 100644
--- a/include/dma.h
+++ b/include/dma.h
@@ -27,28 +27,6 @@ enum dma_direction {
 #define DMA_SUPPORTS_DEV_TO_DEV	BIT(3)
 
 /*
- * struct dma_ops - Driver model DMA operations
- *
- * The uclass interface is implemented by all DMA devices which use
- * driver model.
- */
-struct dma_ops {
-	/*
-	 * Get the current timer count
-	 *
-	 * @dev: The DMA device
-	 * @direction: direction of data transfer should be one from
-		       enum dma_direction
-	 * @dst: Destination pointer
-	 * @src: Source pointer
-	 * @len: Length of the data to be copied.
-	 * @return: 0 if OK, -ve on error
-	 */
-	int (*transfer)(struct udevice *dev, int direction, void *dst,
-			void *src, size_t len);
-};
-
-/*
  * struct dma_dev_priv - information about a device used by the uclass
  *
  * @supported: mode of transfers that DMA can support, should be
-- 
2.11.0

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

* [U-Boot] [PATCH v9 2/3] dma: add channels support
  2018-11-28 18:17   ` [U-Boot] [PATCH v9 0/3] " Álvaro Fernández Rojas
  2018-11-28 18:17     ` [U-Boot] [PATCH v9 1/3] dma: move dma_ops to dma-uclass.h Álvaro Fernández Rojas
@ 2018-11-28 18:17     ` Álvaro Fernández Rojas
  2018-12-07 20:33       ` [U-Boot] [U-Boot,v9,2/3] " Tom Rini
  2018-11-28 18:17     ` [U-Boot] [PATCH v9 3/3] test: dma: add dma-uclass test Álvaro Fernández Rojas
  2018-11-30 23:56     ` [U-Boot] [PATCH v9 0/3] dma: add channels support Grygorii Strashko
  3 siblings, 1 reply; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:17 UTC (permalink / raw)
  To: u-boot

This adds channels support for dma controllers that have multiple channels
which can transfer data to/from different devices (enet, usb...).

DMA channle API:
 dma_get_by_index()
 dma_get_by_name()
 dma_request()
 dma_free()
 dma_enable()
 dma_disable()
 dma_prepare_rcv_buf()
 dma_receive()
 dma_send()

Reviewed-by: Tom Rini <trini@konsulko.com>
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
[grygorii.strashko at ti.com: drop unused dma_get_by_index_platdata(),
 add metadata to send/receive ops, add dma_prepare_rcv_buf(),
 minor clean up]
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 v9: no changes
 v8: no changes
 v7: From Grygorii Strashko:
  - copyright fixed as suggested by Tom Rini
  - added "Reviewed-by" tags
 v6: From Grygorii Strashko:
  - added possibility to pass DMA driver/channel's specific data per each
  transfer using additional parameter "metadata" in dma_send/dma_receive() API.
  For example, port number for network packets to be directed to the
  specific port on multi port ethernet controllers.
  - added new dma_prepare_rcv_buf() API which allows to implement zero-copy
  DEV_TO_MEM transfer using DMA streaming channels which is usual case
  for Networking.
  - removed unused function dma_get_by_index_platdata()
  - updated comments
 v5: remove unneeded dma.h include
 v4: no changes
 v3: Introduce changes reported by Simon Glass:
  - Improve dma-uclass.h documentation.
  - Switch to live tree API.

 drivers/dma/Kconfig      |   7 ++
 drivers/dma/dma-uclass.c | 181 ++++++++++++++++++++++++++++++++-
 include/dma-uclass.h     |  91 ++++++++++++++++-
 include/dma.h            | 260 ++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 532 insertions(+), 7 deletions(-)

diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 4ee6afad35..b9b85c65fc 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -12,6 +12,13 @@ config DMA
 	  buses that is used to transfer data to and from memory.
 	  The uclass interface is defined in include/dma.h.
 
+config DMA_CHANNELS
+	bool "Enable DMA channels support"
+	depends on DMA
+	help
+	  Enable channels support for DMA. Some DMA controllers have multiple
+	  channels which can either transfer data to/from different devices.
+
 config TI_EDMA3
 	bool "TI EDMA3 driver"
 	help
diff --git a/drivers/dma/dma-uclass.c b/drivers/dma/dma-uclass.c
index 6c3506c302..9c961cf1e2 100644
--- a/drivers/dma/dma-uclass.c
+++ b/drivers/dma/dma-uclass.c
@@ -2,19 +2,192 @@
 /*
  * Direct Memory Access U-Class driver
  *
- * (C) Copyright 2015
- *     Texas Instruments Incorporated, <www.ti.com>
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ * Copyright (C) 2015 - 2018 Texas Instruments Incorporated <www.ti.com>
+ * Written by Mugunthan V N <mugunthanvnm@ti.com>
  *
  * Author: Mugunthan V N <mugunthanvnm@ti.com>
  */
 
 #include <common.h>
 #include <dm.h>
-#include <dm/uclass-internal.h>
-#include <dm/device-internal.h>
+#include <dm/read.h>
 #include <dma-uclass.h>
+#include <dt-structs.h>
 #include <errno.h>
 
+#ifdef CONFIG_DMA_CHANNELS
+static inline struct dma_ops *dma_dev_ops(struct udevice *dev)
+{
+	return (struct dma_ops *)dev->driver->ops;
+}
+
+# if CONFIG_IS_ENABLED(OF_CONTROL)
+static int dma_of_xlate_default(struct dma *dma,
+				struct ofnode_phandle_args *args)
+{
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (args->args_count > 1) {
+		pr_err("Invaild args_count: %d\n", args->args_count);
+		return -EINVAL;
+	}
+
+	if (args->args_count)
+		dma->id = args->args[0];
+	else
+		dma->id = 0;
+
+	return 0;
+}
+
+int dma_get_by_index(struct udevice *dev, int index, struct dma *dma)
+{
+	int ret;
+	struct ofnode_phandle_args args;
+	struct udevice *dev_dma;
+	const struct dma_ops *ops;
+
+	debug("%s(dev=%p, index=%d, dma=%p)\n", __func__, dev, index, dma);
+
+	assert(dma);
+	dma->dev = NULL;
+
+	ret = dev_read_phandle_with_args(dev, "dmas", "#dma-cells", 0, index,
+					 &args);
+	if (ret) {
+		pr_err("%s: dev_read_phandle_with_args failed: err=%d\n",
+		       __func__, ret);
+		return ret;
+	}
+
+	ret = uclass_get_device_by_ofnode(UCLASS_DMA, args.node, &dev_dma);
+	if (ret) {
+		pr_err("%s: uclass_get_device_by_ofnode failed: err=%d\n",
+		       __func__, ret);
+		return ret;
+	}
+
+	dma->dev = dev_dma;
+
+	ops = dma_dev_ops(dev_dma);
+
+	if (ops->of_xlate)
+		ret = ops->of_xlate(dma, &args);
+	else
+		ret = dma_of_xlate_default(dma, &args);
+	if (ret) {
+		pr_err("of_xlate() failed: %d\n", ret);
+		return ret;
+	}
+
+	return dma_request(dev_dma, dma);
+}
+
+int dma_get_by_name(struct udevice *dev, const char *name, struct dma *dma)
+{
+	int index;
+
+	debug("%s(dev=%p, name=%s, dma=%p)\n", __func__, dev, name, dma);
+	dma->dev = NULL;
+
+	index = dev_read_stringlist_search(dev, "dma-names", name);
+	if (index < 0) {
+		pr_err("dev_read_stringlist_search() failed: %d\n", index);
+		return index;
+	}
+
+	return dma_get_by_index(dev, index, dma);
+}
+# endif /* OF_CONTROL */
+
+int dma_request(struct udevice *dev, struct dma *dma)
+{
+	struct dma_ops *ops = dma_dev_ops(dev);
+
+	debug("%s(dev=%p, dma=%p)\n", __func__, dev, dma);
+
+	dma->dev = dev;
+
+	if (!ops->request)
+		return 0;
+
+	return ops->request(dma);
+}
+
+int dma_free(struct dma *dma)
+{
+	struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (!ops->free)
+		return 0;
+
+	return ops->free(dma);
+}
+
+int dma_enable(struct dma *dma)
+{
+	struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (!ops->enable)
+		return -ENOSYS;
+
+	return ops->enable(dma);
+}
+
+int dma_disable(struct dma *dma)
+{
+	struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (!ops->disable)
+		return -ENOSYS;
+
+	return ops->disable(dma);
+}
+
+int dma_prepare_rcv_buf(struct dma *dma, void *dst, size_t size)
+{
+	struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (!ops->prepare_rcv_buf)
+		return -1;
+
+	return ops->prepare_rcv_buf(dma, dst, size);
+}
+
+int dma_receive(struct dma *dma, void **dst, void *metadata)
+{
+	struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (!ops->receive)
+		return -ENOSYS;
+
+	return ops->receive(dma, dst, metadata);
+}
+
+int dma_send(struct dma *dma, void *src, size_t len, void *metadata)
+{
+	struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (!ops->send)
+		return -ENOSYS;
+
+	return ops->send(dma, src, len, metadata);
+}
+#endif /* CONFIG_DMA_CHANNELS */
+
 int dma_get_device(u32 transfer_type, struct udevice **devp)
 {
 	struct udevice *dev;
diff --git a/include/dma-uclass.h b/include/dma-uclass.h
index 7bec5d3399..16fc879a5c 100644
--- a/include/dma-uclass.h
+++ b/include/dma-uclass.h
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
- * Copyright (C) 2015 Texas Instruments Incorporated <www.ti.com>
+ * Copyright (C) 2015 - 2018 Texas Instruments Incorporated <www.ti.com>
  * Written by Mugunthan V N <mugunthanvnm@ti.com>
  *
  */
@@ -13,6 +13,8 @@
 
 #include <dma.h>
 
+struct ofnode_phandle_args;
+
 /*
  * struct dma_ops - Driver model DMA operations
  *
@@ -20,6 +22,93 @@
  * driver model.
  */
 struct dma_ops {
+#ifdef CONFIG_DMA_CHANNELS
+	/**
+	 * of_xlate - Translate a client's device-tree (OF) DMA specifier.
+	 *
+	 * The DMA core calls this function as the first step in implementing
+	 * a client's dma_get_by_*() call.
+	 *
+	 * If this function pointer is set to NULL, the DMA core will use a
+	 * default implementation, which assumes #dma-cells = <1>, and that
+	 * the DT cell contains a simple integer DMA Channel.
+	 *
+	 * At present, the DMA API solely supports device-tree. If this
+	 * changes, other xxx_xlate() functions may be added to support those
+	 * other mechanisms.
+	 *
+	 * @dma: The dma struct to hold the translation result.
+	 * @args:	The dma specifier values from device tree.
+	 * @return 0 if OK, or a negative error code.
+	 */
+	int (*of_xlate)(struct dma *dma,
+			struct ofnode_phandle_args *args);
+	/**
+	 * request - Request a translated DMA.
+	 *
+	 * The DMA core calls this function as the second step in
+	 * implementing a client's dma_get_by_*() call, following a successful
+	 * xxx_xlate() call, or as the only step in implementing a client's
+	 * dma_request() call.
+	 *
+	 * @dma: The DMA struct to request; this has been filled in by
+	 *   a previoux xxx_xlate() function call, or by the caller of
+	 *   dma_request().
+	 * @return 0 if OK, or a negative error code.
+	 */
+	int (*request)(struct dma *dma);
+	/**
+	 * free - Free a previously requested dma.
+	 *
+	 * This is the implementation of the client dma_free() API.
+	 *
+	 * @dma: The DMA to free.
+	 * @return 0 if OK, or a negative error code.
+	 */
+	int (*free)(struct dma *dma);
+	/**
+	 * enable() - Enable a DMA Channel.
+	 *
+	 * @dma: The DMA Channel to manipulate.
+	 * @return zero on success, or -ve error code.
+	 */
+	int (*enable)(struct dma *dma);
+	/**
+	 * disable() - Disable a DMA Channel.
+	 *
+	 * @dma: The DMA Channel to manipulate.
+	 * @return zero on success, or -ve error code.
+	 */
+	int (*disable)(struct dma *dma);
+	/**
+	 * add_rcv_buf() - Prepare/Add receive DMA buffer.
+	 *
+	 * @dma: The DMA Channel to manipulate.
+	 * @dst: The receive buffer pointer.
+	 * @size: The receive buffer size
+	 * @return zero on success, or -ve error code.
+	 */
+	int (*prepare_rcv_buf)(struct dma *dma, void *dst, size_t size);
+	/**
+	 * receive() - Receive a DMA transfer.
+	 *
+	 * @dma: The DMA Channel to manipulate.
+	 * @dst: The destination pointer.
+	 * @metadata: DMA driver's specific data
+	 * @return zero on success, or -ve error code.
+	 */
+	int (*receive)(struct dma *dma, void **dst, void *metadata);
+	/**
+	 * send() - Send a DMA transfer.
+	 *
+	 * @dma: The DMA Channel to manipulate.
+	 * @src: The source pointer.
+	 * @len: Length of the data to be sent (number of bytes).
+	 * @metadata: DMA driver's specific data
+	 * @return zero on success, or -ve error code.
+	 */
+	int (*send)(struct dma *dma, void *src, size_t len, void *metadata);
+#endif /* CONFIG_DMA_CHANNELS */
 	/**
 	 * transfer() - Issue a DMA transfer. The implementation must
 	 *   wait until the transfer is done.
diff --git a/include/dma.h b/include/dma.h
index 97fa0cf695..d1c3d0df7d 100644
--- a/include/dma.h
+++ b/include/dma.h
@@ -1,12 +1,17 @@
 /* SPDX-License-Identifier: GPL-2.0+ */
 /*
- * (C) Copyright 2015
- *     Texas Instruments Incorporated, <www.ti.com>
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ * Copyright (C) 2015 - 2018 Texas Instruments Incorporated <www.ti.com>
+ * Written by Mugunthan V N <mugunthanvnm@ti.com>
+ *
  */
 
 #ifndef _DMA_H_
 #define _DMA_H_
 
+#include <linux/errno.h>
+#include <linux/types.h>
+
 /*
  * enum dma_direction - dma transfer direction indicator
  * @DMA_MEM_TO_MEM: Memcpy mode
@@ -36,6 +41,257 @@ struct dma_dev_priv {
 	u32 supported;
 };
 
+#ifdef CONFIG_DMA_CHANNELS
+/**
+ * A DMA is a feature of computer systems that allows certain hardware
+ * subsystems to access main system memory, independent of the CPU.
+ * DMA channels are typically generated externally to the HW module
+ * consuming them, by an entity this API calls a DMA provider. This API
+ * provides a standard means for drivers to enable and disable DMAs, and to
+ * copy, send and receive data using DMA.
+ *
+ * A driver that implements UCLASS_DMA is a DMA provider. A provider will
+ * often implement multiple separate DMAs, since the hardware it manages
+ * often has this capability. dma_uclass.h describes the interface which
+ * DMA providers must implement.
+ *
+ * DMA consumers/clients are the HW modules driven by the DMA channels. This
+ * header file describes the API used by drivers for those HW modules.
+ *
+ * DMA consumer DMA_MEM_TO_DEV (transmit) usage example (based on networking).
+ * Note. dma_send() is sync operation always -  it'll start transfer and will
+ * poll for it to complete:
+ *	- get/request dma channel
+ *	struct dma dma_tx;
+ *	ret = dma_get_by_name(common->dev, "tx0", &dma_tx);
+ *	if (ret) ...
+ *
+ *	- enable dma channel
+ *	ret = dma_enable(&dma_tx);
+ *	if (ret) ...
+ *
+ *	- dma transmit DMA_MEM_TO_DEV.
+ *	struct ti_drv_packet_data packet_data;
+ *
+ *	packet_data.opt1 = val1;
+ *	packet_data.opt2 = val2;
+ *	ret = dma_send(&dma_tx, packet, length, &packet_data);
+ *	if (ret) ..
+ *
+ * DMA consumer DMA_DEV_TO_MEM (receive) usage example (based on networking).
+ * Note. dma_receive() is sync operation always - it'll start transfer
+ * (if required) and will poll for it to complete (or for any previously
+ * configured dev2mem transfer to complete):
+ *	- get/request dma channel
+ *	struct dma dma_rx;
+ *	ret = dma_get_by_name(common->dev, "rx0", &dma_rx);
+ *	if (ret) ...
+ *
+ *	- enable dma channel
+ *	ret = dma_enable(&dma_rx);
+ *	if (ret) ...
+ *
+ *	- dma receive DMA_DEV_TO_MEM.
+ *	struct ti_drv_packet_data packet_data;
+ *
+ *	len = dma_receive(&dma_rx, (void **)packet, &packet_data);
+ *	if (ret < 0) ...
+ *
+ * DMA consumer DMA_DEV_TO_MEM (receive) zero-copy usage example (based on
+ * networking). Networking subsystem allows to configure and use few receive
+ * buffers (dev2mem), as Networking RX DMA channels usually implemented
+ * as streaming interface
+ *	- get/request dma channel
+ *	struct dma dma_rx;
+ *	ret = dma_get_by_name(common->dev, "rx0", &dma_rx);
+ *	if (ret) ...
+ *
+ *	for (i = 0; i < RX_DESC_NUM; i++) {
+ *		ret = dma_prepare_rcv_buf(&dma_rx,
+ *					  net_rx_packets[i],
+ *					  RX_BUF_SIZE);
+ *		if (ret) ...
+ *	}
+ *
+ *	- enable dma channel
+ *	ret = dma_enable(&dma_rx);
+ *	if (ret) ...
+ *
+ *	- dma receive DMA_DEV_TO_MEM.
+ *	struct ti_drv_packet_data packet_data;
+ *
+ *	len = dma_receive(&dma_rx, (void **)packet, &packet_data);
+ *	if (ret < 0) ..
+ *
+ *	-- process packet --
+ *
+ *	- return buffer back to DAM channel
+ *	ret = dma_prepare_rcv_buf(&dma_rx,
+ *				  net_rx_packets[rx_next],
+ *				  RX_BUF_SIZE);
+ */
+
+struct udevice;
+
+/**
+ * struct dma - A handle to (allowing control of) a single DMA.
+ *
+ * Clients provide storage for DMA handles. The content of the structure is
+ * managed solely by the DMA API and DMA drivers. A DMA struct is
+ * initialized by "get"ing the DMA struct. The DMA struct is passed to all
+ * other DMA APIs to identify which DMA channel to operate upon.
+ *
+ * @dev: The device which implements the DMA channel.
+ * @id: The DMA channel ID within the provider.
+ *
+ * Currently, the DMA API assumes that a single integer ID is enough to
+ * identify and configure any DMA channel for any DMA provider. If this
+ * assumption becomes invalid in the future, the struct could be expanded to
+ * either (a) add more fields to allow DMA providers to store additional
+ * information, or (b) replace the id field with an opaque pointer, which the
+ * provider would dynamically allocated during its .of_xlate op, and process
+ * during is .request op. This may require the addition of an extra op to clean
+ * up the allocation.
+ */
+struct dma {
+	struct udevice *dev;
+	/*
+	 * Written by of_xlate. We assume a single id is enough for now. In the
+	 * future, we might add more fields here.
+	 */
+	unsigned long id;
+};
+
+# if CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(DMA)
+/**
+ * dma_get_by_index - Get/request a DMA by integer index.
+ *
+ * This looks up and requests a DMA. The index is relative to the client
+ * device; each device is assumed to have n DMAs associated with it somehow,
+ * and this function finds and requests one of them. The mapping of client
+ * device DMA indices to provider DMAs may be via device-tree properties,
+ * board-provided mapping tables, or some other mechanism.
+ *
+ * @dev:	The client device.
+ * @index:	The index of the DMA to request, within the client's list of
+ *		DMA channels.
+ * @dma:	A pointer to a DMA struct to initialize.
+ * @return 0 if OK, or a negative error code.
+ */
+int dma_get_by_index(struct udevice *dev, int index, struct dma *dma);
+
+/**
+ * dma_get_by_name - Get/request a DMA by name.
+ *
+ * This looks up and requests a DMA. The name is relative to the client
+ * device; each device is assumed to have n DMAs associated with it somehow,
+ * and this function finds and requests one of them. The mapping of client
+ * device DMA names to provider DMAs may be via device-tree properties,
+ * board-provided mapping tables, or some other mechanism.
+ *
+ * @dev:	The client device.
+ * @name:	The name of the DMA to request, within the client's list of
+ *		DMA channels.
+ * @dma:	A pointer to a DMA struct to initialize.
+ * @return 0 if OK, or a negative error code.
+ */
+int dma_get_by_name(struct udevice *dev, const char *name, struct dma *dma);
+# else
+static inline int dma_get_by_index(struct udevice *dev, int index,
+				   struct dma *dma)
+{
+	return -ENOSYS;
+}
+
+static inline int dma_get_by_name(struct udevice *dev, const char *name,
+				  struct dma *dma)
+{
+	return -ENOSYS;
+}
+# endif
+
+/**
+ * dma_request - Request a DMA by provider-specific ID.
+ *
+ * This requests a DMA using a provider-specific ID. Generally, this function
+ * should not be used, since dma_get_by_index/name() provide an interface that
+ * better separates clients from intimate knowledge of DMA providers.
+ * However, this function may be useful in core SoC-specific code.
+ *
+ * @dev: The DMA provider device.
+ * @dma: A pointer to a DMA struct to initialize. The caller must
+ *	 have already initialized any field in this struct which the
+ *	 DMA provider uses to identify the DMA channel.
+ * @return 0 if OK, or a negative error code.
+ */
+int dma_request(struct udevice *dev, struct dma *dma);
+
+/**
+ * dma_free - Free a previously requested DMA.
+ *
+ * @dma: A DMA struct that was previously successfully requested by
+ *	 dma_request/get_by_*().
+ * @return 0 if OK, or a negative error code.
+ */
+int dma_free(struct dma *dma);
+
+/**
+ * dma_enable() - Enable (turn on) a DMA channel.
+ *
+ * @dma: A DMA struct that was previously successfully requested by
+ *	 dma_request/get_by_*().
+ * @return zero on success, or -ve error code.
+ */
+int dma_enable(struct dma *dma);
+
+/**
+ * dma_disable() - Disable (turn off) a DMA channel.
+ *
+ * @dma: A DMA struct that was previously successfully requested by
+ *	 dma_request/get_by_*().
+ * @return zero on success, or -ve error code.
+ */
+int dma_disable(struct dma *dma);
+
+/**
+ * dma_prepare_rcv_buf() - Prepare/add receive DMA buffer.
+ *
+ * It allows to implement zero-copy async DMA_DEV_TO_MEM (receive) transactions
+ * if supported by DMA providers.
+ *
+ * @dma: A DMA struct that was previously successfully requested by
+ *	 dma_request/get_by_*().
+ * @dst: The receive buffer pointer.
+ * @size: The receive buffer size
+ * @return zero on success, or -ve error code.
+ */
+int dma_prepare_rcv_buf(struct dma *dma, void *dst, size_t size);
+
+/**
+ * dma_receive() - Receive a DMA transfer.
+ *
+ * @dma: A DMA struct that was previously successfully requested by
+ *	 dma_request/get_by_*().
+ * @dst: The destination pointer.
+ * @metadata: DMA driver's channel specific data
+ * @return length of received data on success, or zero - no data,
+ * or -ve error code.
+ */
+int dma_receive(struct dma *dma, void **dst, void *metadata);
+
+/**
+ * dma_send() - Send a DMA transfer.
+ *
+ * @dma: A DMA struct that was previously successfully requested by
+ *	 dma_request/get_by_*().
+ * @src: The source pointer.
+ * @len: Length of the data to be sent (number of bytes).
+ * @metadata: DMA driver's channel specific data
+ * @return zero on success, or -ve error code.
+ */
+int dma_send(struct dma *dma, void *src, size_t len, void *metadata);
+#endif /* CONFIG_DMA_CHANNELS */
+
 /*
  * dma_get_device - get a DMA device which supports transfer
  * type of transfer_type
-- 
2.11.0

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

* [U-Boot] [PATCH v9 3/3] test: dma: add dma-uclass test
  2018-11-28 18:17   ` [U-Boot] [PATCH v9 0/3] " Álvaro Fernández Rojas
  2018-11-28 18:17     ` [U-Boot] [PATCH v9 1/3] dma: move dma_ops to dma-uclass.h Álvaro Fernández Rojas
  2018-11-28 18:17     ` [U-Boot] [PATCH v9 2/3] dma: add channels support Álvaro Fernández Rojas
@ 2018-11-28 18:17     ` Álvaro Fernández Rojas
  2018-12-07 20:33       ` [U-Boot] [U-Boot,v9,3/3] " Tom Rini
  2018-11-30 23:56     ` [U-Boot] [PATCH v9 0/3] dma: add channels support Grygorii Strashko
  3 siblings, 1 reply; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:17 UTC (permalink / raw)
  To: u-boot

From: Grygorii Strashko <grygorii.strashko@ti.com>

Add a sandbox DMA driver implementation (provider) and corresponding DM
test.

Reviewed-by: Tom Rini <trini@konsulko.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Acked-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: no changes
 v8: sync with latest u-boot
 v7: no changes
 v6: From Grygorii Strashko:
  - added dma-uclass test

 arch/sandbox/dts/test.dts      |   8 ++
 configs/sandbox_defconfig      |   3 +
 drivers/dma/Kconfig            |   7 +
 drivers/dma/Makefile           |   1 +
 drivers/dma/sandbox-dma-test.c | 282 +++++++++++++++++++++++++++++++++++++++++
 test/dm/Makefile               |   1 +
 test/dm/dma.c                  | 123 ++++++++++++++++++
 7 files changed, 425 insertions(+)
 create mode 100644 drivers/dma/sandbox-dma-test.c
 create mode 100644 test/dm/dma.c

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 2c6b422312..e5932d5a34 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -731,6 +731,14 @@
 	pinctrl {
 		compatible = "sandbox,pinctrl";
 	};
+
+	dma: dma {
+		compatible = "sandbox,dma";
+		#dma-cells = <1>;
+
+		dmas = <&dma 0>, <&dma 1>, <&dma 2>;
+		dma-names = "m2m", "tx0", "rx0";
+	};
 };
 
 #include "sandbox_pmic.dtsi"
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 5a744f4791..0e5e6f687e 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -215,3 +215,6 @@ CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
 CONFIG_UT_ENV=y
 CONFIG_UT_OVERLAY=y
+CONFIG_DMA=y
+CONFIG_DMA_CHANNELS=y
+CONFIG_SANDBOX_DMA=y
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index b9b85c65fc..8a4162eccd 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -19,6 +19,13 @@ config DMA_CHANNELS
 	  Enable channels support for DMA. Some DMA controllers have multiple
 	  channels which can either transfer data to/from different devices.
 
+config SANDBOX_DMA
+	bool "Enable the sandbox DMA test driver"
+	depends on DMA && DMA_CHANNELS && SANDBOX
+	help
+	  Enable support for a test DMA uclass implementation. It stimulates
+	  DMA transfer by simple copying data between channels.
+
 config TI_EDMA3
 	bool "TI EDMA3 driver"
 	help
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 4eaef8ac65..aff31f986a 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_DMA) += dma-uclass.o
 obj-$(CONFIG_FSLDMAFEC) += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o
 obj-$(CONFIG_APBH_DMA) += apbh_dma.o
 obj-$(CONFIG_FSL_DMA) += fsl_dma.o
+obj-$(CONFIG_SANDBOX_DMA) += sandbox-dma-test.o
 obj-$(CONFIG_TI_KSNAV) += keystone_nav.o keystone_nav_cfg.o
 obj-$(CONFIG_TI_EDMA3) += ti-edma3.o
 obj-$(CONFIG_DMA_LPC32XX) += lpc32xx_dma.o
diff --git a/drivers/dma/sandbox-dma-test.c b/drivers/dma/sandbox-dma-test.c
new file mode 100644
index 0000000000..b958ec4d23
--- /dev/null
+++ b/drivers/dma/sandbox-dma-test.c
@@ -0,0 +1,282 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Direct Memory Access U-Class Simulation driver
+ *
+ * Copyright (C) 2018 Texas Instruments Incorporated <www.ti.com>
+ *
+ * Author: Grygorii Strashko <grygorii.strashko@ti.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/read.h>
+#include <dma-uclass.h>
+#include <dt-structs.h>
+#include <errno.h>
+
+#define SANDBOX_DMA_CH_CNT 3
+#define SANDBOX_DMA_BUF_SIZE 1024
+
+struct sandbox_dma_chan {
+	struct sandbox_dma_dev *ud;
+	char name[20];
+	u32 id;
+	enum dma_direction dir;
+	bool in_use;
+	bool enabled;
+};
+
+struct sandbox_dma_dev {
+	struct device *dev;
+	u32 ch_count;
+	struct sandbox_dma_chan channels[SANDBOX_DMA_CH_CNT];
+	uchar   buf[SANDBOX_DMA_BUF_SIZE];
+	uchar	*buf_rx;
+	size_t	data_len;
+	u32	meta;
+};
+
+static int sandbox_dma_transfer(struct udevice *dev, int direction,
+				void *dst, void *src, size_t len)
+{
+	memcpy(dst, src, len);
+
+	return 0;
+}
+
+static int sandbox_dma_of_xlate(struct dma *dma,
+				struct ofnode_phandle_args *args)
+{
+	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
+	struct sandbox_dma_chan *uc;
+
+	debug("%s(dma id=%u)\n", __func__, args->args[0]);
+
+	if (args->args[0] >= SANDBOX_DMA_CH_CNT)
+		return -EINVAL;
+
+	dma->id = args->args[0];
+
+	uc = &ud->channels[dma->id];
+
+	if (dma->id == 1)
+		uc->dir = DMA_MEM_TO_DEV;
+	else if (dma->id == 2)
+		uc->dir = DMA_DEV_TO_MEM;
+	else
+		uc->dir = DMA_MEM_TO_MEM;
+	debug("%s(dma id=%lu dir=%d)\n", __func__, dma->id, uc->dir);
+
+	return 0;
+}
+
+static int sandbox_dma_request(struct dma *dma)
+{
+	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
+	struct sandbox_dma_chan *uc;
+
+	if (dma->id >= SANDBOX_DMA_CH_CNT)
+		return -EINVAL;
+
+	uc = &ud->channels[dma->id];
+	if (uc->in_use)
+		return -EBUSY;
+
+	uc->in_use = true;
+	debug("%s(dma id=%lu in_use=%d)\n", __func__, dma->id, uc->in_use);
+
+	return 0;
+}
+
+static int sandbox_dma_free(struct dma *dma)
+{
+	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
+	struct sandbox_dma_chan *uc;
+
+	if (dma->id >= SANDBOX_DMA_CH_CNT)
+		return -EINVAL;
+
+	uc = &ud->channels[dma->id];
+	if (!uc->in_use)
+		return -EINVAL;
+
+	uc->in_use = false;
+	ud->buf_rx = NULL;
+	ud->data_len = 0;
+	debug("%s(dma id=%lu in_use=%d)\n", __func__, dma->id, uc->in_use);
+
+	return 0;
+}
+
+static int sandbox_dma_enable(struct dma *dma)
+{
+	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
+	struct sandbox_dma_chan *uc;
+
+	if (dma->id >= SANDBOX_DMA_CH_CNT)
+		return -EINVAL;
+
+	uc = &ud->channels[dma->id];
+	if (!uc->in_use)
+		return -EINVAL;
+	if (uc->enabled)
+		return -EINVAL;
+
+	uc->enabled = true;
+	debug("%s(dma id=%lu enabled=%d)\n", __func__, dma->id, uc->enabled);
+
+	return 0;
+}
+
+static int sandbox_dma_disable(struct dma *dma)
+{
+	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
+	struct sandbox_dma_chan *uc;
+
+	if (dma->id >= SANDBOX_DMA_CH_CNT)
+		return -EINVAL;
+
+	uc = &ud->channels[dma->id];
+	if (!uc->in_use)
+		return -EINVAL;
+	if (!uc->enabled)
+		return -EINVAL;
+
+	uc->enabled = false;
+	debug("%s(dma id=%lu enabled=%d)\n", __func__, dma->id, uc->enabled);
+
+	return 0;
+}
+
+static int sandbox_dma_send(struct dma *dma,
+			    void *src, size_t len, void *metadata)
+{
+	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
+	struct sandbox_dma_chan *uc;
+
+	if (dma->id >= SANDBOX_DMA_CH_CNT)
+		return -EINVAL;
+	if (!src || !metadata)
+		return -EINVAL;
+
+	debug("%s(dma id=%lu)\n", __func__, dma->id);
+
+	uc = &ud->channels[dma->id];
+	if (uc->dir != DMA_MEM_TO_DEV)
+		return -EINVAL;
+	if (!uc->in_use)
+		return -EINVAL;
+	if (!uc->enabled)
+		return -EINVAL;
+	if (len >= SANDBOX_DMA_BUF_SIZE)
+		return -EINVAL;
+
+	memcpy(ud->buf, src, len);
+	ud->data_len = len;
+	ud->meta = *((u32 *)metadata);
+
+	debug("%s(dma id=%lu len=%zu meta=%08x)\n",
+	      __func__, dma->id, len, ud->meta);
+
+	return 0;
+}
+
+static int sandbox_dma_receive(struct dma *dma, void **dst, void *metadata)
+{
+	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
+	struct sandbox_dma_chan *uc;
+
+	if (dma->id >= SANDBOX_DMA_CH_CNT)
+		return -EINVAL;
+	if (!dst || !metadata)
+		return -EINVAL;
+
+	uc = &ud->channels[dma->id];
+	if (uc->dir != DMA_DEV_TO_MEM)
+		return -EINVAL;
+	if (!uc->in_use)
+		return -EINVAL;
+	if (!uc->enabled)
+		return -EINVAL;
+	if (!ud->data_len)
+		return 0;
+
+	if (ud->buf_rx) {
+		memcpy(ud->buf_rx, ud->buf, ud->data_len);
+		*dst = ud->buf_rx;
+	} else {
+		memcpy(*dst, ud->buf, ud->data_len);
+	}
+
+	*((u32 *)metadata) = ud->meta;
+
+	debug("%s(dma id=%lu len=%zu meta=%08x %p)\n",
+	      __func__, dma->id, ud->data_len, ud->meta, *dst);
+
+	return ud->data_len;
+}
+
+static int sandbox_dma_add_rcv_buf(struct dma *dma, void *dst, size_t size)
+{
+	struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
+
+	ud->buf_rx = dst;
+
+	return 0;
+}
+
+static const struct dma_ops sandbox_dma_ops = {
+	.transfer	= sandbox_dma_transfer,
+	.of_xlate	= sandbox_dma_of_xlate,
+	.request	= sandbox_dma_request,
+	.free		= sandbox_dma_free,
+	.enable		= sandbox_dma_enable,
+	.disable	= sandbox_dma_disable,
+	.send		= sandbox_dma_send,
+	.receive	= sandbox_dma_receive,
+	.add_rcv_buf	= sandbox_dma_add_rcv_buf,
+};
+
+static int sandbox_dma_probe(struct udevice *dev)
+{
+	struct dma_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct sandbox_dma_dev *ud = dev_get_priv(dev);
+	int i, ret = 0;
+
+	uc_priv->supported = DMA_SUPPORTS_MEM_TO_MEM |
+			     DMA_SUPPORTS_MEM_TO_DEV |
+			     DMA_SUPPORTS_DEV_TO_MEM;
+
+	ud->ch_count = SANDBOX_DMA_CH_CNT;
+	ud->buf_rx = NULL;
+	ud->meta = 0;
+	ud->data_len = 0;
+
+	pr_err("Number of channels: %u\n", ud->ch_count);
+
+	for (i = 0; i < ud->ch_count; i++) {
+		struct sandbox_dma_chan *uc = &ud->channels[i];
+
+		uc->ud = ud;
+		uc->id = i;
+		sprintf(uc->name, "DMA chan%d\n", i);
+		uc->in_use = false;
+		uc->enabled = false;
+	}
+
+	return ret;
+}
+
+static const struct udevice_id sandbox_dma_ids[] = {
+	{ .compatible = "sandbox,dma" },
+	{ }
+};
+
+U_BOOT_DRIVER(sandbox_dma) = {
+	.name	= "sandbox-dma",
+	.id	= UCLASS_DMA,
+	.of_match = sandbox_dma_ids,
+	.ops	= &sandbox_dma_ops,
+	.probe = sandbox_dma_probe,
+	.priv_auto_alloc_size = sizeof(struct sandbox_dma_dev),
+};
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 213e0fda94..757dd0c45b 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -54,4 +54,5 @@ obj-$(CONFIG_DM_SERIAL) += serial.o
 obj-$(CONFIG_CPU) += cpu.o
 obj-$(CONFIG_TEE) += tee.o
 obj-$(CONFIG_VIRTIO_SANDBOX) += virtio.o
+obj-$(CONFIG_DMA) += dma.o
 endif
diff --git a/test/dm/dma.c b/test/dm/dma.c
new file mode 100644
index 0000000000..6f19d6180c
--- /dev/null
+++ b/test/dm/dma.c
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Direct Memory Access U-Class tests
+ *
+ * Copyright (C) 2018 Texas Instruments Incorporated <www.ti.com>
+ * Grygorii Strashko <grygorii.strashko@ti.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/test.h>
+#include <dma.h>
+#include <test/ut.h>
+
+static int dm_test_dma_m2m(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	struct dma dma_m2m;
+	u8 src_buf[512];
+	u8 dst_buf[512];
+	size_t len = 512;
+	int i;
+
+	ut_assertok(uclass_get_device_by_name(UCLASS_DMA, "dma", &dev));
+	ut_assertok(dma_get_by_name(dev, "m2m", &dma_m2m));
+
+	memset(dst_buf, 0, len);
+	for (i = 0; i < len; i++)
+		src_buf[i] = i;
+
+	ut_assertok(dma_memcpy(dst_buf, src_buf, len));
+
+	ut_assertok(memcmp(src_buf, dst_buf, len));
+	return 0;
+}
+DM_TEST(dm_test_dma_m2m, DM_TESTF_SCAN_FDT);
+
+static int dm_test_dma(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	struct dma dma_tx, dma_rx;
+	u8 src_buf[512];
+	u8 dst_buf[512];
+	void *dst_ptr;
+	size_t len = 512;
+	u32 meta1, meta2;
+	int i;
+
+	ut_assertok(uclass_get_device_by_name(UCLASS_DMA, "dma", &dev));
+
+	ut_assertok(dma_get_by_name(dev, "tx0", &dma_tx));
+	ut_assertok(dma_get_by_name(dev, "rx0", &dma_rx));
+
+	ut_assertok(dma_enable(&dma_tx));
+	ut_assertok(dma_enable(&dma_rx));
+
+	memset(dst_buf, 0, len);
+	for (i = 0; i < len; i++)
+		src_buf[i] = i;
+	meta1 = 0xADADDEAD;
+	meta2 = 0;
+	dst_ptr = &dst_buf;
+
+	ut_assertok(dma_send(&dma_tx, src_buf, len, &meta1));
+
+	ut_asserteq(len, dma_receive(&dma_rx, &dst_ptr, &meta2));
+	ut_asserteq(0xADADDEAD, meta2);
+
+	ut_assertok(dma_disable(&dma_tx));
+	ut_assertok(dma_disable(&dma_rx));
+
+	ut_assertok(dma_free(&dma_tx));
+	ut_assertok(dma_free(&dma_rx));
+	ut_assertok(memcmp(src_buf, dst_buf, len));
+
+	return 0;
+}
+DM_TEST(dm_test_dma, DM_TESTF_SCAN_FDT);
+
+static int dm_test_dma_rx(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	struct dma dma_tx, dma_rx;
+	u8 src_buf[512];
+	u8 dst_buf[512];
+	void *dst_ptr;
+	size_t len = 512;
+	u32 meta1, meta2;
+	int i;
+
+	ut_assertok(uclass_get_device_by_name(UCLASS_DMA, "dma", &dev));
+
+	ut_assertok(dma_get_by_name(dev, "tx0", &dma_tx));
+	ut_assertok(dma_get_by_name(dev, "rx0", &dma_rx));
+
+	ut_assertok(dma_enable(&dma_tx));
+	ut_assertok(dma_enable(&dma_rx));
+
+	memset(dst_buf, 0, len);
+	for (i = 0; i < len; i++)
+		src_buf[i] = i;
+	meta1 = 0xADADDEAD;
+	meta2 = 0;
+	dst_ptr = NULL;
+
+	ut_assertok(dma_add_rcv_buf(&dma_tx, dst_buf, len));
+
+	ut_assertok(dma_send(&dma_tx, src_buf, len, &meta1));
+
+	ut_asserteq(len, dma_receive(&dma_rx, &dst_ptr, &meta2));
+	ut_asserteq(0xADADDEAD, meta2);
+	ut_asserteq_ptr(dst_buf, dst_ptr);
+
+	ut_assertok(dma_disable(&dma_tx));
+	ut_assertok(dma_disable(&dma_rx));
+
+	ut_assertok(dma_free(&dma_tx));
+	ut_assertok(dma_free(&dma_rx));
+	ut_assertok(memcmp(src_buf, dst_buf, len));
+
+	return 0;
+}
+DM_TEST(dm_test_dma_rx, DM_TESTF_SCAN_FDT);
-- 
2.11.0

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

* [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support
  2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
                     ` (32 preceding siblings ...)
  2018-11-28 18:17   ` [U-Boot] [PATCH v9 0/3] " Álvaro Fernández Rojas
@ 2018-11-28 18:23   ` Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 01/28] dma: add bcm6348-iudma support Álvaro Fernández Rojas
                       ` (28 more replies)
  33 siblings, 29 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

In order to add bcm6348-enet support, dma-uclass must be extended to support
dma channels and reworked to operate like the other dm uclass (clk, reset...).

v9: Separate generic dma channels support from bmips enet support
 bcm6348-iudma:
  - bcm6348_iudma_chan_stop: switch to mdelay when resetting channel.
  - bcm6348_iudma_receive: track dirty dma descriptors and no longer trigger
   dma rx channel.
  - bcm6348_iudma_send: reorder to properly flush cache and set dma descriptor
   config.
  - bcm6348_iudma_prepare_rcv_buf: implemented to clear dirty dma descriptors.
 bcm6348-enet:
  - bcm6348_eth_recv: clear dirty dma descriptors only when packets are copied
   from rx dma.
  - bcm6348_eth_send: remove dma rx channel reset when sending packet.
 bcm6368-enet:
  - introduce rx packets caching functionality from bcm6348-eth to fix flow
   control issues.
  - code style fixes.
v8: Introduce bcm6368-enet driver support.
v5: Fix issues reported by Grygorii Strashko and other fixes:
 - Remove unused bcm6348-iudma defines.
 - Increment bcm6348-iudma rx descriptors.
 - Fix bcm6348-iudma flow control issues.
 - bcm6348-iudma error checking now depends on hw.
 - Remove unneeded bcm6348-iudma interrupts.
 - Receive as much packets as possible from bcm6348-eth and cache them in
 net_rx_packets. This is needed in order to fix flow control issues.
v4: Fix issues reported by Grygorii Strashko and other fixes:
 - Remove usage of net_rx_packets as buffer from bcm6348-iudma.
 - Allocate dynamic rx buffer on bcm6348-iudma.
 - Copy received dma buffer to net_rx_packets in order to avoid possible
 dma overwrites.
 - Check dma errors and discard invalid packets.
 - Reset dma rx channel when sending a new packet to prevent flow control
 issues.
 - Fix packet casting on bcm6348_eth_recv/send.
v3: Switch to live tree API.
v2: Fix bcm6348-iudma rx burst config.

Álvaro Fernández Rojas (28):
  dma: add bcm6348-iudma support
  bmips: bcm6338: add bcm6348-iudma support
  bmips: bcm6348: add bcm6348-iudma support
  bmips: bcm6358: add bcm6348-iudma support
  bmips: bcm6368: add bcm6348-iudma support
  bmips: bcm6328: add bcm6348-iudma support
  bmips: bcm6362: add bcm6348-iudma support
  bmips: bcm63268: add bcm6348-iudma support
  bmips: bcm6318: add bcm6348-iudma support
  net: add support for bcm6348-enet
  bmips: bcm6338: add support for bcm6348-enet
  bmips: enable f at st1704 enet support
  bmips: bcm6348: add support for bcm6348-enet
  bmips: enable ct-5361 enet support
  bmips: bcm6358: add support for bcm6348-enet
  bmips: enable hg556a enet support
  bmips: enable nb4-ser enet support
  net: add support for bcm6368-enet
  bmips: bcm6368: add support for bcm6368-enet
  bmips: enable wap-5813n enet support
  bmips: bcm6328: add support for bcm6368-enet
  bmips: enable ar-5387un enet support
  bmips: bcm6362: add support for bcm6368-enet
  bmips: enable dgnd3700v2 enet support
  bmips: bcm63268: add support for bcm6368-enet
  bmips: enable vr-3032u enet support
  bmips: bcm6318: add support for bcm6368-enet
  bmips: enable ar-5315u enet support

 arch/mips/dts/brcm,bcm6318.dtsi           |  38 ++
 arch/mips/dts/brcm,bcm63268.dtsi          |  38 ++
 arch/mips/dts/brcm,bcm6328.dtsi           |  30 ++
 arch/mips/dts/brcm,bcm6338.dtsi           |  29 ++
 arch/mips/dts/brcm,bcm6348.dtsi           |  42 ++
 arch/mips/dts/brcm,bcm6358.dtsi           |  46 ++
 arch/mips/dts/brcm,bcm6362.dtsi           |  32 ++
 arch/mips/dts/brcm,bcm6368.dtsi           |  32 ++
 arch/mips/dts/comtrend,ar-5315u.dts       |  32 ++
 arch/mips/dts/comtrend,ar-5387un.dts      |  32 ++
 arch/mips/dts/comtrend,ct-5361.dts        |  12 +
 arch/mips/dts/comtrend,vr-3032u.dts       |  32 ++
 arch/mips/dts/comtrend,wap-5813n.dts      |  14 +
 arch/mips/dts/huawei,hg556a.dts           |  12 +
 arch/mips/dts/netgear,dgnd3700v2.dts      |  14 +
 arch/mips/dts/sagem,f at st1704.dts          |  12 +
 arch/mips/dts/sfr,nb4-ser.dts             |  24 ++
 configs/comtrend_ar5315u_ram_defconfig    |   7 +-
 configs/comtrend_ar5387un_ram_defconfig   |   7 +-
 configs/comtrend_ct5361_ram_defconfig     |   8 +-
 configs/comtrend_vr3032u_ram_defconfig    |   7 +-
 configs/comtrend_wap5813n_ram_defconfig   |   8 +-
 configs/huawei_hg556a_ram_defconfig       |   8 +-
 configs/netgear_dgnd3700v2_ram_defconfig  |   8 +-
 configs/sagem_f at st1704_ram_defconfig      |   8 +-
 configs/sfr_nb4-ser_ram_defconfig         |   8 +-
 drivers/dma/Kconfig                       |   9 +
 drivers/dma/Makefile                      |   1 +
 drivers/dma/bcm6348-iudma.c               | 576 +++++++++++++++++++++++++
 drivers/net/Kconfig                       |  18 +
 drivers/net/Makefile                      |   2 +
 drivers/net/bcm6348-eth.c                 | 576 +++++++++++++++++++++++++
 drivers/net/bcm6368-eth.c                 | 670 ++++++++++++++++++++++++++++++
 include/configs/bmips_common.h            |   5 +-
 include/dt-bindings/clock/bcm6318-clock.h |  11 +
 include/dt-bindings/dma/bcm6318-dma.h     |  15 +
 include/dt-bindings/dma/bcm63268-dma.h    |  15 +
 include/dt-bindings/dma/bcm6328-dma.h     |  15 +
 include/dt-bindings/dma/bcm6338-dma.h     |  15 +
 include/dt-bindings/dma/bcm6348-dma.h     |  17 +
 include/dt-bindings/dma/bcm6358-dma.h     |  17 +
 include/dt-bindings/dma/bcm6362-dma.h     |  15 +
 include/dt-bindings/dma/bcm6368-dma.h     |  15 +
 43 files changed, 2522 insertions(+), 10 deletions(-)
 create mode 100644 drivers/dma/bcm6348-iudma.c
 create mode 100644 drivers/net/bcm6348-eth.c
 create mode 100644 drivers/net/bcm6368-eth.c
 create mode 100644 include/dt-bindings/dma/bcm6318-dma.h
 create mode 100644 include/dt-bindings/dma/bcm63268-dma.h
 create mode 100644 include/dt-bindings/dma/bcm6328-dma.h
 create mode 100644 include/dt-bindings/dma/bcm6338-dma.h
 create mode 100644 include/dt-bindings/dma/bcm6348-dma.h
 create mode 100644 include/dt-bindings/dma/bcm6358-dma.h
 create mode 100644 include/dt-bindings/dma/bcm6362-dma.h
 create mode 100644 include/dt-bindings/dma/bcm6368-dma.h

-- 
2.11.0

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

* [U-Boot] [PATCH v9 01/28] dma: add bcm6348-iudma support
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-28 23:44       ` Daniel Schwierzeck
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 02/28] bmips: bcm6338: " Álvaro Fernández Rojas
                       ` (27 subsequent siblings)
  28 siblings, 1 reply; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

BCM6348 IUDMA controller is present on multiple BMIPS (BCM63xx) SoCs.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: introduce dma_prepare_rcv_buf dma op:
  - bcm6348_iudma_chan_stop: switch to mdelay when resetting channel.
  - bcm6348_iudma_receive: track dirty dma descriptors and no longer trigger
   dma rx channel.
  - bcm6348_iudma_send: reorder to properly flush cache and set dma descriptor
   config.
  - bcm6348_iudma_prepare_rcv_buf: implemented to clear dirty dma descriptors.
 v8: Introduce changes from Grygorii Strashko
 v5: Several fixes and improvements:
  - Remove unused defines.
  - Increment rx descriptors.
  - Fix flow control issues.
  - Error checking now depends on hw.
  - Remove unneeded interrupts.
 v4: Fix issues reported by Grygorii Strashko and other fixes:
  - Remove usage of net_rx_packets as buffer.
  - Allocate dynamic rx buffer.
  - Check dma errors and discard invalid packets.
 v3: no changes
 v2: Fix dma rx burst config and select DMA_CHANNELS.

 drivers/dma/Kconfig         |   9 +
 drivers/dma/Makefile        |   1 +
 drivers/dma/bcm6348-iudma.c | 576 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 586 insertions(+)
 create mode 100644 drivers/dma/bcm6348-iudma.c

diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 8a4162eccd..1820676d7a 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -26,6 +26,15 @@ config SANDBOX_DMA
 	  Enable support for a test DMA uclass implementation. It stimulates
 	  DMA transfer by simple copying data between channels.
 
+config BCM6348_IUDMA
+	bool "BCM6348 IUDMA driver"
+	depends on ARCH_BMIPS
+	select DMA_CHANNELS
+	help
+	  Enable the BCM6348 IUDMA driver.
+	  This driver support data transfer from devices to
+	  memory and from memory to devices.
+
 config TI_EDMA3
 	bool "TI EDMA3 driver"
 	help
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index aff31f986a..b5f9147e0a 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_DMA) += dma-uclass.o
 
 obj-$(CONFIG_FSLDMAFEC) += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o
 obj-$(CONFIG_APBH_DMA) += apbh_dma.o
+obj-$(CONFIG_BCM6348_IUDMA) += bcm6348-iudma.o
 obj-$(CONFIG_FSL_DMA) += fsl_dma.o
 obj-$(CONFIG_SANDBOX_DMA) += sandbox-dma-test.o
 obj-$(CONFIG_TI_KSNAV) += keystone_nav.o keystone_nav_cfg.o
diff --git a/drivers/dma/bcm6348-iudma.c b/drivers/dma/bcm6348-iudma.c
new file mode 100644
index 0000000000..284735fff3
--- /dev/null
+++ b/drivers/dma/bcm6348-iudma.c
@@ -0,0 +1,576 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/dma/bcm63xx-iudma.c:
+ *	Copyright (C) 2015 Simon Arlott <simon@fire.lp0.eu>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c:
+ *	Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ *
+ * Derived from bcm963xx_4.12L.06B_consumer/shared/opensource/include/bcm963xx/63268_map_part.h:
+ *	Copyright (C) 2000-2010 Broadcom Corporation
+ *
+ * Derived from bcm963xx_4.12L.06B_consumer/bcmdrivers/opensource/net/enet/impl4/bcmenet.c:
+ *	Copyright (C) 2010 Broadcom Corporation
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dma-uclass.h>
+#include <memalign.h>
+#include <reset.h>
+#include <asm/io.h>
+
+#define DMA_RX_DESC	6
+#define DMA_TX_DESC	1
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define ALIGN_END_ADDR(type, ptr, size)	\
+	((unsigned long)(ptr) + roundup((size) * sizeof(type), \
+	 ARCH_DMA_MINALIGN))
+
+/* DMA Channels */
+#define DMA_CHAN_FLOWC(x)		((x) >> 1)
+#define DMA_CHAN_MAX			16
+#define DMA_CHAN_SIZE			0x10
+#define DMA_CHAN_TOUT			500
+
+/* DMA Global Configuration register */
+#define DMA_CFG_REG			0x00
+#define  DMA_CFG_ENABLE_SHIFT		0
+#define  DMA_CFG_ENABLE_MASK		(1 << DMA_CFG_ENABLE_SHIFT)
+#define  DMA_CFG_FLOWC_ENABLE(x)	BIT(DMA_CHAN_FLOWC(x) + 1)
+#define  DMA_CFG_NCHANS_SHIFT		24
+#define  DMA_CFG_NCHANS_MASK		(0xf << DMA_CFG_NCHANS_SHIFT)
+
+/* DMA Global Flow Control registers */
+#define DMA_FLOWC_THR_LO_REG(x)		(0x04 + DMA_CHAN_FLOWC(x) * 0x0c)
+#define DMA_FLOWC_THR_HI_REG(x)		(0x08 + DMA_CHAN_FLOWC(x) * 0x0c)
+#define DMA_FLOWC_ALLOC_REG(x)		(0x0c + DMA_CHAN_FLOWC(x) * 0x0c)
+#define  DMA_FLOWC_ALLOC_FORCE_SHIFT	31
+#define  DMA_FLOWC_ALLOC_FORCE_MASK	(1 << DMA_FLOWC_ALLOC_FORCE_SHIFT)
+
+/* DMA Global Reset register */
+#define DMA_RST_REG			0x34
+#define  DMA_RST_CHAN_SHIFT		0
+#define  DMA_RST_CHAN_MASK(x)		(1 << x)
+
+/* DMA Channel Configuration register */
+#define DMAC_CFG_REG(x)			(DMA_CHAN_SIZE * (x) + 0x00)
+#define  DMAC_CFG_ENABLE_SHIFT		0
+#define  DMAC_CFG_ENABLE_MASK		(1 << DMAC_CFG_ENABLE_SHIFT)
+#define  DMAC_CFG_PKT_HALT_SHIFT	1
+#define  DMAC_CFG_PKT_HALT_MASK		(1 << DMAC_CFG_PKT_HALT_SHIFT)
+#define  DMAC_CFG_BRST_HALT_SHIFT	2
+#define  DMAC_CFG_BRST_HALT_MASK	(1 << DMAC_CFG_BRST_HALT_SHIFT)
+
+/* DMA Channel Max Burst Length register */
+#define DMAC_BURST_REG(x)		(DMA_CHAN_SIZE * (x) + 0x0c)
+
+/* DMA SRAM Descriptor Ring Start register */
+#define DMAS_RSTART_REG(x)		(DMA_CHAN_SIZE * (x) + 0x00)
+
+/* DMA SRAM State/Bytes done/ring offset register */
+#define DMAS_STATE_DATA_REG(x)		(DMA_CHAN_SIZE * (x) + 0x04)
+
+/* DMA SRAM Buffer Descriptor status and length register */
+#define DMAS_DESC_LEN_STATUS_REG(x)	(DMA_CHAN_SIZE * (x) + 0x08)
+
+/* DMA SRAM Buffer Descriptor status and length register */
+#define DMAS_DESC_BASE_BUFPTR_REG(x)	(DMA_CHAN_SIZE * (x) + 0x0c)
+
+struct bcm6348_dma_desc {
+	uint16_t length;
+
+	uint16_t status;
+#define DMAD_ST_CRC_SHIFT		8
+#define DMAD_ST_CRC_MASK		(1 << DMAD_ST_CRC_SHIFT)
+#define DMAD_ST_WRAP_SHIFT		12
+#define DMAD_ST_WRAP_MASK		(1 << DMAD_ST_WRAP_SHIFT)
+#define DMAD_ST_SOP_SHIFT		13
+#define DMAD_ST_SOP_MASK		(1 << DMAD_ST_SOP_SHIFT)
+#define DMAD_ST_EOP_SHIFT		14
+#define DMAD_ST_EOP_MASK		(1 << DMAD_ST_EOP_SHIFT)
+#define DMAD_ST_OWN_SHIFT		15
+#define DMAD_ST_OWN_MASK		(1 << DMAD_ST_OWN_SHIFT)
+
+#define DMAD6348_ST_OV_ERR_SHIFT	0
+#define DMAD6348_ST_OV_ERR_MASK		(1 << DMAD6348_ST_OV_ERR_SHIFT)
+#define DMAD6348_ST_CRC_ERR_SHIFT	1
+#define DMAD6348_ST_CRC_ERR_MASK	(1 << DMAD6348_ST_CRC_ERR_SHIFT)
+#define DMAD6348_ST_RX_ERR_SHIFT	2
+#define DMAD6348_ST_RX_ERR_MASK		(1 << DMAD6348_ST_RX_ERR_SHIFT)
+#define DMAD6348_ST_OS_ERR_SHIFT	4
+#define DMAD6348_ST_OS_ERR_MASK		(1 << DMAD6348_ST_OS_ERR_SHIFT)
+#define DMAD6348_ST_UN_ERR_SHIFT	9
+#define DMAD6348_ST_UN_ERR_MASK		(1 << DMAD6348_ST_UN_ERR_SHIFT)
+
+	uint32_t address;
+} __attribute__((aligned(1)));
+
+struct bcm6348_chan_priv {
+	void __iomem *dma_buff;
+	void __iomem *dma_ring;
+	uint8_t dma_ring_size;
+	uint8_t desc_id;
+	uint8_t dirty_cnt;
+	uint8_t dirty_desc;
+};
+
+struct bcm6348_iudma_hw {
+	uint16_t err_mask;
+};
+
+struct bcm6348_iudma_priv {
+	const struct bcm6348_iudma_hw *hw;
+	void __iomem *base;
+	void __iomem *chan;
+	void __iomem *sram;
+	struct bcm6348_chan_priv **ch_priv;
+	uint8_t n_channels;
+};
+
+static inline bool bcm6348_iudma_chan_is_rx(uint8_t ch)
+{
+	return !(ch & 1);
+}
+
+static void bcm6348_iudma_chan_stop(struct bcm6348_iudma_priv *priv,
+				    uint8_t ch)
+{
+	unsigned int timeout = DMA_CHAN_TOUT;
+
+	do {
+		uint32_t cfg, halt;
+
+		if (timeout > DMA_CHAN_TOUT / 2)
+			halt = DMAC_CFG_PKT_HALT_MASK;
+		else
+			halt = DMAC_CFG_BRST_HALT_MASK;
+
+		/* try to stop dma channel */
+		writel_be(halt, priv->chan + DMAC_CFG_REG(ch));
+		mb();
+
+		/* check if channel was stopped */
+		cfg = readl_be(priv->chan + DMAC_CFG_REG(ch));
+		if (!(cfg & DMAC_CFG_ENABLE_MASK))
+			break;
+
+		udelay(1);
+	} while (--timeout);
+
+	if (!timeout)
+		pr_err("unable to stop channel %u\n", ch);
+
+	/* reset dma channel */
+	setbits_be32(priv->base + DMA_RST_REG, DMA_RST_CHAN_MASK(ch));
+	mdelay(1);
+	clrbits_be32(priv->base + DMA_RST_REG, DMA_RST_CHAN_MASK(ch));
+}
+
+static int bcm6348_iudma_disable(struct dma *dma)
+{
+	struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+
+	bcm6348_iudma_chan_stop(priv, dma->id);
+
+	if (bcm6348_iudma_chan_is_rx(dma->id))
+		writel_be(DMA_FLOWC_ALLOC_FORCE_MASK,
+			  DMA_FLOWC_ALLOC_REG(dma->id));
+
+	return 0;
+}
+
+static int bcm6348_iudma_enable(struct dma *dma)
+{
+	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+	struct bcm6348_dma_desc *dma_desc;
+	void __iomem *dma_buff = ch_priv->dma_buff;
+	uint8_t i;
+
+	/* init dma rings */
+	dma_desc = ch_priv->dma_ring;
+	for (i = 0; i < ch_priv->dma_ring_size; i++) {
+		uint16_t status;
+
+		if (bcm6348_iudma_chan_is_rx(dma->id)) {
+			status = DMAD_ST_OWN_MASK;
+			dma_desc->length = PKTSIZE_ALIGN;
+			dma_desc->address = virt_to_phys(dma_buff);
+			dma_buff += PKTSIZE_ALIGN;
+		} else {
+			status = 0;
+			dma_desc->length = 0;
+			dma_desc->address = 0;
+		}
+
+		if (i == ch_priv->dma_ring_size - 1)
+			status |= DMAD_ST_WRAP_MASK;
+
+		dma_desc->status = status;
+
+		dma_desc++;
+	}
+
+	/* init to first descriptor */
+	ch_priv->desc_id = 0;
+	ch_priv->dirty_desc = 0;
+	ch_priv->dirty_cnt = 0;
+
+	/* force cache writeback */
+	flush_dcache_range((ulong)ch_priv->dma_ring,
+		ALIGN_END_ADDR(struct bcm6348_dma_desc, ch_priv->dma_ring,
+			       ch_priv->dma_ring_size));
+
+	/* clear sram */
+	writel_be(0, priv->sram + DMAS_STATE_DATA_REG(dma->id));
+	writel_be(0, priv->sram + DMAS_DESC_LEN_STATUS_REG(dma->id));
+	writel_be(0, priv->sram + DMAS_DESC_BASE_BUFPTR_REG(dma->id));
+
+	/* set dma ring start */
+	writel_be(virt_to_phys(ch_priv->dma_ring),
+		  priv->sram + DMAS_RSTART_REG(dma->id));
+
+	/* set flow control */
+	if (bcm6348_iudma_chan_is_rx(dma->id)) {
+		u32 val;
+
+		setbits_be32(priv->base + DMA_CFG_REG,
+			     DMA_CFG_FLOWC_ENABLE(dma->id));
+
+		val = ch_priv->dma_ring_size / 3;
+		writel_be(val, priv->base + DMA_FLOWC_THR_LO_REG(dma->id));
+
+		val = (ch_priv->dma_ring_size * 2) / 3;
+		writel_be(val, priv->base + DMA_FLOWC_THR_HI_REG(dma->id));
+
+		writel_be(0, priv->base + DMA_FLOWC_ALLOC_REG(dma->id));
+	}
+
+	/* set dma max burst */
+	writel_be(ch_priv->dma_ring_size,
+		  priv->chan + DMAC_BURST_REG(dma->id));
+
+	/* kick dma channel */
+	setbits_be32(priv->chan + DMAC_CFG_REG(dma->id), DMAC_CFG_ENABLE_MASK);
+
+	return 0;
+}
+
+static int bcm6348_iudma_request(struct dma *dma)
+{
+	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+	struct bcm6348_chan_priv *ch_priv;
+
+	/* check if channel is valid */
+	if (dma->id >= priv->n_channels)
+		return -ENODEV;
+
+	/* alloc channel private data */
+	priv->ch_priv[dma->id] = calloc(1, sizeof(struct bcm6348_chan_priv));
+	if (!priv->ch_priv[dma->id])
+		return -ENOMEM;
+	ch_priv = priv->ch_priv[dma->id];
+
+	/* alloc dma ring */
+	if (bcm6348_iudma_chan_is_rx(dma->id))
+		ch_priv->dma_ring_size = DMA_RX_DESC;
+	else
+		ch_priv->dma_ring_size = DMA_TX_DESC;
+
+	ch_priv->dma_ring =
+		malloc_cache_aligned(sizeof(struct bcm6348_dma_desc) *
+				     ch_priv->dma_ring_size);
+	if (!ch_priv->dma_ring)
+		return -ENOMEM;
+
+	if (bcm6348_iudma_chan_is_rx(dma->id)) {
+		ch_priv->dma_buff =
+			malloc_cache_aligned(PKTSIZE_ALIGN *
+					     ch_priv->dma_ring_size);
+		if (!ch_priv->dma_buff)
+			return -ENOMEM;
+	} else {
+		ch_priv->dma_buff = NULL;
+	}
+
+	return 0;
+}
+
+static int bcm6348_iudma_receive(struct dma *dma, void **dst, void *metadata)
+{
+	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+	const struct bcm6348_iudma_hw *hw = priv->hw;
+	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+	struct bcm6348_dma_desc *dma_desc;
+	void __iomem *dma_buff;
+	int ret;
+
+	if (ch_priv->dirty_cnt == ch_priv->dma_ring_size) {
+		pr_err("dma rx ring full of dirty descriptors\n");
+		return -EAGAIN;
+	}
+
+	/* get dma ring descriptor address */
+	dma_desc = ch_priv->dma_ring;
+	dma_desc += ch_priv->desc_id;
+
+	/* invalidate cache data */
+	invalidate_dcache_range((ulong)dma_desc,
+		ALIGN_END_ADDR(struct bcm6348_dma_desc, dma_desc, 1));
+
+	/* check dma own */
+	if (dma_desc->status & DMAD_ST_OWN_MASK)
+		return -EAGAIN;
+
+	/* check pkt */
+	if (!(dma_desc->status & DMAD_ST_EOP_MASK) ||
+	    !(dma_desc->status & DMAD_ST_SOP_MASK) ||
+	    (dma_desc->status & hw->err_mask)) {
+		pr_err("invalid pkt received (ch=%ld) (st=%04x)\n",
+		       dma->id, dma_desc->status);
+		ret = -EAGAIN;
+	} else {
+		uint16_t length;
+
+		/* get dma buff descriptor address */
+		dma_buff = phys_to_virt(dma_desc->address);
+
+		/* invalidate cache data */
+		invalidate_dcache_range((ulong)dma_buff,
+					(ulong)(dma_buff + PKTSIZE_ALIGN));
+
+		/* remove crc */
+		length = dma_desc->length - 4;
+
+		/* copy data */
+		memcpy(*dst, dma_buff, length);
+
+		ret = length;
+	}
+
+	/* increment dma descriptor */
+	ch_priv->desc_id = (ch_priv->desc_id + 1) % ch_priv->dma_ring_size;
+	ch_priv->dirty_cnt++;
+
+	return ret;
+}
+
+static int bcm6348_iudma_send(struct dma *dma, void *src, size_t len,
+			      void *metadata)
+{
+	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+	struct bcm6348_dma_desc *dma_desc;
+	uint16_t status;
+
+	/* flush cache */
+	flush_dcache_range((ulong)src, (ulong)src + PKTSIZE_ALIGN);
+
+	/* get dma ring descriptor address */
+	dma_desc = ch_priv->dma_ring;
+	dma_desc += ch_priv->desc_id;
+
+	/* config dma descriptor */
+	status = (DMAD_ST_OWN_MASK |
+		  DMAD_ST_EOP_MASK |
+		  DMAD_ST_CRC_MASK |
+		  DMAD_ST_SOP_MASK);
+	if (ch_priv->desc_id == ch_priv->dma_ring_size - 1)
+		status |= DMAD_ST_WRAP_MASK;
+
+	dma_desc->address = virt_to_phys(src);
+	dma_desc->length = len;
+	dma_desc->status = status;
+
+	/* flush cache */
+	flush_dcache_range((ulong)dma_desc,
+		ALIGN_END_ADDR(struct bcm6348_dma_desc, dma_desc, 1));
+
+	/* kick tx dma channel */
+	setbits_be32(priv->chan + DMAC_CFG_REG(dma->id), DMAC_CFG_ENABLE_MASK);
+
+	/* poll dma status */
+	do {
+		/* invalidate cache */
+		invalidate_dcache_range((ulong)dma_desc,
+			ALIGN_END_ADDR(struct bcm6348_dma_desc, dma_desc, 1));
+
+		if (!(dma_desc->status & DMAD_ST_OWN_MASK))
+			break;
+	} while(1);
+
+	/* increment dma descriptor */
+	ch_priv->desc_id = (ch_priv->desc_id + 1) % ch_priv->dma_ring_size;
+
+	return 0;
+}
+
+int bcm6348_iudma_prepare_rcv_buf(struct dma *dma, void *dst, size_t size)
+{
+	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+
+	/* init dma rings */
+	while (ch_priv->dirty_cnt) {
+		struct bcm6348_dma_desc *dma_desc = ch_priv->dma_ring;
+		uint16_t status = DMAD_ST_OWN_MASK;
+
+		/* get dirty dma descriptor */
+		dma_desc += ch_priv->dirty_desc;
+
+		/* reinit dirty dma descriptor */
+		if (ch_priv->dirty_desc == ch_priv->dma_ring_size - 1)
+			status |= DMAD_ST_WRAP_MASK;
+		dma_desc->length = PKTSIZE_ALIGN;
+		dma_desc->status = status;
+
+		/* flush cache */
+		flush_dcache_range((ulong)dma_desc,
+			ALIGN_END_ADDR(struct bcm6348_dma_desc, dma_desc, 1));
+
+		/* tell dma engine we allocated one buffer */
+		writel_be(1, DMA_FLOWC_ALLOC_REG(dma->id));
+
+		/* bump dirty dma descriptor */
+		ch_priv->dirty_desc = (ch_priv->dirty_desc + 1) %
+				      ch_priv->dma_ring_size;
+
+		/* kick rx dma channel */
+		ch_priv->dirty_cnt--;
+		if (!ch_priv->dirty_cnt)
+			setbits_be32(priv->chan + DMAC_CFG_REG(dma->id),
+				     DMAC_CFG_ENABLE_MASK);
+	}
+
+	return 0;
+}
+
+static const struct dma_ops bcm6348_iudma_ops = {
+	.disable = bcm6348_iudma_disable,
+	.enable = bcm6348_iudma_enable,
+	.prepare_rcv_buf = bcm6348_iudma_prepare_rcv_buf,
+	.request = bcm6348_iudma_request,
+	.receive = bcm6348_iudma_receive,
+	.send = bcm6348_iudma_send,
+};
+
+static const struct bcm6348_iudma_hw bcm6348_hw = {
+	.err_mask = (DMAD6348_ST_OV_ERR_MASK |
+		     DMAD6348_ST_CRC_ERR_MASK |
+		     DMAD6348_ST_RX_ERR_MASK |
+		     DMAD6348_ST_OS_ERR_MASK |
+		     DMAD6348_ST_UN_ERR_MASK),
+};
+
+static const struct bcm6348_iudma_hw bcm6368_hw = {
+	.err_mask = 0,
+};
+
+static const struct udevice_id bcm6348_iudma_ids[] = {
+	{
+		.compatible = "brcm,bcm6348-iudma",
+		.data = (ulong)&bcm6348_hw,
+	}, {
+		.compatible = "brcm,bcm6368-iudma",
+		.data = (ulong)&bcm6368_hw,
+	}, { /* sentinel */ }
+};
+
+static int bcm6348_iudma_probe(struct udevice *dev)
+{
+	struct dma_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct bcm6348_iudma_priv *priv = dev_get_priv(dev);
+	const struct bcm6348_iudma_hw *hw =
+		(const struct bcm6348_iudma_hw *)dev_get_driver_data(dev);
+	fdt_addr_t addr;
+	uint8_t ch;
+	int i;
+
+	uc_priv->supported = (DMA_SUPPORTS_DEV_TO_MEM |
+			      DMA_SUPPORTS_MEM_TO_DEV);
+	priv->hw = hw;
+
+	/* try to enable clocks */
+	for (i = 0; ; i++) {
+		struct clk clk;
+		int ret;
+
+		ret = clk_get_by_index(dev, i, &clk);
+		if (ret < 0)
+			break;
+		if (clk_enable(&clk))
+			pr_err("failed to enable clock %d\n", i);
+		clk_free(&clk);
+	}
+
+	/* try to perform resets */
+	for (i = 0; ; i++) {
+		struct reset_ctl reset;
+		int ret;
+
+		ret = reset_get_by_index(dev, i, &reset);
+		if (ret < 0)
+			break;
+		if (reset_deassert(&reset))
+			pr_err("failed to deassert reset %d\n", i);
+		reset_free(&reset);
+	}
+
+	/* dma global base address */
+	addr = devfdt_get_addr_name(dev, "dma");
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+	priv->base = ioremap(addr, 0);
+
+	/* dma channels base address */
+	addr = devfdt_get_addr_name(dev, "dma-channels");
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+	priv->chan = ioremap(addr, 0);
+
+	/* dma sram base address */
+	addr = devfdt_get_addr_name(dev, "dma-sram");
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+	priv->sram = ioremap(addr, 0);
+
+	/* disable dma controller */
+	clrbits_be32(priv->base + DMA_CFG_REG, DMA_CFG_ENABLE_MASK);
+
+	/* get number of channels */
+	priv->n_channels = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
+					   "dma-channels", 8);
+	if (priv->n_channels > DMA_CHAN_MAX)
+		return -EINVAL;
+
+	/* alloc channel private data pointers */
+	priv->ch_priv = calloc(priv->n_channels,
+			       sizeof(struct bcm6348_chan_priv*));
+	if (!priv->ch_priv)
+		return -ENOMEM;
+
+	/* stop dma channels */
+	for (ch = 0; ch < priv->n_channels; ch++)
+		bcm6348_iudma_chan_stop(priv, ch);
+
+	/* enable dma controller */
+	setbits_be32(priv->base + DMA_CFG_REG, DMA_CFG_ENABLE_MASK);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(bcm6348_iudma) = {
+	.name = "bcm6348_iudma",
+	.id = UCLASS_DMA,
+	.of_match = bcm6348_iudma_ids,
+	.ops = &bcm6348_iudma_ops,
+	.priv_auto_alloc_size = sizeof(struct bcm6348_iudma_priv),
+	.probe = bcm6348_iudma_probe,
+};
-- 
2.11.0

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

* [U-Boot] [PATCH v9 02/28] bmips: bcm6338: add bcm6348-iudma support
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 01/28] dma: add bcm6348-iudma support Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-28 23:48       ` Daniel Schwierzeck
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 03/28] bmips: bcm6348: " Álvaro Fernández Rojas
                       ` (26 subsequent siblings)
  28 siblings, 1 reply; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6338.dtsi       | 14 ++++++++++++++
 include/dt-bindings/dma/bcm6338-dma.h | 15 +++++++++++++++
 2 files changed, 29 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6338-dma.h

diff --git a/arch/mips/dts/brcm,bcm6338.dtsi b/arch/mips/dts/brcm,bcm6338.dtsi
index bbd58cf803..990355481c 100644
--- a/arch/mips/dts/brcm,bcm6338.dtsi
+++ b/arch/mips/dts/brcm,bcm6338.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6338-clock.h>
+#include <dt-bindings/dma/bcm6338-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/reset/bcm6338-reset.h>
 #include "skeleton.dtsi"
@@ -130,5 +131,18 @@
 			reg = <0xfffe3100 0x38>;
 			u-boot,dm-pre-reloc;
 		};
+
+		iudma: dma-controller at fffe2400 {
+			compatible = "brcm,bcm6348-iudma";
+			reg = <0xfffe2400 0x1c>,
+			      <0xfffe2500 0x60>,
+			      <0xfffe2600 0x60>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <6>;
+			resets = <&periph_rst BCM6338_RST_DMAMEM>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6338-dma.h b/include/dt-bindings/dma/bcm6338-dma.h
new file mode 100644
index 0000000000..5dd66239b4
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6338-dma.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6338_H
+#define __DT_BINDINGS_DMA_BCM6338_H
+
+#define BCM6338_DMA_ENET_RX	0
+#define BCM6338_DMA_ENET_TX	1
+
+#endif /* __DT_BINDINGS_DMA_BCM6338_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v9 03/28] bmips: bcm6348: add bcm6348-iudma support
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 01/28] dma: add bcm6348-iudma support Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 02/28] bmips: bcm6338: " Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 04/28] bmips: bcm6358: " Álvaro Fernández Rojas
                       ` (25 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6348.dtsi       | 16 ++++++++++++++++
 include/dt-bindings/dma/bcm6348-dma.h | 17 +++++++++++++++++
 2 files changed, 33 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6348-dma.h

diff --git a/arch/mips/dts/brcm,bcm6348.dtsi b/arch/mips/dts/brcm,bcm6348.dtsi
index cc80bbc808..875de232ca 100644
--- a/arch/mips/dts/brcm,bcm6348.dtsi
+++ b/arch/mips/dts/brcm,bcm6348.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6348-clock.h>
+#include <dt-bindings/dma/bcm6348-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/reset/bcm6348-reset.h>
 #include "skeleton.dtsi"
@@ -159,5 +160,20 @@
 			reg = <0xfffe2300 0x38>;
 			u-boot,dm-pre-reloc;
 		};
+
+		iudma: dma-controller at fffe7000 {
+			compatible = "brcm,bcm6348-iudma";
+			reg = <0xfffe7000 0x1c>,
+			      <0xfffe7100 0x40>,
+			      <0xfffe7200 0x40>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <4>;
+			clocks = <&periph_clk BCM6348_CLK_ENET>;
+			resets = <&periph_rst BCM6348_RST_ENET>,
+				 <&periph_rst BCM6348_RST_DMAMEM>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6348-dma.h b/include/dt-bindings/dma/bcm6348-dma.h
new file mode 100644
index 0000000000..a1d3a6456d
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6348-dma.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6348_H
+#define __DT_BINDINGS_DMA_BCM6348_H
+
+#define BCM6348_DMA_ENET0_RX	0
+#define BCM6348_DMA_ENET0_TX	1
+#define BCM6348_DMA_ENET1_RX	2
+#define BCM6348_DMA_ENET1_TX	3
+
+#endif /* __DT_BINDINGS_DMA_BCM6348_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v9 04/28] bmips: bcm6358: add bcm6348-iudma support
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                       ` (2 preceding siblings ...)
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 03/28] bmips: bcm6348: " Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 05/28] bmips: bcm6368: " Álvaro Fernández Rojas
                       ` (24 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6358.dtsi       | 18 ++++++++++++++++++
 include/dt-bindings/dma/bcm6358-dma.h | 17 +++++++++++++++++
 2 files changed, 35 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6358-dma.h

diff --git a/arch/mips/dts/brcm,bcm6358.dtsi b/arch/mips/dts/brcm,bcm6358.dtsi
index 0617b46e92..5605723e83 100644
--- a/arch/mips/dts/brcm,bcm6358.dtsi
+++ b/arch/mips/dts/brcm,bcm6358.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6358-clock.h>
+#include <dt-bindings/dma/bcm6358-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/reset/bcm6358-reset.h>
 #include "skeleton.dtsi"
@@ -190,5 +191,22 @@
 
 			status = "disabled";
 		};
+
+		iudma: dma-controller at fffe5000 {
+			compatible = "brcm,bcm6348-iudma";
+			reg = <0xfffe5000 0x24>,
+			      <0xfffe5100 0x80>,
+			      <0xfffe5200 0x80>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <8>;
+			clocks = <&periph_clk BCM6358_CLK_EMUSB>,
+				 <&periph_clk BCM6358_CLK_USBSU>,
+				 <&periph_clk BCM6358_CLK_EPHY>;
+			resets = <&periph_rst BCM6358_RST_ENET>,
+				 <&periph_rst BCM6358_RST_EPHY>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6358-dma.h b/include/dt-bindings/dma/bcm6358-dma.h
new file mode 100644
index 0000000000..3b1fcf8540
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6358-dma.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6358_H
+#define __DT_BINDINGS_DMA_BCM6358_H
+
+#define BCM6358_DMA_ENET0_RX	0
+#define BCM6358_DMA_ENET0_TX	1
+#define BCM6358_DMA_ENET1_RX	2
+#define BCM6358_DMA_ENET1_TX	3
+
+#endif /* __DT_BINDINGS_DMA_BCM6358_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v9 05/28] bmips: bcm6368: add bcm6348-iudma support
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                       ` (3 preceding siblings ...)
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 04/28] bmips: bcm6358: " Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 06/28] bmips: bcm6328: " Álvaro Fernández Rojas
                       ` (23 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6368.dtsi       | 13 +++++++++++++
 include/dt-bindings/dma/bcm6368-dma.h | 15 +++++++++++++++
 2 files changed, 28 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6368-dma.h

diff --git a/arch/mips/dts/brcm,bcm6368.dtsi b/arch/mips/dts/brcm,bcm6368.dtsi
index 65d769ab4f..30047f6360 100644
--- a/arch/mips/dts/brcm,bcm6368.dtsi
+++ b/arch/mips/dts/brcm,bcm6368.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6368-clock.h>
+#include <dt-bindings/dma/bcm6368-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/reset/bcm6368-reset.h>
 #include "skeleton.dtsi"
@@ -192,5 +193,17 @@
 
 			status = "disabled";
 		};
+
+		iudma: dma-controller at 10006800 {
+			compatible = "brcm,bcm6368-iudma";
+			reg = <0x10006800 0x80>,
+			      <0x10006a00 0x80>,
+			      <0x10006c00 0x80>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <8>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6368-dma.h b/include/dt-bindings/dma/bcm6368-dma.h
new file mode 100644
index 0000000000..45ffb89e0a
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6368-dma.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6368_H
+#define __DT_BINDINGS_DMA_BCM6368_H
+
+#define BCM6368_DMA_ENETSW_RX	0
+#define BCM6368_DMA_ENETSW_TX	1
+
+#endif /* __DT_BINDINGS_DMA_BCM6368_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v9 06/28] bmips: bcm6328: add bcm6348-iudma support
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                       ` (4 preceding siblings ...)
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 05/28] bmips: bcm6368: " Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 07/28] bmips: bcm6362: " Álvaro Fernández Rojas
                       ` (22 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6328.dtsi       | 13 +++++++++++++
 include/dt-bindings/dma/bcm6328-dma.h | 15 +++++++++++++++
 2 files changed, 28 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6328-dma.h

diff --git a/arch/mips/dts/brcm,bcm6328.dtsi b/arch/mips/dts/brcm,bcm6328.dtsi
index e00a2950e2..6fa49e22bb 100644
--- a/arch/mips/dts/brcm,bcm6328.dtsi
+++ b/arch/mips/dts/brcm,bcm6328.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6328-clock.h>
+#include <dt-bindings/dma/bcm6328-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/power-domain/bcm6328-power-domain.h>
 #include <dt-bindings/reset/bcm6328-reset.h>
@@ -187,5 +188,17 @@
 			reg = <0x10003000 0x864>;
 			u-boot,dm-pre-reloc;
 		};
+
+		iudma: dma-controller at 1000d800 {
+			compatible = "brcm,bcm6368-iudma";
+			reg = <0x1000d800 0x80>,
+			      <0x1000da00 0x80>,
+			      <0x1000dc00 0x80>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <8>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6328-dma.h b/include/dt-bindings/dma/bcm6328-dma.h
new file mode 100644
index 0000000000..508a5dc523
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6328-dma.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6328_H
+#define __DT_BINDINGS_DMA_BCM6328_H
+
+#define BCM6328_DMA_ENETSW_RX	0
+#define BCM6328_DMA_ENETSW_TX	1
+
+#endif /* __DT_BINDINGS_DMA_BCM6328_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v9 07/28] bmips: bcm6362: add bcm6348-iudma support
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                       ` (5 preceding siblings ...)
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 06/28] bmips: bcm6328: " Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 08/28] bmips: bcm63268: " Álvaro Fernández Rojas
                       ` (21 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6362.dtsi       | 13 +++++++++++++
 include/dt-bindings/dma/bcm6362-dma.h | 15 +++++++++++++++
 2 files changed, 28 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6362-dma.h

diff --git a/arch/mips/dts/brcm,bcm6362.dtsi b/arch/mips/dts/brcm,bcm6362.dtsi
index 3047b82b21..94e7de096d 100644
--- a/arch/mips/dts/brcm,bcm6362.dtsi
+++ b/arch/mips/dts/brcm,bcm6362.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6362-clock.h>
+#include <dt-bindings/dma/bcm6362-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/power-domain/bcm6362-power-domain.h>
 #include <dt-bindings/reset/bcm6362-reset.h>
@@ -211,5 +212,17 @@
 			reg = <0x10003000 0x864>;
 			u-boot,dm-pre-reloc;
 		};
+
+		iudma: dma-controller at 1000d800 {
+			compatible = "brcm,bcm6368-iudma";
+			reg = <0x1000d800 0x80>,
+			      <0x1000da00 0x80>,
+			      <0x1000dc00 0x80>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <8>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6362-dma.h b/include/dt-bindings/dma/bcm6362-dma.h
new file mode 100644
index 0000000000..b90b3ffeb6
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6362-dma.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6362_H
+#define __DT_BINDINGS_DMA_BCM6362_H
+
+#define BCM6362_DMA_ENETSW_RX	0
+#define BCM6362_DMA_ENETSW_TX	1
+
+#endif /* __DT_BINDINGS_DMA_BCM6362_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v9 08/28] bmips: bcm63268: add bcm6348-iudma support
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                       ` (6 preceding siblings ...)
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 07/28] bmips: bcm6362: " Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 09/28] bmips: bcm6318: " Álvaro Fernández Rojas
                       ` (20 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm63268.dtsi       | 13 +++++++++++++
 include/dt-bindings/dma/bcm63268-dma.h | 15 +++++++++++++++
 2 files changed, 28 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm63268-dma.h

diff --git a/arch/mips/dts/brcm,bcm63268.dtsi b/arch/mips/dts/brcm,bcm63268.dtsi
index 62c440e675..c7ad83c306 100644
--- a/arch/mips/dts/brcm,bcm63268.dtsi
+++ b/arch/mips/dts/brcm,bcm63268.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm63268-clock.h>
+#include <dt-bindings/dma/bcm63268-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/power-domain/bcm63268-power-domain.h>
 #include <dt-bindings/reset/bcm63268-reset.h>
@@ -217,5 +218,17 @@
 			reg = <0x10003000 0x894>;
 			u-boot,dm-pre-reloc;
 		};
+
+		iudma: dma-controller at 1000d800 {
+			compatible = "brcm,bcm6368-iudma";
+			reg = <0x1000d800 0x80>,
+			      <0x1000da00 0x80>,
+			      <0x1000dc00 0x80>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <8>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm63268-dma.h b/include/dt-bindings/dma/bcm63268-dma.h
new file mode 100644
index 0000000000..d5d7453be1
--- /dev/null
+++ b/include/dt-bindings/dma/bcm63268-dma.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM63268_H
+#define __DT_BINDINGS_DMA_BCM63268_H
+
+#define BCM63268_DMA_ENETSW_RX	0
+#define BCM63268_DMA_ENETSW_TX	1
+
+#endif /* __DT_BINDINGS_DMA_BCM63268_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v9 09/28] bmips: bcm6318: add bcm6348-iudma support
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                       ` (7 preceding siblings ...)
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 08/28] bmips: bcm63268: " Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 10/28] net: add support for bcm6348-enet Álvaro Fernández Rojas
                       ` (19 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6318.dtsi       | 19 +++++++++++++++++++
 include/dt-bindings/dma/bcm6318-dma.h | 15 +++++++++++++++
 2 files changed, 34 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6318-dma.h

diff --git a/arch/mips/dts/brcm,bcm6318.dtsi b/arch/mips/dts/brcm,bcm6318.dtsi
index f75988be12..d04b7cbb01 100644
--- a/arch/mips/dts/brcm,bcm6318.dtsi
+++ b/arch/mips/dts/brcm,bcm6318.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6318-clock.h>
+#include <dt-bindings/dma/bcm6318-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/power-domain/bcm6318-power-domain.h>
 #include <dt-bindings/reset/bcm6318-reset.h>
@@ -54,6 +55,12 @@
 			reg = <0x10000004 0x4>;
 			#clock-cells = <1>;
 		};
+
+		ubus_clk: ubus-clk {
+			compatible = "brcm,bcm6345-clk";
+			reg = <0x10000008 0x4>;
+			#clock-cells = <1>;
+		};
 	};
 
 	ubus {
@@ -182,5 +189,17 @@
 
 			status = "disabled";
 		};
+
+		iudma: dma-controller at 10088000 {
+			compatible = "brcm,bcm6368-iudma";
+			reg = <0x10088000 0x80>,
+			      <0x10088200 0x80>,
+			      <0x10088400 0x80>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <8>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6318-dma.h b/include/dt-bindings/dma/bcm6318-dma.h
new file mode 100644
index 0000000000..c039391395
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6318-dma.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6318_H
+#define __DT_BINDINGS_DMA_BCM6318_H
+
+#define BCM6318_DMA_ENETSW_RX	0
+#define BCM6318_DMA_ENETSW_TX	1
+
+#endif /* __DT_BINDINGS_DMA_BCM6318_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v9 10/28] net: add support for bcm6348-enet
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                       ` (8 preceding siblings ...)
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 09/28] bmips: bcm6318: " Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-28 23:58       ` Daniel Schwierzeck
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 11/28] bmips: bcm6338: " Álvaro Fernández Rojas
                       ` (18 subsequent siblings)
  28 siblings, 1 reply; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: use dma_prepare_rcv_buf and remove dma rx channel reset:
  - bcm6348_eth_recv: clear dirty dma descriptors only when packets are copied
   from rx dma.
  - bcm6348_eth_send: remove dma rx channel reset when sending packet.
 v8: Introduce changes from Grygorii Strashko
 v5: Receive as much packets as possible from bcm6348-eth and cache them in
 net_rx_packets. This is needed in order to fix flow control issues.
 v4: Fix issues reported by Grygorii Strashko and other fixes:
  - Copy received dma buffer to net_rx_packets in order to avoid possible
  dma overwrites.
  - Reset dma rx channel when sending a new packet to prevent flow control
  issues.
  - Fix packet casting on bcm6348_eth_recv/send.
 v3: no changes
 v2: select DMA_CHANNELS.

 drivers/net/Kconfig            |  10 +
 drivers/net/Makefile           |   1 +
 drivers/net/bcm6348-eth.c      | 576 +++++++++++++++++++++++++++++++++++++++++
 include/configs/bmips_common.h |   5 +-
 4 files changed, 591 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/bcm6348-eth.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 8fb365fc5d..2b7cec8804 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -72,6 +72,16 @@ config BCM_SF2_ETH_GMAC
 	  by the BCM_SF2_ETH driver.
 	  Say Y to any bcmcygnus based platforms.
 
+config BCM6348_ETH
+	bool "BCM6348 EMAC support"
+	depends on DM_ETH && ARCH_BMIPS
+	select DMA
+	select DMA_CHANNELS
+	select MII
+	select PHYLIB
+	help
+	  This driver supports the BCM6348 Ethernet MAC.
+
 config DWC_ETH_QOS
 	bool "Synopsys DWC Ethernet QOS device support"
 	depends on DM_ETH
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 99056aa041..2647d4dd23 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -6,6 +6,7 @@
 obj-$(CONFIG_ALTERA_TSE) += altera_tse.o
 obj-$(CONFIG_AG7XXX) += ag7xxx.o
 obj-$(CONFIG_ARMADA100_FEC) += armada100_fec.o
+obj-$(CONFIG_BCM6348_ETH) += bcm6348-eth.o
 obj-$(CONFIG_DRIVER_AT91EMAC) += at91_emac.o
 obj-$(CONFIG_DRIVER_AX88180) += ax88180.o
 obj-$(CONFIG_BCM_SF2_ETH) += bcm-sf2-eth.o
diff --git a/drivers/net/bcm6348-eth.c b/drivers/net/bcm6348-eth.c
new file mode 100644
index 0000000000..24a44d83cb
--- /dev/null
+++ b/drivers/net/bcm6348-eth.c
@@ -0,0 +1,576 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c:
+ *	Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dma.h>
+#include <miiphy.h>
+#include <net.h>
+#include <phy.h>
+#include <reset.h>
+#include <wait_bit.h>
+#include <asm/io.h>
+
+#define ETH_RX_DESC			PKTBUFSRX
+#define ETH_MAX_MTU_SIZE		1518
+#define ETH_TIMEOUT			100
+#define ETH_TX_WATERMARK		32
+
+/* ETH Receiver Configuration register */
+#define ETH_RXCFG_REG			0x00
+#define ETH_RXCFG_ENFLOW_SHIFT		5
+#define ETH_RXCFG_ENFLOW_MASK		(1 << ETH_RXCFG_ENFLOW_SHIFT)
+
+/* ETH Receive Maximum Length register */
+#define ETH_RXMAXLEN_REG		0x04
+#define ETH_RXMAXLEN_SHIFT		0
+#define ETH_RXMAXLEN_MASK		(0x7ff << ETH_RXMAXLEN_SHIFT)
+
+/* ETH Transmit Maximum Length register */
+#define ETH_TXMAXLEN_REG		0x08
+#define ETH_TXMAXLEN_SHIFT		0
+#define ETH_TXMAXLEN_MASK		(0x7ff << ETH_TXMAXLEN_SHIFT)
+
+/* MII Status/Control register */
+#define MII_SC_REG			0x10
+#define MII_SC_MDCFREQDIV_SHIFT		0
+#define MII_SC_MDCFREQDIV_MASK		(0x7f << MII_SC_MDCFREQDIV_SHIFT)
+#define MII_SC_PREAMBLE_EN_SHIFT	7
+#define MII_SC_PREAMBLE_EN_MASK		(1 << MII_SC_PREAMBLE_EN_SHIFT)
+
+/* MII Data register */
+#define MII_DAT_REG			0x14
+#define MII_DAT_DATA_SHIFT		0
+#define MII_DAT_DATA_MASK		(0xffff << MII_DAT_DATA_SHIFT)
+#define MII_DAT_TA_SHIFT		16
+#define MII_DAT_TA_MASK			(0x3 << MII_DAT_TA_SHIFT)
+#define MII_DAT_REG_SHIFT		18
+#define MII_DAT_REG_MASK		(0x1f << MII_DAT_REG_SHIFT)
+#define MII_DAT_PHY_SHIFT		23
+#define MII_DAT_PHY_MASK		(0x1f << MII_DAT_PHY_SHIFT)
+#define MII_DAT_OP_SHIFT		28
+#define MII_DAT_OP_WRITE		(0x5 << MII_DAT_OP_SHIFT)
+#define MII_DAT_OP_READ			(0x6 << MII_DAT_OP_SHIFT)
+
+/* ETH Interrupts Mask register */
+#define ETH_IRMASK_REG			0x18
+
+/* ETH Interrupts register */
+#define ETH_IR_REG			0x1c
+#define ETH_IR_MII_SHIFT		0
+#define ETH_IR_MII_MASK			(1 << ETH_IR_MII_SHIFT)
+
+/* ETH Control register */
+#define ETH_CTL_REG			0x2c
+#define ETH_CTL_ENABLE_SHIFT		0
+#define ETH_CTL_ENABLE_MASK		(1 << ETH_CTL_ENABLE_SHIFT)
+#define ETH_CTL_DISABLE_SHIFT		1
+#define ETH_CTL_DISABLE_MASK		(1 << ETH_CTL_DISABLE_SHIFT)
+#define ETH_CTL_RESET_SHIFT		2
+#define ETH_CTL_RESET_MASK		(1 << ETH_CTL_RESET_SHIFT)
+#define ETH_CTL_EPHY_SHIFT		3
+#define ETH_CTL_EPHY_MASK		(1 << ETH_CTL_EPHY_SHIFT)
+
+/* ETH Transmit Control register */
+#define ETH_TXCTL_REG			0x30
+#define ETH_TXCTL_FD_SHIFT		0
+#define ETH_TXCTL_FD_MASK		(1 << ETH_TXCTL_FD_SHIFT)
+
+/* ETH Transmit Watermask register */
+#define ETH_TXWMARK_REG			0x34
+#define ETH_TXWMARK_WM_SHIFT		0
+#define ETH_TXWMARK_WM_MASK		(0x3f << ETH_TXWMARK_WM_SHIFT)
+
+/* MIB Control register */
+#define MIB_CTL_REG			0x38
+#define MIB_CTL_RDCLEAR_SHIFT		0
+#define MIB_CTL_RDCLEAR_MASK		(1 << MIB_CTL_RDCLEAR_SHIFT)
+
+/* ETH Perfect Match registers */
+#define ETH_PM_CNT			4
+#define ETH_PML_REG(x)			(0x58 + (x) * 0x8)
+#define ETH_PMH_REG(x)			(0x5c + (x) * 0x8)
+#define ETH_PMH_VALID_SHIFT		16
+#define ETH_PMH_VALID_MASK		(1 << ETH_PMH_VALID_SHIFT)
+
+/* MIB Counters registers */
+#define MIB_REG_CNT			55
+#define MIB_REG(x)			(0x200 + (x) * 4)
+
+/* ETH data */
+struct bcm6348_eth_priv {
+	void __iomem *base;
+	/* RX */
+	uint8_t rx_desc;
+	uint8_t rx_pend;
+	int rx_ret[ETH_RX_DESC];
+	/* DMA */
+	struct dma rx_dma;
+	struct dma tx_dma;
+	/* PHY */
+	int phy_id;
+	struct phy_device *phy_dev;
+};
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void bcm6348_eth_mac_disable(struct bcm6348_eth_priv *priv)
+{
+	/* disable emac */
+	clrsetbits_be32(priv->base + ETH_CTL_REG, ETH_CTL_ENABLE_MASK,
+			ETH_CTL_DISABLE_MASK);
+
+	/* wait until emac is disabled */
+	if (wait_for_bit_be32(priv->base + ETH_CTL_REG,
+			      ETH_CTL_DISABLE_MASK, false,
+			      ETH_TIMEOUT, false))
+		pr_err("error disabling emac\n");
+}
+
+static void bcm6348_eth_mac_enable(struct bcm6348_eth_priv *priv)
+{
+	setbits_be32(priv->base + ETH_CTL_REG, ETH_CTL_ENABLE_MASK);
+}
+
+static void bcm6348_eth_mac_reset(struct bcm6348_eth_priv *priv)
+{
+	/* reset emac */
+	writel_be(ETH_CTL_RESET_MASK, priv->base + ETH_CTL_REG);
+	wmb();
+
+	/* wait until emac is reset */
+	if (wait_for_bit_be32(priv->base + ETH_CTL_REG,
+			      ETH_CTL_RESET_MASK, false,
+			      ETH_TIMEOUT, false))
+		pr_err("error resetting emac\n");
+}
+
+static int bcm6348_eth_free_pkt(struct udevice *dev, uchar *packet, int len)
+{
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+
+	/* sanity check */
+	if (packet != net_rx_packets[priv->rx_pend]) {
+		pr_err("rx_pend %d: packet is not matched,\n", priv->rx_pend);
+		return -EAGAIN;
+	}
+
+	/* free pending packet */
+	priv->rx_ret[priv->rx_pend] = 0;
+	priv->rx_pend = (priv->rx_pend + 1) % ETH_RX_DESC;
+
+	return 0;
+}
+
+static int _bcm6348_eth_recv(struct bcm6348_eth_priv *priv)
+{
+	uint8_t pkt = priv->rx_desc;
+
+	/* check if packet is free */
+	if (priv->rx_ret[pkt] > 0)
+		return -EAGAIN;
+
+	/* try to receive a new packet */
+	priv->rx_ret[pkt] = dma_receive(&priv->rx_dma,
+					(void **)&net_rx_packets[pkt],
+					NULL);
+	if (priv->rx_ret[pkt] > 0)
+		priv->rx_desc = (priv->rx_desc + 1) % ETH_RX_DESC;
+
+	return priv->rx_ret[pkt];
+}
+
+static int bcm6348_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+
+	/* receive packets if queue is empty */
+	if (priv->rx_ret[priv->rx_pend] <= 0) {
+		uint8_t pkt_cnt = 0;
+
+		/* try to receive packets */
+		while (_bcm6348_eth_recv(priv) > 0)
+			pkt_cnt++;
+
+		dma_prepare_rcv_buf(&priv->rx_dma, NULL, 0);
+
+		if (pkt_cnt)
+			debug("%s: received %u packet(s)\n", __func__, pkt_cnt);
+	}
+
+	/* return current packet */
+	if (priv->rx_ret[priv->rx_pend] > 0)
+		*packetp = net_rx_packets[priv->rx_pend];
+
+	return priv->rx_ret[priv->rx_pend];
+}
+
+static int bcm6348_eth_send(struct udevice *dev, void *packet, int length)
+{
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+
+	return dma_send(&priv->tx_dma, packet, length, NULL);
+}
+
+static int bcm6348_eth_adjust_link(struct udevice *dev,
+				   struct phy_device *phydev)
+{
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+
+	/* mac duplex parameters */
+	if (phydev->duplex)
+		setbits_be32(priv->base + ETH_TXCTL_REG, ETH_TXCTL_FD_MASK);
+	else
+		clrbits_be32(priv->base + ETH_TXCTL_REG, ETH_TXCTL_FD_MASK);
+
+	/* rx flow control (pause frame handling) */
+	if (phydev->pause)
+		setbits_be32(priv->base + ETH_RXCFG_REG,
+			     ETH_RXCFG_ENFLOW_MASK);
+	else
+		clrbits_be32(priv->base + ETH_RXCFG_REG,
+			     ETH_RXCFG_ENFLOW_MASK);
+
+	return 0;
+}
+
+static int bcm6348_eth_start(struct udevice *dev)
+{
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+	int ret, i;
+
+	priv->rx_desc = 0;
+	priv->rx_pend = 0;
+	for (i = 0; i < ETH_RX_DESC; i++)
+		priv->rx_ret[i] = 0;
+
+	/* enable dma rx channel */
+	dma_enable(&priv->rx_dma);
+
+	/* enable dma tx channel */
+	dma_enable(&priv->tx_dma);
+
+	ret = phy_startup(priv->phy_dev);
+	if (ret) {
+		pr_err("could not initialize phy\n");
+		return ret;
+	}
+
+	if (!priv->phy_dev->link) {
+		pr_err("no phy link\n");
+		return -EIO;
+	}
+
+	bcm6348_eth_adjust_link(dev, priv->phy_dev);
+
+	/* zero mib counters */
+	for (i = 0; i < MIB_REG_CNT; i++)
+		writel_be(0, MIB_REG(i));
+
+	/* enable rx flow control */
+	setbits_be32(priv->base + ETH_RXCFG_REG, ETH_RXCFG_ENFLOW_MASK);
+
+	/* set max rx/tx length */
+	writel_be((ETH_MAX_MTU_SIZE << ETH_RXMAXLEN_SHIFT) &
+		  ETH_RXMAXLEN_MASK, priv->base + ETH_RXMAXLEN_REG);
+	writel_be((ETH_MAX_MTU_SIZE << ETH_TXMAXLEN_SHIFT) &
+		   ETH_TXMAXLEN_MASK, priv->base + ETH_TXMAXLEN_REG);
+
+	/* set correct transmit fifo watermark */
+	writel_be((ETH_TX_WATERMARK << ETH_TXWMARK_WM_SHIFT) &
+		  ETH_TXWMARK_WM_MASK, priv->base + ETH_TXWMARK_REG);
+
+	/* enable emac */
+	bcm6348_eth_mac_enable(priv);
+
+	/* clear interrupts */
+	writel_be(0, priv->base + ETH_IRMASK_REG);
+
+	return 0;
+}
+
+static void bcm6348_eth_stop(struct udevice *dev)
+{
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+
+	/* disable dma rx channel */
+	dma_disable(&priv->rx_dma);
+
+	/* disable dma tx channel */
+	dma_disable(&priv->tx_dma);
+
+	/* disable emac */
+	bcm6348_eth_mac_disable(priv);
+}
+
+static int bcm6348_eth_write_hwaddr(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+	bool running = false;
+
+	/* check if emac is running */
+	if (readl_be(priv->base + ETH_CTL_REG) & ETH_CTL_ENABLE_MASK)
+		running = true;
+
+	/* disable emac */
+	if (running)
+		bcm6348_eth_mac_disable(priv);
+
+	/* set mac address */
+	writel_be((pdata->enetaddr[2] << 24) | (pdata->enetaddr[3]) << 16 |
+		  (pdata->enetaddr[4]) << 8 | (pdata->enetaddr[5]),
+		  priv->base + ETH_PML_REG(0));
+	writel_be((pdata->enetaddr[1]) | (pdata->enetaddr[0] << 8) |
+		  ETH_PMH_VALID_MASK, priv->base + ETH_PMH_REG(0));
+
+	/* enable emac */
+	if (running)
+		bcm6348_eth_mac_enable(priv);
+
+	return 0;
+}
+
+static const struct eth_ops bcm6348_eth_ops = {
+	.free_pkt = bcm6348_eth_free_pkt,
+	.recv = bcm6348_eth_recv,
+	.send = bcm6348_eth_send,
+	.start = bcm6348_eth_start,
+	.stop = bcm6348_eth_stop,
+	.write_hwaddr = bcm6348_eth_write_hwaddr,
+};
+
+static const struct udevice_id bcm6348_eth_ids[] = {
+	{ .compatible = "brcm,bcm6348-enet", },
+	{ /* sentinel */ }
+};
+
+static int bcm6348_mdio_op(void __iomem *base, uint32_t data)
+{
+	/* make sure mii interrupt status is cleared */
+	writel_be(ETH_IR_MII_MASK, base + ETH_IR_REG);
+
+	/* issue mii op */
+	writel_be(data, base + MII_DAT_REG);
+
+	/* wait until emac is disabled */
+	return wait_for_bit_be32(base + ETH_IR_REG,
+				 ETH_IR_MII_MASK, true,
+				 ETH_TIMEOUT, false);
+}
+
+static int bcm6348_mdio_read(struct mii_dev *bus, int addr, int devaddr,
+			     int reg)
+{
+	void __iomem *base = bus->priv;
+	uint32_t val;
+
+	val = MII_DAT_OP_READ;
+	val |= (reg << MII_DAT_REG_SHIFT) & MII_DAT_REG_MASK;
+	val |= (0x2 << MII_DAT_TA_SHIFT) & MII_DAT_TA_MASK;
+	val |= (addr << MII_DAT_PHY_SHIFT) & MII_DAT_PHY_MASK;
+
+	if (bcm6348_mdio_op(base, val)) {
+		pr_err("%s: timeout\n", __func__);
+		return -EINVAL;
+	}
+
+	val = readl_be(base + MII_DAT_REG) & MII_DAT_DATA_MASK;
+	val >>= MII_DAT_DATA_SHIFT;
+
+	return val;
+}
+
+static int bcm6348_mdio_write(struct mii_dev *bus, int addr, int dev_addr,
+			      int reg, u16 value)
+{
+	void __iomem *base = bus->priv;
+	uint32_t val;
+
+	val = MII_DAT_OP_WRITE;
+	val |= (reg << MII_DAT_REG_SHIFT) & MII_DAT_REG_MASK;
+	val |= (0x2 << MII_DAT_TA_SHIFT) & MII_DAT_TA_MASK;
+	val |= (addr << MII_DAT_PHY_SHIFT) & MII_DAT_PHY_MASK;
+	val |= (value << MII_DAT_DATA_SHIFT) & MII_DAT_DATA_MASK;
+
+	if (bcm6348_mdio_op(base, val)) {
+		pr_err("%s: timeout\n", __func__);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int bcm6348_mdio_init(const char *name, void __iomem *base)
+{
+	struct mii_dev *bus;
+
+	bus = mdio_alloc();
+	if (!bus) {
+		pr_err("%s: failed to allocate MDIO bus\n", __func__);
+		return -ENOMEM;
+	}
+
+	bus->read = bcm6348_mdio_read;
+	bus->write = bcm6348_mdio_write;
+	bus->priv = base;
+	snprintf(bus->name, sizeof(bus->name), "%s", name);
+
+	return mdio_register(bus);
+}
+
+static int bcm6348_phy_init(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+	struct mii_dev *bus;
+
+	/* get mii bus */
+	bus = miiphy_get_dev_by_name(dev->name);
+
+	/* phy connect */
+	priv->phy_dev = phy_connect(bus, priv->phy_id, dev,
+				    pdata->phy_interface);
+	if (!priv->phy_dev) {
+		pr_err("%s: no phy device\n", __func__);
+		return -ENODEV;
+	}
+
+	priv->phy_dev->supported = (SUPPORTED_10baseT_Half |
+				    SUPPORTED_10baseT_Full |
+				    SUPPORTED_100baseT_Half |
+				    SUPPORTED_100baseT_Full |
+				    SUPPORTED_Autoneg |
+				    SUPPORTED_Pause |
+				    SUPPORTED_MII);
+	priv->phy_dev->advertising = priv->phy_dev->supported;
+
+	/* phy config */
+	phy_config(priv->phy_dev);
+
+	return 0;
+}
+
+static int bcm6348_eth_probe(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+	void *blob = (void *)gd->fdt_blob;
+	int node = dev_of_offset(dev);
+	const char *phy_mode;
+	fdt_addr_t addr;
+	int phy_node, ret, i;
+
+	/* get base address */
+	addr = devfdt_get_addr(dev);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	/* get phy mode */
+	pdata->phy_interface = PHY_INTERFACE_MODE_NONE;
+	phy_mode = fdt_getprop(blob, node, "phy-mode", NULL);
+	if (phy_mode)
+		pdata->phy_interface = phy_get_interface_by_name(phy_mode);
+	if (pdata->phy_interface == PHY_INTERFACE_MODE_NONE)
+		return -ENODEV;
+
+	/* get phy */
+	phy_node = fdtdec_lookup_phandle(blob, node, "phy");
+	if (phy_node >= 0)
+		priv->phy_id = fdtdec_get_int(blob, phy_node, "reg", -1);
+	else
+		return -EINVAL;
+
+	/* get dma channels */
+	ret = dma_get_by_name(dev, "tx", &priv->tx_dma);
+	if (ret)
+		return -EINVAL;
+
+	ret = dma_get_by_name(dev, "rx", &priv->rx_dma);
+	if (ret)
+		return -EINVAL;
+
+	/* try to enable clocks */
+	for (i = 0; ; i++) {
+		struct clk clk;
+		int ret;
+
+		ret = clk_get_by_index(dev, i, &clk);
+		if (ret < 0)
+			break;
+		if (clk_enable(&clk))
+			pr_err("failed to enable clock %d\n", i);
+		clk_free(&clk);
+	}
+
+	/* try to perform resets */
+	for (i = 0; ; i++) {
+		struct reset_ctl reset;
+		int ret;
+
+		ret = reset_get_by_index(dev, i, &reset);
+		if (ret < 0)
+			break;
+		if (reset_deassert(&reset))
+			pr_err("failed to deassert reset %d\n", i);
+		reset_free(&reset);
+	}
+
+	/* get base addr */
+	priv->base = ioremap(addr, 0);
+	pdata->iobase = (phys_addr_t) priv->base;
+
+	/* disable emac */
+	bcm6348_eth_mac_disable(priv);
+
+	/* reset emac */
+	bcm6348_eth_mac_reset(priv);
+
+	/* select correct mii interface */
+	if (pdata->phy_interface == PHY_INTERFACE_MODE_INTERNAL)
+		clrbits_be32(priv->base + ETH_CTL_REG, ETH_CTL_EPHY_MASK);
+	else
+		setbits_be32(priv->base + ETH_CTL_REG, ETH_CTL_EPHY_MASK);
+
+	/* turn on mdc clock */
+	writel_be((0x1f << MII_SC_MDCFREQDIV_SHIFT) |
+		  MII_SC_PREAMBLE_EN_MASK, priv->base + MII_SC_REG);
+
+	/* set mib counters to not clear when read */
+	clrbits_be32(priv->base + MIB_CTL_REG, MIB_CTL_RDCLEAR_MASK);
+
+	/* initialize perfect match registers */
+	for (i = 0; i < ETH_PM_CNT; i++) {
+		writel_be(0, priv->base + ETH_PML_REG(i));
+		writel_be(0, priv->base + ETH_PMH_REG(i));
+	}
+
+	/* init mii bus */
+	ret = bcm6348_mdio_init(dev->name, priv->base);
+	if (ret)
+		return ret;
+
+	/* init phy */
+	ret = bcm6348_phy_init(dev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+U_BOOT_DRIVER(bcm6348_eth) = {
+	.name = "bcm6348_eth",
+	.id = UCLASS_ETH,
+	.of_match = bcm6348_eth_ids,
+	.ops = &bcm6348_eth_ops,
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+	.priv_auto_alloc_size = sizeof(struct bcm6348_eth_priv),
+	.probe = bcm6348_eth_probe,
+};
diff --git a/include/configs/bmips_common.h b/include/configs/bmips_common.h
index 39ca2e0bf3..65aa9c77cc 100644
--- a/include/configs/bmips_common.h
+++ b/include/configs/bmips_common.h
@@ -6,6 +6,9 @@
 #ifndef __CONFIG_BMIPS_COMMON_H
 #define __CONFIG_BMIPS_COMMON_H
 
+/* ETH */
+#define CONFIG_PHY_RESET_DELAY		20
+
 /* UART */
 #define CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200, \
 					  230400, 500000, 1500000 }
@@ -16,7 +19,7 @@
 
 /* Memory usage */
 #define CONFIG_SYS_MAXARGS		24
-#define CONFIG_SYS_MALLOC_LEN		(1024 * 1024)
+#define CONFIG_SYS_MALLOC_LEN		(2 * 1024 * 1024)
 #define CONFIG_SYS_BOOTPARAMS_LEN	(128 * 1024)
 #define CONFIG_SYS_CBSIZE		512
 
-- 
2.11.0

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

* [U-Boot] [PATCH v9 11/28] bmips: bcm6338: add support for bcm6348-enet
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                       ` (9 preceding siblings ...)
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 10/28] net: add support for bcm6348-enet Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 12/28] bmips: enable f@st1704 enet support Álvaro Fernández Rojas
                       ` (17 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6338.dtsi | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6338.dtsi b/arch/mips/dts/brcm,bcm6338.dtsi
index 990355481c..c547e949dd 100644
--- a/arch/mips/dts/brcm,bcm6338.dtsi
+++ b/arch/mips/dts/brcm,bcm6338.dtsi
@@ -144,5 +144,20 @@
 			dma-channels = <6>;
 			resets = <&periph_rst BCM6338_RST_DMAMEM>;
 		};
+
+		enet: ethernet at fffe2800 {
+			compatible = "brcm,bcm6348-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xfffe2800 0x2dc>;
+			clocks = <&periph_clk BCM6338_CLK_ENET>;
+			resets = <&periph_rst BCM6338_RST_ENET>;
+			dmas = <&iudma BCM6338_DMA_ENET_RX>,
+			       <&iudma BCM6338_DMA_ENET_TX>;
+			dma-names = "rx",
+				    "tx";
+
+			status = "disabled";
+		};
 	};
 };
-- 
2.11.0

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

* [U-Boot] [PATCH v9 12/28] bmips: enable f@st1704 enet support
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                       ` (10 preceding siblings ...)
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 11/28] bmips: bcm6338: " Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 13/28] bmips: bcm6348: add support for bcm6348-enet Álvaro Fernández Rojas
                       ` (16 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/sagem,f at st1704.dts     | 12 ++++++++++++
 configs/sagem_f at st1704_ram_defconfig |  8 +++++++-
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/sagem,f at st1704.dts b/arch/mips/dts/sagem,f at st1704.dts
index 5300f8b6df..ec6846dd9f 100644
--- a/arch/mips/dts/sagem,f at st1704.dts
+++ b/arch/mips/dts/sagem,f at st1704.dts
@@ -39,6 +39,18 @@
 	};
 };
 
+&enet {
+	status = "okay";
+	phy = <&enetphy>;
+	phy-mode = "mii";
+
+	enetphy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio {
 	status = "okay";
 };
diff --git a/configs/sagem_f at st1704_ram_defconfig b/configs/sagem_f at st1704_ram_defconfig
index 91a966327a..8c36f5dbf8 100644
--- a/configs/sagem_f at st1704_ram_defconfig
+++ b/configs/sagem_f at st1704_ram_defconfig
@@ -27,11 +27,14 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="sagem,f at st1704"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
@@ -40,6 +43,9 @@ CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_SPI_FLASH_MTD=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6348_ETH=y
 CONFIG_DM_RESET=y
 CONFIG_RESET_BCM6345=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
-- 
2.11.0

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

* [U-Boot] [PATCH v9 13/28] bmips: bcm6348: add support for bcm6348-enet
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                       ` (11 preceding siblings ...)
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 12/28] bmips: enable f@st1704 enet support Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 14/28] bmips: enable ct-5361 enet support Álvaro Fernández Rojas
                       ` (15 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6348.dtsi | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6348.dtsi b/arch/mips/dts/brcm,bcm6348.dtsi
index 875de232ca..79e7bd892b 100644
--- a/arch/mips/dts/brcm,bcm6348.dtsi
+++ b/arch/mips/dts/brcm,bcm6348.dtsi
@@ -161,6 +161,32 @@
 			u-boot,dm-pre-reloc;
 		};
 
+		enet0: ethernet at fffe6000 {
+			compatible = "brcm,bcm6348-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xfffe6000 0x2dc>;
+			dmas = <&iudma BCM6348_DMA_ENET0_RX>,
+			       <&iudma BCM6348_DMA_ENET0_TX>;
+			dma-names = "rx",
+				    "tx";
+
+			status = "disabled";
+		};
+
+		enet1: ethernet at fffe6800 {
+			compatible = "brcm,bcm6348-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xfffe6800 0x2dc>;
+			dmas = <&iudma BCM6348_DMA_ENET1_RX>,
+			       <&iudma BCM6348_DMA_ENET1_TX>;
+			dma-names = "rx",
+				    "tx";
+
+			status = "disabled";
+		};
+
 		iudma: dma-controller at fffe7000 {
 			compatible = "brcm,bcm6348-iudma";
 			reg = <0xfffe7000 0x1c>,
-- 
2.11.0

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

* [U-Boot] [PATCH v9 14/28] bmips: enable ct-5361 enet support
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                       ` (12 preceding siblings ...)
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 13/28] bmips: bcm6348: add support for bcm6348-enet Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 15/28] bmips: bcm6358: add support for bcm6348-enet Álvaro Fernández Rojas
                       ` (14 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/comtrend,ct-5361.dts    | 12 ++++++++++++
 configs/comtrend_ct5361_ram_defconfig |  8 +++++++-
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/comtrend,ct-5361.dts b/arch/mips/dts/comtrend,ct-5361.dts
index 25747ca95d..f6b8a94e25 100644
--- a/arch/mips/dts/comtrend,ct-5361.dts
+++ b/arch/mips/dts/comtrend,ct-5361.dts
@@ -34,6 +34,18 @@
 	};
 };
 
+&enet1 {
+	status = "okay";
+	phy = <&enet1phy>;
+	phy-mode = "mii";
+
+	enet1phy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
diff --git a/configs/comtrend_ct5361_ram_defconfig b/configs/comtrend_ct5361_ram_defconfig
index 82f2070713..6297e78fd9 100644
--- a/configs/comtrend_ct5361_ram_defconfig
+++ b/configs/comtrend_ct5361_ram_defconfig
@@ -25,11 +25,14 @@ CONFIG_CMD_LICENSE=y
 CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="comtrend,ct-5361"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
@@ -40,6 +43,9 @@ CONFIG_FLASH_CFI_DRIVER=y
 CONFIG_CFI_FLASH=y
 CONFIG_SYS_FLASH_PROTECTION=y
 CONFIG_SYS_FLASH_CFI=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6348_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6348_USBH_PHY=y
 CONFIG_DM_RESET=y
-- 
2.11.0

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

* [U-Boot] [PATCH v9 15/28] bmips: bcm6358: add support for bcm6348-enet
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                       ` (13 preceding siblings ...)
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 14/28] bmips: enable ct-5361 enet support Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 16/28] bmips: enable hg556a enet support Álvaro Fernández Rojas
                       ` (13 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6358.dtsi | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6358.dtsi b/arch/mips/dts/brcm,bcm6358.dtsi
index 5605723e83..5e9c9ad769 100644
--- a/arch/mips/dts/brcm,bcm6358.dtsi
+++ b/arch/mips/dts/brcm,bcm6358.dtsi
@@ -192,6 +192,34 @@
 			status = "disabled";
 		};
 
+		enet0: ethernet at fffe4000 {
+			compatible = "brcm,bcm6348-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xfffe4000 0x2dc>;
+			clocks = <&periph_clk BCM6358_CLK_ENET0>;
+			dmas = <&iudma BCM6358_DMA_ENET0_RX>,
+			       <&iudma BCM6358_DMA_ENET0_TX>;
+			dma-names = "rx",
+				    "tx";
+
+			status = "disabled";
+		};
+
+		enet1: ethernet at fffe4800 {
+			compatible = "brcm,bcm6348-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xfffe4800 0x2dc>;
+			clocks = <&periph_clk BCM6358_CLK_ENET1>;
+			dmas = <&iudma BCM6358_DMA_ENET1_RX>,
+			       <&iudma BCM6358_DMA_ENET1_TX>;
+			dma-names = "rx",
+				    "tx";
+
+			status = "disabled";
+		};
+
 		iudma: dma-controller at fffe5000 {
 			compatible = "brcm,bcm6348-iudma";
 			reg = <0xfffe5000 0x24>,
-- 
2.11.0

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

* [U-Boot] [PATCH v9 16/28] bmips: enable hg556a enet support
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                       ` (14 preceding siblings ...)
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 15/28] bmips: bcm6358: add support for bcm6348-enet Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 17/28] bmips: enable nb4-ser " Álvaro Fernández Rojas
                       ` (12 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/huawei,hg556a.dts     | 12 ++++++++++++
 configs/huawei_hg556a_ram_defconfig |  8 +++++++-
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/huawei,hg556a.dts b/arch/mips/dts/huawei,hg556a.dts
index 60455c2ff8..6a7fc1df4b 100644
--- a/arch/mips/dts/huawei,hg556a.dts
+++ b/arch/mips/dts/huawei,hg556a.dts
@@ -93,6 +93,18 @@
 	status = "okay";
 };
 
+&enet1 {
+	status = "okay";
+	phy = <&enet1phy>;
+	phy-mode = "mii";
+
+	enet1phy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
diff --git a/configs/huawei_hg556a_ram_defconfig b/configs/huawei_hg556a_ram_defconfig
index 6bb14ba736..d4e6144319 100644
--- a/configs/huawei_hg556a_ram_defconfig
+++ b/configs/huawei_hg556a_ram_defconfig
@@ -25,11 +25,14 @@ CONFIG_CMD_LICENSE=y
 CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="huawei,hg556a"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
@@ -40,6 +43,9 @@ CONFIG_FLASH_CFI_DRIVER=y
 CONFIG_CFI_FLASH=y
 CONFIG_SYS_FLASH_PROTECTION=y
 CONFIG_SYS_FLASH_CFI=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6348_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6358_USBH_PHY=y
 CONFIG_DM_RESET=y
-- 
2.11.0

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

* [U-Boot] [PATCH v9 17/28] bmips: enable nb4-ser enet support
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                       ` (15 preceding siblings ...)
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 16/28] bmips: enable hg556a enet support Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 18/28] net: add support for bcm6368-enet Álvaro Fernández Rojas
                       ` (11 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/sfr,nb4-ser.dts     | 24 ++++++++++++++++++++++++
 configs/sfr_nb4-ser_ram_defconfig |  8 +++++++-
 2 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/sfr,nb4-ser.dts b/arch/mips/dts/sfr,nb4-ser.dts
index bdc6f8ae45..dfbc4148dc 100644
--- a/arch/mips/dts/sfr,nb4-ser.dts
+++ b/arch/mips/dts/sfr,nb4-ser.dts
@@ -53,6 +53,30 @@
 	status = "okay";
 };
 
+&enet0 {
+	status = "okay";
+	phy = <&enet0phy>;
+	phy-mode = "internal";
+
+	enet0phy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
+&enet1 {
+	status = "okay";
+	phy = <&enet1phy>;
+	phy-mode = "mii";
+
+	enet1phy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
diff --git a/configs/sfr_nb4-ser_ram_defconfig b/configs/sfr_nb4-ser_ram_defconfig
index 12adfb01e7..39622875b1 100644
--- a/configs/sfr_nb4-ser_ram_defconfig
+++ b/configs/sfr_nb4-ser_ram_defconfig
@@ -26,11 +26,14 @@ CONFIG_CMD_LICENSE=y
 CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="sfr,nb4-ser"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
@@ -42,6 +45,9 @@ CONFIG_FLASH_CFI_DRIVER=y
 CONFIG_CFI_FLASH=y
 CONFIG_SYS_FLASH_PROTECTION=y
 CONFIG_SYS_FLASH_CFI=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6348_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6358_USBH_PHY=y
 CONFIG_DM_RESET=y
-- 
2.11.0

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

* [U-Boot] [PATCH v9 18/28] net: add support for bcm6368-enet
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                       ` (16 preceding siblings ...)
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 17/28] bmips: enable nb4-ser " Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-29  0:44       ` Daniel Schwierzeck
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 19/28] bmips: bcm6368: " Álvaro Fernández Rojas
                       ` (10 subsequent siblings)
  28 siblings, 1 reply; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: introduce flow control improvements from bcm6348-eth:
  - introduce rx packets caching functionality from bcm6348-eth to fix flow
   control issues.
  - code style fixes.
 v8: introduce bcm6368-enet driver

 drivers/net/Kconfig       |   8 +
 drivers/net/Makefile      |   1 +
 drivers/net/bcm6368-eth.c | 670 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 679 insertions(+)
 create mode 100644 drivers/net/bcm6368-eth.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 2b7cec8804..7044c6adf3 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -82,6 +82,14 @@ config BCM6348_ETH
 	help
 	  This driver supports the BCM6348 Ethernet MAC.
 
+config BCM6368_ETH
+	bool "BCM6368 EMAC support"
+	depends on DM_ETH && ARCH_BMIPS
+	select DMA
+	select MII
+	help
+	  This driver supports the BCM6368 Ethernet MAC.
+
 config DWC_ETH_QOS
 	bool "Synopsys DWC Ethernet QOS device support"
 	depends on DM_ETH
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 2647d4dd23..0dbfa03306 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_ALTERA_TSE) += altera_tse.o
 obj-$(CONFIG_AG7XXX) += ag7xxx.o
 obj-$(CONFIG_ARMADA100_FEC) += armada100_fec.o
 obj-$(CONFIG_BCM6348_ETH) += bcm6348-eth.o
+obj-$(CONFIG_BCM6368_ETH) += bcm6368-eth.o
 obj-$(CONFIG_DRIVER_AT91EMAC) += at91_emac.o
 obj-$(CONFIG_DRIVER_AX88180) += ax88180.o
 obj-$(CONFIG_BCM_SF2_ETH) += bcm-sf2-eth.o
diff --git a/drivers/net/bcm6368-eth.c b/drivers/net/bcm6368-eth.c
new file mode 100644
index 0000000000..f0c2ada3e2
--- /dev/null
+++ b/drivers/net/bcm6368-eth.c
@@ -0,0 +1,670 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c:
+ *	Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dma.h>
+#include <miiphy.h>
+#include <net.h>
+#include <reset.h>
+#include <wait_bit.h>
+#include <asm/io.h>
+
+#define ETH_PORT_STR			"brcm,enetsw-port"
+
+#define ETH_RX_DESC			PKTBUFSRX
+#define ETH_ZLEN			60
+#define ETH_TIMEOUT			100
+
+#define ETH_MAX_PORT			8
+#define ETH_RGMII_PORT0			4
+
+/* Port traffic control */
+#define ETH_PTCTRL_REG(x)		(0x0 + (x))
+#define ETH_PTCTRL_RXDIS_SHIFT		0
+#define ETH_PTCTRL_RXDIS_MASK		(1 << ETH_PTCTRL_RXDIS_SHIFT)
+#define ETH_PTCTRL_TXDIS_SHIFT		1
+#define ETH_PTCTRL_TXDIS_MASK		(1 << ETH_PTCTRL_TXDIS_SHIFT)
+
+/* Switch mode register */
+#define ETH_SWMODE_REG			0xb
+#define ETH_SWMODE_FWD_EN_SHIFT		1
+#define ETH_SWMODE_FWD_EN_MASK		(1 << ETH_SWMODE_FWD_EN_SHIFT)
+
+/* IMP override Register */
+#define ETH_IMPOV_REG			0xe
+#define ETH_IMPOV_LINKUP_SHIFT		0
+#define ETH_IMPOV_LINKUP_MASK		(1 << ETH_IMPOV_LINKUP_SHIFT)
+#define ETH_IMPOV_FDX_SHIFT		1
+#define ETH_IMPOV_FDX_MASK		(1 << ETH_IMPOV_FDX_SHIFT)
+#define ETH_IMPOV_100_SHIFT		2
+#define ETH_IMPOV_100_MASK		(1 << ETH_IMPOV_100_SHIFT)
+#define ETH_IMPOV_1000_SHIFT		3
+#define ETH_IMPOV_1000_MASK		(1 << ETH_IMPOV_1000_SHIFT)
+#define ETH_IMPOV_RXFLOW_SHIFT		4
+#define ETH_IMPOV_RXFLOW_MASK		(1 << ETH_IMPOV_RXFLOW_SHIFT)
+#define ETH_IMPOV_TXFLOW_SHIFT		5
+#define ETH_IMPOV_TXFLOW_MASK		(1 << ETH_IMPOV_TXFLOW_SHIFT)
+#define ETH_IMPOV_FORCE_SHIFT		7
+#define ETH_IMPOV_FORCE_MASK		(1 << ETH_IMPOV_FORCE_SHIFT)
+
+/* Port override Register */
+#define ETH_PORTOV_REG(x)		(0x58 + (x))
+#define ETH_PORTOV_LINKUP_SHIFT		0
+#define ETH_PORTOV_LINKUP_MASK		(1 << ETH_PORTOV_LINKUP_SHIFT)
+#define ETH_PORTOV_FDX_SHIFT		1
+#define ETH_PORTOV_FDX_MASK		(1 << ETH_PORTOV_FDX_SHIFT)
+#define ETH_PORTOV_100_SHIFT		2
+#define ETH_PORTOV_100_MASK		(1 << ETH_PORTOV_100_SHIFT)
+#define ETH_PORTOV_1000_SHIFT		3
+#define ETH_PORTOV_1000_MASK		(1 << ETH_PORTOV_1000_SHIFT)
+#define ETH_PORTOV_RXFLOW_SHIFT		4
+#define ETH_PORTOV_RXFLOW_MASK		(1 << ETH_PORTOV_RXFLOW_SHIFT)
+#define ETH_PORTOV_TXFLOW_SHIFT		5
+#define ETH_PORTOV_TXFLOW_MASK		(1 << ETH_PORTOV_TXFLOW_SHIFT)
+#define ETH_PORTOV_ENABLE_SHIFT		6
+#define ETH_PORTOV_ENABLE_MASK		(1 << ETH_PORTOV_ENABLE_SHIFT)
+
+/* Port RGMII control register */
+#define ETH_RGMII_CTRL_REG(x)		(0x60 + (x))
+#define ETH_RGMII_CTRL_GMII_CLK_EN	(1 << 7)
+#define ETH_RGMII_CTRL_MII_OVERRIDE_EN	(1 << 6)
+#define ETH_RGMII_CTRL_MII_MODE_MASK	(3 << 4)
+#define ETH_RGMII_CTRL_RGMII_MODE	(0 << 4)
+#define ETH_RGMII_CTRL_MII_MODE		(1 << 4)
+#define ETH_RGMII_CTRL_RVMII_MODE	(2 << 4)
+#define ETH_RGMII_CTRL_TIMING_SEL_EN	(1 << 0)
+
+/* Port RGMII timing register */
+#define ENETSW_RGMII_TIMING_REG(x)	(0x68 + (x))
+
+/* MDIO control register */
+#define MII_SC_REG			0xb0
+#define MII_SC_EXT_SHIFT		16
+#define MII_SC_EXT_MASK			(1 << MII_SC_EXT_SHIFT)
+#define MII_SC_REG_SHIFT		20
+#define MII_SC_PHYID_SHIFT		25
+#define MII_SC_RD_SHIFT			30
+#define MII_SC_RD_MASK			(1 << MII_SC_RD_SHIFT)
+#define MII_SC_WR_SHIFT			31
+#define MII_SC_WR_MASK			(1 << MII_SC_WR_SHIFT)
+
+/* MDIO data register */
+#define MII_DAT_REG			0xb4
+
+/* MDIO 1000BASE-T control/status */
+#define MII_ADVERTISE_1000		(ADVERTISE_1000HALF |\
+					 ADVERTISE_1000FULL)
+#define MII_LPA_1000			(LPA_1000HALF | LPA_1000FULL)
+
+/* Global Management Configuration Register */
+#define ETH_GMCR_REG			0x200
+#define ETH_GMCR_RST_MIB_SHIFT		0
+#define ETH_GMCR_RST_MIB_MASK		(1 << ETH_GMCR_RST_MIB_SHIFT)
+
+/* Jumbo control register port mask register */
+#define ETH_JMBCTL_PORT_REG		0x4004
+
+/* Jumbo control mib good frame register */
+#define ETH_JMBCTL_MAXSIZE_REG		0x4008
+
+/* ETH port data */
+struct bcm_enetsw_port {
+	bool used;
+	const char *name;
+	/* Config */
+	bool bypass_link;
+	int force_speed;
+	bool force_duplex_full;
+	/* PHY */
+	int phy_id;
+};
+
+/* ETH data */
+struct bcm6368_eth_priv {
+	struct udevice *dev;
+	void __iomem *base;
+	/* RX */
+	uint8_t rx_desc;
+	uint8_t rx_pend;
+	int rx_ret[ETH_RX_DESC];
+	/* DMA */
+	struct dma rx_dma;
+	struct dma tx_dma;
+	/* Ports */
+	uint8_t num_ports;
+	struct bcm_enetsw_port used_ports[ETH_MAX_PORT];
+	int sw_port_link[ETH_MAX_PORT];
+	bool rgmii_override;
+	bool rgmii_timing;
+	/* PHY */
+	int phy_id;
+};
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static inline bool bcm_enet_port_is_rgmii(int portid)
+{
+	return portid >= ETH_RGMII_PORT0;
+}
+
+static int bcm6368_mdio_read(struct bcm6368_eth_priv *priv, uint8_t ext,
+			     int phy_id, int reg)
+{
+	uint32_t val;
+
+	writel_be(0, priv->base + MII_SC_REG);
+
+	val = MII_SC_RD_MASK |
+	      (phy_id << MII_SC_PHYID_SHIFT) |
+	      (reg << MII_SC_REG_SHIFT);
+
+	if (ext)
+		val |= MII_SC_EXT_MASK;
+
+	writel_be(val, priv->base + MII_SC_REG);
+	udelay(50);
+
+	return readw_be(priv->base + MII_DAT_REG);
+}
+
+static int bcm6368_mdio_write(struct bcm6368_eth_priv *priv, uint8_t ext,
+			      int phy_id, int reg, u16 data)
+{
+	uint32_t val;
+
+	writel_be(0, priv->base + MII_SC_REG);
+
+	val = MII_SC_WR_MASK |
+	      (phy_id << MII_SC_PHYID_SHIFT) |
+	      (reg << MII_SC_REG_SHIFT);
+
+	if (ext)
+		val |= MII_SC_EXT_MASK;
+
+	val |= data;
+
+	writel_be(val, priv->base + MII_SC_REG);
+	udelay(50);
+
+	return 0;
+}
+
+static int bcm6368_eth_free_pkt(struct udevice *dev, uchar *packet, int len)
+{
+	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+
+	/* sanity check */
+	if (packet != net_rx_packets[priv->rx_pend]) {
+		pr_err("rx_pend %d: packet is not matched,\n", priv->rx_pend);
+		return -EAGAIN;
+	}
+
+	/* free pending packet */
+	priv->rx_ret[priv->rx_pend] = 0;
+	priv->rx_pend = (priv->rx_pend + 1) % ETH_RX_DESC;
+
+	return 0;
+}
+
+static int _bcm6368_eth_recv(struct bcm6368_eth_priv *priv)
+{
+	uint8_t pkt = priv->rx_desc;
+
+	/* check if packet is free */
+	if (priv->rx_ret[pkt] > 0)
+		return -EAGAIN;
+
+	/* try to receive a new packet */
+	priv->rx_ret[pkt] = dma_receive(&priv->rx_dma,
+					(void **)&net_rx_packets[pkt],
+					NULL);
+	if (priv->rx_ret[pkt] > 0)
+		priv->rx_desc = (priv->rx_desc + 1) % ETH_RX_DESC;
+
+	return priv->rx_ret[pkt];
+}
+
+static int bcm6368_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+
+	/* receive packets if queue is empty */
+	if (priv->rx_ret[priv->rx_pend] <= 0) {
+		uint8_t pkt_cnt = 0;
+
+		/* try to receive packets */
+		while (_bcm6368_eth_recv(priv) > 0)
+			pkt_cnt++;
+
+		dma_prepare_rcv_buf(&priv->rx_dma, NULL, 0);
+
+		if (pkt_cnt)
+			debug("%s: received %u packet(s)\n", __func__, pkt_cnt);
+	}
+
+	/* return current packet */
+	if (priv->rx_ret[priv->rx_pend] > 0)
+		*packetp = net_rx_packets[priv->rx_pend];
+
+	return priv->rx_ret[priv->rx_pend];
+}
+
+static int bcm6368_eth_send(struct udevice *dev, void *packet, int length)
+{
+	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+
+	length = max(length, ETH_ZLEN);
+
+	return dma_send(&priv->tx_dma, packet, length, NULL);
+}
+
+static int bcm6368_eth_adjust_link(struct bcm6368_eth_priv *priv)
+{
+	unsigned int i;
+
+	for (i = 0; i < priv->num_ports; i++) {
+		struct bcm_enetsw_port *port;
+		int val, j, up, advertise, lpa, speed, duplex, media;
+		int external_phy = bcm_enet_port_is_rgmii(i);
+		u8 override;
+
+		port = &priv->used_ports[i];
+		if (!port->used)
+			continue;
+
+		if (port->bypass_link)
+			continue;
+
+		/* dummy read to clear */
+		for (j = 0; j < 2; j++)
+			val = bcm6368_mdio_read(priv, external_phy,
+						port->phy_id, MII_BMSR);
+
+		if (val == 0xffff)
+			continue;
+
+		up = (val & BMSR_LSTATUS) ? 1 : 0;
+		if (!(up ^ priv->sw_port_link[i]))
+			continue;
+
+		priv->sw_port_link[i] = up;
+
+		/* link changed */
+		if (!up) {
+			dev_info(&priv->pdev->dev, "link DOWN on %s\n",
+				 port->name);
+			writeb_be(ETH_PORTOV_ENABLE_MASK,
+				  priv->base + ETH_PORTOV_REG(i));
+			writeb_be(ETH_PTCTRL_RXDIS_MASK |
+				  ETH_PTCTRL_TXDIS_MASK,
+				  priv->base + ETH_PTCTRL_REG(i));
+			continue;
+		}
+
+		advertise = bcm6368_mdio_read(priv, external_phy, port->phy_id,
+					      MII_ADVERTISE);
+
+		lpa = bcm6368_mdio_read(priv, external_phy, port->phy_id,
+					MII_LPA);
+
+		/* figure out media and duplex from advertise and LPA values */
+		media = mii_nway_result(lpa & advertise);
+		duplex = (media & ADVERTISE_FULL) ? 1 : 0;
+
+		if (media & (ADVERTISE_100FULL | ADVERTISE_100HALF))
+			speed = 100;
+		else
+			speed = 10;
+
+		if (val & BMSR_ESTATEN) {
+			advertise = bcm6368_mdio_read(priv, external_phy,
+						port->phy_id, MII_CTRL1000);
+
+			lpa = bcm6368_mdio_read(priv, external_phy,
+						port->phy_id, MII_STAT1000);
+
+			if ((advertise & MII_ADVERTISE_1000) &&
+			    (lpa & MII_LPA_1000)) {
+				speed = 1000;
+				duplex = (lpa & LPA_1000FULL);
+			}
+		}
+
+		pr_alert("link UP on %s, %dMbps, %s-duplex\n",
+			 port->name, speed, duplex ? "full" : "half");
+
+		override = ETH_PORTOV_ENABLE_MASK |
+			   ETH_PORTOV_LINKUP_MASK;
+
+		if (speed == 1000)
+			override |= ETH_PORTOV_1000_MASK;
+		else if (speed == 100)
+			override |= ETH_PORTOV_100_MASK;
+		if (duplex)
+			override |= ETH_PORTOV_FDX_MASK;
+
+		writeb_be(override, priv->base + ETH_PORTOV_REG(i));
+		writeb_be(0, priv->base + ETH_PTCTRL_REG(i));
+	}
+
+	return 0;
+}
+
+static int bcm6368_eth_start(struct udevice *dev)
+{
+	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+	int i;
+	u32 val;
+
+	priv->rx_desc = 0;
+	priv->rx_pend = 0;
+	for (i = 0; i < ETH_RX_DESC; i++)
+		priv->rx_ret[i] = 0;
+
+	/* disable all ports */
+	for (i = 0; i < priv->num_ports; i++) {
+		writeb_be(ETH_PORTOV_ENABLE_MASK,
+			  priv->base + ETH_PORTOV_REG(i));
+		writeb_be(ETH_PTCTRL_RXDIS_MASK |
+			  ETH_PTCTRL_TXDIS_MASK,
+			  priv->base + ETH_PTCTRL_REG(i));
+
+		priv->sw_port_link[i] = 0;
+	}
+
+	/* enable external ports */
+	for (i = ETH_RGMII_PORT0; i < priv->num_ports; i++) {
+		u8 rgmii_ctrl;
+
+		if (!priv->used_ports[i].used)
+			continue;
+
+		rgmii_ctrl = readb_be(priv->base + ETH_RGMII_CTRL_REG(i));
+		rgmii_ctrl |= ETH_RGMII_CTRL_GMII_CLK_EN;
+		if (priv->rgmii_override)
+			rgmii_ctrl |= ETH_RGMII_CTRL_MII_OVERRIDE_EN;
+		if (priv->rgmii_timing)
+			rgmii_ctrl |= ETH_RGMII_CTRL_TIMING_SEL_EN;
+		writeb_be(rgmii_ctrl, priv->base + ETH_RGMII_CTRL_REG(i));
+	}
+
+	/* reset mib */
+	val = readb_be(priv->base + ETH_GMCR_REG);
+	val |= ETH_GMCR_RST_MIB_MASK;
+	writeb_be(val, priv->base + ETH_GMCR_REG);
+	mdelay(1);
+	val &= ~ETH_GMCR_RST_MIB_MASK;
+	writeb_be(val, priv->base + ETH_GMCR_REG);
+	mdelay(1);
+
+	/* force CPU port state */
+	val = readb_be(priv->base + ETH_IMPOV_REG);
+	val |= ETH_IMPOV_FORCE_MASK | ETH_IMPOV_LINKUP_MASK;
+	writeb_be(val, priv->base + ETH_IMPOV_REG);
+
+	/* enable switch forward engine */
+	val = readb_be(priv->base + ETH_SWMODE_REG);
+	val |= ETH_SWMODE_FWD_EN_MASK;
+	writeb_be(val, priv->base + ETH_SWMODE_REG);
+
+	/* enable jumbo on all ports */
+	writel_be(0x1ff, priv->base + ETH_JMBCTL_PORT_REG);
+	writew_be(9728, priv->base + ETH_JMBCTL_MAXSIZE_REG);
+
+	/* enable dma rx channel */
+	dma_enable(&priv->rx_dma);
+
+	/* enable dma tx channel */
+	dma_enable(&priv->tx_dma);
+
+	/* apply override config for bypass_link ports here. */
+	for (i = 0; i < priv->num_ports; i++) {
+		struct bcm_enetsw_port *port;
+		u8 override;
+		port = &priv->used_ports[i];
+		if (!port->used)
+			continue;
+
+		if (!port->bypass_link)
+			continue;
+
+		override = ETH_PORTOV_ENABLE_MASK |
+			ETH_PORTOV_LINKUP_MASK;
+
+		switch (port->force_speed) {
+		case 1000:
+			override |= ETH_PORTOV_1000_MASK;
+			break;
+		case 100:
+			override |= ETH_PORTOV_100_MASK;
+			break;
+		case 10:
+			break;
+		default:
+			pr_warn("invalid forced speed on port %s: assume 10\n",
+				port->name);
+			break;
+		}
+
+		if (port->force_duplex_full)
+			override |= ETH_PORTOV_FDX_MASK;
+
+		writeb_be(override, priv->base + ETH_PORTOV_REG(i));
+		writeb_be(0, priv->base + ETH_PTCTRL_REG(i));
+	}
+
+	bcm6368_eth_adjust_link(priv);
+
+	return 0;
+}
+
+static void bcm6368_eth_stop(struct udevice *dev)
+{
+	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+
+	/* disable dma rx channel */
+	dma_disable(&priv->rx_dma);
+
+	/* disable dma tx channel */
+	dma_disable(&priv->tx_dma);
+}
+
+static const struct eth_ops bcm6368_eth_ops = {
+	.free_pkt = bcm6368_eth_free_pkt,
+	.recv = bcm6368_eth_recv,
+	.send = bcm6368_eth_send,
+	.start = bcm6368_eth_start,
+	.stop = bcm6368_eth_stop,
+};
+
+static const struct udevice_id bcm6368_eth_ids[] = {
+	{ .compatible = "brcm,bcm6368-enet", },
+	{ /* sentinel */ }
+};
+
+static bool bcm6368_phy_is_external(struct bcm6368_eth_priv *priv,
+				       int phy_id)
+{
+	uint8_t i;
+
+	for (i = 0; i < priv->num_ports; ++i) {
+		if (!priv->used_ports[i].used)
+			continue;
+		if (priv->used_ports[i].phy_id == phy_id)
+			return bcm_enet_port_is_rgmii(i);
+	}
+
+	return true;
+}
+
+static int bcm6368_mii_mdio_read(struct mii_dev *bus, int addr, int devaddr,
+				 int reg)
+{
+	struct bcm6368_eth_priv *priv = bus->priv;
+	bool ext = bcm6368_phy_is_external(priv, addr);
+
+	return bcm6368_mdio_read(priv, ext, addr, reg);
+}
+
+static int bcm6368_mii_mdio_write(struct mii_dev *bus, int addr, int devaddr,
+				  int reg, u16 data)
+{
+	struct bcm6368_eth_priv *priv = bus->priv;
+	bool ext = bcm6368_phy_is_external(priv, addr);
+
+	return bcm6368_mdio_write(priv, ext, addr, reg, data);
+}
+
+static int bcm6368_mdio_init(const char *name, struct bcm6368_eth_priv *priv)
+{
+	struct mii_dev *bus;
+
+	bus = mdio_alloc();
+	if (!bus) {
+		pr_err("%s: failed to allocate MDIO bus\n", __func__);
+		return -ENOMEM;
+	}
+
+	bus->read = bcm6368_mii_mdio_read;
+	bus->write = bcm6368_mii_mdio_write;
+	bus->priv = priv;
+	snprintf(bus->name, sizeof(bus->name), "%s", name);
+
+	return mdio_register(bus);
+}
+
+static int bcm6368_eth_probe(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+	void *blob = (void *)gd->fdt_blob;
+	fdt_addr_t addr;
+	int node = dev_of_offset(dev);
+	int ret, i;
+	unsigned int num_ports;
+
+	/* get base address */
+	addr = devfdt_get_addr(dev);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	/* get number of ports */
+	num_ports = fdtdec_get_uint(gd->fdt_blob, node, "brcm,num-ports",
+				    ETH_MAX_PORT);
+	if (!num_ports || num_ports > ETH_MAX_PORT)
+		return -EINVAL;
+
+	/* get dma channels */
+	ret = dma_get_by_name(dev, "tx", &priv->tx_dma);
+	if (ret)
+		return -EINVAL;
+
+	ret = dma_get_by_name(dev, "rx", &priv->rx_dma);
+	if (ret)
+		return -EINVAL;
+
+	/* try to enable clocks */
+	for (i = 0; ; i++) {
+		struct clk clk;
+		int ret;
+
+		ret = clk_get_by_index(dev, i, &clk);
+		if (ret < 0)
+			break;
+		if (clk_enable(&clk))
+			pr_err("failed to enable clock %d\n", i);
+		clk_free(&clk);
+	}
+
+	/* try to perform resets */
+	for (i = 0; ; i++) {
+		struct reset_ctl reset;
+		int ret;
+
+		ret = reset_get_by_index(dev, i, &reset);
+		if (ret < 0)
+			break;
+		if (reset_deassert(&reset))
+			pr_err("failed to deassert reset %d\n", i);
+		reset_free(&reset);
+	}
+
+	/* set priv data */
+	priv->dev = dev;
+
+	priv->base = ioremap(addr, 0);
+	pdata->iobase = (phys_addr_t) priv->base;
+
+	priv->num_ports = num_ports;
+
+	if (fdtdec_get_bool(gd->fdt_blob, i, "brcm,rgmii-override"))
+		priv->rgmii_override = true;
+	if (fdtdec_get_bool(gd->fdt_blob, i, "brcm,rgmii-timing"))
+		priv->rgmii_timing = true;
+
+	/* get ports */
+	for (i = fdt_first_subnode(blob, node);
+	     i > 0;
+	     i = fdt_next_subnode(blob, i)) {
+		const char *comp;
+		const char *label;
+		unsigned int p;
+		int phy_id;
+		int speed;
+
+		comp = fdt_getprop(blob, i, "compatible", NULL);
+		if (!comp || memcmp(comp, ETH_PORT_STR, sizeof(ETH_PORT_STR)))
+			continue;
+
+		p = fdtdec_get_uint(gd->fdt_blob, i, "reg",
+				      ETH_MAX_PORT);
+		if (p >= num_ports)
+			return -EINVAL;
+
+		label = fdt_getprop(blob, i, "label", NULL);
+		if (!label) {
+			debug("%s: node %s has no label\n", __func__,
+			      fdt_get_name(blob, i, NULL));
+			return -EINVAL;
+		}
+
+		phy_id = fdtdec_get_int(gd->fdt_blob, i, "brcm,phy-id", -1);
+
+		priv->used_ports[p].used = true;
+		priv->used_ports[p].name = label;
+		priv->used_ports[p].phy_id = phy_id;
+
+		if (fdtdec_get_bool(gd->fdt_blob, i, "full-duplex"))
+			priv->used_ports[p].force_duplex_full = true;
+		if (fdtdec_get_bool(gd->fdt_blob, i, "bypass-link"))
+			priv->used_ports[p].bypass_link = true;
+		speed = fdtdec_get_int(gd->fdt_blob, i, "speed", 0);
+		if (speed)
+			priv->used_ports[p].force_speed = speed;
+	}
+
+	/* init mii bus */
+	ret = bcm6368_mdio_init(dev->name, priv);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+U_BOOT_DRIVER(bcm6368_eth) = {
+	.name = "bcm6368_eth",
+	.id = UCLASS_ETH,
+	.of_match = bcm6368_eth_ids,
+	.ops = &bcm6368_eth_ops,
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+	.priv_auto_alloc_size = sizeof(struct bcm6368_eth_priv),
+	.probe = bcm6368_eth_probe,
+};
-- 
2.11.0

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

* [U-Boot] [PATCH v9 19/28] bmips: bcm6368: add support for bcm6368-enet
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                       ` (17 preceding siblings ...)
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 18/28] net: add support for bcm6368-enet Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 20/28] bmips: enable wap-5813n enet support Álvaro Fernández Rojas
                       ` (9 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6368.dtsi | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6368.dtsi b/arch/mips/dts/brcm,bcm6368.dtsi
index 30047f6360..89590d6ff9 100644
--- a/arch/mips/dts/brcm,bcm6368.dtsi
+++ b/arch/mips/dts/brcm,bcm6368.dtsi
@@ -205,5 +205,24 @@
 			#dma-cells = <1>;
 			dma-channels = <8>;
 		};
+
+		enet: ethernet at 10f00000 {
+			compatible = "brcm,bcm6368-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x10f00000 0x10000>;
+			clocks = <&periph_clk BCM6368_CLK_SWPKT_USB>,
+				 <&periph_clk BCM6368_CLK_SWPKT_SAR>,
+				 <&periph_clk BCM6368_CLK_ROBOSW>;
+			resets = <&periph_rst BCM6368_RST_SWITCH>,
+				 <&periph_rst BCM6368_RST_EPHY>;
+			dmas = <&iudma BCM6368_DMA_ENETSW_RX>,
+			       <&iudma BCM6368_DMA_ENETSW_TX>;
+			dma-names = "rx",
+				    "tx";
+			brcm,num-ports = <6>;
+
+			status = "disabled";
+		};
 	};
 };
-- 
2.11.0

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

* [U-Boot] [PATCH v9 20/28] bmips: enable wap-5813n enet support
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                       ` (18 preceding siblings ...)
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 19/28] bmips: bcm6368: " Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 21/28] bmips: bcm6328: add support for bcm6368-enet Álvaro Fernández Rojas
                       ` (8 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/comtrend,wap-5813n.dts    | 14 ++++++++++++++
 configs/comtrend_wap5813n_ram_defconfig |  8 +++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/comtrend,wap-5813n.dts b/arch/mips/dts/comtrend,wap-5813n.dts
index bd41dab9f8..7e835b28d2 100644
--- a/arch/mips/dts/comtrend,wap-5813n.dts
+++ b/arch/mips/dts/comtrend,wap-5813n.dts
@@ -54,6 +54,20 @@
 	status = "okay";
 };
 
+&enet {
+	status = "okay";
+
+	port at 4 {
+		compatible = "brcm,enetsw-port";
+		reg = <4>;
+		label = "rgmii";
+		brcm,phy-id = <0xff>;
+		speed = <1000>;
+		full-duplex;
+		bypass-link;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
diff --git a/configs/comtrend_wap5813n_ram_defconfig b/configs/comtrend_wap5813n_ram_defconfig
index 987e4c3fbc..fd5107bb7d 100644
--- a/configs/comtrend_wap5813n_ram_defconfig
+++ b/configs/comtrend_wap5813n_ram_defconfig
@@ -25,11 +25,14 @@ CONFIG_CMD_LICENSE=y
 CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="comtrend,wap-5813n"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
@@ -40,6 +43,9 @@ CONFIG_FLASH_CFI_DRIVER=y
 CONFIG_CFI_FLASH=y
 CONFIG_SYS_FLASH_PROTECTION=y
 CONFIG_SYS_FLASH_CFI=y
+CONFIG_DM_ETH=y
+CONFIG_PHY_GIGE=y
+CONFIG_BCM6368_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6368_USBH_PHY=y
 CONFIG_DM_RESET=y
-- 
2.11.0

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

* [U-Boot] [PATCH v9 21/28] bmips: bcm6328: add support for bcm6368-enet
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                       ` (19 preceding siblings ...)
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 20/28] bmips: enable wap-5813n enet support Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 22/28] bmips: enable ar-5387un enet support Álvaro Fernández Rojas
                       ` (7 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6328.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6328.dtsi b/arch/mips/dts/brcm,bcm6328.dtsi
index 6fa49e22bb..50beed4171 100644
--- a/arch/mips/dts/brcm,bcm6328.dtsi
+++ b/arch/mips/dts/brcm,bcm6328.dtsi
@@ -200,5 +200,22 @@
 			#dma-cells = <1>;
 			dma-channels = <8>;
 		};
+
+		enet: ethernet at 10e00000 {
+			compatible = "brcm,bcm6368-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x10e00000 0x10000>;
+			clocks = <&periph_clk BCM6328_CLK_ROBOSW>;
+			resets = <&periph_rst BCM6328_RST_ENETSW>,
+				 <&periph_rst BCM6328_RST_EPHY>;
+			dmas = <&iudma BCM6328_DMA_ENETSW_RX>,
+			       <&iudma BCM6328_DMA_ENETSW_TX>;
+			dma-names = "rx",
+				    "tx";
+			brcm,num-ports = <5>;
+
+			status = "disabled";
+		};
 	};
 };
-- 
2.11.0

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

* [U-Boot] [PATCH v9 22/28] bmips: enable ar-5387un enet support
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                       ` (20 preceding siblings ...)
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 21/28] bmips: bcm6328: add support for bcm6368-enet Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 23/28] bmips: bcm6362: add support for bcm6368-enet Álvaro Fernández Rojas
                       ` (6 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/comtrend,ar-5387un.dts    | 32 ++++++++++++++++++++++++++++++++
 configs/comtrend_ar5387un_ram_defconfig |  7 ++++++-
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/comtrend,ar-5387un.dts b/arch/mips/dts/comtrend,ar-5387un.dts
index e993b5cd89..03e3851ab1 100644
--- a/arch/mips/dts/comtrend,ar-5387un.dts
+++ b/arch/mips/dts/comtrend,ar-5387un.dts
@@ -24,6 +24,38 @@
 	status = "okay";
 };
 
+&enet {
+	status = "okay";
+
+	port at 0 {
+		compatible = "brcm,enetsw-port";
+		reg = <0>;
+		label = "fe1";
+		brcm,phy-id = <1>;
+	};
+
+	port at 1 {
+		compatible = "brcm,enetsw-port";
+		reg = <1>;
+		label = "fe2";
+		brcm,phy-id = <2>;
+	};
+
+	port at 2 {
+		compatible = "brcm,enetsw-port";
+		reg = <2>;
+		label = "fe3";
+		brcm,phy-id = <3>;
+	};
+
+	port at 3 {
+		compatible = "brcm,enetsw-port";
+		reg = <3>;
+		label = "fe4";
+		brcm,phy-id = <4>;
+	};
+};
+
 &leds {
 	status = "okay";
 
diff --git a/configs/comtrend_ar5387un_ram_defconfig b/configs/comtrend_ar5387un_ram_defconfig
index f129870ca0..5ba401a441 100644
--- a/configs/comtrend_ar5387un_ram_defconfig
+++ b/configs/comtrend_ar5387un_ram_defconfig
@@ -28,11 +28,14 @@ CONFIG_CMD_MEMINFO=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="comtrend,ar-5387un"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_LED=y
 CONFIG_LED_BCM6328=y
@@ -41,6 +44,8 @@ CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_MACRONIX=y
 CONFIG_SPI_FLASH_MTD=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6368_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6368_USBH_PHY=y
 CONFIG_POWER_DOMAIN=y
-- 
2.11.0

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

* [U-Boot] [PATCH v9 23/28] bmips: bcm6362: add support for bcm6368-enet
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                       ` (21 preceding siblings ...)
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 22/28] bmips: enable ar-5387un enet support Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 24/28] bmips: enable dgnd3700v2 enet support Álvaro Fernández Rojas
                       ` (5 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6362.dtsi | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6362.dtsi b/arch/mips/dts/brcm,bcm6362.dtsi
index 94e7de096d..c77b80a4cc 100644
--- a/arch/mips/dts/brcm,bcm6362.dtsi
+++ b/arch/mips/dts/brcm,bcm6362.dtsi
@@ -224,5 +224,24 @@
 			#dma-cells = <1>;
 			dma-channels = <8>;
 		};
+
+		enet: ethernet at 10e00000 {
+			compatible = "brcm,bcm6368-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x10e00000 0x10000>;
+			clocks = <&periph_clk BCM6362_CLK_SWPKT_USB>,
+				 <&periph_clk BCM6362_CLK_SWPKT_SAR>,
+				 <&periph_clk BCM6362_CLK_ROBOSW>;
+			resets = <&periph_rst BCM6362_RST_ENETSW>,
+				 <&periph_rst BCM6362_RST_EPHY>;
+			dmas = <&iudma BCM6362_DMA_ENETSW_RX>,
+			       <&iudma BCM6362_DMA_ENETSW_TX>;
+			dma-names = "rx",
+				    "tx";
+			brcm,num-ports = <6>;
+
+			status = "disabled";
+		};
 	};
 };
-- 
2.11.0

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

* [U-Boot] [PATCH v9 24/28] bmips: enable dgnd3700v2 enet support
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                       ` (22 preceding siblings ...)
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 23/28] bmips: bcm6362: add support for bcm6368-enet Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 25/28] bmips: bcm63268: add support for bcm6368-enet Álvaro Fernández Rojas
                       ` (4 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/netgear,dgnd3700v2.dts     | 14 ++++++++++++++
 configs/netgear_dgnd3700v2_ram_defconfig |  8 +++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/netgear,dgnd3700v2.dts b/arch/mips/dts/netgear,dgnd3700v2.dts
index 322d1567ff..2b72491f0b 100644
--- a/arch/mips/dts/netgear,dgnd3700v2.dts
+++ b/arch/mips/dts/netgear,dgnd3700v2.dts
@@ -43,6 +43,20 @@
 	status = "okay";
 };
 
+&enet {
+	status = "okay";
+
+	port at 4 {
+		compatible = "brcm,enetsw-port";
+		reg = <4>;
+		label = "rgmii";
+		brcm,phy-id = <0xff>;
+		speed = <1000>;
+		full-duplex;
+		bypass-link;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
diff --git a/configs/netgear_dgnd3700v2_ram_defconfig b/configs/netgear_dgnd3700v2_ram_defconfig
index 1abc869856..0f3914fe7e 100644
--- a/configs/netgear_dgnd3700v2_ram_defconfig
+++ b/configs/netgear_dgnd3700v2_ram_defconfig
@@ -27,17 +27,23 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
-# CONFIG_CMD_NET is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="netgear,dgnd3700v2"
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
 CONFIG_LED_BCM6328=y
 CONFIG_LED_BLINK=y
 CONFIG_LED_GPIO=y
+CONFIG_DM_ETH=y
+CONFIG_PHY_GIGE=y
+CONFIG_BCM6368_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6368_USBH_PHY=y
 CONFIG_POWER_DOMAIN=y
-- 
2.11.0

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

* [U-Boot] [PATCH v9 25/28] bmips: bcm63268: add support for bcm6368-enet
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                       ` (23 preceding siblings ...)
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 24/28] bmips: enable dgnd3700v2 enet support Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 26/28] bmips: enable vr-3032u enet support Álvaro Fernández Rojas
                       ` (3 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm63268.dtsi | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm63268.dtsi b/arch/mips/dts/brcm,bcm63268.dtsi
index c7ad83c306..f8a72ef535 100644
--- a/arch/mips/dts/brcm,bcm63268.dtsi
+++ b/arch/mips/dts/brcm,bcm63268.dtsi
@@ -230,5 +230,30 @@
 			#dma-cells = <1>;
 			dma-channels = <8>;
 		};
+
+		enet: ethernet at 10700000 {
+			compatible = "brcm,bcm6368-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x10700000 0x10000>;
+			clocks = <&periph_clk BCM63268_CLK_GMAC>,
+				 <&periph_clk BCM63268_CLK_ROBOSW>,
+				 <&periph_clk BCM63268_CLK_ROBOSW250>,
+				 <&timer_clk BCM63268_TCLK_EPHY1>,
+				 <&timer_clk BCM63268_TCLK_EPHY2>,
+				 <&timer_clk BCM63268_TCLK_EPHY3>,
+				 <&timer_clk BCM63268_TCLK_GPHY>;
+			resets = <&periph_rst BCM63268_RST_ENETSW>,
+				 <&periph_rst BCM63268_RST_EPHY>,
+				 <&periph_rst BCM63268_RST_GPHY>;
+			dmas = <&iudma BCM63268_DMA_ENETSW_RX>,
+			       <&iudma BCM63268_DMA_ENETSW_TX>;
+			dma-names = "rx",
+				    "tx";
+			brcm,rgmii-override;
+			brcm,rgmii-timing;
+
+			status = "disabled";
+		};
 	};
 };
-- 
2.11.0

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

* [U-Boot] [PATCH v9 26/28] bmips: enable vr-3032u enet support
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                       ` (24 preceding siblings ...)
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 25/28] bmips: bcm63268: add support for bcm6368-enet Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 27/28] bmips: bcm6318: add support for bcm6368-enet Álvaro Fernández Rojas
                       ` (2 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/comtrend,vr-3032u.dts    | 32 ++++++++++++++++++++++++++++++++
 configs/comtrend_vr3032u_ram_defconfig |  7 ++++++-
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/comtrend,vr-3032u.dts b/arch/mips/dts/comtrend,vr-3032u.dts
index 8c6a4a1eac..512cb52de3 100644
--- a/arch/mips/dts/comtrend,vr-3032u.dts
+++ b/arch/mips/dts/comtrend,vr-3032u.dts
@@ -24,6 +24,38 @@
 	status = "okay";
 };
 
+&enet {
+	status = "okay";
+
+	port at 0 {
+		compatible = "brcm,enetsw-port";
+		reg = <0>;
+		label = "fe2";
+		brcm,phy-id = <1>;
+	};
+
+	port at 1 {
+		compatible = "brcm,enetsw-port";
+		reg = <1>;
+		label = "fe3";
+		brcm,phy-id = <2>;
+	};
+
+	port at 2 {
+		compatible = "brcm,enetsw-port";
+		reg = <2>;
+		label = "fe4";
+		brcm,phy-id = <3>;
+	};
+
+	port at 3 {
+		compatible = "brcm,enetsw-port";
+		reg = <3>;
+		label = "fe1";
+		brcm,phy-id = <4>;
+	};
+};
+
 &leds {
 	status = "okay";
 	brcm,serial-leds;
diff --git a/configs/comtrend_vr3032u_ram_defconfig b/configs/comtrend_vr3032u_ram_defconfig
index 1689eecec1..47f53998e1 100644
--- a/configs/comtrend_vr3032u_ram_defconfig
+++ b/configs/comtrend_vr3032u_ram_defconfig
@@ -26,15 +26,20 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="comtrend,vr-3032u"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_LED=y
 CONFIG_LED_BCM6328=y
 CONFIG_LED_BLINK=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6368_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6368_USBH_PHY=y
 CONFIG_POWER_DOMAIN=y
-- 
2.11.0

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

* [U-Boot] [PATCH v9 27/28] bmips: bcm6318: add support for bcm6368-enet
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                       ` (25 preceding siblings ...)
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 26/28] bmips: enable vr-3032u enet support Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 28/28] bmips: enable ar-5315u enet support Álvaro Fernández Rojas
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6318.dtsi           | 19 +++++++++++++++++++
 include/dt-bindings/clock/bcm6318-clock.h | 11 +++++++++++
 2 files changed, 30 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6318.dtsi b/arch/mips/dts/brcm,bcm6318.dtsi
index d04b7cbb01..d678dab242 100644
--- a/arch/mips/dts/brcm,bcm6318.dtsi
+++ b/arch/mips/dts/brcm,bcm6318.dtsi
@@ -190,6 +190,25 @@
 			status = "disabled";
 		};
 
+		enet: ethernet at 10080000 {
+			compatible = "brcm,bcm6368-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x10080000 0x8000>;
+			clocks = <&periph_clk BCM6318_CLK_ROBOSW250>,
+				 <&periph_clk BCM6318_CLK_ROBOSW025>,
+				 <&ubus_clk BCM6318_UCLK_ROBOSW>;
+			resets = <&periph_rst BCM6318_RST_ENETSW>,
+				 <&periph_rst BCM6318_RST_EPHY>;
+			dmas = <&iudma BCM6318_DMA_ENETSW_RX>,
+			       <&iudma BCM6318_DMA_ENETSW_TX>;
+			dma-names = "rx",
+				    "tx";
+			brcm,num-ports = <5>;
+
+			status = "disabled";
+		};
+
 		iudma: dma-controller at 10088000 {
 			compatible = "brcm,bcm6368-iudma";
 			reg = <0x10088000 0x80>,
diff --git a/include/dt-bindings/clock/bcm6318-clock.h b/include/dt-bindings/clock/bcm6318-clock.h
index d5e13c5c2d..3f10448cef 100644
--- a/include/dt-bindings/clock/bcm6318-clock.h
+++ b/include/dt-bindings/clock/bcm6318-clock.h
@@ -33,4 +33,15 @@
 #define BCM6318_CLK_AFE		29
 #define BCM6318_CLK_QPROC	30
 
+#define BCM6318_UCLK_ADSL	0
+#define BCM6318_UCLK_ARB	1
+#define BCM6318_UCLK_MIPS	2
+#define BCM6318_UCLK_PCIE	3
+#define BCM6318_UCLK_PERIPH	4
+#define BCM6318_UCLK_PHYMIPS	5
+#define BCM6318_UCLK_ROBOSW	6
+#define BCM6318_UCLK_SAR	7
+#define BCM6318_UCLK_SDR	8
+#define BCM6318_UCLK_USB	9
+
 #endif /* __DT_BINDINGS_CLOCK_BCM6318_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v9 28/28] bmips: enable ar-5315u enet support
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                       ` (26 preceding siblings ...)
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 27/28] bmips: bcm6318: add support for bcm6368-enet Álvaro Fernández Rojas
@ 2018-11-28 18:23     ` Álvaro Fernández Rojas
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-28 18:23 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/comtrend,ar-5315u.dts    | 32 ++++++++++++++++++++++++++++++++
 configs/comtrend_ar5315u_ram_defconfig |  7 ++++++-
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/comtrend,ar-5315u.dts b/arch/mips/dts/comtrend,ar-5315u.dts
index 45570189d0..eb60aaa8d5 100644
--- a/arch/mips/dts/comtrend,ar-5315u.dts
+++ b/arch/mips/dts/comtrend,ar-5315u.dts
@@ -24,6 +24,38 @@
 	status = "okay";
 };
 
+&enet {
+	status = "okay";
+
+	port at 0 {
+		compatible = "brcm,enetsw-port";
+		reg = <0>;
+		label = "fe4";
+		brcm,phy-id = <1>;
+	};
+
+	port at 1 {
+		compatible = "brcm,enetsw-port";
+		reg = <1>;
+		label = "fe3";
+		brcm,phy-id = <2>;
+	};
+
+	port at 2 {
+		compatible = "brcm,enetsw-port";
+		reg = <2>;
+		label = "fe2";
+		brcm,phy-id = <3>;
+	};
+
+	port at 3 {
+		compatible = "brcm,enetsw-port";
+		reg = <3>;
+		label = "fe1";
+		brcm,phy-id = <4>;
+	};
+};
+
 &leds {
 	status = "okay";
 
diff --git a/configs/comtrend_ar5315u_ram_defconfig b/configs/comtrend_ar5315u_ram_defconfig
index d9ef52e68d..1b8e4e43c4 100644
--- a/configs/comtrend_ar5315u_ram_defconfig
+++ b/configs/comtrend_ar5315u_ram_defconfig
@@ -28,11 +28,14 @@ CONFIG_CMD_MEMINFO=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="comtrend,ar-5315u"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_LED=y
 CONFIG_LED_BCM6328=y
@@ -41,6 +44,8 @@ CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_SPI_FLASH_MTD=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6368_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6318_USBH_PHY=y
 CONFIG_BCM6328_POWER_DOMAIN=y
-- 
2.11.0

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

* [U-Boot] [PATCH v9 01/28] dma: add bcm6348-iudma support
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 01/28] dma: add bcm6348-iudma support Álvaro Fernández Rojas
@ 2018-11-28 23:44       ` Daniel Schwierzeck
  0 siblings, 0 replies; 145+ messages in thread
From: Daniel Schwierzeck @ 2018-11-28 23:44 UTC (permalink / raw)
  To: u-boot



Am 28.11.18 um 19:23 schrieb Álvaro Fernández Rojas:
> BCM6348 IUDMA controller is present on multiple BMIPS (BCM63xx) SoCs.
> 
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> ---
>  v9: introduce dma_prepare_rcv_buf dma op:
>   - bcm6348_iudma_chan_stop: switch to mdelay when resetting channel.
>   - bcm6348_iudma_receive: track dirty dma descriptors and no longer trigger
>    dma rx channel.
>   - bcm6348_iudma_send: reorder to properly flush cache and set dma descriptor
>    config.
>   - bcm6348_iudma_prepare_rcv_buf: implemented to clear dirty dma descriptors.
>  v8: Introduce changes from Grygorii Strashko
>  v5: Several fixes and improvements:
>   - Remove unused defines.
>   - Increment rx descriptors.
>   - Fix flow control issues.
>   - Error checking now depends on hw.
>   - Remove unneeded interrupts.
>  v4: Fix issues reported by Grygorii Strashko and other fixes:
>   - Remove usage of net_rx_packets as buffer.
>   - Allocate dynamic rx buffer.
>   - Check dma errors and discard invalid packets.
>  v3: no changes
>  v2: Fix dma rx burst config and select DMA_CHANNELS.
> 
>  drivers/dma/Kconfig         |   9 +
>  drivers/dma/Makefile        |   1 +
>  drivers/dma/bcm6348-iudma.c | 576 ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 586 insertions(+)
>  create mode 100644 drivers/dma/bcm6348-iudma.c
> 
> diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
> index 8a4162eccd..1820676d7a 100644
> --- a/drivers/dma/Kconfig
> +++ b/drivers/dma/Kconfig
> @@ -26,6 +26,15 @@ config SANDBOX_DMA
>  	  Enable support for a test DMA uclass implementation. It stimulates
>  	  DMA transfer by simple copying data between channels.
>  
> +config BCM6348_IUDMA
> +	bool "BCM6348 IUDMA driver"
> +	depends on ARCH_BMIPS
> +	select DMA_CHANNELS
> +	help
> +	  Enable the BCM6348 IUDMA driver.
> +	  This driver support data transfer from devices to
> +	  memory and from memory to devices.
> +
>  config TI_EDMA3
>  	bool "TI EDMA3 driver"
>  	help
> diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
> index aff31f986a..b5f9147e0a 100644
> --- a/drivers/dma/Makefile
> +++ b/drivers/dma/Makefile
> @@ -7,6 +7,7 @@ obj-$(CONFIG_DMA) += dma-uclass.o
>  
>  obj-$(CONFIG_FSLDMAFEC) += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o
>  obj-$(CONFIG_APBH_DMA) += apbh_dma.o
> +obj-$(CONFIG_BCM6348_IUDMA) += bcm6348-iudma.o
>  obj-$(CONFIG_FSL_DMA) += fsl_dma.o
>  obj-$(CONFIG_SANDBOX_DMA) += sandbox-dma-test.o
>  obj-$(CONFIG_TI_KSNAV) += keystone_nav.o keystone_nav_cfg.o
> diff --git a/drivers/dma/bcm6348-iudma.c b/drivers/dma/bcm6348-iudma.c
> new file mode 100644
> index 0000000000..284735fff3
> --- /dev/null
> +++ b/drivers/dma/bcm6348-iudma.c
> @@ -0,0 +1,576 @@
> +/*
> + * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
> + *
> + * Derived from linux/drivers/dma/bcm63xx-iudma.c:
> + *	Copyright (C) 2015 Simon Arlott <simon@fire.lp0.eu>
> + *
> + * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c:
> + *	Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
> + *
> + * Derived from bcm963xx_4.12L.06B_consumer/shared/opensource/include/bcm963xx/63268_map_part.h:
> + *	Copyright (C) 2000-2010 Broadcom Corporation
> + *
> + * Derived from bcm963xx_4.12L.06B_consumer/bcmdrivers/opensource/net/enet/impl4/bcmenet.c:
> + *	Copyright (C) 2010 Broadcom Corporation
> + *
> + * SPDX-License-Identifier: GPL-2.0+

// SPDX-License-Identifier: GPL-2.0+
must be the first line of the file

> + */
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <dma-uclass.h>
> +#include <memalign.h>
> +#include <reset.h>
> +#include <asm/io.h>
> +
> +#define DMA_RX_DESC	6
> +#define DMA_TX_DESC	1
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#define ALIGN_END_ADDR(type, ptr, size)	\
> +	((unsigned long)(ptr) + roundup((size) * sizeof(type), \
> +	 ARCH_DMA_MINALIGN))
> +
> +/* DMA Channels */
> +#define DMA_CHAN_FLOWC(x)		((x) >> 1)
> +#define DMA_CHAN_MAX			16
> +#define DMA_CHAN_SIZE			0x10
> +#define DMA_CHAN_TOUT			500
> +
> +/* DMA Global Configuration register */
> +#define DMA_CFG_REG			0x00
> +#define  DMA_CFG_ENABLE_SHIFT		0
> +#define  DMA_CFG_ENABLE_MASK		(1 << DMA_CFG_ENABLE_SHIFT)
> +#define  DMA_CFG_FLOWC_ENABLE(x)	BIT(DMA_CHAN_FLOWC(x) + 1)
> +#define  DMA_CFG_NCHANS_SHIFT		24
> +#define  DMA_CFG_NCHANS_MASK		(0xf << DMA_CFG_NCHANS_SHIFT)
> +
> +/* DMA Global Flow Control registers */
> +#define DMA_FLOWC_THR_LO_REG(x)		(0x04 + DMA_CHAN_FLOWC(x) * 0x0c)
> +#define DMA_FLOWC_THR_HI_REG(x)		(0x08 + DMA_CHAN_FLOWC(x) * 0x0c)
> +#define DMA_FLOWC_ALLOC_REG(x)		(0x0c + DMA_CHAN_FLOWC(x) * 0x0c)
> +#define  DMA_FLOWC_ALLOC_FORCE_SHIFT	31
> +#define  DMA_FLOWC_ALLOC_FORCE_MASK	(1 << DMA_FLOWC_ALLOC_FORCE_SHIFT)
> +
> +/* DMA Global Reset register */
> +#define DMA_RST_REG			0x34
> +#define  DMA_RST_CHAN_SHIFT		0
> +#define  DMA_RST_CHAN_MASK(x)		(1 << x)
> +
> +/* DMA Channel Configuration register */
> +#define DMAC_CFG_REG(x)			(DMA_CHAN_SIZE * (x) + 0x00)
> +#define  DMAC_CFG_ENABLE_SHIFT		0
> +#define  DMAC_CFG_ENABLE_MASK		(1 << DMAC_CFG_ENABLE_SHIFT)
> +#define  DMAC_CFG_PKT_HALT_SHIFT	1
> +#define  DMAC_CFG_PKT_HALT_MASK		(1 << DMAC_CFG_PKT_HALT_SHIFT)
> +#define  DMAC_CFG_BRST_HALT_SHIFT	2
> +#define  DMAC_CFG_BRST_HALT_MASK	(1 << DMAC_CFG_BRST_HALT_SHIFT)
> +
> +/* DMA Channel Max Burst Length register */
> +#define DMAC_BURST_REG(x)		(DMA_CHAN_SIZE * (x) + 0x0c)
> +
> +/* DMA SRAM Descriptor Ring Start register */
> +#define DMAS_RSTART_REG(x)		(DMA_CHAN_SIZE * (x) + 0x00)
> +
> +/* DMA SRAM State/Bytes done/ring offset register */
> +#define DMAS_STATE_DATA_REG(x)		(DMA_CHAN_SIZE * (x) + 0x04)
> +
> +/* DMA SRAM Buffer Descriptor status and length register */
> +#define DMAS_DESC_LEN_STATUS_REG(x)	(DMA_CHAN_SIZE * (x) + 0x08)
> +
> +/* DMA SRAM Buffer Descriptor status and length register */
> +#define DMAS_DESC_BASE_BUFPTR_REG(x)	(DMA_CHAN_SIZE * (x) + 0x0c)
> +
> +struct bcm6348_dma_desc {
> +	uint16_t length;
> +
> +	uint16_t status;
> +#define DMAD_ST_CRC_SHIFT		8
> +#define DMAD_ST_CRC_MASK		(1 << DMAD_ST_CRC_SHIFT)
> +#define DMAD_ST_WRAP_SHIFT		12
> +#define DMAD_ST_WRAP_MASK		(1 << DMAD_ST_WRAP_SHIFT)
> +#define DMAD_ST_SOP_SHIFT		13
> +#define DMAD_ST_SOP_MASK		(1 << DMAD_ST_SOP_SHIFT)
> +#define DMAD_ST_EOP_SHIFT		14
> +#define DMAD_ST_EOP_MASK		(1 << DMAD_ST_EOP_SHIFT)
> +#define DMAD_ST_OWN_SHIFT		15
> +#define DMAD_ST_OWN_MASK		(1 << DMAD_ST_OWN_SHIFT)
> +
> +#define DMAD6348_ST_OV_ERR_SHIFT	0
> +#define DMAD6348_ST_OV_ERR_MASK		(1 << DMAD6348_ST_OV_ERR_SHIFT)
> +#define DMAD6348_ST_CRC_ERR_SHIFT	1
> +#define DMAD6348_ST_CRC_ERR_MASK	(1 << DMAD6348_ST_CRC_ERR_SHIFT)
> +#define DMAD6348_ST_RX_ERR_SHIFT	2
> +#define DMAD6348_ST_RX_ERR_MASK		(1 << DMAD6348_ST_RX_ERR_SHIFT)
> +#define DMAD6348_ST_OS_ERR_SHIFT	4
> +#define DMAD6348_ST_OS_ERR_MASK		(1 << DMAD6348_ST_OS_ERR_SHIFT)
> +#define DMAD6348_ST_UN_ERR_SHIFT	9
> +#define DMAD6348_ST_UN_ERR_MASK		(1 << DMAD6348_ST_UN_ERR_SHIFT)

I would move this out of the struct definition

> +
> +	uint32_t address;
> +} __attribute__((aligned(1)));

__aligned(1)? But what's the sense of aligning to 1 byte?

> +
> +struct bcm6348_chan_priv {
> +	void __iomem *dma_buff;
> +	void __iomem *dma_ring;
> +	uint8_t dma_ring_size;
> +	uint8_t desc_id;
> +	uint8_t dirty_cnt;
> +	uint8_t dirty_desc;
> +};
> +
> +struct bcm6348_iudma_hw {
> +	uint16_t err_mask;
> +};
> +
> +struct bcm6348_iudma_priv {
> +	const struct bcm6348_iudma_hw *hw;
> +	void __iomem *base;
> +	void __iomem *chan;
> +	void __iomem *sram;
> +	struct bcm6348_chan_priv **ch_priv;
> +	uint8_t n_channels;
> +};
> +
> +static inline bool bcm6348_iudma_chan_is_rx(uint8_t ch)
> +{
> +	return !(ch & 1);
> +}
> +
> +static void bcm6348_iudma_chan_stop(struct bcm6348_iudma_priv *priv,
> +				    uint8_t ch)
> +{
> +	unsigned int timeout = DMA_CHAN_TOUT;
> +
> +	do {
> +		uint32_t cfg, halt;
> +
> +		if (timeout > DMA_CHAN_TOUT / 2)
> +			halt = DMAC_CFG_PKT_HALT_MASK;
> +		else
> +			halt = DMAC_CFG_BRST_HALT_MASK;
> +
> +		/* try to stop dma channel */
> +		writel_be(halt, priv->chan + DMAC_CFG_REG(ch));
> +		mb();
> +
> +		/* check if channel was stopped */
> +		cfg = readl_be(priv->chan + DMAC_CFG_REG(ch));
> +		if (!(cfg & DMAC_CFG_ENABLE_MASK))
> +			break;
> +
> +		udelay(1);
> +	} while (--timeout);
> +
> +	if (!timeout)
> +		pr_err("unable to stop channel %u\n", ch);
> +
> +	/* reset dma channel */
> +	setbits_be32(priv->base + DMA_RST_REG, DMA_RST_CHAN_MASK(ch));
> +	mdelay(1);
> +	clrbits_be32(priv->base + DMA_RST_REG, DMA_RST_CHAN_MASK(ch));
> +}
> +
> +static int bcm6348_iudma_disable(struct dma *dma)
> +{
> +	struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
> +
> +	bcm6348_iudma_chan_stop(priv, dma->id);
> +
> +	if (bcm6348_iudma_chan_is_rx(dma->id))
> +		writel_be(DMA_FLOWC_ALLOC_FORCE_MASK,
> +			  DMA_FLOWC_ALLOC_REG(dma->id));
> +
> +	return 0;
> +}
> +
> +static int bcm6348_iudma_enable(struct dma *dma)
> +{
> +	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
> +	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
> +	struct bcm6348_dma_desc *dma_desc;
> +	void __iomem *dma_buff = ch_priv->dma_buff;
> +	uint8_t i;
> +
> +	/* init dma rings */
> +	dma_desc = ch_priv->dma_ring;
> +	for (i = 0; i < ch_priv->dma_ring_size; i++) {
> +		uint16_t status;
> +
> +		if (bcm6348_iudma_chan_is_rx(dma->id)) {
> +			status = DMAD_ST_OWN_MASK;
> +			dma_desc->length = PKTSIZE_ALIGN;
> +			dma_desc->address = virt_to_phys(dma_buff);
> +			dma_buff += PKTSIZE_ALIGN;

shouldn't this be somehow set by a consumer driver instead of
hard-coding the size of a network packet?

> +		} else {
> +			status = 0;
> +			dma_desc->length = 0;
> +			dma_desc->address = 0;
> +		}
> +
> +		if (i == ch_priv->dma_ring_size - 1)
> +			status |= DMAD_ST_WRAP_MASK;
> +
> +		dma_desc->status = status;
> +
> +		dma_desc++;
> +	}
> +
> +	/* init to first descriptor */
> +	ch_priv->desc_id = 0;
> +	ch_priv->dirty_desc = 0;
> +	ch_priv->dirty_cnt = 0;
> +
> +	/* force cache writeback */
> +	flush_dcache_range((ulong)ch_priv->dma_ring,
> +		ALIGN_END_ADDR(struct bcm6348_dma_desc, ch_priv->dma_ring,
> +			       ch_priv->dma_ring_size));
> +
> +	/* clear sram */
> +	writel_be(0, priv->sram + DMAS_STATE_DATA_REG(dma->id));
> +	writel_be(0, priv->sram + DMAS_DESC_LEN_STATUS_REG(dma->id));
> +	writel_be(0, priv->sram + DMAS_DESC_BASE_BUFPTR_REG(dma->id));
> +
> +	/* set dma ring start */
> +	writel_be(virt_to_phys(ch_priv->dma_ring),
> +		  priv->sram + DMAS_RSTART_REG(dma->id));
> +
> +	/* set flow control */
> +	if (bcm6348_iudma_chan_is_rx(dma->id)) {
> +		u32 val;
> +
> +		setbits_be32(priv->base + DMA_CFG_REG,
> +			     DMA_CFG_FLOWC_ENABLE(dma->id));
> +
> +		val = ch_priv->dma_ring_size / 3;
> +		writel_be(val, priv->base + DMA_FLOWC_THR_LO_REG(dma->id));
> +
> +		val = (ch_priv->dma_ring_size * 2) / 3;
> +		writel_be(val, priv->base + DMA_FLOWC_THR_HI_REG(dma->id));
> +
> +		writel_be(0, priv->base + DMA_FLOWC_ALLOC_REG(dma->id));
> +	}
> +
> +	/* set dma max burst */
> +	writel_be(ch_priv->dma_ring_size,
> +		  priv->chan + DMAC_BURST_REG(dma->id));
> +
> +	/* kick dma channel */
> +	setbits_be32(priv->chan + DMAC_CFG_REG(dma->id), DMAC_CFG_ENABLE_MASK);
> +
> +	return 0;
> +}
> +
> +static int bcm6348_iudma_request(struct dma *dma)
> +{
> +	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
> +	struct bcm6348_chan_priv *ch_priv;
> +
> +	/* check if channel is valid */
> +	if (dma->id >= priv->n_channels)
> +		return -ENODEV;
> +
> +	/* alloc channel private data */
> +	priv->ch_priv[dma->id] = calloc(1, sizeof(struct bcm6348_chan_priv));
> +	if (!priv->ch_priv[dma->id])
> +		return -ENOMEM;
> +	ch_priv = priv->ch_priv[dma->id];
> +
> +	/* alloc dma ring */
> +	if (bcm6348_iudma_chan_is_rx(dma->id))
> +		ch_priv->dma_ring_size = DMA_RX_DESC;
> +	else
> +		ch_priv->dma_ring_size = DMA_TX_DESC;
> +
> +	ch_priv->dma_ring =
> +		malloc_cache_aligned(sizeof(struct bcm6348_dma_desc) *
> +				     ch_priv->dma_ring_size);
> +	if (!ch_priv->dma_ring)
> +		return -ENOMEM;
> +
> +	if (bcm6348_iudma_chan_is_rx(dma->id)) {
> +		ch_priv->dma_buff =
> +			malloc_cache_aligned(PKTSIZE_ALIGN *
> +					     ch_priv->dma_ring_size);
> +		if (!ch_priv->dma_buff)
> +			return -ENOMEM;
> +	} else {
> +		ch_priv->dma_buff = NULL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int bcm6348_iudma_receive(struct dma *dma, void **dst, void *metadata)
> +{
> +	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
> +	const struct bcm6348_iudma_hw *hw = priv->hw;
> +	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
> +	struct bcm6348_dma_desc *dma_desc;
> +	void __iomem *dma_buff;
> +	int ret;
> +
> +	if (ch_priv->dirty_cnt == ch_priv->dma_ring_size) {
> +		pr_err("dma rx ring full of dirty descriptors\n");
> +		return -EAGAIN;
> +	}
> +
> +	/* get dma ring descriptor address */
> +	dma_desc = ch_priv->dma_ring;
> +	dma_desc += ch_priv->desc_id;
> +
> +	/* invalidate cache data */
> +	invalidate_dcache_range((ulong)dma_desc,
> +		ALIGN_END_ADDR(struct bcm6348_dma_desc, dma_desc, 1));
> +
> +	/* check dma own */
> +	if (dma_desc->status & DMAD_ST_OWN_MASK)
> +		return -EAGAIN;
> +
> +	/* check pkt */
> +	if (!(dma_desc->status & DMAD_ST_EOP_MASK) ||
> +	    !(dma_desc->status & DMAD_ST_SOP_MASK) ||
> +	    (dma_desc->status & hw->err_mask)) {
> +		pr_err("invalid pkt received (ch=%ld) (st=%04x)\n",
> +		       dma->id, dma_desc->status);
> +		ret = -EAGAIN;
> +	} else {
> +		uint16_t length;
> +
> +		/* get dma buff descriptor address */
> +		dma_buff = phys_to_virt(dma_desc->address);
> +
> +		/* invalidate cache data */
> +		invalidate_dcache_range((ulong)dma_buff,
> +					(ulong)(dma_buff + PKTSIZE_ALIGN));
> +
> +		/* remove crc */
> +		length = dma_desc->length - 4;
> +
> +		/* copy data */
> +		memcpy(*dst, dma_buff, length);

why not returning the buffer address where the DMA transfered the data
to instead of making a copy?

> +
> +		ret = length;
> +	}
> +
> +	/* increment dma descriptor */
> +	ch_priv->desc_id = (ch_priv->desc_id + 1) % ch_priv->dma_ring_size;
> +	ch_priv->dirty_cnt++;
> +
> +	return ret;
> +}
> +
> +static int bcm6348_iudma_send(struct dma *dma, void *src, size_t len,
> +			      void *metadata)
> +{
> +	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
> +	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
> +	struct bcm6348_dma_desc *dma_desc;
> +	uint16_t status;
> +
> +	/* flush cache */
> +	flush_dcache_range((ulong)src, (ulong)src + PKTSIZE_ALIGN);

you pass a 'size_t len' but still use the hard-coded buffer size?

> +
> +	/* get dma ring descriptor address */
> +	dma_desc = ch_priv->dma_ring;
> +	dma_desc += ch_priv->desc_id;
> +
> +	/* config dma descriptor */
> +	status = (DMAD_ST_OWN_MASK |
> +		  DMAD_ST_EOP_MASK |
> +		  DMAD_ST_CRC_MASK |
> +		  DMAD_ST_SOP_MASK);
> +	if (ch_priv->desc_id == ch_priv->dma_ring_size - 1)
> +		status |= DMAD_ST_WRAP_MASK;
> +
> +	dma_desc->address = virt_to_phys(src);
> +	dma_desc->length = len;
> +	dma_desc->status = status;
> +
> +	/* flush cache */
> +	flush_dcache_range((ulong)dma_desc,
> +		ALIGN_END_ADDR(struct bcm6348_dma_desc, dma_desc, 1));
> +
> +	/* kick tx dma channel */
> +	setbits_be32(priv->chan + DMAC_CFG_REG(dma->id), DMAC_CFG_ENABLE_MASK);
> +
> +	/* poll dma status */
> +	do {
> +		/* invalidate cache */
> +		invalidate_dcache_range((ulong)dma_desc,
> +			ALIGN_END_ADDR(struct bcm6348_dma_desc, dma_desc, 1));
> +
> +		if (!(dma_desc->status & DMAD_ST_OWN_MASK))
> +			break;
> +	} while(1);
> +
> +	/* increment dma descriptor */
> +	ch_priv->desc_id = (ch_priv->desc_id + 1) % ch_priv->dma_ring_size;
> +
> +	return 0;
> +}
> +
> +int bcm6348_iudma_prepare_rcv_buf(struct dma *dma, void *dst, size_t size)
> +{
> +	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
> +	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
> +
> +	/* init dma rings */
> +	while (ch_priv->dirty_cnt) {
> +		struct bcm6348_dma_desc *dma_desc = ch_priv->dma_ring;
> +		uint16_t status = DMAD_ST_OWN_MASK;
> +
> +		/* get dirty dma descriptor */
> +		dma_desc += ch_priv->dirty_desc;
> +
> +		/* reinit dirty dma descriptor */
> +		if (ch_priv->dirty_desc == ch_priv->dma_ring_size - 1)
> +			status |= DMAD_ST_WRAP_MASK;
> +		dma_desc->length = PKTSIZE_ALIGN;

you pass a 'size_t size' but still use the hard-coded buffer size?

> +		dma_desc->status = status;
> +
> +		/* flush cache */
> +		flush_dcache_range((ulong)dma_desc,
> +			ALIGN_END_ADDR(struct bcm6348_dma_desc, dma_desc, 1));
> +
> +		/* tell dma engine we allocated one buffer */
> +		writel_be(1, DMA_FLOWC_ALLOC_REG(dma->id));
> +
> +		/* bump dirty dma descriptor */
> +		ch_priv->dirty_desc = (ch_priv->dirty_desc + 1) %
> +				      ch_priv->dma_ring_size;
> +
> +		/* kick rx dma channel */
> +		ch_priv->dirty_cnt--;
> +		if (!ch_priv->dirty_cnt)
> +			setbits_be32(priv->chan + DMAC_CFG_REG(dma->id),
> +				     DMAC_CFG_ENABLE_MASK);
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct dma_ops bcm6348_iudma_ops = {
> +	.disable = bcm6348_iudma_disable,
> +	.enable = bcm6348_iudma_enable,
> +	.prepare_rcv_buf = bcm6348_iudma_prepare_rcv_buf,
> +	.request = bcm6348_iudma_request,
> +	.receive = bcm6348_iudma_receive,
> +	.send = bcm6348_iudma_send,
> +};
> +
> +static const struct bcm6348_iudma_hw bcm6348_hw = {
> +	.err_mask = (DMAD6348_ST_OV_ERR_MASK |
> +		     DMAD6348_ST_CRC_ERR_MASK |
> +		     DMAD6348_ST_RX_ERR_MASK |
> +		     DMAD6348_ST_OS_ERR_MASK |
> +		     DMAD6348_ST_UN_ERR_MASK),
> +};
> +
> +static const struct bcm6348_iudma_hw bcm6368_hw = {
> +	.err_mask = 0,
> +};
> +
> +static const struct udevice_id bcm6348_iudma_ids[] = {
> +	{
> +		.compatible = "brcm,bcm6348-iudma",
> +		.data = (ulong)&bcm6348_hw,
> +	}, {
> +		.compatible = "brcm,bcm6368-iudma",
> +		.data = (ulong)&bcm6368_hw,
> +	}, { /* sentinel */ }
> +};
> +
> +static int bcm6348_iudma_probe(struct udevice *dev)
> +{
> +	struct dma_dev_priv *uc_priv = dev_get_uclass_priv(dev);
> +	struct bcm6348_iudma_priv *priv = dev_get_priv(dev);
> +	const struct bcm6348_iudma_hw *hw =
> +		(const struct bcm6348_iudma_hw *)dev_get_driver_data(dev);
> +	fdt_addr_t addr;
> +	uint8_t ch;
> +	int i;
> +
> +	uc_priv->supported = (DMA_SUPPORTS_DEV_TO_MEM |
> +			      DMA_SUPPORTS_MEM_TO_DEV);
> +	priv->hw = hw;
> +
> +	/* try to enable clocks */
> +	for (i = 0; ; i++) {
> +		struct clk clk;
> +		int ret;
> +
> +		ret = clk_get_by_index(dev, i, &clk);
> +		if (ret < 0)
> +			break;

why not getting the reference once and do appropiate error handling.
Although it's only probing but this looks very inefficient

> +		if (clk_enable(&clk))
> +			pr_err("failed to enable clock %d\n", i);
> +		clk_free(&clk);
> +	}
> +
> +	/* try to perform resets */

no error handling for clk_get_by_index()? I guess it doesn't make sense
to continue without enabled clocks?

> +	for (i = 0; ; i++) {
> +		struct reset_ctl reset;
> +		int ret;
> +
> +		ret = reset_get_by_index(dev, i, &reset);
> +		if (ret < 0)
> +			break;
> +		if (reset_deassert(&reset))
> +			pr_err("failed to deassert reset %d\n", i);
> +		reset_free(&reset);
> +	}

same here

> +
> +	/* dma global base address */
> +	addr = devfdt_get_addr_name(dev, "dma");
> +	if (addr == FDT_ADDR_T_NONE)
> +		return -EINVAL;
> +	priv->base = ioremap(addr, 0);

this is not compatible with DM live tree which you already enabled for
BMIPS platform. You should use dev_remap_addr_index() or you should add
a generic dev_remap_addr_name().

> +
> +	/* dma channels base address */
> +	addr = devfdt_get_addr_name(dev, "dma-channels");
> +	if (addr == FDT_ADDR_T_NONE)
> +		return -EINVAL;
> +	priv->chan = ioremap(addr, 0);
> +
> +	/* dma sram base address */
> +	addr = devfdt_get_addr_name(dev, "dma-sram");
> +	if (addr == FDT_ADDR_T_NONE)
> +		return -EINVAL;
> +	priv->sram = ioremap(addr, 0);
> +
> +	/* disable dma controller */
> +	clrbits_be32(priv->base + DMA_CFG_REG, DMA_CFG_ENABLE_MASK);
> +
> +	/* get number of channels */
> +	priv->n_channels = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
> +					   "dma-channels", 8);

dev_read_u32() ?

> +	if (priv->n_channels > DMA_CHAN_MAX)
> +		return -EINVAL;
> +
> +	/* alloc channel private data pointers */
> +	priv->ch_priv = calloc(priv->n_channels,
> +			       sizeof(struct bcm6348_chan_priv*));
> +	if (!priv->ch_priv)
> +		return -ENOMEM;
> +
> +	/* stop dma channels */
> +	for (ch = 0; ch < priv->n_channels; ch++)
> +		bcm6348_iudma_chan_stop(priv, ch);
> +
> +	/* enable dma controller */
> +	setbits_be32(priv->base + DMA_CFG_REG, DMA_CFG_ENABLE_MASK);
> +
> +	return 0;
> +}
> +
> +U_BOOT_DRIVER(bcm6348_iudma) = {
> +	.name = "bcm6348_iudma",
> +	.id = UCLASS_DMA,
> +	.of_match = bcm6348_iudma_ids,
> +	.ops = &bcm6348_iudma_ops,
> +	.priv_auto_alloc_size = sizeof(struct bcm6348_iudma_priv),
> +	.probe = bcm6348_iudma_probe,
> +};
> 

-- 
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20181129/a1bd05ee/attachment.sig>

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

* [U-Boot] [PATCH v9 02/28] bmips: bcm6338: add bcm6348-iudma support
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 02/28] bmips: bcm6338: " Álvaro Fernández Rojas
@ 2018-11-28 23:48       ` Daniel Schwierzeck
  0 siblings, 0 replies; 145+ messages in thread
From: Daniel Schwierzeck @ 2018-11-28 23:48 UTC (permalink / raw)
  To: u-boot



Am 28.11.18 um 19:23 schrieb Álvaro Fernández Rojas:
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> ---
>  v9: no changes
>  v8: no changes
>  v5: no changes
>  v4: no changes
>  v3: no changes
>  v2: no changes
> 
>  arch/mips/dts/brcm,bcm6338.dtsi       | 14 ++++++++++++++
>  include/dt-bindings/dma/bcm6338-dma.h | 15 +++++++++++++++
>  2 files changed, 29 insertions(+)
>  create mode 100644 include/dt-bindings/dma/bcm6338-dma.h
> 
> diff --git a/arch/mips/dts/brcm,bcm6338.dtsi b/arch/mips/dts/brcm,bcm6338.dtsi
> index bbd58cf803..990355481c 100644
> --- a/arch/mips/dts/brcm,bcm6338.dtsi
> +++ b/arch/mips/dts/brcm,bcm6338.dtsi
> @@ -4,6 +4,7 @@
>   */
>  
>  #include <dt-bindings/clock/bcm6338-clock.h>
> +#include <dt-bindings/dma/bcm6338-dma.h>
>  #include <dt-bindings/gpio/gpio.h>
>  #include <dt-bindings/reset/bcm6338-reset.h>
>  #include "skeleton.dtsi"
> @@ -130,5 +131,18 @@
>  			reg = <0xfffe3100 0x38>;
>  			u-boot,dm-pre-reloc;
>  		};
> +
> +		iudma: dma-controller at fffe2400 {
> +			compatible = "brcm,bcm6348-iudma";
> +			reg = <0xfffe2400 0x1c>,
> +			      <0xfffe2500 0x60>,
> +			      <0xfffe2600 0x60>;
> +			reg-names = "dma",
> +				    "dma-channels",
> +				    "dma-sram";
> +			#dma-cells = <1>;
> +			dma-channels = <6>;
> +			resets = <&periph_rst BCM6338_RST_DMAMEM>;
> +		};
>  	};
>  };
> diff --git a/include/dt-bindings/dma/bcm6338-dma.h b/include/dt-bindings/dma/bcm6338-dma.h
> new file mode 100644
> index 0000000000..5dd66239b4
> --- /dev/null
> +++ b/include/dt-bindings/dma/bcm6338-dma.h
> @@ -0,0 +1,15 @@
> +/*
> + * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
> + *
> + * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
> + *
> + * SPDX-License-Identifier:	GPL-2.0+

// SPDX-License-Identifier: GPL-2.0+

need to be fixed in all patches

> + */
> +
> +#ifndef __DT_BINDINGS_DMA_BCM6338_H
> +#define __DT_BINDINGS_DMA_BCM6338_H
> +
> +#define BCM6338_DMA_ENET_RX	0
> +#define BCM6338_DMA_ENET_TX	1
> +
> +#endif /* __DT_BINDINGS_DMA_BCM6338_H */
> 

-- 
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20181129/58dff1b6/attachment.sig>

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

* [U-Boot] [PATCH v9 10/28] net: add support for bcm6348-enet
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 10/28] net: add support for bcm6348-enet Álvaro Fernández Rojas
@ 2018-11-28 23:58       ` Daniel Schwierzeck
  0 siblings, 0 replies; 145+ messages in thread
From: Daniel Schwierzeck @ 2018-11-28 23:58 UTC (permalink / raw)
  To: u-boot



Am 28.11.18 um 19:23 schrieb Álvaro Fernández Rojas:
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> ---
>  v9: use dma_prepare_rcv_buf and remove dma rx channel reset:
>   - bcm6348_eth_recv: clear dirty dma descriptors only when packets are copied
>    from rx dma.
>   - bcm6348_eth_send: remove dma rx channel reset when sending packet.
>  v8: Introduce changes from Grygorii Strashko
>  v5: Receive as much packets as possible from bcm6348-eth and cache them in
>  net_rx_packets. This is needed in order to fix flow control issues.
>  v4: Fix issues reported by Grygorii Strashko and other fixes:
>   - Copy received dma buffer to net_rx_packets in order to avoid possible
>   dma overwrites.
>   - Reset dma rx channel when sending a new packet to prevent flow control
>   issues.
>   - Fix packet casting on bcm6348_eth_recv/send.
>  v3: no changes
>  v2: select DMA_CHANNELS.
> 
>  drivers/net/Kconfig            |  10 +
>  drivers/net/Makefile           |   1 +
>  drivers/net/bcm6348-eth.c      | 576 +++++++++++++++++++++++++++++++++++++++++
>  include/configs/bmips_common.h |   5 +-
>  4 files changed, 591 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/net/bcm6348-eth.c
> 
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index 8fb365fc5d..2b7cec8804 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -72,6 +72,16 @@ config BCM_SF2_ETH_GMAC
>  	  by the BCM_SF2_ETH driver.
>  	  Say Y to any bcmcygnus based platforms.
>  
> +config BCM6348_ETH
> +	bool "BCM6348 EMAC support"
> +	depends on DM_ETH && ARCH_BMIPS
> +	select DMA
> +	select DMA_CHANNELS
> +	select MII
> +	select PHYLIB
> +	help
> +	  This driver supports the BCM6348 Ethernet MAC.
> +
>  config DWC_ETH_QOS
>  	bool "Synopsys DWC Ethernet QOS device support"
>  	depends on DM_ETH
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index 99056aa041..2647d4dd23 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -6,6 +6,7 @@
>  obj-$(CONFIG_ALTERA_TSE) += altera_tse.o
>  obj-$(CONFIG_AG7XXX) += ag7xxx.o
>  obj-$(CONFIG_ARMADA100_FEC) += armada100_fec.o
> +obj-$(CONFIG_BCM6348_ETH) += bcm6348-eth.o
>  obj-$(CONFIG_DRIVER_AT91EMAC) += at91_emac.o
>  obj-$(CONFIG_DRIVER_AX88180) += ax88180.o
>  obj-$(CONFIG_BCM_SF2_ETH) += bcm-sf2-eth.o
> diff --git a/drivers/net/bcm6348-eth.c b/drivers/net/bcm6348-eth.c
> new file mode 100644
> index 0000000000..24a44d83cb
> --- /dev/null
> +++ b/drivers/net/bcm6348-eth.c
> @@ -0,0 +1,576 @@
> +/*
> + * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
> + *
> + * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c:
> + *	Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <dma.h>
> +#include <miiphy.h>
> +#include <net.h>
> +#include <phy.h>
> +#include <reset.h>
> +#include <wait_bit.h>
> +#include <asm/io.h>
> +
> +#define ETH_RX_DESC			PKTBUFSRX
> +#define ETH_MAX_MTU_SIZE		1518
> +#define ETH_TIMEOUT			100
> +#define ETH_TX_WATERMARK		32
> +
> +/* ETH Receiver Configuration register */
> +#define ETH_RXCFG_REG			0x00
> +#define ETH_RXCFG_ENFLOW_SHIFT		5
> +#define ETH_RXCFG_ENFLOW_MASK		(1 << ETH_RXCFG_ENFLOW_SHIFT)
> +
> +/* ETH Receive Maximum Length register */
> +#define ETH_RXMAXLEN_REG		0x04
> +#define ETH_RXMAXLEN_SHIFT		0
> +#define ETH_RXMAXLEN_MASK		(0x7ff << ETH_RXMAXLEN_SHIFT)
> +
> +/* ETH Transmit Maximum Length register */
> +#define ETH_TXMAXLEN_REG		0x08
> +#define ETH_TXMAXLEN_SHIFT		0
> +#define ETH_TXMAXLEN_MASK		(0x7ff << ETH_TXMAXLEN_SHIFT)
> +
> +/* MII Status/Control register */
> +#define MII_SC_REG			0x10
> +#define MII_SC_MDCFREQDIV_SHIFT		0
> +#define MII_SC_MDCFREQDIV_MASK		(0x7f << MII_SC_MDCFREQDIV_SHIFT)
> +#define MII_SC_PREAMBLE_EN_SHIFT	7
> +#define MII_SC_PREAMBLE_EN_MASK		(1 << MII_SC_PREAMBLE_EN_SHIFT)
> +
> +/* MII Data register */
> +#define MII_DAT_REG			0x14
> +#define MII_DAT_DATA_SHIFT		0
> +#define MII_DAT_DATA_MASK		(0xffff << MII_DAT_DATA_SHIFT)
> +#define MII_DAT_TA_SHIFT		16
> +#define MII_DAT_TA_MASK			(0x3 << MII_DAT_TA_SHIFT)
> +#define MII_DAT_REG_SHIFT		18
> +#define MII_DAT_REG_MASK		(0x1f << MII_DAT_REG_SHIFT)
> +#define MII_DAT_PHY_SHIFT		23
> +#define MII_DAT_PHY_MASK		(0x1f << MII_DAT_PHY_SHIFT)
> +#define MII_DAT_OP_SHIFT		28
> +#define MII_DAT_OP_WRITE		(0x5 << MII_DAT_OP_SHIFT)
> +#define MII_DAT_OP_READ			(0x6 << MII_DAT_OP_SHIFT)
> +
> +/* ETH Interrupts Mask register */
> +#define ETH_IRMASK_REG			0x18
> +
> +/* ETH Interrupts register */
> +#define ETH_IR_REG			0x1c
> +#define ETH_IR_MII_SHIFT		0
> +#define ETH_IR_MII_MASK			(1 << ETH_IR_MII_SHIFT)
> +
> +/* ETH Control register */
> +#define ETH_CTL_REG			0x2c
> +#define ETH_CTL_ENABLE_SHIFT		0
> +#define ETH_CTL_ENABLE_MASK		(1 << ETH_CTL_ENABLE_SHIFT)
> +#define ETH_CTL_DISABLE_SHIFT		1
> +#define ETH_CTL_DISABLE_MASK		(1 << ETH_CTL_DISABLE_SHIFT)
> +#define ETH_CTL_RESET_SHIFT		2
> +#define ETH_CTL_RESET_MASK		(1 << ETH_CTL_RESET_SHIFT)
> +#define ETH_CTL_EPHY_SHIFT		3
> +#define ETH_CTL_EPHY_MASK		(1 << ETH_CTL_EPHY_SHIFT)
> +
> +/* ETH Transmit Control register */
> +#define ETH_TXCTL_REG			0x30
> +#define ETH_TXCTL_FD_SHIFT		0
> +#define ETH_TXCTL_FD_MASK		(1 << ETH_TXCTL_FD_SHIFT)
> +
> +/* ETH Transmit Watermask register */
> +#define ETH_TXWMARK_REG			0x34
> +#define ETH_TXWMARK_WM_SHIFT		0
> +#define ETH_TXWMARK_WM_MASK		(0x3f << ETH_TXWMARK_WM_SHIFT)
> +
> +/* MIB Control register */
> +#define MIB_CTL_REG			0x38
> +#define MIB_CTL_RDCLEAR_SHIFT		0
> +#define MIB_CTL_RDCLEAR_MASK		(1 << MIB_CTL_RDCLEAR_SHIFT)
> +
> +/* ETH Perfect Match registers */
> +#define ETH_PM_CNT			4
> +#define ETH_PML_REG(x)			(0x58 + (x) * 0x8)
> +#define ETH_PMH_REG(x)			(0x5c + (x) * 0x8)
> +#define ETH_PMH_VALID_SHIFT		16
> +#define ETH_PMH_VALID_MASK		(1 << ETH_PMH_VALID_SHIFT)
> +
> +/* MIB Counters registers */
> +#define MIB_REG_CNT			55
> +#define MIB_REG(x)			(0x200 + (x) * 4)
> +
> +/* ETH data */
> +struct bcm6348_eth_priv {
> +	void __iomem *base;
> +	/* RX */
> +	uint8_t rx_desc;
> +	uint8_t rx_pend;
> +	int rx_ret[ETH_RX_DESC];
> +	/* DMA */
> +	struct dma rx_dma;
> +	struct dma tx_dma;
> +	/* PHY */
> +	int phy_id;
> +	struct phy_device *phy_dev;
> +};
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +static void bcm6348_eth_mac_disable(struct bcm6348_eth_priv *priv)
> +{
> +	/* disable emac */
> +	clrsetbits_be32(priv->base + ETH_CTL_REG, ETH_CTL_ENABLE_MASK,
> +			ETH_CTL_DISABLE_MASK);
> +
> +	/* wait until emac is disabled */
> +	if (wait_for_bit_be32(priv->base + ETH_CTL_REG,
> +			      ETH_CTL_DISABLE_MASK, false,
> +			      ETH_TIMEOUT, false))
> +		pr_err("error disabling emac\n");
> +}
> +
> +static void bcm6348_eth_mac_enable(struct bcm6348_eth_priv *priv)
> +{
> +	setbits_be32(priv->base + ETH_CTL_REG, ETH_CTL_ENABLE_MASK);
> +}
> +
> +static void bcm6348_eth_mac_reset(struct bcm6348_eth_priv *priv)
> +{
> +	/* reset emac */
> +	writel_be(ETH_CTL_RESET_MASK, priv->base + ETH_CTL_REG);
> +	wmb();
> +
> +	/* wait until emac is reset */
> +	if (wait_for_bit_be32(priv->base + ETH_CTL_REG,
> +			      ETH_CTL_RESET_MASK, false,
> +			      ETH_TIMEOUT, false))
> +		pr_err("error resetting emac\n");
> +}
> +
> +static int bcm6348_eth_free_pkt(struct udevice *dev, uchar *packet, int len)
> +{
> +	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
> +
> +	/* sanity check */
> +	if (packet != net_rx_packets[priv->rx_pend]) {
> +		pr_err("rx_pend %d: packet is not matched,\n", priv->rx_pend);
> +		return -EAGAIN;
> +	}
> +
> +	/* free pending packet */
> +	priv->rx_ret[priv->rx_pend] = 0;
> +	priv->rx_pend = (priv->rx_pend + 1) % ETH_RX_DESC;
> +
> +	return 0;
> +}
> +
> +static int _bcm6348_eth_recv(struct bcm6348_eth_priv *priv)
> +{
> +	uint8_t pkt = priv->rx_desc;
> +
> +	/* check if packet is free */
> +	if (priv->rx_ret[pkt] > 0)
> +		return -EAGAIN;
> +
> +	/* try to receive a new packet */
> +	priv->rx_ret[pkt] = dma_receive(&priv->rx_dma,
> +					(void **)&net_rx_packets[pkt],
> +					NULL);
> +	if (priv->rx_ret[pkt] > 0)
> +		priv->rx_desc = (priv->rx_desc + 1) % ETH_RX_DESC;
> +
> +	return priv->rx_ret[pkt];
> +}
> +
> +static int bcm6348_eth_recv(struct udevice *dev, int flags, uchar **packetp)
> +{
> +	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
> +
> +	/* receive packets if queue is empty */
> +	if (priv->rx_ret[priv->rx_pend] <= 0) {
> +		uint8_t pkt_cnt = 0;
> +
> +		/* try to receive packets */
> +		while (_bcm6348_eth_recv(priv) > 0)
> +			pkt_cnt++;
> +
> +		dma_prepare_rcv_buf(&priv->rx_dma, NULL, 0);
> +
> +		if (pkt_cnt)
> +			debug("%s: received %u packet(s)\n", __func__, pkt_cnt);
> +	}
> +
> +	/* return current packet */
> +	if (priv->rx_ret[priv->rx_pend] > 0)
> +		*packetp = net_rx_packets[priv->rx_pend];
> +
> +	return priv->rx_ret[priv->rx_pend];
> +}
> +
> +static int bcm6348_eth_send(struct udevice *dev, void *packet, int length)
> +{
> +	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
> +
> +	return dma_send(&priv->tx_dma, packet, length, NULL);
> +}
> +
> +static int bcm6348_eth_adjust_link(struct udevice *dev,
> +				   struct phy_device *phydev)
> +{
> +	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
> +
> +	/* mac duplex parameters */
> +	if (phydev->duplex)
> +		setbits_be32(priv->base + ETH_TXCTL_REG, ETH_TXCTL_FD_MASK);
> +	else
> +		clrbits_be32(priv->base + ETH_TXCTL_REG, ETH_TXCTL_FD_MASK);
> +
> +	/* rx flow control (pause frame handling) */
> +	if (phydev->pause)
> +		setbits_be32(priv->base + ETH_RXCFG_REG,
> +			     ETH_RXCFG_ENFLOW_MASK);
> +	else
> +		clrbits_be32(priv->base + ETH_RXCFG_REG,
> +			     ETH_RXCFG_ENFLOW_MASK);
> +
> +	return 0;
> +}
> +
> +static int bcm6348_eth_start(struct udevice *dev)
> +{
> +	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
> +	int ret, i;
> +
> +	priv->rx_desc = 0;
> +	priv->rx_pend = 0;
> +	for (i = 0; i < ETH_RX_DESC; i++)
> +		priv->rx_ret[i] = 0;
> +
> +	/* enable dma rx channel */
> +	dma_enable(&priv->rx_dma);
> +
> +	/* enable dma tx channel */
> +	dma_enable(&priv->tx_dma);
> +
> +	ret = phy_startup(priv->phy_dev);
> +	if (ret) {
> +		pr_err("could not initialize phy\n");
> +		return ret;
> +	}
> +
> +	if (!priv->phy_dev->link) {
> +		pr_err("no phy link\n");
> +		return -EIO;
> +	}
> +
> +	bcm6348_eth_adjust_link(dev, priv->phy_dev);
> +
> +	/* zero mib counters */
> +	for (i = 0; i < MIB_REG_CNT; i++)
> +		writel_be(0, MIB_REG(i));
> +
> +	/* enable rx flow control */
> +	setbits_be32(priv->base + ETH_RXCFG_REG, ETH_RXCFG_ENFLOW_MASK);
> +
> +	/* set max rx/tx length */
> +	writel_be((ETH_MAX_MTU_SIZE << ETH_RXMAXLEN_SHIFT) &
> +		  ETH_RXMAXLEN_MASK, priv->base + ETH_RXMAXLEN_REG);
> +	writel_be((ETH_MAX_MTU_SIZE << ETH_TXMAXLEN_SHIFT) &
> +		   ETH_TXMAXLEN_MASK, priv->base + ETH_TXMAXLEN_REG);
> +
> +	/* set correct transmit fifo watermark */
> +	writel_be((ETH_TX_WATERMARK << ETH_TXWMARK_WM_SHIFT) &
> +		  ETH_TXWMARK_WM_MASK, priv->base + ETH_TXWMARK_REG);
> +
> +	/* enable emac */
> +	bcm6348_eth_mac_enable(priv);
> +
> +	/* clear interrupts */
> +	writel_be(0, priv->base + ETH_IRMASK_REG);
> +
> +	return 0;
> +}
> +
> +static void bcm6348_eth_stop(struct udevice *dev)
> +{
> +	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
> +
> +	/* disable dma rx channel */
> +	dma_disable(&priv->rx_dma);
> +
> +	/* disable dma tx channel */
> +	dma_disable(&priv->tx_dma);
> +
> +	/* disable emac */
> +	bcm6348_eth_mac_disable(priv);
> +}
> +
> +static int bcm6348_eth_write_hwaddr(struct udevice *dev)
> +{
> +	struct eth_pdata *pdata = dev_get_platdata(dev);
> +	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
> +	bool running = false;
> +
> +	/* check if emac is running */
> +	if (readl_be(priv->base + ETH_CTL_REG) & ETH_CTL_ENABLE_MASK)
> +		running = true;
> +
> +	/* disable emac */
> +	if (running)
> +		bcm6348_eth_mac_disable(priv);
> +
> +	/* set mac address */
> +	writel_be((pdata->enetaddr[2] << 24) | (pdata->enetaddr[3]) << 16 |
> +		  (pdata->enetaddr[4]) << 8 | (pdata->enetaddr[5]),
> +		  priv->base + ETH_PML_REG(0));
> +	writel_be((pdata->enetaddr[1]) | (pdata->enetaddr[0] << 8) |
> +		  ETH_PMH_VALID_MASK, priv->base + ETH_PMH_REG(0));
> +
> +	/* enable emac */
> +	if (running)
> +		bcm6348_eth_mac_enable(priv);
> +
> +	return 0;
> +}
> +
> +static const struct eth_ops bcm6348_eth_ops = {
> +	.free_pkt = bcm6348_eth_free_pkt,
> +	.recv = bcm6348_eth_recv,
> +	.send = bcm6348_eth_send,
> +	.start = bcm6348_eth_start,
> +	.stop = bcm6348_eth_stop,
> +	.write_hwaddr = bcm6348_eth_write_hwaddr,
> +};
> +
> +static const struct udevice_id bcm6348_eth_ids[] = {
> +	{ .compatible = "brcm,bcm6348-enet", },
> +	{ /* sentinel */ }
> +};
> +
> +static int bcm6348_mdio_op(void __iomem *base, uint32_t data)
> +{
> +	/* make sure mii interrupt status is cleared */
> +	writel_be(ETH_IR_MII_MASK, base + ETH_IR_REG);
> +
> +	/* issue mii op */
> +	writel_be(data, base + MII_DAT_REG);
> +
> +	/* wait until emac is disabled */
> +	return wait_for_bit_be32(base + ETH_IR_REG,
> +				 ETH_IR_MII_MASK, true,
> +				 ETH_TIMEOUT, false);
> +}
> +
> +static int bcm6348_mdio_read(struct mii_dev *bus, int addr, int devaddr,
> +			     int reg)
> +{
> +	void __iomem *base = bus->priv;
> +	uint32_t val;
> +
> +	val = MII_DAT_OP_READ;
> +	val |= (reg << MII_DAT_REG_SHIFT) & MII_DAT_REG_MASK;
> +	val |= (0x2 << MII_DAT_TA_SHIFT) & MII_DAT_TA_MASK;
> +	val |= (addr << MII_DAT_PHY_SHIFT) & MII_DAT_PHY_MASK;
> +
> +	if (bcm6348_mdio_op(base, val)) {
> +		pr_err("%s: timeout\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	val = readl_be(base + MII_DAT_REG) & MII_DAT_DATA_MASK;
> +	val >>= MII_DAT_DATA_SHIFT;
> +
> +	return val;
> +}
> +
> +static int bcm6348_mdio_write(struct mii_dev *bus, int addr, int dev_addr,
> +			      int reg, u16 value)
> +{
> +	void __iomem *base = bus->priv;
> +	uint32_t val;
> +
> +	val = MII_DAT_OP_WRITE;
> +	val |= (reg << MII_DAT_REG_SHIFT) & MII_DAT_REG_MASK;
> +	val |= (0x2 << MII_DAT_TA_SHIFT) & MII_DAT_TA_MASK;
> +	val |= (addr << MII_DAT_PHY_SHIFT) & MII_DAT_PHY_MASK;
> +	val |= (value << MII_DAT_DATA_SHIFT) & MII_DAT_DATA_MASK;
> +
> +	if (bcm6348_mdio_op(base, val)) {
> +		pr_err("%s: timeout\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int bcm6348_mdio_init(const char *name, void __iomem *base)
> +{
> +	struct mii_dev *bus;
> +
> +	bus = mdio_alloc();
> +	if (!bus) {
> +		pr_err("%s: failed to allocate MDIO bus\n", __func__);
> +		return -ENOMEM;
> +	}
> +
> +	bus->read = bcm6348_mdio_read;
> +	bus->write = bcm6348_mdio_write;
> +	bus->priv = base;
> +	snprintf(bus->name, sizeof(bus->name), "%s", name);
> +
> +	return mdio_register(bus);
> +}
> +
> +static int bcm6348_phy_init(struct udevice *dev)
> +{
> +	struct eth_pdata *pdata = dev_get_platdata(dev);
> +	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
> +	struct mii_dev *bus;
> +
> +	/* get mii bus */
> +	bus = miiphy_get_dev_by_name(dev->name);
> +
> +	/* phy connect */
> +	priv->phy_dev = phy_connect(bus, priv->phy_id, dev,
> +				    pdata->phy_interface);
> +	if (!priv->phy_dev) {
> +		pr_err("%s: no phy device\n", __func__);
> +		return -ENODEV;
> +	}
> +
> +	priv->phy_dev->supported = (SUPPORTED_10baseT_Half |
> +				    SUPPORTED_10baseT_Full |
> +				    SUPPORTED_100baseT_Half |
> +				    SUPPORTED_100baseT_Full |
> +				    SUPPORTED_Autoneg |
> +				    SUPPORTED_Pause |
> +				    SUPPORTED_MII);
> +	priv->phy_dev->advertising = priv->phy_dev->supported;
> +
> +	/* phy config */
> +	phy_config(priv->phy_dev);
> +
> +	return 0;
> +}
> +
> +static int bcm6348_eth_probe(struct udevice *dev)
> +{
> +	struct eth_pdata *pdata = dev_get_platdata(dev);
> +	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
> +	void *blob = (void *)gd->fdt_blob;
> +	int node = dev_of_offset(dev);
> +	const char *phy_mode;
> +	fdt_addr_t addr;
> +	int phy_node, ret, i;
> +
> +	/* get base address */
> +	addr = devfdt_get_addr(dev);
> +	if (addr == FDT_ADDR_T_NONE)
> +		return -EINVAL;

dev_remap_addr() ?

> +
> +	/* get phy mode */
> +	pdata->phy_interface = PHY_INTERFACE_MODE_NONE;
> +	phy_mode = fdt_getprop(blob, node, "phy-mode", NULL);

dev_read_string() ?

> +	if (phy_mode)
> +		pdata->phy_interface = phy_get_interface_by_name(phy_mode);
> +	if (pdata->phy_interface == PHY_INTERFACE_MODE_NONE)
> +		return -ENODEV;
> +
> +	/* get phy */
> +	phy_node = fdtdec_lookup_phandle(blob, node, "phy");
> +	if (phy_node >= 0)
> +		priv->phy_id = fdtdec_get_int(blob, phy_node, "reg", -1);
> +	else
> +		return -EINVAL;

dev_read_phandle_with_args() ?

> +
> +	/* get dma channels */
> +	ret = dma_get_by_name(dev, "tx", &priv->tx_dma);
> +	if (ret)
> +		return -EINVAL;
> +
> +	ret = dma_get_by_name(dev, "rx", &priv->rx_dma);
> +	if (ret)
> +		return -EINVAL;
> +
> +	/* try to enable clocks */
> +	for (i = 0; ; i++) {
> +		struct clk clk;
> +		int ret;
> +
> +		ret = clk_get_by_index(dev, i, &clk);
> +		if (ret < 0)
> +			break;
> +		if (clk_enable(&clk))
> +			pr_err("failed to enable clock %d\n", i);
> +		clk_free(&clk);
> +	}
> +
> +	/* try to perform resets */
> +	for (i = 0; ; i++) {
> +		struct reset_ctl reset;
> +		int ret;
> +
> +		ret = reset_get_by_index(dev, i, &reset);
> +		if (ret < 0)
> +			break;
> +		if (reset_deassert(&reset))
> +			pr_err("failed to deassert reset %d\n", i);
> +		reset_free(&reset);
> +	}
> +
> +	/* get base addr */
> +	priv->base = ioremap(addr, 0);
> +	pdata->iobase = (phys_addr_t) priv->base;
> +
> +	/* disable emac */
> +	bcm6348_eth_mac_disable(priv);
> +
> +	/* reset emac */
> +	bcm6348_eth_mac_reset(priv);
> +
> +	/* select correct mii interface */
> +	if (pdata->phy_interface == PHY_INTERFACE_MODE_INTERNAL)
> +		clrbits_be32(priv->base + ETH_CTL_REG, ETH_CTL_EPHY_MASK);
> +	else
> +		setbits_be32(priv->base + ETH_CTL_REG, ETH_CTL_EPHY_MASK);
> +
> +	/* turn on mdc clock */
> +	writel_be((0x1f << MII_SC_MDCFREQDIV_SHIFT) |
> +		  MII_SC_PREAMBLE_EN_MASK, priv->base + MII_SC_REG);
> +
> +	/* set mib counters to not clear when read */
> +	clrbits_be32(priv->base + MIB_CTL_REG, MIB_CTL_RDCLEAR_MASK);
> +
> +	/* initialize perfect match registers */
> +	for (i = 0; i < ETH_PM_CNT; i++) {
> +		writel_be(0, priv->base + ETH_PML_REG(i));
> +		writel_be(0, priv->base + ETH_PMH_REG(i));
> +	}
> +
> +	/* init mii bus */
> +	ret = bcm6348_mdio_init(dev->name, priv->base);
> +	if (ret)
> +		return ret;
> +
> +	/* init phy */
> +	ret = bcm6348_phy_init(dev);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +U_BOOT_DRIVER(bcm6348_eth) = {
> +	.name = "bcm6348_eth",
> +	.id = UCLASS_ETH,
> +	.of_match = bcm6348_eth_ids,
> +	.ops = &bcm6348_eth_ops,
> +	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
> +	.priv_auto_alloc_size = sizeof(struct bcm6348_eth_priv),
> +	.probe = bcm6348_eth_probe,
> +};
> diff --git a/include/configs/bmips_common.h b/include/configs/bmips_common.h
> index 39ca2e0bf3..65aa9c77cc 100644
> --- a/include/configs/bmips_common.h
> +++ b/include/configs/bmips_common.h
> @@ -6,6 +6,9 @@
>  #ifndef __CONFIG_BMIPS_COMMON_H
>  #define __CONFIG_BMIPS_COMMON_H
>  
> +/* ETH */
> +#define CONFIG_PHY_RESET_DELAY		20
> +
>  /* UART */
>  #define CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200, \
>  					  230400, 500000, 1500000 }
> @@ -16,7 +19,7 @@
>  
>  /* Memory usage */
>  #define CONFIG_SYS_MAXARGS		24
> -#define CONFIG_SYS_MALLOC_LEN		(1024 * 1024)
> +#define CONFIG_SYS_MALLOC_LEN		(2 * 1024 * 1024)
>  #define CONFIG_SYS_BOOTPARAMS_LEN	(128 * 1024)
>  #define CONFIG_SYS_CBSIZE		512
>  
> 

-- 
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20181129/563550e3/attachment.sig>

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

* [U-Boot] [PATCH v9 18/28] net: add support for bcm6368-enet
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 18/28] net: add support for bcm6368-enet Álvaro Fernández Rojas
@ 2018-11-29  0:44       ` Daniel Schwierzeck
  0 siblings, 0 replies; 145+ messages in thread
From: Daniel Schwierzeck @ 2018-11-29  0:44 UTC (permalink / raw)
  To: u-boot



Am 28.11.18 um 19:23 schrieb Álvaro Fernández Rojas:
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> ---
>  v9: introduce flow control improvements from bcm6348-eth:
>   - introduce rx packets caching functionality from bcm6348-eth to fix flow
>    control issues.
>   - code style fixes.
>  v8: introduce bcm6368-enet driver
> 
>  drivers/net/Kconfig       |   8 +
>  drivers/net/Makefile      |   1 +
>  drivers/net/bcm6368-eth.c | 670 ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 679 insertions(+)
>  create mode 100644 drivers/net/bcm6368-eth.c
> 
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index 2b7cec8804..7044c6adf3 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -82,6 +82,14 @@ config BCM6348_ETH
>  	help
>  	  This driver supports the BCM6348 Ethernet MAC.
>  
> +config BCM6368_ETH
> +	bool "BCM6368 EMAC support"
> +	depends on DM_ETH && ARCH_BMIPS
> +	select DMA
> +	select MII
> +	help
> +	  This driver supports the BCM6368 Ethernet MAC.
> +
>  config DWC_ETH_QOS
>  	bool "Synopsys DWC Ethernet QOS device support"
>  	depends on DM_ETH
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index 2647d4dd23..0dbfa03306 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -7,6 +7,7 @@ obj-$(CONFIG_ALTERA_TSE) += altera_tse.o
>  obj-$(CONFIG_AG7XXX) += ag7xxx.o
>  obj-$(CONFIG_ARMADA100_FEC) += armada100_fec.o
>  obj-$(CONFIG_BCM6348_ETH) += bcm6348-eth.o
> +obj-$(CONFIG_BCM6368_ETH) += bcm6368-eth.o
>  obj-$(CONFIG_DRIVER_AT91EMAC) += at91_emac.o
>  obj-$(CONFIG_DRIVER_AX88180) += ax88180.o
>  obj-$(CONFIG_BCM_SF2_ETH) += bcm-sf2-eth.o
> diff --git a/drivers/net/bcm6368-eth.c b/drivers/net/bcm6368-eth.c
> new file mode 100644
> index 0000000000..f0c2ada3e2
> --- /dev/null
> +++ b/drivers/net/bcm6368-eth.c
> @@ -0,0 +1,670 @@
> +/*
> + * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
> + *
> + * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c:
> + *	Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <dma.h>
> +#include <miiphy.h>
> +#include <net.h>
> +#include <reset.h>
> +#include <wait_bit.h>
> +#include <asm/io.h>
> +
> +#define ETH_PORT_STR			"brcm,enetsw-port"
> +
> +#define ETH_RX_DESC			PKTBUFSRX
> +#define ETH_ZLEN			60
> +#define ETH_TIMEOUT			100
> +
> +#define ETH_MAX_PORT			8
> +#define ETH_RGMII_PORT0			4
> +
> +/* Port traffic control */
> +#define ETH_PTCTRL_REG(x)		(0x0 + (x))
> +#define ETH_PTCTRL_RXDIS_SHIFT		0
> +#define ETH_PTCTRL_RXDIS_MASK		(1 << ETH_PTCTRL_RXDIS_SHIFT)
> +#define ETH_PTCTRL_TXDIS_SHIFT		1
> +#define ETH_PTCTRL_TXDIS_MASK		(1 << ETH_PTCTRL_TXDIS_SHIFT)
> +
> +/* Switch mode register */
> +#define ETH_SWMODE_REG			0xb
> +#define ETH_SWMODE_FWD_EN_SHIFT		1
> +#define ETH_SWMODE_FWD_EN_MASK		(1 << ETH_SWMODE_FWD_EN_SHIFT)
> +
> +/* IMP override Register */
> +#define ETH_IMPOV_REG			0xe
> +#define ETH_IMPOV_LINKUP_SHIFT		0
> +#define ETH_IMPOV_LINKUP_MASK		(1 << ETH_IMPOV_LINKUP_SHIFT)
> +#define ETH_IMPOV_FDX_SHIFT		1
> +#define ETH_IMPOV_FDX_MASK		(1 << ETH_IMPOV_FDX_SHIFT)
> +#define ETH_IMPOV_100_SHIFT		2
> +#define ETH_IMPOV_100_MASK		(1 << ETH_IMPOV_100_SHIFT)
> +#define ETH_IMPOV_1000_SHIFT		3
> +#define ETH_IMPOV_1000_MASK		(1 << ETH_IMPOV_1000_SHIFT)
> +#define ETH_IMPOV_RXFLOW_SHIFT		4
> +#define ETH_IMPOV_RXFLOW_MASK		(1 << ETH_IMPOV_RXFLOW_SHIFT)
> +#define ETH_IMPOV_TXFLOW_SHIFT		5
> +#define ETH_IMPOV_TXFLOW_MASK		(1 << ETH_IMPOV_TXFLOW_SHIFT)
> +#define ETH_IMPOV_FORCE_SHIFT		7
> +#define ETH_IMPOV_FORCE_MASK		(1 << ETH_IMPOV_FORCE_SHIFT)
> +
> +/* Port override Register */
> +#define ETH_PORTOV_REG(x)		(0x58 + (x))
> +#define ETH_PORTOV_LINKUP_SHIFT		0
> +#define ETH_PORTOV_LINKUP_MASK		(1 << ETH_PORTOV_LINKUP_SHIFT)
> +#define ETH_PORTOV_FDX_SHIFT		1
> +#define ETH_PORTOV_FDX_MASK		(1 << ETH_PORTOV_FDX_SHIFT)
> +#define ETH_PORTOV_100_SHIFT		2
> +#define ETH_PORTOV_100_MASK		(1 << ETH_PORTOV_100_SHIFT)
> +#define ETH_PORTOV_1000_SHIFT		3
> +#define ETH_PORTOV_1000_MASK		(1 << ETH_PORTOV_1000_SHIFT)
> +#define ETH_PORTOV_RXFLOW_SHIFT		4
> +#define ETH_PORTOV_RXFLOW_MASK		(1 << ETH_PORTOV_RXFLOW_SHIFT)
> +#define ETH_PORTOV_TXFLOW_SHIFT		5
> +#define ETH_PORTOV_TXFLOW_MASK		(1 << ETH_PORTOV_TXFLOW_SHIFT)
> +#define ETH_PORTOV_ENABLE_SHIFT		6
> +#define ETH_PORTOV_ENABLE_MASK		(1 << ETH_PORTOV_ENABLE_SHIFT)
> +
> +/* Port RGMII control register */
> +#define ETH_RGMII_CTRL_REG(x)		(0x60 + (x))
> +#define ETH_RGMII_CTRL_GMII_CLK_EN	(1 << 7)
> +#define ETH_RGMII_CTRL_MII_OVERRIDE_EN	(1 << 6)
> +#define ETH_RGMII_CTRL_MII_MODE_MASK	(3 << 4)
> +#define ETH_RGMII_CTRL_RGMII_MODE	(0 << 4)
> +#define ETH_RGMII_CTRL_MII_MODE		(1 << 4)
> +#define ETH_RGMII_CTRL_RVMII_MODE	(2 << 4)
> +#define ETH_RGMII_CTRL_TIMING_SEL_EN	(1 << 0)
> +
> +/* Port RGMII timing register */
> +#define ENETSW_RGMII_TIMING_REG(x)	(0x68 + (x))
> +
> +/* MDIO control register */
> +#define MII_SC_REG			0xb0
> +#define MII_SC_EXT_SHIFT		16
> +#define MII_SC_EXT_MASK			(1 << MII_SC_EXT_SHIFT)
> +#define MII_SC_REG_SHIFT		20
> +#define MII_SC_PHYID_SHIFT		25
> +#define MII_SC_RD_SHIFT			30
> +#define MII_SC_RD_MASK			(1 << MII_SC_RD_SHIFT)
> +#define MII_SC_WR_SHIFT			31
> +#define MII_SC_WR_MASK			(1 << MII_SC_WR_SHIFT)
> +
> +/* MDIO data register */
> +#define MII_DAT_REG			0xb4
> +
> +/* MDIO 1000BASE-T control/status */
> +#define MII_ADVERTISE_1000		(ADVERTISE_1000HALF |\
> +					 ADVERTISE_1000FULL)
> +#define MII_LPA_1000			(LPA_1000HALF | LPA_1000FULL)
> +
> +/* Global Management Configuration Register */
> +#define ETH_GMCR_REG			0x200
> +#define ETH_GMCR_RST_MIB_SHIFT		0
> +#define ETH_GMCR_RST_MIB_MASK		(1 << ETH_GMCR_RST_MIB_SHIFT)
> +
> +/* Jumbo control register port mask register */
> +#define ETH_JMBCTL_PORT_REG		0x4004
> +
> +/* Jumbo control mib good frame register */
> +#define ETH_JMBCTL_MAXSIZE_REG		0x4008
> +
> +/* ETH port data */
> +struct bcm_enetsw_port {
> +	bool used;
> +	const char *name;
> +	/* Config */
> +	bool bypass_link;
> +	int force_speed;
> +	bool force_duplex_full;
> +	/* PHY */
> +	int phy_id;
> +};
> +
> +/* ETH data */
> +struct bcm6368_eth_priv {
> +	struct udevice *dev;
> +	void __iomem *base;
> +	/* RX */
> +	uint8_t rx_desc;
> +	uint8_t rx_pend;
> +	int rx_ret[ETH_RX_DESC];
> +	/* DMA */
> +	struct dma rx_dma;
> +	struct dma tx_dma;
> +	/* Ports */
> +	uint8_t num_ports;
> +	struct bcm_enetsw_port used_ports[ETH_MAX_PORT];
> +	int sw_port_link[ETH_MAX_PORT];
> +	bool rgmii_override;
> +	bool rgmii_timing;
> +	/* PHY */
> +	int phy_id;
> +};
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +static inline bool bcm_enet_port_is_rgmii(int portid)
> +{
> +	return portid >= ETH_RGMII_PORT0;
> +}
> +
> +static int bcm6368_mdio_read(struct bcm6368_eth_priv *priv, uint8_t ext,
> +			     int phy_id, int reg)
> +{
> +	uint32_t val;
> +
> +	writel_be(0, priv->base + MII_SC_REG);
> +
> +	val = MII_SC_RD_MASK |
> +	      (phy_id << MII_SC_PHYID_SHIFT) |
> +	      (reg << MII_SC_REG_SHIFT);
> +
> +	if (ext)
> +		val |= MII_SC_EXT_MASK;
> +
> +	writel_be(val, priv->base + MII_SC_REG);
> +	udelay(50);
> +
> +	return readw_be(priv->base + MII_DAT_REG);
> +}
> +
> +static int bcm6368_mdio_write(struct bcm6368_eth_priv *priv, uint8_t ext,
> +			      int phy_id, int reg, u16 data)
> +{
> +	uint32_t val;
> +
> +	writel_be(0, priv->base + MII_SC_REG);
> +
> +	val = MII_SC_WR_MASK |
> +	      (phy_id << MII_SC_PHYID_SHIFT) |
> +	      (reg << MII_SC_REG_SHIFT);
> +
> +	if (ext)
> +		val |= MII_SC_EXT_MASK;
> +
> +	val |= data;
> +
> +	writel_be(val, priv->base + MII_SC_REG);
> +	udelay(50);
> +
> +	return 0;
> +}
> +
> +static int bcm6368_eth_free_pkt(struct udevice *dev, uchar *packet, int len)
> +{
> +	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
> +
> +	/* sanity check */
> +	if (packet != net_rx_packets[priv->rx_pend]) {
> +		pr_err("rx_pend %d: packet is not matched,\n", priv->rx_pend);
> +		return -EAGAIN;
> +	}
> +
> +	/* free pending packet */
> +	priv->rx_ret[priv->rx_pend] = 0;
> +	priv->rx_pend = (priv->rx_pend + 1) % ETH_RX_DESC;
> +
> +	return 0;
> +}
> +
> +static int _bcm6368_eth_recv(struct bcm6368_eth_priv *priv)
> +{
> +	uint8_t pkt = priv->rx_desc;
> +
> +	/* check if packet is free */
> +	if (priv->rx_ret[pkt] > 0)
> +		return -EAGAIN;
> +
> +	/* try to receive a new packet */
> +	priv->rx_ret[pkt] = dma_receive(&priv->rx_dma,
> +					(void **)&net_rx_packets[pkt],
> +					NULL);
> +	if (priv->rx_ret[pkt] > 0)
> +		priv->rx_desc = (priv->rx_desc + 1) % ETH_RX_DESC;
> +
> +	return priv->rx_ret[pkt];
> +}
> +
> +static int bcm6368_eth_recv(struct udevice *dev, int flags, uchar **packetp)
> +{
> +	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
> +
> +	/* receive packets if queue is empty */
> +	if (priv->rx_ret[priv->rx_pend] <= 0) {
> +		uint8_t pkt_cnt = 0;
> +
> +		/* try to receive packets */
> +		while (_bcm6368_eth_recv(priv) > 0)
> +			pkt_cnt++;
> +
> +		dma_prepare_rcv_buf(&priv->rx_dma, NULL, 0);

I forgot to mention this in your other ethernet driver but why do you
have your own packet queue? eth_recv() is supposed to receive one packet
from HW or return -EAGAIN. Also I think dma_prepare_rcv_buf should go to
eth_free_pkt() and pass net_rx_packets[]. eth_recv should only call
dma_receive() to check if packets are available.

> +
> +		if (pkt_cnt)
> +			debug("%s: received %u packet(s)\n", __func__, pkt_cnt);
> +	}
> +
> +	/* return current packet */
> +	if (priv->rx_ret[priv->rx_pend] > 0)
> +		*packetp = net_rx_packets[priv->rx_pend];
> +
> +	return priv->rx_ret[priv->rx_pend];
> +}
> +
> +static int bcm6368_eth_send(struct udevice *dev, void *packet, int length)
> +{
> +	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
> +
> +	length = max(length, ETH_ZLEN);
> +
> +	return dma_send(&priv->tx_dma, packet, length, NULL);

does the HW do the actual padding? Otherwise you should set the padding
bytes to zero to avoid sending random memory content on the wire.

> +}
> +
> +static int bcm6368_eth_adjust_link(struct bcm6368_eth_priv *priv)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < priv->num_ports; i++) {
> +		struct bcm_enetsw_port *port;
> +		int val, j, up, advertise, lpa, speed, duplex, media;
> +		int external_phy = bcm_enet_port_is_rgmii(i);
> +		u8 override;
> +
> +		port = &priv->used_ports[i];
> +		if (!port->used)
> +			continue;
> +
> +		if (port->bypass_link)
> +			continue;
> +
> +		/* dummy read to clear */
> +		for (j = 0; j < 2; j++)
> +			val = bcm6368_mdio_read(priv, external_phy,
> +						port->phy_id, MII_BMSR);
> +
> +		if (val == 0xffff)
> +			continue;
> +
> +		up = (val & BMSR_LSTATUS) ? 1 : 0;
> +		if (!(up ^ priv->sw_port_link[i]))
> +			continue;
> +
> +		priv->sw_port_link[i] = up;
> +
> +		/* link changed */
> +		if (!up) {
> +			dev_info(&priv->pdev->dev, "link DOWN on %s\n",
> +				 port->name);
> +			writeb_be(ETH_PORTOV_ENABLE_MASK,
> +				  priv->base + ETH_PORTOV_REG(i));
> +			writeb_be(ETH_PTCTRL_RXDIS_MASK |
> +				  ETH_PTCTRL_TXDIS_MASK,
> +				  priv->base + ETH_PTCTRL_REG(i));
> +			continue;
> +		}
> +
> +		advertise = bcm6368_mdio_read(priv, external_phy, port->phy_id,
> +					      MII_ADVERTISE);
> +
> +		lpa = bcm6368_mdio_read(priv, external_phy, port->phy_id,
> +					MII_LPA);
> +
> +		/* figure out media and duplex from advertise and LPA values */
> +		media = mii_nway_result(lpa & advertise);
> +		duplex = (media & ADVERTISE_FULL) ? 1 : 0;
> +
> +		if (media & (ADVERTISE_100FULL | ADVERTISE_100HALF))
> +			speed = 100;
> +		else
> +			speed = 10;
> +
> +		if (val & BMSR_ESTATEN) {
> +			advertise = bcm6368_mdio_read(priv, external_phy,
> +						port->phy_id, MII_CTRL1000);
> +
> +			lpa = bcm6368_mdio_read(priv, external_phy,
> +						port->phy_id, MII_STAT1000);
> +
> +			if ((advertise & MII_ADVERTISE_1000) &&
> +			    (lpa & MII_LPA_1000)) {
> +				speed = 1000;
> +				duplex = (lpa & LPA_1000FULL);
> +			}
> +		}
> +
> +		pr_alert("link UP on %s, %dMbps, %s-duplex\n",
> +			 port->name, speed, duplex ? "full" : "half");
> +
> +		override = ETH_PORTOV_ENABLE_MASK |
> +			   ETH_PORTOV_LINKUP_MASK;
> +
> +		if (speed == 1000)
> +			override |= ETH_PORTOV_1000_MASK;
> +		else if (speed == 100)
> +			override |= ETH_PORTOV_100_MASK;
> +		if (duplex)
> +			override |= ETH_PORTOV_FDX_MASK;
> +
> +		writeb_be(override, priv->base + ETH_PORTOV_REG(i));
> +		writeb_be(0, priv->base + ETH_PTCTRL_REG(i));
> +	}
> +
> +	return 0;
> +}
> +
> +static int bcm6368_eth_start(struct udevice *dev)
> +{
> +	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
> +	int i;
> +	u32 val;
> +
> +	priv->rx_desc = 0;
> +	priv->rx_pend = 0;
> +	for (i = 0; i < ETH_RX_DESC; i++)
> +		priv->rx_ret[i] = 0;
> +
> +	/* disable all ports */
> +	for (i = 0; i < priv->num_ports; i++) {
> +		writeb_be(ETH_PORTOV_ENABLE_MASK,
> +			  priv->base + ETH_PORTOV_REG(i));
> +		writeb_be(ETH_PTCTRL_RXDIS_MASK |
> +			  ETH_PTCTRL_TXDIS_MASK,
> +			  priv->base + ETH_PTCTRL_REG(i));
> +
> +		priv->sw_port_link[i] = 0;
> +	}
> +
> +	/* enable external ports */
> +	for (i = ETH_RGMII_PORT0; i < priv->num_ports; i++) {
> +		u8 rgmii_ctrl;
> +
> +		if (!priv->used_ports[i].used)
> +			continue;
> +
> +		rgmii_ctrl = readb_be(priv->base + ETH_RGMII_CTRL_REG(i));
> +		rgmii_ctrl |= ETH_RGMII_CTRL_GMII_CLK_EN;
> +		if (priv->rgmii_override)
> +			rgmii_ctrl |= ETH_RGMII_CTRL_MII_OVERRIDE_EN;
> +		if (priv->rgmii_timing)
> +			rgmii_ctrl |= ETH_RGMII_CTRL_TIMING_SEL_EN;
> +		writeb_be(rgmii_ctrl, priv->base + ETH_RGMII_CTRL_REG(i));
> +	}
> +
> +	/* reset mib */
> +	val = readb_be(priv->base + ETH_GMCR_REG);
> +	val |= ETH_GMCR_RST_MIB_MASK;
> +	writeb_be(val, priv->base + ETH_GMCR_REG);
> +	mdelay(1);
> +	val &= ~ETH_GMCR_RST_MIB_MASK;
> +	writeb_be(val, priv->base + ETH_GMCR_REG);
> +	mdelay(1);
> +
> +	/* force CPU port state */
> +	val = readb_be(priv->base + ETH_IMPOV_REG);
> +	val |= ETH_IMPOV_FORCE_MASK | ETH_IMPOV_LINKUP_MASK;
> +	writeb_be(val, priv->base + ETH_IMPOV_REG);
> +
> +	/* enable switch forward engine */
> +	val = readb_be(priv->base + ETH_SWMODE_REG);
> +	val |= ETH_SWMODE_FWD_EN_MASK;
> +	writeb_be(val, priv->base + ETH_SWMODE_REG);
> +
> +	/* enable jumbo on all ports */
> +	writel_be(0x1ff, priv->base + ETH_JMBCTL_PORT_REG);
> +	writew_be(9728, priv->base + ETH_JMBCTL_MAXSIZE_REG);
> +
> +	/* enable dma rx channel */
> +	dma_enable(&priv->rx_dma);
> +
> +	/* enable dma tx channel */
> +	dma_enable(&priv->tx_dma);
> +
> +	/* apply override config for bypass_link ports here. */
> +	for (i = 0; i < priv->num_ports; i++) {
> +		struct bcm_enetsw_port *port;
> +		u8 override;
> +		port = &priv->used_ports[i];
> +		if (!port->used)
> +			continue;
> +
> +		if (!port->bypass_link)
> +			continue;
> +
> +		override = ETH_PORTOV_ENABLE_MASK |
> +			ETH_PORTOV_LINKUP_MASK;
> +
> +		switch (port->force_speed) {
> +		case 1000:
> +			override |= ETH_PORTOV_1000_MASK;
> +			break;
> +		case 100:
> +			override |= ETH_PORTOV_100_MASK;
> +			break;
> +		case 10:
> +			break;
> +		default:
> +			pr_warn("invalid forced speed on port %s: assume 10\n",
> +				port->name);
> +			break;
> +		}
> +
> +		if (port->force_duplex_full)
> +			override |= ETH_PORTOV_FDX_MASK;
> +
> +		writeb_be(override, priv->base + ETH_PORTOV_REG(i));
> +		writeb_be(0, priv->base + ETH_PTCTRL_REG(i));
> +	}
> +
> +	bcm6368_eth_adjust_link(priv);
> +
> +	return 0;
> +}
> +
> +static void bcm6368_eth_stop(struct udevice *dev)
> +{
> +	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
> +
> +	/* disable dma rx channel */
> +	dma_disable(&priv->rx_dma);
> +
> +	/* disable dma tx channel */
> +	dma_disable(&priv->tx_dma);
> +}
> +
> +static const struct eth_ops bcm6368_eth_ops = {
> +	.free_pkt = bcm6368_eth_free_pkt,
> +	.recv = bcm6368_eth_recv,
> +	.send = bcm6368_eth_send,
> +	.start = bcm6368_eth_start,
> +	.stop = bcm6368_eth_stop,
> +};
> +
> +static const struct udevice_id bcm6368_eth_ids[] = {
> +	{ .compatible = "brcm,bcm6368-enet", },
> +	{ /* sentinel */ }
> +};
> +
> +static bool bcm6368_phy_is_external(struct bcm6368_eth_priv *priv,
> +				       int phy_id)
> +{
> +	uint8_t i;
> +
> +	for (i = 0; i < priv->num_ports; ++i) {
> +		if (!priv->used_ports[i].used)
> +			continue;
> +		if (priv->used_ports[i].phy_id == phy_id)
> +			return bcm_enet_port_is_rgmii(i);
> +	}
> +
> +	return true;
> +}
> +
> +static int bcm6368_mii_mdio_read(struct mii_dev *bus, int addr, int devaddr,
> +				 int reg)
> +{
> +	struct bcm6368_eth_priv *priv = bus->priv;
> +	bool ext = bcm6368_phy_is_external(priv, addr);
> +
> +	return bcm6368_mdio_read(priv, ext, addr, reg);
> +}
> +
> +static int bcm6368_mii_mdio_write(struct mii_dev *bus, int addr, int devaddr,
> +				  int reg, u16 data)
> +{
> +	struct bcm6368_eth_priv *priv = bus->priv;
> +	bool ext = bcm6368_phy_is_external(priv, addr);
> +
> +	return bcm6368_mdio_write(priv, ext, addr, reg, data);
> +}
> +
> +static int bcm6368_mdio_init(const char *name, struct bcm6368_eth_priv *priv)
> +{
> +	struct mii_dev *bus;
> +
> +	bus = mdio_alloc();
> +	if (!bus) {
> +		pr_err("%s: failed to allocate MDIO bus\n", __func__);
> +		return -ENOMEM;
> +	}
> +
> +	bus->read = bcm6368_mii_mdio_read;
> +	bus->write = bcm6368_mii_mdio_write;
> +	bus->priv = priv;
> +	snprintf(bus->name, sizeof(bus->name), "%s", name);
> +
> +	return mdio_register(bus);
> +}
> +
> +static int bcm6368_eth_probe(struct udevice *dev)
> +{
> +	struct eth_pdata *pdata = dev_get_platdata(dev);
> +	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
> +	void *blob = (void *)gd->fdt_blob;
> +	fdt_addr_t addr;
> +	int node = dev_of_offset(dev);
> +	int ret, i;
> +	unsigned int num_ports;
> +
> +	/* get base address */
> +	addr = devfdt_get_addr(dev);
> +	if (addr == FDT_ADDR_T_NONE)
> +		return -EINVAL;

dev_remap_addr() ?

> +
> +	/* get number of ports */
> +	num_ports = fdtdec_get_uint(gd->fdt_blob, node, "brcm,num-ports",
> +				    ETH_MAX_PORT);
> +	if (!num_ports || num_ports > ETH_MAX_PORT)
> +		return -EINVAL;

dev_read_u32() ?

> +
> +	/* get dma channels */
> +	ret = dma_get_by_name(dev, "tx", &priv->tx_dma);
> +	if (ret)
> +		return -EINVAL;
> +
> +	ret = dma_get_by_name(dev, "rx", &priv->rx_dma);
> +	if (ret)
> +		return -EINVAL;
> +
> +	/* try to enable clocks */
> +	for (i = 0; ; i++) {
> +		struct clk clk;
> +		int ret;
> +
> +		ret = clk_get_by_index(dev, i, &clk);
> +		if (ret < 0)
> +			break;
> +		if (clk_enable(&clk))
> +			pr_err("failed to enable clock %d\n", i);
> +		clk_free(&clk);
> +	}
> +
> +	/* try to perform resets */
> +	for (i = 0; ; i++) {
> +		struct reset_ctl reset;
> +		int ret;
> +
> +		ret = reset_get_by_index(dev, i, &reset);
> +		if (ret < 0)
> +			break;
> +		if (reset_deassert(&reset))
> +			pr_err("failed to deassert reset %d\n", i);
> +		reset_free(&reset);
> +	}
> +
> +	/* set priv data */
> +	priv->dev = dev;
> +
> +	priv->base = ioremap(addr, 0);
> +	pdata->iobase = (phys_addr_t) priv->base;
> +
> +	priv->num_ports = num_ports;
> +
> +	if (fdtdec_get_bool(gd->fdt_blob, i, "brcm,rgmii-override"))
> +		priv->rgmii_override = true;
> +	if (fdtdec_get_bool(gd->fdt_blob, i, "brcm,rgmii-timing"))
> +		priv->rgmii_timing = true;

dev_read_bool() ?

> +
> +	/* get ports */
> +	for (i = fdt_first_subnode(blob, node);
> +	     i > 0;
> +	     i = fdt_next_subnode(blob, i)) {

dev_read_first_subnode(), dev_read_next_subnode() and dev_read_*() in
the loop body?

> +		const char *comp;
> +		const char *label;
> +		unsigned int p;
> +		int phy_id;
> +		int speed;
> +
> +		comp = fdt_getprop(blob, i, "compatible", NULL);
> +		if (!comp || memcmp(comp, ETH_PORT_STR, sizeof(ETH_PORT_STR)))
> +			continue;
> +
> +		p = fdtdec_get_uint(gd->fdt_blob, i, "reg",
> +				      ETH_MAX_PORT);
> +		if (p >= num_ports)
> +			return -EINVAL;
> +
> +		label = fdt_getprop(blob, i, "label", NULL);
> +		if (!label) {
> +			debug("%s: node %s has no label\n", __func__,
> +			      fdt_get_name(blob, i, NULL));
> +			return -EINVAL;
> +		}
> +
> +		phy_id = fdtdec_get_int(gd->fdt_blob, i, "brcm,phy-id", -1);
> +
> +		priv->used_ports[p].used = true;
> +		priv->used_ports[p].name = label;
> +		priv->used_ports[p].phy_id = phy_id;
> +
> +		if (fdtdec_get_bool(gd->fdt_blob, i, "full-duplex"))
> +			priv->used_ports[p].force_duplex_full = true;
> +		if (fdtdec_get_bool(gd->fdt_blob, i, "bypass-link"))
> +			priv->used_ports[p].bypass_link = true;
> +		speed = fdtdec_get_int(gd->fdt_blob, i, "speed", 0);
> +		if (speed)
> +			priv->used_ports[p].force_speed = speed;
> +	}
> +
> +	/* init mii bus */
> +	ret = bcm6368_mdio_init(dev->name, priv);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +U_BOOT_DRIVER(bcm6368_eth) = {
> +	.name = "bcm6368_eth",
> +	.id = UCLASS_ETH,
> +	.of_match = bcm6368_eth_ids,
> +	.ops = &bcm6368_eth_ops,
> +	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
> +	.priv_auto_alloc_size = sizeof(struct bcm6368_eth_priv),
> +	.probe = bcm6368_eth_probe,
> +};
> 

-- 
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20181129/09cfab10/attachment.sig>

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

* [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support
  2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                       ` (27 preceding siblings ...)
  2018-11-28 18:23     ` [U-Boot] [PATCH v9 28/28] bmips: enable ar-5315u enet support Álvaro Fernández Rojas
@ 2018-11-29 22:25     ` Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 01/28] dma: add bcm6348-iudma support Álvaro Fernández Rojas
                         ` (28 more replies)
  28 siblings, 29 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

In order to add bcm6348-enet support, dma-uclass must be extended to support
dma channels and reworked to operate like the other dm uclass (clk, reset...).

v10: Introduce changes suggested by Daniel Schwierzeck:
 - Fix license identifiers.
 bcm6348-iudma:
  - Move DMAD_ST defines out of dma desc struct definition.
  - Remove unneded aigned attribute from dma desc struct definition.
  - Fill dma ring from consumer driver instead of allocating a new buffer.
  - Correctly check clock/reset errors while probing.
  - Switch to live DM live tree.
 bcm6348-enet:
  - Remove packet queue.
  - Move dma_prepare_rcv_buf to free_pkt.
  - Switch to live DM live tree.
 bcm6368-enet:
  - Remove packet queue.
  - Move dma_prepare_rcv_buf to free_pkt.
  - Pad packets smaller than ETH_ZLEN.
  - Switch to live DM live tree.
v9: Separate generic dma channels support from bmips enet support
 bcm6348-iudma:
  - bcm6348_iudma_chan_stop: switch to mdelay when resetting channel.
  - bcm6348_iudma_receive: track dirty dma descriptors and no longer trigger
   dma rx channel.
  - bcm6348_iudma_send: reorder to properly flush cache and set dma descriptor
   config.
  - bcm6348_iudma_prepare_rcv_buf: implemented to clear dirty dma descriptors.
 bcm6348-enet:
  - bcm6348_eth_recv: clear dirty dma descriptors only when packets are copied
   from rx dma.
  - bcm6348_eth_send: remove dma rx channel reset when sending packet.
 bcm6368-enet:
  - introduce rx packets caching functionality from bcm6348-eth to fix flow
   control issues.
  - code style fixes.
v8: Introduce bcm6368-enet driver support.
v5: Fix issues reported by Grygorii Strashko and other fixes:
 - Remove unused bcm6348-iudma defines.
 - Increment bcm6348-iudma rx descriptors.
 - Fix bcm6348-iudma flow control issues.
 - bcm6348-iudma error checking now depends on hw.
 - Remove unneeded bcm6348-iudma interrupts.
 - Receive as much packets as possible from bcm6348-eth and cache them in
 net_rx_packets. This is needed in order to fix flow control issues.
v4: Fix issues reported by Grygorii Strashko and other fixes:
 - Remove usage of net_rx_packets as buffer from bcm6348-iudma.
 - Allocate dynamic rx buffer on bcm6348-iudma.
 - Copy received dma buffer to net_rx_packets in order to avoid possible
 dma overwrites.
 - Check dma errors and discard invalid packets.
 - Reset dma rx channel when sending a new packet to prevent flow control
 issues.
 - Fix packet casting on bcm6348_eth_recv/send.
v3: Switch to live tree API.
v2: Fix bcm6348-iudma rx burst config.

Álvaro Fernández Rojas (28):
  dma: add bcm6348-iudma support
  bmips: bcm6338: add bcm6348-iudma support
  bmips: bcm6348: add bcm6348-iudma support
  bmips: bcm6358: add bcm6348-iudma support
  bmips: bcm6368: add bcm6348-iudma support
  bmips: bcm6328: add bcm6348-iudma support
  bmips: bcm6362: add bcm6348-iudma support
  bmips: bcm63268: add bcm6348-iudma support
  bmips: bcm6318: add bcm6348-iudma support
  net: add support for bcm6348-enet
  bmips: bcm6338: add support for bcm6348-enet
  bmips: enable f at st1704 enet support
  bmips: bcm6348: add support for bcm6348-enet
  bmips: enable ct-5361 enet support
  bmips: bcm6358: add support for bcm6348-enet
  bmips: enable hg556a enet support
  bmips: enable nb4-ser enet support
  net: add support for bcm6368-enet
  bmips: bcm6368: add support for bcm6368-enet
  bmips: enable wap-5813n enet support
  bmips: bcm6328: add support for bcm6368-enet
  bmips: enable ar-5387un enet support
  bmips: bcm6362: add support for bcm6368-enet
  bmips: enable dgnd3700v2 enet support
  bmips: bcm63268: add support for bcm6368-enet
  bmips: enable vr-3032u enet support
  bmips: bcm6318: add support for bcm6368-enet
  bmips: enable ar-5315u enet support

 arch/mips/dts/brcm,bcm6318.dtsi           |  38 ++
 arch/mips/dts/brcm,bcm63268.dtsi          |  38 ++
 arch/mips/dts/brcm,bcm6328.dtsi           |  30 ++
 arch/mips/dts/brcm,bcm6338.dtsi           |  29 ++
 arch/mips/dts/brcm,bcm6348.dtsi           |  42 ++
 arch/mips/dts/brcm,bcm6358.dtsi           |  46 +++
 arch/mips/dts/brcm,bcm6362.dtsi           |  32 ++
 arch/mips/dts/brcm,bcm6368.dtsi           |  32 ++
 arch/mips/dts/comtrend,ar-5315u.dts       |  32 ++
 arch/mips/dts/comtrend,ar-5387un.dts      |  32 ++
 arch/mips/dts/comtrend,ct-5361.dts        |  12 +
 arch/mips/dts/comtrend,vr-3032u.dts       |  32 ++
 arch/mips/dts/comtrend,wap-5813n.dts      |  14 +
 arch/mips/dts/huawei,hg556a.dts           |  12 +
 arch/mips/dts/netgear,dgnd3700v2.dts      |  14 +
 arch/mips/dts/sagem,f at st1704.dts          |  12 +
 arch/mips/dts/sfr,nb4-ser.dts             |  24 ++
 configs/comtrend_ar5315u_ram_defconfig    |   7 +-
 configs/comtrend_ar5387un_ram_defconfig   |   7 +-
 configs/comtrend_ct5361_ram_defconfig     |   8 +-
 configs/comtrend_vr3032u_ram_defconfig    |   7 +-
 configs/comtrend_wap5813n_ram_defconfig   |   8 +-
 configs/huawei_hg556a_ram_defconfig       |   8 +-
 configs/netgear_dgnd3700v2_ram_defconfig  |   8 +-
 configs/sagem_f at st1704_ram_defconfig      |   8 +-
 configs/sfr_nb4-ser_ram_defconfig         |   8 +-
 drivers/dma/Kconfig                       |   9 +
 drivers/dma/Makefile                      |   1 +
 drivers/dma/bcm6348-iudma.c               | 642 ++++++++++++++++++++++++++++++
 drivers/net/Kconfig                       |  18 +
 drivers/net/Makefile                      |   2 +
 drivers/net/bcm6348-eth.c                 | 537 +++++++++++++++++++++++++
 drivers/net/bcm6368-eth.c                 | 625 +++++++++++++++++++++++++++++
 include/configs/bmips_common.h            |   6 +-
 include/dt-bindings/clock/bcm6318-clock.h |  11 +
 include/dt-bindings/dma/bcm6318-dma.h     |  14 +
 include/dt-bindings/dma/bcm63268-dma.h    |  14 +
 include/dt-bindings/dma/bcm6328-dma.h     |  14 +
 include/dt-bindings/dma/bcm6338-dma.h     |  14 +
 include/dt-bindings/dma/bcm6348-dma.h     |  16 +
 include/dt-bindings/dma/bcm6358-dma.h     |  16 +
 include/dt-bindings/dma/bcm6362-dma.h     |  14 +
 include/dt-bindings/dma/bcm6368-dma.h     |  14 +
 43 files changed, 2497 insertions(+), 10 deletions(-)
 create mode 100644 drivers/dma/bcm6348-iudma.c
 create mode 100644 drivers/net/bcm6348-eth.c
 create mode 100644 drivers/net/bcm6368-eth.c
 create mode 100644 include/dt-bindings/dma/bcm6318-dma.h
 create mode 100644 include/dt-bindings/dma/bcm63268-dma.h
 create mode 100644 include/dt-bindings/dma/bcm6328-dma.h
 create mode 100644 include/dt-bindings/dma/bcm6338-dma.h
 create mode 100644 include/dt-bindings/dma/bcm6348-dma.h
 create mode 100644 include/dt-bindings/dma/bcm6358-dma.h
 create mode 100644 include/dt-bindings/dma/bcm6362-dma.h
 create mode 100644 include/dt-bindings/dma/bcm6368-dma.h

-- 
2.11.0

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

* [U-Boot] [PATCH v10 01/28] dma: add bcm6348-iudma support
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-30 13:46         ` Daniel Schwierzeck
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 02/28] bmips: bcm6338: " Álvaro Fernández Rojas
                         ` (27 subsequent siblings)
  28 siblings, 1 reply; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

BCM6348 IUDMA controller is present on multiple BMIPS (BCM63xx) SoCs.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: Introduce changes suggested by Daniel Schwierzeck:
  - Fix license identifiers.
  - Move DMAD_ST defines out of dma desc struct definition.
  - Remove unneded aigned attribute from dma desc struct definition.
  - Fill dma ring from consumer driver instead of allocating a new buffer.
  - Correctly check clock/reset errors while probing.
  - Switch to live DM live tree.
 v9: introduce dma_prepare_rcv_buf dma op:
  - bcm6348_iudma_chan_stop: switch to mdelay when resetting channel.
  - bcm6348_iudma_receive: track dirty dma descriptors and no longer trigger
   dma rx channel.
  - bcm6348_iudma_send: reorder to properly flush cache and set dma descriptor
   config.
  - bcm6348_iudma_prepare_rcv_buf: implemented to clear dirty dma descriptors.
 v8: Introduce changes from Grygorii Strashko
 v5: Several fixes and improvements:
  - Remove unused defines.
  - Increment rx descriptors.
  - Fix flow control issues.
  - Error checking now depends on hw.
  - Remove unneeded interrupts.
 v4: Fix issues reported by Grygorii Strashko and other fixes:
  - Remove usage of net_rx_packets as buffer.
  - Allocate dynamic rx buffer.
  - Check dma errors and discard invalid packets.
 v3: no changes
 v2: Fix dma rx burst config and select DMA_CHANNELS.

 drivers/dma/Kconfig         |   9 +
 drivers/dma/Makefile        |   1 +
 drivers/dma/bcm6348-iudma.c | 642 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 652 insertions(+)
 create mode 100644 drivers/dma/bcm6348-iudma.c

diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 8a4162eccd..1820676d7a 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -26,6 +26,15 @@ config SANDBOX_DMA
 	  Enable support for a test DMA uclass implementation. It stimulates
 	  DMA transfer by simple copying data between channels.
 
+config BCM6348_IUDMA
+	bool "BCM6348 IUDMA driver"
+	depends on ARCH_BMIPS
+	select DMA_CHANNELS
+	help
+	  Enable the BCM6348 IUDMA driver.
+	  This driver support data transfer from devices to
+	  memory and from memory to devices.
+
 config TI_EDMA3
 	bool "TI EDMA3 driver"
 	help
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index aff31f986a..b5f9147e0a 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_DMA) += dma-uclass.o
 
 obj-$(CONFIG_FSLDMAFEC) += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o
 obj-$(CONFIG_APBH_DMA) += apbh_dma.o
+obj-$(CONFIG_BCM6348_IUDMA) += bcm6348-iudma.o
 obj-$(CONFIG_FSL_DMA) += fsl_dma.o
 obj-$(CONFIG_SANDBOX_DMA) += sandbox-dma-test.o
 obj-$(CONFIG_TI_KSNAV) += keystone_nav.o keystone_nav_cfg.o
diff --git a/drivers/dma/bcm6348-iudma.c b/drivers/dma/bcm6348-iudma.c
new file mode 100644
index 0000000000..699f1a6754
--- /dev/null
+++ b/drivers/dma/bcm6348-iudma.c
@@ -0,0 +1,642 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/dma/bcm63xx-iudma.c:
+ *	Copyright (C) 2015 Simon Arlott <simon@fire.lp0.eu>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c:
+ *	Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ *
+ * Derived from bcm963xx_4.12L.06B_consumer/shared/opensource/include/bcm963xx/63268_map_part.h:
+ *	Copyright (C) 2000-2010 Broadcom Corporation
+ *
+ * Derived from bcm963xx_4.12L.06B_consumer/bcmdrivers/opensource/net/enet/impl4/bcmenet.c:
+ *	Copyright (C) 2010 Broadcom Corporation
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dma-uclass.h>
+#include <memalign.h>
+#include <reset.h>
+#include <asm/io.h>
+
+#define DMA_RX_DESC	6
+#define DMA_TX_DESC	1
+
+/* DMA Channels */
+#define DMA_CHAN_FLOWC(x)		((x) >> 1)
+#define DMA_CHAN_MAX			16
+#define DMA_CHAN_SIZE			0x10
+#define DMA_CHAN_TOUT			500
+
+/* DMA Global Configuration register */
+#define DMA_CFG_REG			0x00
+#define  DMA_CFG_ENABLE_SHIFT		0
+#define  DMA_CFG_ENABLE_MASK		(1 << DMA_CFG_ENABLE_SHIFT)
+#define  DMA_CFG_FLOWC_ENABLE(x)	BIT(DMA_CHAN_FLOWC(x) + 1)
+#define  DMA_CFG_NCHANS_SHIFT		24
+#define  DMA_CFG_NCHANS_MASK		(0xf << DMA_CFG_NCHANS_SHIFT)
+
+/* DMA Global Flow Control registers */
+#define DMA_FLOWC_THR_LO_REG(x)		(0x04 + DMA_CHAN_FLOWC(x) * 0x0c)
+#define DMA_FLOWC_THR_HI_REG(x)		(0x08 + DMA_CHAN_FLOWC(x) * 0x0c)
+#define DMA_FLOWC_ALLOC_REG(x)		(0x0c + DMA_CHAN_FLOWC(x) * 0x0c)
+#define  DMA_FLOWC_ALLOC_FORCE_SHIFT	31
+#define  DMA_FLOWC_ALLOC_FORCE_MASK	(1 << DMA_FLOWC_ALLOC_FORCE_SHIFT)
+
+/* DMA Global Reset register */
+#define DMA_RST_REG			0x34
+#define  DMA_RST_CHAN_SHIFT		0
+#define  DMA_RST_CHAN_MASK(x)		(1 << x)
+
+/* DMA Channel Configuration register */
+#define DMAC_CFG_REG(x)			(DMA_CHAN_SIZE * (x) + 0x00)
+#define  DMAC_CFG_ENABLE_SHIFT		0
+#define  DMAC_CFG_ENABLE_MASK		(1 << DMAC_CFG_ENABLE_SHIFT)
+#define  DMAC_CFG_PKT_HALT_SHIFT	1
+#define  DMAC_CFG_PKT_HALT_MASK		(1 << DMAC_CFG_PKT_HALT_SHIFT)
+#define  DMAC_CFG_BRST_HALT_SHIFT	2
+#define  DMAC_CFG_BRST_HALT_MASK	(1 << DMAC_CFG_BRST_HALT_SHIFT)
+
+/* DMA Channel Max Burst Length register */
+#define DMAC_BURST_REG(x)		(DMA_CHAN_SIZE * (x) + 0x0c)
+
+/* DMA SRAM Descriptor Ring Start register */
+#define DMAS_RSTART_REG(x)		(DMA_CHAN_SIZE * (x) + 0x00)
+
+/* DMA SRAM State/Bytes done/ring offset register */
+#define DMAS_STATE_DATA_REG(x)		(DMA_CHAN_SIZE * (x) + 0x04)
+
+/* DMA SRAM Buffer Descriptor status and length register */
+#define DMAS_DESC_LEN_STATUS_REG(x)	(DMA_CHAN_SIZE * (x) + 0x08)
+
+/* DMA SRAM Buffer Descriptor status and length register */
+#define DMAS_DESC_BASE_BUFPTR_REG(x)	(DMA_CHAN_SIZE * (x) + 0x0c)
+
+/* DMA Descriptor Status */
+#define DMAD_ST_CRC_SHIFT		8
+#define DMAD_ST_CRC_MASK		(1 << DMAD_ST_CRC_SHIFT)
+#define DMAD_ST_WRAP_SHIFT		12
+#define DMAD_ST_WRAP_MASK		(1 << DMAD_ST_WRAP_SHIFT)
+#define DMAD_ST_SOP_SHIFT		13
+#define DMAD_ST_SOP_MASK		(1 << DMAD_ST_SOP_SHIFT)
+#define DMAD_ST_EOP_SHIFT		14
+#define DMAD_ST_EOP_MASK		(1 << DMAD_ST_EOP_SHIFT)
+#define DMAD_ST_OWN_SHIFT		15
+#define DMAD_ST_OWN_MASK		(1 << DMAD_ST_OWN_SHIFT)
+
+#define DMAD6348_ST_OV_ERR_SHIFT	0
+#define DMAD6348_ST_OV_ERR_MASK		(1 << DMAD6348_ST_OV_ERR_SHIFT)
+#define DMAD6348_ST_CRC_ERR_SHIFT	1
+#define DMAD6348_ST_CRC_ERR_MASK	(1 << DMAD6348_ST_CRC_ERR_SHIFT)
+#define DMAD6348_ST_RX_ERR_SHIFT	2
+#define DMAD6348_ST_RX_ERR_MASK		(1 << DMAD6348_ST_RX_ERR_SHIFT)
+#define DMAD6348_ST_OS_ERR_SHIFT	4
+#define DMAD6348_ST_OS_ERR_MASK		(1 << DMAD6348_ST_OS_ERR_SHIFT)
+#define DMAD6348_ST_UN_ERR_SHIFT	9
+#define DMAD6348_ST_UN_ERR_MASK		(1 << DMAD6348_ST_UN_ERR_SHIFT)
+
+struct bcm6348_dma_desc {
+	uint16_t length;
+	uint16_t status;
+	uint32_t address;
+};
+
+struct bcm6348_chan_priv {
+	void __iomem *dma_ring;
+	uint8_t dma_ring_size;
+	uint8_t desc_id;
+	uint8_t desc_cnt;
+	bool *busy_desc;
+	bool running;
+};
+
+struct bcm6348_iudma_hw {
+	uint16_t err_mask;
+};
+
+struct bcm6348_iudma_priv {
+	const struct bcm6348_iudma_hw *hw;
+	void __iomem *base;
+	void __iomem *chan;
+	void __iomem *sram;
+	struct bcm6348_chan_priv **ch_priv;
+	uint8_t n_channels;
+};
+
+static inline bool bcm6348_iudma_chan_is_rx(uint8_t ch)
+{
+	return !(ch & 1);
+}
+
+static inline void bcm6348_iudma_fdc(void *ptr, ulong size)
+{
+	ulong start = (ulong) ptr;
+
+	flush_dcache_range(start, start + size);
+}
+
+static inline void bcm6348_iudma_idc(void *ptr, ulong size)
+{
+	ulong start = (ulong) ptr;
+
+	invalidate_dcache_range(start, start + size);
+}
+
+static void bcm6348_iudma_chan_stop(struct bcm6348_iudma_priv *priv,
+				    uint8_t ch)
+{
+	unsigned int timeout = DMA_CHAN_TOUT;
+
+	do {
+		uint32_t cfg, halt;
+
+		if (timeout > DMA_CHAN_TOUT / 2)
+			halt = DMAC_CFG_PKT_HALT_MASK;
+		else
+			halt = DMAC_CFG_BRST_HALT_MASK;
+
+		/* try to stop dma channel */
+		writel_be(halt, priv->chan + DMAC_CFG_REG(ch));
+		mb();
+
+		/* check if channel was stopped */
+		cfg = readl_be(priv->chan + DMAC_CFG_REG(ch));
+		if (!(cfg & DMAC_CFG_ENABLE_MASK))
+			break;
+
+		udelay(1);
+	} while (--timeout);
+
+	if (!timeout)
+		pr_err("unable to stop channel %u\n", ch);
+
+	/* reset dma channel */
+	setbits_be32(priv->base + DMA_RST_REG, DMA_RST_CHAN_MASK(ch));
+	mb();
+	clrbits_be32(priv->base + DMA_RST_REG, DMA_RST_CHAN_MASK(ch));
+}
+
+static int bcm6348_iudma_disable(struct dma *dma)
+{
+	struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+
+	/* stop dma channel */
+	bcm6348_iudma_chan_stop(priv, dma->id);
+
+	/* dma flow control */
+	if (bcm6348_iudma_chan_is_rx(dma->id))
+		writel_be(DMA_FLOWC_ALLOC_FORCE_MASK,
+			  DMA_FLOWC_ALLOC_REG(dma->id));
+
+	/* init channel config */
+	ch_priv->running = false;
+	ch_priv->desc_id = 0;
+	if (bcm6348_iudma_chan_is_rx(dma->id))
+		ch_priv->desc_cnt = 0;
+	else
+		ch_priv->desc_cnt = ch_priv->dma_ring_size;
+
+	return 0;
+}
+
+static int bcm6348_iudma_enable(struct dma *dma)
+{
+	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+	struct bcm6348_dma_desc *dma_desc = ch_priv->dma_ring;
+	uint8_t i;
+
+	/* dma ring init */
+	for (i = 0; i < ch_priv->desc_cnt; i++) {
+		if (bcm6348_iudma_chan_is_rx(dma->id)) {
+			ch_priv->busy_desc[i] = false;
+			dma_desc->status |= DMAD_ST_OWN_MASK;
+		} else {
+			dma_desc->status = 0;
+			dma_desc->length = 0;
+			dma_desc->address = 0;
+		}
+
+		if (i == ch_priv->desc_cnt - 1)
+			dma_desc->status |= DMAD_ST_WRAP_MASK;
+
+		dma_desc++;
+	}
+
+	/* init to first descriptor */
+	ch_priv->desc_id = 0;
+
+	/* force cache writeback */
+	bcm6348_iudma_fdc(ch_priv->dma_ring,
+			  sizeof(*dma_desc) * ch_priv->desc_cnt);
+
+	/* clear sram */
+	writel_be(0, priv->sram + DMAS_STATE_DATA_REG(dma->id));
+	writel_be(0, priv->sram + DMAS_DESC_LEN_STATUS_REG(dma->id));
+	writel_be(0, priv->sram + DMAS_DESC_BASE_BUFPTR_REG(dma->id));
+
+	/* set dma ring start */
+	writel_be(virt_to_phys(ch_priv->dma_ring),
+		  priv->sram + DMAS_RSTART_REG(dma->id));
+
+	/* set flow control */
+	if (bcm6348_iudma_chan_is_rx(dma->id)) {
+		u32 val;
+
+		setbits_be32(priv->base + DMA_CFG_REG,
+			     DMA_CFG_FLOWC_ENABLE(dma->id));
+
+		val = ch_priv->desc_cnt / 3;
+		writel_be(val, priv->base + DMA_FLOWC_THR_LO_REG(dma->id));
+
+		val = (ch_priv->desc_cnt * 2) / 3;
+		writel_be(val, priv->base + DMA_FLOWC_THR_HI_REG(dma->id));
+
+		writel_be(0, priv->base + DMA_FLOWC_ALLOC_REG(dma->id));
+	}
+
+	/* set dma max burst */
+	writel_be(ch_priv->desc_cnt,
+		  priv->chan + DMAC_BURST_REG(dma->id));
+
+	/* kick rx dma channel */
+	if (bcm6348_iudma_chan_is_rx(dma->id))
+		setbits_be32(priv->chan + DMAC_CFG_REG(dma->id),
+			     DMAC_CFG_ENABLE_MASK);
+
+	/* channel is now enabled */
+	ch_priv->running = true;
+
+	return 0;
+}
+
+static int bcm6348_iudma_request(struct dma *dma)
+{
+	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+	struct bcm6348_chan_priv *ch_priv;
+
+	/* check if channel is valid */
+	if (dma->id >= priv->n_channels)
+		return -ENODEV;
+
+	/* alloc channel private data */
+	priv->ch_priv[dma->id] = calloc(1, sizeof(struct bcm6348_chan_priv));
+	if (!priv->ch_priv[dma->id])
+		return -ENOMEM;
+	ch_priv = priv->ch_priv[dma->id];
+
+	/* alloc dma ring */
+	if (bcm6348_iudma_chan_is_rx(dma->id))
+		ch_priv->dma_ring_size = DMA_RX_DESC;
+	else
+		ch_priv->dma_ring_size = DMA_TX_DESC;
+
+	ch_priv->dma_ring =
+		malloc_cache_aligned(sizeof(struct bcm6348_dma_desc) *
+				     ch_priv->dma_ring_size);
+	if (!ch_priv->dma_ring)
+		return -ENOMEM;
+
+	/* init channel config */
+	ch_priv->running = false;
+	ch_priv->desc_id = 0;
+	if (bcm6348_iudma_chan_is_rx(dma->id)) {
+		ch_priv->desc_cnt = 0;
+		ch_priv->busy_desc = calloc(ch_priv->desc_cnt, sizeof(bool));
+	} else {
+		ch_priv->desc_cnt = ch_priv->dma_ring_size;
+		ch_priv->busy_desc = NULL;
+	}
+
+	return 0;
+}
+
+static int bcm6348_iudma_receive(struct dma *dma, void **dst, void *metadata)
+{
+	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+	const struct bcm6348_iudma_hw *hw = priv->hw;
+	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+	struct bcm6348_dma_desc *dma_desc = dma_desc = ch_priv->dma_ring;
+	int ret;
+
+	/* get dma ring descriptor address */
+	dma_desc += ch_priv->desc_id;
+
+	/* invalidate cache data */
+	bcm6348_iudma_idc(dma_desc, sizeof(*dma_desc));
+
+	/* check dma own */
+	if (dma_desc->status & DMAD_ST_OWN_MASK)
+		return -EAGAIN;
+
+	/* check pkt */
+	if (!(dma_desc->status & DMAD_ST_EOP_MASK) ||
+	    !(dma_desc->status & DMAD_ST_SOP_MASK) ||
+	    (dma_desc->status & hw->err_mask)) {
+		pr_err("invalid pkt received (ch=%ld desc=%u) (st=%04x)\n",
+		       dma->id, ch_priv->desc_id, dma_desc->status);
+		ret = -EAGAIN;
+	} else {
+		/* set dma buffer address */
+		*dst = phys_to_virt(dma_desc->address);
+
+		/* invalidate cache data */
+		bcm6348_iudma_idc(*dst, dma_desc->length);
+
+		/* remove crc */
+		ret = dma_desc->length - 4;
+	}
+
+	/* busy dma descriptor */
+	ch_priv->busy_desc[ch_priv->desc_id] = true;
+
+	/* increment dma descriptor */
+	ch_priv->desc_id = (ch_priv->desc_id + 1) % ch_priv->desc_cnt;
+
+	return ret;
+}
+
+static int bcm6348_iudma_send(struct dma *dma, void *src, size_t len,
+			      void *metadata)
+{
+	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+	struct bcm6348_dma_desc *dma_desc;
+	uint16_t status;
+
+	/* flush cache */
+	bcm6348_iudma_fdc(src, len);
+
+	/* get dma ring descriptor address */
+	dma_desc = ch_priv->dma_ring;
+	dma_desc += ch_priv->desc_id;
+
+	/* config dma descriptor */
+	status = (DMAD_ST_OWN_MASK |
+		  DMAD_ST_EOP_MASK |
+		  DMAD_ST_CRC_MASK |
+		  DMAD_ST_SOP_MASK);
+	if (ch_priv->desc_id == ch_priv->desc_cnt - 1)
+		status |= DMAD_ST_WRAP_MASK;
+
+	/* set dma descriptor */
+	dma_desc->address = virt_to_phys(src);
+	dma_desc->length = len;
+	dma_desc->status = status;
+
+	/* flush cache */
+	bcm6348_iudma_fdc(dma_desc, sizeof(*dma_desc));
+
+	/* kick tx dma channel */
+	setbits_be32(priv->chan + DMAC_CFG_REG(dma->id), DMAC_CFG_ENABLE_MASK);
+
+	/* poll dma status */
+	do {
+		/* invalidate cache */
+		bcm6348_iudma_idc(dma_desc, sizeof(*dma_desc));
+
+		if (!(dma_desc->status & DMAD_ST_OWN_MASK))
+			break;
+	} while(1);
+
+	/* increment dma descriptor */
+	ch_priv->desc_id = (ch_priv->desc_id + 1) % ch_priv->desc_cnt;
+
+	return 0;
+}
+
+static int bcm6348_iudma_free_rcv_buf(struct dma *dma, void *dst, size_t size)
+{
+	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+	struct bcm6348_dma_desc *dma_desc = ch_priv->dma_ring;
+	uint16_t status;
+	uint8_t i;
+	u32 cfg;
+
+	/* get dirty dma descriptor */
+	for (i = 0; i < ch_priv->desc_cnt; i++) {
+		if (phys_to_virt(dma_desc->address) == dst)
+			break;
+
+		dma_desc++;
+	}
+
+	/* dma descriptor not found */
+	if (i == ch_priv->desc_cnt) {
+		pr_err("dirty dma descriptor not found\n");
+		return -ENOENT;
+	}
+
+	/* invalidate cache */
+	bcm6348_iudma_idc(ch_priv->dma_ring,
+			  sizeof(*dma_desc) * ch_priv->desc_cnt);
+
+	/* free dma descriptor */
+	ch_priv->busy_desc[i] = false;
+
+	status = DMAD_ST_OWN_MASK;
+	if (i == ch_priv->desc_cnt - 1)
+		status |= DMAD_ST_WRAP_MASK;
+
+	dma_desc->status |= status;
+	dma_desc->length = PKTSIZE_ALIGN;
+
+	/* tell dma we allocated one buffer */
+	writel_be(1, DMA_FLOWC_ALLOC_REG(dma->id));
+
+	/* flush cache */
+	bcm6348_iudma_fdc(ch_priv->dma_ring,
+			  sizeof(*dma_desc) * ch_priv->desc_cnt);
+
+	/* kick rx dma channel if disabled */
+	cfg = readl_be(priv->chan + DMAC_CFG_REG(dma->id));
+	if (!(cfg & DMAC_CFG_ENABLE_MASK))
+		setbits_be32(priv->chan + DMAC_CFG_REG(dma->id),
+			     DMAC_CFG_ENABLE_MASK);
+
+	return 0;
+}
+
+static int bcm6348_iudma_add_rcv_buf(struct dma *dma, void *dst, size_t size)
+{
+	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+	struct bcm6348_dma_desc *dma_desc = ch_priv->dma_ring;
+
+	/* no more dma descriptors available */
+	if (ch_priv->desc_cnt == ch_priv->dma_ring_size) {
+		pr_err("max number of buffers reached\n");
+		return -EINVAL;
+	}
+
+	/* get next dma descriptor */
+	dma_desc += ch_priv->desc_cnt;
+
+	/* init dma descriptor */
+	dma_desc->address = virt_to_phys(dst);
+	dma_desc->length = size;
+	dma_desc->status = 0;
+
+	/* flush cache */
+	bcm6348_iudma_fdc(dma_desc, sizeof(*dma_desc));
+
+	/* increment dma descriptors */
+	ch_priv->desc_cnt++;
+
+	return 0;
+}
+
+static int bcm6348_iudma_prepare_rcv_buf(struct dma *dma, void *dst,
+					 size_t size)
+{
+	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+
+	/* only add new rx buffers if channel isn't running */
+	if (ch_priv->running)
+		return bcm6348_iudma_free_rcv_buf(dma, dst, size);
+	else
+		return bcm6348_iudma_add_rcv_buf(dma, dst, size);
+}
+
+static const struct dma_ops bcm6348_iudma_ops = {
+	.disable = bcm6348_iudma_disable,
+	.enable = bcm6348_iudma_enable,
+	.prepare_rcv_buf = bcm6348_iudma_prepare_rcv_buf,
+	.request = bcm6348_iudma_request,
+	.receive = bcm6348_iudma_receive,
+	.send = bcm6348_iudma_send,
+};
+
+static const struct bcm6348_iudma_hw bcm6348_hw = {
+	.err_mask = (DMAD6348_ST_OV_ERR_MASK |
+		     DMAD6348_ST_CRC_ERR_MASK |
+		     DMAD6348_ST_RX_ERR_MASK |
+		     DMAD6348_ST_OS_ERR_MASK |
+		     DMAD6348_ST_UN_ERR_MASK),
+};
+
+static const struct bcm6348_iudma_hw bcm6368_hw = {
+	.err_mask = 0,
+};
+
+static const struct udevice_id bcm6348_iudma_ids[] = {
+	{
+		.compatible = "brcm,bcm6348-iudma",
+		.data = (ulong)&bcm6348_hw,
+	}, {
+		.compatible = "brcm,bcm6368-iudma",
+		.data = (ulong)&bcm6368_hw,
+	}, { /* sentinel */ }
+};
+
+static int bcm6348_iudma_probe(struct udevice *dev)
+{
+	struct dma_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct bcm6348_iudma_priv *priv = dev_get_priv(dev);
+	const struct bcm6348_iudma_hw *hw =
+		(const struct bcm6348_iudma_hw *)dev_get_driver_data(dev);
+	uint8_t ch;
+	int i;
+
+	uc_priv->supported = (DMA_SUPPORTS_DEV_TO_MEM |
+			      DMA_SUPPORTS_MEM_TO_DEV);
+	priv->hw = hw;
+
+	/* dma global base address */
+	priv->base = dev_remap_addr_name(dev, "dma");
+	if (!priv->base)
+		return -EINVAL;
+
+	/* dma channels base address */
+	priv->chan = dev_remap_addr_name(dev, "dma-channels");
+	if (!priv->chan)
+		return -EINVAL;
+
+	/* dma sram base address */
+	priv->sram = dev_remap_addr_name(dev, "dma-sram");
+	if (!priv->sram)
+		return -EINVAL;
+
+	/* get number of channels */
+	priv->n_channels = dev_read_u32_default(dev, "dma-channels", 8);
+	if (priv->n_channels > DMA_CHAN_MAX)
+		return -EINVAL;
+
+	/* try to enable clocks */
+	for (i = 0; ; i++) {
+		struct clk clk;
+		int ret;
+
+		ret = clk_get_by_index(dev, i, &clk);
+		if (ret < 0)
+			break;
+
+		ret = clk_enable(&clk);
+		if (ret < 0) {
+			pr_err("error enabling clock %d\n", i);
+			return ret;
+		}
+
+		ret = clk_free(&clk);
+		if (ret < 0) {
+			pr_err("error freeing clock %d\n", i);
+			return ret;
+		}
+	}
+
+	/* try to perform resets */
+	for (i = 0; ; i++) {
+		struct reset_ctl reset;
+		int ret;
+
+		ret = reset_get_by_index(dev, i, &reset);
+		if (ret < 0)
+			break;
+
+		ret = reset_deassert(&reset);
+		if (ret < 0) {
+			pr_err("error deasserting reset %d\n", i);
+			return ret;
+		}
+
+		ret = reset_free(&reset);
+		if (ret < 0) {
+			pr_err("error freeing reset %d\n", i);
+			return ret;
+		}
+	}
+
+	/* disable dma controller */
+	clrbits_be32(priv->base + DMA_CFG_REG, DMA_CFG_ENABLE_MASK);
+
+	/* alloc channel private data pointers */
+	priv->ch_priv = calloc(priv->n_channels,
+			       sizeof(struct bcm6348_chan_priv*));
+	if (!priv->ch_priv)
+		return -ENOMEM;
+
+	/* stop dma channels */
+	for (ch = 0; ch < priv->n_channels; ch++)
+		bcm6348_iudma_chan_stop(priv, ch);
+
+	/* enable dma controller */
+	setbits_be32(priv->base + DMA_CFG_REG, DMA_CFG_ENABLE_MASK);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(bcm6348_iudma) = {
+	.name = "bcm6348_iudma",
+	.id = UCLASS_DMA,
+	.of_match = bcm6348_iudma_ids,
+	.ops = &bcm6348_iudma_ops,
+	.priv_auto_alloc_size = sizeof(struct bcm6348_iudma_priv),
+	.probe = bcm6348_iudma_probe,
+};
-- 
2.11.0

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

* [U-Boot] [PATCH v10 02/28] bmips: bcm6338: add bcm6348-iudma support
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 01/28] dma: add bcm6348-iudma support Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 03/28] bmips: bcm6348: " Álvaro Fernández Rojas
                         ` (26 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: fix license identifiers
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6338.dtsi       | 14 ++++++++++++++
 include/dt-bindings/dma/bcm6338-dma.h | 14 ++++++++++++++
 2 files changed, 28 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6338-dma.h

diff --git a/arch/mips/dts/brcm,bcm6338.dtsi b/arch/mips/dts/brcm,bcm6338.dtsi
index bbd58cf803..990355481c 100644
--- a/arch/mips/dts/brcm,bcm6338.dtsi
+++ b/arch/mips/dts/brcm,bcm6338.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6338-clock.h>
+#include <dt-bindings/dma/bcm6338-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/reset/bcm6338-reset.h>
 #include "skeleton.dtsi"
@@ -130,5 +131,18 @@
 			reg = <0xfffe3100 0x38>;
 			u-boot,dm-pre-reloc;
 		};
+
+		iudma: dma-controller at fffe2400 {
+			compatible = "brcm,bcm6348-iudma";
+			reg = <0xfffe2400 0x1c>,
+			      <0xfffe2500 0x60>,
+			      <0xfffe2600 0x60>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <6>;
+			resets = <&periph_rst BCM6338_RST_DMAMEM>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6338-dma.h b/include/dt-bindings/dma/bcm6338-dma.h
new file mode 100644
index 0000000000..f2e0b20444
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6338-dma.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6338_H
+#define __DT_BINDINGS_DMA_BCM6338_H
+
+#define BCM6338_DMA_ENET_RX	0
+#define BCM6338_DMA_ENET_TX	1
+
+#endif /* __DT_BINDINGS_DMA_BCM6338_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v10 03/28] bmips: bcm6348: add bcm6348-iudma support
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 01/28] dma: add bcm6348-iudma support Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 02/28] bmips: bcm6338: " Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 04/28] bmips: bcm6358: " Álvaro Fernández Rojas
                         ` (25 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: fix license identifiers
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6348.dtsi       | 16 ++++++++++++++++
 include/dt-bindings/dma/bcm6348-dma.h | 16 ++++++++++++++++
 2 files changed, 32 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6348-dma.h

diff --git a/arch/mips/dts/brcm,bcm6348.dtsi b/arch/mips/dts/brcm,bcm6348.dtsi
index cc80bbc808..875de232ca 100644
--- a/arch/mips/dts/brcm,bcm6348.dtsi
+++ b/arch/mips/dts/brcm,bcm6348.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6348-clock.h>
+#include <dt-bindings/dma/bcm6348-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/reset/bcm6348-reset.h>
 #include "skeleton.dtsi"
@@ -159,5 +160,20 @@
 			reg = <0xfffe2300 0x38>;
 			u-boot,dm-pre-reloc;
 		};
+
+		iudma: dma-controller at fffe7000 {
+			compatible = "brcm,bcm6348-iudma";
+			reg = <0xfffe7000 0x1c>,
+			      <0xfffe7100 0x40>,
+			      <0xfffe7200 0x40>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <4>;
+			clocks = <&periph_clk BCM6348_CLK_ENET>;
+			resets = <&periph_rst BCM6348_RST_ENET>,
+				 <&periph_rst BCM6348_RST_DMAMEM>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6348-dma.h b/include/dt-bindings/dma/bcm6348-dma.h
new file mode 100644
index 0000000000..36c2ffd412
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6348-dma.h
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6348_H
+#define __DT_BINDINGS_DMA_BCM6348_H
+
+#define BCM6348_DMA_ENET0_RX	0
+#define BCM6348_DMA_ENET0_TX	1
+#define BCM6348_DMA_ENET1_RX	2
+#define BCM6348_DMA_ENET1_TX	3
+
+#endif /* __DT_BINDINGS_DMA_BCM6348_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v10 04/28] bmips: bcm6358: add bcm6348-iudma support
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                         ` (2 preceding siblings ...)
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 03/28] bmips: bcm6348: " Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 05/28] bmips: bcm6368: " Álvaro Fernández Rojas
                         ` (24 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: fix license identifiers
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6358.dtsi       | 18 ++++++++++++++++++
 include/dt-bindings/dma/bcm6358-dma.h | 16 ++++++++++++++++
 2 files changed, 34 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6358-dma.h

diff --git a/arch/mips/dts/brcm,bcm6358.dtsi b/arch/mips/dts/brcm,bcm6358.dtsi
index 0617b46e92..5605723e83 100644
--- a/arch/mips/dts/brcm,bcm6358.dtsi
+++ b/arch/mips/dts/brcm,bcm6358.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6358-clock.h>
+#include <dt-bindings/dma/bcm6358-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/reset/bcm6358-reset.h>
 #include "skeleton.dtsi"
@@ -190,5 +191,22 @@
 
 			status = "disabled";
 		};
+
+		iudma: dma-controller at fffe5000 {
+			compatible = "brcm,bcm6348-iudma";
+			reg = <0xfffe5000 0x24>,
+			      <0xfffe5100 0x80>,
+			      <0xfffe5200 0x80>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <8>;
+			clocks = <&periph_clk BCM6358_CLK_EMUSB>,
+				 <&periph_clk BCM6358_CLK_USBSU>,
+				 <&periph_clk BCM6358_CLK_EPHY>;
+			resets = <&periph_rst BCM6358_RST_ENET>,
+				 <&periph_rst BCM6358_RST_EPHY>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6358-dma.h b/include/dt-bindings/dma/bcm6358-dma.h
new file mode 100644
index 0000000000..3118b9da0a
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6358-dma.h
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6358_H
+#define __DT_BINDINGS_DMA_BCM6358_H
+
+#define BCM6358_DMA_ENET0_RX	0
+#define BCM6358_DMA_ENET0_TX	1
+#define BCM6358_DMA_ENET1_RX	2
+#define BCM6358_DMA_ENET1_TX	3
+
+#endif /* __DT_BINDINGS_DMA_BCM6358_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v10 05/28] bmips: bcm6368: add bcm6348-iudma support
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                         ` (3 preceding siblings ...)
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 04/28] bmips: bcm6358: " Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 06/28] bmips: bcm6328: " Álvaro Fernández Rojas
                         ` (23 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: fix license identifiers
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6368.dtsi       | 13 +++++++++++++
 include/dt-bindings/dma/bcm6368-dma.h | 14 ++++++++++++++
 2 files changed, 27 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6368-dma.h

diff --git a/arch/mips/dts/brcm,bcm6368.dtsi b/arch/mips/dts/brcm,bcm6368.dtsi
index 65d769ab4f..30047f6360 100644
--- a/arch/mips/dts/brcm,bcm6368.dtsi
+++ b/arch/mips/dts/brcm,bcm6368.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6368-clock.h>
+#include <dt-bindings/dma/bcm6368-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/reset/bcm6368-reset.h>
 #include "skeleton.dtsi"
@@ -192,5 +193,17 @@
 
 			status = "disabled";
 		};
+
+		iudma: dma-controller at 10006800 {
+			compatible = "brcm,bcm6368-iudma";
+			reg = <0x10006800 0x80>,
+			      <0x10006a00 0x80>,
+			      <0x10006c00 0x80>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <8>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6368-dma.h b/include/dt-bindings/dma/bcm6368-dma.h
new file mode 100644
index 0000000000..36c6caa0e1
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6368-dma.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6368_H
+#define __DT_BINDINGS_DMA_BCM6368_H
+
+#define BCM6368_DMA_ENETSW_RX	0
+#define BCM6368_DMA_ENETSW_TX	1
+
+#endif /* __DT_BINDINGS_DMA_BCM6368_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v10 06/28] bmips: bcm6328: add bcm6348-iudma support
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                         ` (4 preceding siblings ...)
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 05/28] bmips: bcm6368: " Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 07/28] bmips: bcm6362: " Álvaro Fernández Rojas
                         ` (22 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: fix license identifiers
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6328.dtsi       | 13 +++++++++++++
 include/dt-bindings/dma/bcm6328-dma.h | 14 ++++++++++++++
 2 files changed, 27 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6328-dma.h

diff --git a/arch/mips/dts/brcm,bcm6328.dtsi b/arch/mips/dts/brcm,bcm6328.dtsi
index e00a2950e2..6fa49e22bb 100644
--- a/arch/mips/dts/brcm,bcm6328.dtsi
+++ b/arch/mips/dts/brcm,bcm6328.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6328-clock.h>
+#include <dt-bindings/dma/bcm6328-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/power-domain/bcm6328-power-domain.h>
 #include <dt-bindings/reset/bcm6328-reset.h>
@@ -187,5 +188,17 @@
 			reg = <0x10003000 0x864>;
 			u-boot,dm-pre-reloc;
 		};
+
+		iudma: dma-controller at 1000d800 {
+			compatible = "brcm,bcm6368-iudma";
+			reg = <0x1000d800 0x80>,
+			      <0x1000da00 0x80>,
+			      <0x1000dc00 0x80>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <8>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6328-dma.h b/include/dt-bindings/dma/bcm6328-dma.h
new file mode 100644
index 0000000000..7494df2feb
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6328-dma.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6328_H
+#define __DT_BINDINGS_DMA_BCM6328_H
+
+#define BCM6328_DMA_ENETSW_RX	0
+#define BCM6328_DMA_ENETSW_TX	1
+
+#endif /* __DT_BINDINGS_DMA_BCM6328_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v10 07/28] bmips: bcm6362: add bcm6348-iudma support
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                         ` (5 preceding siblings ...)
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 06/28] bmips: bcm6328: " Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 08/28] bmips: bcm63268: " Álvaro Fernández Rojas
                         ` (21 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: fix license identifiers
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6362.dtsi       | 13 +++++++++++++
 include/dt-bindings/dma/bcm6362-dma.h | 14 ++++++++++++++
 2 files changed, 27 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6362-dma.h

diff --git a/arch/mips/dts/brcm,bcm6362.dtsi b/arch/mips/dts/brcm,bcm6362.dtsi
index 3047b82b21..94e7de096d 100644
--- a/arch/mips/dts/brcm,bcm6362.dtsi
+++ b/arch/mips/dts/brcm,bcm6362.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6362-clock.h>
+#include <dt-bindings/dma/bcm6362-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/power-domain/bcm6362-power-domain.h>
 #include <dt-bindings/reset/bcm6362-reset.h>
@@ -211,5 +212,17 @@
 			reg = <0x10003000 0x864>;
 			u-boot,dm-pre-reloc;
 		};
+
+		iudma: dma-controller at 1000d800 {
+			compatible = "brcm,bcm6368-iudma";
+			reg = <0x1000d800 0x80>,
+			      <0x1000da00 0x80>,
+			      <0x1000dc00 0x80>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <8>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6362-dma.h b/include/dt-bindings/dma/bcm6362-dma.h
new file mode 100644
index 0000000000..1e62236daa
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6362-dma.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6362_H
+#define __DT_BINDINGS_DMA_BCM6362_H
+
+#define BCM6362_DMA_ENETSW_RX	0
+#define BCM6362_DMA_ENETSW_TX	1
+
+#endif /* __DT_BINDINGS_DMA_BCM6362_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v10 08/28] bmips: bcm63268: add bcm6348-iudma support
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                         ` (6 preceding siblings ...)
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 07/28] bmips: bcm6362: " Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 09/28] bmips: bcm6318: " Álvaro Fernández Rojas
                         ` (20 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: fix license identifiers
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm63268.dtsi       | 13 +++++++++++++
 include/dt-bindings/dma/bcm63268-dma.h | 14 ++++++++++++++
 2 files changed, 27 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm63268-dma.h

diff --git a/arch/mips/dts/brcm,bcm63268.dtsi b/arch/mips/dts/brcm,bcm63268.dtsi
index 62c440e675..c7ad83c306 100644
--- a/arch/mips/dts/brcm,bcm63268.dtsi
+++ b/arch/mips/dts/brcm,bcm63268.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm63268-clock.h>
+#include <dt-bindings/dma/bcm63268-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/power-domain/bcm63268-power-domain.h>
 #include <dt-bindings/reset/bcm63268-reset.h>
@@ -217,5 +218,17 @@
 			reg = <0x10003000 0x894>;
 			u-boot,dm-pre-reloc;
 		};
+
+		iudma: dma-controller at 1000d800 {
+			compatible = "brcm,bcm6368-iudma";
+			reg = <0x1000d800 0x80>,
+			      <0x1000da00 0x80>,
+			      <0x1000dc00 0x80>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <8>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm63268-dma.h b/include/dt-bindings/dma/bcm63268-dma.h
new file mode 100644
index 0000000000..7d027119e6
--- /dev/null
+++ b/include/dt-bindings/dma/bcm63268-dma.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM63268_H
+#define __DT_BINDINGS_DMA_BCM63268_H
+
+#define BCM63268_DMA_ENETSW_RX	0
+#define BCM63268_DMA_ENETSW_TX	1
+
+#endif /* __DT_BINDINGS_DMA_BCM63268_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v10 09/28] bmips: bcm6318: add bcm6348-iudma support
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                         ` (7 preceding siblings ...)
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 08/28] bmips: bcm63268: " Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 10/28] net: add support for bcm6348-enet Álvaro Fernández Rojas
                         ` (19 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: fix license identifiers
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6318.dtsi       | 19 +++++++++++++++++++
 include/dt-bindings/dma/bcm6318-dma.h | 14 ++++++++++++++
 2 files changed, 33 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6318-dma.h

diff --git a/arch/mips/dts/brcm,bcm6318.dtsi b/arch/mips/dts/brcm,bcm6318.dtsi
index f75988be12..d04b7cbb01 100644
--- a/arch/mips/dts/brcm,bcm6318.dtsi
+++ b/arch/mips/dts/brcm,bcm6318.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6318-clock.h>
+#include <dt-bindings/dma/bcm6318-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/power-domain/bcm6318-power-domain.h>
 #include <dt-bindings/reset/bcm6318-reset.h>
@@ -54,6 +55,12 @@
 			reg = <0x10000004 0x4>;
 			#clock-cells = <1>;
 		};
+
+		ubus_clk: ubus-clk {
+			compatible = "brcm,bcm6345-clk";
+			reg = <0x10000008 0x4>;
+			#clock-cells = <1>;
+		};
 	};
 
 	ubus {
@@ -182,5 +189,17 @@
 
 			status = "disabled";
 		};
+
+		iudma: dma-controller at 10088000 {
+			compatible = "brcm,bcm6368-iudma";
+			reg = <0x10088000 0x80>,
+			      <0x10088200 0x80>,
+			      <0x10088400 0x80>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <8>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6318-dma.h b/include/dt-bindings/dma/bcm6318-dma.h
new file mode 100644
index 0000000000..ad7c5ac2df
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6318-dma.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6318_H
+#define __DT_BINDINGS_DMA_BCM6318_H
+
+#define BCM6318_DMA_ENETSW_RX	0
+#define BCM6318_DMA_ENETSW_TX	1
+
+#endif /* __DT_BINDINGS_DMA_BCM6318_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v10 10/28] net: add support for bcm6348-enet
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                         ` (8 preceding siblings ...)
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 09/28] bmips: bcm6318: " Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-30 16:54         ` Daniel Schwierzeck
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 11/28] bmips: bcm6338: " Álvaro Fernández Rojas
                         ` (18 subsequent siblings)
  28 siblings, 1 reply; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: Introduce changes suggested by Daniel Schwierzeck:
  - Fix license identifiers.
  - Remove packet queue.
  - Move dma_prepare_rcv_buf to free_pkt.
  - Switch to live DM live tree.
 v9: use dma_prepare_rcv_buf and remove dma rx channel reset:
  - bcm6348_eth_recv: clear dirty dma descriptors only when packets are copied
   from rx dma.
  - bcm6348_eth_send: remove dma rx channel reset when sending packet.
 v8: Introduce changes from Grygorii Strashko
 v5: Receive as much packets as possible from bcm6348-eth and cache them in
 net_rx_packets. This is needed in order to fix flow control issues.
 v4: Fix issues reported by Grygorii Strashko and other fixes:
  - Copy received dma buffer to net_rx_packets in order to avoid possible
  dma overwrites.
  - Reset dma rx channel when sending a new packet to prevent flow control
  issues.
  - Fix packet casting on bcm6348_eth_recv/send.
 v3: no changes
 v2: select DMA_CHANNELS.

 drivers/net/Kconfig            |  10 +
 drivers/net/Makefile           |   1 +
 drivers/net/bcm6348-eth.c      | 537 +++++++++++++++++++++++++++++++++++++++++
 include/configs/bmips_common.h |   6 +-
 4 files changed, 553 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/bcm6348-eth.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 8fb365fc5d..2b7cec8804 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -72,6 +72,16 @@ config BCM_SF2_ETH_GMAC
 	  by the BCM_SF2_ETH driver.
 	  Say Y to any bcmcygnus based platforms.
 
+config BCM6348_ETH
+	bool "BCM6348 EMAC support"
+	depends on DM_ETH && ARCH_BMIPS
+	select DMA
+	select DMA_CHANNELS
+	select MII
+	select PHYLIB
+	help
+	  This driver supports the BCM6348 Ethernet MAC.
+
 config DWC_ETH_QOS
 	bool "Synopsys DWC Ethernet QOS device support"
 	depends on DM_ETH
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 99056aa041..2647d4dd23 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -6,6 +6,7 @@
 obj-$(CONFIG_ALTERA_TSE) += altera_tse.o
 obj-$(CONFIG_AG7XXX) += ag7xxx.o
 obj-$(CONFIG_ARMADA100_FEC) += armada100_fec.o
+obj-$(CONFIG_BCM6348_ETH) += bcm6348-eth.o
 obj-$(CONFIG_DRIVER_AT91EMAC) += at91_emac.o
 obj-$(CONFIG_DRIVER_AX88180) += ax88180.o
 obj-$(CONFIG_BCM_SF2_ETH) += bcm-sf2-eth.o
diff --git a/drivers/net/bcm6348-eth.c b/drivers/net/bcm6348-eth.c
new file mode 100644
index 0000000000..7100e68bd2
--- /dev/null
+++ b/drivers/net/bcm6348-eth.c
@@ -0,0 +1,537 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c:
+ *	Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dma.h>
+#include <miiphy.h>
+#include <net.h>
+#include <phy.h>
+#include <reset.h>
+#include <wait_bit.h>
+#include <asm/io.h>
+
+#define ETH_RX_DESC			PKTBUFSRX
+#define ETH_MAX_MTU_SIZE		1518
+#define ETH_TIMEOUT			100
+#define ETH_TX_WATERMARK		32
+
+/* ETH Receiver Configuration register */
+#define ETH_RXCFG_REG			0x00
+#define ETH_RXCFG_ENFLOW_SHIFT		5
+#define ETH_RXCFG_ENFLOW_MASK		(1 << ETH_RXCFG_ENFLOW_SHIFT)
+
+/* ETH Receive Maximum Length register */
+#define ETH_RXMAXLEN_REG		0x04
+#define ETH_RXMAXLEN_SHIFT		0
+#define ETH_RXMAXLEN_MASK		(0x7ff << ETH_RXMAXLEN_SHIFT)
+
+/* ETH Transmit Maximum Length register */
+#define ETH_TXMAXLEN_REG		0x08
+#define ETH_TXMAXLEN_SHIFT		0
+#define ETH_TXMAXLEN_MASK		(0x7ff << ETH_TXMAXLEN_SHIFT)
+
+/* MII Status/Control register */
+#define MII_SC_REG			0x10
+#define MII_SC_MDCFREQDIV_SHIFT		0
+#define MII_SC_MDCFREQDIV_MASK		(0x7f << MII_SC_MDCFREQDIV_SHIFT)
+#define MII_SC_PREAMBLE_EN_SHIFT	7
+#define MII_SC_PREAMBLE_EN_MASK		(1 << MII_SC_PREAMBLE_EN_SHIFT)
+
+/* MII Data register */
+#define MII_DAT_REG			0x14
+#define MII_DAT_DATA_SHIFT		0
+#define MII_DAT_DATA_MASK		(0xffff << MII_DAT_DATA_SHIFT)
+#define MII_DAT_TA_SHIFT		16
+#define MII_DAT_TA_MASK			(0x3 << MII_DAT_TA_SHIFT)
+#define MII_DAT_REG_SHIFT		18
+#define MII_DAT_REG_MASK		(0x1f << MII_DAT_REG_SHIFT)
+#define MII_DAT_PHY_SHIFT		23
+#define MII_DAT_PHY_MASK		(0x1f << MII_DAT_PHY_SHIFT)
+#define MII_DAT_OP_SHIFT		28
+#define MII_DAT_OP_WRITE		(0x5 << MII_DAT_OP_SHIFT)
+#define MII_DAT_OP_READ			(0x6 << MII_DAT_OP_SHIFT)
+
+/* ETH Interrupts Mask register */
+#define ETH_IRMASK_REG			0x18
+
+/* ETH Interrupts register */
+#define ETH_IR_REG			0x1c
+#define ETH_IR_MII_SHIFT		0
+#define ETH_IR_MII_MASK			(1 << ETH_IR_MII_SHIFT)
+
+/* ETH Control register */
+#define ETH_CTL_REG			0x2c
+#define ETH_CTL_ENABLE_SHIFT		0
+#define ETH_CTL_ENABLE_MASK		(1 << ETH_CTL_ENABLE_SHIFT)
+#define ETH_CTL_DISABLE_SHIFT		1
+#define ETH_CTL_DISABLE_MASK		(1 << ETH_CTL_DISABLE_SHIFT)
+#define ETH_CTL_RESET_SHIFT		2
+#define ETH_CTL_RESET_MASK		(1 << ETH_CTL_RESET_SHIFT)
+#define ETH_CTL_EPHY_SHIFT		3
+#define ETH_CTL_EPHY_MASK		(1 << ETH_CTL_EPHY_SHIFT)
+
+/* ETH Transmit Control register */
+#define ETH_TXCTL_REG			0x30
+#define ETH_TXCTL_FD_SHIFT		0
+#define ETH_TXCTL_FD_MASK		(1 << ETH_TXCTL_FD_SHIFT)
+
+/* ETH Transmit Watermask register */
+#define ETH_TXWMARK_REG			0x34
+#define ETH_TXWMARK_WM_SHIFT		0
+#define ETH_TXWMARK_WM_MASK		(0x3f << ETH_TXWMARK_WM_SHIFT)
+
+/* MIB Control register */
+#define MIB_CTL_REG			0x38
+#define MIB_CTL_RDCLEAR_SHIFT		0
+#define MIB_CTL_RDCLEAR_MASK		(1 << MIB_CTL_RDCLEAR_SHIFT)
+
+/* ETH Perfect Match registers */
+#define ETH_PM_CNT			4
+#define ETH_PML_REG(x)			(0x58 + (x) * 0x8)
+#define ETH_PMH_REG(x)			(0x5c + (x) * 0x8)
+#define ETH_PMH_VALID_SHIFT		16
+#define ETH_PMH_VALID_MASK		(1 << ETH_PMH_VALID_SHIFT)
+
+/* MIB Counters registers */
+#define MIB_REG_CNT			55
+#define MIB_REG(x)			(0x200 + (x) * 4)
+
+/* ETH data */
+struct bcm6348_eth_priv {
+	void __iomem *base;
+	/* DMA */
+	struct dma rx_dma;
+	struct dma tx_dma;
+	/* PHY */
+	int phy_id;
+	struct phy_device *phy_dev;
+};
+
+static void bcm6348_eth_mac_disable(struct bcm6348_eth_priv *priv)
+{
+	/* disable emac */
+	clrsetbits_be32(priv->base + ETH_CTL_REG, ETH_CTL_ENABLE_MASK,
+			ETH_CTL_DISABLE_MASK);
+
+	/* wait until emac is disabled */
+	if (wait_for_bit_be32(priv->base + ETH_CTL_REG,
+			      ETH_CTL_DISABLE_MASK, false,
+			      ETH_TIMEOUT, false))
+		pr_err("%s: error disabling emac\n", __func__);
+}
+
+static void bcm6348_eth_mac_enable(struct bcm6348_eth_priv *priv)
+{
+	setbits_be32(priv->base + ETH_CTL_REG, ETH_CTL_ENABLE_MASK);
+}
+
+static void bcm6348_eth_mac_reset(struct bcm6348_eth_priv *priv)
+{
+	/* reset emac */
+	writel_be(ETH_CTL_RESET_MASK, priv->base + ETH_CTL_REG);
+	wmb();
+
+	/* wait until emac is reset */
+	if (wait_for_bit_be32(priv->base + ETH_CTL_REG,
+			      ETH_CTL_RESET_MASK, false,
+			      ETH_TIMEOUT, false))
+		pr_err("%s: error resetting emac\n", __func__);
+}
+
+static int bcm6348_eth_free_pkt(struct udevice *dev, uchar *packet, int len)
+{
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+
+	return dma_prepare_rcv_buf(&priv->rx_dma, packet, len);
+}
+
+static int bcm6348_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+
+	return dma_receive(&priv->rx_dma, (void**)packetp, NULL);
+}
+
+static int bcm6348_eth_send(struct udevice *dev, void *packet, int length)
+{
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+
+	return dma_send(&priv->tx_dma, packet, length, NULL);
+}
+
+static int bcm6348_eth_adjust_link(struct udevice *dev,
+				   struct phy_device *phydev)
+{
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+
+	/* mac duplex parameters */
+	if (phydev->duplex)
+		setbits_be32(priv->base + ETH_TXCTL_REG, ETH_TXCTL_FD_MASK);
+	else
+		clrbits_be32(priv->base + ETH_TXCTL_REG, ETH_TXCTL_FD_MASK);
+
+	/* rx flow control (pause frame handling) */
+	if (phydev->pause)
+		setbits_be32(priv->base + ETH_RXCFG_REG,
+			     ETH_RXCFG_ENFLOW_MASK);
+	else
+		clrbits_be32(priv->base + ETH_RXCFG_REG,
+			     ETH_RXCFG_ENFLOW_MASK);
+
+	return 0;
+}
+
+static int bcm6348_eth_start(struct udevice *dev)
+{
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+	int ret, i;
+
+	/* prepare rx dma buffers */
+	for (i = 0; i < ETH_RX_DESC; i++) {
+		ret = dma_prepare_rcv_buf(&priv->rx_dma, net_rx_packets[i],
+					  PKTSIZE_ALIGN);
+		if (ret < 0)
+			break;
+	}
+
+	/* enable dma rx channel */
+	dma_enable(&priv->rx_dma);
+
+	/* enable dma tx channel */
+	dma_enable(&priv->tx_dma);
+
+	ret = phy_startup(priv->phy_dev);
+	if (ret) {
+		pr_err("%s: could not initialize phy\n", __func__);
+		return ret;
+	}
+
+	if (!priv->phy_dev->link) {
+		pr_err("%s: no phy link\n", __func__);
+		return -EIO;
+	}
+
+	bcm6348_eth_adjust_link(dev, priv->phy_dev);
+
+	/* zero mib counters */
+	for (i = 0; i < MIB_REG_CNT; i++)
+		writel_be(0, MIB_REG(i));
+
+	/* enable rx flow control */
+	setbits_be32(priv->base + ETH_RXCFG_REG, ETH_RXCFG_ENFLOW_MASK);
+
+	/* set max rx/tx length */
+	writel_be((ETH_MAX_MTU_SIZE << ETH_RXMAXLEN_SHIFT) &
+		  ETH_RXMAXLEN_MASK, priv->base + ETH_RXMAXLEN_REG);
+	writel_be((ETH_MAX_MTU_SIZE << ETH_TXMAXLEN_SHIFT) &
+		  ETH_TXMAXLEN_MASK, priv->base + ETH_TXMAXLEN_REG);
+
+	/* set correct transmit fifo watermark */
+	writel_be((ETH_TX_WATERMARK << ETH_TXWMARK_WM_SHIFT) &
+		  ETH_TXWMARK_WM_MASK, priv->base + ETH_TXWMARK_REG);
+
+	/* enable emac */
+	bcm6348_eth_mac_enable(priv);
+
+	/* clear interrupts */
+	writel_be(0, priv->base + ETH_IRMASK_REG);
+
+	return 0;
+}
+
+static void bcm6348_eth_stop(struct udevice *dev)
+{
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+
+	/* disable dma rx channel */
+	dma_disable(&priv->rx_dma);
+
+	/* disable dma tx channel */
+	dma_disable(&priv->tx_dma);
+
+	/* disable emac */
+	bcm6348_eth_mac_disable(priv);
+}
+
+static int bcm6348_eth_write_hwaddr(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+	bool running = false;
+
+	/* check if emac is running */
+	if (readl_be(priv->base + ETH_CTL_REG) & ETH_CTL_ENABLE_MASK)
+		running = true;
+
+	/* disable emac */
+	if (running)
+		bcm6348_eth_mac_disable(priv);
+
+	/* set mac address */
+	writel_be((pdata->enetaddr[2] << 24) | (pdata->enetaddr[3]) << 16 |
+		  (pdata->enetaddr[4]) << 8 | (pdata->enetaddr[5]),
+		  priv->base + ETH_PML_REG(0));
+	writel_be((pdata->enetaddr[1]) | (pdata->enetaddr[0] << 8) |
+		  ETH_PMH_VALID_MASK, priv->base + ETH_PMH_REG(0));
+
+	/* enable emac */
+	if (running)
+		bcm6348_eth_mac_enable(priv);
+
+	return 0;
+}
+
+static const struct eth_ops bcm6348_eth_ops = {
+	.free_pkt = bcm6348_eth_free_pkt,
+	.recv = bcm6348_eth_recv,
+	.send = bcm6348_eth_send,
+	.start = bcm6348_eth_start,
+	.stop = bcm6348_eth_stop,
+	.write_hwaddr = bcm6348_eth_write_hwaddr,
+};
+
+static const struct udevice_id bcm6348_eth_ids[] = {
+	{ .compatible = "brcm,bcm6348-enet", },
+	{ /* sentinel */ }
+};
+
+static int bcm6348_mdio_op(void __iomem *base, uint32_t data)
+{
+	/* make sure mii interrupt status is cleared */
+	writel_be(ETH_IR_MII_MASK, base + ETH_IR_REG);
+
+	/* issue mii op */
+	writel_be(data, base + MII_DAT_REG);
+
+	/* wait until emac is disabled */
+	return wait_for_bit_be32(base + ETH_IR_REG,
+				 ETH_IR_MII_MASK, true,
+				 ETH_TIMEOUT, false);
+}
+
+static int bcm6348_mdio_read(struct mii_dev *bus, int addr, int devaddr,
+			     int reg)
+{
+	void __iomem *base = bus->priv;
+	uint32_t val;
+
+	val = MII_DAT_OP_READ;
+	val |= (reg << MII_DAT_REG_SHIFT) & MII_DAT_REG_MASK;
+	val |= (0x2 << MII_DAT_TA_SHIFT) & MII_DAT_TA_MASK;
+	val |= (addr << MII_DAT_PHY_SHIFT) & MII_DAT_PHY_MASK;
+
+	if (bcm6348_mdio_op(base, val)) {
+		pr_err("%s: timeout\n", __func__);
+		return -EINVAL;
+	}
+
+	val = readl_be(base + MII_DAT_REG) & MII_DAT_DATA_MASK;
+	val >>= MII_DAT_DATA_SHIFT;
+
+	return val;
+}
+
+static int bcm6348_mdio_write(struct mii_dev *bus, int addr, int dev_addr,
+			      int reg, u16 value)
+{
+	void __iomem *base = bus->priv;
+	uint32_t val;
+
+	val = MII_DAT_OP_WRITE;
+	val |= (reg << MII_DAT_REG_SHIFT) & MII_DAT_REG_MASK;
+	val |= (0x2 << MII_DAT_TA_SHIFT) & MII_DAT_TA_MASK;
+	val |= (addr << MII_DAT_PHY_SHIFT) & MII_DAT_PHY_MASK;
+	val |= (value << MII_DAT_DATA_SHIFT) & MII_DAT_DATA_MASK;
+
+	if (bcm6348_mdio_op(base, val)) {
+		pr_err("%s: timeout\n", __func__);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int bcm6348_mdio_init(const char *name, void __iomem *base)
+{
+	struct mii_dev *bus;
+
+	bus = mdio_alloc();
+	if (!bus) {
+		pr_err("%s: failed to allocate MDIO bus\n", __func__);
+		return -ENOMEM;
+	}
+
+	bus->read = bcm6348_mdio_read;
+	bus->write = bcm6348_mdio_write;
+	bus->priv = base;
+	snprintf(bus->name, sizeof(bus->name), "%s", name);
+
+	return mdio_register(bus);
+}
+
+static int bcm6348_phy_init(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+	struct mii_dev *bus;
+
+	/* get mii bus */
+	bus = miiphy_get_dev_by_name(dev->name);
+
+	/* phy connect */
+	priv->phy_dev = phy_connect(bus, priv->phy_id, dev,
+				    pdata->phy_interface);
+	if (!priv->phy_dev) {
+		pr_err("%s: no phy device\n", __func__);
+		return -ENODEV;
+	}
+
+	priv->phy_dev->supported = (SUPPORTED_10baseT_Half |
+				    SUPPORTED_10baseT_Full |
+				    SUPPORTED_100baseT_Half |
+				    SUPPORTED_100baseT_Full |
+				    SUPPORTED_Autoneg |
+				    SUPPORTED_Pause |
+				    SUPPORTED_MII);
+	priv->phy_dev->advertising = priv->phy_dev->supported;
+
+	/* phy config */
+	phy_config(priv->phy_dev);
+
+	return 0;
+}
+
+static int bcm6348_eth_probe(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+	struct ofnode_phandle_args phy;
+	const char *phy_mode;
+	int ret, i;
+
+	/* get base address */
+	priv->base = dev_remap_addr(dev);
+	if (!priv->base)
+		return -EINVAL;
+	pdata->iobase = (phys_addr_t) priv->base;
+
+	/* get phy mode */
+	pdata->phy_interface = PHY_INTERFACE_MODE_NONE;
+	phy_mode = dev_read_string(dev, "phy-mode");
+	if (phy_mode)
+		pdata->phy_interface = phy_get_interface_by_name(phy_mode);
+	if (pdata->phy_interface == PHY_INTERFACE_MODE_NONE)
+		return -ENODEV;
+
+	/* get phy */
+	if (dev_read_phandle_with_args(dev, "phy", NULL, 0, 0, &phy))
+		return -ENOENT;
+	priv->phy_id = ofnode_read_u32_default(phy.node, "reg", -1);
+
+	/* get dma channels */
+	ret = dma_get_by_name(dev, "tx", &priv->tx_dma);
+	if (ret)
+		return -EINVAL;
+
+	ret = dma_get_by_name(dev, "rx", &priv->rx_dma);
+	if (ret)
+		return -EINVAL;
+
+	/* try to enable clocks */
+	for (i = 0; ; i++) {
+		struct clk clk;
+		int ret;
+
+		ret = clk_get_by_index(dev, i, &clk);
+		if (ret < 0)
+			break;
+
+		ret = clk_enable(&clk);
+		if (ret < 0) {
+			pr_err("%s: error enabling clock %d\n", __func__, i);
+			return ret;
+		}
+
+		ret = clk_free(&clk);
+		if (ret < 0) {
+			pr_err("%s: error freeing clock %d\n", __func__, i);
+			return ret;
+		}
+	}
+
+	/* try to perform resets */
+	for (i = 0; ; i++) {
+		struct reset_ctl reset;
+		int ret;
+
+		ret = reset_get_by_index(dev, i, &reset);
+		if (ret < 0)
+			break;
+
+		ret = reset_deassert(&reset);
+		if (ret < 0) {
+			pr_err("%s: error deasserting reset %d\n", __func__, i);
+			return ret;
+		}
+
+		ret = reset_free(&reset);
+		if (ret < 0) {
+			pr_err("%s: error freeing reset %d\n", __func__, i);
+			return ret;
+		}
+	}
+
+	/* disable emac */
+	bcm6348_eth_mac_disable(priv);
+
+	/* reset emac */
+	bcm6348_eth_mac_reset(priv);
+
+	/* select correct mii interface */
+	if (pdata->phy_interface == PHY_INTERFACE_MODE_INTERNAL)
+		clrbits_be32(priv->base + ETH_CTL_REG, ETH_CTL_EPHY_MASK);
+	else
+		setbits_be32(priv->base + ETH_CTL_REG, ETH_CTL_EPHY_MASK);
+
+	/* turn on mdc clock */
+	writel_be((0x1f << MII_SC_MDCFREQDIV_SHIFT) |
+		  MII_SC_PREAMBLE_EN_MASK, priv->base + MII_SC_REG);
+
+	/* set mib counters to not clear when read */
+	clrbits_be32(priv->base + MIB_CTL_REG, MIB_CTL_RDCLEAR_MASK);
+
+	/* initialize perfect match registers */
+	for (i = 0; i < ETH_PM_CNT; i++) {
+		writel_be(0, priv->base + ETH_PML_REG(i));
+		writel_be(0, priv->base + ETH_PMH_REG(i));
+	}
+
+	/* init mii bus */
+	ret = bcm6348_mdio_init(dev->name, priv->base);
+	if (ret)
+		return ret;
+
+	/* init phy */
+	ret = bcm6348_phy_init(dev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+U_BOOT_DRIVER(bcm6348_eth) = {
+	.name = "bcm6348_eth",
+	.id = UCLASS_ETH,
+	.of_match = bcm6348_eth_ids,
+	.ops = &bcm6348_eth_ops,
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+	.priv_auto_alloc_size = sizeof(struct bcm6348_eth_priv),
+	.probe = bcm6348_eth_probe,
+};
diff --git a/include/configs/bmips_common.h b/include/configs/bmips_common.h
index 39ca2e0bf3..788f4af70d 100644
--- a/include/configs/bmips_common.h
+++ b/include/configs/bmips_common.h
@@ -6,6 +6,10 @@
 #ifndef __CONFIG_BMIPS_COMMON_H
 #define __CONFIG_BMIPS_COMMON_H
 
+/* ETH */
+#define CONFIG_PHY_RESET_DELAY		20
+#define CONFIG_SYS_RX_ETH_BUFFER	6
+
 /* UART */
 #define CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200, \
 					  230400, 500000, 1500000 }
@@ -16,7 +20,7 @@
 
 /* Memory usage */
 #define CONFIG_SYS_MAXARGS		24
-#define CONFIG_SYS_MALLOC_LEN		(1024 * 1024)
+#define CONFIG_SYS_MALLOC_LEN		(2 * 1024 * 1024)
 #define CONFIG_SYS_BOOTPARAMS_LEN	(128 * 1024)
 #define CONFIG_SYS_CBSIZE		512
 
-- 
2.11.0

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

* [U-Boot] [PATCH v10 11/28] bmips: bcm6338: add support for bcm6348-enet
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                         ` (9 preceding siblings ...)
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 10/28] net: add support for bcm6348-enet Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 12/28] bmips: enable f@st1704 enet support Álvaro Fernández Rojas
                         ` (17 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: no changes
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 v10: no changes
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6338.dtsi | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6338.dtsi b/arch/mips/dts/brcm,bcm6338.dtsi
index 990355481c..c547e949dd 100644
--- a/arch/mips/dts/brcm,bcm6338.dtsi
+++ b/arch/mips/dts/brcm,bcm6338.dtsi
@@ -144,5 +144,20 @@
 			dma-channels = <6>;
 			resets = <&periph_rst BCM6338_RST_DMAMEM>;
 		};
+
+		enet: ethernet at fffe2800 {
+			compatible = "brcm,bcm6348-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xfffe2800 0x2dc>;
+			clocks = <&periph_clk BCM6338_CLK_ENET>;
+			resets = <&periph_rst BCM6338_RST_ENET>;
+			dmas = <&iudma BCM6338_DMA_ENET_RX>,
+			       <&iudma BCM6338_DMA_ENET_TX>;
+			dma-names = "rx",
+				    "tx";
+
+			status = "disabled";
+		};
 	};
 };
-- 
2.11.0

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

* [U-Boot] [PATCH v10 12/28] bmips: enable f@st1704 enet support
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                         ` (10 preceding siblings ...)
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 11/28] bmips: bcm6338: " Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 13/28] bmips: bcm6348: add support for bcm6348-enet Álvaro Fernández Rojas
                         ` (16 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: no changes
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/sagem,f at st1704.dts     | 12 ++++++++++++
 configs/sagem_f at st1704_ram_defconfig |  8 +++++++-
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/sagem,f at st1704.dts b/arch/mips/dts/sagem,f at st1704.dts
index 5300f8b6df..ec6846dd9f 100644
--- a/arch/mips/dts/sagem,f at st1704.dts
+++ b/arch/mips/dts/sagem,f at st1704.dts
@@ -39,6 +39,18 @@
 	};
 };
 
+&enet {
+	status = "okay";
+	phy = <&enetphy>;
+	phy-mode = "mii";
+
+	enetphy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio {
 	status = "okay";
 };
diff --git a/configs/sagem_f at st1704_ram_defconfig b/configs/sagem_f at st1704_ram_defconfig
index 91a966327a..8c36f5dbf8 100644
--- a/configs/sagem_f at st1704_ram_defconfig
+++ b/configs/sagem_f at st1704_ram_defconfig
@@ -27,11 +27,14 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="sagem,f at st1704"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
@@ -40,6 +43,9 @@ CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_SPI_FLASH_MTD=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6348_ETH=y
 CONFIG_DM_RESET=y
 CONFIG_RESET_BCM6345=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
-- 
2.11.0

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

* [U-Boot] [PATCH v10 13/28] bmips: bcm6348: add support for bcm6348-enet
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                         ` (11 preceding siblings ...)
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 12/28] bmips: enable f@st1704 enet support Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 14/28] bmips: enable ct-5361 enet support Álvaro Fernández Rojas
                         ` (15 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: no changes
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6348.dtsi | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6348.dtsi b/arch/mips/dts/brcm,bcm6348.dtsi
index 875de232ca..79e7bd892b 100644
--- a/arch/mips/dts/brcm,bcm6348.dtsi
+++ b/arch/mips/dts/brcm,bcm6348.dtsi
@@ -161,6 +161,32 @@
 			u-boot,dm-pre-reloc;
 		};
 
+		enet0: ethernet at fffe6000 {
+			compatible = "brcm,bcm6348-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xfffe6000 0x2dc>;
+			dmas = <&iudma BCM6348_DMA_ENET0_RX>,
+			       <&iudma BCM6348_DMA_ENET0_TX>;
+			dma-names = "rx",
+				    "tx";
+
+			status = "disabled";
+		};
+
+		enet1: ethernet at fffe6800 {
+			compatible = "brcm,bcm6348-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xfffe6800 0x2dc>;
+			dmas = <&iudma BCM6348_DMA_ENET1_RX>,
+			       <&iudma BCM6348_DMA_ENET1_TX>;
+			dma-names = "rx",
+				    "tx";
+
+			status = "disabled";
+		};
+
 		iudma: dma-controller at fffe7000 {
 			compatible = "brcm,bcm6348-iudma";
 			reg = <0xfffe7000 0x1c>,
-- 
2.11.0

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

* [U-Boot] [PATCH v10 14/28] bmips: enable ct-5361 enet support
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                         ` (12 preceding siblings ...)
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 13/28] bmips: bcm6348: add support for bcm6348-enet Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 15/28] bmips: bcm6358: add support for bcm6348-enet Álvaro Fernández Rojas
                         ` (14 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: no changes
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/comtrend,ct-5361.dts    | 12 ++++++++++++
 configs/comtrend_ct5361_ram_defconfig |  8 +++++++-
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/comtrend,ct-5361.dts b/arch/mips/dts/comtrend,ct-5361.dts
index 25747ca95d..f6b8a94e25 100644
--- a/arch/mips/dts/comtrend,ct-5361.dts
+++ b/arch/mips/dts/comtrend,ct-5361.dts
@@ -34,6 +34,18 @@
 	};
 };
 
+&enet1 {
+	status = "okay";
+	phy = <&enet1phy>;
+	phy-mode = "mii";
+
+	enet1phy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
diff --git a/configs/comtrend_ct5361_ram_defconfig b/configs/comtrend_ct5361_ram_defconfig
index 82f2070713..6297e78fd9 100644
--- a/configs/comtrend_ct5361_ram_defconfig
+++ b/configs/comtrend_ct5361_ram_defconfig
@@ -25,11 +25,14 @@ CONFIG_CMD_LICENSE=y
 CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="comtrend,ct-5361"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
@@ -40,6 +43,9 @@ CONFIG_FLASH_CFI_DRIVER=y
 CONFIG_CFI_FLASH=y
 CONFIG_SYS_FLASH_PROTECTION=y
 CONFIG_SYS_FLASH_CFI=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6348_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6348_USBH_PHY=y
 CONFIG_DM_RESET=y
-- 
2.11.0

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

* [U-Boot] [PATCH v10 15/28] bmips: bcm6358: add support for bcm6348-enet
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                         ` (13 preceding siblings ...)
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 14/28] bmips: enable ct-5361 enet support Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 16/28] bmips: enable hg556a enet support Álvaro Fernández Rojas
                         ` (13 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: no changes
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6358.dtsi | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6358.dtsi b/arch/mips/dts/brcm,bcm6358.dtsi
index 5605723e83..5e9c9ad769 100644
--- a/arch/mips/dts/brcm,bcm6358.dtsi
+++ b/arch/mips/dts/brcm,bcm6358.dtsi
@@ -192,6 +192,34 @@
 			status = "disabled";
 		};
 
+		enet0: ethernet at fffe4000 {
+			compatible = "brcm,bcm6348-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xfffe4000 0x2dc>;
+			clocks = <&periph_clk BCM6358_CLK_ENET0>;
+			dmas = <&iudma BCM6358_DMA_ENET0_RX>,
+			       <&iudma BCM6358_DMA_ENET0_TX>;
+			dma-names = "rx",
+				    "tx";
+
+			status = "disabled";
+		};
+
+		enet1: ethernet at fffe4800 {
+			compatible = "brcm,bcm6348-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xfffe4800 0x2dc>;
+			clocks = <&periph_clk BCM6358_CLK_ENET1>;
+			dmas = <&iudma BCM6358_DMA_ENET1_RX>,
+			       <&iudma BCM6358_DMA_ENET1_TX>;
+			dma-names = "rx",
+				    "tx";
+
+			status = "disabled";
+		};
+
 		iudma: dma-controller at fffe5000 {
 			compatible = "brcm,bcm6348-iudma";
 			reg = <0xfffe5000 0x24>,
-- 
2.11.0

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

* [U-Boot] [PATCH v10 16/28] bmips: enable hg556a enet support
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                         ` (14 preceding siblings ...)
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 15/28] bmips: bcm6358: add support for bcm6348-enet Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 17/28] bmips: enable nb4-ser " Álvaro Fernández Rojas
                         ` (12 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: no changes
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/huawei,hg556a.dts     | 12 ++++++++++++
 configs/huawei_hg556a_ram_defconfig |  8 +++++++-
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/huawei,hg556a.dts b/arch/mips/dts/huawei,hg556a.dts
index 60455c2ff8..6a7fc1df4b 100644
--- a/arch/mips/dts/huawei,hg556a.dts
+++ b/arch/mips/dts/huawei,hg556a.dts
@@ -93,6 +93,18 @@
 	status = "okay";
 };
 
+&enet1 {
+	status = "okay";
+	phy = <&enet1phy>;
+	phy-mode = "mii";
+
+	enet1phy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
diff --git a/configs/huawei_hg556a_ram_defconfig b/configs/huawei_hg556a_ram_defconfig
index 6bb14ba736..d4e6144319 100644
--- a/configs/huawei_hg556a_ram_defconfig
+++ b/configs/huawei_hg556a_ram_defconfig
@@ -25,11 +25,14 @@ CONFIG_CMD_LICENSE=y
 CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="huawei,hg556a"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
@@ -40,6 +43,9 @@ CONFIG_FLASH_CFI_DRIVER=y
 CONFIG_CFI_FLASH=y
 CONFIG_SYS_FLASH_PROTECTION=y
 CONFIG_SYS_FLASH_CFI=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6348_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6358_USBH_PHY=y
 CONFIG_DM_RESET=y
-- 
2.11.0

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

* [U-Boot] [PATCH v10 17/28] bmips: enable nb4-ser enet support
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                         ` (15 preceding siblings ...)
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 16/28] bmips: enable hg556a enet support Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 18/28] net: add support for bcm6368-enet Álvaro Fernández Rojas
                         ` (11 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: no changes
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/sfr,nb4-ser.dts     | 24 ++++++++++++++++++++++++
 configs/sfr_nb4-ser_ram_defconfig |  8 +++++++-
 2 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/sfr,nb4-ser.dts b/arch/mips/dts/sfr,nb4-ser.dts
index bdc6f8ae45..dfbc4148dc 100644
--- a/arch/mips/dts/sfr,nb4-ser.dts
+++ b/arch/mips/dts/sfr,nb4-ser.dts
@@ -53,6 +53,30 @@
 	status = "okay";
 };
 
+&enet0 {
+	status = "okay";
+	phy = <&enet0phy>;
+	phy-mode = "internal";
+
+	enet0phy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
+&enet1 {
+	status = "okay";
+	phy = <&enet1phy>;
+	phy-mode = "mii";
+
+	enet1phy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
diff --git a/configs/sfr_nb4-ser_ram_defconfig b/configs/sfr_nb4-ser_ram_defconfig
index 12adfb01e7..39622875b1 100644
--- a/configs/sfr_nb4-ser_ram_defconfig
+++ b/configs/sfr_nb4-ser_ram_defconfig
@@ -26,11 +26,14 @@ CONFIG_CMD_LICENSE=y
 CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="sfr,nb4-ser"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
@@ -42,6 +45,9 @@ CONFIG_FLASH_CFI_DRIVER=y
 CONFIG_CFI_FLASH=y
 CONFIG_SYS_FLASH_PROTECTION=y
 CONFIG_SYS_FLASH_CFI=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6348_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6358_USBH_PHY=y
 CONFIG_DM_RESET=y
-- 
2.11.0

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

* [U-Boot] [PATCH v10 18/28] net: add support for bcm6368-enet
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                         ` (16 preceding siblings ...)
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 17/28] bmips: enable nb4-ser " Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-30 16:58         ` Daniel Schwierzeck
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 19/28] bmips: bcm6368: " Álvaro Fernández Rojas
                         ` (10 subsequent siblings)
  28 siblings, 1 reply; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: Introduce changes suggested by Daniel Schwierzeck:
  - Fix license identifiers.
  - Remove packet queue.
  - Move dma_prepare_rcv_buf to free_pkt.
  - Pad packets smaller than ETH_ZLEN.
  - Switch to live DM live tree.
 v9: introduce flow control improvements from bcm6348-eth:
  - introduce rx packets caching functionality from bcm6348-eth to fix flow
   control issues.
  - code style fixes.
 v8: introduce bcm6368-enet driver

 drivers/net/Kconfig       |   8 +
 drivers/net/Makefile      |   1 +
 drivers/net/bcm6368-eth.c | 625 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 634 insertions(+)
 create mode 100644 drivers/net/bcm6368-eth.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 2b7cec8804..7044c6adf3 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -82,6 +82,14 @@ config BCM6348_ETH
 	help
 	  This driver supports the BCM6348 Ethernet MAC.
 
+config BCM6368_ETH
+	bool "BCM6368 EMAC support"
+	depends on DM_ETH && ARCH_BMIPS
+	select DMA
+	select MII
+	help
+	  This driver supports the BCM6368 Ethernet MAC.
+
 config DWC_ETH_QOS
 	bool "Synopsys DWC Ethernet QOS device support"
 	depends on DM_ETH
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 2647d4dd23..0dbfa03306 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_ALTERA_TSE) += altera_tse.o
 obj-$(CONFIG_AG7XXX) += ag7xxx.o
 obj-$(CONFIG_ARMADA100_FEC) += armada100_fec.o
 obj-$(CONFIG_BCM6348_ETH) += bcm6348-eth.o
+obj-$(CONFIG_BCM6368_ETH) += bcm6368-eth.o
 obj-$(CONFIG_DRIVER_AT91EMAC) += at91_emac.o
 obj-$(CONFIG_DRIVER_AX88180) += ax88180.o
 obj-$(CONFIG_BCM_SF2_ETH) += bcm-sf2-eth.o
diff --git a/drivers/net/bcm6368-eth.c b/drivers/net/bcm6368-eth.c
new file mode 100644
index 0000000000..a31efba9d1
--- /dev/null
+++ b/drivers/net/bcm6368-eth.c
@@ -0,0 +1,625 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c:
+ *	Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dma.h>
+#include <miiphy.h>
+#include <net.h>
+#include <reset.h>
+#include <wait_bit.h>
+#include <asm/io.h>
+
+#define ETH_PORT_STR			"brcm,enetsw-port"
+
+#define ETH_RX_DESC			PKTBUFSRX
+#define ETH_ZLEN			60
+#define ETH_TIMEOUT			100
+
+#define ETH_MAX_PORT			8
+#define ETH_RGMII_PORT0			4
+
+/* Port traffic control */
+#define ETH_PTCTRL_REG(x)		(0x0 + (x))
+#define ETH_PTCTRL_RXDIS_SHIFT		0
+#define ETH_PTCTRL_RXDIS_MASK		(1 << ETH_PTCTRL_RXDIS_SHIFT)
+#define ETH_PTCTRL_TXDIS_SHIFT		1
+#define ETH_PTCTRL_TXDIS_MASK		(1 << ETH_PTCTRL_TXDIS_SHIFT)
+
+/* Switch mode register */
+#define ETH_SWMODE_REG			0xb
+#define ETH_SWMODE_FWD_EN_SHIFT		1
+#define ETH_SWMODE_FWD_EN_MASK		(1 << ETH_SWMODE_FWD_EN_SHIFT)
+
+/* IMP override Register */
+#define ETH_IMPOV_REG			0xe
+#define ETH_IMPOV_LINKUP_SHIFT		0
+#define ETH_IMPOV_LINKUP_MASK		(1 << ETH_IMPOV_LINKUP_SHIFT)
+#define ETH_IMPOV_FDX_SHIFT		1
+#define ETH_IMPOV_FDX_MASK		(1 << ETH_IMPOV_FDX_SHIFT)
+#define ETH_IMPOV_100_SHIFT		2
+#define ETH_IMPOV_100_MASK		(1 << ETH_IMPOV_100_SHIFT)
+#define ETH_IMPOV_1000_SHIFT		3
+#define ETH_IMPOV_1000_MASK		(1 << ETH_IMPOV_1000_SHIFT)
+#define ETH_IMPOV_RXFLOW_SHIFT		4
+#define ETH_IMPOV_RXFLOW_MASK		(1 << ETH_IMPOV_RXFLOW_SHIFT)
+#define ETH_IMPOV_TXFLOW_SHIFT		5
+#define ETH_IMPOV_TXFLOW_MASK		(1 << ETH_IMPOV_TXFLOW_SHIFT)
+#define ETH_IMPOV_FORCE_SHIFT		7
+#define ETH_IMPOV_FORCE_MASK		(1 << ETH_IMPOV_FORCE_SHIFT)
+
+/* Port override Register */
+#define ETH_PORTOV_REG(x)		(0x58 + (x))
+#define ETH_PORTOV_LINKUP_SHIFT		0
+#define ETH_PORTOV_LINKUP_MASK		(1 << ETH_PORTOV_LINKUP_SHIFT)
+#define ETH_PORTOV_FDX_SHIFT		1
+#define ETH_PORTOV_FDX_MASK		(1 << ETH_PORTOV_FDX_SHIFT)
+#define ETH_PORTOV_100_SHIFT		2
+#define ETH_PORTOV_100_MASK		(1 << ETH_PORTOV_100_SHIFT)
+#define ETH_PORTOV_1000_SHIFT		3
+#define ETH_PORTOV_1000_MASK		(1 << ETH_PORTOV_1000_SHIFT)
+#define ETH_PORTOV_RXFLOW_SHIFT		4
+#define ETH_PORTOV_RXFLOW_MASK		(1 << ETH_PORTOV_RXFLOW_SHIFT)
+#define ETH_PORTOV_TXFLOW_SHIFT		5
+#define ETH_PORTOV_TXFLOW_MASK		(1 << ETH_PORTOV_TXFLOW_SHIFT)
+#define ETH_PORTOV_ENABLE_SHIFT		6
+#define ETH_PORTOV_ENABLE_MASK		(1 << ETH_PORTOV_ENABLE_SHIFT)
+
+/* Port RGMII control register */
+#define ETH_RGMII_CTRL_REG(x)		(0x60 + (x))
+#define ETH_RGMII_CTRL_GMII_CLK_EN	(1 << 7)
+#define ETH_RGMII_CTRL_MII_OVERRIDE_EN	(1 << 6)
+#define ETH_RGMII_CTRL_MII_MODE_MASK	(3 << 4)
+#define ETH_RGMII_CTRL_RGMII_MODE	(0 << 4)
+#define ETH_RGMII_CTRL_MII_MODE		(1 << 4)
+#define ETH_RGMII_CTRL_RVMII_MODE	(2 << 4)
+#define ETH_RGMII_CTRL_TIMING_SEL_EN	(1 << 0)
+
+/* Port RGMII timing register */
+#define ENETSW_RGMII_TIMING_REG(x)	(0x68 + (x))
+
+/* MDIO control register */
+#define MII_SC_REG			0xb0
+#define MII_SC_EXT_SHIFT		16
+#define MII_SC_EXT_MASK			(1 << MII_SC_EXT_SHIFT)
+#define MII_SC_REG_SHIFT		20
+#define MII_SC_PHYID_SHIFT		25
+#define MII_SC_RD_SHIFT			30
+#define MII_SC_RD_MASK			(1 << MII_SC_RD_SHIFT)
+#define MII_SC_WR_SHIFT			31
+#define MII_SC_WR_MASK			(1 << MII_SC_WR_SHIFT)
+
+/* MDIO data register */
+#define MII_DAT_REG			0xb4
+
+/* Global Management Configuration Register */
+#define ETH_GMCR_REG			0x200
+#define ETH_GMCR_RST_MIB_SHIFT		0
+#define ETH_GMCR_RST_MIB_MASK		(1 << ETH_GMCR_RST_MIB_SHIFT)
+
+/* Jumbo control register port mask register */
+#define ETH_JMBCTL_PORT_REG		0x4004
+
+/* Jumbo control mib good frame register */
+#define ETH_JMBCTL_MAXSIZE_REG		0x4008
+
+/* ETH port data */
+struct bcm_enetsw_port {
+	bool used;
+	const char *name;
+	/* Config */
+	bool bypass_link;
+	int force_speed;
+	bool force_duplex_full;
+	/* PHY */
+	int phy_id;
+};
+
+/* ETH data */
+struct bcm6368_eth_priv {
+	void __iomem *base;
+	/* DMA */
+	struct dma rx_dma;
+	struct dma tx_dma;
+	/* Ports */
+	uint8_t num_ports;
+	struct bcm_enetsw_port used_ports[ETH_MAX_PORT];
+	int sw_port_link[ETH_MAX_PORT];
+	bool rgmii_override;
+	bool rgmii_timing;
+	/* PHY */
+	int phy_id;
+};
+
+static inline bool bcm_enet_port_is_rgmii(int portid)
+{
+	return portid >= ETH_RGMII_PORT0;
+}
+
+static int bcm6368_mdio_read(struct bcm6368_eth_priv *priv, uint8_t ext,
+			     int phy_id, int reg)
+{
+	uint32_t val;
+
+	writel_be(0, priv->base + MII_SC_REG);
+
+	val = MII_SC_RD_MASK |
+	      (phy_id << MII_SC_PHYID_SHIFT) |
+	      (reg << MII_SC_REG_SHIFT);
+
+	if (ext)
+		val |= MII_SC_EXT_MASK;
+
+	writel_be(val, priv->base + MII_SC_REG);
+	udelay(50);
+
+	return readw_be(priv->base + MII_DAT_REG);
+}
+
+static int bcm6368_mdio_write(struct bcm6368_eth_priv *priv, uint8_t ext,
+			      int phy_id, int reg, u16 data)
+{
+	uint32_t val;
+
+	writel_be(0, priv->base + MII_SC_REG);
+
+	val = MII_SC_WR_MASK |
+	      (phy_id << MII_SC_PHYID_SHIFT) |
+	      (reg << MII_SC_REG_SHIFT);
+
+	if (ext)
+		val |= MII_SC_EXT_MASK;
+
+	val |= data;
+
+	writel_be(val, priv->base + MII_SC_REG);
+	udelay(50);
+
+	return 0;
+}
+
+static int bcm6368_eth_free_pkt(struct udevice *dev, uchar *packet, int len)
+{
+	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+
+	return dma_prepare_rcv_buf(&priv->rx_dma, packet, len);
+}
+
+static int bcm6368_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+
+	return dma_receive(&priv->rx_dma, (void**)packetp, NULL);
+}
+
+static int bcm6368_eth_send(struct udevice *dev, void *packet, int length)
+{
+	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+
+	/* pad packets smaller than ETH_ZLEN */
+	if (length < ETH_ZLEN) {
+		memset(packet + length, 0, ETH_ZLEN - length);
+		length = ETH_ZLEN;
+	}
+
+	return dma_send(&priv->tx_dma, packet, length, NULL);
+}
+
+static int bcm6368_eth_adjust_link(struct udevice *dev)
+{
+	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+	unsigned int i;
+
+	for (i = 0; i < priv->num_ports; i++) {
+		struct bcm_enetsw_port *port;
+		int val, j, up, adv, lpa, speed, duplex, media;
+		int external_phy = bcm_enet_port_is_rgmii(i);
+		u8 override;
+
+		port = &priv->used_ports[i];
+		if (!port->used)
+			continue;
+
+		if (port->bypass_link)
+			continue;
+
+		/* dummy read to clear */
+		for (j = 0; j < 2; j++)
+			val = bcm6368_mdio_read(priv, external_phy,
+						port->phy_id, MII_BMSR);
+
+		if (val == 0xffff)
+			continue;
+
+		up = (val & BMSR_LSTATUS) ? 1 : 0;
+		if (!(up ^ priv->sw_port_link[i]))
+			continue;
+
+		priv->sw_port_link[i] = up;
+
+		/* link changed */
+		if (!up) {
+			dev_info(&priv->pdev->dev, "link DOWN on %s\n",
+				 port->name);
+			writeb_be(ETH_PORTOV_ENABLE_MASK,
+				  priv->base + ETH_PORTOV_REG(i));
+			writeb_be(ETH_PTCTRL_RXDIS_MASK |
+				  ETH_PTCTRL_TXDIS_MASK,
+				  priv->base + ETH_PTCTRL_REG(i));
+			continue;
+		}
+
+		adv = bcm6368_mdio_read(priv, external_phy,
+					port->phy_id, MII_ADVERTISE);
+
+		lpa = bcm6368_mdio_read(priv, external_phy, port->phy_id,
+					MII_LPA);
+
+		/* figure out media and duplex from advertise and LPA values */
+		media = mii_nway_result(lpa & adv);
+		duplex = (media & ADVERTISE_FULL) ? 1 : 0;
+
+		if (media & (ADVERTISE_100FULL | ADVERTISE_100HALF))
+			speed = 100;
+		else
+			speed = 10;
+
+		if (val & BMSR_ESTATEN) {
+			adv = bcm6368_mdio_read(priv, external_phy,
+						port->phy_id, MII_CTRL1000);
+
+			lpa = bcm6368_mdio_read(priv, external_phy,
+						port->phy_id, MII_STAT1000);
+
+			if ((adv & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)) &&
+			    (lpa & (LPA_1000FULL | LPA_1000HALF))) {
+				speed = 1000;
+				duplex = (lpa & LPA_1000FULL);
+			}
+		}
+
+		pr_alert("link UP on %s, %dMbps, %s-duplex\n",
+			 port->name, speed, duplex ? "full" : "half");
+
+		override = ETH_PORTOV_ENABLE_MASK |
+			   ETH_PORTOV_LINKUP_MASK;
+
+		if (speed == 1000)
+			override |= ETH_PORTOV_1000_MASK;
+		else if (speed == 100)
+			override |= ETH_PORTOV_100_MASK;
+		if (duplex)
+			override |= ETH_PORTOV_FDX_MASK;
+
+		writeb_be(override, priv->base + ETH_PORTOV_REG(i));
+		writeb_be(0, priv->base + ETH_PTCTRL_REG(i));
+	}
+
+	return 0;
+}
+
+static int bcm6368_eth_start(struct udevice *dev)
+{
+	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+	uint8_t i;
+
+	/* prepare rx dma buffers */
+	for (i = 0; i < ETH_RX_DESC; i++) {
+		int ret = dma_prepare_rcv_buf(&priv->rx_dma, net_rx_packets[i],
+					      PKTSIZE_ALIGN);
+		if (ret < 0)
+			break;
+	}
+
+	/* enable dma rx channel */
+	dma_enable(&priv->rx_dma);
+
+	/* enable dma tx channel */
+	dma_enable(&priv->tx_dma);
+
+	/* apply override config for bypass_link ports here. */
+	for (i = 0; i < priv->num_ports; i++) {
+		struct bcm_enetsw_port *port;
+		u8 override;
+
+		port = &priv->used_ports[i];
+		if (!port->used)
+			continue;
+
+		if (!port->bypass_link)
+			continue;
+
+		override = ETH_PORTOV_ENABLE_MASK |
+			   ETH_PORTOV_LINKUP_MASK;
+
+		switch (port->force_speed) {
+		case 1000:
+			override |= ETH_PORTOV_1000_MASK;
+			break;
+		case 100:
+			override |= ETH_PORTOV_100_MASK;
+			break;
+		case 10:
+			break;
+		default:
+			pr_warn("%s: invalid forced speed on port %s\n",
+				__func__, port->name);
+			break;
+		}
+
+		if (port->force_duplex_full)
+			override |= ETH_PORTOV_FDX_MASK;
+
+		writeb_be(override, priv->base + ETH_PORTOV_REG(i));
+		writeb_be(0, priv->base + ETH_PTCTRL_REG(i));
+	}
+
+	bcm6368_eth_adjust_link(dev);
+
+	return 0;
+}
+
+static void bcm6368_eth_stop(struct udevice *dev)
+{
+	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+
+	/* disable dma rx channel */
+	dma_disable(&priv->rx_dma);
+
+	/* disable dma tx channel */
+	dma_disable(&priv->tx_dma);
+}
+
+static const struct eth_ops bcm6368_eth_ops = {
+	.free_pkt = bcm6368_eth_free_pkt,
+	.recv = bcm6368_eth_recv,
+	.send = bcm6368_eth_send,
+	.start = bcm6368_eth_start,
+	.stop = bcm6368_eth_stop,
+};
+
+static const struct udevice_id bcm6368_eth_ids[] = {
+	{ .compatible = "brcm,bcm6368-enet", },
+	{ /* sentinel */ }
+};
+
+static bool bcm6368_phy_is_external(struct bcm6368_eth_priv *priv, int phy_id)
+{
+	uint8_t i;
+
+	for (i = 0; i < priv->num_ports; ++i) {
+		if (!priv->used_ports[i].used)
+			continue;
+		if (priv->used_ports[i].phy_id == phy_id)
+			return bcm_enet_port_is_rgmii(i);
+	}
+
+	return true;
+}
+
+static int bcm6368_mii_mdio_read(struct mii_dev *bus, int addr, int devaddr,
+				 int reg)
+{
+	struct bcm6368_eth_priv *priv = bus->priv;
+	bool ext = bcm6368_phy_is_external(priv, addr);
+
+	return bcm6368_mdio_read(priv, ext, addr, reg);
+}
+
+static int bcm6368_mii_mdio_write(struct mii_dev *bus, int addr, int devaddr,
+				  int reg, u16 data)
+{
+	struct bcm6368_eth_priv *priv = bus->priv;
+	bool ext = bcm6368_phy_is_external(priv, addr);
+
+	return bcm6368_mdio_write(priv, ext, addr, reg, data);
+}
+
+static int bcm6368_mdio_init(const char *name, struct bcm6368_eth_priv *priv)
+{
+	struct mii_dev *bus;
+
+	bus = mdio_alloc();
+	if (!bus) {
+		pr_err("%s: failed to allocate MDIO bus\n", __func__);
+		return -ENOMEM;
+	}
+
+	bus->read = bcm6368_mii_mdio_read;
+	bus->write = bcm6368_mii_mdio_write;
+	bus->priv = priv;
+	snprintf(bus->name, sizeof(bus->name), "%s", name);
+
+	return mdio_register(bus);
+}
+
+static int bcm6368_eth_probe(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+	int num_ports, ret, i;
+	uint32_t val;
+	ofnode node;
+
+	/* get base address */
+	priv->base = dev_remap_addr(dev);
+	if (!priv->base)
+		return -EINVAL;
+	pdata->iobase = (phys_addr_t) priv->base;
+
+	/* get number of ports */
+	num_ports = dev_read_u32_default(dev, "brcm,num-ports", ETH_MAX_PORT);
+	if (!num_ports || num_ports > ETH_MAX_PORT)
+		return -EINVAL;
+
+	/* get dma channels */
+	ret = dma_get_by_name(dev, "tx", &priv->tx_dma);
+	if (ret)
+		return -EINVAL;
+
+	ret = dma_get_by_name(dev, "rx", &priv->rx_dma);
+	if (ret)
+		return -EINVAL;
+
+	/* try to enable clocks */
+	for (i = 0; ; i++) {
+		struct clk clk;
+		int ret;
+
+		ret = clk_get_by_index(dev, i, &clk);
+		if (ret < 0)
+			break;
+
+		ret = clk_enable(&clk);
+		if (ret < 0) {
+			pr_err("%s: error enabling clock %d\n", __func__, i);
+			return ret;
+		}
+
+		ret = clk_free(&clk);
+		if (ret < 0) {
+			pr_err("%s: error freeing clock %d\n", __func__, i);
+			return ret;
+		}
+	}
+
+	/* try to perform resets */
+	for (i = 0; ; i++) {
+		struct reset_ctl reset;
+		int ret;
+
+		ret = reset_get_by_index(dev, i, &reset);
+		if (ret < 0)
+			break;
+
+		ret = reset_deassert(&reset);
+		if (ret < 0) {
+			pr_err("%s: error deasserting reset %d\n", __func__, i);
+			return ret;
+		}
+
+		ret = reset_free(&reset);
+		if (ret < 0) {
+			pr_err("%s: error freeing reset %d\n", __func__, i);
+			return ret;
+		}
+	}
+
+	/* set priv data */
+	priv->num_ports = num_ports;
+	if (dev_read_bool(dev, "brcm,rgmii-override"))
+		priv->rgmii_override = true;
+	if (dev_read_bool(dev, "brcm,rgmii-timing"))
+		priv->rgmii_timing = true;
+
+	/* get ports */
+	dev_for_each_subnode(node, dev) {
+		const char *comp;
+		const char *label;
+		unsigned int p;
+		int phy_id;
+		int speed;
+
+		comp = ofnode_read_string(node, "compatible");
+		if (!comp || memcmp(comp, ETH_PORT_STR, sizeof(ETH_PORT_STR)))
+			continue;
+
+		p = ofnode_read_u32_default(node, "reg", ETH_MAX_PORT);
+		if (p >= num_ports)
+			return -EINVAL;
+
+		label = ofnode_read_string(node, "label");
+		if (!label) {
+			debug("%s: node %s has no label\n", __func__,
+			      ofnode_get_name(node));
+			return -EINVAL;
+		}
+
+		phy_id = ofnode_read_u32_default(node, "brcm,phy-id", -1);
+
+		priv->used_ports[p].used = true;
+		priv->used_ports[p].name = label;
+		priv->used_ports[p].phy_id = phy_id;
+
+		if (ofnode_read_bool(node, "full-duplex"))
+			priv->used_ports[p].force_duplex_full = true;
+		if (ofnode_read_bool(node, "bypass-link"))
+			priv->used_ports[p].bypass_link = true;
+		speed = ofnode_read_u32_default(node, "speed", 0);
+		if (speed)
+			priv->used_ports[p].force_speed = speed;
+	}
+
+	/* init mii bus */
+	ret = bcm6368_mdio_init(dev->name, priv);
+	if (ret)
+		return ret;
+
+	/* disable all ports */
+	for (i = 0; i < priv->num_ports; i++) {
+		writeb_be(ETH_PORTOV_ENABLE_MASK,
+			      priv->base + ETH_PORTOV_REG(i));
+		writeb_be(ETH_PTCTRL_RXDIS_MASK |
+			      ETH_PTCTRL_TXDIS_MASK,
+			      priv->base + ETH_PTCTRL_REG(i));
+
+		priv->sw_port_link[i] = 0;
+	}
+
+	/* enable external ports */
+	for (i = ETH_RGMII_PORT0; i < priv->num_ports; i++) {
+		u8 rgmii_ctrl;
+
+		if (!priv->used_ports[i].used)
+			continue;
+
+		rgmii_ctrl = readb_be(priv->base + ETH_RGMII_CTRL_REG(i));
+		rgmii_ctrl |= ETH_RGMII_CTRL_GMII_CLK_EN;
+		if (priv->rgmii_override)
+			rgmii_ctrl |= ETH_RGMII_CTRL_MII_OVERRIDE_EN;
+		if (priv->rgmii_timing)
+			rgmii_ctrl |= ETH_RGMII_CTRL_TIMING_SEL_EN;
+		writeb_be(rgmii_ctrl, priv->base + ETH_RGMII_CTRL_REG(i));
+	}
+
+	/* reset mib */
+	val = readb_be(priv->base + ETH_GMCR_REG);
+	val |= ETH_GMCR_RST_MIB_MASK;
+	writeb_be(val, priv->base + ETH_GMCR_REG);
+	mdelay(1);
+	val &= ~ETH_GMCR_RST_MIB_MASK;
+	writeb_be(val, priv->base + ETH_GMCR_REG);
+	mdelay(1);
+
+	/* force CPU port state */
+	val = readb_be(priv->base + ETH_IMPOV_REG);
+	val |= ETH_IMPOV_FORCE_MASK | ETH_IMPOV_LINKUP_MASK;
+	writeb_be(val, priv->base + ETH_IMPOV_REG);
+
+	/* enable switch forward engine */
+	val = readb_be(priv->base + ETH_SWMODE_REG);
+	val |= ETH_SWMODE_FWD_EN_MASK;
+	writeb_be(val, priv->base + ETH_SWMODE_REG);
+
+	/* enable jumbo on all ports */
+	writel_be(0x1ff, priv->base + ETH_JMBCTL_PORT_REG);
+	writew_be(9728, priv->base + ETH_JMBCTL_MAXSIZE_REG);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(bcm6368_eth) = {
+	.name = "bcm6368_eth",
+	.id = UCLASS_ETH,
+	.of_match = bcm6368_eth_ids,
+	.ops = &bcm6368_eth_ops,
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+	.priv_auto_alloc_size = sizeof(struct bcm6368_eth_priv),
+	.probe = bcm6368_eth_probe,
+};
-- 
2.11.0

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

* [U-Boot] [PATCH v10 19/28] bmips: bcm6368: add support for bcm6368-enet
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                         ` (17 preceding siblings ...)
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 18/28] net: add support for bcm6368-enet Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 20/28] bmips: enable wap-5813n enet support Álvaro Fernández Rojas
                         ` (9 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: no changes
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6368.dtsi | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6368.dtsi b/arch/mips/dts/brcm,bcm6368.dtsi
index 30047f6360..89590d6ff9 100644
--- a/arch/mips/dts/brcm,bcm6368.dtsi
+++ b/arch/mips/dts/brcm,bcm6368.dtsi
@@ -205,5 +205,24 @@
 			#dma-cells = <1>;
 			dma-channels = <8>;
 		};
+
+		enet: ethernet at 10f00000 {
+			compatible = "brcm,bcm6368-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x10f00000 0x10000>;
+			clocks = <&periph_clk BCM6368_CLK_SWPKT_USB>,
+				 <&periph_clk BCM6368_CLK_SWPKT_SAR>,
+				 <&periph_clk BCM6368_CLK_ROBOSW>;
+			resets = <&periph_rst BCM6368_RST_SWITCH>,
+				 <&periph_rst BCM6368_RST_EPHY>;
+			dmas = <&iudma BCM6368_DMA_ENETSW_RX>,
+			       <&iudma BCM6368_DMA_ENETSW_TX>;
+			dma-names = "rx",
+				    "tx";
+			brcm,num-ports = <6>;
+
+			status = "disabled";
+		};
 	};
 };
-- 
2.11.0

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

* [U-Boot] [PATCH v10 20/28] bmips: enable wap-5813n enet support
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                         ` (18 preceding siblings ...)
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 19/28] bmips: bcm6368: " Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 21/28] bmips: bcm6328: add support for bcm6368-enet Álvaro Fernández Rojas
                         ` (8 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: no changes
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/comtrend,wap-5813n.dts    | 14 ++++++++++++++
 configs/comtrend_wap5813n_ram_defconfig |  8 +++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/comtrend,wap-5813n.dts b/arch/mips/dts/comtrend,wap-5813n.dts
index bd41dab9f8..7e835b28d2 100644
--- a/arch/mips/dts/comtrend,wap-5813n.dts
+++ b/arch/mips/dts/comtrend,wap-5813n.dts
@@ -54,6 +54,20 @@
 	status = "okay";
 };
 
+&enet {
+	status = "okay";
+
+	port at 4 {
+		compatible = "brcm,enetsw-port";
+		reg = <4>;
+		label = "rgmii";
+		brcm,phy-id = <0xff>;
+		speed = <1000>;
+		full-duplex;
+		bypass-link;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
diff --git a/configs/comtrend_wap5813n_ram_defconfig b/configs/comtrend_wap5813n_ram_defconfig
index 987e4c3fbc..fd5107bb7d 100644
--- a/configs/comtrend_wap5813n_ram_defconfig
+++ b/configs/comtrend_wap5813n_ram_defconfig
@@ -25,11 +25,14 @@ CONFIG_CMD_LICENSE=y
 CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="comtrend,wap-5813n"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
@@ -40,6 +43,9 @@ CONFIG_FLASH_CFI_DRIVER=y
 CONFIG_CFI_FLASH=y
 CONFIG_SYS_FLASH_PROTECTION=y
 CONFIG_SYS_FLASH_CFI=y
+CONFIG_DM_ETH=y
+CONFIG_PHY_GIGE=y
+CONFIG_BCM6368_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6368_USBH_PHY=y
 CONFIG_DM_RESET=y
-- 
2.11.0

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

* [U-Boot] [PATCH v10 21/28] bmips: bcm6328: add support for bcm6368-enet
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                         ` (19 preceding siblings ...)
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 20/28] bmips: enable wap-5813n enet support Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 22/28] bmips: enable ar-5387un enet support Álvaro Fernández Rojas
                         ` (7 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: no changes
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6328.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6328.dtsi b/arch/mips/dts/brcm,bcm6328.dtsi
index 6fa49e22bb..50beed4171 100644
--- a/arch/mips/dts/brcm,bcm6328.dtsi
+++ b/arch/mips/dts/brcm,bcm6328.dtsi
@@ -200,5 +200,22 @@
 			#dma-cells = <1>;
 			dma-channels = <8>;
 		};
+
+		enet: ethernet at 10e00000 {
+			compatible = "brcm,bcm6368-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x10e00000 0x10000>;
+			clocks = <&periph_clk BCM6328_CLK_ROBOSW>;
+			resets = <&periph_rst BCM6328_RST_ENETSW>,
+				 <&periph_rst BCM6328_RST_EPHY>;
+			dmas = <&iudma BCM6328_DMA_ENETSW_RX>,
+			       <&iudma BCM6328_DMA_ENETSW_TX>;
+			dma-names = "rx",
+				    "tx";
+			brcm,num-ports = <5>;
+
+			status = "disabled";
+		};
 	};
 };
-- 
2.11.0

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

* [U-Boot] [PATCH v10 22/28] bmips: enable ar-5387un enet support
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                         ` (20 preceding siblings ...)
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 21/28] bmips: bcm6328: add support for bcm6368-enet Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 23/28] bmips: bcm6362: add support for bcm6368-enet Álvaro Fernández Rojas
                         ` (6 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: no changes
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/comtrend,ar-5387un.dts    | 32 ++++++++++++++++++++++++++++++++
 configs/comtrend_ar5387un_ram_defconfig |  7 ++++++-
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/comtrend,ar-5387un.dts b/arch/mips/dts/comtrend,ar-5387un.dts
index e993b5cd89..03e3851ab1 100644
--- a/arch/mips/dts/comtrend,ar-5387un.dts
+++ b/arch/mips/dts/comtrend,ar-5387un.dts
@@ -24,6 +24,38 @@
 	status = "okay";
 };
 
+&enet {
+	status = "okay";
+
+	port at 0 {
+		compatible = "brcm,enetsw-port";
+		reg = <0>;
+		label = "fe1";
+		brcm,phy-id = <1>;
+	};
+
+	port at 1 {
+		compatible = "brcm,enetsw-port";
+		reg = <1>;
+		label = "fe2";
+		brcm,phy-id = <2>;
+	};
+
+	port at 2 {
+		compatible = "brcm,enetsw-port";
+		reg = <2>;
+		label = "fe3";
+		brcm,phy-id = <3>;
+	};
+
+	port at 3 {
+		compatible = "brcm,enetsw-port";
+		reg = <3>;
+		label = "fe4";
+		brcm,phy-id = <4>;
+	};
+};
+
 &leds {
 	status = "okay";
 
diff --git a/configs/comtrend_ar5387un_ram_defconfig b/configs/comtrend_ar5387un_ram_defconfig
index f129870ca0..5ba401a441 100644
--- a/configs/comtrend_ar5387un_ram_defconfig
+++ b/configs/comtrend_ar5387un_ram_defconfig
@@ -28,11 +28,14 @@ CONFIG_CMD_MEMINFO=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="comtrend,ar-5387un"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_LED=y
 CONFIG_LED_BCM6328=y
@@ -41,6 +44,8 @@ CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_MACRONIX=y
 CONFIG_SPI_FLASH_MTD=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6368_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6368_USBH_PHY=y
 CONFIG_POWER_DOMAIN=y
-- 
2.11.0

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

* [U-Boot] [PATCH v10 23/28] bmips: bcm6362: add support for bcm6368-enet
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                         ` (21 preceding siblings ...)
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 22/28] bmips: enable ar-5387un enet support Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 24/28] bmips: enable dgnd3700v2 enet support Álvaro Fernández Rojas
                         ` (5 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: no changes
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6362.dtsi | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6362.dtsi b/arch/mips/dts/brcm,bcm6362.dtsi
index 94e7de096d..c77b80a4cc 100644
--- a/arch/mips/dts/brcm,bcm6362.dtsi
+++ b/arch/mips/dts/brcm,bcm6362.dtsi
@@ -224,5 +224,24 @@
 			#dma-cells = <1>;
 			dma-channels = <8>;
 		};
+
+		enet: ethernet at 10e00000 {
+			compatible = "brcm,bcm6368-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x10e00000 0x10000>;
+			clocks = <&periph_clk BCM6362_CLK_SWPKT_USB>,
+				 <&periph_clk BCM6362_CLK_SWPKT_SAR>,
+				 <&periph_clk BCM6362_CLK_ROBOSW>;
+			resets = <&periph_rst BCM6362_RST_ENETSW>,
+				 <&periph_rst BCM6362_RST_EPHY>;
+			dmas = <&iudma BCM6362_DMA_ENETSW_RX>,
+			       <&iudma BCM6362_DMA_ENETSW_TX>;
+			dma-names = "rx",
+				    "tx";
+			brcm,num-ports = <6>;
+
+			status = "disabled";
+		};
 	};
 };
-- 
2.11.0

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

* [U-Boot] [PATCH v10 24/28] bmips: enable dgnd3700v2 enet support
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                         ` (22 preceding siblings ...)
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 23/28] bmips: bcm6362: add support for bcm6368-enet Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 25/28] bmips: bcm63268: add support for bcm6368-enet Álvaro Fernández Rojas
                         ` (4 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: no changes
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/netgear,dgnd3700v2.dts     | 14 ++++++++++++++
 configs/netgear_dgnd3700v2_ram_defconfig |  8 +++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/netgear,dgnd3700v2.dts b/arch/mips/dts/netgear,dgnd3700v2.dts
index 322d1567ff..2b72491f0b 100644
--- a/arch/mips/dts/netgear,dgnd3700v2.dts
+++ b/arch/mips/dts/netgear,dgnd3700v2.dts
@@ -43,6 +43,20 @@
 	status = "okay";
 };
 
+&enet {
+	status = "okay";
+
+	port at 4 {
+		compatible = "brcm,enetsw-port";
+		reg = <4>;
+		label = "rgmii";
+		brcm,phy-id = <0xff>;
+		speed = <1000>;
+		full-duplex;
+		bypass-link;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
diff --git a/configs/netgear_dgnd3700v2_ram_defconfig b/configs/netgear_dgnd3700v2_ram_defconfig
index 1abc869856..0f3914fe7e 100644
--- a/configs/netgear_dgnd3700v2_ram_defconfig
+++ b/configs/netgear_dgnd3700v2_ram_defconfig
@@ -27,17 +27,23 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
-# CONFIG_CMD_NET is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="netgear,dgnd3700v2"
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
 CONFIG_LED_BCM6328=y
 CONFIG_LED_BLINK=y
 CONFIG_LED_GPIO=y
+CONFIG_DM_ETH=y
+CONFIG_PHY_GIGE=y
+CONFIG_BCM6368_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6368_USBH_PHY=y
 CONFIG_POWER_DOMAIN=y
-- 
2.11.0

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

* [U-Boot] [PATCH v10 25/28] bmips: bcm63268: add support for bcm6368-enet
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                         ` (23 preceding siblings ...)
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 24/28] bmips: enable dgnd3700v2 enet support Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 26/28] bmips: enable vr-3032u enet support Álvaro Fernández Rojas
                         ` (3 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: no changes
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm63268.dtsi | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm63268.dtsi b/arch/mips/dts/brcm,bcm63268.dtsi
index c7ad83c306..f8a72ef535 100644
--- a/arch/mips/dts/brcm,bcm63268.dtsi
+++ b/arch/mips/dts/brcm,bcm63268.dtsi
@@ -230,5 +230,30 @@
 			#dma-cells = <1>;
 			dma-channels = <8>;
 		};
+
+		enet: ethernet at 10700000 {
+			compatible = "brcm,bcm6368-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x10700000 0x10000>;
+			clocks = <&periph_clk BCM63268_CLK_GMAC>,
+				 <&periph_clk BCM63268_CLK_ROBOSW>,
+				 <&periph_clk BCM63268_CLK_ROBOSW250>,
+				 <&timer_clk BCM63268_TCLK_EPHY1>,
+				 <&timer_clk BCM63268_TCLK_EPHY2>,
+				 <&timer_clk BCM63268_TCLK_EPHY3>,
+				 <&timer_clk BCM63268_TCLK_GPHY>;
+			resets = <&periph_rst BCM63268_RST_ENETSW>,
+				 <&periph_rst BCM63268_RST_EPHY>,
+				 <&periph_rst BCM63268_RST_GPHY>;
+			dmas = <&iudma BCM63268_DMA_ENETSW_RX>,
+			       <&iudma BCM63268_DMA_ENETSW_TX>;
+			dma-names = "rx",
+				    "tx";
+			brcm,rgmii-override;
+			brcm,rgmii-timing;
+
+			status = "disabled";
+		};
 	};
 };
-- 
2.11.0

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

* [U-Boot] [PATCH v10 26/28] bmips: enable vr-3032u enet support
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                         ` (24 preceding siblings ...)
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 25/28] bmips: bcm63268: add support for bcm6368-enet Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 27/28] bmips: bcm6318: add support for bcm6368-enet Álvaro Fernández Rojas
                         ` (2 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: no changes
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/comtrend,vr-3032u.dts    | 32 ++++++++++++++++++++++++++++++++
 configs/comtrend_vr3032u_ram_defconfig |  7 ++++++-
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/comtrend,vr-3032u.dts b/arch/mips/dts/comtrend,vr-3032u.dts
index 8c6a4a1eac..512cb52de3 100644
--- a/arch/mips/dts/comtrend,vr-3032u.dts
+++ b/arch/mips/dts/comtrend,vr-3032u.dts
@@ -24,6 +24,38 @@
 	status = "okay";
 };
 
+&enet {
+	status = "okay";
+
+	port at 0 {
+		compatible = "brcm,enetsw-port";
+		reg = <0>;
+		label = "fe2";
+		brcm,phy-id = <1>;
+	};
+
+	port at 1 {
+		compatible = "brcm,enetsw-port";
+		reg = <1>;
+		label = "fe3";
+		brcm,phy-id = <2>;
+	};
+
+	port at 2 {
+		compatible = "brcm,enetsw-port";
+		reg = <2>;
+		label = "fe4";
+		brcm,phy-id = <3>;
+	};
+
+	port at 3 {
+		compatible = "brcm,enetsw-port";
+		reg = <3>;
+		label = "fe1";
+		brcm,phy-id = <4>;
+	};
+};
+
 &leds {
 	status = "okay";
 	brcm,serial-leds;
diff --git a/configs/comtrend_vr3032u_ram_defconfig b/configs/comtrend_vr3032u_ram_defconfig
index 1689eecec1..47f53998e1 100644
--- a/configs/comtrend_vr3032u_ram_defconfig
+++ b/configs/comtrend_vr3032u_ram_defconfig
@@ -26,15 +26,20 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="comtrend,vr-3032u"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_LED=y
 CONFIG_LED_BCM6328=y
 CONFIG_LED_BLINK=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6368_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6368_USBH_PHY=y
 CONFIG_POWER_DOMAIN=y
-- 
2.11.0

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

* [U-Boot] [PATCH v10 27/28] bmips: bcm6318: add support for bcm6368-enet
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                         ` (25 preceding siblings ...)
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 26/28] bmips: enable vr-3032u enet support Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 28/28] bmips: enable ar-5315u enet support Álvaro Fernández Rojas
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: no changes
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6318.dtsi           | 19 +++++++++++++++++++
 include/dt-bindings/clock/bcm6318-clock.h | 11 +++++++++++
 2 files changed, 30 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6318.dtsi b/arch/mips/dts/brcm,bcm6318.dtsi
index d04b7cbb01..d678dab242 100644
--- a/arch/mips/dts/brcm,bcm6318.dtsi
+++ b/arch/mips/dts/brcm,bcm6318.dtsi
@@ -190,6 +190,25 @@
 			status = "disabled";
 		};
 
+		enet: ethernet at 10080000 {
+			compatible = "brcm,bcm6368-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x10080000 0x8000>;
+			clocks = <&periph_clk BCM6318_CLK_ROBOSW250>,
+				 <&periph_clk BCM6318_CLK_ROBOSW025>,
+				 <&ubus_clk BCM6318_UCLK_ROBOSW>;
+			resets = <&periph_rst BCM6318_RST_ENETSW>,
+				 <&periph_rst BCM6318_RST_EPHY>;
+			dmas = <&iudma BCM6318_DMA_ENETSW_RX>,
+			       <&iudma BCM6318_DMA_ENETSW_TX>;
+			dma-names = "rx",
+				    "tx";
+			brcm,num-ports = <5>;
+
+			status = "disabled";
+		};
+
 		iudma: dma-controller at 10088000 {
 			compatible = "brcm,bcm6368-iudma";
 			reg = <0x10088000 0x80>,
diff --git a/include/dt-bindings/clock/bcm6318-clock.h b/include/dt-bindings/clock/bcm6318-clock.h
index d5e13c5c2d..3f10448cef 100644
--- a/include/dt-bindings/clock/bcm6318-clock.h
+++ b/include/dt-bindings/clock/bcm6318-clock.h
@@ -33,4 +33,15 @@
 #define BCM6318_CLK_AFE		29
 #define BCM6318_CLK_QPROC	30
 
+#define BCM6318_UCLK_ADSL	0
+#define BCM6318_UCLK_ARB	1
+#define BCM6318_UCLK_MIPS	2
+#define BCM6318_UCLK_PCIE	3
+#define BCM6318_UCLK_PERIPH	4
+#define BCM6318_UCLK_PHYMIPS	5
+#define BCM6318_UCLK_ROBOSW	6
+#define BCM6318_UCLK_SAR	7
+#define BCM6318_UCLK_SDR	8
+#define BCM6318_UCLK_USB	9
+
 #endif /* __DT_BINDINGS_CLOCK_BCM6318_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v10 28/28] bmips: enable ar-5315u enet support
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                         ` (26 preceding siblings ...)
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 27/28] bmips: bcm6318: add support for bcm6368-enet Álvaro Fernández Rojas
@ 2018-11-29 22:25       ` Álvaro Fernández Rojas
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-29 22:25 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v10: no changes
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/comtrend,ar-5315u.dts    | 32 ++++++++++++++++++++++++++++++++
 configs/comtrend_ar5315u_ram_defconfig |  7 ++++++-
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/comtrend,ar-5315u.dts b/arch/mips/dts/comtrend,ar-5315u.dts
index 45570189d0..eb60aaa8d5 100644
--- a/arch/mips/dts/comtrend,ar-5315u.dts
+++ b/arch/mips/dts/comtrend,ar-5315u.dts
@@ -24,6 +24,38 @@
 	status = "okay";
 };
 
+&enet {
+	status = "okay";
+
+	port at 0 {
+		compatible = "brcm,enetsw-port";
+		reg = <0>;
+		label = "fe4";
+		brcm,phy-id = <1>;
+	};
+
+	port at 1 {
+		compatible = "brcm,enetsw-port";
+		reg = <1>;
+		label = "fe3";
+		brcm,phy-id = <2>;
+	};
+
+	port at 2 {
+		compatible = "brcm,enetsw-port";
+		reg = <2>;
+		label = "fe2";
+		brcm,phy-id = <3>;
+	};
+
+	port at 3 {
+		compatible = "brcm,enetsw-port";
+		reg = <3>;
+		label = "fe1";
+		brcm,phy-id = <4>;
+	};
+};
+
 &leds {
 	status = "okay";
 
diff --git a/configs/comtrend_ar5315u_ram_defconfig b/configs/comtrend_ar5315u_ram_defconfig
index d9ef52e68d..1b8e4e43c4 100644
--- a/configs/comtrend_ar5315u_ram_defconfig
+++ b/configs/comtrend_ar5315u_ram_defconfig
@@ -28,11 +28,14 @@ CONFIG_CMD_MEMINFO=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="comtrend,ar-5315u"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_LED=y
 CONFIG_LED_BCM6328=y
@@ -41,6 +44,8 @@ CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_SPI_FLASH_MTD=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6368_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6318_USBH_PHY=y
 CONFIG_BCM6328_POWER_DOMAIN=y
-- 
2.11.0

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

* [U-Boot] [PATCH v10 01/28] dma: add bcm6348-iudma support
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 01/28] dma: add bcm6348-iudma support Álvaro Fernández Rojas
@ 2018-11-30 13:46         ` Daniel Schwierzeck
  2018-11-30 17:13           ` Álvaro Fernández Rojas
  0 siblings, 1 reply; 145+ messages in thread
From: Daniel Schwierzeck @ 2018-11-30 13:46 UTC (permalink / raw)
  To: u-boot



Am 29.11.18 um 23:25 schrieb Álvaro Fernández Rojas:
> BCM6348 IUDMA controller is present on multiple BMIPS (BCM63xx) SoCs.
> 
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> ---
>  v10: Introduce changes suggested by Daniel Schwierzeck:
>   - Fix license identifiers.
>   - Move DMAD_ST defines out of dma desc struct definition.
>   - Remove unneded aigned attribute from dma desc struct definition.
>   - Fill dma ring from consumer driver instead of allocating a new buffer.
>   - Correctly check clock/reset errors while probing.
>   - Switch to live DM live tree.
>  v9: introduce dma_prepare_rcv_buf dma op:
>   - bcm6348_iudma_chan_stop: switch to mdelay when resetting channel.
>   - bcm6348_iudma_receive: track dirty dma descriptors and no longer trigger
>    dma rx channel.
>   - bcm6348_iudma_send: reorder to properly flush cache and set dma descriptor
>    config.
>   - bcm6348_iudma_prepare_rcv_buf: implemented to clear dirty dma descriptors.
>  v8: Introduce changes from Grygorii Strashko
>  v5: Several fixes and improvements:
>   - Remove unused defines.
>   - Increment rx descriptors.
>   - Fix flow control issues.
>   - Error checking now depends on hw.
>   - Remove unneeded interrupts.
>  v4: Fix issues reported by Grygorii Strashko and other fixes:
>   - Remove usage of net_rx_packets as buffer.
>   - Allocate dynamic rx buffer.
>   - Check dma errors and discard invalid packets.
>  v3: no changes
>  v2: Fix dma rx burst config and select DMA_CHANNELS.
> 
>  drivers/dma/Kconfig         |   9 +
>  drivers/dma/Makefile        |   1 +
>  drivers/dma/bcm6348-iudma.c | 642 ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 652 insertions(+)
>  create mode 100644 drivers/dma/bcm6348-iudma.c

Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

only one nit left

> 
> diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
> index 8a4162eccd..1820676d7a 100644
> --- a/drivers/dma/Kconfig
> +++ b/drivers/dma/Kconfig
> @@ -26,6 +26,15 @@ config SANDBOX_DMA
>  	  Enable support for a test DMA uclass implementation. It stimulates
>  	  DMA transfer by simple copying data between channels.
>  
> +config BCM6348_IUDMA
> +	bool "BCM6348 IUDMA driver"
> +	depends on ARCH_BMIPS
> +	select DMA_CHANNELS
> +	help
> +	  Enable the BCM6348 IUDMA driver.
> +	  This driver support data transfer from devices to
> +	  memory and from memory to devices.
> +
>  config TI_EDMA3
>  	bool "TI EDMA3 driver"
>  	help
> diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
> index aff31f986a..b5f9147e0a 100644
> --- a/drivers/dma/Makefile
> +++ b/drivers/dma/Makefile
> @@ -7,6 +7,7 @@ obj-$(CONFIG_DMA) += dma-uclass.o
>  
>  obj-$(CONFIG_FSLDMAFEC) += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o
>  obj-$(CONFIG_APBH_DMA) += apbh_dma.o
> +obj-$(CONFIG_BCM6348_IUDMA) += bcm6348-iudma.o
>  obj-$(CONFIG_FSL_DMA) += fsl_dma.o
>  obj-$(CONFIG_SANDBOX_DMA) += sandbox-dma-test.o
>  obj-$(CONFIG_TI_KSNAV) += keystone_nav.o keystone_nav_cfg.o
> diff --git a/drivers/dma/bcm6348-iudma.c b/drivers/dma/bcm6348-iudma.c
> new file mode 100644
> index 0000000000..699f1a6754
> --- /dev/null
> +++ b/drivers/dma/bcm6348-iudma.c
> @@ -0,0 +1,642 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
> + *
> + * Derived from linux/drivers/dma/bcm63xx-iudma.c:
> + *	Copyright (C) 2015 Simon Arlott <simon@fire.lp0.eu>
> + *
> + * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c:
> + *	Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
> + *
> + * Derived from bcm963xx_4.12L.06B_consumer/shared/opensource/include/bcm963xx/63268_map_part.h:
> + *	Copyright (C) 2000-2010 Broadcom Corporation
> + *
> + * Derived from bcm963xx_4.12L.06B_consumer/bcmdrivers/opensource/net/enet/impl4/bcmenet.c:
> + *	Copyright (C) 2010 Broadcom Corporation
> + */
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <dma-uclass.h>
> +#include <memalign.h>
> +#include <reset.h>
> +#include <asm/io.h>
> +
> +#define DMA_RX_DESC	6
> +#define DMA_TX_DESC	1
> +
> +/* DMA Channels */
> +#define DMA_CHAN_FLOWC(x)		((x) >> 1)
> +#define DMA_CHAN_MAX			16
> +#define DMA_CHAN_SIZE			0x10
> +#define DMA_CHAN_TOUT			500
> +
> +/* DMA Global Configuration register */
> +#define DMA_CFG_REG			0x00
> +#define  DMA_CFG_ENABLE_SHIFT		0
> +#define  DMA_CFG_ENABLE_MASK		(1 << DMA_CFG_ENABLE_SHIFT)
> +#define  DMA_CFG_FLOWC_ENABLE(x)	BIT(DMA_CHAN_FLOWC(x) + 1)
> +#define  DMA_CFG_NCHANS_SHIFT		24
> +#define  DMA_CFG_NCHANS_MASK		(0xf << DMA_CFG_NCHANS_SHIFT)
> +
> +/* DMA Global Flow Control registers */
> +#define DMA_FLOWC_THR_LO_REG(x)		(0x04 + DMA_CHAN_FLOWC(x) * 0x0c)
> +#define DMA_FLOWC_THR_HI_REG(x)		(0x08 + DMA_CHAN_FLOWC(x) * 0x0c)
> +#define DMA_FLOWC_ALLOC_REG(x)		(0x0c + DMA_CHAN_FLOWC(x) * 0x0c)
> +#define  DMA_FLOWC_ALLOC_FORCE_SHIFT	31
> +#define  DMA_FLOWC_ALLOC_FORCE_MASK	(1 << DMA_FLOWC_ALLOC_FORCE_SHIFT)
> +
> +/* DMA Global Reset register */
> +#define DMA_RST_REG			0x34
> +#define  DMA_RST_CHAN_SHIFT		0
> +#define  DMA_RST_CHAN_MASK(x)		(1 << x)
> +
> +/* DMA Channel Configuration register */
> +#define DMAC_CFG_REG(x)			(DMA_CHAN_SIZE * (x) + 0x00)
> +#define  DMAC_CFG_ENABLE_SHIFT		0
> +#define  DMAC_CFG_ENABLE_MASK		(1 << DMAC_CFG_ENABLE_SHIFT)
> +#define  DMAC_CFG_PKT_HALT_SHIFT	1
> +#define  DMAC_CFG_PKT_HALT_MASK		(1 << DMAC_CFG_PKT_HALT_SHIFT)
> +#define  DMAC_CFG_BRST_HALT_SHIFT	2
> +#define  DMAC_CFG_BRST_HALT_MASK	(1 << DMAC_CFG_BRST_HALT_SHIFT)
> +
> +/* DMA Channel Max Burst Length register */
> +#define DMAC_BURST_REG(x)		(DMA_CHAN_SIZE * (x) + 0x0c)
> +
> +/* DMA SRAM Descriptor Ring Start register */
> +#define DMAS_RSTART_REG(x)		(DMA_CHAN_SIZE * (x) + 0x00)
> +
> +/* DMA SRAM State/Bytes done/ring offset register */
> +#define DMAS_STATE_DATA_REG(x)		(DMA_CHAN_SIZE * (x) + 0x04)
> +
> +/* DMA SRAM Buffer Descriptor status and length register */
> +#define DMAS_DESC_LEN_STATUS_REG(x)	(DMA_CHAN_SIZE * (x) + 0x08)
> +
> +/* DMA SRAM Buffer Descriptor status and length register */
> +#define DMAS_DESC_BASE_BUFPTR_REG(x)	(DMA_CHAN_SIZE * (x) + 0x0c)
> +
> +/* DMA Descriptor Status */
> +#define DMAD_ST_CRC_SHIFT		8
> +#define DMAD_ST_CRC_MASK		(1 << DMAD_ST_CRC_SHIFT)
> +#define DMAD_ST_WRAP_SHIFT		12
> +#define DMAD_ST_WRAP_MASK		(1 << DMAD_ST_WRAP_SHIFT)
> +#define DMAD_ST_SOP_SHIFT		13
> +#define DMAD_ST_SOP_MASK		(1 << DMAD_ST_SOP_SHIFT)
> +#define DMAD_ST_EOP_SHIFT		14
> +#define DMAD_ST_EOP_MASK		(1 << DMAD_ST_EOP_SHIFT)
> +#define DMAD_ST_OWN_SHIFT		15
> +#define DMAD_ST_OWN_MASK		(1 << DMAD_ST_OWN_SHIFT)
> +
> +#define DMAD6348_ST_OV_ERR_SHIFT	0
> +#define DMAD6348_ST_OV_ERR_MASK		(1 << DMAD6348_ST_OV_ERR_SHIFT)
> +#define DMAD6348_ST_CRC_ERR_SHIFT	1
> +#define DMAD6348_ST_CRC_ERR_MASK	(1 << DMAD6348_ST_CRC_ERR_SHIFT)
> +#define DMAD6348_ST_RX_ERR_SHIFT	2
> +#define DMAD6348_ST_RX_ERR_MASK		(1 << DMAD6348_ST_RX_ERR_SHIFT)
> +#define DMAD6348_ST_OS_ERR_SHIFT	4
> +#define DMAD6348_ST_OS_ERR_MASK		(1 << DMAD6348_ST_OS_ERR_SHIFT)
> +#define DMAD6348_ST_UN_ERR_SHIFT	9
> +#define DMAD6348_ST_UN_ERR_MASK		(1 << DMAD6348_ST_UN_ERR_SHIFT)
> +
> +struct bcm6348_dma_desc {
> +	uint16_t length;
> +	uint16_t status;
> +	uint32_t address;
> +};
> +
> +struct bcm6348_chan_priv {
> +	void __iomem *dma_ring;
> +	uint8_t dma_ring_size;
> +	uint8_t desc_id;
> +	uint8_t desc_cnt;
> +	bool *busy_desc;
> +	bool running;
> +};
> +
> +struct bcm6348_iudma_hw {
> +	uint16_t err_mask;
> +};
> +
> +struct bcm6348_iudma_priv {
> +	const struct bcm6348_iudma_hw *hw;
> +	void __iomem *base;
> +	void __iomem *chan;
> +	void __iomem *sram;
> +	struct bcm6348_chan_priv **ch_priv;
> +	uint8_t n_channels;
> +};
> +
> +static inline bool bcm6348_iudma_chan_is_rx(uint8_t ch)
> +{
> +	return !(ch & 1);
> +}
> +
> +static inline void bcm6348_iudma_fdc(void *ptr, ulong size)
> +{
> +	ulong start = (ulong) ptr;
> +
> +	flush_dcache_range(start, start + size);
> +}
> +
> +static inline void bcm6348_iudma_idc(void *ptr, ulong size)
> +{
> +	ulong start = (ulong) ptr;
> +
> +	invalidate_dcache_range(start, start + size);
> +}
> +
> +static void bcm6348_iudma_chan_stop(struct bcm6348_iudma_priv *priv,
> +				    uint8_t ch)
> +{
> +	unsigned int timeout = DMA_CHAN_TOUT;
> +
> +	do {
> +		uint32_t cfg, halt;
> +
> +		if (timeout > DMA_CHAN_TOUT / 2)
> +			halt = DMAC_CFG_PKT_HALT_MASK;
> +		else
> +			halt = DMAC_CFG_BRST_HALT_MASK;
> +
> +		/* try to stop dma channel */
> +		writel_be(halt, priv->chan + DMAC_CFG_REG(ch));
> +		mb();
> +
> +		/* check if channel was stopped */
> +		cfg = readl_be(priv->chan + DMAC_CFG_REG(ch));
> +		if (!(cfg & DMAC_CFG_ENABLE_MASK))
> +			break;
> +
> +		udelay(1);
> +	} while (--timeout);
> +
> +	if (!timeout)
> +		pr_err("unable to stop channel %u\n", ch);
> +
> +	/* reset dma channel */
> +	setbits_be32(priv->base + DMA_RST_REG, DMA_RST_CHAN_MASK(ch));
> +	mb();
> +	clrbits_be32(priv->base + DMA_RST_REG, DMA_RST_CHAN_MASK(ch));
> +}
> +
> +static int bcm6348_iudma_disable(struct dma *dma)
> +{
> +	struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
> +	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
> +
> +	/* stop dma channel */
> +	bcm6348_iudma_chan_stop(priv, dma->id);
> +
> +	/* dma flow control */
> +	if (bcm6348_iudma_chan_is_rx(dma->id))
> +		writel_be(DMA_FLOWC_ALLOC_FORCE_MASK,
> +			  DMA_FLOWC_ALLOC_REG(dma->id));
> +
> +	/* init channel config */
> +	ch_priv->running = false;
> +	ch_priv->desc_id = 0;
> +	if (bcm6348_iudma_chan_is_rx(dma->id))
> +		ch_priv->desc_cnt = 0;
> +	else
> +		ch_priv->desc_cnt = ch_priv->dma_ring_size;
> +
> +	return 0;
> +}
> +
> +static int bcm6348_iudma_enable(struct dma *dma)
> +{
> +	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
> +	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
> +	struct bcm6348_dma_desc *dma_desc = ch_priv->dma_ring;
> +	uint8_t i;
> +
> +	/* dma ring init */
> +	for (i = 0; i < ch_priv->desc_cnt; i++) {
> +		if (bcm6348_iudma_chan_is_rx(dma->id)) {
> +			ch_priv->busy_desc[i] = false;
> +			dma_desc->status |= DMAD_ST_OWN_MASK;
> +		} else {
> +			dma_desc->status = 0;
> +			dma_desc->length = 0;
> +			dma_desc->address = 0;
> +		}
> +
> +		if (i == ch_priv->desc_cnt - 1)
> +			dma_desc->status |= DMAD_ST_WRAP_MASK;
> +
> +		dma_desc++;
> +	}
> +
> +	/* init to first descriptor */
> +	ch_priv->desc_id = 0;
> +
> +	/* force cache writeback */
> +	bcm6348_iudma_fdc(ch_priv->dma_ring,
> +			  sizeof(*dma_desc) * ch_priv->desc_cnt);
> +
> +	/* clear sram */
> +	writel_be(0, priv->sram + DMAS_STATE_DATA_REG(dma->id));
> +	writel_be(0, priv->sram + DMAS_DESC_LEN_STATUS_REG(dma->id));
> +	writel_be(0, priv->sram + DMAS_DESC_BASE_BUFPTR_REG(dma->id));
> +
> +	/* set dma ring start */
> +	writel_be(virt_to_phys(ch_priv->dma_ring),
> +		  priv->sram + DMAS_RSTART_REG(dma->id));
> +
> +	/* set flow control */
> +	if (bcm6348_iudma_chan_is_rx(dma->id)) {
> +		u32 val;
> +
> +		setbits_be32(priv->base + DMA_CFG_REG,
> +			     DMA_CFG_FLOWC_ENABLE(dma->id));
> +
> +		val = ch_priv->desc_cnt / 3;
> +		writel_be(val, priv->base + DMA_FLOWC_THR_LO_REG(dma->id));
> +
> +		val = (ch_priv->desc_cnt * 2) / 3;
> +		writel_be(val, priv->base + DMA_FLOWC_THR_HI_REG(dma->id));
> +
> +		writel_be(0, priv->base + DMA_FLOWC_ALLOC_REG(dma->id));
> +	}
> +
> +	/* set dma max burst */
> +	writel_be(ch_priv->desc_cnt,
> +		  priv->chan + DMAC_BURST_REG(dma->id));
> +
> +	/* kick rx dma channel */
> +	if (bcm6348_iudma_chan_is_rx(dma->id))
> +		setbits_be32(priv->chan + DMAC_CFG_REG(dma->id),
> +			     DMAC_CFG_ENABLE_MASK);
> +
> +	/* channel is now enabled */
> +	ch_priv->running = true;
> +
> +	return 0;
> +}
> +
> +static int bcm6348_iudma_request(struct dma *dma)
> +{
> +	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
> +	struct bcm6348_chan_priv *ch_priv;
> +
> +	/* check if channel is valid */
> +	if (dma->id >= priv->n_channels)
> +		return -ENODEV;
> +
> +	/* alloc channel private data */
> +	priv->ch_priv[dma->id] = calloc(1, sizeof(struct bcm6348_chan_priv));
> +	if (!priv->ch_priv[dma->id])
> +		return -ENOMEM;
> +	ch_priv = priv->ch_priv[dma->id];
> +
> +	/* alloc dma ring */
> +	if (bcm6348_iudma_chan_is_rx(dma->id))
> +		ch_priv->dma_ring_size = DMA_RX_DESC;
> +	else
> +		ch_priv->dma_ring_size = DMA_TX_DESC;
> +
> +	ch_priv->dma_ring =
> +		malloc_cache_aligned(sizeof(struct bcm6348_dma_desc) *
> +				     ch_priv->dma_ring_size);
> +	if (!ch_priv->dma_ring)
> +		return -ENOMEM;
> +
> +	/* init channel config */
> +	ch_priv->running = false;
> +	ch_priv->desc_id = 0;
> +	if (bcm6348_iudma_chan_is_rx(dma->id)) {
> +		ch_priv->desc_cnt = 0;
> +		ch_priv->busy_desc = calloc(ch_priv->desc_cnt, sizeof(bool));
> +	} else {
> +		ch_priv->desc_cnt = ch_priv->dma_ring_size;
> +		ch_priv->busy_desc = NULL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int bcm6348_iudma_receive(struct dma *dma, void **dst, void *metadata)
> +{
> +	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
> +	const struct bcm6348_iudma_hw *hw = priv->hw;
> +	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
> +	struct bcm6348_dma_desc *dma_desc = dma_desc = ch_priv->dma_ring;
> +	int ret;
> +
> +	/* get dma ring descriptor address */
> +	dma_desc += ch_priv->desc_id;
> +
> +	/* invalidate cache data */
> +	bcm6348_iudma_idc(dma_desc, sizeof(*dma_desc));
> +
> +	/* check dma own */
> +	if (dma_desc->status & DMAD_ST_OWN_MASK)
> +		return -EAGAIN;
> +
> +	/* check pkt */
> +	if (!(dma_desc->status & DMAD_ST_EOP_MASK) ||
> +	    !(dma_desc->status & DMAD_ST_SOP_MASK) ||
> +	    (dma_desc->status & hw->err_mask)) {
> +		pr_err("invalid pkt received (ch=%ld desc=%u) (st=%04x)\n",
> +		       dma->id, ch_priv->desc_id, dma_desc->status);
> +		ret = -EAGAIN;
> +	} else {
> +		/* set dma buffer address */
> +		*dst = phys_to_virt(dma_desc->address);
> +
> +		/* invalidate cache data */
> +		bcm6348_iudma_idc(*dst, dma_desc->length);
> +
> +		/* remove crc */
> +		ret = dma_desc->length - 4;

is CRC a feature of the DMA engine or does this belong to the ethernet
driver?

> +	}
> +
> +	/* busy dma descriptor */
> +	ch_priv->busy_desc[ch_priv->desc_id] = true;
> +
> +	/* increment dma descriptor */
> +	ch_priv->desc_id = (ch_priv->desc_id + 1) % ch_priv->desc_cnt;
> +
> +	return ret;
> +}
> +
> +static int bcm6348_iudma_send(struct dma *dma, void *src, size_t len,
> +			      void *metadata)
> +{
> +	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
> +	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
> +	struct bcm6348_dma_desc *dma_desc;
> +	uint16_t status;
> +
> +	/* flush cache */
> +	bcm6348_iudma_fdc(src, len);
> +
> +	/* get dma ring descriptor address */
> +	dma_desc = ch_priv->dma_ring;
> +	dma_desc += ch_priv->desc_id;
> +
> +	/* config dma descriptor */
> +	status = (DMAD_ST_OWN_MASK |
> +		  DMAD_ST_EOP_MASK |
> +		  DMAD_ST_CRC_MASK |
> +		  DMAD_ST_SOP_MASK);
> +	if (ch_priv->desc_id == ch_priv->desc_cnt - 1)
> +		status |= DMAD_ST_WRAP_MASK;
> +
> +	/* set dma descriptor */
> +	dma_desc->address = virt_to_phys(src);
> +	dma_desc->length = len;
> +	dma_desc->status = status;
> +
> +	/* flush cache */
> +	bcm6348_iudma_fdc(dma_desc, sizeof(*dma_desc));
> +
> +	/* kick tx dma channel */
> +	setbits_be32(priv->chan + DMAC_CFG_REG(dma->id), DMAC_CFG_ENABLE_MASK);
> +
> +	/* poll dma status */
> +	do {
> +		/* invalidate cache */
> +		bcm6348_iudma_idc(dma_desc, sizeof(*dma_desc));
> +
> +		if (!(dma_desc->status & DMAD_ST_OWN_MASK))
> +			break;
> +	} while(1);
> +
> +	/* increment dma descriptor */
> +	ch_priv->desc_id = (ch_priv->desc_id + 1) % ch_priv->desc_cnt;
> +
> +	return 0;
> +}
> +
> +static int bcm6348_iudma_free_rcv_buf(struct dma *dma, void *dst, size_t size)
> +{
> +	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
> +	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
> +	struct bcm6348_dma_desc *dma_desc = ch_priv->dma_ring;
> +	uint16_t status;
> +	uint8_t i;
> +	u32 cfg;
> +
> +	/* get dirty dma descriptor */
> +	for (i = 0; i < ch_priv->desc_cnt; i++) {
> +		if (phys_to_virt(dma_desc->address) == dst)
> +			break;
> +
> +		dma_desc++;
> +	}
> +
> +	/* dma descriptor not found */
> +	if (i == ch_priv->desc_cnt) {
> +		pr_err("dirty dma descriptor not found\n");
> +		return -ENOENT;
> +	}
> +
> +	/* invalidate cache */
> +	bcm6348_iudma_idc(ch_priv->dma_ring,
> +			  sizeof(*dma_desc) * ch_priv->desc_cnt);
> +
> +	/* free dma descriptor */
> +	ch_priv->busy_desc[i] = false;
> +
> +	status = DMAD_ST_OWN_MASK;
> +	if (i == ch_priv->desc_cnt - 1)
> +		status |= DMAD_ST_WRAP_MASK;
> +
> +	dma_desc->status |= status;
> +	dma_desc->length = PKTSIZE_ALIGN;
> +
> +	/* tell dma we allocated one buffer */
> +	writel_be(1, DMA_FLOWC_ALLOC_REG(dma->id));
> +
> +	/* flush cache */
> +	bcm6348_iudma_fdc(ch_priv->dma_ring,
> +			  sizeof(*dma_desc) * ch_priv->desc_cnt);
> +
> +	/* kick rx dma channel if disabled */
> +	cfg = readl_be(priv->chan + DMAC_CFG_REG(dma->id));
> +	if (!(cfg & DMAC_CFG_ENABLE_MASK))
> +		setbits_be32(priv->chan + DMAC_CFG_REG(dma->id),
> +			     DMAC_CFG_ENABLE_MASK);
> +
> +	return 0;
> +}
> +
> +static int bcm6348_iudma_add_rcv_buf(struct dma *dma, void *dst, size_t size)
> +{
> +	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
> +	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
> +	struct bcm6348_dma_desc *dma_desc = ch_priv->dma_ring;
> +
> +	/* no more dma descriptors available */
> +	if (ch_priv->desc_cnt == ch_priv->dma_ring_size) {
> +		pr_err("max number of buffers reached\n");
> +		return -EINVAL;
> +	}
> +
> +	/* get next dma descriptor */
> +	dma_desc += ch_priv->desc_cnt;
> +
> +	/* init dma descriptor */
> +	dma_desc->address = virt_to_phys(dst);
> +	dma_desc->length = size;
> +	dma_desc->status = 0;
> +
> +	/* flush cache */
> +	bcm6348_iudma_fdc(dma_desc, sizeof(*dma_desc));
> +
> +	/* increment dma descriptors */
> +	ch_priv->desc_cnt++;
> +
> +	return 0;
> +}
> +
> +static int bcm6348_iudma_prepare_rcv_buf(struct dma *dma, void *dst,
> +					 size_t size)
> +{
> +	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
> +	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
> +
> +	/* only add new rx buffers if channel isn't running */
> +	if (ch_priv->running)
> +		return bcm6348_iudma_free_rcv_buf(dma, dst, size);
> +	else
> +		return bcm6348_iudma_add_rcv_buf(dma, dst, size);
> +}
> +
> +static const struct dma_ops bcm6348_iudma_ops = {
> +	.disable = bcm6348_iudma_disable,
> +	.enable = bcm6348_iudma_enable,
> +	.prepare_rcv_buf = bcm6348_iudma_prepare_rcv_buf,
> +	.request = bcm6348_iudma_request,
> +	.receive = bcm6348_iudma_receive,
> +	.send = bcm6348_iudma_send,
> +};
> +
> +static const struct bcm6348_iudma_hw bcm6348_hw = {
> +	.err_mask = (DMAD6348_ST_OV_ERR_MASK |
> +		     DMAD6348_ST_CRC_ERR_MASK |
> +		     DMAD6348_ST_RX_ERR_MASK |
> +		     DMAD6348_ST_OS_ERR_MASK |
> +		     DMAD6348_ST_UN_ERR_MASK),
> +};
> +
> +static const struct bcm6348_iudma_hw bcm6368_hw = {
> +	.err_mask = 0,
> +};
> +
> +static const struct udevice_id bcm6348_iudma_ids[] = {
> +	{
> +		.compatible = "brcm,bcm6348-iudma",
> +		.data = (ulong)&bcm6348_hw,
> +	}, {
> +		.compatible = "brcm,bcm6368-iudma",
> +		.data = (ulong)&bcm6368_hw,
> +	}, { /* sentinel */ }
> +};
> +
> +static int bcm6348_iudma_probe(struct udevice *dev)
> +{
> +	struct dma_dev_priv *uc_priv = dev_get_uclass_priv(dev);
> +	struct bcm6348_iudma_priv *priv = dev_get_priv(dev);
> +	const struct bcm6348_iudma_hw *hw =
> +		(const struct bcm6348_iudma_hw *)dev_get_driver_data(dev);
> +	uint8_t ch;
> +	int i;
> +
> +	uc_priv->supported = (DMA_SUPPORTS_DEV_TO_MEM |
> +			      DMA_SUPPORTS_MEM_TO_DEV);
> +	priv->hw = hw;
> +
> +	/* dma global base address */
> +	priv->base = dev_remap_addr_name(dev, "dma");
> +	if (!priv->base)
> +		return -EINVAL;
> +
> +	/* dma channels base address */
> +	priv->chan = dev_remap_addr_name(dev, "dma-channels");
> +	if (!priv->chan)
> +		return -EINVAL;
> +
> +	/* dma sram base address */
> +	priv->sram = dev_remap_addr_name(dev, "dma-sram");
> +	if (!priv->sram)
> +		return -EINVAL;
> +
> +	/* get number of channels */
> +	priv->n_channels = dev_read_u32_default(dev, "dma-channels", 8);
> +	if (priv->n_channels > DMA_CHAN_MAX)
> +		return -EINVAL;
> +
> +	/* try to enable clocks */
> +	for (i = 0; ; i++) {
> +		struct clk clk;
> +		int ret;
> +
> +		ret = clk_get_by_index(dev, i, &clk);
> +		if (ret < 0)
> +			break;
> +
> +		ret = clk_enable(&clk);
> +		if (ret < 0) {
> +			pr_err("error enabling clock %d\n", i);
> +			return ret;
> +		}
> +
> +		ret = clk_free(&clk);
> +		if (ret < 0) {
> +			pr_err("error freeing clock %d\n", i);
> +			return ret;
> +		}
> +	}
> +
> +	/* try to perform resets */
> +	for (i = 0; ; i++) {
> +		struct reset_ctl reset;
> +		int ret;
> +
> +		ret = reset_get_by_index(dev, i, &reset);
> +		if (ret < 0)
> +			break;
> +
> +		ret = reset_deassert(&reset);
> +		if (ret < 0) {
> +			pr_err("error deasserting reset %d\n", i);
> +			return ret;
> +		}
> +
> +		ret = reset_free(&reset);
> +		if (ret < 0) {
> +			pr_err("error freeing reset %d\n", i);
> +			return ret;
> +		}
> +	}
> +
> +	/* disable dma controller */
> +	clrbits_be32(priv->base + DMA_CFG_REG, DMA_CFG_ENABLE_MASK);
> +
> +	/* alloc channel private data pointers */
> +	priv->ch_priv = calloc(priv->n_channels,
> +			       sizeof(struct bcm6348_chan_priv*));
> +	if (!priv->ch_priv)
> +		return -ENOMEM;
> +
> +	/* stop dma channels */
> +	for (ch = 0; ch < priv->n_channels; ch++)
> +		bcm6348_iudma_chan_stop(priv, ch);
> +
> +	/* enable dma controller */
> +	setbits_be32(priv->base + DMA_CFG_REG, DMA_CFG_ENABLE_MASK);
> +
> +	return 0;
> +}
> +
> +U_BOOT_DRIVER(bcm6348_iudma) = {
> +	.name = "bcm6348_iudma",
> +	.id = UCLASS_DMA,
> +	.of_match = bcm6348_iudma_ids,
> +	.ops = &bcm6348_iudma_ops,
> +	.priv_auto_alloc_size = sizeof(struct bcm6348_iudma_priv),
> +	.probe = bcm6348_iudma_probe,
> +};
> 

-- 
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20181130/584703df/attachment.sig>

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

* [U-Boot] [PATCH v10 10/28] net: add support for bcm6348-enet
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 10/28] net: add support for bcm6348-enet Álvaro Fernández Rojas
@ 2018-11-30 16:54         ` Daniel Schwierzeck
  0 siblings, 0 replies; 145+ messages in thread
From: Daniel Schwierzeck @ 2018-11-30 16:54 UTC (permalink / raw)
  To: u-boot



Am 29.11.18 um 23:25 schrieb Álvaro Fernández Rojas:
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> ---
>  v10: Introduce changes suggested by Daniel Schwierzeck:
>   - Fix license identifiers.
>   - Remove packet queue.
>   - Move dma_prepare_rcv_buf to free_pkt.
>   - Switch to live DM live tree.
>  v9: use dma_prepare_rcv_buf and remove dma rx channel reset:
>   - bcm6348_eth_recv: clear dirty dma descriptors only when packets are copied
>    from rx dma.
>   - bcm6348_eth_send: remove dma rx channel reset when sending packet.
>  v8: Introduce changes from Grygorii Strashko
>  v5: Receive as much packets as possible from bcm6348-eth and cache them in
>  net_rx_packets. This is needed in order to fix flow control issues.
>  v4: Fix issues reported by Grygorii Strashko and other fixes:
>   - Copy received dma buffer to net_rx_packets in order to avoid possible
>   dma overwrites.
>   - Reset dma rx channel when sending a new packet to prevent flow control
>   issues.
>   - Fix packet casting on bcm6348_eth_recv/send.
>  v3: no changes
>  v2: select DMA_CHANNELS.
> 
>  drivers/net/Kconfig            |  10 +
>  drivers/net/Makefile           |   1 +
>  drivers/net/bcm6348-eth.c      | 537 +++++++++++++++++++++++++++++++++++++++++
>  include/configs/bmips_common.h |   6 +-
>  4 files changed, 553 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/net/bcm6348-eth.c
> 

Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

-- 
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20181130/0183de2e/attachment.sig>

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

* [U-Boot] [PATCH v10 18/28] net: add support for bcm6368-enet
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 18/28] net: add support for bcm6368-enet Álvaro Fernández Rojas
@ 2018-11-30 16:58         ` Daniel Schwierzeck
  0 siblings, 0 replies; 145+ messages in thread
From: Daniel Schwierzeck @ 2018-11-30 16:58 UTC (permalink / raw)
  To: u-boot



Am 29.11.18 um 23:25 schrieb Álvaro Fernández Rojas:
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> ---
>  v10: Introduce changes suggested by Daniel Schwierzeck:
>   - Fix license identifiers.
>   - Remove packet queue.
>   - Move dma_prepare_rcv_buf to free_pkt.
>   - Pad packets smaller than ETH_ZLEN.
>   - Switch to live DM live tree.
>  v9: introduce flow control improvements from bcm6348-eth:
>   - introduce rx packets caching functionality from bcm6348-eth to fix flow
>    control issues.
>   - code style fixes.
>  v8: introduce bcm6368-enet driver
> 
>  drivers/net/Kconfig       |   8 +
>  drivers/net/Makefile      |   1 +
>  drivers/net/bcm6368-eth.c | 625 ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 634 insertions(+)
>  create mode 100644 drivers/net/bcm6368-eth.c
> 

Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>

-- 
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20181130/7fff8b45/attachment.sig>

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

* [U-Boot] [PATCH v10 01/28] dma: add bcm6348-iudma support
  2018-11-30 13:46         ` Daniel Schwierzeck
@ 2018-11-30 17:13           ` Álvaro Fernández Rojas
  0 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-11-30 17:13 UTC (permalink / raw)
  To: u-boot

Hi Daniel,

El 30/11/2018 a las 14:46, Daniel Schwierzeck escribió:
>
> Am 29.11.18 um 23:25 schrieb Álvaro Fernández Rojas:
>> BCM6348 IUDMA controller is present on multiple BMIPS (BCM63xx) SoCs.
>>
>> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
>> ---
>>   v10: Introduce changes suggested by Daniel Schwierzeck:
>>    - Fix license identifiers.
>>    - Move DMAD_ST defines out of dma desc struct definition.
>>    - Remove unneded aigned attribute from dma desc struct definition.
>>    - Fill dma ring from consumer driver instead of allocating a new buffer.
>>    - Correctly check clock/reset errors while probing.
>>    - Switch to live DM live tree.
>>   v9: introduce dma_prepare_rcv_buf dma op:
>>    - bcm6348_iudma_chan_stop: switch to mdelay when resetting channel.
>>    - bcm6348_iudma_receive: track dirty dma descriptors and no longer trigger
>>     dma rx channel.
>>    - bcm6348_iudma_send: reorder to properly flush cache and set dma descriptor
>>     config.
>>    - bcm6348_iudma_prepare_rcv_buf: implemented to clear dirty dma descriptors.
>>   v8: Introduce changes from Grygorii Strashko
>>   v5: Several fixes and improvements:
>>    - Remove unused defines.
>>    - Increment rx descriptors.
>>    - Fix flow control issues.
>>    - Error checking now depends on hw.
>>    - Remove unneeded interrupts.
>>   v4: Fix issues reported by Grygorii Strashko and other fixes:
>>    - Remove usage of net_rx_packets as buffer.
>>    - Allocate dynamic rx buffer.
>>    - Check dma errors and discard invalid packets.
>>   v3: no changes
>>   v2: Fix dma rx burst config and select DMA_CHANNELS.
>>
>>   drivers/dma/Kconfig         |   9 +
>>   drivers/dma/Makefile        |   1 +
>>   drivers/dma/bcm6348-iudma.c | 642 ++++++++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 652 insertions(+)
>>   create mode 100644 drivers/dma/bcm6348-iudma.c
> Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
>
> only one nit left
>
>> diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
>> index 8a4162eccd..1820676d7a 100644
>> --- a/drivers/dma/Kconfig
>> +++ b/drivers/dma/Kconfig
>> @@ -26,6 +26,15 @@ config SANDBOX_DMA
>>   	  Enable support for a test DMA uclass implementation. It stimulates
>>   	  DMA transfer by simple copying data between channels.
>>   
>> +config BCM6348_IUDMA
>> +	bool "BCM6348 IUDMA driver"
>> +	depends on ARCH_BMIPS
>> +	select DMA_CHANNELS
>> +	help
>> +	  Enable the BCM6348 IUDMA driver.
>> +	  This driver support data transfer from devices to
>> +	  memory and from memory to devices.
>> +
>>   config TI_EDMA3
>>   	bool "TI EDMA3 driver"
>>   	help
>> diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
>> index aff31f986a..b5f9147e0a 100644
>> --- a/drivers/dma/Makefile
>> +++ b/drivers/dma/Makefile
>> @@ -7,6 +7,7 @@ obj-$(CONFIG_DMA) += dma-uclass.o
>>   
>>   obj-$(CONFIG_FSLDMAFEC) += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o
>>   obj-$(CONFIG_APBH_DMA) += apbh_dma.o
>> +obj-$(CONFIG_BCM6348_IUDMA) += bcm6348-iudma.o
>>   obj-$(CONFIG_FSL_DMA) += fsl_dma.o
>>   obj-$(CONFIG_SANDBOX_DMA) += sandbox-dma-test.o
>>   obj-$(CONFIG_TI_KSNAV) += keystone_nav.o keystone_nav_cfg.o
>> diff --git a/drivers/dma/bcm6348-iudma.c b/drivers/dma/bcm6348-iudma.c
>> new file mode 100644
>> index 0000000000..699f1a6754
>> --- /dev/null
>> +++ b/drivers/dma/bcm6348-iudma.c
>> @@ -0,0 +1,642 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
>> + *
>> + * Derived from linux/drivers/dma/bcm63xx-iudma.c:
>> + *	Copyright (C) 2015 Simon Arlott <simon@fire.lp0.eu>
>> + *
>> + * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c:
>> + *	Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
>> + *
>> + * Derived from bcm963xx_4.12L.06B_consumer/shared/opensource/include/bcm963xx/63268_map_part.h:
>> + *	Copyright (C) 2000-2010 Broadcom Corporation
>> + *
>> + * Derived from bcm963xx_4.12L.06B_consumer/bcmdrivers/opensource/net/enet/impl4/bcmenet.c:
>> + *	Copyright (C) 2010 Broadcom Corporation
>> + */
>> +
>> +#include <common.h>
>> +#include <clk.h>
>> +#include <dm.h>
>> +#include <dma-uclass.h>
>> +#include <memalign.h>
>> +#include <reset.h>
>> +#include <asm/io.h>
>> +
>> +#define DMA_RX_DESC	6
>> +#define DMA_TX_DESC	1
>> +
>> +/* DMA Channels */
>> +#define DMA_CHAN_FLOWC(x)		((x) >> 1)
>> +#define DMA_CHAN_MAX			16
>> +#define DMA_CHAN_SIZE			0x10
>> +#define DMA_CHAN_TOUT			500
>> +
>> +/* DMA Global Configuration register */
>> +#define DMA_CFG_REG			0x00
>> +#define  DMA_CFG_ENABLE_SHIFT		0
>> +#define  DMA_CFG_ENABLE_MASK		(1 << DMA_CFG_ENABLE_SHIFT)
>> +#define  DMA_CFG_FLOWC_ENABLE(x)	BIT(DMA_CHAN_FLOWC(x) + 1)
>> +#define  DMA_CFG_NCHANS_SHIFT		24
>> +#define  DMA_CFG_NCHANS_MASK		(0xf << DMA_CFG_NCHANS_SHIFT)
>> +
>> +/* DMA Global Flow Control registers */
>> +#define DMA_FLOWC_THR_LO_REG(x)		(0x04 + DMA_CHAN_FLOWC(x) * 0x0c)
>> +#define DMA_FLOWC_THR_HI_REG(x)		(0x08 + DMA_CHAN_FLOWC(x) * 0x0c)
>> +#define DMA_FLOWC_ALLOC_REG(x)		(0x0c + DMA_CHAN_FLOWC(x) * 0x0c)
>> +#define  DMA_FLOWC_ALLOC_FORCE_SHIFT	31
>> +#define  DMA_FLOWC_ALLOC_FORCE_MASK	(1 << DMA_FLOWC_ALLOC_FORCE_SHIFT)
>> +
>> +/* DMA Global Reset register */
>> +#define DMA_RST_REG			0x34
>> +#define  DMA_RST_CHAN_SHIFT		0
>> +#define  DMA_RST_CHAN_MASK(x)		(1 << x)
>> +
>> +/* DMA Channel Configuration register */
>> +#define DMAC_CFG_REG(x)			(DMA_CHAN_SIZE * (x) + 0x00)
>> +#define  DMAC_CFG_ENABLE_SHIFT		0
>> +#define  DMAC_CFG_ENABLE_MASK		(1 << DMAC_CFG_ENABLE_SHIFT)
>> +#define  DMAC_CFG_PKT_HALT_SHIFT	1
>> +#define  DMAC_CFG_PKT_HALT_MASK		(1 << DMAC_CFG_PKT_HALT_SHIFT)
>> +#define  DMAC_CFG_BRST_HALT_SHIFT	2
>> +#define  DMAC_CFG_BRST_HALT_MASK	(1 << DMAC_CFG_BRST_HALT_SHIFT)
>> +
>> +/* DMA Channel Max Burst Length register */
>> +#define DMAC_BURST_REG(x)		(DMA_CHAN_SIZE * (x) + 0x0c)
>> +
>> +/* DMA SRAM Descriptor Ring Start register */
>> +#define DMAS_RSTART_REG(x)		(DMA_CHAN_SIZE * (x) + 0x00)
>> +
>> +/* DMA SRAM State/Bytes done/ring offset register */
>> +#define DMAS_STATE_DATA_REG(x)		(DMA_CHAN_SIZE * (x) + 0x04)
>> +
>> +/* DMA SRAM Buffer Descriptor status and length register */
>> +#define DMAS_DESC_LEN_STATUS_REG(x)	(DMA_CHAN_SIZE * (x) + 0x08)
>> +
>> +/* DMA SRAM Buffer Descriptor status and length register */
>> +#define DMAS_DESC_BASE_BUFPTR_REG(x)	(DMA_CHAN_SIZE * (x) + 0x0c)
>> +
>> +/* DMA Descriptor Status */
>> +#define DMAD_ST_CRC_SHIFT		8
>> +#define DMAD_ST_CRC_MASK		(1 << DMAD_ST_CRC_SHIFT)
>> +#define DMAD_ST_WRAP_SHIFT		12
>> +#define DMAD_ST_WRAP_MASK		(1 << DMAD_ST_WRAP_SHIFT)
>> +#define DMAD_ST_SOP_SHIFT		13
>> +#define DMAD_ST_SOP_MASK		(1 << DMAD_ST_SOP_SHIFT)
>> +#define DMAD_ST_EOP_SHIFT		14
>> +#define DMAD_ST_EOP_MASK		(1 << DMAD_ST_EOP_SHIFT)
>> +#define DMAD_ST_OWN_SHIFT		15
>> +#define DMAD_ST_OWN_MASK		(1 << DMAD_ST_OWN_SHIFT)
>> +
>> +#define DMAD6348_ST_OV_ERR_SHIFT	0
>> +#define DMAD6348_ST_OV_ERR_MASK		(1 << DMAD6348_ST_OV_ERR_SHIFT)
>> +#define DMAD6348_ST_CRC_ERR_SHIFT	1
>> +#define DMAD6348_ST_CRC_ERR_MASK	(1 << DMAD6348_ST_CRC_ERR_SHIFT)
>> +#define DMAD6348_ST_RX_ERR_SHIFT	2
>> +#define DMAD6348_ST_RX_ERR_MASK		(1 << DMAD6348_ST_RX_ERR_SHIFT)
>> +#define DMAD6348_ST_OS_ERR_SHIFT	4
>> +#define DMAD6348_ST_OS_ERR_MASK		(1 << DMAD6348_ST_OS_ERR_SHIFT)
>> +#define DMAD6348_ST_UN_ERR_SHIFT	9
>> +#define DMAD6348_ST_UN_ERR_MASK		(1 << DMAD6348_ST_UN_ERR_SHIFT)
>> +
>> +struct bcm6348_dma_desc {
>> +	uint16_t length;
>> +	uint16_t status;
>> +	uint32_t address;
>> +};
>> +
>> +struct bcm6348_chan_priv {
>> +	void __iomem *dma_ring;
>> +	uint8_t dma_ring_size;
>> +	uint8_t desc_id;
>> +	uint8_t desc_cnt;
>> +	bool *busy_desc;
>> +	bool running;
>> +};
>> +
>> +struct bcm6348_iudma_hw {
>> +	uint16_t err_mask;
>> +};
>> +
>> +struct bcm6348_iudma_priv {
>> +	const struct bcm6348_iudma_hw *hw;
>> +	void __iomem *base;
>> +	void __iomem *chan;
>> +	void __iomem *sram;
>> +	struct bcm6348_chan_priv **ch_priv;
>> +	uint8_t n_channels;
>> +};
>> +
>> +static inline bool bcm6348_iudma_chan_is_rx(uint8_t ch)
>> +{
>> +	return !(ch & 1);
>> +}
>> +
>> +static inline void bcm6348_iudma_fdc(void *ptr, ulong size)
>> +{
>> +	ulong start = (ulong) ptr;
>> +
>> +	flush_dcache_range(start, start + size);
>> +}
>> +
>> +static inline void bcm6348_iudma_idc(void *ptr, ulong size)
>> +{
>> +	ulong start = (ulong) ptr;
>> +
>> +	invalidate_dcache_range(start, start + size);
>> +}
>> +
>> +static void bcm6348_iudma_chan_stop(struct bcm6348_iudma_priv *priv,
>> +				    uint8_t ch)
>> +{
>> +	unsigned int timeout = DMA_CHAN_TOUT;
>> +
>> +	do {
>> +		uint32_t cfg, halt;
>> +
>> +		if (timeout > DMA_CHAN_TOUT / 2)
>> +			halt = DMAC_CFG_PKT_HALT_MASK;
>> +		else
>> +			halt = DMAC_CFG_BRST_HALT_MASK;
>> +
>> +		/* try to stop dma channel */
>> +		writel_be(halt, priv->chan + DMAC_CFG_REG(ch));
>> +		mb();
>> +
>> +		/* check if channel was stopped */
>> +		cfg = readl_be(priv->chan + DMAC_CFG_REG(ch));
>> +		if (!(cfg & DMAC_CFG_ENABLE_MASK))
>> +			break;
>> +
>> +		udelay(1);
>> +	} while (--timeout);
>> +
>> +	if (!timeout)
>> +		pr_err("unable to stop channel %u\n", ch);
>> +
>> +	/* reset dma channel */
>> +	setbits_be32(priv->base + DMA_RST_REG, DMA_RST_CHAN_MASK(ch));
>> +	mb();
>> +	clrbits_be32(priv->base + DMA_RST_REG, DMA_RST_CHAN_MASK(ch));
>> +}
>> +
>> +static int bcm6348_iudma_disable(struct dma *dma)
>> +{
>> +	struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
>> +	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
>> +
>> +	/* stop dma channel */
>> +	bcm6348_iudma_chan_stop(priv, dma->id);
>> +
>> +	/* dma flow control */
>> +	if (bcm6348_iudma_chan_is_rx(dma->id))
>> +		writel_be(DMA_FLOWC_ALLOC_FORCE_MASK,
>> +			  DMA_FLOWC_ALLOC_REG(dma->id));
>> +
>> +	/* init channel config */
>> +	ch_priv->running = false;
>> +	ch_priv->desc_id = 0;
>> +	if (bcm6348_iudma_chan_is_rx(dma->id))
>> +		ch_priv->desc_cnt = 0;
>> +	else
>> +		ch_priv->desc_cnt = ch_priv->dma_ring_size;
>> +
>> +	return 0;
>> +}
>> +
>> +static int bcm6348_iudma_enable(struct dma *dma)
>> +{
>> +	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
>> +	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
>> +	struct bcm6348_dma_desc *dma_desc = ch_priv->dma_ring;
>> +	uint8_t i;
>> +
>> +	/* dma ring init */
>> +	for (i = 0; i < ch_priv->desc_cnt; i++) {
>> +		if (bcm6348_iudma_chan_is_rx(dma->id)) {
>> +			ch_priv->busy_desc[i] = false;
>> +			dma_desc->status |= DMAD_ST_OWN_MASK;
>> +		} else {
>> +			dma_desc->status = 0;
>> +			dma_desc->length = 0;
>> +			dma_desc->address = 0;
>> +		}
>> +
>> +		if (i == ch_priv->desc_cnt - 1)
>> +			dma_desc->status |= DMAD_ST_WRAP_MASK;
>> +
>> +		dma_desc++;
>> +	}
>> +
>> +	/* init to first descriptor */
>> +	ch_priv->desc_id = 0;
>> +
>> +	/* force cache writeback */
>> +	bcm6348_iudma_fdc(ch_priv->dma_ring,
>> +			  sizeof(*dma_desc) * ch_priv->desc_cnt);
>> +
>> +	/* clear sram */
>> +	writel_be(0, priv->sram + DMAS_STATE_DATA_REG(dma->id));
>> +	writel_be(0, priv->sram + DMAS_DESC_LEN_STATUS_REG(dma->id));
>> +	writel_be(0, priv->sram + DMAS_DESC_BASE_BUFPTR_REG(dma->id));
>> +
>> +	/* set dma ring start */
>> +	writel_be(virt_to_phys(ch_priv->dma_ring),
>> +		  priv->sram + DMAS_RSTART_REG(dma->id));
>> +
>> +	/* set flow control */
>> +	if (bcm6348_iudma_chan_is_rx(dma->id)) {
>> +		u32 val;
>> +
>> +		setbits_be32(priv->base + DMA_CFG_REG,
>> +			     DMA_CFG_FLOWC_ENABLE(dma->id));
>> +
>> +		val = ch_priv->desc_cnt / 3;
>> +		writel_be(val, priv->base + DMA_FLOWC_THR_LO_REG(dma->id));
>> +
>> +		val = (ch_priv->desc_cnt * 2) / 3;
>> +		writel_be(val, priv->base + DMA_FLOWC_THR_HI_REG(dma->id));
>> +
>> +		writel_be(0, priv->base + DMA_FLOWC_ALLOC_REG(dma->id));
>> +	}
>> +
>> +	/* set dma max burst */
>> +	writel_be(ch_priv->desc_cnt,
>> +		  priv->chan + DMAC_BURST_REG(dma->id));
>> +
>> +	/* kick rx dma channel */
>> +	if (bcm6348_iudma_chan_is_rx(dma->id))
>> +		setbits_be32(priv->chan + DMAC_CFG_REG(dma->id),
>> +			     DMAC_CFG_ENABLE_MASK);
>> +
>> +	/* channel is now enabled */
>> +	ch_priv->running = true;
>> +
>> +	return 0;
>> +}
>> +
>> +static int bcm6348_iudma_request(struct dma *dma)
>> +{
>> +	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
>> +	struct bcm6348_chan_priv *ch_priv;
>> +
>> +	/* check if channel is valid */
>> +	if (dma->id >= priv->n_channels)
>> +		return -ENODEV;
>> +
>> +	/* alloc channel private data */
>> +	priv->ch_priv[dma->id] = calloc(1, sizeof(struct bcm6348_chan_priv));
>> +	if (!priv->ch_priv[dma->id])
>> +		return -ENOMEM;
>> +	ch_priv = priv->ch_priv[dma->id];
>> +
>> +	/* alloc dma ring */
>> +	if (bcm6348_iudma_chan_is_rx(dma->id))
>> +		ch_priv->dma_ring_size = DMA_RX_DESC;
>> +	else
>> +		ch_priv->dma_ring_size = DMA_TX_DESC;
>> +
>> +	ch_priv->dma_ring =
>> +		malloc_cache_aligned(sizeof(struct bcm6348_dma_desc) *
>> +				     ch_priv->dma_ring_size);
>> +	if (!ch_priv->dma_ring)
>> +		return -ENOMEM;
>> +
>> +	/* init channel config */
>> +	ch_priv->running = false;
>> +	ch_priv->desc_id = 0;
>> +	if (bcm6348_iudma_chan_is_rx(dma->id)) {
>> +		ch_priv->desc_cnt = 0;
>> +		ch_priv->busy_desc = calloc(ch_priv->desc_cnt, sizeof(bool));
>> +	} else {
>> +		ch_priv->desc_cnt = ch_priv->dma_ring_size;
>> +		ch_priv->busy_desc = NULL;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int bcm6348_iudma_receive(struct dma *dma, void **dst, void *metadata)
>> +{
>> +	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
>> +	const struct bcm6348_iudma_hw *hw = priv->hw;
>> +	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
>> +	struct bcm6348_dma_desc *dma_desc = dma_desc = ch_priv->dma_ring;
>> +	int ret;
>> +
>> +	/* get dma ring descriptor address */
>> +	dma_desc += ch_priv->desc_id;
>> +
>> +	/* invalidate cache data */
>> +	bcm6348_iudma_idc(dma_desc, sizeof(*dma_desc));
>> +
>> +	/* check dma own */
>> +	if (dma_desc->status & DMAD_ST_OWN_MASK)
>> +		return -EAGAIN;
>> +
>> +	/* check pkt */
>> +	if (!(dma_desc->status & DMAD_ST_EOP_MASK) ||
>> +	    !(dma_desc->status & DMAD_ST_SOP_MASK) ||
>> +	    (dma_desc->status & hw->err_mask)) {
>> +		pr_err("invalid pkt received (ch=%ld desc=%u) (st=%04x)\n",
>> +		       dma->id, ch_priv->desc_id, dma_desc->status);
>> +		ret = -EAGAIN;
>> +	} else {
>> +		/* set dma buffer address */
>> +		*dst = phys_to_virt(dma_desc->address);
>> +
>> +		/* invalidate cache data */
>> +		bcm6348_iudma_idc(*dst, dma_desc->length);
>> +
>> +		/* remove crc */
>> +		ret = dma_desc->length - 4;
> is CRC a feature of the DMA engine or does this belong to the ethernet
> driver?

I would say it belongs to ethernet, since I copied that from linux:

https://github.com/Noltari/linux/blob/master/drivers/net/ethernet/broadcom/bcm63xx_enet.c#L379

However, I just did one version without removing FCS and it worked, so I 
will remove it in the next version.

>
>> +	}
>> +
>> +	/* busy dma descriptor */
>> +	ch_priv->busy_desc[ch_priv->desc_id] = true;
>> +
>> +	/* increment dma descriptor */
>> +	ch_priv->desc_id = (ch_priv->desc_id + 1) % ch_priv->desc_cnt;
>> +
>> +	return ret;
>> +}
>> +
>> +static int bcm6348_iudma_send(struct dma *dma, void *src, size_t len,
>> +			      void *metadata)
>> +{
>> +	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
>> +	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
>> +	struct bcm6348_dma_desc *dma_desc;
>> +	uint16_t status;
>> +
>> +	/* flush cache */
>> +	bcm6348_iudma_fdc(src, len);
>> +
>> +	/* get dma ring descriptor address */
>> +	dma_desc = ch_priv->dma_ring;
>> +	dma_desc += ch_priv->desc_id;
>> +
>> +	/* config dma descriptor */
>> +	status = (DMAD_ST_OWN_MASK |
>> +		  DMAD_ST_EOP_MASK |
>> +		  DMAD_ST_CRC_MASK |
>> +		  DMAD_ST_SOP_MASK);
>> +	if (ch_priv->desc_id == ch_priv->desc_cnt - 1)
>> +		status |= DMAD_ST_WRAP_MASK;
>> +
>> +	/* set dma descriptor */
>> +	dma_desc->address = virt_to_phys(src);
>> +	dma_desc->length = len;
>> +	dma_desc->status = status;
>> +
>> +	/* flush cache */
>> +	bcm6348_iudma_fdc(dma_desc, sizeof(*dma_desc));
>> +
>> +	/* kick tx dma channel */
>> +	setbits_be32(priv->chan + DMAC_CFG_REG(dma->id), DMAC_CFG_ENABLE_MASK);
>> +
>> +	/* poll dma status */
>> +	do {
>> +		/* invalidate cache */
>> +		bcm6348_iudma_idc(dma_desc, sizeof(*dma_desc));
>> +
>> +		if (!(dma_desc->status & DMAD_ST_OWN_MASK))
>> +			break;
>> +	} while(1);
>> +
>> +	/* increment dma descriptor */
>> +	ch_priv->desc_id = (ch_priv->desc_id + 1) % ch_priv->desc_cnt;
>> +
>> +	return 0;
>> +}
>> +
>> +static int bcm6348_iudma_free_rcv_buf(struct dma *dma, void *dst, size_t size)
>> +{
>> +	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
>> +	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
>> +	struct bcm6348_dma_desc *dma_desc = ch_priv->dma_ring;
>> +	uint16_t status;
>> +	uint8_t i;
>> +	u32 cfg;
>> +
>> +	/* get dirty dma descriptor */
>> +	for (i = 0; i < ch_priv->desc_cnt; i++) {
>> +		if (phys_to_virt(dma_desc->address) == dst)
>> +			break;
>> +
>> +		dma_desc++;
>> +	}
>> +
>> +	/* dma descriptor not found */
>> +	if (i == ch_priv->desc_cnt) {
>> +		pr_err("dirty dma descriptor not found\n");
>> +		return -ENOENT;
>> +	}
>> +
>> +	/* invalidate cache */
>> +	bcm6348_iudma_idc(ch_priv->dma_ring,
>> +			  sizeof(*dma_desc) * ch_priv->desc_cnt);
>> +
>> +	/* free dma descriptor */
>> +	ch_priv->busy_desc[i] = false;
>> +
>> +	status = DMAD_ST_OWN_MASK;
>> +	if (i == ch_priv->desc_cnt - 1)
>> +		status |= DMAD_ST_WRAP_MASK;
>> +
>> +	dma_desc->status |= status;
>> +	dma_desc->length = PKTSIZE_ALIGN;
>> +
>> +	/* tell dma we allocated one buffer */
>> +	writel_be(1, DMA_FLOWC_ALLOC_REG(dma->id));
>> +
>> +	/* flush cache */
>> +	bcm6348_iudma_fdc(ch_priv->dma_ring,
>> +			  sizeof(*dma_desc) * ch_priv->desc_cnt);
>> +
>> +	/* kick rx dma channel if disabled */
>> +	cfg = readl_be(priv->chan + DMAC_CFG_REG(dma->id));
>> +	if (!(cfg & DMAC_CFG_ENABLE_MASK))
>> +		setbits_be32(priv->chan + DMAC_CFG_REG(dma->id),
>> +			     DMAC_CFG_ENABLE_MASK);
>> +
>> +	return 0;
>> +}
>> +
>> +static int bcm6348_iudma_add_rcv_buf(struct dma *dma, void *dst, size_t size)
>> +{
>> +	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
>> +	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
>> +	struct bcm6348_dma_desc *dma_desc = ch_priv->dma_ring;
>> +
>> +	/* no more dma descriptors available */
>> +	if (ch_priv->desc_cnt == ch_priv->dma_ring_size) {
>> +		pr_err("max number of buffers reached\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	/* get next dma descriptor */
>> +	dma_desc += ch_priv->desc_cnt;
>> +
>> +	/* init dma descriptor */
>> +	dma_desc->address = virt_to_phys(dst);
>> +	dma_desc->length = size;
>> +	dma_desc->status = 0;
>> +
>> +	/* flush cache */
>> +	bcm6348_iudma_fdc(dma_desc, sizeof(*dma_desc));
>> +
>> +	/* increment dma descriptors */
>> +	ch_priv->desc_cnt++;
>> +
>> +	return 0;
>> +}
>> +
>> +static int bcm6348_iudma_prepare_rcv_buf(struct dma *dma, void *dst,
>> +					 size_t size)
>> +{
>> +	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
>> +	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
>> +
>> +	/* only add new rx buffers if channel isn't running */
>> +	if (ch_priv->running)
>> +		return bcm6348_iudma_free_rcv_buf(dma, dst, size);
>> +	else
>> +		return bcm6348_iudma_add_rcv_buf(dma, dst, size);
>> +}
>> +
>> +static const struct dma_ops bcm6348_iudma_ops = {
>> +	.disable = bcm6348_iudma_disable,
>> +	.enable = bcm6348_iudma_enable,
>> +	.prepare_rcv_buf = bcm6348_iudma_prepare_rcv_buf,
>> +	.request = bcm6348_iudma_request,
>> +	.receive = bcm6348_iudma_receive,
>> +	.send = bcm6348_iudma_send,
>> +};
>> +
>> +static const struct bcm6348_iudma_hw bcm6348_hw = {
>> +	.err_mask = (DMAD6348_ST_OV_ERR_MASK |
>> +		     DMAD6348_ST_CRC_ERR_MASK |
>> +		     DMAD6348_ST_RX_ERR_MASK |
>> +		     DMAD6348_ST_OS_ERR_MASK |
>> +		     DMAD6348_ST_UN_ERR_MASK),
>> +};
>> +
>> +static const struct bcm6348_iudma_hw bcm6368_hw = {
>> +	.err_mask = 0,
>> +};
>> +
>> +static const struct udevice_id bcm6348_iudma_ids[] = {
>> +	{
>> +		.compatible = "brcm,bcm6348-iudma",
>> +		.data = (ulong)&bcm6348_hw,
>> +	}, {
>> +		.compatible = "brcm,bcm6368-iudma",
>> +		.data = (ulong)&bcm6368_hw,
>> +	}, { /* sentinel */ }
>> +};
>> +
>> +static int bcm6348_iudma_probe(struct udevice *dev)
>> +{
>> +	struct dma_dev_priv *uc_priv = dev_get_uclass_priv(dev);
>> +	struct bcm6348_iudma_priv *priv = dev_get_priv(dev);
>> +	const struct bcm6348_iudma_hw *hw =
>> +		(const struct bcm6348_iudma_hw *)dev_get_driver_data(dev);
>> +	uint8_t ch;
>> +	int i;
>> +
>> +	uc_priv->supported = (DMA_SUPPORTS_DEV_TO_MEM |
>> +			      DMA_SUPPORTS_MEM_TO_DEV);
>> +	priv->hw = hw;
>> +
>> +	/* dma global base address */
>> +	priv->base = dev_remap_addr_name(dev, "dma");
>> +	if (!priv->base)
>> +		return -EINVAL;
>> +
>> +	/* dma channels base address */
>> +	priv->chan = dev_remap_addr_name(dev, "dma-channels");
>> +	if (!priv->chan)
>> +		return -EINVAL;
>> +
>> +	/* dma sram base address */
>> +	priv->sram = dev_remap_addr_name(dev, "dma-sram");
>> +	if (!priv->sram)
>> +		return -EINVAL;
>> +
>> +	/* get number of channels */
>> +	priv->n_channels = dev_read_u32_default(dev, "dma-channels", 8);
>> +	if (priv->n_channels > DMA_CHAN_MAX)
>> +		return -EINVAL;
>> +
>> +	/* try to enable clocks */
>> +	for (i = 0; ; i++) {
>> +		struct clk clk;
>> +		int ret;
>> +
>> +		ret = clk_get_by_index(dev, i, &clk);
>> +		if (ret < 0)
>> +			break;
>> +
>> +		ret = clk_enable(&clk);
>> +		if (ret < 0) {
>> +			pr_err("error enabling clock %d\n", i);
>> +			return ret;
>> +		}
>> +
>> +		ret = clk_free(&clk);
>> +		if (ret < 0) {
>> +			pr_err("error freeing clock %d\n", i);
>> +			return ret;
>> +		}
>> +	}
>> +
>> +	/* try to perform resets */
>> +	for (i = 0; ; i++) {
>> +		struct reset_ctl reset;
>> +		int ret;
>> +
>> +		ret = reset_get_by_index(dev, i, &reset);
>> +		if (ret < 0)
>> +			break;
>> +
>> +		ret = reset_deassert(&reset);
>> +		if (ret < 0) {
>> +			pr_err("error deasserting reset %d\n", i);
>> +			return ret;
>> +		}
>> +
>> +		ret = reset_free(&reset);
>> +		if (ret < 0) {
>> +			pr_err("error freeing reset %d\n", i);
>> +			return ret;
>> +		}
>> +	}
>> +
>> +	/* disable dma controller */
>> +	clrbits_be32(priv->base + DMA_CFG_REG, DMA_CFG_ENABLE_MASK);
>> +
>> +	/* alloc channel private data pointers */
>> +	priv->ch_priv = calloc(priv->n_channels,
>> +			       sizeof(struct bcm6348_chan_priv*));
>> +	if (!priv->ch_priv)
>> +		return -ENOMEM;
>> +
>> +	/* stop dma channels */
>> +	for (ch = 0; ch < priv->n_channels; ch++)
>> +		bcm6348_iudma_chan_stop(priv, ch);
>> +
>> +	/* enable dma controller */
>> +	setbits_be32(priv->base + DMA_CFG_REG, DMA_CFG_ENABLE_MASK);
>> +
>> +	return 0;
>> +}
>> +
>> +U_BOOT_DRIVER(bcm6348_iudma) = {
>> +	.name = "bcm6348_iudma",
>> +	.id = UCLASS_DMA,
>> +	.of_match = bcm6348_iudma_ids,
>> +	.ops = &bcm6348_iudma_ops,
>> +	.priv_auto_alloc_size = sizeof(struct bcm6348_iudma_priv),
>> +	.probe = bcm6348_iudma_probe,
>> +};
>>

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

* [U-Boot] [PATCH v9 0/3] dma: add channels support
  2018-11-28 18:17   ` [U-Boot] [PATCH v9 0/3] " Álvaro Fernández Rojas
                       ` (2 preceding siblings ...)
  2018-11-28 18:17     ` [U-Boot] [PATCH v9 3/3] test: dma: add dma-uclass test Álvaro Fernández Rojas
@ 2018-11-30 23:56     ` Grygorii Strashko
  3 siblings, 0 replies; 145+ messages in thread
From: Grygorii Strashko @ 2018-11-30 23:56 UTC (permalink / raw)
  To: u-boot

Hi Álvaro,

On 11/28/18 12:17 PM, Álvaro Fernández Rojas wrote:
> In order to add bcm6348-enet support, dma-uclass must be extended to support
> dma channels and reworked to operate like the other dm uclass (clk, reset...).
> 
> ===

Thank you for picking this up.
I, unfortunately, will be out unresponsive next few month due to personal reasons,
but hope this will be moved forward eventually.

> 
> ===
> 
> v9: Separate generic dma channels support from bmips enet support
> v8: Sync with latest u-boot.
> v7: From Grygorii Strashko:
>   - copyright fixed as suggested by Tom Rini
>   - added "Reviewed-by" tags
> v6: From Grygorii Strashko:
>   - added possibility to pass DMA driver/channel's specific data per each
>   transfer using additional parameter "metadata" in dma_send/dma_receive() API.
>   For example, port number for network packets to be directed to the
>   specific port on multi port ethernet controllers.
>   - added new dma_prepare_rcv_buf() API which allows to implement zero-copy
>   DEV_TO_MEM transfer using DMA streaming channels which is usual case
>   for Networking.
>   - added dma-uclass test
>   - removed unused function dma_get_by_index_platdata()
>   - updated comments
> v5: Fix build of ti-edma3.
> v4: No changes
> v3: Introduce changes reported by Simon Glass:
>   - Improve dma-uclass.h documentation.
>   - Switch to live tree API.
> v2: Introduce changes reported by Vignesh:
>   - Respect current dma implementation.
>   - Let dma_memcpy find a compatible dma device.
> 
> Grygorii Strashko (1):
>    test: dma: add dma-uclass test
> 
> Álvaro Fernández Rojas (2):
>    dma: move dma_ops to dma-uclass.h
>    dma: add channels support
> 
>   arch/sandbox/dts/test.dts      |   8 ++
>   configs/sandbox_defconfig      |   3 +
>   drivers/dma/Kconfig            |  14 ++
>   drivers/dma/Makefile           |   1 +
>   drivers/dma/dma-uclass.c       | 183 +++++++++++++++++++++++++-
>   drivers/dma/sandbox-dma-test.c | 282 +++++++++++++++++++++++++++++++++++++++++
>   drivers/dma/ti-edma3.c         |   2 +-
>   include/dma-uclass.h           | 128 +++++++++++++++++++
>   include/dma.h                  | 282 +++++++++++++++++++++++++++++++++++++----
>   test/dm/Makefile               |   1 +
>   test/dm/dma.c                  | 123 ++++++++++++++++++
>   11 files changed, 997 insertions(+), 30 deletions(-)
>   create mode 100644 drivers/dma/sandbox-dma-test.c
>   create mode 100644 include/dma-uclass.h
>   create mode 100644 test/dm/dma.c
> 

-- 
regards,
-grygorii

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

* [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support
  2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                         ` (27 preceding siblings ...)
  2018-11-29 22:25       ` [U-Boot] [PATCH v10 28/28] bmips: enable ar-5315u enet support Álvaro Fernández Rojas
@ 2018-12-01 18:00       ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 01/28] dma: add bcm6348-iudma support Álvaro Fernández Rojas
                           ` (28 more replies)
  28 siblings, 29 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

In order to add bcm6348-enet support, dma-uclass must be extended to support
dma channels and reworked to operate like the other dm uclass (clk, reset...).

v11: Introduce change suggested by Daniel Schwierzeck:
 - Avoid trimming ethernet FCS from DMA driver.
v10: Introduce changes suggested by Daniel Schwierzeck:
 - Fix license identifiers.
 bcm6348-iudma:
  - Move DMAD_ST defines out of dma desc struct definition.
  - Remove unneded aigned attribute from dma desc struct definition.
  - Fill dma ring from consumer driver instead of allocating a new buffer.
  - Correctly check clock/reset errors while probing.
  - Switch to live DM live tree.
 bcm6348-enet:
  - Remove packet queue.
  - Move dma_prepare_rcv_buf to free_pkt.
  - Switch to live DM live tree.
 bcm6368-enet:
  - Remove packet queue.
  - Move dma_prepare_rcv_buf to free_pkt.
  - Pad packets smaller than ETH_ZLEN.
  - Switch to live DM live tree.
v9: Separate generic dma channels support from bmips enet support
 bcm6348-iudma:
  - bcm6348_iudma_chan_stop: switch to mdelay when resetting channel.
  - bcm6348_iudma_receive: track dirty dma descriptors and no longer trigger
   dma rx channel.
  - bcm6348_iudma_send: reorder to properly flush cache and set dma descriptor
   config.
  - bcm6348_iudma_prepare_rcv_buf: implemented to clear dirty dma descriptors.
 bcm6348-enet:
  - bcm6348_eth_recv: clear dirty dma descriptors only when packets are copied
   from rx dma.
  - bcm6348_eth_send: remove dma rx channel reset when sending packet.
 bcm6368-enet:
  - introduce rx packets caching functionality from bcm6348-eth to fix flow
   control issues.
  - code style fixes.
v8: Introduce bcm6368-enet driver support.
v5: Fix issues reported by Grygorii Strashko and other fixes:
 - Remove unused bcm6348-iudma defines.
 - Increment bcm6348-iudma rx descriptors.
 - Fix bcm6348-iudma flow control issues.
 - bcm6348-iudma error checking now depends on hw.
 - Remove unneeded bcm6348-iudma interrupts.
 - Receive as much packets as possible from bcm6348-eth and cache them in
 net_rx_packets. This is needed in order to fix flow control issues.
v4: Fix issues reported by Grygorii Strashko and other fixes:
 - Remove usage of net_rx_packets as buffer from bcm6348-iudma.
 - Allocate dynamic rx buffer on bcm6348-iudma.
 - Copy received dma buffer to net_rx_packets in order to avoid possible
 dma overwrites.
 - Check dma errors and discard invalid packets.
 - Reset dma rx channel when sending a new packet to prevent flow control
 issues.
 - Fix packet casting on bcm6348_eth_recv/send.
v3: Switch to live tree API.
v2: Fix bcm6348-iudma rx burst config.

Álvaro Fernández Rojas (28):
  dma: add bcm6348-iudma support
  bmips: bcm6338: add bcm6348-iudma support
  bmips: bcm6348: add bcm6348-iudma support
  bmips: bcm6358: add bcm6348-iudma support
  bmips: bcm6368: add bcm6348-iudma support
  bmips: bcm6328: add bcm6348-iudma support
  bmips: bcm6362: add bcm6348-iudma support
  bmips: bcm63268: add bcm6348-iudma support
  bmips: bcm6318: add bcm6348-iudma support
  net: add support for bcm6348-enet
  bmips: bcm6338: add support for bcm6348-enet
  bmips: enable f at st1704 enet support
  bmips: bcm6348: add support for bcm6348-enet
  bmips: enable ct-5361 enet support
  bmips: bcm6358: add support for bcm6348-enet
  bmips: enable hg556a enet support
  bmips: enable nb4-ser enet support
  net: add support for bcm6368-enet
  bmips: bcm6368: add support for bcm6368-enet
  bmips: enable wap-5813n enet support
  bmips: bcm6328: add support for bcm6368-enet
  bmips: enable ar-5387un enet support
  bmips: bcm6362: add support for bcm6368-enet
  bmips: enable dgnd3700v2 enet support
  bmips: bcm63268: add support for bcm6368-enet
  bmips: enable vr-3032u enet support
  bmips: bcm6318: add support for bcm6368-enet
  bmips: enable ar-5315u enet support

 arch/mips/dts/brcm,bcm6318.dtsi           |  38 ++
 arch/mips/dts/brcm,bcm63268.dtsi          |  38 ++
 arch/mips/dts/brcm,bcm6328.dtsi           |  30 ++
 arch/mips/dts/brcm,bcm6338.dtsi           |  29 ++
 arch/mips/dts/brcm,bcm6348.dtsi           |  42 ++
 arch/mips/dts/brcm,bcm6358.dtsi           |  46 +++
 arch/mips/dts/brcm,bcm6362.dtsi           |  32 ++
 arch/mips/dts/brcm,bcm6368.dtsi           |  32 ++
 arch/mips/dts/comtrend,ar-5315u.dts       |  32 ++
 arch/mips/dts/comtrend,ar-5387un.dts      |  32 ++
 arch/mips/dts/comtrend,ct-5361.dts        |  12 +
 arch/mips/dts/comtrend,vr-3032u.dts       |  32 ++
 arch/mips/dts/comtrend,wap-5813n.dts      |  14 +
 arch/mips/dts/huawei,hg556a.dts           |  12 +
 arch/mips/dts/netgear,dgnd3700v2.dts      |  14 +
 arch/mips/dts/sagem,f at st1704.dts          |  12 +
 arch/mips/dts/sfr,nb4-ser.dts             |  24 ++
 configs/comtrend_ar5315u_ram_defconfig    |   7 +-
 configs/comtrend_ar5387un_ram_defconfig   |   7 +-
 configs/comtrend_ct5361_ram_defconfig     |   8 +-
 configs/comtrend_vr3032u_ram_defconfig    |   7 +-
 configs/comtrend_wap5813n_ram_defconfig   |   8 +-
 configs/huawei_hg556a_ram_defconfig       |   8 +-
 configs/netgear_dgnd3700v2_ram_defconfig  |   8 +-
 configs/sagem_f at st1704_ram_defconfig      |   8 +-
 configs/sfr_nb4-ser_ram_defconfig         |   8 +-
 drivers/dma/Kconfig                       |   9 +
 drivers/dma/Makefile                      |   1 +
 drivers/dma/bcm6348-iudma.c               | 642 ++++++++++++++++++++++++++++++
 drivers/net/Kconfig                       |  18 +
 drivers/net/Makefile                      |   2 +
 drivers/net/bcm6348-eth.c                 | 537 +++++++++++++++++++++++++
 drivers/net/bcm6368-eth.c                 | 625 +++++++++++++++++++++++++++++
 include/configs/bmips_common.h            |   6 +-
 include/dt-bindings/clock/bcm6318-clock.h |  11 +
 include/dt-bindings/dma/bcm6318-dma.h     |  14 +
 include/dt-bindings/dma/bcm63268-dma.h    |  14 +
 include/dt-bindings/dma/bcm6328-dma.h     |  14 +
 include/dt-bindings/dma/bcm6338-dma.h     |  14 +
 include/dt-bindings/dma/bcm6348-dma.h     |  16 +
 include/dt-bindings/dma/bcm6358-dma.h     |  16 +
 include/dt-bindings/dma/bcm6362-dma.h     |  14 +
 include/dt-bindings/dma/bcm6368-dma.h     |  14 +
 43 files changed, 2497 insertions(+), 10 deletions(-)
 create mode 100644 drivers/dma/bcm6348-iudma.c
 create mode 100644 drivers/net/bcm6348-eth.c
 create mode 100644 drivers/net/bcm6368-eth.c
 create mode 100644 include/dt-bindings/dma/bcm6318-dma.h
 create mode 100644 include/dt-bindings/dma/bcm63268-dma.h
 create mode 100644 include/dt-bindings/dma/bcm6328-dma.h
 create mode 100644 include/dt-bindings/dma/bcm6338-dma.h
 create mode 100644 include/dt-bindings/dma/bcm6348-dma.h
 create mode 100644 include/dt-bindings/dma/bcm6358-dma.h
 create mode 100644 include/dt-bindings/dma/bcm6362-dma.h
 create mode 100644 include/dt-bindings/dma/bcm6368-dma.h

-- 
2.11.0

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

* [U-Boot] [PATCH v11 01/28] dma: add bcm6348-iudma support
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 02/28] bmips: bcm6338: " Álvaro Fernández Rojas
                           ` (27 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

BCM6348 IUDMA controller is present on multiple BMIPS (BCM63xx) SoCs.

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v11: Introduce change suggested by Daniel Schwierzeck:
  - Avoid trimming ethernet FCS from DMA driver.
 v10: Introduce changes suggested by Daniel Schwierzeck:
  - Fix license identifiers.
  - Move DMAD_ST defines out of dma desc struct definition.
  - Remove unneded aigned attribute from dma desc struct definition.
  - Fill dma ring from consumer driver instead of allocating a new buffer.
  - Correctly check clock/reset errors while probing.
  - Switch to live DM live tree.
 v9: introduce dma_prepare_rcv_buf dma op:
  - bcm6348_iudma_chan_stop: switch to mdelay when resetting channel.
  - bcm6348_iudma_receive: track dirty dma descriptors and no longer trigger
   dma rx channel.
  - bcm6348_iudma_send: reorder to properly flush cache and set dma descriptor
   config.
  - bcm6348_iudma_prepare_rcv_buf: implemented to clear dirty dma descriptors.
 v8: Introduce changes from Grygorii Strashko
 v5: Several fixes and improvements:
  - Remove unused defines.
  - Increment rx descriptors.
  - Fix flow control issues.
  - Error checking now depends on hw.
  - Remove unneeded interrupts.
 v4: Fix issues reported by Grygorii Strashko and other fixes:
  - Remove usage of net_rx_packets as buffer.
  - Allocate dynamic rx buffer.
  - Check dma errors and discard invalid packets.
 v3: no changes
 v2: Fix dma rx burst config and select DMA_CHANNELS.

 drivers/dma/Kconfig         |   9 +
 drivers/dma/Makefile        |   1 +
 drivers/dma/bcm6348-iudma.c | 642 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 652 insertions(+)
 create mode 100644 drivers/dma/bcm6348-iudma.c

diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 8a4162eccd..1820676d7a 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -26,6 +26,15 @@ config SANDBOX_DMA
 	  Enable support for a test DMA uclass implementation. It stimulates
 	  DMA transfer by simple copying data between channels.
 
+config BCM6348_IUDMA
+	bool "BCM6348 IUDMA driver"
+	depends on ARCH_BMIPS
+	select DMA_CHANNELS
+	help
+	  Enable the BCM6348 IUDMA driver.
+	  This driver support data transfer from devices to
+	  memory and from memory to devices.
+
 config TI_EDMA3
 	bool "TI EDMA3 driver"
 	help
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index aff31f986a..b5f9147e0a 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_DMA) += dma-uclass.o
 
 obj-$(CONFIG_FSLDMAFEC) += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o
 obj-$(CONFIG_APBH_DMA) += apbh_dma.o
+obj-$(CONFIG_BCM6348_IUDMA) += bcm6348-iudma.o
 obj-$(CONFIG_FSL_DMA) += fsl_dma.o
 obj-$(CONFIG_SANDBOX_DMA) += sandbox-dma-test.o
 obj-$(CONFIG_TI_KSNAV) += keystone_nav.o keystone_nav_cfg.o
diff --git a/drivers/dma/bcm6348-iudma.c b/drivers/dma/bcm6348-iudma.c
new file mode 100644
index 0000000000..1d3c192cfe
--- /dev/null
+++ b/drivers/dma/bcm6348-iudma.c
@@ -0,0 +1,642 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/dma/bcm63xx-iudma.c:
+ *	Copyright (C) 2015 Simon Arlott <simon@fire.lp0.eu>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c:
+ *	Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ *
+ * Derived from bcm963xx_4.12L.06B_consumer/shared/opensource/include/bcm963xx/63268_map_part.h:
+ *	Copyright (C) 2000-2010 Broadcom Corporation
+ *
+ * Derived from bcm963xx_4.12L.06B_consumer/bcmdrivers/opensource/net/enet/impl4/bcmenet.c:
+ *	Copyright (C) 2010 Broadcom Corporation
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dma-uclass.h>
+#include <memalign.h>
+#include <reset.h>
+#include <asm/io.h>
+
+#define DMA_RX_DESC	6
+#define DMA_TX_DESC	1
+
+/* DMA Channels */
+#define DMA_CHAN_FLOWC(x)		((x) >> 1)
+#define DMA_CHAN_MAX			16
+#define DMA_CHAN_SIZE			0x10
+#define DMA_CHAN_TOUT			500
+
+/* DMA Global Configuration register */
+#define DMA_CFG_REG			0x00
+#define  DMA_CFG_ENABLE_SHIFT		0
+#define  DMA_CFG_ENABLE_MASK		(1 << DMA_CFG_ENABLE_SHIFT)
+#define  DMA_CFG_FLOWC_ENABLE(x)	BIT(DMA_CHAN_FLOWC(x) + 1)
+#define  DMA_CFG_NCHANS_SHIFT		24
+#define  DMA_CFG_NCHANS_MASK		(0xf << DMA_CFG_NCHANS_SHIFT)
+
+/* DMA Global Flow Control registers */
+#define DMA_FLOWC_THR_LO_REG(x)		(0x04 + DMA_CHAN_FLOWC(x) * 0x0c)
+#define DMA_FLOWC_THR_HI_REG(x)		(0x08 + DMA_CHAN_FLOWC(x) * 0x0c)
+#define DMA_FLOWC_ALLOC_REG(x)		(0x0c + DMA_CHAN_FLOWC(x) * 0x0c)
+#define  DMA_FLOWC_ALLOC_FORCE_SHIFT	31
+#define  DMA_FLOWC_ALLOC_FORCE_MASK	(1 << DMA_FLOWC_ALLOC_FORCE_SHIFT)
+
+/* DMA Global Reset register */
+#define DMA_RST_REG			0x34
+#define  DMA_RST_CHAN_SHIFT		0
+#define  DMA_RST_CHAN_MASK(x)		(1 << x)
+
+/* DMA Channel Configuration register */
+#define DMAC_CFG_REG(x)			(DMA_CHAN_SIZE * (x) + 0x00)
+#define  DMAC_CFG_ENABLE_SHIFT		0
+#define  DMAC_CFG_ENABLE_MASK		(1 << DMAC_CFG_ENABLE_SHIFT)
+#define  DMAC_CFG_PKT_HALT_SHIFT	1
+#define  DMAC_CFG_PKT_HALT_MASK		(1 << DMAC_CFG_PKT_HALT_SHIFT)
+#define  DMAC_CFG_BRST_HALT_SHIFT	2
+#define  DMAC_CFG_BRST_HALT_MASK	(1 << DMAC_CFG_BRST_HALT_SHIFT)
+
+/* DMA Channel Max Burst Length register */
+#define DMAC_BURST_REG(x)		(DMA_CHAN_SIZE * (x) + 0x0c)
+
+/* DMA SRAM Descriptor Ring Start register */
+#define DMAS_RSTART_REG(x)		(DMA_CHAN_SIZE * (x) + 0x00)
+
+/* DMA SRAM State/Bytes done/ring offset register */
+#define DMAS_STATE_DATA_REG(x)		(DMA_CHAN_SIZE * (x) + 0x04)
+
+/* DMA SRAM Buffer Descriptor status and length register */
+#define DMAS_DESC_LEN_STATUS_REG(x)	(DMA_CHAN_SIZE * (x) + 0x08)
+
+/* DMA SRAM Buffer Descriptor status and length register */
+#define DMAS_DESC_BASE_BUFPTR_REG(x)	(DMA_CHAN_SIZE * (x) + 0x0c)
+
+/* DMA Descriptor Status */
+#define DMAD_ST_CRC_SHIFT		8
+#define DMAD_ST_CRC_MASK		(1 << DMAD_ST_CRC_SHIFT)
+#define DMAD_ST_WRAP_SHIFT		12
+#define DMAD_ST_WRAP_MASK		(1 << DMAD_ST_WRAP_SHIFT)
+#define DMAD_ST_SOP_SHIFT		13
+#define DMAD_ST_SOP_MASK		(1 << DMAD_ST_SOP_SHIFT)
+#define DMAD_ST_EOP_SHIFT		14
+#define DMAD_ST_EOP_MASK		(1 << DMAD_ST_EOP_SHIFT)
+#define DMAD_ST_OWN_SHIFT		15
+#define DMAD_ST_OWN_MASK		(1 << DMAD_ST_OWN_SHIFT)
+
+#define DMAD6348_ST_OV_ERR_SHIFT	0
+#define DMAD6348_ST_OV_ERR_MASK		(1 << DMAD6348_ST_OV_ERR_SHIFT)
+#define DMAD6348_ST_CRC_ERR_SHIFT	1
+#define DMAD6348_ST_CRC_ERR_MASK	(1 << DMAD6348_ST_CRC_ERR_SHIFT)
+#define DMAD6348_ST_RX_ERR_SHIFT	2
+#define DMAD6348_ST_RX_ERR_MASK		(1 << DMAD6348_ST_RX_ERR_SHIFT)
+#define DMAD6348_ST_OS_ERR_SHIFT	4
+#define DMAD6348_ST_OS_ERR_MASK		(1 << DMAD6348_ST_OS_ERR_SHIFT)
+#define DMAD6348_ST_UN_ERR_SHIFT	9
+#define DMAD6348_ST_UN_ERR_MASK		(1 << DMAD6348_ST_UN_ERR_SHIFT)
+
+struct bcm6348_dma_desc {
+	uint16_t length;
+	uint16_t status;
+	uint32_t address;
+};
+
+struct bcm6348_chan_priv {
+	void __iomem *dma_ring;
+	uint8_t dma_ring_size;
+	uint8_t desc_id;
+	uint8_t desc_cnt;
+	bool *busy_desc;
+	bool running;
+};
+
+struct bcm6348_iudma_hw {
+	uint16_t err_mask;
+};
+
+struct bcm6348_iudma_priv {
+	const struct bcm6348_iudma_hw *hw;
+	void __iomem *base;
+	void __iomem *chan;
+	void __iomem *sram;
+	struct bcm6348_chan_priv **ch_priv;
+	uint8_t n_channels;
+};
+
+static inline bool bcm6348_iudma_chan_is_rx(uint8_t ch)
+{
+	return !(ch & 1);
+}
+
+static inline void bcm6348_iudma_fdc(void *ptr, ulong size)
+{
+	ulong start = (ulong) ptr;
+
+	flush_dcache_range(start, start + size);
+}
+
+static inline void bcm6348_iudma_idc(void *ptr, ulong size)
+{
+	ulong start = (ulong) ptr;
+
+	invalidate_dcache_range(start, start + size);
+}
+
+static void bcm6348_iudma_chan_stop(struct bcm6348_iudma_priv *priv,
+				    uint8_t ch)
+{
+	unsigned int timeout = DMA_CHAN_TOUT;
+
+	do {
+		uint32_t cfg, halt;
+
+		if (timeout > DMA_CHAN_TOUT / 2)
+			halt = DMAC_CFG_PKT_HALT_MASK;
+		else
+			halt = DMAC_CFG_BRST_HALT_MASK;
+
+		/* try to stop dma channel */
+		writel_be(halt, priv->chan + DMAC_CFG_REG(ch));
+		mb();
+
+		/* check if channel was stopped */
+		cfg = readl_be(priv->chan + DMAC_CFG_REG(ch));
+		if (!(cfg & DMAC_CFG_ENABLE_MASK))
+			break;
+
+		udelay(1);
+	} while (--timeout);
+
+	if (!timeout)
+		pr_err("unable to stop channel %u\n", ch);
+
+	/* reset dma channel */
+	setbits_be32(priv->base + DMA_RST_REG, DMA_RST_CHAN_MASK(ch));
+	mb();
+	clrbits_be32(priv->base + DMA_RST_REG, DMA_RST_CHAN_MASK(ch));
+}
+
+static int bcm6348_iudma_disable(struct dma *dma)
+{
+	struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+
+	/* stop dma channel */
+	bcm6348_iudma_chan_stop(priv, dma->id);
+
+	/* dma flow control */
+	if (bcm6348_iudma_chan_is_rx(dma->id))
+		writel_be(DMA_FLOWC_ALLOC_FORCE_MASK,
+			  DMA_FLOWC_ALLOC_REG(dma->id));
+
+	/* init channel config */
+	ch_priv->running = false;
+	ch_priv->desc_id = 0;
+	if (bcm6348_iudma_chan_is_rx(dma->id))
+		ch_priv->desc_cnt = 0;
+	else
+		ch_priv->desc_cnt = ch_priv->dma_ring_size;
+
+	return 0;
+}
+
+static int bcm6348_iudma_enable(struct dma *dma)
+{
+	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+	struct bcm6348_dma_desc *dma_desc = ch_priv->dma_ring;
+	uint8_t i;
+
+	/* dma ring init */
+	for (i = 0; i < ch_priv->desc_cnt; i++) {
+		if (bcm6348_iudma_chan_is_rx(dma->id)) {
+			ch_priv->busy_desc[i] = false;
+			dma_desc->status |= DMAD_ST_OWN_MASK;
+		} else {
+			dma_desc->status = 0;
+			dma_desc->length = 0;
+			dma_desc->address = 0;
+		}
+
+		if (i == ch_priv->desc_cnt - 1)
+			dma_desc->status |= DMAD_ST_WRAP_MASK;
+
+		dma_desc++;
+	}
+
+	/* init to first descriptor */
+	ch_priv->desc_id = 0;
+
+	/* force cache writeback */
+	bcm6348_iudma_fdc(ch_priv->dma_ring,
+			  sizeof(*dma_desc) * ch_priv->desc_cnt);
+
+	/* clear sram */
+	writel_be(0, priv->sram + DMAS_STATE_DATA_REG(dma->id));
+	writel_be(0, priv->sram + DMAS_DESC_LEN_STATUS_REG(dma->id));
+	writel_be(0, priv->sram + DMAS_DESC_BASE_BUFPTR_REG(dma->id));
+
+	/* set dma ring start */
+	writel_be(virt_to_phys(ch_priv->dma_ring),
+		  priv->sram + DMAS_RSTART_REG(dma->id));
+
+	/* set flow control */
+	if (bcm6348_iudma_chan_is_rx(dma->id)) {
+		u32 val;
+
+		setbits_be32(priv->base + DMA_CFG_REG,
+			     DMA_CFG_FLOWC_ENABLE(dma->id));
+
+		val = ch_priv->desc_cnt / 3;
+		writel_be(val, priv->base + DMA_FLOWC_THR_LO_REG(dma->id));
+
+		val = (ch_priv->desc_cnt * 2) / 3;
+		writel_be(val, priv->base + DMA_FLOWC_THR_HI_REG(dma->id));
+
+		writel_be(0, priv->base + DMA_FLOWC_ALLOC_REG(dma->id));
+	}
+
+	/* set dma max burst */
+	writel_be(ch_priv->desc_cnt,
+		  priv->chan + DMAC_BURST_REG(dma->id));
+
+	/* kick rx dma channel */
+	if (bcm6348_iudma_chan_is_rx(dma->id))
+		setbits_be32(priv->chan + DMAC_CFG_REG(dma->id),
+			     DMAC_CFG_ENABLE_MASK);
+
+	/* channel is now enabled */
+	ch_priv->running = true;
+
+	return 0;
+}
+
+static int bcm6348_iudma_request(struct dma *dma)
+{
+	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+	struct bcm6348_chan_priv *ch_priv;
+
+	/* check if channel is valid */
+	if (dma->id >= priv->n_channels)
+		return -ENODEV;
+
+	/* alloc channel private data */
+	priv->ch_priv[dma->id] = calloc(1, sizeof(struct bcm6348_chan_priv));
+	if (!priv->ch_priv[dma->id])
+		return -ENOMEM;
+	ch_priv = priv->ch_priv[dma->id];
+
+	/* alloc dma ring */
+	if (bcm6348_iudma_chan_is_rx(dma->id))
+		ch_priv->dma_ring_size = DMA_RX_DESC;
+	else
+		ch_priv->dma_ring_size = DMA_TX_DESC;
+
+	ch_priv->dma_ring =
+		malloc_cache_aligned(sizeof(struct bcm6348_dma_desc) *
+				     ch_priv->dma_ring_size);
+	if (!ch_priv->dma_ring)
+		return -ENOMEM;
+
+	/* init channel config */
+	ch_priv->running = false;
+	ch_priv->desc_id = 0;
+	if (bcm6348_iudma_chan_is_rx(dma->id)) {
+		ch_priv->desc_cnt = 0;
+		ch_priv->busy_desc = calloc(ch_priv->desc_cnt, sizeof(bool));
+	} else {
+		ch_priv->desc_cnt = ch_priv->dma_ring_size;
+		ch_priv->busy_desc = NULL;
+	}
+
+	return 0;
+}
+
+static int bcm6348_iudma_receive(struct dma *dma, void **dst, void *metadata)
+{
+	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+	const struct bcm6348_iudma_hw *hw = priv->hw;
+	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+	struct bcm6348_dma_desc *dma_desc = dma_desc = ch_priv->dma_ring;
+	int ret;
+
+	/* get dma ring descriptor address */
+	dma_desc += ch_priv->desc_id;
+
+	/* invalidate cache data */
+	bcm6348_iudma_idc(dma_desc, sizeof(*dma_desc));
+
+	/* check dma own */
+	if (dma_desc->status & DMAD_ST_OWN_MASK)
+		return -EAGAIN;
+
+	/* check pkt */
+	if (!(dma_desc->status & DMAD_ST_EOP_MASK) ||
+	    !(dma_desc->status & DMAD_ST_SOP_MASK) ||
+	    (dma_desc->status & hw->err_mask)) {
+		pr_err("invalid pkt received (ch=%ld desc=%u) (st=%04x)\n",
+		       dma->id, ch_priv->desc_id, dma_desc->status);
+		ret = -EAGAIN;
+	} else {
+		/* set dma buffer address */
+		*dst = phys_to_virt(dma_desc->address);
+
+		/* invalidate cache data */
+		bcm6348_iudma_idc(*dst, dma_desc->length);
+
+		/* return packet length */
+		ret = dma_desc->length;
+	}
+
+	/* busy dma descriptor */
+	ch_priv->busy_desc[ch_priv->desc_id] = true;
+
+	/* increment dma descriptor */
+	ch_priv->desc_id = (ch_priv->desc_id + 1) % ch_priv->desc_cnt;
+
+	return ret;
+}
+
+static int bcm6348_iudma_send(struct dma *dma, void *src, size_t len,
+			      void *metadata)
+{
+	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+	struct bcm6348_dma_desc *dma_desc;
+	uint16_t status;
+
+	/* flush cache */
+	bcm6348_iudma_fdc(src, len);
+
+	/* get dma ring descriptor address */
+	dma_desc = ch_priv->dma_ring;
+	dma_desc += ch_priv->desc_id;
+
+	/* config dma descriptor */
+	status = (DMAD_ST_OWN_MASK |
+		  DMAD_ST_EOP_MASK |
+		  DMAD_ST_CRC_MASK |
+		  DMAD_ST_SOP_MASK);
+	if (ch_priv->desc_id == ch_priv->desc_cnt - 1)
+		status |= DMAD_ST_WRAP_MASK;
+
+	/* set dma descriptor */
+	dma_desc->address = virt_to_phys(src);
+	dma_desc->length = len;
+	dma_desc->status = status;
+
+	/* flush cache */
+	bcm6348_iudma_fdc(dma_desc, sizeof(*dma_desc));
+
+	/* kick tx dma channel */
+	setbits_be32(priv->chan + DMAC_CFG_REG(dma->id), DMAC_CFG_ENABLE_MASK);
+
+	/* poll dma status */
+	do {
+		/* invalidate cache */
+		bcm6348_iudma_idc(dma_desc, sizeof(*dma_desc));
+
+		if (!(dma_desc->status & DMAD_ST_OWN_MASK))
+			break;
+	} while(1);
+
+	/* increment dma descriptor */
+	ch_priv->desc_id = (ch_priv->desc_id + 1) % ch_priv->desc_cnt;
+
+	return 0;
+}
+
+static int bcm6348_iudma_free_rcv_buf(struct dma *dma, void *dst, size_t size)
+{
+	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+	struct bcm6348_dma_desc *dma_desc = ch_priv->dma_ring;
+	uint16_t status;
+	uint8_t i;
+	u32 cfg;
+
+	/* get dirty dma descriptor */
+	for (i = 0; i < ch_priv->desc_cnt; i++) {
+		if (phys_to_virt(dma_desc->address) == dst)
+			break;
+
+		dma_desc++;
+	}
+
+	/* dma descriptor not found */
+	if (i == ch_priv->desc_cnt) {
+		pr_err("dirty dma descriptor not found\n");
+		return -ENOENT;
+	}
+
+	/* invalidate cache */
+	bcm6348_iudma_idc(ch_priv->dma_ring,
+			  sizeof(*dma_desc) * ch_priv->desc_cnt);
+
+	/* free dma descriptor */
+	ch_priv->busy_desc[i] = false;
+
+	status = DMAD_ST_OWN_MASK;
+	if (i == ch_priv->desc_cnt - 1)
+		status |= DMAD_ST_WRAP_MASK;
+
+	dma_desc->status |= status;
+	dma_desc->length = PKTSIZE_ALIGN;
+
+	/* tell dma we allocated one buffer */
+	writel_be(1, DMA_FLOWC_ALLOC_REG(dma->id));
+
+	/* flush cache */
+	bcm6348_iudma_fdc(ch_priv->dma_ring,
+			  sizeof(*dma_desc) * ch_priv->desc_cnt);
+
+	/* kick rx dma channel if disabled */
+	cfg = readl_be(priv->chan + DMAC_CFG_REG(dma->id));
+	if (!(cfg & DMAC_CFG_ENABLE_MASK))
+		setbits_be32(priv->chan + DMAC_CFG_REG(dma->id),
+			     DMAC_CFG_ENABLE_MASK);
+
+	return 0;
+}
+
+static int bcm6348_iudma_add_rcv_buf(struct dma *dma, void *dst, size_t size)
+{
+	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+	struct bcm6348_dma_desc *dma_desc = ch_priv->dma_ring;
+
+	/* no more dma descriptors available */
+	if (ch_priv->desc_cnt == ch_priv->dma_ring_size) {
+		pr_err("max number of buffers reached\n");
+		return -EINVAL;
+	}
+
+	/* get next dma descriptor */
+	dma_desc += ch_priv->desc_cnt;
+
+	/* init dma descriptor */
+	dma_desc->address = virt_to_phys(dst);
+	dma_desc->length = size;
+	dma_desc->status = 0;
+
+	/* flush cache */
+	bcm6348_iudma_fdc(dma_desc, sizeof(*dma_desc));
+
+	/* increment dma descriptors */
+	ch_priv->desc_cnt++;
+
+	return 0;
+}
+
+static int bcm6348_iudma_prepare_rcv_buf(struct dma *dma, void *dst,
+					 size_t size)
+{
+	const struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];
+
+	/* only add new rx buffers if channel isn't running */
+	if (ch_priv->running)
+		return bcm6348_iudma_free_rcv_buf(dma, dst, size);
+	else
+		return bcm6348_iudma_add_rcv_buf(dma, dst, size);
+}
+
+static const struct dma_ops bcm6348_iudma_ops = {
+	.disable = bcm6348_iudma_disable,
+	.enable = bcm6348_iudma_enable,
+	.prepare_rcv_buf = bcm6348_iudma_prepare_rcv_buf,
+	.request = bcm6348_iudma_request,
+	.receive = bcm6348_iudma_receive,
+	.send = bcm6348_iudma_send,
+};
+
+static const struct bcm6348_iudma_hw bcm6348_hw = {
+	.err_mask = (DMAD6348_ST_OV_ERR_MASK |
+		     DMAD6348_ST_CRC_ERR_MASK |
+		     DMAD6348_ST_RX_ERR_MASK |
+		     DMAD6348_ST_OS_ERR_MASK |
+		     DMAD6348_ST_UN_ERR_MASK),
+};
+
+static const struct bcm6348_iudma_hw bcm6368_hw = {
+	.err_mask = 0,
+};
+
+static const struct udevice_id bcm6348_iudma_ids[] = {
+	{
+		.compatible = "brcm,bcm6348-iudma",
+		.data = (ulong)&bcm6348_hw,
+	}, {
+		.compatible = "brcm,bcm6368-iudma",
+		.data = (ulong)&bcm6368_hw,
+	}, { /* sentinel */ }
+};
+
+static int bcm6348_iudma_probe(struct udevice *dev)
+{
+	struct dma_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct bcm6348_iudma_priv *priv = dev_get_priv(dev);
+	const struct bcm6348_iudma_hw *hw =
+		(const struct bcm6348_iudma_hw *)dev_get_driver_data(dev);
+	uint8_t ch;
+	int i;
+
+	uc_priv->supported = (DMA_SUPPORTS_DEV_TO_MEM |
+			      DMA_SUPPORTS_MEM_TO_DEV);
+	priv->hw = hw;
+
+	/* dma global base address */
+	priv->base = dev_remap_addr_name(dev, "dma");
+	if (!priv->base)
+		return -EINVAL;
+
+	/* dma channels base address */
+	priv->chan = dev_remap_addr_name(dev, "dma-channels");
+	if (!priv->chan)
+		return -EINVAL;
+
+	/* dma sram base address */
+	priv->sram = dev_remap_addr_name(dev, "dma-sram");
+	if (!priv->sram)
+		return -EINVAL;
+
+	/* get number of channels */
+	priv->n_channels = dev_read_u32_default(dev, "dma-channels", 8);
+	if (priv->n_channels > DMA_CHAN_MAX)
+		return -EINVAL;
+
+	/* try to enable clocks */
+	for (i = 0; ; i++) {
+		struct clk clk;
+		int ret;
+
+		ret = clk_get_by_index(dev, i, &clk);
+		if (ret < 0)
+			break;
+
+		ret = clk_enable(&clk);
+		if (ret < 0) {
+			pr_err("error enabling clock %d\n", i);
+			return ret;
+		}
+
+		ret = clk_free(&clk);
+		if (ret < 0) {
+			pr_err("error freeing clock %d\n", i);
+			return ret;
+		}
+	}
+
+	/* try to perform resets */
+	for (i = 0; ; i++) {
+		struct reset_ctl reset;
+		int ret;
+
+		ret = reset_get_by_index(dev, i, &reset);
+		if (ret < 0)
+			break;
+
+		ret = reset_deassert(&reset);
+		if (ret < 0) {
+			pr_err("error deasserting reset %d\n", i);
+			return ret;
+		}
+
+		ret = reset_free(&reset);
+		if (ret < 0) {
+			pr_err("error freeing reset %d\n", i);
+			return ret;
+		}
+	}
+
+	/* disable dma controller */
+	clrbits_be32(priv->base + DMA_CFG_REG, DMA_CFG_ENABLE_MASK);
+
+	/* alloc channel private data pointers */
+	priv->ch_priv = calloc(priv->n_channels,
+			       sizeof(struct bcm6348_chan_priv*));
+	if (!priv->ch_priv)
+		return -ENOMEM;
+
+	/* stop dma channels */
+	for (ch = 0; ch < priv->n_channels; ch++)
+		bcm6348_iudma_chan_stop(priv, ch);
+
+	/* enable dma controller */
+	setbits_be32(priv->base + DMA_CFG_REG, DMA_CFG_ENABLE_MASK);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(bcm6348_iudma) = {
+	.name = "bcm6348_iudma",
+	.id = UCLASS_DMA,
+	.of_match = bcm6348_iudma_ids,
+	.ops = &bcm6348_iudma_ops,
+	.priv_auto_alloc_size = sizeof(struct bcm6348_iudma_priv),
+	.probe = bcm6348_iudma_probe,
+};
-- 
2.11.0

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

* [U-Boot] [PATCH v11 02/28] bmips: bcm6338: add bcm6348-iudma support
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 01/28] dma: add bcm6348-iudma support Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 03/28] bmips: bcm6348: " Álvaro Fernández Rojas
                           ` (26 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v11: no changes
 v10: fix license identifiers
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6338.dtsi       | 14 ++++++++++++++
 include/dt-bindings/dma/bcm6338-dma.h | 14 ++++++++++++++
 2 files changed, 28 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6338-dma.h

diff --git a/arch/mips/dts/brcm,bcm6338.dtsi b/arch/mips/dts/brcm,bcm6338.dtsi
index bbd58cf803..990355481c 100644
--- a/arch/mips/dts/brcm,bcm6338.dtsi
+++ b/arch/mips/dts/brcm,bcm6338.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6338-clock.h>
+#include <dt-bindings/dma/bcm6338-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/reset/bcm6338-reset.h>
 #include "skeleton.dtsi"
@@ -130,5 +131,18 @@
 			reg = <0xfffe3100 0x38>;
 			u-boot,dm-pre-reloc;
 		};
+
+		iudma: dma-controller at fffe2400 {
+			compatible = "brcm,bcm6348-iudma";
+			reg = <0xfffe2400 0x1c>,
+			      <0xfffe2500 0x60>,
+			      <0xfffe2600 0x60>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <6>;
+			resets = <&periph_rst BCM6338_RST_DMAMEM>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6338-dma.h b/include/dt-bindings/dma/bcm6338-dma.h
new file mode 100644
index 0000000000..f2e0b20444
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6338-dma.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6338_H
+#define __DT_BINDINGS_DMA_BCM6338_H
+
+#define BCM6338_DMA_ENET_RX	0
+#define BCM6338_DMA_ENET_TX	1
+
+#endif /* __DT_BINDINGS_DMA_BCM6338_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v11 03/28] bmips: bcm6348: add bcm6348-iudma support
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 01/28] dma: add bcm6348-iudma support Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 02/28] bmips: bcm6338: " Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 04/28] bmips: bcm6358: " Álvaro Fernández Rojas
                           ` (25 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v11: no changes
 v10: fix license identifiers
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6348.dtsi       | 16 ++++++++++++++++
 include/dt-bindings/dma/bcm6348-dma.h | 16 ++++++++++++++++
 2 files changed, 32 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6348-dma.h

diff --git a/arch/mips/dts/brcm,bcm6348.dtsi b/arch/mips/dts/brcm,bcm6348.dtsi
index cc80bbc808..875de232ca 100644
--- a/arch/mips/dts/brcm,bcm6348.dtsi
+++ b/arch/mips/dts/brcm,bcm6348.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6348-clock.h>
+#include <dt-bindings/dma/bcm6348-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/reset/bcm6348-reset.h>
 #include "skeleton.dtsi"
@@ -159,5 +160,20 @@
 			reg = <0xfffe2300 0x38>;
 			u-boot,dm-pre-reloc;
 		};
+
+		iudma: dma-controller at fffe7000 {
+			compatible = "brcm,bcm6348-iudma";
+			reg = <0xfffe7000 0x1c>,
+			      <0xfffe7100 0x40>,
+			      <0xfffe7200 0x40>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <4>;
+			clocks = <&periph_clk BCM6348_CLK_ENET>;
+			resets = <&periph_rst BCM6348_RST_ENET>,
+				 <&periph_rst BCM6348_RST_DMAMEM>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6348-dma.h b/include/dt-bindings/dma/bcm6348-dma.h
new file mode 100644
index 0000000000..36c2ffd412
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6348-dma.h
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6348_H
+#define __DT_BINDINGS_DMA_BCM6348_H
+
+#define BCM6348_DMA_ENET0_RX	0
+#define BCM6348_DMA_ENET0_TX	1
+#define BCM6348_DMA_ENET1_RX	2
+#define BCM6348_DMA_ENET1_TX	3
+
+#endif /* __DT_BINDINGS_DMA_BCM6348_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v11 04/28] bmips: bcm6358: add bcm6348-iudma support
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                           ` (2 preceding siblings ...)
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 03/28] bmips: bcm6348: " Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 05/28] bmips: bcm6368: " Álvaro Fernández Rojas
                           ` (24 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v11: no changes
 v10: fix license identifiers
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6358.dtsi       | 18 ++++++++++++++++++
 include/dt-bindings/dma/bcm6358-dma.h | 16 ++++++++++++++++
 2 files changed, 34 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6358-dma.h

diff --git a/arch/mips/dts/brcm,bcm6358.dtsi b/arch/mips/dts/brcm,bcm6358.dtsi
index 0617b46e92..5605723e83 100644
--- a/arch/mips/dts/brcm,bcm6358.dtsi
+++ b/arch/mips/dts/brcm,bcm6358.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6358-clock.h>
+#include <dt-bindings/dma/bcm6358-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/reset/bcm6358-reset.h>
 #include "skeleton.dtsi"
@@ -190,5 +191,22 @@
 
 			status = "disabled";
 		};
+
+		iudma: dma-controller at fffe5000 {
+			compatible = "brcm,bcm6348-iudma";
+			reg = <0xfffe5000 0x24>,
+			      <0xfffe5100 0x80>,
+			      <0xfffe5200 0x80>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <8>;
+			clocks = <&periph_clk BCM6358_CLK_EMUSB>,
+				 <&periph_clk BCM6358_CLK_USBSU>,
+				 <&periph_clk BCM6358_CLK_EPHY>;
+			resets = <&periph_rst BCM6358_RST_ENET>,
+				 <&periph_rst BCM6358_RST_EPHY>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6358-dma.h b/include/dt-bindings/dma/bcm6358-dma.h
new file mode 100644
index 0000000000..3118b9da0a
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6358-dma.h
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6358_H
+#define __DT_BINDINGS_DMA_BCM6358_H
+
+#define BCM6358_DMA_ENET0_RX	0
+#define BCM6358_DMA_ENET0_TX	1
+#define BCM6358_DMA_ENET1_RX	2
+#define BCM6358_DMA_ENET1_TX	3
+
+#endif /* __DT_BINDINGS_DMA_BCM6358_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v11 05/28] bmips: bcm6368: add bcm6348-iudma support
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                           ` (3 preceding siblings ...)
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 04/28] bmips: bcm6358: " Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 06/28] bmips: bcm6328: " Álvaro Fernández Rojas
                           ` (23 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v11: no changes
 v10: fix license identifiers
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6368.dtsi       | 13 +++++++++++++
 include/dt-bindings/dma/bcm6368-dma.h | 14 ++++++++++++++
 2 files changed, 27 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6368-dma.h

diff --git a/arch/mips/dts/brcm,bcm6368.dtsi b/arch/mips/dts/brcm,bcm6368.dtsi
index 65d769ab4f..30047f6360 100644
--- a/arch/mips/dts/brcm,bcm6368.dtsi
+++ b/arch/mips/dts/brcm,bcm6368.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6368-clock.h>
+#include <dt-bindings/dma/bcm6368-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/reset/bcm6368-reset.h>
 #include "skeleton.dtsi"
@@ -192,5 +193,17 @@
 
 			status = "disabled";
 		};
+
+		iudma: dma-controller at 10006800 {
+			compatible = "brcm,bcm6368-iudma";
+			reg = <0x10006800 0x80>,
+			      <0x10006a00 0x80>,
+			      <0x10006c00 0x80>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <8>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6368-dma.h b/include/dt-bindings/dma/bcm6368-dma.h
new file mode 100644
index 0000000000..36c6caa0e1
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6368-dma.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6368_H
+#define __DT_BINDINGS_DMA_BCM6368_H
+
+#define BCM6368_DMA_ENETSW_RX	0
+#define BCM6368_DMA_ENETSW_TX	1
+
+#endif /* __DT_BINDINGS_DMA_BCM6368_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v11 06/28] bmips: bcm6328: add bcm6348-iudma support
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                           ` (4 preceding siblings ...)
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 05/28] bmips: bcm6368: " Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 07/28] bmips: bcm6362: " Álvaro Fernández Rojas
                           ` (22 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v11: no changes
 v10: fix license identifiers
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6328.dtsi       | 13 +++++++++++++
 include/dt-bindings/dma/bcm6328-dma.h | 14 ++++++++++++++
 2 files changed, 27 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6328-dma.h

diff --git a/arch/mips/dts/brcm,bcm6328.dtsi b/arch/mips/dts/brcm,bcm6328.dtsi
index e00a2950e2..6fa49e22bb 100644
--- a/arch/mips/dts/brcm,bcm6328.dtsi
+++ b/arch/mips/dts/brcm,bcm6328.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6328-clock.h>
+#include <dt-bindings/dma/bcm6328-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/power-domain/bcm6328-power-domain.h>
 #include <dt-bindings/reset/bcm6328-reset.h>
@@ -187,5 +188,17 @@
 			reg = <0x10003000 0x864>;
 			u-boot,dm-pre-reloc;
 		};
+
+		iudma: dma-controller at 1000d800 {
+			compatible = "brcm,bcm6368-iudma";
+			reg = <0x1000d800 0x80>,
+			      <0x1000da00 0x80>,
+			      <0x1000dc00 0x80>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <8>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6328-dma.h b/include/dt-bindings/dma/bcm6328-dma.h
new file mode 100644
index 0000000000..7494df2feb
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6328-dma.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6328_H
+#define __DT_BINDINGS_DMA_BCM6328_H
+
+#define BCM6328_DMA_ENETSW_RX	0
+#define BCM6328_DMA_ENETSW_TX	1
+
+#endif /* __DT_BINDINGS_DMA_BCM6328_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v11 07/28] bmips: bcm6362: add bcm6348-iudma support
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                           ` (5 preceding siblings ...)
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 06/28] bmips: bcm6328: " Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 08/28] bmips: bcm63268: " Álvaro Fernández Rojas
                           ` (21 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v11: no changes
 v10: fix license identifiers
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6362.dtsi       | 13 +++++++++++++
 include/dt-bindings/dma/bcm6362-dma.h | 14 ++++++++++++++
 2 files changed, 27 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6362-dma.h

diff --git a/arch/mips/dts/brcm,bcm6362.dtsi b/arch/mips/dts/brcm,bcm6362.dtsi
index 3047b82b21..94e7de096d 100644
--- a/arch/mips/dts/brcm,bcm6362.dtsi
+++ b/arch/mips/dts/brcm,bcm6362.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6362-clock.h>
+#include <dt-bindings/dma/bcm6362-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/power-domain/bcm6362-power-domain.h>
 #include <dt-bindings/reset/bcm6362-reset.h>
@@ -211,5 +212,17 @@
 			reg = <0x10003000 0x864>;
 			u-boot,dm-pre-reloc;
 		};
+
+		iudma: dma-controller at 1000d800 {
+			compatible = "brcm,bcm6368-iudma";
+			reg = <0x1000d800 0x80>,
+			      <0x1000da00 0x80>,
+			      <0x1000dc00 0x80>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <8>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6362-dma.h b/include/dt-bindings/dma/bcm6362-dma.h
new file mode 100644
index 0000000000..1e62236daa
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6362-dma.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6362_H
+#define __DT_BINDINGS_DMA_BCM6362_H
+
+#define BCM6362_DMA_ENETSW_RX	0
+#define BCM6362_DMA_ENETSW_TX	1
+
+#endif /* __DT_BINDINGS_DMA_BCM6362_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v11 08/28] bmips: bcm63268: add bcm6348-iudma support
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                           ` (6 preceding siblings ...)
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 07/28] bmips: bcm6362: " Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 09/28] bmips: bcm6318: " Álvaro Fernández Rojas
                           ` (20 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v11: no changes
 v10: fix license identifiers
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm63268.dtsi       | 13 +++++++++++++
 include/dt-bindings/dma/bcm63268-dma.h | 14 ++++++++++++++
 2 files changed, 27 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm63268-dma.h

diff --git a/arch/mips/dts/brcm,bcm63268.dtsi b/arch/mips/dts/brcm,bcm63268.dtsi
index 62c440e675..c7ad83c306 100644
--- a/arch/mips/dts/brcm,bcm63268.dtsi
+++ b/arch/mips/dts/brcm,bcm63268.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm63268-clock.h>
+#include <dt-bindings/dma/bcm63268-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/power-domain/bcm63268-power-domain.h>
 #include <dt-bindings/reset/bcm63268-reset.h>
@@ -217,5 +218,17 @@
 			reg = <0x10003000 0x894>;
 			u-boot,dm-pre-reloc;
 		};
+
+		iudma: dma-controller at 1000d800 {
+			compatible = "brcm,bcm6368-iudma";
+			reg = <0x1000d800 0x80>,
+			      <0x1000da00 0x80>,
+			      <0x1000dc00 0x80>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <8>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm63268-dma.h b/include/dt-bindings/dma/bcm63268-dma.h
new file mode 100644
index 0000000000..7d027119e6
--- /dev/null
+++ b/include/dt-bindings/dma/bcm63268-dma.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM63268_H
+#define __DT_BINDINGS_DMA_BCM63268_H
+
+#define BCM63268_DMA_ENETSW_RX	0
+#define BCM63268_DMA_ENETSW_TX	1
+
+#endif /* __DT_BINDINGS_DMA_BCM63268_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v11 09/28] bmips: bcm6318: add bcm6348-iudma support
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                           ` (7 preceding siblings ...)
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 08/28] bmips: bcm63268: " Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 10/28] net: add support for bcm6348-enet Álvaro Fernández Rojas
                           ` (19 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v11: no changes
 v10: fix license identifiers
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6318.dtsi       | 19 +++++++++++++++++++
 include/dt-bindings/dma/bcm6318-dma.h | 14 ++++++++++++++
 2 files changed, 33 insertions(+)
 create mode 100644 include/dt-bindings/dma/bcm6318-dma.h

diff --git a/arch/mips/dts/brcm,bcm6318.dtsi b/arch/mips/dts/brcm,bcm6318.dtsi
index f75988be12..d04b7cbb01 100644
--- a/arch/mips/dts/brcm,bcm6318.dtsi
+++ b/arch/mips/dts/brcm,bcm6318.dtsi
@@ -4,6 +4,7 @@
  */
 
 #include <dt-bindings/clock/bcm6318-clock.h>
+#include <dt-bindings/dma/bcm6318-dma.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/power-domain/bcm6318-power-domain.h>
 #include <dt-bindings/reset/bcm6318-reset.h>
@@ -54,6 +55,12 @@
 			reg = <0x10000004 0x4>;
 			#clock-cells = <1>;
 		};
+
+		ubus_clk: ubus-clk {
+			compatible = "brcm,bcm6345-clk";
+			reg = <0x10000008 0x4>;
+			#clock-cells = <1>;
+		};
 	};
 
 	ubus {
@@ -182,5 +189,17 @@
 
 			status = "disabled";
 		};
+
+		iudma: dma-controller at 10088000 {
+			compatible = "brcm,bcm6368-iudma";
+			reg = <0x10088000 0x80>,
+			      <0x10088200 0x80>,
+			      <0x10088400 0x80>;
+			reg-names = "dma",
+				    "dma-channels",
+				    "dma-sram";
+			#dma-cells = <1>;
+			dma-channels = <8>;
+		};
 	};
 };
diff --git a/include/dt-bindings/dma/bcm6318-dma.h b/include/dt-bindings/dma/bcm6318-dma.h
new file mode 100644
index 0000000000..ad7c5ac2df
--- /dev/null
+++ b/include/dt-bindings/dma/bcm6318-dma.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+ */
+
+#ifndef __DT_BINDINGS_DMA_BCM6318_H
+#define __DT_BINDINGS_DMA_BCM6318_H
+
+#define BCM6318_DMA_ENETSW_RX	0
+#define BCM6318_DMA_ENETSW_TX	1
+
+#endif /* __DT_BINDINGS_DMA_BCM6318_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v11 10/28] net: add support for bcm6348-enet
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                           ` (8 preceding siblings ...)
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 09/28] bmips: bcm6318: " Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 11/28] bmips: bcm6338: " Álvaro Fernández Rojas
                           ` (18 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v11: no changes
 v10: Introduce changes suggested by Daniel Schwierzeck:
  - Fix license identifiers.
  - Remove packet queue.
  - Move dma_prepare_rcv_buf to free_pkt.
  - Switch to live DM live tree.
 v9: use dma_prepare_rcv_buf and remove dma rx channel reset:
  - bcm6348_eth_recv: clear dirty dma descriptors only when packets are copied
   from rx dma.
  - bcm6348_eth_send: remove dma rx channel reset when sending packet.
 v8: Introduce changes from Grygorii Strashko
 v5: Receive as much packets as possible from bcm6348-eth and cache them in
 net_rx_packets. This is needed in order to fix flow control issues.
 v4: Fix issues reported by Grygorii Strashko and other fixes:
  - Copy received dma buffer to net_rx_packets in order to avoid possible
  dma overwrites.
  - Reset dma rx channel when sending a new packet to prevent flow control
  issues.
  - Fix packet casting on bcm6348_eth_recv/send.
 v3: no changes
 v2: select DMA_CHANNELS.

 drivers/net/Kconfig            |  10 +
 drivers/net/Makefile           |   1 +
 drivers/net/bcm6348-eth.c      | 537 +++++++++++++++++++++++++++++++++++++++++
 include/configs/bmips_common.h |   6 +-
 4 files changed, 553 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/bcm6348-eth.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 8fb365fc5d..2b7cec8804 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -72,6 +72,16 @@ config BCM_SF2_ETH_GMAC
 	  by the BCM_SF2_ETH driver.
 	  Say Y to any bcmcygnus based platforms.
 
+config BCM6348_ETH
+	bool "BCM6348 EMAC support"
+	depends on DM_ETH && ARCH_BMIPS
+	select DMA
+	select DMA_CHANNELS
+	select MII
+	select PHYLIB
+	help
+	  This driver supports the BCM6348 Ethernet MAC.
+
 config DWC_ETH_QOS
 	bool "Synopsys DWC Ethernet QOS device support"
 	depends on DM_ETH
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 99056aa041..2647d4dd23 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -6,6 +6,7 @@
 obj-$(CONFIG_ALTERA_TSE) += altera_tse.o
 obj-$(CONFIG_AG7XXX) += ag7xxx.o
 obj-$(CONFIG_ARMADA100_FEC) += armada100_fec.o
+obj-$(CONFIG_BCM6348_ETH) += bcm6348-eth.o
 obj-$(CONFIG_DRIVER_AT91EMAC) += at91_emac.o
 obj-$(CONFIG_DRIVER_AX88180) += ax88180.o
 obj-$(CONFIG_BCM_SF2_ETH) += bcm-sf2-eth.o
diff --git a/drivers/net/bcm6348-eth.c b/drivers/net/bcm6348-eth.c
new file mode 100644
index 0000000000..7100e68bd2
--- /dev/null
+++ b/drivers/net/bcm6348-eth.c
@@ -0,0 +1,537 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c:
+ *	Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dma.h>
+#include <miiphy.h>
+#include <net.h>
+#include <phy.h>
+#include <reset.h>
+#include <wait_bit.h>
+#include <asm/io.h>
+
+#define ETH_RX_DESC			PKTBUFSRX
+#define ETH_MAX_MTU_SIZE		1518
+#define ETH_TIMEOUT			100
+#define ETH_TX_WATERMARK		32
+
+/* ETH Receiver Configuration register */
+#define ETH_RXCFG_REG			0x00
+#define ETH_RXCFG_ENFLOW_SHIFT		5
+#define ETH_RXCFG_ENFLOW_MASK		(1 << ETH_RXCFG_ENFLOW_SHIFT)
+
+/* ETH Receive Maximum Length register */
+#define ETH_RXMAXLEN_REG		0x04
+#define ETH_RXMAXLEN_SHIFT		0
+#define ETH_RXMAXLEN_MASK		(0x7ff << ETH_RXMAXLEN_SHIFT)
+
+/* ETH Transmit Maximum Length register */
+#define ETH_TXMAXLEN_REG		0x08
+#define ETH_TXMAXLEN_SHIFT		0
+#define ETH_TXMAXLEN_MASK		(0x7ff << ETH_TXMAXLEN_SHIFT)
+
+/* MII Status/Control register */
+#define MII_SC_REG			0x10
+#define MII_SC_MDCFREQDIV_SHIFT		0
+#define MII_SC_MDCFREQDIV_MASK		(0x7f << MII_SC_MDCFREQDIV_SHIFT)
+#define MII_SC_PREAMBLE_EN_SHIFT	7
+#define MII_SC_PREAMBLE_EN_MASK		(1 << MII_SC_PREAMBLE_EN_SHIFT)
+
+/* MII Data register */
+#define MII_DAT_REG			0x14
+#define MII_DAT_DATA_SHIFT		0
+#define MII_DAT_DATA_MASK		(0xffff << MII_DAT_DATA_SHIFT)
+#define MII_DAT_TA_SHIFT		16
+#define MII_DAT_TA_MASK			(0x3 << MII_DAT_TA_SHIFT)
+#define MII_DAT_REG_SHIFT		18
+#define MII_DAT_REG_MASK		(0x1f << MII_DAT_REG_SHIFT)
+#define MII_DAT_PHY_SHIFT		23
+#define MII_DAT_PHY_MASK		(0x1f << MII_DAT_PHY_SHIFT)
+#define MII_DAT_OP_SHIFT		28
+#define MII_DAT_OP_WRITE		(0x5 << MII_DAT_OP_SHIFT)
+#define MII_DAT_OP_READ			(0x6 << MII_DAT_OP_SHIFT)
+
+/* ETH Interrupts Mask register */
+#define ETH_IRMASK_REG			0x18
+
+/* ETH Interrupts register */
+#define ETH_IR_REG			0x1c
+#define ETH_IR_MII_SHIFT		0
+#define ETH_IR_MII_MASK			(1 << ETH_IR_MII_SHIFT)
+
+/* ETH Control register */
+#define ETH_CTL_REG			0x2c
+#define ETH_CTL_ENABLE_SHIFT		0
+#define ETH_CTL_ENABLE_MASK		(1 << ETH_CTL_ENABLE_SHIFT)
+#define ETH_CTL_DISABLE_SHIFT		1
+#define ETH_CTL_DISABLE_MASK		(1 << ETH_CTL_DISABLE_SHIFT)
+#define ETH_CTL_RESET_SHIFT		2
+#define ETH_CTL_RESET_MASK		(1 << ETH_CTL_RESET_SHIFT)
+#define ETH_CTL_EPHY_SHIFT		3
+#define ETH_CTL_EPHY_MASK		(1 << ETH_CTL_EPHY_SHIFT)
+
+/* ETH Transmit Control register */
+#define ETH_TXCTL_REG			0x30
+#define ETH_TXCTL_FD_SHIFT		0
+#define ETH_TXCTL_FD_MASK		(1 << ETH_TXCTL_FD_SHIFT)
+
+/* ETH Transmit Watermask register */
+#define ETH_TXWMARK_REG			0x34
+#define ETH_TXWMARK_WM_SHIFT		0
+#define ETH_TXWMARK_WM_MASK		(0x3f << ETH_TXWMARK_WM_SHIFT)
+
+/* MIB Control register */
+#define MIB_CTL_REG			0x38
+#define MIB_CTL_RDCLEAR_SHIFT		0
+#define MIB_CTL_RDCLEAR_MASK		(1 << MIB_CTL_RDCLEAR_SHIFT)
+
+/* ETH Perfect Match registers */
+#define ETH_PM_CNT			4
+#define ETH_PML_REG(x)			(0x58 + (x) * 0x8)
+#define ETH_PMH_REG(x)			(0x5c + (x) * 0x8)
+#define ETH_PMH_VALID_SHIFT		16
+#define ETH_PMH_VALID_MASK		(1 << ETH_PMH_VALID_SHIFT)
+
+/* MIB Counters registers */
+#define MIB_REG_CNT			55
+#define MIB_REG(x)			(0x200 + (x) * 4)
+
+/* ETH data */
+struct bcm6348_eth_priv {
+	void __iomem *base;
+	/* DMA */
+	struct dma rx_dma;
+	struct dma tx_dma;
+	/* PHY */
+	int phy_id;
+	struct phy_device *phy_dev;
+};
+
+static void bcm6348_eth_mac_disable(struct bcm6348_eth_priv *priv)
+{
+	/* disable emac */
+	clrsetbits_be32(priv->base + ETH_CTL_REG, ETH_CTL_ENABLE_MASK,
+			ETH_CTL_DISABLE_MASK);
+
+	/* wait until emac is disabled */
+	if (wait_for_bit_be32(priv->base + ETH_CTL_REG,
+			      ETH_CTL_DISABLE_MASK, false,
+			      ETH_TIMEOUT, false))
+		pr_err("%s: error disabling emac\n", __func__);
+}
+
+static void bcm6348_eth_mac_enable(struct bcm6348_eth_priv *priv)
+{
+	setbits_be32(priv->base + ETH_CTL_REG, ETH_CTL_ENABLE_MASK);
+}
+
+static void bcm6348_eth_mac_reset(struct bcm6348_eth_priv *priv)
+{
+	/* reset emac */
+	writel_be(ETH_CTL_RESET_MASK, priv->base + ETH_CTL_REG);
+	wmb();
+
+	/* wait until emac is reset */
+	if (wait_for_bit_be32(priv->base + ETH_CTL_REG,
+			      ETH_CTL_RESET_MASK, false,
+			      ETH_TIMEOUT, false))
+		pr_err("%s: error resetting emac\n", __func__);
+}
+
+static int bcm6348_eth_free_pkt(struct udevice *dev, uchar *packet, int len)
+{
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+
+	return dma_prepare_rcv_buf(&priv->rx_dma, packet, len);
+}
+
+static int bcm6348_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+
+	return dma_receive(&priv->rx_dma, (void**)packetp, NULL);
+}
+
+static int bcm6348_eth_send(struct udevice *dev, void *packet, int length)
+{
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+
+	return dma_send(&priv->tx_dma, packet, length, NULL);
+}
+
+static int bcm6348_eth_adjust_link(struct udevice *dev,
+				   struct phy_device *phydev)
+{
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+
+	/* mac duplex parameters */
+	if (phydev->duplex)
+		setbits_be32(priv->base + ETH_TXCTL_REG, ETH_TXCTL_FD_MASK);
+	else
+		clrbits_be32(priv->base + ETH_TXCTL_REG, ETH_TXCTL_FD_MASK);
+
+	/* rx flow control (pause frame handling) */
+	if (phydev->pause)
+		setbits_be32(priv->base + ETH_RXCFG_REG,
+			     ETH_RXCFG_ENFLOW_MASK);
+	else
+		clrbits_be32(priv->base + ETH_RXCFG_REG,
+			     ETH_RXCFG_ENFLOW_MASK);
+
+	return 0;
+}
+
+static int bcm6348_eth_start(struct udevice *dev)
+{
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+	int ret, i;
+
+	/* prepare rx dma buffers */
+	for (i = 0; i < ETH_RX_DESC; i++) {
+		ret = dma_prepare_rcv_buf(&priv->rx_dma, net_rx_packets[i],
+					  PKTSIZE_ALIGN);
+		if (ret < 0)
+			break;
+	}
+
+	/* enable dma rx channel */
+	dma_enable(&priv->rx_dma);
+
+	/* enable dma tx channel */
+	dma_enable(&priv->tx_dma);
+
+	ret = phy_startup(priv->phy_dev);
+	if (ret) {
+		pr_err("%s: could not initialize phy\n", __func__);
+		return ret;
+	}
+
+	if (!priv->phy_dev->link) {
+		pr_err("%s: no phy link\n", __func__);
+		return -EIO;
+	}
+
+	bcm6348_eth_adjust_link(dev, priv->phy_dev);
+
+	/* zero mib counters */
+	for (i = 0; i < MIB_REG_CNT; i++)
+		writel_be(0, MIB_REG(i));
+
+	/* enable rx flow control */
+	setbits_be32(priv->base + ETH_RXCFG_REG, ETH_RXCFG_ENFLOW_MASK);
+
+	/* set max rx/tx length */
+	writel_be((ETH_MAX_MTU_SIZE << ETH_RXMAXLEN_SHIFT) &
+		  ETH_RXMAXLEN_MASK, priv->base + ETH_RXMAXLEN_REG);
+	writel_be((ETH_MAX_MTU_SIZE << ETH_TXMAXLEN_SHIFT) &
+		  ETH_TXMAXLEN_MASK, priv->base + ETH_TXMAXLEN_REG);
+
+	/* set correct transmit fifo watermark */
+	writel_be((ETH_TX_WATERMARK << ETH_TXWMARK_WM_SHIFT) &
+		  ETH_TXWMARK_WM_MASK, priv->base + ETH_TXWMARK_REG);
+
+	/* enable emac */
+	bcm6348_eth_mac_enable(priv);
+
+	/* clear interrupts */
+	writel_be(0, priv->base + ETH_IRMASK_REG);
+
+	return 0;
+}
+
+static void bcm6348_eth_stop(struct udevice *dev)
+{
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+
+	/* disable dma rx channel */
+	dma_disable(&priv->rx_dma);
+
+	/* disable dma tx channel */
+	dma_disable(&priv->tx_dma);
+
+	/* disable emac */
+	bcm6348_eth_mac_disable(priv);
+}
+
+static int bcm6348_eth_write_hwaddr(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+	bool running = false;
+
+	/* check if emac is running */
+	if (readl_be(priv->base + ETH_CTL_REG) & ETH_CTL_ENABLE_MASK)
+		running = true;
+
+	/* disable emac */
+	if (running)
+		bcm6348_eth_mac_disable(priv);
+
+	/* set mac address */
+	writel_be((pdata->enetaddr[2] << 24) | (pdata->enetaddr[3]) << 16 |
+		  (pdata->enetaddr[4]) << 8 | (pdata->enetaddr[5]),
+		  priv->base + ETH_PML_REG(0));
+	writel_be((pdata->enetaddr[1]) | (pdata->enetaddr[0] << 8) |
+		  ETH_PMH_VALID_MASK, priv->base + ETH_PMH_REG(0));
+
+	/* enable emac */
+	if (running)
+		bcm6348_eth_mac_enable(priv);
+
+	return 0;
+}
+
+static const struct eth_ops bcm6348_eth_ops = {
+	.free_pkt = bcm6348_eth_free_pkt,
+	.recv = bcm6348_eth_recv,
+	.send = bcm6348_eth_send,
+	.start = bcm6348_eth_start,
+	.stop = bcm6348_eth_stop,
+	.write_hwaddr = bcm6348_eth_write_hwaddr,
+};
+
+static const struct udevice_id bcm6348_eth_ids[] = {
+	{ .compatible = "brcm,bcm6348-enet", },
+	{ /* sentinel */ }
+};
+
+static int bcm6348_mdio_op(void __iomem *base, uint32_t data)
+{
+	/* make sure mii interrupt status is cleared */
+	writel_be(ETH_IR_MII_MASK, base + ETH_IR_REG);
+
+	/* issue mii op */
+	writel_be(data, base + MII_DAT_REG);
+
+	/* wait until emac is disabled */
+	return wait_for_bit_be32(base + ETH_IR_REG,
+				 ETH_IR_MII_MASK, true,
+				 ETH_TIMEOUT, false);
+}
+
+static int bcm6348_mdio_read(struct mii_dev *bus, int addr, int devaddr,
+			     int reg)
+{
+	void __iomem *base = bus->priv;
+	uint32_t val;
+
+	val = MII_DAT_OP_READ;
+	val |= (reg << MII_DAT_REG_SHIFT) & MII_DAT_REG_MASK;
+	val |= (0x2 << MII_DAT_TA_SHIFT) & MII_DAT_TA_MASK;
+	val |= (addr << MII_DAT_PHY_SHIFT) & MII_DAT_PHY_MASK;
+
+	if (bcm6348_mdio_op(base, val)) {
+		pr_err("%s: timeout\n", __func__);
+		return -EINVAL;
+	}
+
+	val = readl_be(base + MII_DAT_REG) & MII_DAT_DATA_MASK;
+	val >>= MII_DAT_DATA_SHIFT;
+
+	return val;
+}
+
+static int bcm6348_mdio_write(struct mii_dev *bus, int addr, int dev_addr,
+			      int reg, u16 value)
+{
+	void __iomem *base = bus->priv;
+	uint32_t val;
+
+	val = MII_DAT_OP_WRITE;
+	val |= (reg << MII_DAT_REG_SHIFT) & MII_DAT_REG_MASK;
+	val |= (0x2 << MII_DAT_TA_SHIFT) & MII_DAT_TA_MASK;
+	val |= (addr << MII_DAT_PHY_SHIFT) & MII_DAT_PHY_MASK;
+	val |= (value << MII_DAT_DATA_SHIFT) & MII_DAT_DATA_MASK;
+
+	if (bcm6348_mdio_op(base, val)) {
+		pr_err("%s: timeout\n", __func__);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int bcm6348_mdio_init(const char *name, void __iomem *base)
+{
+	struct mii_dev *bus;
+
+	bus = mdio_alloc();
+	if (!bus) {
+		pr_err("%s: failed to allocate MDIO bus\n", __func__);
+		return -ENOMEM;
+	}
+
+	bus->read = bcm6348_mdio_read;
+	bus->write = bcm6348_mdio_write;
+	bus->priv = base;
+	snprintf(bus->name, sizeof(bus->name), "%s", name);
+
+	return mdio_register(bus);
+}
+
+static int bcm6348_phy_init(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+	struct mii_dev *bus;
+
+	/* get mii bus */
+	bus = miiphy_get_dev_by_name(dev->name);
+
+	/* phy connect */
+	priv->phy_dev = phy_connect(bus, priv->phy_id, dev,
+				    pdata->phy_interface);
+	if (!priv->phy_dev) {
+		pr_err("%s: no phy device\n", __func__);
+		return -ENODEV;
+	}
+
+	priv->phy_dev->supported = (SUPPORTED_10baseT_Half |
+				    SUPPORTED_10baseT_Full |
+				    SUPPORTED_100baseT_Half |
+				    SUPPORTED_100baseT_Full |
+				    SUPPORTED_Autoneg |
+				    SUPPORTED_Pause |
+				    SUPPORTED_MII);
+	priv->phy_dev->advertising = priv->phy_dev->supported;
+
+	/* phy config */
+	phy_config(priv->phy_dev);
+
+	return 0;
+}
+
+static int bcm6348_eth_probe(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct bcm6348_eth_priv *priv = dev_get_priv(dev);
+	struct ofnode_phandle_args phy;
+	const char *phy_mode;
+	int ret, i;
+
+	/* get base address */
+	priv->base = dev_remap_addr(dev);
+	if (!priv->base)
+		return -EINVAL;
+	pdata->iobase = (phys_addr_t) priv->base;
+
+	/* get phy mode */
+	pdata->phy_interface = PHY_INTERFACE_MODE_NONE;
+	phy_mode = dev_read_string(dev, "phy-mode");
+	if (phy_mode)
+		pdata->phy_interface = phy_get_interface_by_name(phy_mode);
+	if (pdata->phy_interface == PHY_INTERFACE_MODE_NONE)
+		return -ENODEV;
+
+	/* get phy */
+	if (dev_read_phandle_with_args(dev, "phy", NULL, 0, 0, &phy))
+		return -ENOENT;
+	priv->phy_id = ofnode_read_u32_default(phy.node, "reg", -1);
+
+	/* get dma channels */
+	ret = dma_get_by_name(dev, "tx", &priv->tx_dma);
+	if (ret)
+		return -EINVAL;
+
+	ret = dma_get_by_name(dev, "rx", &priv->rx_dma);
+	if (ret)
+		return -EINVAL;
+
+	/* try to enable clocks */
+	for (i = 0; ; i++) {
+		struct clk clk;
+		int ret;
+
+		ret = clk_get_by_index(dev, i, &clk);
+		if (ret < 0)
+			break;
+
+		ret = clk_enable(&clk);
+		if (ret < 0) {
+			pr_err("%s: error enabling clock %d\n", __func__, i);
+			return ret;
+		}
+
+		ret = clk_free(&clk);
+		if (ret < 0) {
+			pr_err("%s: error freeing clock %d\n", __func__, i);
+			return ret;
+		}
+	}
+
+	/* try to perform resets */
+	for (i = 0; ; i++) {
+		struct reset_ctl reset;
+		int ret;
+
+		ret = reset_get_by_index(dev, i, &reset);
+		if (ret < 0)
+			break;
+
+		ret = reset_deassert(&reset);
+		if (ret < 0) {
+			pr_err("%s: error deasserting reset %d\n", __func__, i);
+			return ret;
+		}
+
+		ret = reset_free(&reset);
+		if (ret < 0) {
+			pr_err("%s: error freeing reset %d\n", __func__, i);
+			return ret;
+		}
+	}
+
+	/* disable emac */
+	bcm6348_eth_mac_disable(priv);
+
+	/* reset emac */
+	bcm6348_eth_mac_reset(priv);
+
+	/* select correct mii interface */
+	if (pdata->phy_interface == PHY_INTERFACE_MODE_INTERNAL)
+		clrbits_be32(priv->base + ETH_CTL_REG, ETH_CTL_EPHY_MASK);
+	else
+		setbits_be32(priv->base + ETH_CTL_REG, ETH_CTL_EPHY_MASK);
+
+	/* turn on mdc clock */
+	writel_be((0x1f << MII_SC_MDCFREQDIV_SHIFT) |
+		  MII_SC_PREAMBLE_EN_MASK, priv->base + MII_SC_REG);
+
+	/* set mib counters to not clear when read */
+	clrbits_be32(priv->base + MIB_CTL_REG, MIB_CTL_RDCLEAR_MASK);
+
+	/* initialize perfect match registers */
+	for (i = 0; i < ETH_PM_CNT; i++) {
+		writel_be(0, priv->base + ETH_PML_REG(i));
+		writel_be(0, priv->base + ETH_PMH_REG(i));
+	}
+
+	/* init mii bus */
+	ret = bcm6348_mdio_init(dev->name, priv->base);
+	if (ret)
+		return ret;
+
+	/* init phy */
+	ret = bcm6348_phy_init(dev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+U_BOOT_DRIVER(bcm6348_eth) = {
+	.name = "bcm6348_eth",
+	.id = UCLASS_ETH,
+	.of_match = bcm6348_eth_ids,
+	.ops = &bcm6348_eth_ops,
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+	.priv_auto_alloc_size = sizeof(struct bcm6348_eth_priv),
+	.probe = bcm6348_eth_probe,
+};
diff --git a/include/configs/bmips_common.h b/include/configs/bmips_common.h
index 39ca2e0bf3..788f4af70d 100644
--- a/include/configs/bmips_common.h
+++ b/include/configs/bmips_common.h
@@ -6,6 +6,10 @@
 #ifndef __CONFIG_BMIPS_COMMON_H
 #define __CONFIG_BMIPS_COMMON_H
 
+/* ETH */
+#define CONFIG_PHY_RESET_DELAY		20
+#define CONFIG_SYS_RX_ETH_BUFFER	6
+
 /* UART */
 #define CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200, \
 					  230400, 500000, 1500000 }
@@ -16,7 +20,7 @@
 
 /* Memory usage */
 #define CONFIG_SYS_MAXARGS		24
-#define CONFIG_SYS_MALLOC_LEN		(1024 * 1024)
+#define CONFIG_SYS_MALLOC_LEN		(2 * 1024 * 1024)
 #define CONFIG_SYS_BOOTPARAMS_LEN	(128 * 1024)
 #define CONFIG_SYS_CBSIZE		512
 
-- 
2.11.0

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

* [U-Boot] [PATCH v11 11/28] bmips: bcm6338: add support for bcm6348-enet
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                           ` (9 preceding siblings ...)
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 10/28] net: add support for bcm6348-enet Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 12/28] bmips: enable f@st1704 enet support Álvaro Fernández Rojas
                           ` (17 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v11: no changes
 v10: no changes
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6338.dtsi | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6338.dtsi b/arch/mips/dts/brcm,bcm6338.dtsi
index 990355481c..c547e949dd 100644
--- a/arch/mips/dts/brcm,bcm6338.dtsi
+++ b/arch/mips/dts/brcm,bcm6338.dtsi
@@ -144,5 +144,20 @@
 			dma-channels = <6>;
 			resets = <&periph_rst BCM6338_RST_DMAMEM>;
 		};
+
+		enet: ethernet at fffe2800 {
+			compatible = "brcm,bcm6348-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xfffe2800 0x2dc>;
+			clocks = <&periph_clk BCM6338_CLK_ENET>;
+			resets = <&periph_rst BCM6338_RST_ENET>;
+			dmas = <&iudma BCM6338_DMA_ENET_RX>,
+			       <&iudma BCM6338_DMA_ENET_TX>;
+			dma-names = "rx",
+				    "tx";
+
+			status = "disabled";
+		};
 	};
 };
-- 
2.11.0

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

* [U-Boot] [PATCH v11 12/28] bmips: enable f@st1704 enet support
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                           ` (10 preceding siblings ...)
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 11/28] bmips: bcm6338: " Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 13/28] bmips: bcm6348: add support for bcm6348-enet Álvaro Fernández Rojas
                           ` (16 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v11: no changes
 v10: no changes
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/sagem,f at st1704.dts     | 12 ++++++++++++
 configs/sagem_f at st1704_ram_defconfig |  8 +++++++-
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/sagem,f at st1704.dts b/arch/mips/dts/sagem,f at st1704.dts
index 5300f8b6df..ec6846dd9f 100644
--- a/arch/mips/dts/sagem,f at st1704.dts
+++ b/arch/mips/dts/sagem,f at st1704.dts
@@ -39,6 +39,18 @@
 	};
 };
 
+&enet {
+	status = "okay";
+	phy = <&enetphy>;
+	phy-mode = "mii";
+
+	enetphy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio {
 	status = "okay";
 };
diff --git a/configs/sagem_f at st1704_ram_defconfig b/configs/sagem_f at st1704_ram_defconfig
index 91a966327a..8c36f5dbf8 100644
--- a/configs/sagem_f at st1704_ram_defconfig
+++ b/configs/sagem_f at st1704_ram_defconfig
@@ -27,11 +27,14 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="sagem,f at st1704"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
@@ -40,6 +43,9 @@ CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_SPI_FLASH_MTD=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6348_ETH=y
 CONFIG_DM_RESET=y
 CONFIG_RESET_BCM6345=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
-- 
2.11.0

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

* [U-Boot] [PATCH v11 13/28] bmips: bcm6348: add support for bcm6348-enet
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                           ` (11 preceding siblings ...)
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 12/28] bmips: enable f@st1704 enet support Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 14/28] bmips: enable ct-5361 enet support Álvaro Fernández Rojas
                           ` (15 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v11: no changes
 v10: no changes
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6348.dtsi | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6348.dtsi b/arch/mips/dts/brcm,bcm6348.dtsi
index 875de232ca..79e7bd892b 100644
--- a/arch/mips/dts/brcm,bcm6348.dtsi
+++ b/arch/mips/dts/brcm,bcm6348.dtsi
@@ -161,6 +161,32 @@
 			u-boot,dm-pre-reloc;
 		};
 
+		enet0: ethernet at fffe6000 {
+			compatible = "brcm,bcm6348-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xfffe6000 0x2dc>;
+			dmas = <&iudma BCM6348_DMA_ENET0_RX>,
+			       <&iudma BCM6348_DMA_ENET0_TX>;
+			dma-names = "rx",
+				    "tx";
+
+			status = "disabled";
+		};
+
+		enet1: ethernet at fffe6800 {
+			compatible = "brcm,bcm6348-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xfffe6800 0x2dc>;
+			dmas = <&iudma BCM6348_DMA_ENET1_RX>,
+			       <&iudma BCM6348_DMA_ENET1_TX>;
+			dma-names = "rx",
+				    "tx";
+
+			status = "disabled";
+		};
+
 		iudma: dma-controller at fffe7000 {
 			compatible = "brcm,bcm6348-iudma";
 			reg = <0xfffe7000 0x1c>,
-- 
2.11.0

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

* [U-Boot] [PATCH v11 14/28] bmips: enable ct-5361 enet support
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                           ` (12 preceding siblings ...)
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 13/28] bmips: bcm6348: add support for bcm6348-enet Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 15/28] bmips: bcm6358: add support for bcm6348-enet Álvaro Fernández Rojas
                           ` (14 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v11: no changes
 v10: no changes
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/comtrend,ct-5361.dts    | 12 ++++++++++++
 configs/comtrend_ct5361_ram_defconfig |  8 +++++++-
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/comtrend,ct-5361.dts b/arch/mips/dts/comtrend,ct-5361.dts
index 25747ca95d..f6b8a94e25 100644
--- a/arch/mips/dts/comtrend,ct-5361.dts
+++ b/arch/mips/dts/comtrend,ct-5361.dts
@@ -34,6 +34,18 @@
 	};
 };
 
+&enet1 {
+	status = "okay";
+	phy = <&enet1phy>;
+	phy-mode = "mii";
+
+	enet1phy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
diff --git a/configs/comtrend_ct5361_ram_defconfig b/configs/comtrend_ct5361_ram_defconfig
index 82f2070713..6297e78fd9 100644
--- a/configs/comtrend_ct5361_ram_defconfig
+++ b/configs/comtrend_ct5361_ram_defconfig
@@ -25,11 +25,14 @@ CONFIG_CMD_LICENSE=y
 CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="comtrend,ct-5361"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
@@ -40,6 +43,9 @@ CONFIG_FLASH_CFI_DRIVER=y
 CONFIG_CFI_FLASH=y
 CONFIG_SYS_FLASH_PROTECTION=y
 CONFIG_SYS_FLASH_CFI=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6348_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6348_USBH_PHY=y
 CONFIG_DM_RESET=y
-- 
2.11.0

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

* [U-Boot] [PATCH v11 15/28] bmips: bcm6358: add support for bcm6348-enet
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                           ` (13 preceding siblings ...)
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 14/28] bmips: enable ct-5361 enet support Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 16/28] bmips: enable hg556a enet support Álvaro Fernández Rojas
                           ` (13 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v11: no changes
 v10: no changes
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/brcm,bcm6358.dtsi | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6358.dtsi b/arch/mips/dts/brcm,bcm6358.dtsi
index 5605723e83..5e9c9ad769 100644
--- a/arch/mips/dts/brcm,bcm6358.dtsi
+++ b/arch/mips/dts/brcm,bcm6358.dtsi
@@ -192,6 +192,34 @@
 			status = "disabled";
 		};
 
+		enet0: ethernet at fffe4000 {
+			compatible = "brcm,bcm6348-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xfffe4000 0x2dc>;
+			clocks = <&periph_clk BCM6358_CLK_ENET0>;
+			dmas = <&iudma BCM6358_DMA_ENET0_RX>,
+			       <&iudma BCM6358_DMA_ENET0_TX>;
+			dma-names = "rx",
+				    "tx";
+
+			status = "disabled";
+		};
+
+		enet1: ethernet at fffe4800 {
+			compatible = "brcm,bcm6348-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xfffe4800 0x2dc>;
+			clocks = <&periph_clk BCM6358_CLK_ENET1>;
+			dmas = <&iudma BCM6358_DMA_ENET1_RX>,
+			       <&iudma BCM6358_DMA_ENET1_TX>;
+			dma-names = "rx",
+				    "tx";
+
+			status = "disabled";
+		};
+
 		iudma: dma-controller at fffe5000 {
 			compatible = "brcm,bcm6348-iudma";
 			reg = <0xfffe5000 0x24>,
-- 
2.11.0

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

* [U-Boot] [PATCH v11 16/28] bmips: enable hg556a enet support
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                           ` (14 preceding siblings ...)
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 15/28] bmips: bcm6358: add support for bcm6348-enet Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 17/28] bmips: enable nb4-ser " Álvaro Fernández Rojas
                           ` (12 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v11: no changes
 v10: no changes
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/huawei,hg556a.dts     | 12 ++++++++++++
 configs/huawei_hg556a_ram_defconfig |  8 +++++++-
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/huawei,hg556a.dts b/arch/mips/dts/huawei,hg556a.dts
index 60455c2ff8..6a7fc1df4b 100644
--- a/arch/mips/dts/huawei,hg556a.dts
+++ b/arch/mips/dts/huawei,hg556a.dts
@@ -93,6 +93,18 @@
 	status = "okay";
 };
 
+&enet1 {
+	status = "okay";
+	phy = <&enet1phy>;
+	phy-mode = "mii";
+
+	enet1phy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
diff --git a/configs/huawei_hg556a_ram_defconfig b/configs/huawei_hg556a_ram_defconfig
index 6bb14ba736..d4e6144319 100644
--- a/configs/huawei_hg556a_ram_defconfig
+++ b/configs/huawei_hg556a_ram_defconfig
@@ -25,11 +25,14 @@ CONFIG_CMD_LICENSE=y
 CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="huawei,hg556a"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
@@ -40,6 +43,9 @@ CONFIG_FLASH_CFI_DRIVER=y
 CONFIG_CFI_FLASH=y
 CONFIG_SYS_FLASH_PROTECTION=y
 CONFIG_SYS_FLASH_CFI=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6348_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6358_USBH_PHY=y
 CONFIG_DM_RESET=y
-- 
2.11.0

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

* [U-Boot] [PATCH v11 17/28] bmips: enable nb4-ser enet support
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                           ` (15 preceding siblings ...)
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 16/28] bmips: enable hg556a enet support Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 18/28] net: add support for bcm6368-enet Álvaro Fernández Rojas
                           ` (11 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v11: no changes
 v10: no changes
 v9: no changes
 v8: no changes
 v5: no changes
 v4: no changes
 v3: no changes
 v2: no changes

 arch/mips/dts/sfr,nb4-ser.dts     | 24 ++++++++++++++++++++++++
 configs/sfr_nb4-ser_ram_defconfig |  8 +++++++-
 2 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/sfr,nb4-ser.dts b/arch/mips/dts/sfr,nb4-ser.dts
index bdc6f8ae45..dfbc4148dc 100644
--- a/arch/mips/dts/sfr,nb4-ser.dts
+++ b/arch/mips/dts/sfr,nb4-ser.dts
@@ -53,6 +53,30 @@
 	status = "okay";
 };
 
+&enet0 {
+	status = "okay";
+	phy = <&enet0phy>;
+	phy-mode = "internal";
+
+	enet0phy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
+&enet1 {
+	status = "okay";
+	phy = <&enet1phy>;
+	phy-mode = "mii";
+
+	enet1phy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
diff --git a/configs/sfr_nb4-ser_ram_defconfig b/configs/sfr_nb4-ser_ram_defconfig
index 12adfb01e7..39622875b1 100644
--- a/configs/sfr_nb4-ser_ram_defconfig
+++ b/configs/sfr_nb4-ser_ram_defconfig
@@ -26,11 +26,14 @@ CONFIG_CMD_LICENSE=y
 CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="sfr,nb4-ser"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
@@ -42,6 +45,9 @@ CONFIG_FLASH_CFI_DRIVER=y
 CONFIG_CFI_FLASH=y
 CONFIG_SYS_FLASH_PROTECTION=y
 CONFIG_SYS_FLASH_CFI=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6348_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6358_USBH_PHY=y
 CONFIG_DM_RESET=y
-- 
2.11.0

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

* [U-Boot] [PATCH v11 18/28] net: add support for bcm6368-enet
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                           ` (16 preceding siblings ...)
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 17/28] bmips: enable nb4-ser " Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 19/28] bmips: bcm6368: " Álvaro Fernández Rojas
                           ` (10 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---
 v11: no changes
 v10: Introduce changes suggested by Daniel Schwierzeck:
  - Fix license identifiers.
  - Remove packet queue.
  - Move dma_prepare_rcv_buf to free_pkt.
  - Pad packets smaller than ETH_ZLEN.
  - Switch to live DM live tree.
 v9: introduce flow control improvements from bcm6348-eth:
  - introduce rx packets caching functionality from bcm6348-eth to fix flow
   control issues.
  - code style fixes.
 v8: introduce bcm6368-enet driver

 drivers/net/Kconfig       |   8 +
 drivers/net/Makefile      |   1 +
 drivers/net/bcm6368-eth.c | 625 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 634 insertions(+)
 create mode 100644 drivers/net/bcm6368-eth.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 2b7cec8804..7044c6adf3 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -82,6 +82,14 @@ config BCM6348_ETH
 	help
 	  This driver supports the BCM6348 Ethernet MAC.
 
+config BCM6368_ETH
+	bool "BCM6368 EMAC support"
+	depends on DM_ETH && ARCH_BMIPS
+	select DMA
+	select MII
+	help
+	  This driver supports the BCM6368 Ethernet MAC.
+
 config DWC_ETH_QOS
 	bool "Synopsys DWC Ethernet QOS device support"
 	depends on DM_ETH
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 2647d4dd23..0dbfa03306 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_ALTERA_TSE) += altera_tse.o
 obj-$(CONFIG_AG7XXX) += ag7xxx.o
 obj-$(CONFIG_ARMADA100_FEC) += armada100_fec.o
 obj-$(CONFIG_BCM6348_ETH) += bcm6348-eth.o
+obj-$(CONFIG_BCM6368_ETH) += bcm6368-eth.o
 obj-$(CONFIG_DRIVER_AT91EMAC) += at91_emac.o
 obj-$(CONFIG_DRIVER_AX88180) += ax88180.o
 obj-$(CONFIG_BCM_SF2_ETH) += bcm-sf2-eth.o
diff --git a/drivers/net/bcm6368-eth.c b/drivers/net/bcm6368-eth.c
new file mode 100644
index 0000000000..a31efba9d1
--- /dev/null
+++ b/drivers/net/bcm6368-eth.c
@@ -0,0 +1,625 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c:
+ *	Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dma.h>
+#include <miiphy.h>
+#include <net.h>
+#include <reset.h>
+#include <wait_bit.h>
+#include <asm/io.h>
+
+#define ETH_PORT_STR			"brcm,enetsw-port"
+
+#define ETH_RX_DESC			PKTBUFSRX
+#define ETH_ZLEN			60
+#define ETH_TIMEOUT			100
+
+#define ETH_MAX_PORT			8
+#define ETH_RGMII_PORT0			4
+
+/* Port traffic control */
+#define ETH_PTCTRL_REG(x)		(0x0 + (x))
+#define ETH_PTCTRL_RXDIS_SHIFT		0
+#define ETH_PTCTRL_RXDIS_MASK		(1 << ETH_PTCTRL_RXDIS_SHIFT)
+#define ETH_PTCTRL_TXDIS_SHIFT		1
+#define ETH_PTCTRL_TXDIS_MASK		(1 << ETH_PTCTRL_TXDIS_SHIFT)
+
+/* Switch mode register */
+#define ETH_SWMODE_REG			0xb
+#define ETH_SWMODE_FWD_EN_SHIFT		1
+#define ETH_SWMODE_FWD_EN_MASK		(1 << ETH_SWMODE_FWD_EN_SHIFT)
+
+/* IMP override Register */
+#define ETH_IMPOV_REG			0xe
+#define ETH_IMPOV_LINKUP_SHIFT		0
+#define ETH_IMPOV_LINKUP_MASK		(1 << ETH_IMPOV_LINKUP_SHIFT)
+#define ETH_IMPOV_FDX_SHIFT		1
+#define ETH_IMPOV_FDX_MASK		(1 << ETH_IMPOV_FDX_SHIFT)
+#define ETH_IMPOV_100_SHIFT		2
+#define ETH_IMPOV_100_MASK		(1 << ETH_IMPOV_100_SHIFT)
+#define ETH_IMPOV_1000_SHIFT		3
+#define ETH_IMPOV_1000_MASK		(1 << ETH_IMPOV_1000_SHIFT)
+#define ETH_IMPOV_RXFLOW_SHIFT		4
+#define ETH_IMPOV_RXFLOW_MASK		(1 << ETH_IMPOV_RXFLOW_SHIFT)
+#define ETH_IMPOV_TXFLOW_SHIFT		5
+#define ETH_IMPOV_TXFLOW_MASK		(1 << ETH_IMPOV_TXFLOW_SHIFT)
+#define ETH_IMPOV_FORCE_SHIFT		7
+#define ETH_IMPOV_FORCE_MASK		(1 << ETH_IMPOV_FORCE_SHIFT)
+
+/* Port override Register */
+#define ETH_PORTOV_REG(x)		(0x58 + (x))
+#define ETH_PORTOV_LINKUP_SHIFT		0
+#define ETH_PORTOV_LINKUP_MASK		(1 << ETH_PORTOV_LINKUP_SHIFT)
+#define ETH_PORTOV_FDX_SHIFT		1
+#define ETH_PORTOV_FDX_MASK		(1 << ETH_PORTOV_FDX_SHIFT)
+#define ETH_PORTOV_100_SHIFT		2
+#define ETH_PORTOV_100_MASK		(1 << ETH_PORTOV_100_SHIFT)
+#define ETH_PORTOV_1000_SHIFT		3
+#define ETH_PORTOV_1000_MASK		(1 << ETH_PORTOV_1000_SHIFT)
+#define ETH_PORTOV_RXFLOW_SHIFT		4
+#define ETH_PORTOV_RXFLOW_MASK		(1 << ETH_PORTOV_RXFLOW_SHIFT)
+#define ETH_PORTOV_TXFLOW_SHIFT		5
+#define ETH_PORTOV_TXFLOW_MASK		(1 << ETH_PORTOV_TXFLOW_SHIFT)
+#define ETH_PORTOV_ENABLE_SHIFT		6
+#define ETH_PORTOV_ENABLE_MASK		(1 << ETH_PORTOV_ENABLE_SHIFT)
+
+/* Port RGMII control register */
+#define ETH_RGMII_CTRL_REG(x)		(0x60 + (x))
+#define ETH_RGMII_CTRL_GMII_CLK_EN	(1 << 7)
+#define ETH_RGMII_CTRL_MII_OVERRIDE_EN	(1 << 6)
+#define ETH_RGMII_CTRL_MII_MODE_MASK	(3 << 4)
+#define ETH_RGMII_CTRL_RGMII_MODE	(0 << 4)
+#define ETH_RGMII_CTRL_MII_MODE		(1 << 4)
+#define ETH_RGMII_CTRL_RVMII_MODE	(2 << 4)
+#define ETH_RGMII_CTRL_TIMING_SEL_EN	(1 << 0)
+
+/* Port RGMII timing register */
+#define ENETSW_RGMII_TIMING_REG(x)	(0x68 + (x))
+
+/* MDIO control register */
+#define MII_SC_REG			0xb0
+#define MII_SC_EXT_SHIFT		16
+#define MII_SC_EXT_MASK			(1 << MII_SC_EXT_SHIFT)
+#define MII_SC_REG_SHIFT		20
+#define MII_SC_PHYID_SHIFT		25
+#define MII_SC_RD_SHIFT			30
+#define MII_SC_RD_MASK			(1 << MII_SC_RD_SHIFT)
+#define MII_SC_WR_SHIFT			31
+#define MII_SC_WR_MASK			(1 << MII_SC_WR_SHIFT)
+
+/* MDIO data register */
+#define MII_DAT_REG			0xb4
+
+/* Global Management Configuration Register */
+#define ETH_GMCR_REG			0x200
+#define ETH_GMCR_RST_MIB_SHIFT		0
+#define ETH_GMCR_RST_MIB_MASK		(1 << ETH_GMCR_RST_MIB_SHIFT)
+
+/* Jumbo control register port mask register */
+#define ETH_JMBCTL_PORT_REG		0x4004
+
+/* Jumbo control mib good frame register */
+#define ETH_JMBCTL_MAXSIZE_REG		0x4008
+
+/* ETH port data */
+struct bcm_enetsw_port {
+	bool used;
+	const char *name;
+	/* Config */
+	bool bypass_link;
+	int force_speed;
+	bool force_duplex_full;
+	/* PHY */
+	int phy_id;
+};
+
+/* ETH data */
+struct bcm6368_eth_priv {
+	void __iomem *base;
+	/* DMA */
+	struct dma rx_dma;
+	struct dma tx_dma;
+	/* Ports */
+	uint8_t num_ports;
+	struct bcm_enetsw_port used_ports[ETH_MAX_PORT];
+	int sw_port_link[ETH_MAX_PORT];
+	bool rgmii_override;
+	bool rgmii_timing;
+	/* PHY */
+	int phy_id;
+};
+
+static inline bool bcm_enet_port_is_rgmii(int portid)
+{
+	return portid >= ETH_RGMII_PORT0;
+}
+
+static int bcm6368_mdio_read(struct bcm6368_eth_priv *priv, uint8_t ext,
+			     int phy_id, int reg)
+{
+	uint32_t val;
+
+	writel_be(0, priv->base + MII_SC_REG);
+
+	val = MII_SC_RD_MASK |
+	      (phy_id << MII_SC_PHYID_SHIFT) |
+	      (reg << MII_SC_REG_SHIFT);
+
+	if (ext)
+		val |= MII_SC_EXT_MASK;
+
+	writel_be(val, priv->base + MII_SC_REG);
+	udelay(50);
+
+	return readw_be(priv->base + MII_DAT_REG);
+}
+
+static int bcm6368_mdio_write(struct bcm6368_eth_priv *priv, uint8_t ext,
+			      int phy_id, int reg, u16 data)
+{
+	uint32_t val;
+
+	writel_be(0, priv->base + MII_SC_REG);
+
+	val = MII_SC_WR_MASK |
+	      (phy_id << MII_SC_PHYID_SHIFT) |
+	      (reg << MII_SC_REG_SHIFT);
+
+	if (ext)
+		val |= MII_SC_EXT_MASK;
+
+	val |= data;
+
+	writel_be(val, priv->base + MII_SC_REG);
+	udelay(50);
+
+	return 0;
+}
+
+static int bcm6368_eth_free_pkt(struct udevice *dev, uchar *packet, int len)
+{
+	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+
+	return dma_prepare_rcv_buf(&priv->rx_dma, packet, len);
+}
+
+static int bcm6368_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+
+	return dma_receive(&priv->rx_dma, (void**)packetp, NULL);
+}
+
+static int bcm6368_eth_send(struct udevice *dev, void *packet, int length)
+{
+	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+
+	/* pad packets smaller than ETH_ZLEN */
+	if (length < ETH_ZLEN) {
+		memset(packet + length, 0, ETH_ZLEN - length);
+		length = ETH_ZLEN;
+	}
+
+	return dma_send(&priv->tx_dma, packet, length, NULL);
+}
+
+static int bcm6368_eth_adjust_link(struct udevice *dev)
+{
+	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+	unsigned int i;
+
+	for (i = 0; i < priv->num_ports; i++) {
+		struct bcm_enetsw_port *port;
+		int val, j, up, adv, lpa, speed, duplex, media;
+		int external_phy = bcm_enet_port_is_rgmii(i);
+		u8 override;
+
+		port = &priv->used_ports[i];
+		if (!port->used)
+			continue;
+
+		if (port->bypass_link)
+			continue;
+
+		/* dummy read to clear */
+		for (j = 0; j < 2; j++)
+			val = bcm6368_mdio_read(priv, external_phy,
+						port->phy_id, MII_BMSR);
+
+		if (val == 0xffff)
+			continue;
+
+		up = (val & BMSR_LSTATUS) ? 1 : 0;
+		if (!(up ^ priv->sw_port_link[i]))
+			continue;
+
+		priv->sw_port_link[i] = up;
+
+		/* link changed */
+		if (!up) {
+			dev_info(&priv->pdev->dev, "link DOWN on %s\n",
+				 port->name);
+			writeb_be(ETH_PORTOV_ENABLE_MASK,
+				  priv->base + ETH_PORTOV_REG(i));
+			writeb_be(ETH_PTCTRL_RXDIS_MASK |
+				  ETH_PTCTRL_TXDIS_MASK,
+				  priv->base + ETH_PTCTRL_REG(i));
+			continue;
+		}
+
+		adv = bcm6368_mdio_read(priv, external_phy,
+					port->phy_id, MII_ADVERTISE);
+
+		lpa = bcm6368_mdio_read(priv, external_phy, port->phy_id,
+					MII_LPA);
+
+		/* figure out media and duplex from advertise and LPA values */
+		media = mii_nway_result(lpa & adv);
+		duplex = (media & ADVERTISE_FULL) ? 1 : 0;
+
+		if (media & (ADVERTISE_100FULL | ADVERTISE_100HALF))
+			speed = 100;
+		else
+			speed = 10;
+
+		if (val & BMSR_ESTATEN) {
+			adv = bcm6368_mdio_read(priv, external_phy,
+						port->phy_id, MII_CTRL1000);
+
+			lpa = bcm6368_mdio_read(priv, external_phy,
+						port->phy_id, MII_STAT1000);
+
+			if ((adv & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)) &&
+			    (lpa & (LPA_1000FULL | LPA_1000HALF))) {
+				speed = 1000;
+				duplex = (lpa & LPA_1000FULL);
+			}
+		}
+
+		pr_alert("link UP on %s, %dMbps, %s-duplex\n",
+			 port->name, speed, duplex ? "full" : "half");
+
+		override = ETH_PORTOV_ENABLE_MASK |
+			   ETH_PORTOV_LINKUP_MASK;
+
+		if (speed == 1000)
+			override |= ETH_PORTOV_1000_MASK;
+		else if (speed == 100)
+			override |= ETH_PORTOV_100_MASK;
+		if (duplex)
+			override |= ETH_PORTOV_FDX_MASK;
+
+		writeb_be(override, priv->base + ETH_PORTOV_REG(i));
+		writeb_be(0, priv->base + ETH_PTCTRL_REG(i));
+	}
+
+	return 0;
+}
+
+static int bcm6368_eth_start(struct udevice *dev)
+{
+	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+	uint8_t i;
+
+	/* prepare rx dma buffers */
+	for (i = 0; i < ETH_RX_DESC; i++) {
+		int ret = dma_prepare_rcv_buf(&priv->rx_dma, net_rx_packets[i],
+					      PKTSIZE_ALIGN);
+		if (ret < 0)
+			break;
+	}
+
+	/* enable dma rx channel */
+	dma_enable(&priv->rx_dma);
+
+	/* enable dma tx channel */
+	dma_enable(&priv->tx_dma);
+
+	/* apply override config for bypass_link ports here. */
+	for (i = 0; i < priv->num_ports; i++) {
+		struct bcm_enetsw_port *port;
+		u8 override;
+
+		port = &priv->used_ports[i];
+		if (!port->used)
+			continue;
+
+		if (!port->bypass_link)
+			continue;
+
+		override = ETH_PORTOV_ENABLE_MASK |
+			   ETH_PORTOV_LINKUP_MASK;
+
+		switch (port->force_speed) {
+		case 1000:
+			override |= ETH_PORTOV_1000_MASK;
+			break;
+		case 100:
+			override |= ETH_PORTOV_100_MASK;
+			break;
+		case 10:
+			break;
+		default:
+			pr_warn("%s: invalid forced speed on port %s\n",
+				__func__, port->name);
+			break;
+		}
+
+		if (port->force_duplex_full)
+			override |= ETH_PORTOV_FDX_MASK;
+
+		writeb_be(override, priv->base + ETH_PORTOV_REG(i));
+		writeb_be(0, priv->base + ETH_PTCTRL_REG(i));
+	}
+
+	bcm6368_eth_adjust_link(dev);
+
+	return 0;
+}
+
+static void bcm6368_eth_stop(struct udevice *dev)
+{
+	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+
+	/* disable dma rx channel */
+	dma_disable(&priv->rx_dma);
+
+	/* disable dma tx channel */
+	dma_disable(&priv->tx_dma);
+}
+
+static const struct eth_ops bcm6368_eth_ops = {
+	.free_pkt = bcm6368_eth_free_pkt,
+	.recv = bcm6368_eth_recv,
+	.send = bcm6368_eth_send,
+	.start = bcm6368_eth_start,
+	.stop = bcm6368_eth_stop,
+};
+
+static const struct udevice_id bcm6368_eth_ids[] = {
+	{ .compatible = "brcm,bcm6368-enet", },
+	{ /* sentinel */ }
+};
+
+static bool bcm6368_phy_is_external(struct bcm6368_eth_priv *priv, int phy_id)
+{
+	uint8_t i;
+
+	for (i = 0; i < priv->num_ports; ++i) {
+		if (!priv->used_ports[i].used)
+			continue;
+		if (priv->used_ports[i].phy_id == phy_id)
+			return bcm_enet_port_is_rgmii(i);
+	}
+
+	return true;
+}
+
+static int bcm6368_mii_mdio_read(struct mii_dev *bus, int addr, int devaddr,
+				 int reg)
+{
+	struct bcm6368_eth_priv *priv = bus->priv;
+	bool ext = bcm6368_phy_is_external(priv, addr);
+
+	return bcm6368_mdio_read(priv, ext, addr, reg);
+}
+
+static int bcm6368_mii_mdio_write(struct mii_dev *bus, int addr, int devaddr,
+				  int reg, u16 data)
+{
+	struct bcm6368_eth_priv *priv = bus->priv;
+	bool ext = bcm6368_phy_is_external(priv, addr);
+
+	return bcm6368_mdio_write(priv, ext, addr, reg, data);
+}
+
+static int bcm6368_mdio_init(const char *name, struct bcm6368_eth_priv *priv)
+{
+	struct mii_dev *bus;
+
+	bus = mdio_alloc();
+	if (!bus) {
+		pr_err("%s: failed to allocate MDIO bus\n", __func__);
+		return -ENOMEM;
+	}
+
+	bus->read = bcm6368_mii_mdio_read;
+	bus->write = bcm6368_mii_mdio_write;
+	bus->priv = priv;
+	snprintf(bus->name, sizeof(bus->name), "%s", name);
+
+	return mdio_register(bus);
+}
+
+static int bcm6368_eth_probe(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct bcm6368_eth_priv *priv = dev_get_priv(dev);
+	int num_ports, ret, i;
+	uint32_t val;
+	ofnode node;
+
+	/* get base address */
+	priv->base = dev_remap_addr(dev);
+	if (!priv->base)
+		return -EINVAL;
+	pdata->iobase = (phys_addr_t) priv->base;
+
+	/* get number of ports */
+	num_ports = dev_read_u32_default(dev, "brcm,num-ports", ETH_MAX_PORT);
+	if (!num_ports || num_ports > ETH_MAX_PORT)
+		return -EINVAL;
+
+	/* get dma channels */
+	ret = dma_get_by_name(dev, "tx", &priv->tx_dma);
+	if (ret)
+		return -EINVAL;
+
+	ret = dma_get_by_name(dev, "rx", &priv->rx_dma);
+	if (ret)
+		return -EINVAL;
+
+	/* try to enable clocks */
+	for (i = 0; ; i++) {
+		struct clk clk;
+		int ret;
+
+		ret = clk_get_by_index(dev, i, &clk);
+		if (ret < 0)
+			break;
+
+		ret = clk_enable(&clk);
+		if (ret < 0) {
+			pr_err("%s: error enabling clock %d\n", __func__, i);
+			return ret;
+		}
+
+		ret = clk_free(&clk);
+		if (ret < 0) {
+			pr_err("%s: error freeing clock %d\n", __func__, i);
+			return ret;
+		}
+	}
+
+	/* try to perform resets */
+	for (i = 0; ; i++) {
+		struct reset_ctl reset;
+		int ret;
+
+		ret = reset_get_by_index(dev, i, &reset);
+		if (ret < 0)
+			break;
+
+		ret = reset_deassert(&reset);
+		if (ret < 0) {
+			pr_err("%s: error deasserting reset %d\n", __func__, i);
+			return ret;
+		}
+
+		ret = reset_free(&reset);
+		if (ret < 0) {
+			pr_err("%s: error freeing reset %d\n", __func__, i);
+			return ret;
+		}
+	}
+
+	/* set priv data */
+	priv->num_ports = num_ports;
+	if (dev_read_bool(dev, "brcm,rgmii-override"))
+		priv->rgmii_override = true;
+	if (dev_read_bool(dev, "brcm,rgmii-timing"))
+		priv->rgmii_timing = true;
+
+	/* get ports */
+	dev_for_each_subnode(node, dev) {
+		const char *comp;
+		const char *label;
+		unsigned int p;
+		int phy_id;
+		int speed;
+
+		comp = ofnode_read_string(node, "compatible");
+		if (!comp || memcmp(comp, ETH_PORT_STR, sizeof(ETH_PORT_STR)))
+			continue;
+
+		p = ofnode_read_u32_default(node, "reg", ETH_MAX_PORT);
+		if (p >= num_ports)
+			return -EINVAL;
+
+		label = ofnode_read_string(node, "label");
+		if (!label) {
+			debug("%s: node %s has no label\n", __func__,
+			      ofnode_get_name(node));
+			return -EINVAL;
+		}
+
+		phy_id = ofnode_read_u32_default(node, "brcm,phy-id", -1);
+
+		priv->used_ports[p].used = true;
+		priv->used_ports[p].name = label;
+		priv->used_ports[p].phy_id = phy_id;
+
+		if (ofnode_read_bool(node, "full-duplex"))
+			priv->used_ports[p].force_duplex_full = true;
+		if (ofnode_read_bool(node, "bypass-link"))
+			priv->used_ports[p].bypass_link = true;
+		speed = ofnode_read_u32_default(node, "speed", 0);
+		if (speed)
+			priv->used_ports[p].force_speed = speed;
+	}
+
+	/* init mii bus */
+	ret = bcm6368_mdio_init(dev->name, priv);
+	if (ret)
+		return ret;
+
+	/* disable all ports */
+	for (i = 0; i < priv->num_ports; i++) {
+		writeb_be(ETH_PORTOV_ENABLE_MASK,
+			      priv->base + ETH_PORTOV_REG(i));
+		writeb_be(ETH_PTCTRL_RXDIS_MASK |
+			      ETH_PTCTRL_TXDIS_MASK,
+			      priv->base + ETH_PTCTRL_REG(i));
+
+		priv->sw_port_link[i] = 0;
+	}
+
+	/* enable external ports */
+	for (i = ETH_RGMII_PORT0; i < priv->num_ports; i++) {
+		u8 rgmii_ctrl;
+
+		if (!priv->used_ports[i].used)
+			continue;
+
+		rgmii_ctrl = readb_be(priv->base + ETH_RGMII_CTRL_REG(i));
+		rgmii_ctrl |= ETH_RGMII_CTRL_GMII_CLK_EN;
+		if (priv->rgmii_override)
+			rgmii_ctrl |= ETH_RGMII_CTRL_MII_OVERRIDE_EN;
+		if (priv->rgmii_timing)
+			rgmii_ctrl |= ETH_RGMII_CTRL_TIMING_SEL_EN;
+		writeb_be(rgmii_ctrl, priv->base + ETH_RGMII_CTRL_REG(i));
+	}
+
+	/* reset mib */
+	val = readb_be(priv->base + ETH_GMCR_REG);
+	val |= ETH_GMCR_RST_MIB_MASK;
+	writeb_be(val, priv->base + ETH_GMCR_REG);
+	mdelay(1);
+	val &= ~ETH_GMCR_RST_MIB_MASK;
+	writeb_be(val, priv->base + ETH_GMCR_REG);
+	mdelay(1);
+
+	/* force CPU port state */
+	val = readb_be(priv->base + ETH_IMPOV_REG);
+	val |= ETH_IMPOV_FORCE_MASK | ETH_IMPOV_LINKUP_MASK;
+	writeb_be(val, priv->base + ETH_IMPOV_REG);
+
+	/* enable switch forward engine */
+	val = readb_be(priv->base + ETH_SWMODE_REG);
+	val |= ETH_SWMODE_FWD_EN_MASK;
+	writeb_be(val, priv->base + ETH_SWMODE_REG);
+
+	/* enable jumbo on all ports */
+	writel_be(0x1ff, priv->base + ETH_JMBCTL_PORT_REG);
+	writew_be(9728, priv->base + ETH_JMBCTL_MAXSIZE_REG);
+
+	return 0;
+}
+
+U_BOOT_DRIVER(bcm6368_eth) = {
+	.name = "bcm6368_eth",
+	.id = UCLASS_ETH,
+	.of_match = bcm6368_eth_ids,
+	.ops = &bcm6368_eth_ops,
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+	.priv_auto_alloc_size = sizeof(struct bcm6368_eth_priv),
+	.probe = bcm6368_eth_probe,
+};
-- 
2.11.0

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

* [U-Boot] [PATCH v11 19/28] bmips: bcm6368: add support for bcm6368-enet
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                           ` (17 preceding siblings ...)
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 18/28] net: add support for bcm6368-enet Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 20/28] bmips: enable wap-5813n enet support Álvaro Fernández Rojas
                           ` (9 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v11: no changes
 v10: no changes
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6368.dtsi | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6368.dtsi b/arch/mips/dts/brcm,bcm6368.dtsi
index 30047f6360..89590d6ff9 100644
--- a/arch/mips/dts/brcm,bcm6368.dtsi
+++ b/arch/mips/dts/brcm,bcm6368.dtsi
@@ -205,5 +205,24 @@
 			#dma-cells = <1>;
 			dma-channels = <8>;
 		};
+
+		enet: ethernet at 10f00000 {
+			compatible = "brcm,bcm6368-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x10f00000 0x10000>;
+			clocks = <&periph_clk BCM6368_CLK_SWPKT_USB>,
+				 <&periph_clk BCM6368_CLK_SWPKT_SAR>,
+				 <&periph_clk BCM6368_CLK_ROBOSW>;
+			resets = <&periph_rst BCM6368_RST_SWITCH>,
+				 <&periph_rst BCM6368_RST_EPHY>;
+			dmas = <&iudma BCM6368_DMA_ENETSW_RX>,
+			       <&iudma BCM6368_DMA_ENETSW_TX>;
+			dma-names = "rx",
+				    "tx";
+			brcm,num-ports = <6>;
+
+			status = "disabled";
+		};
 	};
 };
-- 
2.11.0

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

* [U-Boot] [PATCH v11 20/28] bmips: enable wap-5813n enet support
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                           ` (18 preceding siblings ...)
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 19/28] bmips: bcm6368: " Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 21/28] bmips: bcm6328: add support for bcm6368-enet Álvaro Fernández Rojas
                           ` (8 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v11: no changes
 v10: no changes
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/comtrend,wap-5813n.dts    | 14 ++++++++++++++
 configs/comtrend_wap5813n_ram_defconfig |  8 +++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/comtrend,wap-5813n.dts b/arch/mips/dts/comtrend,wap-5813n.dts
index bd41dab9f8..7e835b28d2 100644
--- a/arch/mips/dts/comtrend,wap-5813n.dts
+++ b/arch/mips/dts/comtrend,wap-5813n.dts
@@ -54,6 +54,20 @@
 	status = "okay";
 };
 
+&enet {
+	status = "okay";
+
+	port at 4 {
+		compatible = "brcm,enetsw-port";
+		reg = <4>;
+		label = "rgmii";
+		brcm,phy-id = <0xff>;
+		speed = <1000>;
+		full-duplex;
+		bypass-link;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
diff --git a/configs/comtrend_wap5813n_ram_defconfig b/configs/comtrend_wap5813n_ram_defconfig
index 987e4c3fbc..fd5107bb7d 100644
--- a/configs/comtrend_wap5813n_ram_defconfig
+++ b/configs/comtrend_wap5813n_ram_defconfig
@@ -25,11 +25,14 @@ CONFIG_CMD_LICENSE=y
 CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="comtrend,wap-5813n"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
@@ -40,6 +43,9 @@ CONFIG_FLASH_CFI_DRIVER=y
 CONFIG_CFI_FLASH=y
 CONFIG_SYS_FLASH_PROTECTION=y
 CONFIG_SYS_FLASH_CFI=y
+CONFIG_DM_ETH=y
+CONFIG_PHY_GIGE=y
+CONFIG_BCM6368_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6368_USBH_PHY=y
 CONFIG_DM_RESET=y
-- 
2.11.0

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

* [U-Boot] [PATCH v11 21/28] bmips: bcm6328: add support for bcm6368-enet
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                           ` (19 preceding siblings ...)
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 20/28] bmips: enable wap-5813n enet support Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 22/28] bmips: enable ar-5387un enet support Álvaro Fernández Rojas
                           ` (7 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v11: no changes
 v10: no changes
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6328.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6328.dtsi b/arch/mips/dts/brcm,bcm6328.dtsi
index 6fa49e22bb..50beed4171 100644
--- a/arch/mips/dts/brcm,bcm6328.dtsi
+++ b/arch/mips/dts/brcm,bcm6328.dtsi
@@ -200,5 +200,22 @@
 			#dma-cells = <1>;
 			dma-channels = <8>;
 		};
+
+		enet: ethernet at 10e00000 {
+			compatible = "brcm,bcm6368-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x10e00000 0x10000>;
+			clocks = <&periph_clk BCM6328_CLK_ROBOSW>;
+			resets = <&periph_rst BCM6328_RST_ENETSW>,
+				 <&periph_rst BCM6328_RST_EPHY>;
+			dmas = <&iudma BCM6328_DMA_ENETSW_RX>,
+			       <&iudma BCM6328_DMA_ENETSW_TX>;
+			dma-names = "rx",
+				    "tx";
+			brcm,num-ports = <5>;
+
+			status = "disabled";
+		};
 	};
 };
-- 
2.11.0

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

* [U-Boot] [PATCH v11 22/28] bmips: enable ar-5387un enet support
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                           ` (20 preceding siblings ...)
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 21/28] bmips: bcm6328: add support for bcm6368-enet Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 23/28] bmips: bcm6362: add support for bcm6368-enet Álvaro Fernández Rojas
                           ` (6 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v11: no changes
 v10: no changes
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/comtrend,ar-5387un.dts    | 32 ++++++++++++++++++++++++++++++++
 configs/comtrend_ar5387un_ram_defconfig |  7 ++++++-
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/comtrend,ar-5387un.dts b/arch/mips/dts/comtrend,ar-5387un.dts
index e993b5cd89..03e3851ab1 100644
--- a/arch/mips/dts/comtrend,ar-5387un.dts
+++ b/arch/mips/dts/comtrend,ar-5387un.dts
@@ -24,6 +24,38 @@
 	status = "okay";
 };
 
+&enet {
+	status = "okay";
+
+	port at 0 {
+		compatible = "brcm,enetsw-port";
+		reg = <0>;
+		label = "fe1";
+		brcm,phy-id = <1>;
+	};
+
+	port at 1 {
+		compatible = "brcm,enetsw-port";
+		reg = <1>;
+		label = "fe2";
+		brcm,phy-id = <2>;
+	};
+
+	port at 2 {
+		compatible = "brcm,enetsw-port";
+		reg = <2>;
+		label = "fe3";
+		brcm,phy-id = <3>;
+	};
+
+	port at 3 {
+		compatible = "brcm,enetsw-port";
+		reg = <3>;
+		label = "fe4";
+		brcm,phy-id = <4>;
+	};
+};
+
 &leds {
 	status = "okay";
 
diff --git a/configs/comtrend_ar5387un_ram_defconfig b/configs/comtrend_ar5387un_ram_defconfig
index f129870ca0..5ba401a441 100644
--- a/configs/comtrend_ar5387un_ram_defconfig
+++ b/configs/comtrend_ar5387un_ram_defconfig
@@ -28,11 +28,14 @@ CONFIG_CMD_MEMINFO=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="comtrend,ar-5387un"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_LED=y
 CONFIG_LED_BCM6328=y
@@ -41,6 +44,8 @@ CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_MACRONIX=y
 CONFIG_SPI_FLASH_MTD=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6368_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6368_USBH_PHY=y
 CONFIG_POWER_DOMAIN=y
-- 
2.11.0

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

* [U-Boot] [PATCH v11 23/28] bmips: bcm6362: add support for bcm6368-enet
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                           ` (21 preceding siblings ...)
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 22/28] bmips: enable ar-5387un enet support Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 24/28] bmips: enable dgnd3700v2 enet support Álvaro Fernández Rojas
                           ` (5 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v11: no changes
 v10: no changes
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6362.dtsi | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6362.dtsi b/arch/mips/dts/brcm,bcm6362.dtsi
index 94e7de096d..c77b80a4cc 100644
--- a/arch/mips/dts/brcm,bcm6362.dtsi
+++ b/arch/mips/dts/brcm,bcm6362.dtsi
@@ -224,5 +224,24 @@
 			#dma-cells = <1>;
 			dma-channels = <8>;
 		};
+
+		enet: ethernet at 10e00000 {
+			compatible = "brcm,bcm6368-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x10e00000 0x10000>;
+			clocks = <&periph_clk BCM6362_CLK_SWPKT_USB>,
+				 <&periph_clk BCM6362_CLK_SWPKT_SAR>,
+				 <&periph_clk BCM6362_CLK_ROBOSW>;
+			resets = <&periph_rst BCM6362_RST_ENETSW>,
+				 <&periph_rst BCM6362_RST_EPHY>;
+			dmas = <&iudma BCM6362_DMA_ENETSW_RX>,
+			       <&iudma BCM6362_DMA_ENETSW_TX>;
+			dma-names = "rx",
+				    "tx";
+			brcm,num-ports = <6>;
+
+			status = "disabled";
+		};
 	};
 };
-- 
2.11.0

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

* [U-Boot] [PATCH v11 24/28] bmips: enable dgnd3700v2 enet support
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                           ` (22 preceding siblings ...)
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 23/28] bmips: bcm6362: add support for bcm6368-enet Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 25/28] bmips: bcm63268: add support for bcm6368-enet Álvaro Fernández Rojas
                           ` (4 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v11: no changes
 v10: no changes
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/netgear,dgnd3700v2.dts     | 14 ++++++++++++++
 configs/netgear_dgnd3700v2_ram_defconfig |  8 +++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/netgear,dgnd3700v2.dts b/arch/mips/dts/netgear,dgnd3700v2.dts
index 322d1567ff..2b72491f0b 100644
--- a/arch/mips/dts/netgear,dgnd3700v2.dts
+++ b/arch/mips/dts/netgear,dgnd3700v2.dts
@@ -43,6 +43,20 @@
 	status = "okay";
 };
 
+&enet {
+	status = "okay";
+
+	port at 4 {
+		compatible = "brcm,enetsw-port";
+		reg = <4>;
+		label = "rgmii";
+		brcm,phy-id = <0xff>;
+		speed = <1000>;
+		full-duplex;
+		bypass-link;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
diff --git a/configs/netgear_dgnd3700v2_ram_defconfig b/configs/netgear_dgnd3700v2_ram_defconfig
index 1abc869856..0f3914fe7e 100644
--- a/configs/netgear_dgnd3700v2_ram_defconfig
+++ b/configs/netgear_dgnd3700v2_ram_defconfig
@@ -27,17 +27,23 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
-# CONFIG_CMD_NET is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="netgear,dgnd3700v2"
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
 CONFIG_LED_BCM6328=y
 CONFIG_LED_BLINK=y
 CONFIG_LED_GPIO=y
+CONFIG_DM_ETH=y
+CONFIG_PHY_GIGE=y
+CONFIG_BCM6368_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6368_USBH_PHY=y
 CONFIG_POWER_DOMAIN=y
-- 
2.11.0

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

* [U-Boot] [PATCH v11 25/28] bmips: bcm63268: add support for bcm6368-enet
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                           ` (23 preceding siblings ...)
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 24/28] bmips: enable dgnd3700v2 enet support Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 26/28] bmips: enable vr-3032u enet support Álvaro Fernández Rojas
                           ` (3 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v11: no changes
 v10: no changes
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm63268.dtsi | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm63268.dtsi b/arch/mips/dts/brcm,bcm63268.dtsi
index c7ad83c306..f8a72ef535 100644
--- a/arch/mips/dts/brcm,bcm63268.dtsi
+++ b/arch/mips/dts/brcm,bcm63268.dtsi
@@ -230,5 +230,30 @@
 			#dma-cells = <1>;
 			dma-channels = <8>;
 		};
+
+		enet: ethernet at 10700000 {
+			compatible = "brcm,bcm6368-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x10700000 0x10000>;
+			clocks = <&periph_clk BCM63268_CLK_GMAC>,
+				 <&periph_clk BCM63268_CLK_ROBOSW>,
+				 <&periph_clk BCM63268_CLK_ROBOSW250>,
+				 <&timer_clk BCM63268_TCLK_EPHY1>,
+				 <&timer_clk BCM63268_TCLK_EPHY2>,
+				 <&timer_clk BCM63268_TCLK_EPHY3>,
+				 <&timer_clk BCM63268_TCLK_GPHY>;
+			resets = <&periph_rst BCM63268_RST_ENETSW>,
+				 <&periph_rst BCM63268_RST_EPHY>,
+				 <&periph_rst BCM63268_RST_GPHY>;
+			dmas = <&iudma BCM63268_DMA_ENETSW_RX>,
+			       <&iudma BCM63268_DMA_ENETSW_TX>;
+			dma-names = "rx",
+				    "tx";
+			brcm,rgmii-override;
+			brcm,rgmii-timing;
+
+			status = "disabled";
+		};
 	};
 };
-- 
2.11.0

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

* [U-Boot] [PATCH v11 26/28] bmips: enable vr-3032u enet support
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                           ` (24 preceding siblings ...)
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 25/28] bmips: bcm63268: add support for bcm6368-enet Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 27/28] bmips: bcm6318: add support for bcm6368-enet Álvaro Fernández Rojas
                           ` (2 subsequent siblings)
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v11: no changes
 v10: no changes
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/comtrend,vr-3032u.dts    | 32 ++++++++++++++++++++++++++++++++
 configs/comtrend_vr3032u_ram_defconfig |  7 ++++++-
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/comtrend,vr-3032u.dts b/arch/mips/dts/comtrend,vr-3032u.dts
index 8c6a4a1eac..512cb52de3 100644
--- a/arch/mips/dts/comtrend,vr-3032u.dts
+++ b/arch/mips/dts/comtrend,vr-3032u.dts
@@ -24,6 +24,38 @@
 	status = "okay";
 };
 
+&enet {
+	status = "okay";
+
+	port at 0 {
+		compatible = "brcm,enetsw-port";
+		reg = <0>;
+		label = "fe2";
+		brcm,phy-id = <1>;
+	};
+
+	port at 1 {
+		compatible = "brcm,enetsw-port";
+		reg = <1>;
+		label = "fe3";
+		brcm,phy-id = <2>;
+	};
+
+	port at 2 {
+		compatible = "brcm,enetsw-port";
+		reg = <2>;
+		label = "fe4";
+		brcm,phy-id = <3>;
+	};
+
+	port at 3 {
+		compatible = "brcm,enetsw-port";
+		reg = <3>;
+		label = "fe1";
+		brcm,phy-id = <4>;
+	};
+};
+
 &leds {
 	status = "okay";
 	brcm,serial-leds;
diff --git a/configs/comtrend_vr3032u_ram_defconfig b/configs/comtrend_vr3032u_ram_defconfig
index 1689eecec1..47f53998e1 100644
--- a/configs/comtrend_vr3032u_ram_defconfig
+++ b/configs/comtrend_vr3032u_ram_defconfig
@@ -26,15 +26,20 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="comtrend,vr-3032u"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_LED=y
 CONFIG_LED_BCM6328=y
 CONFIG_LED_BLINK=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6368_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6368_USBH_PHY=y
 CONFIG_POWER_DOMAIN=y
-- 
2.11.0

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

* [U-Boot] [PATCH v11 27/28] bmips: bcm6318: add support for bcm6368-enet
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                           ` (25 preceding siblings ...)
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 26/28] bmips: enable vr-3032u enet support Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 28/28] bmips: enable ar-5315u enet support Álvaro Fernández Rojas
  2018-12-10 15:36         ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Daniel Schwierzeck
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v11: no changes
 v10: no changes
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/brcm,bcm6318.dtsi           | 19 +++++++++++++++++++
 include/dt-bindings/clock/bcm6318-clock.h | 11 +++++++++++
 2 files changed, 30 insertions(+)

diff --git a/arch/mips/dts/brcm,bcm6318.dtsi b/arch/mips/dts/brcm,bcm6318.dtsi
index d04b7cbb01..d678dab242 100644
--- a/arch/mips/dts/brcm,bcm6318.dtsi
+++ b/arch/mips/dts/brcm,bcm6318.dtsi
@@ -190,6 +190,25 @@
 			status = "disabled";
 		};
 
+		enet: ethernet at 10080000 {
+			compatible = "brcm,bcm6368-enet";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x10080000 0x8000>;
+			clocks = <&periph_clk BCM6318_CLK_ROBOSW250>,
+				 <&periph_clk BCM6318_CLK_ROBOSW025>,
+				 <&ubus_clk BCM6318_UCLK_ROBOSW>;
+			resets = <&periph_rst BCM6318_RST_ENETSW>,
+				 <&periph_rst BCM6318_RST_EPHY>;
+			dmas = <&iudma BCM6318_DMA_ENETSW_RX>,
+			       <&iudma BCM6318_DMA_ENETSW_TX>;
+			dma-names = "rx",
+				    "tx";
+			brcm,num-ports = <5>;
+
+			status = "disabled";
+		};
+
 		iudma: dma-controller at 10088000 {
 			compatible = "brcm,bcm6368-iudma";
 			reg = <0x10088000 0x80>,
diff --git a/include/dt-bindings/clock/bcm6318-clock.h b/include/dt-bindings/clock/bcm6318-clock.h
index d5e13c5c2d..3f10448cef 100644
--- a/include/dt-bindings/clock/bcm6318-clock.h
+++ b/include/dt-bindings/clock/bcm6318-clock.h
@@ -33,4 +33,15 @@
 #define BCM6318_CLK_AFE		29
 #define BCM6318_CLK_QPROC	30
 
+#define BCM6318_UCLK_ADSL	0
+#define BCM6318_UCLK_ARB	1
+#define BCM6318_UCLK_MIPS	2
+#define BCM6318_UCLK_PCIE	3
+#define BCM6318_UCLK_PERIPH	4
+#define BCM6318_UCLK_PHYMIPS	5
+#define BCM6318_UCLK_ROBOSW	6
+#define BCM6318_UCLK_SAR	7
+#define BCM6318_UCLK_SDR	8
+#define BCM6318_UCLK_USB	9
+
 #endif /* __DT_BINDINGS_CLOCK_BCM6318_H */
-- 
2.11.0

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

* [U-Boot] [PATCH v11 28/28] bmips: enable ar-5315u enet support
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                           ` (26 preceding siblings ...)
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 27/28] bmips: bcm6318: add support for bcm6368-enet Álvaro Fernández Rojas
@ 2018-12-01 18:00         ` Álvaro Fernández Rojas
  2018-12-10 15:36         ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Daniel Schwierzeck
  28 siblings, 0 replies; 145+ messages in thread
From: Álvaro Fernández Rojas @ 2018-12-01 18:00 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
---
 v11: no changes
 v10: no changes
 v9: no changes
 v8: introduce bcm6368-enet driver

 arch/mips/dts/comtrend,ar-5315u.dts    | 32 ++++++++++++++++++++++++++++++++
 configs/comtrend_ar5315u_ram_defconfig |  7 ++++++-
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/arch/mips/dts/comtrend,ar-5315u.dts b/arch/mips/dts/comtrend,ar-5315u.dts
index 45570189d0..eb60aaa8d5 100644
--- a/arch/mips/dts/comtrend,ar-5315u.dts
+++ b/arch/mips/dts/comtrend,ar-5315u.dts
@@ -24,6 +24,38 @@
 	status = "okay";
 };
 
+&enet {
+	status = "okay";
+
+	port at 0 {
+		compatible = "brcm,enetsw-port";
+		reg = <0>;
+		label = "fe4";
+		brcm,phy-id = <1>;
+	};
+
+	port at 1 {
+		compatible = "brcm,enetsw-port";
+		reg = <1>;
+		label = "fe3";
+		brcm,phy-id = <2>;
+	};
+
+	port at 2 {
+		compatible = "brcm,enetsw-port";
+		reg = <2>;
+		label = "fe2";
+		brcm,phy-id = <3>;
+	};
+
+	port at 3 {
+		compatible = "brcm,enetsw-port";
+		reg = <3>;
+		label = "fe1";
+		brcm,phy-id = <4>;
+	};
+};
+
 &leds {
 	status = "okay";
 
diff --git a/configs/comtrend_ar5315u_ram_defconfig b/configs/comtrend_ar5315u_ram_defconfig
index d9ef52e68d..1b8e4e43c4 100644
--- a/configs/comtrend_ar5315u_ram_defconfig
+++ b/configs/comtrend_ar5315u_ram_defconfig
@@ -28,11 +28,14 @@ CONFIG_CMD_MEMINFO=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
 CONFIG_DEFAULT_DEVICE_TREE="comtrend,ar-5315u"
-# CONFIG_NET is not set
+CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_BCM6348_IUDMA=y
 CONFIG_DM_GPIO=y
 CONFIG_LED=y
 CONFIG_LED_BCM6328=y
@@ -41,6 +44,8 @@ CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_SPI_FLASH_MTD=y
+CONFIG_DM_ETH=y
+CONFIG_BCM6368_ETH=y
 CONFIG_PHY=y
 CONFIG_BCM6318_USBH_PHY=y
 CONFIG_BCM6328_POWER_DOMAIN=y
-- 
2.11.0

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

* [U-Boot] [U-Boot,v9,1/3] dma: move dma_ops to dma-uclass.h
  2018-11-28 18:17     ` [U-Boot] [PATCH v9 1/3] dma: move dma_ops to dma-uclass.h Álvaro Fernández Rojas
@ 2018-12-07 20:33       ` Tom Rini
  0 siblings, 0 replies; 145+ messages in thread
From: Tom Rini @ 2018-12-07 20:33 UTC (permalink / raw)
  To: u-boot

On Wed, Nov 28, 2018 at 07:17:49PM +0100, Álvaro Fernández Rojas wrote:

> Move dma_ops to a separate header file, following other uclass
> implementations. While doing so, this patch also improves dma_ops
> documentation.
> 
> Reviewed-by: Tom Rini <trini@konsulko.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>

Note that we had a comment about add_recv rather than prepare_rcv_buf
that I've corrected.

Applied to u-boot/master, thanks!

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

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

* [U-Boot] [U-Boot,v9,2/3] dma: add channels support
  2018-11-28 18:17     ` [U-Boot] [PATCH v9 2/3] dma: add channels support Álvaro Fernández Rojas
@ 2018-12-07 20:33       ` Tom Rini
  0 siblings, 0 replies; 145+ messages in thread
From: Tom Rini @ 2018-12-07 20:33 UTC (permalink / raw)
  To: u-boot

On Wed, Nov 28, 2018 at 07:17:50PM +0100, Álvaro Fernández Rojas wrote:

> This adds channels support for dma controllers that have multiple channels
> which can transfer data to/from different devices (enet, usb...).
> 
> DMA channle API:
>  dma_get_by_index()
>  dma_get_by_name()
>  dma_request()
>  dma_free()
>  dma_enable()
>  dma_disable()
>  dma_prepare_rcv_buf()
>  dma_receive()
>  dma_send()
> 
> Reviewed-by: Tom Rini <trini@konsulko.com>
> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
> [grygorii.strashko at ti.com: drop unused dma_get_by_index_platdata(),
>  add metadata to send/receive ops, add dma_prepare_rcv_buf(),
>  minor clean up]
> Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

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

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

* [U-Boot] [U-Boot,v9,3/3] test: dma: add dma-uclass test
  2018-11-28 18:17     ` [U-Boot] [PATCH v9 3/3] test: dma: add dma-uclass test Álvaro Fernández Rojas
@ 2018-12-07 20:33       ` Tom Rini
  0 siblings, 0 replies; 145+ messages in thread
From: Tom Rini @ 2018-12-07 20:33 UTC (permalink / raw)
  To: u-boot

On Wed, Nov 28, 2018 at 07:17:51PM +0100, Álvaro Fernández Rojas wrote:

> From: Grygorii Strashko <grygorii.strashko@ti.com>
> 
> Add a sandbox DMA driver implementation (provider) and corresponding DM
> test.
> 
> Reviewed-by: Tom Rini <trini@konsulko.com>
> Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Acked-by: Álvaro Fernández Rojas <noltari@gmail.com>

Note that all of this was using add_recv and not prepare_rcv_buf and
I've fixed that.

Applied to u-boot/master, thanks!

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

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

* [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support
  2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
                           ` (27 preceding siblings ...)
  2018-12-01 18:00         ` [U-Boot] [PATCH v11 28/28] bmips: enable ar-5315u enet support Álvaro Fernández Rojas
@ 2018-12-10 15:36         ` Daniel Schwierzeck
  28 siblings, 0 replies; 145+ messages in thread
From: Daniel Schwierzeck @ 2018-12-10 15:36 UTC (permalink / raw)
  To: u-boot



Am 01.12.18 um 19:00 schrieb Álvaro Fernández Rojas:
> In order to add bcm6348-enet support, dma-uclass must be extended to support
> dma channels and reworked to operate like the other dm uclass (clk, reset...).
> 
> v11: Introduce change suggested by Daniel Schwierzeck:
>  - Avoid trimming ethernet FCS from DMA driver.
> v10: Introduce changes suggested by Daniel Schwierzeck:
>  - Fix license identifiers.
>  bcm6348-iudma:
>   - Move DMAD_ST defines out of dma desc struct definition.
>   - Remove unneded aigned attribute from dma desc struct definition.
>   - Fill dma ring from consumer driver instead of allocating a new buffer.
>   - Correctly check clock/reset errors while probing.
>   - Switch to live DM live tree.
>  bcm6348-enet:
>   - Remove packet queue.
>   - Move dma_prepare_rcv_buf to free_pkt.
>   - Switch to live DM live tree.
>  bcm6368-enet:
>   - Remove packet queue.
>   - Move dma_prepare_rcv_buf to free_pkt.
>   - Pad packets smaller than ETH_ZLEN.
>   - Switch to live DM live tree.
> v9: Separate generic dma channels support from bmips enet support
>  bcm6348-iudma:
>   - bcm6348_iudma_chan_stop: switch to mdelay when resetting channel.
>   - bcm6348_iudma_receive: track dirty dma descriptors and no longer trigger
>    dma rx channel.
>   - bcm6348_iudma_send: reorder to properly flush cache and set dma descriptor
>    config.
>   - bcm6348_iudma_prepare_rcv_buf: implemented to clear dirty dma descriptors.
>  bcm6348-enet:
>   - bcm6348_eth_recv: clear dirty dma descriptors only when packets are copied
>    from rx dma.
>   - bcm6348_eth_send: remove dma rx channel reset when sending packet.
>  bcm6368-enet:
>   - introduce rx packets caching functionality from bcm6348-eth to fix flow
>    control issues.
>   - code style fixes.
> v8: Introduce bcm6368-enet driver support.
> v5: Fix issues reported by Grygorii Strashko and other fixes:
>  - Remove unused bcm6348-iudma defines.
>  - Increment bcm6348-iudma rx descriptors.
>  - Fix bcm6348-iudma flow control issues.
>  - bcm6348-iudma error checking now depends on hw.
>  - Remove unneeded bcm6348-iudma interrupts.
>  - Receive as much packets as possible from bcm6348-eth and cache them in
>  net_rx_packets. This is needed in order to fix flow control issues.
> v4: Fix issues reported by Grygorii Strashko and other fixes:
>  - Remove usage of net_rx_packets as buffer from bcm6348-iudma.
>  - Allocate dynamic rx buffer on bcm6348-iudma.
>  - Copy received dma buffer to net_rx_packets in order to avoid possible
>  dma overwrites.
>  - Check dma errors and discard invalid packets.
>  - Reset dma rx channel when sending a new packet to prevent flow control
>  issues.
>  - Fix packet casting on bcm6348_eth_recv/send.
> v3: Switch to live tree API.
> v2: Fix bcm6348-iudma rx burst config.
> 
> Álvaro Fernández Rojas (28):
>   dma: add bcm6348-iudma support
>   bmips: bcm6338: add bcm6348-iudma support
>   bmips: bcm6348: add bcm6348-iudma support
>   bmips: bcm6358: add bcm6348-iudma support
>   bmips: bcm6368: add bcm6348-iudma support
>   bmips: bcm6328: add bcm6348-iudma support
>   bmips: bcm6362: add bcm6348-iudma support
>   bmips: bcm63268: add bcm6348-iudma support
>   bmips: bcm6318: add bcm6348-iudma support
>   net: add support for bcm6348-enet
>   bmips: bcm6338: add support for bcm6348-enet
>   bmips: enable f at st1704 enet support
>   bmips: bcm6348: add support for bcm6348-enet
>   bmips: enable ct-5361 enet support
>   bmips: bcm6358: add support for bcm6348-enet
>   bmips: enable hg556a enet support
>   bmips: enable nb4-ser enet support
>   net: add support for bcm6368-enet
>   bmips: bcm6368: add support for bcm6368-enet
>   bmips: enable wap-5813n enet support
>   bmips: bcm6328: add support for bcm6368-enet
>   bmips: enable ar-5387un enet support
>   bmips: bcm6362: add support for bcm6368-enet
>   bmips: enable dgnd3700v2 enet support
>   bmips: bcm63268: add support for bcm6368-enet
>   bmips: enable vr-3032u enet support
>   bmips: bcm6318: add support for bcm6368-enet
>   bmips: enable ar-5315u enet support
> 
>  arch/mips/dts/brcm,bcm6318.dtsi           |  38 ++
>  arch/mips/dts/brcm,bcm63268.dtsi          |  38 ++
>  arch/mips/dts/brcm,bcm6328.dtsi           |  30 ++
>  arch/mips/dts/brcm,bcm6338.dtsi           |  29 ++
>  arch/mips/dts/brcm,bcm6348.dtsi           |  42 ++
>  arch/mips/dts/brcm,bcm6358.dtsi           |  46 +++
>  arch/mips/dts/brcm,bcm6362.dtsi           |  32 ++
>  arch/mips/dts/brcm,bcm6368.dtsi           |  32 ++
>  arch/mips/dts/comtrend,ar-5315u.dts       |  32 ++
>  arch/mips/dts/comtrend,ar-5387un.dts      |  32 ++
>  arch/mips/dts/comtrend,ct-5361.dts        |  12 +
>  arch/mips/dts/comtrend,vr-3032u.dts       |  32 ++
>  arch/mips/dts/comtrend,wap-5813n.dts      |  14 +
>  arch/mips/dts/huawei,hg556a.dts           |  12 +
>  arch/mips/dts/netgear,dgnd3700v2.dts      |  14 +
>  arch/mips/dts/sagem,f at st1704.dts          |  12 +
>  arch/mips/dts/sfr,nb4-ser.dts             |  24 ++
>  configs/comtrend_ar5315u_ram_defconfig    |   7 +-
>  configs/comtrend_ar5387un_ram_defconfig   |   7 +-
>  configs/comtrend_ct5361_ram_defconfig     |   8 +-
>  configs/comtrend_vr3032u_ram_defconfig    |   7 +-
>  configs/comtrend_wap5813n_ram_defconfig   |   8 +-
>  configs/huawei_hg556a_ram_defconfig       |   8 +-
>  configs/netgear_dgnd3700v2_ram_defconfig  |   8 +-
>  configs/sagem_f at st1704_ram_defconfig      |   8 +-
>  configs/sfr_nb4-ser_ram_defconfig         |   8 +-
>  drivers/dma/Kconfig                       |   9 +
>  drivers/dma/Makefile                      |   1 +
>  drivers/dma/bcm6348-iudma.c               | 642 ++++++++++++++++++++++++++++++
>  drivers/net/Kconfig                       |  18 +
>  drivers/net/Makefile                      |   2 +
>  drivers/net/bcm6348-eth.c                 | 537 +++++++++++++++++++++++++
>  drivers/net/bcm6368-eth.c                 | 625 +++++++++++++++++++++++++++++
>  include/configs/bmips_common.h            |   6 +-
>  include/dt-bindings/clock/bcm6318-clock.h |  11 +
>  include/dt-bindings/dma/bcm6318-dma.h     |  14 +
>  include/dt-bindings/dma/bcm63268-dma.h    |  14 +
>  include/dt-bindings/dma/bcm6328-dma.h     |  14 +
>  include/dt-bindings/dma/bcm6338-dma.h     |  14 +
>  include/dt-bindings/dma/bcm6348-dma.h     |  16 +
>  include/dt-bindings/dma/bcm6358-dma.h     |  16 +
>  include/dt-bindings/dma/bcm6362-dma.h     |  14 +
>  include/dt-bindings/dma/bcm6368-dma.h     |  14 +
>  43 files changed, 2497 insertions(+), 10 deletions(-)
>  create mode 100644 drivers/dma/bcm6348-iudma.c
>  create mode 100644 drivers/net/bcm6348-eth.c
>  create mode 100644 drivers/net/bcm6368-eth.c
>  create mode 100644 include/dt-bindings/dma/bcm6318-dma.h
>  create mode 100644 include/dt-bindings/dma/bcm63268-dma.h
>  create mode 100644 include/dt-bindings/dma/bcm6328-dma.h
>  create mode 100644 include/dt-bindings/dma/bcm6338-dma.h
>  create mode 100644 include/dt-bindings/dma/bcm6348-dma.h
>  create mode 100644 include/dt-bindings/dma/bcm6358-dma.h
>  create mode 100644 include/dt-bindings/dma/bcm6362-dma.h
>  create mode 100644 include/dt-bindings/dma/bcm6368-dma.h
> 

series applied to u-boot-mips/next, thanks.

Could you send a patch to fix this DTC warning?

w+arch/mips/dts/brcm,bcm968380gerg.dtb: Warning (avoid_unnecessary_addr_size): /clocks: unnecessary #address-cells/#size-cells without "ranges" or child "reg" property

-- 
- Daniel

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

end of thread, other threads:[~2018-12-10 15:36 UTC | newest]

Thread overview: 145+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-10 21:06 [U-Boot] [PATCH v7 0/5] dma: add channels support Grygorii Strashko
2018-11-10 21:06 ` [U-Boot] [PATCH v7 1/5] dma: move dma_ops to dma-uclass.h Grygorii Strashko
2018-11-10 21:06 ` [U-Boot] [PATCH v7 2/5] dma: add channels support Grygorii Strashko
2018-11-13 19:53   ` Simon Glass
2018-11-10 21:06 ` [U-Boot] [PATCH v7 3/5] test: dma: add dma-uclass test Grygorii Strashko
2018-11-13 19:53   ` Simon Glass
2018-11-10 21:06 ` [U-Boot] [NOT-FOR-MERGE-PATCH PATCH v7 4/5] dma: ti: add driver to K3 UDMA Grygorii Strashko
2018-11-10 21:06 ` [U-Boot] [NOT-FOR-MERGE-PATCH PATCH v7 5/5] net: ethernet: ti: introduce am654 gigabit eth switch subsystem driver Grygorii Strashko
2018-11-26 18:00 ` [U-Boot] [PATCH v8 00/31] dma: add channels support Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 01/31] dma: move dma_ops to dma-uclass.h Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 02/31] dma: add channels support Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 03/31] test: dma: add dma-uclass test Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 04/31] dma: add bcm6348-iudma support Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 05/31] bmips: bcm6338: " Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 06/31] bmips: bcm6348: " Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 07/31] bmips: bcm6358: " Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 08/31] bmips: bcm6368: " Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 09/31] bmips: bcm6328: " Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 10/31] bmips: bcm6362: " Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 11/31] bmips: bcm63268: " Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 12/31] bmips: bcm6318: " Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 13/31] net: add support for bcm6348-enet Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 14/31] bmips: bcm6338: " Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 15/31] bmips: enable f@st1704 enet support Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 16/31] bmips: bcm6348: add support for bcm6348-enet Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 17/31] bmips: enable ct-5361 enet support Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 18/31] bmips: bcm6358: add support for bcm6348-enet Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 19/31] bmips: enable hg556a enet support Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 20/31] bmips: enable nb4-ser " Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 21/31] net: add support for bcm6368-enet Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 22/31] bmips: bcm6368: " Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 23/31] bmips: enable wap-5813n enet support Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 24/31] bmips: bcm6328: add support for bcm6368-enet Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 25/31] bmips: enable ar-5387un enet support Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 26/31] bmips: bcm6362: add support for bcm6368-enet Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 27/31] bmips: enable dgnd3700v2 enet support Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 28/31] bmips: bcm63268: add support for bcm6368-enet Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 29/31] bmips: enable vr-3032u enet support Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 30/31] bmips: bcm6318: add support for bcm6368-enet Álvaro Fernández Rojas
2018-11-26 18:00   ` [U-Boot] [PATCH v8 31/31] bmips: enable ar-5315u enet support Álvaro Fernández Rojas
2018-11-26 23:15   ` [U-Boot] [PATCH v8 00/31] dma: add channels support Tom Rini
2018-11-28 18:17   ` [U-Boot] [PATCH v9 0/3] " Álvaro Fernández Rojas
2018-11-28 18:17     ` [U-Boot] [PATCH v9 1/3] dma: move dma_ops to dma-uclass.h Álvaro Fernández Rojas
2018-12-07 20:33       ` [U-Boot] [U-Boot,v9,1/3] " Tom Rini
2018-11-28 18:17     ` [U-Boot] [PATCH v9 2/3] dma: add channels support Álvaro Fernández Rojas
2018-12-07 20:33       ` [U-Boot] [U-Boot,v9,2/3] " Tom Rini
2018-11-28 18:17     ` [U-Boot] [PATCH v9 3/3] test: dma: add dma-uclass test Álvaro Fernández Rojas
2018-12-07 20:33       ` [U-Boot] [U-Boot,v9,3/3] " Tom Rini
2018-11-30 23:56     ` [U-Boot] [PATCH v9 0/3] dma: add channels support Grygorii Strashko
2018-11-28 18:23   ` [U-Boot] [PATCH v9 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
2018-11-28 18:23     ` [U-Boot] [PATCH v9 01/28] dma: add bcm6348-iudma support Álvaro Fernández Rojas
2018-11-28 23:44       ` Daniel Schwierzeck
2018-11-28 18:23     ` [U-Boot] [PATCH v9 02/28] bmips: bcm6338: " Álvaro Fernández Rojas
2018-11-28 23:48       ` Daniel Schwierzeck
2018-11-28 18:23     ` [U-Boot] [PATCH v9 03/28] bmips: bcm6348: " Álvaro Fernández Rojas
2018-11-28 18:23     ` [U-Boot] [PATCH v9 04/28] bmips: bcm6358: " Álvaro Fernández Rojas
2018-11-28 18:23     ` [U-Boot] [PATCH v9 05/28] bmips: bcm6368: " Álvaro Fernández Rojas
2018-11-28 18:23     ` [U-Boot] [PATCH v9 06/28] bmips: bcm6328: " Álvaro Fernández Rojas
2018-11-28 18:23     ` [U-Boot] [PATCH v9 07/28] bmips: bcm6362: " Álvaro Fernández Rojas
2018-11-28 18:23     ` [U-Boot] [PATCH v9 08/28] bmips: bcm63268: " Álvaro Fernández Rojas
2018-11-28 18:23     ` [U-Boot] [PATCH v9 09/28] bmips: bcm6318: " Álvaro Fernández Rojas
2018-11-28 18:23     ` [U-Boot] [PATCH v9 10/28] net: add support for bcm6348-enet Álvaro Fernández Rojas
2018-11-28 23:58       ` Daniel Schwierzeck
2018-11-28 18:23     ` [U-Boot] [PATCH v9 11/28] bmips: bcm6338: " Álvaro Fernández Rojas
2018-11-28 18:23     ` [U-Boot] [PATCH v9 12/28] bmips: enable f@st1704 enet support Álvaro Fernández Rojas
2018-11-28 18:23     ` [U-Boot] [PATCH v9 13/28] bmips: bcm6348: add support for bcm6348-enet Álvaro Fernández Rojas
2018-11-28 18:23     ` [U-Boot] [PATCH v9 14/28] bmips: enable ct-5361 enet support Álvaro Fernández Rojas
2018-11-28 18:23     ` [U-Boot] [PATCH v9 15/28] bmips: bcm6358: add support for bcm6348-enet Álvaro Fernández Rojas
2018-11-28 18:23     ` [U-Boot] [PATCH v9 16/28] bmips: enable hg556a enet support Álvaro Fernández Rojas
2018-11-28 18:23     ` [U-Boot] [PATCH v9 17/28] bmips: enable nb4-ser " Álvaro Fernández Rojas
2018-11-28 18:23     ` [U-Boot] [PATCH v9 18/28] net: add support for bcm6368-enet Álvaro Fernández Rojas
2018-11-29  0:44       ` Daniel Schwierzeck
2018-11-28 18:23     ` [U-Boot] [PATCH v9 19/28] bmips: bcm6368: " Álvaro Fernández Rojas
2018-11-28 18:23     ` [U-Boot] [PATCH v9 20/28] bmips: enable wap-5813n enet support Álvaro Fernández Rojas
2018-11-28 18:23     ` [U-Boot] [PATCH v9 21/28] bmips: bcm6328: add support for bcm6368-enet Álvaro Fernández Rojas
2018-11-28 18:23     ` [U-Boot] [PATCH v9 22/28] bmips: enable ar-5387un enet support Álvaro Fernández Rojas
2018-11-28 18:23     ` [U-Boot] [PATCH v9 23/28] bmips: bcm6362: add support for bcm6368-enet Álvaro Fernández Rojas
2018-11-28 18:23     ` [U-Boot] [PATCH v9 24/28] bmips: enable dgnd3700v2 enet support Álvaro Fernández Rojas
2018-11-28 18:23     ` [U-Boot] [PATCH v9 25/28] bmips: bcm63268: add support for bcm6368-enet Álvaro Fernández Rojas
2018-11-28 18:23     ` [U-Boot] [PATCH v9 26/28] bmips: enable vr-3032u enet support Álvaro Fernández Rojas
2018-11-28 18:23     ` [U-Boot] [PATCH v9 27/28] bmips: bcm6318: add support for bcm6368-enet Álvaro Fernández Rojas
2018-11-28 18:23     ` [U-Boot] [PATCH v9 28/28] bmips: enable ar-5315u enet support Álvaro Fernández Rojas
2018-11-29 22:25     ` [U-Boot] [PATCH v10 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
2018-11-29 22:25       ` [U-Boot] [PATCH v10 01/28] dma: add bcm6348-iudma support Álvaro Fernández Rojas
2018-11-30 13:46         ` Daniel Schwierzeck
2018-11-30 17:13           ` Álvaro Fernández Rojas
2018-11-29 22:25       ` [U-Boot] [PATCH v10 02/28] bmips: bcm6338: " Álvaro Fernández Rojas
2018-11-29 22:25       ` [U-Boot] [PATCH v10 03/28] bmips: bcm6348: " Álvaro Fernández Rojas
2018-11-29 22:25       ` [U-Boot] [PATCH v10 04/28] bmips: bcm6358: " Álvaro Fernández Rojas
2018-11-29 22:25       ` [U-Boot] [PATCH v10 05/28] bmips: bcm6368: " Álvaro Fernández Rojas
2018-11-29 22:25       ` [U-Boot] [PATCH v10 06/28] bmips: bcm6328: " Álvaro Fernández Rojas
2018-11-29 22:25       ` [U-Boot] [PATCH v10 07/28] bmips: bcm6362: " Álvaro Fernández Rojas
2018-11-29 22:25       ` [U-Boot] [PATCH v10 08/28] bmips: bcm63268: " Álvaro Fernández Rojas
2018-11-29 22:25       ` [U-Boot] [PATCH v10 09/28] bmips: bcm6318: " Álvaro Fernández Rojas
2018-11-29 22:25       ` [U-Boot] [PATCH v10 10/28] net: add support for bcm6348-enet Álvaro Fernández Rojas
2018-11-30 16:54         ` Daniel Schwierzeck
2018-11-29 22:25       ` [U-Boot] [PATCH v10 11/28] bmips: bcm6338: " Álvaro Fernández Rojas
2018-11-29 22:25       ` [U-Boot] [PATCH v10 12/28] bmips: enable f@st1704 enet support Álvaro Fernández Rojas
2018-11-29 22:25       ` [U-Boot] [PATCH v10 13/28] bmips: bcm6348: add support for bcm6348-enet Álvaro Fernández Rojas
2018-11-29 22:25       ` [U-Boot] [PATCH v10 14/28] bmips: enable ct-5361 enet support Álvaro Fernández Rojas
2018-11-29 22:25       ` [U-Boot] [PATCH v10 15/28] bmips: bcm6358: add support for bcm6348-enet Álvaro Fernández Rojas
2018-11-29 22:25       ` [U-Boot] [PATCH v10 16/28] bmips: enable hg556a enet support Álvaro Fernández Rojas
2018-11-29 22:25       ` [U-Boot] [PATCH v10 17/28] bmips: enable nb4-ser " Álvaro Fernández Rojas
2018-11-29 22:25       ` [U-Boot] [PATCH v10 18/28] net: add support for bcm6368-enet Álvaro Fernández Rojas
2018-11-30 16:58         ` Daniel Schwierzeck
2018-11-29 22:25       ` [U-Boot] [PATCH v10 19/28] bmips: bcm6368: " Álvaro Fernández Rojas
2018-11-29 22:25       ` [U-Boot] [PATCH v10 20/28] bmips: enable wap-5813n enet support Álvaro Fernández Rojas
2018-11-29 22:25       ` [U-Boot] [PATCH v10 21/28] bmips: bcm6328: add support for bcm6368-enet Álvaro Fernández Rojas
2018-11-29 22:25       ` [U-Boot] [PATCH v10 22/28] bmips: enable ar-5387un enet support Álvaro Fernández Rojas
2018-11-29 22:25       ` [U-Boot] [PATCH v10 23/28] bmips: bcm6362: add support for bcm6368-enet Álvaro Fernández Rojas
2018-11-29 22:25       ` [U-Boot] [PATCH v10 24/28] bmips: enable dgnd3700v2 enet support Álvaro Fernández Rojas
2018-11-29 22:25       ` [U-Boot] [PATCH v10 25/28] bmips: bcm63268: add support for bcm6368-enet Álvaro Fernández Rojas
2018-11-29 22:25       ` [U-Boot] [PATCH v10 26/28] bmips: enable vr-3032u enet support Álvaro Fernández Rojas
2018-11-29 22:25       ` [U-Boot] [PATCH v10 27/28] bmips: bcm6318: add support for bcm6368-enet Álvaro Fernández Rojas
2018-11-29 22:25       ` [U-Boot] [PATCH v10 28/28] bmips: enable ar-5315u enet support Álvaro Fernández Rojas
2018-12-01 18:00       ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 01/28] dma: add bcm6348-iudma support Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 02/28] bmips: bcm6338: " Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 03/28] bmips: bcm6348: " Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 04/28] bmips: bcm6358: " Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 05/28] bmips: bcm6368: " Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 06/28] bmips: bcm6328: " Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 07/28] bmips: bcm6362: " Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 08/28] bmips: bcm63268: " Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 09/28] bmips: bcm6318: " Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 10/28] net: add support for bcm6348-enet Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 11/28] bmips: bcm6338: " Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 12/28] bmips: enable f@st1704 enet support Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 13/28] bmips: bcm6348: add support for bcm6348-enet Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 14/28] bmips: enable ct-5361 enet support Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 15/28] bmips: bcm6358: add support for bcm6348-enet Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 16/28] bmips: enable hg556a enet support Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 17/28] bmips: enable nb4-ser " Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 18/28] net: add support for bcm6368-enet Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 19/28] bmips: bcm6368: " Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 20/28] bmips: enable wap-5813n enet support Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 21/28] bmips: bcm6328: add support for bcm6368-enet Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 22/28] bmips: enable ar-5387un enet support Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 23/28] bmips: bcm6362: add support for bcm6368-enet Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 24/28] bmips: enable dgnd3700v2 enet support Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 25/28] bmips: bcm63268: add support for bcm6368-enet Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 26/28] bmips: enable vr-3032u enet support Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 27/28] bmips: bcm6318: add support for bcm6368-enet Álvaro Fernández Rojas
2018-12-01 18:00         ` [U-Boot] [PATCH v11 28/28] bmips: enable ar-5315u enet support Álvaro Fernández Rojas
2018-12-10 15:36         ` [U-Boot] [PATCH v11 00/28] bmips: add iudma/enet support Daniel Schwierzeck

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.