Skip to contentSkip to conversation

bmips: add bcm6348-enet support

RFC New Álvaro Fernández Rojas 6 participants 106 messages Feb 12, 2018 – Mar 11, 2018

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

cover bmips: add bcm6348-enet support

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

This is an RFC, so please give you feedback on the things that I should fix or rework.

Álvaro Fernández Rojas (14):
dma: add dma channels support and improve uclass
dma: add bcm6348-iudma support
bmips: bcm6338: add bcm6348-iudma support
bmips: bcm6348: add bcm6348-iudma support
bmips: bcm6358: add bcm6348-iudma support
phy: add support for internal phys
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

 arch/mips/dts/brcm,bcm6338.dtsi       |  29 ++
 arch/mips/dts/brcm,bcm6348.dtsi       |  42 +++
 arch/mips/dts/brcm,bcm6358.dtsi       |  46 +++
 arch/mips/dts/comtrend,ct-5361.dts    |  12 +
 arch/mips/dts/huawei,hg556a.dts       |  12 +
 arch/mips/dts/sagem,f at st1704.dts      |  12 +
 arch/mips/dts/sfr,nb4-ser.dts         |  24 ++
 configs/comtrend_ct5361_ram_defconfig |   8 +-
 configs/huawei_hg556a_ram_defconfig   |   8 +-
 configs/sagem_f at st1704_ram_defconfig  |   9 +-
 configs/sfr_nb4-ser_ram_defconfig     |   8 +-
 drivers/dma/Kconfig                   |   8 +
 drivers/dma/Makefile                  |   1 +
 drivers/dma/bcm6348-iudma.c           | 498 ++++++++++++++++++++++++++++++++
 drivers/dma/dma-uclass.c              | 212 +++++++++++---
 drivers/mtd/spi/sf-uclass.c           |  17 ++
 drivers/mtd/spi/spi_flash.c           |  11 +-
 drivers/net/Kconfig                   |   9 +
 drivers/net/Makefile                  |   1 +
 drivers/net/bcm6348-eth.c             | 517 ++++++++++++++++++++++++++++++++++
 include/configs/bmips_common.h        |   5 +-
 include/dma-uclass.h                  | 110 ++++++++
 include/dma.h                         | 226 +++++++++++----
 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/phy.h                         |   2 +
 include/spi_flash.h                   |   3 +
 28 files changed, 1780 insertions(+), 99 deletions(-)
 create mode 100644 drivers/dma/bcm6348-iudma.c
 create mode 100644 drivers/net/bcm6348-eth.c
 create mode 100644 include/dma-uclass.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
Signature · 1 line
2.11.0
#1 lore raw

RFC 1/14 dma: add dma channels support and improve uclass

---
 drivers/dma/dma-uclass.c    | 212 ++++++++++++++++++++++++++++++++++-------
 drivers/mtd/spi/sf-uclass.c |  17 ++++
 drivers/mtd/spi/spi_flash.c |  11 ++-
 include/dma-uclass.h        | 110 +++++++++++++++++++++
 include/dma.h               | 226 +++++++++++++++++++++++++++++++++-----------
 include/spi_flash.h         |   3 +
 6 files changed, 485 insertions(+), 94 deletions(-)
 create mode 100644 include/dma-uclass.h
drivers/dma/dma-uclass.c +176 -36
index 3d0ce22fbc..7d04d98493 100644
@@ -1,59 +1,176 @@
 /*
- * Direct Memory Access U-Class driver
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ * Copyright (C) 2015 Texas Instruments Incorporated, <www.ti.com>
+ * Written by Mugunthan V N <[email protected]>
  *
- * (C) Copyright 2015
- *     Texas Instruments Incorporated, <www.ti.com>
- *
- * Author: Mugunthan V N <[email protected]>
- *
- * SPDX-License-Identifier:     GPL-2.0+
+ * SPDX-License-Identifier:	GPL-2.0+
  */
 
 #include <common.h>
-#include <dma.h>
 #include <dm.h>
-#include <dm/uclass-internal.h>
-#include <dm/device-internal.h>
+#include <dma.h>
+#include <dma-uclass.h>
+#include <dt-structs.h>
 #include <errno.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
-int dma_get_device(u32 transfer_type, struct udevice **devp)
+static inline struct dma_ops *dma_dev_ops(struct udevice *dev)
+{
+	return (struct dma_ops *)dev->driver->ops;
+}
+
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+# if CONFIG_IS_ENABLED(OF_PLATDATA)
+int dma_get_by_index_platdata(struct udevice *dev, int index,
+			      struct phandle_2_cell *cells, struct dma *dma)
 {
-	struct udevice *dev;
 	int ret;
 
-	for (ret = uclass_first_device(UCLASS_DMA, &dev); dev && !ret;
-	     ret = uclass_next_device(&dev)) {
-		struct dma_dev_priv *uc_priv;
+	if (index != 0)
+		return -ENOSYS;
+	ret = uclass_get_device(UCLASS_DMA, 0, &dma->dev);
+	if (ret)
+		return ret;
+	dma->id = cells[0].id;
 
-		uc_priv = dev_get_uclass_priv(dev);
-		if (uc_priv->supported & transfer_type)
-			break;
-	}
+	return 0;
+}
+# else
+static int dma_of_xlate_default(struct dma *dma,
+				struct fdtdec_phandle_args *args)
+{
+	debug("%s(dma=%p)\n", __func__, dma);
 
-	if (!dev) {
-		pr_err("No DMA device found that supports %x type\n",
-		      transfer_type);
-		return -EPROTONOSUPPORT;
+	if (args->args_count > 1) {
+		pr_err("Invaild args_count: %d\n", args->args_count);
+		return -EINVAL;
 	}
 
-	*devp = dev;
+	if (args->args_count)
+		dma->id = args->args[0];
+	else
+		dma->id = 0;
 
-	return ret;
+	return 0;
 }
 
-int dma_memcpy(void *dst, void *src, size_t len)
+int dma_get_by_index(struct udevice *dev, int index, struct dma *dma)
 {
-	struct udevice *dev;
-	const struct dma_ops *ops;
 	int ret;
+	struct fdtdec_phandle_args args;
+	struct udevice *dev_dma;
+	struct dma_ops *ops;
+
+	debug("%s(dev=%p, index=%d, dma=%p)\n", __func__, dev, index, dma);
 
-	ret = dma_get_device(DMA_SUPPORTS_MEM_TO_MEM, &dev);
-	if (ret < 0)
+	assert(dma);
+	ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev),
+					     "dmas", "#dma-cells", 0, index,
+					     &args);
+	if (ret) {
+		pr_err("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
+		      __func__, ret);
 		return ret;
+	}
+
+	ret = uclass_get_device_by_of_offset(UCLASS_DMA, args.node, &dev_dma);
+	if (ret) {
+		pr_err("%s: uclass_get_device_by_of_offset 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);
+}
+# endif /* OF_PLATDATA */
+
+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);
+
+	index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev),
+				      "dma-names", name);
+	if (index < 0) {
+		pr_err("fdt_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_memcpy(struct dma *dma, void *dst, void *src, size_t len)
+{
+	struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+	debug("%s(dma=%p)\n", __func__, dma);
 
-	ops = device_get_ops(dev);
 	if (!ops->transfer)
 		return -ENOSYS;
 
@@ -61,12 +178,35 @@ int dma_memcpy(void *dst, void *src, size_t len)
 	invalidate_dcache_range((unsigned long)dst, (unsigned long)dst +
 				roundup(len, ARCH_DMA_MINALIGN));
 
-	return ops->transfer(dev, DMA_MEM_TO_MEM, dst, src, len);
+	return ops->transfer(dma, DMA_MEM_TO_MEM, dst, src, len);
+}
+
+int dma_receive(struct dma *dma, void **dst)
+{
+	struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (!ops->receive)
+		return -1;
+
+	return ops->receive(dma, dst);
+}
+
+int dma_send(struct dma *dma, void *src, size_t len)
+{
+	struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (!ops->send)
+		return -1;
+
+	return ops->send(dma, src, len);
 }
 
 UCLASS_DRIVER(dma) = {
-	.id		= UCLASS_DMA,
-	.name		= "dma",
-	.flags		= DM_UC_FLAG_SEQ_ALIAS,
-	.per_device_auto_alloc_size = sizeof(struct dma_dev_priv),
+	.id = UCLASS_DMA,
+	.name = "dma",
+	.flags = DM_UC_FLAG_SEQ_ALIAS,
 };
drivers/mtd/spi/sf-uclass.c +17 -0
index 83876485fe..992dead1a2 100644
@@ -6,6 +6,7 @@
 
 #include <common.h>
 #include <dm.h>
+#include <dma.h>
 #include <spi.h>
 #include <spi_flash.h>
 #include <dm/device-internal.h>
@@ -72,6 +73,22 @@ int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs,
 		return ret;
 
 	*devp = slave->dev;
+
+#ifdef CONFIG_DMA
+	if (fdtdec_lookup_phandle(gd->fdt_blob, dev_of_offset(*devp),
+				  "dmas") > 0) {
+		struct spi_flash *priv = dev_get_uclass_priv(*devp);
+
+		priv->dma = calloc(1, sizeof(struct dma));
+		if (!priv->dma)
+			return -ENOMEM;
+
+		ret = dma_get_by_index(*devp, 0, priv->dma);
+		if (ret)
+			return -EINVAL;
+	}
+#endif
+
 	return 0;
 }
 
drivers/mtd/spi/spi_flash.c +6 -5
index 294d9f9d79..8b1c6a27de 100644
@@ -458,10 +458,6 @@ int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
  */
 void __weak spi_flash_copy_mmap(void *data, void *offset, size_t len)
 {
-#ifdef CONFIG_DMA
-	if (!dma_memcpy(data, offset, len))
-		return;
-#endif
 	memcpy(data, offset, len);
 }
 
@@ -482,7 +478,12 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
 			return ret;
 		}
 		spi_xfer(spi, 0, NULL, NULL, SPI_XFER_MMAP);
-		spi_flash_copy_mmap(data, flash->memory_map + offset, len);
+		if (flash->dma)
+			dma_memcpy(flash->dma, data,
+				   flash->memory_map + offset, len);
+		else
+			spi_flash_copy_mmap(data, flash->memory_map + offset,
+					    len);
 		spi_xfer(spi, 0, NULL, NULL, SPI_XFER_MMAP_END);
 		spi_release_bus(spi);
 		return 0;
include/dma-uclass.h new file +110 -0

110 lines not on this page · raw message

include/dma.h +173 -53

259 lines not on this page · raw message

include/spi_flash.h +3 -0
index f3c4e83424..f31e8b8145 100644
@@ -65,6 +65,9 @@ struct spi_flash {
 #ifdef CONFIG_DM_SPI_FLASH
 	struct udevice *dev;
 #endif
+#ifdef CONFIG_DMA
+	struct dma *dma;
+#endif
 	const char *name;
 	u8 dual_flash;
 	u8 shift;
Signature · 1 line
2.11.0
maintainer
#2 lore raw

RFC 1/14 dma: add dma channels support and improve uclass

Please add a commit message as this is a pretty big change providing a overview what is being added and why?

Quoted 3 lines · Álvaro Fernández Rojas
---
 drivers/dma/dma-uclass.c    | 212 ++++++++++++++++++++++++++++++++++-------

This patch definitely breaks drivers/dma/ti-edma3.c which implements current definition of dma-uclass.

One of the assumption of current dma_memcpy() implementation is that the client's DT node need not have "dmas" entry to specify which DMA provider and DMA channel to use for dma memcpy. (This is true in linux kernel as well). Most DMA HWs have general purpose channels that are not tied to any peripherals and can be used for mem to mem transfers. So, if the client device's DT node does not populate "dmas" property then dma_memcpy() API should try to find a DMA provider that supports memcpy operation, request a memcpy capable channel from the provider and use it to transfer data. Please keep the current behavior as is. Or, provide a API for clients to request such a channel.

Quoted 160 lines
 drivers/mtd/spi/sf-uclass.c |  17 ++++
 drivers/mtd/spi/spi_flash.c |  11 ++-
 include/dma-uclass.h        | 110 +++++++++++++++++++++
 include/dma.h               | 226 +++++++++++++++++++++++++++++++++-----------
 include/spi_flash.h         |   3 +
 6 files changed, 485 insertions(+), 94 deletions(-)
 create mode 100644 include/dma-uclass.h
drivers/dma/dma-uclass.c +93 -30
index 3d0ce22fbc..7d04d98493 100644
@@ -1,59 +1,176 @@
 /*
- * Direct Memory Access U-Class driver
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ * Copyright (C) 2015 Texas Instruments Incorporated, <www.ti.com>
+ * Written by Mugunthan V N <[email protected]>
  *
- * (C) Copyright 2015
- *     Texas Instruments Incorporated, <www.ti.com>
- *
- * Author: Mugunthan V N <[email protected]>
- *
- * SPDX-License-Identifier:     GPL-2.0+
+ * SPDX-License-Identifier:	GPL-2.0+
  */
 
 #include <common.h>
-#include <dma.h>
 #include <dm.h>
-#include <dm/uclass-internal.h>
-#include <dm/device-internal.h>
+#include <dma.h>
+#include <dma-uclass.h>
+#include <dt-structs.h>
 #include <errno.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
-int dma_get_device(u32 transfer_type, struct udevice **devp)
+static inline struct dma_ops *dma_dev_ops(struct udevice *dev)
+{
+	return (struct dma_ops *)dev->driver->ops;
+}
+
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+# if CONFIG_IS_ENABLED(OF_PLATDATA)
+int dma_get_by_index_platdata(struct udevice *dev, int index,
+			      struct phandle_2_cell *cells, struct dma *dma)
 {
-	struct udevice *dev;
 	int ret;
 
-	for (ret = uclass_first_device(UCLASS_DMA, &dev); dev && !ret;
-	     ret = uclass_next_device(&dev)) {
-		struct dma_dev_priv *uc_priv;
+	if (index != 0)
+		return -ENOSYS;
+	ret = uclass_get_device(UCLASS_DMA, 0, &dma->dev);
+	if (ret)
+		return ret;
+	dma->id = cells[0].id;
 
-		uc_priv = dev_get_uclass_priv(dev);
-		if (uc_priv->supported & transfer_type)
-			break;
-	}
+	return 0;
+}
+# else
+static int dma_of_xlate_default(struct dma *dma,
+				struct fdtdec_phandle_args *args)
+{
+	debug("%s(dma=%p)\n", __func__, dma);
 
-	if (!dev) {
-		pr_err("No DMA device found that supports %x type\n",
-		      transfer_type);
-		return -EPROTONOSUPPORT;
+	if (args->args_count > 1) {
+		pr_err("Invaild args_count: %d\n", args->args_count);
+		return -EINVAL;
 	}
 
-	*devp = dev;
+	if (args->args_count)
+		dma->id = args->args[0];
+	else
+		dma->id = 0;
 
-	return ret;
+	return 0;
 }
 
-int dma_memcpy(void *dst, void *src, size_t len)
+int dma_get_by_index(struct udevice *dev, int index, struct dma *dma)
 {
-	struct udevice *dev;
-	const struct dma_ops *ops;
 	int ret;
+	struct fdtdec_phandle_args args;
+	struct udevice *dev_dma;
+	struct dma_ops *ops;
+
+	debug("%s(dev=%p, index=%d, dma=%p)\n", __func__, dev, index, dma);
 
-	ret = dma_get_device(DMA_SUPPORTS_MEM_TO_MEM, &dev);
-	if (ret < 0)
+	assert(dma);
+	ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev),
+					     "dmas", "#dma-cells", 0, index,
+					     &args);
+	if (ret) {
+		pr_err("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
+		      __func__, ret);
 		return ret;
+	}
+
+	ret = uclass_get_device_by_of_offset(UCLASS_DMA, args.node, &dev_dma);
+	if (ret) {
+		pr_err("%s: uclass_get_device_by_of_offset 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);
+}
+# endif /* OF_PLATDATA */
+
+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);
+
+	index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev),
+				      "dma-names", name);
+	if (index < 0) {
+		pr_err("fdt_stringlist_search() failed: %d\n", index);
+		return index;
+	}
+
+	return dma_get_by_index(dev, index, dma);
+}
+#endif /* OF_CONTROL */
+

drivers/dma/dma-uclass.c line 127

Quoted 10 lines
drivers/dma/dma-uclass.c +10 -0
+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 0? I guess you meant to return -ENOSYS or something.

drivers/dma/dma-uclass.c line 140

Quoted 13 lines
drivers/dma/dma-uclass.c +13 -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;
+

Same as above

Quoted 43 lines
drivers/dma/dma-uclass.c +33 -2
+	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_memcpy(struct dma *dma, void *dst, void *src, size_t len)
+{
+	struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+	debug("%s(dma=%p)\n", __func__, dma);
 
-	ops = device_get_ops(dev);
 	if (!ops->transfer)
 		return -ENOSYS;
 
@@ -61,12 +178,35 @@ int dma_memcpy(void *dst, void *src, size_t len)
 	invalidate_dcache_range((unsigned long)dst, (unsigned long)dst +
 				roundup(len, ARCH_DMA_MINALIGN));
 
-	return ops->transfer(dev, DMA_MEM_TO_MEM, dst, src, len);
+	return ops->transfer(dma, DMA_MEM_TO_MEM, dst, src, len);

drivers/dma/dma-uclass.c int dma_memcpy(void *dst, void *src, size_t len) · line 191

Quoted 10 lines
drivers/dma/dma-uclass.c +10 -0
+}
+
+int dma_receive(struct dma *dma, void **dst)
+{
+	struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (!ops->receive)
+		return -1;

-ENOSYS?

drivers/dma/dma-uclass.c int dma_memcpy(void *dst, void *src, size_t len) · line 203

Quoted 12 lines
drivers/dma/dma-uclass.c +12 -0
+
+	return ops->receive(dma, dst);
+}
+
+int dma_send(struct dma *dma, void *src, size_t len)
+{
+	struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (!ops->send)
+		return -1;

-ENOSYS?

Quoted 180 lines
drivers/dma/dma-uclass.c +5 -4
+
+	return ops->send(dma, src, len);
 }
 
 UCLASS_DRIVER(dma) = {
-	.id		= UCLASS_DMA,
-	.name		= "dma",
-	.flags		= DM_UC_FLAG_SEQ_ALIAS,
-	.per_device_auto_alloc_size = sizeof(struct dma_dev_priv),
+	.id = UCLASS_DMA,
+	.name = "dma",
+	.flags = DM_UC_FLAG_SEQ_ALIAS,
 };
drivers/mtd/spi/sf-uclass.c +17 -0
index 83876485fe..992dead1a2 100644
@@ -6,6 +6,7 @@
 
 #include <common.h>
 #include <dm.h>
+#include <dma.h>
 #include <spi.h>
 #include <spi_flash.h>
 #include <dm/device-internal.h>
@@ -72,6 +73,22 @@ int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs,
 		return ret;
 
 	*devp = slave->dev;
+
+#ifdef CONFIG_DMA
+	if (fdtdec_lookup_phandle(gd->fdt_blob, dev_of_offset(*devp),
+				  "dmas") > 0) {
+		struct spi_flash *priv = dev_get_uclass_priv(*devp);
+
+		priv->dma = calloc(1, sizeof(struct dma));
+		if (!priv->dma)
+			return -ENOMEM;
+
+		ret = dma_get_by_index(*devp, 0, priv->dma);
+		if (ret)
+			return -EINVAL;
+	}
+#endif
+
 	return 0;
 }
 
drivers/mtd/spi/spi_flash.c +6 -5
index 294d9f9d79..8b1c6a27de 100644
@@ -458,10 +458,6 @@ int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
  */
 void __weak spi_flash_copy_mmap(void *data, void *offset, size_t len)
 {
-#ifdef CONFIG_DMA
-	if (!dma_memcpy(data, offset, len))
-		return;
-#endif
 	memcpy(data, offset, len);
 }
 
@@ -482,7 +478,12 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
 			return ret;
 		}
 		spi_xfer(spi, 0, NULL, NULL, SPI_XFER_MMAP);
-		spi_flash_copy_mmap(data, flash->memory_map + offset, len);
+		if (flash->dma)
+			dma_memcpy(flash->dma, data,
+				   flash->memory_map + offset, len);
+		else
+			spi_flash_copy_mmap(data, flash->memory_map + offset,
+					    len);
 		spi_xfer(spi, 0, NULL, NULL, SPI_XFER_MMAP_END);
 		spi_release_bus(spi);
 		return 0;
include/dma-uclass.h new file +97 -0
new file mode 100644
index 0000000000..0315e54441
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ * Copyright (C) 2015 Texas Instruments Incorporated, <www.ti.com>
+ * Written by Mugunthan V N <[email protected]>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _DMA_UCLASS_H
+#define _DMA_UCLASS_H
+
+/* See dma.h for background documentation. */
+
+#include <dma.h>
+#include <fdtdec.h>
+
+/**
+ * struct dma_ops - The functions that a DMA driver must implement.
+ */
+struct dma_ops {
+	/**
+	 * 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 fdtdec_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);
+	/**
+	 * transfer() - Issue a DMA transfer.
+	 *
+	 * @dma: The DMA Channel to manipulate.
+	 * @dir: The direction of data transfer.
+	 * @dst: The destination pointer.
+	 * @src: The source pointer.
+	 * @len: Length of the data to be copied.
+	 * @return zero on success, or -ve error code.
+	 */
+	int (*transfer)(struct dma *dma, enum dma_transfer_direction dir,
+			void *dst, void *src, size_t len);
+	/**
+	 * receive() - Receive a DMA transfer.
+	 *
+	 * @dma: The DMA Channel to manipulate.
+	 * @dst: The destination pointer.
+	 * @return zero on success, or -ve error code.
+	 */
+	int (*receive)(struct dma *dma, void **dst);

include/dma-uclass.h line 107

Quoted 10 lines
include/dma-uclass.h new file +10 -0
+	/**
+	 * send() - Send a DMA transfer.
+	 *
+	 * @dma: The DMA Channel to manipulate.
+	 * @src: The source pointer.
+	 * @len: Length of the data to be copied.
+	 * @return zero on success, or -ve error code.
+	 */
+	int (*send)(struct dma *dma, void *src, size_t len);
+

I wonder why separate send()/receive() is needed. Isn't transfer() alone sufficient with appropriate direction flags? If its very specific to networking use case then, please explain that more clearly as to why this interface is provided in the comments (especially receive() interface that does not pass length).

Regards
Vignesh

Quoted 282 lines
include/dma-uclass.h new file +3 -0
+};
+
+#endif /* _DMA_UCLASS_H */
include/dma.h +173 -53
index 71fa77f2ea..3632e3256d 100644
@@ -1,86 +1,206 @@
 /*
- * (C) Copyright 2015
- *     Texas Instruments Incorporated, <www.ti.com>
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ * Copyright (C) 2015 Texas Instruments Incorporated, <www.ti.com>
+ * Written by Mugunthan V N <[email protected]>
  *
- * SPDX-License-Identifier:     GPL-2.0+
+ * SPDX-License-Identifier:	GPL-2.0+
  */
 
 #ifndef _DMA_H_
 #define _DMA_H_
 
+#include <linux/errno.h>
+#include <linux/types.h>
+
 /*
- * enum dma_direction - dma transfer direction indicator
+ * enum dma_transfer_direction - dma transfer direction indicator
  * @DMA_MEM_TO_MEM: Memcpy mode
  * @DMA_MEM_TO_DEV: From Memory to Device
  * @DMA_DEV_TO_MEM: From Device to Memory
  * @DMA_DEV_TO_DEV: From Device to Device
  */
-enum dma_direction {
+enum dma_transfer_direction {
 	DMA_MEM_TO_MEM,
 	DMA_MEM_TO_DEV,
 	DMA_DEV_TO_MEM,
 	DMA_DEV_TO_DEV,
 };
 
-#define DMA_SUPPORTS_MEM_TO_MEM	BIT(0)
-#define DMA_SUPPORTS_MEM_TO_DEV	BIT(1)
-#define DMA_SUPPORTS_DEV_TO_MEM	BIT(2)
-#define DMA_SUPPORTS_DEV_TO_DEV	BIT(3)
+/**
+ * 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.
+ */
 
-/*
- * struct dma_ops - Driver model DMA operations
+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.
  *
- * The uclass interface is implemented by all DMA devices which use
- * driver model.
+ * @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_ops {
+struct dma {
+	struct udevice *dev;
 	/*
-	 * 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
+	 * Written by of_xlate. We assume a single id is enough for now. In the
+	 * future, we might add more fields here.
 	 */
-	int (*transfer)(struct udevice *dev, int direction, void *dst,
-			void *src, size_t len);
+	unsigned long id;
 };
 
-/*
- * struct dma_dev_priv - information about a device used by the uclass
+#if CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(DMA)
+struct phandle_2_cell;
+int dma_get_by_index_platdata(struct udevice *dev, int index,
+			      struct phandle_2_cell *cells, struct dma *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.
  *
- * @supported: mode of transfers that DMA can support, should be
- *	       one/multiple of DMA_SUPPORTS_*
+ * @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.
  */
-struct dma_dev_priv {
-	u32 supported;
-};
+int dma_get_by_index(struct udevice *dev, int index, struct dma *dma);
 
-/*
- * dma_get_device - get a DMA device which supports transfer
- * type of transfer_type
- *
- * @transfer_type - transfer type should be one/multiple of
- *		    DMA_SUPPORTS_*
- * @devp - udevice pointer to return the found device
- * @return - will return on success and devp will hold the
- *	     pointer to the device
+/**
+ * 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_device(u32 transfer_type, struct udevice **devp);
+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;
+}
 
-/*
- * dma_memcpy - try to use DMA to do a mem copy which will be
- *		much faster than CPU mem copy
- *
- * @dst - destination pointer
- * @src - souce pointer
- * @len - data length to be copied
- * @return - on successful transfer returns no of bytes
-	     transferred and on failure return error code.
+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_memcpy() - Try to use DMA to do a mem copy which will be much faster
+ *		  than CPU mem copy.
+ *
+ * @dma: A DMA struct that was previously successfully requested by
+ *	 dma_request/get_by_*().
+ * @dst: The destination pointer.
+ * @src: The source pointer.
+ * @len: Length of the data to be copied.
+ * @return zero on success, or -ve error code.
+ */
+int dma_memcpy(struct dma *dma, void *dst, void *src, size_t len);
+
+/**
+ * dma_receive() - Receive a DMA transfer.
+ *
+ * @dma: A DMA struct that was previously successfully requested by
+ *	 dma_request/get_by_*().
+ * @dst: The destination pointer.
+ * @return zero on success, or -ve error code.
+ */
+int dma_receive(struct dma *dma, void **dst);
+
+/**
+ * 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 copied.
+ * @return zero on success, or -ve error code.
  */
-int dma_memcpy(void *dst, void *src, size_t len);
+int dma_send(struct dma *dma, void *src, size_t len);
 
-#endif	/* _DMA_H_ */
+#endif /* _DMA_H_ */
include/spi_flash.h +3 -0
index f3c4e83424..f31e8b8145 100644
@@ -65,6 +65,9 @@ struct spi_flash {
 #ifdef CONFIG_DM_SPI_FLASH
 	struct udevice *dev;
 #endif
+#ifdef CONFIG_DMA
+	struct dma *dma;
+#endif
 	const char *name;
 	u8 dual_flash;
 	u8 shift;
Signature · 2 lines
Regards
Vignesh
#3 lore raw

RFC 2/14 dma: add bcm6348-iudma support

In reply to Álvaro Fernández Rojas
---
 drivers/dma/Kconfig         |   8 +
 drivers/dma/Makefile        |   1 +
 drivers/dma/bcm6348-iudma.c | 498 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 507 insertions(+)
 create mode 100644 drivers/dma/bcm6348-iudma.c
drivers/dma/Kconfig +8 -0
index 1b92c7789d..f58323f6c0 100644
@@ -12,6 +12,14 @@ config DMA
 	  buses that is used to transfer data to and from memory.
 	  The uclass interface is defined in include/dma.h.
 
+config BCM6348_IUDMA
+	bool "BCM6348 IUDMA driver"
+	depends on ARCH_BMIPS
+	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
drivers/dma/Makefile +1 -0
index 39b78b2a3d..b2b4147349 100644
@@ -9,6 +9,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_TI_KSNAV) += keystone_nav.o keystone_nav_cfg.o
 obj-$(CONFIG_TI_EDMA3) += ti-edma3.o
drivers/dma/bcm6348-iudma.c new file +498 -0

498 lines not on this page · raw message

Signature · 1 line
2.11.0
#4 lore raw

RFC 3/14 bmips: bcm6338: add bcm6348-iudma support

In reply to Álvaro Fernández Rojas
---
 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
arch/mips/dts/brcm,bcm6338.dtsi +14 -0
index 0cab44cb8d..4125f71d9f 100644
@@ -5,6 +5,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"
@@ -131,5 +132,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>;
+		};
 	};
 };
include/dt-bindings/dma/bcm6338-dma.h new file +15 -0
new file mode 100644
index 0000000000..5dd66239b4
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ *
+ * 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 */
Signature · 1 line
2.11.0
#5 lore raw

RFC 4/14 bmips: bcm6348: add bcm6348-iudma support

In reply to Álvaro Fernández Rojas
---
 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
arch/mips/dts/brcm,bcm6348.dtsi +16 -0
index 92fb91afc1..d774c59665 100644
@@ -5,6 +5,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"
@@ -160,5 +161,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>;
+		};
 	};
 };
include/dt-bindings/dma/bcm6348-dma.h new file +17 -0
new file mode 100644
index 0000000000..a1d3a6456d
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ *
+ * 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 */
Signature · 1 line
2.11.0
#6 lore raw

RFC 5/14 bmips: bcm6358: add bcm6348-iudma support

In reply to Álvaro Fernández Rojas
---
 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
arch/mips/dts/brcm,bcm6358.dtsi +18 -0
index b63b53baee..1468e4f63a 100644
@@ -5,6 +5,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"
@@ -191,5 +192,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>;
+		};
 	};
 };
include/dt-bindings/dma/bcm6358-dma.h new file +17 -0
new file mode 100644
index 0000000000..3b1fcf8540
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ *
+ * 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 */
Signature · 1 line
2.11.0
#7 lore raw

RFC 6/14 phy: add support for internal phys

In reply to Álvaro Fernández Rojas
---
 include/phy.h | 2 ++
 1 file changed, 2 insertions(+)
include/phy.h +2 -0
index 0543ec10c2..8f3e53db01 100644
@@ -50,6 +50,7 @@
 
 
 typedef enum {
+	PHY_INTERFACE_MODE_INTERNAL,
 	PHY_INTERFACE_MODE_MII,
 	PHY_INTERFACE_MODE_GMII,
 	PHY_INTERFACE_MODE_SGMII,
@@ -72,6 +73,7 @@ typedef enum {
 } phy_interface_t;
 
 static const char *phy_interface_strings[] = {
+	[PHY_INTERFACE_MODE_INTERNAL]		= "internal",
 	[PHY_INTERFACE_MODE_MII]		= "mii",
 	[PHY_INTERFACE_MODE_GMII]		= "gmii",
 	[PHY_INTERFACE_MODE_SGMII]		= "sgmii",
Signature · 1 line
2.11.0
#8 lore raw

RFC 7/14 net: add support for bcm6348-enet

In reply to Álvaro Fernández Rojas
---
 drivers/net/Kconfig            |   9 +
 drivers/net/Makefile           |   1 +
 drivers/net/bcm6348-eth.c      | 517 +++++++++++++++++++++++++++++++++++++++++
 include/configs/bmips_common.h |   5 +-
 4 files changed, 531 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/bcm6348-eth.c
drivers/net/Kconfig +9 -0
index de1947ccc1..12a231cc99 100644
@@ -71,6 +71,15 @@ 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 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
drivers/net/Makefile +1 -0
index ac5443c752..282adbc775 100644
@@ -8,6 +8,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
drivers/net/bcm6348-eth.c new file +517 -0

517 lines not on this page · raw message

include/configs/bmips_common.h +4 -1
index 38bf7a272b..eb66512f67 100644
@@ -7,6 +7,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 }
@@ -17,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
 
Signature · 1 line
2.11.0
#9 lore raw

RFC 8/14 bmips: bcm6338: add support for bcm6348-enet

In reply to Álvaro Fernández Rojas
---
 arch/mips/dts/brcm,bcm6338.dtsi | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
arch/mips/dts/brcm,bcm6338.dtsi +15 -0
index 4125f71d9f..621278c9d1 100644
@@ -145,5 +145,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";
+		};
 	};
 };
Signature · 1 line
2.11.0
#10 lore raw

RFC 9/14 bmips: enable f@st1704 enet support

In reply to Álvaro Fernández Rojas
---
 arch/mips/dts/sagem,f at st1704.dts     | 12 ++++++++++++
 configs/sagem_f at st1704_ram_defconfig |  9 ++++++++-
 2 files changed, 20 insertions(+), 1 deletion(-)
arch/mips/dts/sagem,f at st1704.dts +12 -0
index dd0e5b8b7c..99d031f10a 100644
@@ -40,6 +40,18 @@
 	};
 };
 
+&enet {
+	status = "okay";
+	phy = <&enetphy>;
+	phy-mode = "mii";
+
+	enetphy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio {
 	status = "okay";
 };
configs/sagem_f at st1704_ram_defconfig +8 -1
index 0adcd46d51..1a640781b7 100644
@@ -28,11 +28,15 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
-# CONFIG_CMD_NET is not set
+CONFIG_CMD_DHCP=y
 # CONFIG_CMD_NFS is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
+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
@@ -41,6 +45,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
Signature · 1 line
2.11.0
#11 lore raw

RFC 10/14 bmips: bcm6348: add support for bcm6348-enet

In reply to Álvaro Fernández Rojas
---
 arch/mips/dts/brcm,bcm6348.dtsi | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
arch/mips/dts/brcm,bcm6348.dtsi +26 -0
index d774c59665..e540865019 100644
@@ -162,6 +162,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>,
Signature · 1 line
2.11.0
#12 lore raw

RFC 11/14 bmips: enable ct-5361 enet support

In reply to Álvaro Fernández Rojas
---
 arch/mips/dts/comtrend,ct-5361.dts    | 12 ++++++++++++
 configs/comtrend_ct5361_ram_defconfig |  8 +++++++-
 2 files changed, 19 insertions(+), 1 deletion(-)
arch/mips/dts/comtrend,ct-5361.dts +12 -0
index 74dc09046c..a78aa877fc 100644
@@ -35,6 +35,18 @@
 	};
 };
 
+&enet1 {
+	status = "okay";
+	phy = <&enet1phy>;
+	phy-mode = "mii";
+
+	enet1phy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
configs/comtrend_ct5361_ram_defconfig +7 -1
index 8b842606f5..0737772dd2 100644
@@ -26,11 +26,14 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FPGA is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
-# CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
+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
@@ -38,6 +41,9 @@ CONFIG_LED_GPIO=y
 CONFIG_MTD=y
 CONFIG_MTD_NOR_FLASH=y
 CONFIG_CFI_FLASH=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
Signature · 1 line
2.11.0
#13 lore raw

RFC 12/14 bmips: bcm6358: add support for bcm6348-enet

In reply to Álvaro Fernández Rojas
---
 arch/mips/dts/brcm,bcm6358.dtsi | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)
arch/mips/dts/brcm,bcm6358.dtsi +28 -0
index 1468e4f63a..04329864c2 100644
@@ -193,6 +193,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>,
Signature · 1 line
2.11.0
#14 lore raw

RFC 13/14 bmips: enable hg556a enet support

In reply to Álvaro Fernández Rojas
---
 arch/mips/dts/huawei,hg556a.dts     | 12 ++++++++++++
 configs/huawei_hg556a_ram_defconfig |  8 +++++++-
 2 files changed, 19 insertions(+), 1 deletion(-)
arch/mips/dts/huawei,hg556a.dts +12 -0
index a1e9c15ab9..2f99e0905c 100644
@@ -94,6 +94,18 @@
 	status = "okay";
 };
 
+&enet1 {
+	status = "okay";
+	phy = <&enet1phy>;
+	phy-mode = "mii";
+
+	enet1phy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
configs/huawei_hg556a_ram_defconfig +7 -1
index 7f7f34ed61..c7c7c6554f 100644
@@ -26,11 +26,14 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FPGA is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
-# CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
+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
@@ -38,6 +41,9 @@ CONFIG_LED_GPIO=y
 CONFIG_MTD=y
 CONFIG_MTD_NOR_FLASH=y
 CONFIG_CFI_FLASH=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
Signature · 1 line
2.11.0
#15 lore raw

RFC 14/14 bmips: enable nb4-ser enet support

In reply to Álvaro Fernández Rojas
---
 arch/mips/dts/sfr,nb4-ser.dts     | 24 ++++++++++++++++++++++++
 configs/sfr_nb4-ser_ram_defconfig |  8 +++++++-
 2 files changed, 31 insertions(+), 1 deletion(-)
arch/mips/dts/sfr,nb4-ser.dts +24 -0
index 473372faa1..73db45f9ea 100644
@@ -54,6 +54,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";
 };
configs/sfr_nb4-ser_ram_defconfig +7 -1
index fc323d879d..07b49a1a77 100644
@@ -27,11 +27,14 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FPGA is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
-# CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
+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_LED_GPIO=y
 CONFIG_MTD=y
 CONFIG_MTD_NOR_FLASH=y
 CONFIG_CFI_FLASH=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
Signature · 1 line
2.11.0
#16 lore raw

cover bmips: add bcm6348-enet support

In reply to Álvaro Fernández Rojas

No comments about DMA?

2018-02-12 17:38 GMT+01:00 Álvaro Fernández Rojas <[email protected]>:

Quoted 66 lines

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

This is an RFC, so please give you feedback on the things that I should fix or rework.

Álvaro Fernández Rojas (14):
dma: add dma channels support and improve uclass
dma: add bcm6348-iudma support
bmips: bcm6338: add bcm6348-iudma support
bmips: bcm6348: add bcm6348-iudma support
bmips: bcm6358: add bcm6348-iudma support
phy: add support for internal phys
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

 arch/mips/dts/brcm,bcm6338.dtsi       |  29 ++
 arch/mips/dts/brcm,bcm6348.dtsi       |  42 +++
 arch/mips/dts/brcm,bcm6358.dtsi       |  46 +++
 arch/mips/dts/comtrend,ct-5361.dts    |  12 +
 arch/mips/dts/huawei,hg556a.dts       |  12 +
 arch/mips/dts/sagem,f at st1704.dts      |  12 +
 arch/mips/dts/sfr,nb4-ser.dts         |  24 ++
 configs/comtrend_ct5361_ram_defconfig |   8 +-
 configs/huawei_hg556a_ram_defconfig   |   8 +-
 configs/sagem_f at st1704_ram_defconfig  |   9 +-
 configs/sfr_nb4-ser_ram_defconfig     |   8 +-
 drivers/dma/Kconfig                   |   8 +
 drivers/dma/Makefile                  |   1 +
 drivers/dma/bcm6348-iudma.c           | 498 ++++++++++++++++++++++++++++++
++
 drivers/dma/dma-uclass.c              | 212 +++++++++++---
 drivers/mtd/spi/sf-uclass.c           |  17 ++
 drivers/mtd/spi/spi_flash.c           |  11 +-
 drivers/net/Kconfig                   |   9 +
 drivers/net/Makefile                  |   1 +
 drivers/net/bcm6348-eth.c             | 517 ++++++++++++++++++++++++++++++
++++
 include/configs/bmips_common.h        |   5 +-
 include/dma-uclass.h                  | 110 ++++++++
 include/dma.h                         | 226 +++++++++++----
 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/phy.h                         |   2 +
 include/spi_flash.h                   |   3 +
 28 files changed, 1780 insertions(+), 99 deletions(-)
 create mode 100644 drivers/dma/bcm6348-iudma.c
 create mode 100644 drivers/net/bcm6348-eth.c
 create mode 100644 include/dma-uclass.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

--
2.11.0

#17 lore raw

v2 cover bmips: add bcm6348-enet support

In reply to Á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...).

This is a RFC, so please give you feedback on the things that I should fix or rework.

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.

Álvaro Fernández Rojas (15):
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
phy: add support for internal phys
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

 arch/mips/dts/brcm,bcm6338.dtsi       |  29 ++
 arch/mips/dts/brcm,bcm6348.dtsi       |  42 +++
 arch/mips/dts/brcm,bcm6358.dtsi       |  46 +++
 arch/mips/dts/comtrend,ct-5361.dts    |  12 +
 arch/mips/dts/huawei,hg556a.dts       |  12 +
 arch/mips/dts/sagem,f at st1704.dts      |  12 +
 arch/mips/dts/sfr,nb4-ser.dts         |  24 ++
 configs/comtrend_ct5361_ram_defconfig |   8 +-
 configs/huawei_hg556a_ram_defconfig   |   8 +-
 configs/sagem_f at st1704_ram_defconfig  |   9 +-
 configs/sfr_nb4-ser_ram_defconfig     |   8 +-
 drivers/dma/Kconfig                   |  16 ++
 drivers/dma/Makefile                  |   1 +
 drivers/dma/bcm6348-iudma.c           | 505 +++++++++++++++++++++++++++++++++
 drivers/dma/dma-uclass.c              | 180 +++++++++++-
 drivers/net/Kconfig                   |  10 +
 drivers/net/Makefile                  |   1 +
 drivers/net/bcm6348-eth.c             | 517 ++++++++++++++++++++++++++++++++++
 include/configs/bmips_common.h        |   5 +-
 include/dma-uclass.h                  | 115 ++++++++
 include/dma.h                         | 191 +++++++++++--
 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/phy.h                         |   2 +
 25 files changed, 1774 insertions(+), 28 deletions(-)
 create mode 100644 drivers/dma/bcm6348-iudma.c
 create mode 100644 drivers/net/bcm6348-eth.c
 create mode 100644 include/dma-uclass.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
Signature · 1 line
2.11.0
#18 lore raw

RFC v2 1/15 dma: move dma_ops to dma-uclass.h

Move dma_ops to a separate header file, following other uclass implementations.

---
 drivers/dma/dma-uclass.c |  3 ++-
 include/dma-uclass.h     | 38 ++++++++++++++++++++++++++++++++++++++
 include/dma.h            | 22 ----------------------
 3 files changed, 40 insertions(+), 23 deletions(-)
 create mode 100644 include/dma-uclass.h
drivers/dma/dma-uclass.c +2 -1
index 3d0ce22fbc..6fd4e1b35d 100644
@@ -10,10 +10,11 @@
  */
 
 #include <common.h>
-#include <dma.h>
 #include <dm.h>
 #include <dm/uclass-internal.h>
 #include <dm/device-internal.h>
+#include <dma.h>
+#include <dma-uclass.h>
 #include <errno.h>
 
 DECLARE_GLOBAL_DATA_PTR;
include/dma-uclass.h new file +38 -0
new file mode 100644
index 0000000000..e29ad103f2
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ * Copyright (C) 2015 Texas Instruments Incorporated, <www.ti.com>
+ * Written by Mugunthan V N <[email protected]>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#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 {
+	/*
+	 * 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);
+};
+
+#endif /* _DMA_UCLASS_H */
include/dma.h +0 -22
index 71fa77f2ea..89320f10d9 100644
@@ -28,28 +28,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
Signature · 1 line
2.11.0
#19 lore raw

RFC v2 1/15 dma: move dma_ops to dma-uclass.h

Hi Alvaro,

Quoted 47 lines · Álvaro Fernández Rojas

Move dma_ops to a separate header file, following other uclass implementations.

---
 drivers/dma/dma-uclass.c |  3 ++-
 include/dma-uclass.h     | 38 ++++++++++++++++++++++++++++++++++++++
 include/dma.h            | 22 ----------------------
 3 files changed, 40 insertions(+), 23 deletions(-)
 create mode 100644 include/dma-uclass.h
drivers/dma/dma-uclass.c +2 -1
index 3d0ce22fbc..6fd4e1b35d 100644
@@ -10,10 +10,11 @@
  */
 
 #include <common.h>
-#include <dma.h>
 #include <dm.h>
 #include <dm/uclass-internal.h>
 #include <dm/device-internal.h>
+#include <dma.h>
+#include <dma-uclass.h>
 #include <errno.h>
 
 DECLARE_GLOBAL_DATA_PTR;
include/dma-uclass.h new file +14 -0
new file mode 100644
index 0000000000..e29ad103f2
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ * Copyright (C) 2015 Texas Instruments Incorporated, <www.ti.com>
+ * Written by Mugunthan V N <[email protected]>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _DMA_UCLASS_H
+#define _DMA_UCLASS_H
+
+/* See dma.h for background documentation. */
+
+#include <dma.h>

include/dma-uclass.h line 24

Quoted 10 lines
include/dma-uclass.h new file +10 -0
+
+/*
+ * 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

Is this the correct purpose for the transfer() method?

include/dma-uclass.h line 31

Quoted 7 lines
include/dma-uclass.h new file +7 -0
+        *
+        * @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.

Is this the number of bytes

What does this function actually do? Does it queue a transfer which completes later? How do I check if it is done?

Please add a lot more docs here.

Quoted 41 lines
include/dma-uclass.h new file +7 -0
+        * @return: 0 if OK, -ve on error
+        */
+       int (*transfer)(struct udevice *dev, int direction, void *dst,
+                       void *src, size_t len);
+};
+
+#endif /* _DMA_UCLASS_H */
include/dma.h +0 -23
index 71fa77f2ea..89320f10d9 100644
@@ -28,28 +28,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
--
Quoted 2 lines

2.11.0

Regards,
Simon

#20 lore raw

RFC v2 1/15 dma: move dma_ops to dma-uclass.h

Hi Simon,

Quoted 53 lines · Simon Glass

Hi Alvaro,

Quoted 50 lines · Álvaro Fernández Rojas

Move dma_ops to a separate header file, following other uclass implementations.

---
  drivers/dma/dma-uclass.c |  3 ++-
  include/dma-uclass.h     | 38 ++++++++++++++++++++++++++++++++++++++
  include/dma.h            | 22 ----------------------
  3 files changed, 40 insertions(+), 23 deletions(-)

create mode 100644 include/dma-uclass.h

drivers/dma/dma-uclass.c +2 -1
index 3d0ce22fbc..6fd4e1b35d 100644
@@ -10,10 +10,11 @@
   */
 
  #include <common.h>
-#include <dma.h>
  #include <dm.h>
  #include <dm/uclass-internal.h>
  #include <dm/device-internal.h>
+#include <dma.h>
+#include <dma-uclass.h>
  #include <errno.h>
 
  DECLARE_GLOBAL_DATA_PTR;
include/dma-uclass.h new file +17 -0
new file mode 100644
index 0000000000..e29ad103f2
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ * Copyright (C) 2015 Texas Instruments Incorporated, <www.ti.com>
+ * Written by Mugunthan V N <[email protected]>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _DMA_UCLASS_H
+#define _DMA_UCLASS_H
+
+/* See dma.h for background documentation. */
+
+#include <dma.h>
+
+/*
+ * struct dma_ops - Driver model DMA operations
Quoted 8 lines

include/dma-uclass.h line 24

Quoted 7 lines
include/dma-uclass.h new file +7 -0
+ *
+ * The uclass interface is implemented by all DMA devices which use
+ * driver model.
+ */
+struct dma_ops {
+       /*
+        * Get the current timer count

Is this the correct purpose for the transfer() method?

This is just a copy&paste, that's what you can find in upstream dma.h ;D Anyway, I will fix that.

Quoted 7 lines

include/dma-uclass.h line 31

Quoted 7 lines
include/dma-uclass.h new file +7 -0
+        *
+        * @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.
Quoted 6 lines

Is this the number of bytes

What does this function actually do? Does it queue a transfer which completes later? How do I check if it is done?

Please add a lot more docs here.

Same as above.

Quoted 38 lines
Quoted 38 lines
include/dma-uclass.h new file +7 -0
+        * @return: 0 if OK, -ve on error
+        */
+       int (*transfer)(struct udevice *dev, int direction, void *dst,
+                       void *src, size_t len);
+};
+
+#endif /* _DMA_UCLASS_H */
include/dma.h +0 -22
index 71fa77f2ea..89320f10d9 100644
@@ -28,28 +28,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);
-};
-
-/*
Quoted 8 lines
Quoted 6 lines
include/dma.h +0 -1
   * 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

Regards,
Simon

Regards,
Álvaro.

#21 lore raw

RFC v2 2/15 dma: add channels support

In reply to Álvaro Fernández Rojas

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

---
v2: Introduce changes reported by Vignesh:
- Respect current dma implementation.
- Let dma_memcpy find a compatible dma device.

 drivers/dma/Kconfig      |   7 ++
 drivers/dma/dma-uclass.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++
 include/dma-uclass.h     |  77 +++++++++++++++++++++
 include/dma.h            | 169 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 430 insertions(+)
drivers/dma/Kconfig +7 -0
index 1b92c7789d..21b2c0dcaa 100644
@@ -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
drivers/dma/dma-uclass.c +177 -0

187 lines not on this page · raw message

include/dma-uclass.h +77 -0

89 lines not on this page · raw message

include/dma.h +169 -0

181 lines not on this page · raw message

Signature · 1 line
2.11.0
#22 lore raw

RFC v2 2/15 dma: add channels support

Hi Alvaro,

Quoted 90 lines · Álvaro Fernández Rojas

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

---
v2: Introduce changes reported by Vignesh:
- Respect current dma implementation.
- Let dma_memcpy find a compatible dma device.

 drivers/dma/Kconfig      |   7 ++
 drivers/dma/dma-uclass.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++
 include/dma-uclass.h     |  77 +++++++++++++++++++++
 include/dma.h            | 169 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 430 insertions(+)
drivers/dma/Kconfig +7 -0
index 1b92c7789d..21b2c0dcaa 100644
@@ -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
drivers/dma/dma-uclass.c +45 -0
index 6fd4e1b35d..a16c3a786c 100644
@@ -15,10 +15,187 @@
 #include <dm/device-internal.h>
 #include <dma.h>
 #include <dma-uclass.h>
+#include <dt-structs.h>
 #include <errno.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#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)
+#  if CONFIG_IS_ENABLED(OF_PLATDATA)
+int dma_get_by_index_platdata(struct udevice *dev, int index,
+                             struct phandle_2_cell *cells, struct dma *dma)
+{
+       int ret;
+
+       if (index != 0)
+               return -ENOSYS;
+       ret = uclass_get_device(UCLASS_DMA, 0, &dma->dev);
+       if (ret)
+               return ret;
+       dma->id = cells[0].id;
+
+       return 0;
+}
+#  else
+static int dma_of_xlate_default(struct dma *dma,
+                               struct fdtdec_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;

drivers/dma/dma-uclass.c line 76

Quoted 10 lines
drivers/dma/dma-uclass.c +10 -0
+       struct fdtdec_phandle_args args;
+       struct udevice *dev_dma;
+       struct dma_ops *ops;
+
+       debug("%s(dev=%p, index=%d, dma=%p)\n", __func__, dev, index, dma);
+
+       assert(dma);
+       ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev),
+                                            "dmas", "#dma-cells", 0, index,
+                                            &args);

Can you please use the livetree API? E.g. see dev_read_phandle_with_args()

Also please move this into an ofdata_to_platdata function rather than doing it each time this function is called.

Quoted 28 lines
drivers/dma/dma-uclass.c +28 -0
+       if (ret) {
+               pr_err("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
+                     __func__, ret);
+               return ret;
+       }
+
+       ret = uclass_get_device_by_of_offset(UCLASS_DMA, args.node, &dev_dma);
+       if (ret) {
+               pr_err("%s: uclass_get_device_by_of_offset 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);
+}

drivers/dma/dma-uclass.c line 114

Quoted 10 lines
drivers/dma/dma-uclass.c +10 -0
+#  endif /* OF_PLATDATA */
+
+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);
+
+       index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev),
+                                     "dma-names", name);

dev_read...

Quoted 114 lines
drivers/dma/dma-uclass.c +84 -0
+       if (index < 0) {
+               pr_err("fdt_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_receive(struct dma *dma, void **dst)
+{
+       struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+       debug("%s(dma=%p)\n", __func__, dma);
+
+       if (!ops->receive)
+               return -1;
+
+       return ops->receive(dma, dst);
+}
+
+int dma_send(struct dma *dma, void *src, size_t len)
+{
+       struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+       debug("%s(dma=%p)\n", __func__, dma);
+
+       if (!ops->send)
+               return -1;
+
+       return ops->send(dma, src, len);
+}
+#endif /* CONFIG_DMA_CHANNELS */
+
 int dma_get_device(u32 transfer_type, struct udevice **devp)
 {
        struct udevice *dev;
include/dma-uclass.h +12 -0
index e29ad103f2..5faec69207 100644
@@ -12,6 +12,7 @@
 /* See dma.h for background documentation. */
 
 #include <dma.h>
+#include <fdtdec.h>
 
 /*
  * struct dma_ops - Driver model DMA operations
@@ -20,6 +21,82 @@
  * 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.
+        *

include/dma-uclass.h line 44

Quoted 10 lines
include/dma-uclass.h +10 -0
+        * 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 fdtdec_phandle_args *args);

Use new livetree struct here

Regards,
Simon

#23 lore raw

RFC v2 2/15 dma: add channels support

Hi Simon,

Quoted 105 lines · Simon Glass

Hi Alvaro,

Quoted 90 lines · Álvaro Fernández Rojas

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

---
v2: Introduce changes reported by Vignesh:
- Respect current dma implementation.
- Let dma_memcpy find a compatible dma device.

  drivers/dma/Kconfig      |   7 ++
  drivers/dma/dma-uclass.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++
  include/dma-uclass.h     |  77 +++++++++++++++++++++
  include/dma.h            | 169 ++++++++++++++++++++++++++++++++++++++++++++
  4 files changed, 430 insertions(+)
drivers/dma/Kconfig +7 -0
index 1b92c7789d..21b2c0dcaa 100644
@@ -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
drivers/dma/dma-uclass.c +45 -0
index 6fd4e1b35d..a16c3a786c 100644
@@ -15,10 +15,187 @@
  #include <dm/device-internal.h>
  #include <dma.h>
  #include <dma-uclass.h>
+#include <dt-structs.h>
  #include <errno.h>
 
  DECLARE_GLOBAL_DATA_PTR;
 
+#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)
+#  if CONFIG_IS_ENABLED(OF_PLATDATA)
+int dma_get_by_index_platdata(struct udevice *dev, int index,
+                             struct phandle_2_cell *cells, struct dma *dma)
+{
+       int ret;
+
+       if (index != 0)
+               return -ENOSYS;
+       ret = uclass_get_device(UCLASS_DMA, 0, &dma->dev);
+       if (ret)
+               return ret;
+       dma->id = cells[0].id;
+
+       return 0;
+}
+#  else
+static int dma_of_xlate_default(struct dma *dma,
+                               struct fdtdec_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;

drivers/dma/dma-uclass.c line 76

Quoted 10 lines
drivers/dma/dma-uclass.c +10 -0
+       struct fdtdec_phandle_args args;
+       struct udevice *dev_dma;
+       struct dma_ops *ops;
+
+       debug("%s(dev=%p, index=%d, dma=%p)\n", __func__, dev, index, dma);
+
+       assert(dma);
+       ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev),
+                                            "dmas", "#dma-cells", 0, index,
+                                            &args);

Can you please use the livetree API? E.g. see dev_read_phandle_with_args()

Quoted 2 lines

Also please move this into an ofdata_to_platdata function rather than doing it each time this function is called.

Ok, I did this some time ago and I used an older version of clk-uclass as a starting point.
I will switch to livetree in the next patch version.

Quoted 32 lines
Quoted 32 lines
drivers/dma/dma-uclass.c +31 -0
+       if (ret) {
+               pr_err("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
+                     __func__, ret);
+               return ret;
+       }
+
+       ret = uclass_get_device_by_of_offset(UCLASS_DMA, args.node, &dev_dma);
+       if (ret) {
+               pr_err("%s: uclass_get_device_by_of_offset 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);
+}
+#  endif /* OF_PLATDATA */
+
+int dma_get_by_name(struct udevice *dev, const char *name, struct dma *dma)
Quoted 8 lines

drivers/dma/dma-uclass.c line 114

Quoted 7 lines
drivers/dma/dma-uclass.c +7 -0
+{
+       int index;
+
+       debug("%s(dev=%p, name=%s, dma=%p)\n", __func__, dev, name, dma);
+
+       index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev),
+                                     "dma-names", name);

dev_read...

Ok.

Quoted 118 lines
Quoted 118 lines
drivers/dma/dma-uclass.c +84 -0
+       if (index < 0) {
+               pr_err("fdt_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_receive(struct dma *dma, void **dst)
+{
+       struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+       debug("%s(dma=%p)\n", __func__, dma);
+
+       if (!ops->receive)
+               return -1;
+
+       return ops->receive(dma, dst);
+}
+
+int dma_send(struct dma *dma, void *src, size_t len)
+{
+       struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+       debug("%s(dma=%p)\n", __func__, dma);
+
+       if (!ops->send)
+               return -1;
+
+       return ops->send(dma, src, len);
+}
+#endif /* CONFIG_DMA_CHANNELS */
+
  int dma_get_device(u32 transfer_type, struct udevice **devp)
  {
         struct udevice *dev;
include/dma-uclass.h +15 -0
index e29ad103f2..5faec69207 100644
@@ -12,6 +12,7 @@
  /* See dma.h for background documentation. */
 
  #include <dma.h>
+#include <fdtdec.h>
 
  /*
   * struct dma_ops - Driver model DMA operations
@@ -20,6 +21,82 @@
   * 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.
Quoted 8 lines

include/dma-uclass.h line 44

Quoted 7 lines
include/dma-uclass.h +7 -0
+        *
+        * @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 fdtdec_phandle_args *args);

Use new livetree struct here

Ok.

Quoted 3 lines

Regards,
Simon

Regards,
Álvaro.

#24 lore raw

RFC v2 2/15 dma: add channels support

In reply to Simon Glass

Hi Simon,

Quoted 105 lines · Simon Glass

Hi Alvaro,

Quoted 90 lines · Álvaro Fernández Rojas

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

---
v2: Introduce changes reported by Vignesh:
- Respect current dma implementation.
- Let dma_memcpy find a compatible dma device.

  drivers/dma/Kconfig      |   7 ++
  drivers/dma/dma-uclass.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++
  include/dma-uclass.h     |  77 +++++++++++++++++++++
  include/dma.h            | 169 ++++++++++++++++++++++++++++++++++++++++++++
  4 files changed, 430 insertions(+)
drivers/dma/Kconfig +7 -0
index 1b92c7789d..21b2c0dcaa 100644
@@ -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
drivers/dma/dma-uclass.c +45 -0
index 6fd4e1b35d..a16c3a786c 100644
@@ -15,10 +15,187 @@
  #include <dm/device-internal.h>
  #include <dma.h>
  #include <dma-uclass.h>
+#include <dt-structs.h>
  #include <errno.h>
 
  DECLARE_GLOBAL_DATA_PTR;
 
+#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)
+#  if CONFIG_IS_ENABLED(OF_PLATDATA)
+int dma_get_by_index_platdata(struct udevice *dev, int index,
+                             struct phandle_2_cell *cells, struct dma *dma)
+{
+       int ret;
+
+       if (index != 0)
+               return -ENOSYS;
+       ret = uclass_get_device(UCLASS_DMA, 0, &dma->dev);
+       if (ret)
+               return ret;
+       dma->id = cells[0].id;
+
+       return 0;
+}
+#  else
+static int dma_of_xlate_default(struct dma *dma,
+                               struct fdtdec_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;

drivers/dma/dma-uclass.c line 76

Quoted 10 lines
drivers/dma/dma-uclass.c +10 -0
+       struct fdtdec_phandle_args args;
+       struct udevice *dev_dma;
+       struct dma_ops *ops;
+
+       debug("%s(dev=%p, index=%d, dma=%p)\n", __func__, dev, index, dma);
+
+       assert(dma);
+       ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev),
+                                            "dmas", "#dma-cells", 0, index,
+                                            &args);

Can you please use the livetree API? E.g. see dev_read_phandle_with_args()

Quoted 2 lines

Also please move this into an ofdata_to_platdata function rather than doing it each time this function is called.

I don't really get what you mean by moving this into an ofdata_to_platdata function.
This code is copied from other uclasses:
https://github.com/Noltari/u-boot/blob/master/drivers/clk/clk-uclass.c#L71
https://github.com/Noltari/u-boot/blob/master/drivers/power/domain/power-domain-uclass.c#L43
https://github.com/Noltari/u-boot/blob/master/drivers/reset/reset-uclass.c#L47

Quoted 167 lines
Quoted 29 lines
drivers/dma/dma-uclass.c +28 -0
+       if (ret) {
+               pr_err("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
+                     __func__, ret);
+               return ret;
+       }
+
+       ret = uclass_get_device_by_of_offset(UCLASS_DMA, args.node, &dev_dma);
+       if (ret) {
+               pr_err("%s: uclass_get_device_by_of_offset 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);
+}

drivers/dma/dma-uclass.c line 114

Quoted 10 lines
drivers/dma/dma-uclass.c +10 -0
+#  endif /* OF_PLATDATA */
+
+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);
+
+       index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev),
+                                     "dma-names", name);

dev_read...

Quoted 114 lines
drivers/dma/dma-uclass.c +84 -0
+       if (index < 0) {
+               pr_err("fdt_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_receive(struct dma *dma, void **dst)
+{
+       struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+       debug("%s(dma=%p)\n", __func__, dma);
+
+       if (!ops->receive)
+               return -1;
+
+       return ops->receive(dma, dst);
+}
+
+int dma_send(struct dma *dma, void *src, size_t len)
+{
+       struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+       debug("%s(dma=%p)\n", __func__, dma);
+
+       if (!ops->send)
+               return -1;
+
+       return ops->send(dma, src, len);
+}
+#endif /* CONFIG_DMA_CHANNELS */
+
  int dma_get_device(u32 transfer_type, struct udevice **devp)
  {
         struct udevice *dev;
include/dma-uclass.h +12 -0
index e29ad103f2..5faec69207 100644
@@ -12,6 +12,7 @@
  /* See dma.h for background documentation. */
 
  #include <dma.h>
+#include <fdtdec.h>
 
  /*
   * struct dma_ops - Driver model DMA operations
@@ -20,6 +21,82 @@
   * 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.
+        *

include/dma-uclass.h line 44

Quoted 10 lines
include/dma-uclass.h +10 -0
+        * 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 fdtdec_phandle_args *args);

Use new livetree struct here

Quoted 2 lines

Regards,
Simon

Regards,
Álvaro.

#25 lore raw

RFC v2 3/15 dma: add bcm6348-iudma support

In reply to Álvaro Fernández Rojas

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

---
v2: Fix dma rx burst config and select DMA_CHANNELS.

 drivers/dma/Kconfig         |   9 +
 drivers/dma/Makefile        |   1 +
 drivers/dma/bcm6348-iudma.c | 505 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 515 insertions(+)
 create mode 100644 drivers/dma/bcm6348-iudma.c
drivers/dma/Kconfig +9 -0
index 21b2c0dcaa..9afa158b51 100644
@@ -19,6 +19,15 @@ config DMA_CHANNELS
 	  Enable channels support for DMA. Some DMA controllers have multiple
 	  channels which can either transfer data to/from different devices.
 
+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
drivers/dma/Makefile +1 -0
index 39b78b2a3d..b2b4147349 100644
@@ -9,6 +9,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_TI_KSNAV) += keystone_nav.o keystone_nav_cfg.o
 obj-$(CONFIG_TI_EDMA3) += ti-edma3.o
drivers/dma/bcm6348-iudma.c new file +505 -0

505 lines not on this page · raw message

Signature · 1 line
2.11.0
#26 lore raw

RFC v2 4/15 bmips: bcm6338: add bcm6348-iudma support

In reply to Álvaro Fernández Rojas

---
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
arch/mips/dts/brcm,bcm6338.dtsi +14 -0
index 0cab44cb8d..4125f71d9f 100644
@@ -5,6 +5,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"
@@ -131,5 +132,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>;
+		};
 	};
 };
include/dt-bindings/dma/bcm6338-dma.h new file +15 -0
new file mode 100644
index 0000000000..5dd66239b4
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ *
+ * 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 */
Signature · 1 line
2.11.0
#27 lore raw

RFC v2 5/15 bmips: bcm6348: add bcm6348-iudma support

In reply to Álvaro Fernández Rojas

---
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
arch/mips/dts/brcm,bcm6348.dtsi +16 -0
index 92fb91afc1..d774c59665 100644
@@ -5,6 +5,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"
@@ -160,5 +161,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>;
+		};
 	};
 };
include/dt-bindings/dma/bcm6348-dma.h new file +17 -0
new file mode 100644
index 0000000000..a1d3a6456d
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ *
+ * 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 */
Signature · 1 line
2.11.0
#28 lore raw

RFC v2 6/15 bmips: bcm6358: add bcm6348-iudma support

In reply to Álvaro Fernández Rojas

---
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
arch/mips/dts/brcm,bcm6358.dtsi +18 -0
index b63b53baee..1468e4f63a 100644
@@ -5,6 +5,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"
@@ -191,5 +192,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>;
+		};
 	};
 };
include/dt-bindings/dma/bcm6358-dma.h new file +17 -0
new file mode 100644
index 0000000000..3b1fcf8540
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ *
+ * 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 */
Signature · 1 line
2.11.0
#29 lore raw

RFC v2 7/15 phy: add support for internal phys

In reply to Álvaro Fernández Rojas

---
v2: no changes

 include/phy.h | 2 ++
 1 file changed, 2 insertions(+)
include/phy.h +2 -0
index 0543ec10c2..8f3e53db01 100644
@@ -50,6 +50,7 @@
 
 
 typedef enum {
+	PHY_INTERFACE_MODE_INTERNAL,
 	PHY_INTERFACE_MODE_MII,
 	PHY_INTERFACE_MODE_GMII,
 	PHY_INTERFACE_MODE_SGMII,
@@ -72,6 +73,7 @@ typedef enum {
 } phy_interface_t;
 
 static const char *phy_interface_strings[] = {
+	[PHY_INTERFACE_MODE_INTERNAL]		= "internal",
 	[PHY_INTERFACE_MODE_MII]		= "mii",
 	[PHY_INTERFACE_MODE_GMII]		= "gmii",
 	[PHY_INTERFACE_MODE_SGMII]		= "sgmii",
Signature · 1 line
2.11.0
#30 lore raw

RFC v2 8/15 net: add support for bcm6348-enet

In reply to Álvaro Fernández Rojas

---
v2: select DMA_CHANNELS.

 drivers/net/Kconfig            |  10 +
 drivers/net/Makefile           |   1 +
 drivers/net/bcm6348-eth.c      | 517 +++++++++++++++++++++++++++++++++++++++++
 include/configs/bmips_common.h |   5 +-
 4 files changed, 532 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/bcm6348-eth.c
drivers/net/Kconfig +10 -0
index de1947ccc1..e532332d78 100644
@@ -71,6 +71,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
drivers/net/Makefile +1 -0
index ac5443c752..282adbc775 100644
@@ -8,6 +8,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
drivers/net/bcm6348-eth.c new file +517 -0

517 lines not on this page · raw message

include/configs/bmips_common.h +4 -1
index 38bf7a272b..eb66512f67 100644
@@ -7,6 +7,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 }
@@ -17,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
 
Signature · 1 line
2.11.0
#31 lore raw

RFC v2 9/15 bmips: bcm6338: add support for bcm6348-enet

In reply to Álvaro Fernández Rojas

---
v2: no changes

 arch/mips/dts/brcm,bcm6338.dtsi | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
arch/mips/dts/brcm,bcm6338.dtsi +15 -0
index 4125f71d9f..621278c9d1 100644
@@ -145,5 +145,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";
+		};
 	};
 };
Signature · 1 line
2.11.0
#32 lore raw

RFC v2 10/15 bmips: enable f@st1704 enet support

In reply to Álvaro Fernández Rojas

---
v2: no changes

 arch/mips/dts/sagem,f at st1704.dts     | 12 ++++++++++++
 configs/sagem_f at st1704_ram_defconfig |  9 ++++++++-
 2 files changed, 20 insertions(+), 1 deletion(-)
arch/mips/dts/sagem,f at st1704.dts +12 -0
index dd0e5b8b7c..99d031f10a 100644
@@ -40,6 +40,18 @@
 	};
 };
 
+&enet {
+	status = "okay";
+	phy = <&enetphy>;
+	phy-mode = "mii";
+
+	enetphy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio {
 	status = "okay";
 };
configs/sagem_f at st1704_ram_defconfig +8 -1
index 0adcd46d51..1a640781b7 100644
@@ -28,11 +28,15 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
-# CONFIG_CMD_NET is not set
+CONFIG_CMD_DHCP=y
 # CONFIG_CMD_NFS is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
+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
@@ -41,6 +45,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
Signature · 1 line
2.11.0
#33 lore raw

RFC v2 11/15 bmips: bcm6348: add support for bcm6348-enet

In reply to Álvaro Fernández Rojas

---
v2: no changes

 arch/mips/dts/brcm,bcm6348.dtsi | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
arch/mips/dts/brcm,bcm6348.dtsi +26 -0
index d774c59665..e540865019 100644
@@ -162,6 +162,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>,
Signature · 1 line
2.11.0
#34 lore raw

RFC v2 12/15 bmips: enable ct-5361 enet support

In reply to Álvaro Fernández Rojas

---
v2: no changes

 arch/mips/dts/comtrend,ct-5361.dts    | 12 ++++++++++++
 configs/comtrend_ct5361_ram_defconfig |  8 +++++++-
 2 files changed, 19 insertions(+), 1 deletion(-)
arch/mips/dts/comtrend,ct-5361.dts +12 -0
index 74dc09046c..a78aa877fc 100644
@@ -35,6 +35,18 @@
 	};
 };
 
+&enet1 {
+	status = "okay";
+	phy = <&enet1phy>;
+	phy-mode = "mii";
+
+	enet1phy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
configs/comtrend_ct5361_ram_defconfig +7 -1
index 8b842606f5..0737772dd2 100644
@@ -26,11 +26,14 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FPGA is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
-# CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
+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
@@ -38,6 +41,9 @@ CONFIG_LED_GPIO=y
 CONFIG_MTD=y
 CONFIG_MTD_NOR_FLASH=y
 CONFIG_CFI_FLASH=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
Signature · 1 line
2.11.0
#35 lore raw

RFC v2 13/15 bmips: bcm6358: add support for bcm6348-enet

In reply to Álvaro Fernández Rojas

---
v2: no changes

 arch/mips/dts/brcm,bcm6358.dtsi | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)
arch/mips/dts/brcm,bcm6358.dtsi +28 -0
index 1468e4f63a..04329864c2 100644
@@ -193,6 +193,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>,
Signature · 1 line
2.11.0
#36 lore raw

RFC v2 14/15 bmips: enable hg556a enet support

In reply to Álvaro Fernández Rojas

---
v2: no changes

 arch/mips/dts/huawei,hg556a.dts     | 12 ++++++++++++
 configs/huawei_hg556a_ram_defconfig |  8 +++++++-
 2 files changed, 19 insertions(+), 1 deletion(-)
arch/mips/dts/huawei,hg556a.dts +12 -0
index a1e9c15ab9..2f99e0905c 100644
@@ -94,6 +94,18 @@
 	status = "okay";
 };
 
+&enet1 {
+	status = "okay";
+	phy = <&enet1phy>;
+	phy-mode = "mii";
+
+	enet1phy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
configs/huawei_hg556a_ram_defconfig +7 -1
index 7f7f34ed61..c7c7c6554f 100644
@@ -26,11 +26,14 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FPGA is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
-# CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
+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
@@ -38,6 +41,9 @@ CONFIG_LED_GPIO=y
 CONFIG_MTD=y
 CONFIG_MTD_NOR_FLASH=y
 CONFIG_CFI_FLASH=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
Signature · 1 line
2.11.0
#37 lore raw

RFC v2 15/15 bmips: enable nb4-ser enet support

In reply to Álvaro Fernández Rojas

---
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(-)
arch/mips/dts/sfr,nb4-ser.dts +24 -0
index 473372faa1..73db45f9ea 100644
@@ -54,6 +54,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";
 };
configs/sfr_nb4-ser_ram_defconfig +7 -1
index fc323d879d..07b49a1a77 100644
@@ -27,11 +27,14 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FPGA is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
-# CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
+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_LED_GPIO=y
 CONFIG_MTD=y
 CONFIG_MTD_NOR_FLASH=y
 CONFIG_CFI_FLASH=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
Signature · 1 line
2.11.0
#38 lore raw

v3 cover bmips: add bcm6348-enet support

In reply to Á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...).

This is a RFC, so please give you feedback on the things that I should fix or rework.

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.

Álvaro Fernández Rojas (15):
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
phy: add support for internal phys
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

 arch/mips/dts/brcm,bcm6338.dtsi       |  29 ++
 arch/mips/dts/brcm,bcm6348.dtsi       |  42 +++
 arch/mips/dts/brcm,bcm6358.dtsi       |  46 +++
 arch/mips/dts/comtrend,ct-5361.dts    |  12 +
 arch/mips/dts/huawei,hg556a.dts       |  12 +
 arch/mips/dts/sagem,f at st1704.dts      |  12 +
 arch/mips/dts/sfr,nb4-ser.dts         |  24 ++
 configs/comtrend_ct5361_ram_defconfig |   8 +-
 configs/huawei_hg556a_ram_defconfig   |   8 +-
 configs/sagem_f at st1704_ram_defconfig  |   9 +-
 configs/sfr_nb4-ser_ram_defconfig     |   8 +-
 drivers/dma/Kconfig                   |  16 ++
 drivers/dma/Makefile                  |   1 +
 drivers/dma/bcm6348-iudma.c           | 505 +++++++++++++++++++++++++++++++++
 drivers/dma/dma-uclass.c              | 191 ++++++++++++-
 drivers/net/Kconfig                   |  10 +
 drivers/net/Makefile                  |   1 +
 drivers/net/bcm6348-eth.c             | 517 ++++++++++++++++++++++++++++++++++
 include/configs/bmips_common.h        |   5 +-
 include/dma-uclass.h                  | 117 ++++++++
 include/dma.h                         | 196 +++++++++++--
 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/phy.h                         |   2 +
 25 files changed, 1784 insertions(+), 36 deletions(-)
 create mode 100644 drivers/dma/bcm6348-iudma.c
 create mode 100644 drivers/net/bcm6348-eth.c
 create mode 100644 include/dma-uclass.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
Signature · 1 line
2.11.0
#39 lore raw

RFC v3 1/15 dma: move dma_ops to dma-uclass.h

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

---
v3: Introduce changes reported by Simon Glass:
- Improve dma-uclass.h documentation.
- Switch to live tree API.

 drivers/dma/dma-uclass.c |  3 ++-
 include/dma-uclass.h     | 39 +++++++++++++++++++++++++++++++++++++++
 include/dma.h            | 22 ----------------------
 3 files changed, 41 insertions(+), 23 deletions(-)
 create mode 100644 include/dma-uclass.h
drivers/dma/dma-uclass.c +2 -1
index 3d0ce22fbc..6fd4e1b35d 100644
@@ -10,10 +10,11 @@
  */
 
 #include <common.h>
-#include <dma.h>
 #include <dm.h>
 #include <dm/uclass-internal.h>
 #include <dm/device-internal.h>
+#include <dma.h>
+#include <dma-uclass.h>
 #include <errno.h>
 
 DECLARE_GLOBAL_DATA_PTR;
include/dma-uclass.h new file +39 -0
new file mode 100644
index 0000000000..abf750a5ce
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ * Copyright (C) 2015 Texas Instruments Incorporated <www.ti.com>
+ * Written by Mugunthan V N <[email protected]>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#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 */
include/dma.h +0 -22
index 71fa77f2ea..89320f10d9 100644
@@ -28,28 +28,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
Signature · 1 line
2.11.0
#40 lore raw

RFC v3 1/15 dma: move dma_ops to dma-uclass.h

Quoted 9 lines · Álvaro Fernández Rojas

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

---
v3: Introduce changes reported by Simon Glass:
- Improve dma-uclass.h documentation.
- Switch to live tree API.

Quoted 5 lines
 drivers/dma/dma-uclass.c |  3 ++-
 include/dma-uclass.h     | 39 +++++++++++++++++++++++++++++++++++++++
 include/dma.h            | 22 ----------------------
 3 files changed, 41 insertions(+), 23 deletions(-)
 create mode 100644 include/dma-uclass.h
#41 lore raw

RFC v3 1/15 dma: move dma_ops to dma-uclass.h

Quoted 10 lines · Simon Glass
Quoted 9 lines · Álvaro Fernández Rojas

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

---
v3: Introduce changes reported by Simon Glass:
- Improve dma-uclass.h documentation.
- Switch to live tree API.

Quoted 7 lines
Quoted 5 lines
  drivers/dma/dma-uclass.c |  3 ++-
  include/dma-uclass.h     | 39 +++++++++++++++++++++++++++++++++++++++
  include/dma.h            | 22 ----------------------
  3 files changed, 41 insertions(+), 23 deletions(-)

create mode 100644 include/dma-uclass.h

this patch will break build of existing DMA drivers, as the do not have #include <dma-uclass.h>.

drivers/dma/ti-edma3.c:563:21: error: variable 'ti_edma3_ops' has initializer but incomplete type

 static const struct dma_ops ti_edma3_ops = {
                     ^~~~~~~

drivers/dma/ti-edma3.c:564:2: error: unknown field 'transfer' specified in initializer
.transfer = ti_edma3_transfer,
^
drivers/dma/ti-edma3.c:564:14: warning: excess elements in struct initializer
.transfer = ti_edma3_transfer,

              ^~~~~~~~~~~~~~~~~
drivers/dma/ti-edma3.c:564:14: note: (near initialization for 'ti_edma3_ops')
drivers/dma/ti-edma3.c:563:29: error: storage size of 'ti_edma3_ops' isn't known
 static const struct dma_ops ti_edma3_ops = {
                             ^~~~~~~~~~~~

make[1]: *** [drivers/dma/ti-edma3.o] Error 1

Signature · 2 lines
regards,
-grygorii
#42 lore raw

RFC v3 1/15 dma: move dma_ops to dma-uclass.h

Hi Grygorii,

Thanks for reporting that, it should be fixed on v5.

Regards,

Álvaro.

Quoted 37 lines · Grygorii Strashko
Quoted 10 lines · Simon Glass
Quoted 9 lines · Álvaro Fernández Rojas

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

---
v3: Introduce changes reported by Simon Glass:
- Improve dma-uclass.h documentation.
- Switch to live tree API.

Quoted 6 lines
Quoted 5 lines
   drivers/dma/dma-uclass.c |  3 ++-
   include/dma-uclass.h     | 39 +++++++++++++++++++++++++++++++++++++++
   include/dma.h            | 22 ----------------------
   3 files changed, 41 insertions(+), 23 deletions(-)

create mode 100644 include/dma-uclass.h

this patch will break build of existing DMA drivers, as the do not have #include <dma-uclass.h>.

drivers/dma/ti-edma3.c:563:21: error: variable 'ti_edma3_ops' has initializer but incomplete type

  static const struct dma_ops ti_edma3_ops = {
                      ^~~~~~~

drivers/dma/ti-edma3.c:564:2: error: unknown field 'transfer' specified in initializer
.transfer = ti_edma3_transfer,
^
drivers/dma/ti-edma3.c:564:14: warning: excess elements in struct initializer
.transfer = ti_edma3_transfer,

               ^~~~~~~~~~~~~~~~~
drivers/dma/ti-edma3.c:564:14: note: (near initialization for 'ti_edma3_ops')
drivers/dma/ti-edma3.c:563:29: error: storage size of 'ti_edma3_ops' isn't known
  static const struct dma_ops ti_edma3_ops = {
                              ^~~~~~~~~~~~

make[1]: *** [drivers/dma/ti-edma3.o] Error 1

#43 lore raw

RFC v3 2/15 dma: add channels support

In reply to Álvaro Fernández Rojas

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

---
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 | 188 +++++++++++++++++++++++++++++++++++++++++++++--
 include/dma-uclass.h     |  78 ++++++++++++++++++++
 include/dma.h            | 174 ++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 439 insertions(+), 8 deletions(-)
drivers/dma/Kconfig +7 -0
index 1b92c7789d..21b2c0dcaa 100644
@@ -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
drivers/dma/dma-uclass.c +182 -6

206 lines not on this page · raw message

include/dma-uclass.h +78 -0

90 lines not on this page · raw message

include/dma.h +172 -2

190 lines not on this page · raw message

Signature · 1 line
2.11.0
#44 lore raw

RFC v3 2/15 dma: add channels support

Quoted 9 lines · Álvaro Fernández Rojas

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

---
v3: Introduce changes reported by Simon Glass:
- Improve dma-uclass.h documentation.
- Switch to live tree API.

Quoted 6 lines
 drivers/dma/Kconfig      |   7 ++
 drivers/dma/dma-uclass.c | 188 +++++++++++++++++++++++++++++++++++++++++++++--
 include/dma-uclass.h     |  78 ++++++++++++++++++++
 include/dma.h            | 174 ++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 439 insertions(+), 8 deletions(-)

Re moving the code into ofdata_to_platdata(), I suppose what you have here is OK.

Regards,
Simon

#45 lore raw

RFC v3 3/15 dma: add bcm6348-iudma support

In reply to Álvaro Fernández Rojas

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

---
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 | 505 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 515 insertions(+)
 create mode 100644 drivers/dma/bcm6348-iudma.c
drivers/dma/Kconfig +9 -0
index 21b2c0dcaa..9afa158b51 100644
@@ -19,6 +19,15 @@ config DMA_CHANNELS
 	  Enable channels support for DMA. Some DMA controllers have multiple
 	  channels which can either transfer data to/from different devices.
 
+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
drivers/dma/Makefile +1 -0
index 39b78b2a3d..b2b4147349 100644
@@ -9,6 +9,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_TI_KSNAV) += keystone_nav.o keystone_nav_cfg.o
 obj-$(CONFIG_TI_EDMA3) += ti-edma3.o
drivers/dma/bcm6348-iudma.c new file +505 -0

505 lines not on this page · raw message

Signature · 1 line
2.11.0
#46 lore raw

RFC v3 3/15 dma: add bcm6348-iudma support

Hi

I'd appreciated if you can clarify few points below.

Quoted 13 lines · Álvaro Fernández Rojas

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

---
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 | 505 ++++++++++++++++++++++++++++++++++++++++++++
  3 files changed, 515 insertions(+)

create mode 100644 drivers/dma/bcm6348-iudma.c

[...]

Quoted 5 lines
drivers/dma/bcm6348-iudma.c new file +4 -0
+static int bcm6348_iudma_enable(struct dma *dma)
+{
+	struct bcm6348_iudma_priv *priv = dev_get_priv(dma->dev);
+	struct bcm6348_chan_priv *ch_priv = priv->ch_priv[dma->id];

drivers/dma/bcm6348-iudma.c line 200

Quoted 10 lines
drivers/dma/bcm6348-iudma.c new file +10 -0
+	struct bcm6348_dma_desc *dma_desc;
+	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(net_rx_packets[i]);

You are filling RX queue/ring with buffers defined in Net core. Does it mean that this DMA driver will not be usable for other purposes, as Net can be compiled out?

Wouldn't it be reasonable to have some sort of .receive_prepare() callback in DMA dma_ops, so DMA user can control which buffers to push in RX DMA channel? And it also can be used in eth_ops.free_pkt() callback (see below).

Quoted 59 lines
drivers/dma/bcm6348-iudma.c new file +59 -0
+		} 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;
+
+		if (bcm6348_iudma_chan_is_rx(dma->id))
+			writel_be(1,
+				  priv->base + DMA_FLOWC_ALLOC_REG(dma->id));
+
+		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));
+	}
+
+	/* set dma max burst */
+	writel_be(ch_priv->dma_ring_size,
+		  priv->chan + DMAC_BURST_REG(dma->id));
+
+	/* clear interrupts */
+	writel_be(DMAC_IR_DONE_MASK, priv->chan + DMAC_IR_ST_REG(dma->id));
+	writel_be(0, priv->chan + DMAC_IR_EN_REG(dma->id));
+
+	setbits_be32(priv->chan + DMAC_CFG_REG(dma->id), DMAC_CFG_ENABLE_MASK);
+
+	return 0;
+}

[...]

Quoted 37 lines
drivers/dma/bcm6348-iudma.c new file +37 -0
+
+static int bcm6348_iudma_receive(struct dma *dma, void **dst)
+{
+	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;
+	uint16_t status;
+	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 0;
+
+	/* check dma end */
+	if (!(dma_desc->status & DMAD_ST_EOP_MASK))
+		return -EINVAL;
+
+	/* 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));
+
+	/* get dma data */
+	*dst = dma_buff;
+	ret = dma_desc->length;
+

drivers/dma/bcm6348-iudma.c line 335

Quoted 10 lines
drivers/dma/bcm6348-iudma.c new file +10 -0
+	/* reinit dma descriptor */
+	status = dma_desc->status & DMAD_ST_WRAP_MASK;
+	status |= DMAD_ST_OWN_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));

Could you clarify pls, if you do return dma_desc to RX ring here or not?

if yes, wouldn't it cause potential problem on Net RX path

		ret = eth_get_ops(current)->recv(current, flags, &packet);

^^ (1) here buffer will be received from DMA ( and pushed back to RX ring ?? )

		flags = 0;
		if (ret > 0)
			net_process_received_packet(packet, ret);

^^ (2) here it will be passed in Net stack

		if (ret >= 0 && eth_get_ops(current)->free_pkt)
			eth_get_ops(current)->free_pkt(current, packet, ret);

^^ at this point it should be safe to return buffer in DMA RX ring.

		if (ret <= 0)
			break;

Can DMA overwrite packet after point (1) while packet is still processed (2)?

Quoted 16 lines
drivers/dma/bcm6348-iudma.c new file +16 -0
+
+	/* set flow control buffer alloc */
+	writel_be(1, priv->base + DMA_FLOWC_ALLOC_REG(dma->id));
+
+	/* enable dma */
+	setbits_be32(priv->chan + DMAC_CFG_REG(dma->id), DMAC_CFG_ENABLE_MASK);
+
+	/* set interrupt */
+	writel_be(DMAC_IR_DONE_MASK, priv->chan + DMAC_IR_EN_REG(dma->id));
+
+	/* increment dma descriptor */
+	ch_priv->desc_id = (ch_priv->desc_id + 1) % ch_priv->dma_ring_size;
+
+	return ret - 4;
+}
+
Signature · 2 lines
regards,
-grygorii
#47 lore raw

RFC v3 3/15 dma: add bcm6348-iudma support

Hi Grygori,

Quoted 29 lines · Grygorii Strashko

Hi

I'd appreciated if you can clarify few points below.

Quoted 13 lines · Álvaro Fernández Rojas

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

---
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 | 505 ++++++++++++++++++++++++++++++++++++++++++++
   3 files changed, 515 insertions(+)

create mode 100644 drivers/dma/bcm6348-iudma.c

[...]

Quoted 9 lines
drivers/dma/bcm6348-iudma.c new file +9 -0
+static int bcm6348_iudma_enable(struct dma *dma)
+{
+	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;
+	uint8_t i;
+
+	/* init dma rings */
+	dma_desc = ch_priv->dma_ring;
Quoted 8 lines

drivers/dma/bcm6348-iudma.c line 200

Quoted 5 lines
drivers/dma/bcm6348-iudma.c new file +5 -0
+	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(net_rx_packets[i]);

You are filling RX queue/ring with buffers defined in Net core. Does it mean that this DMA driver will not be usable for other purposes, as Net can be compiled out?

As far as I know, and depending on the specific SoC, BCM63xx IUDMA is used for Ethernet, USB (device only) and xDSL.
So yes, in u-boot it will be used for ethernet only.
BTW, my first attempt didn't use net_rx_packets, but I saw that in pic32_eth implementation and dropped the dma specific buffers. I will add them again ;).

Quoted 4 lines

Wouldn't it be reasonable to have some sort of .receive_prepare() callback in DMA dma_ops, so DMA user can control which buffers to push in RX DMA channel? And it also can be used in eth_ops.free_pkt() callback (see below).

Yes, probably, but maybe we can achieve that without adding another call.

Quoted 102 lines
Quoted 60 lines
drivers/dma/bcm6348-iudma.c new file +59 -0
+		} 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;
+
+		if (bcm6348_iudma_chan_is_rx(dma->id))
+			writel_be(1,
+				  priv->base + DMA_FLOWC_ALLOC_REG(dma->id));
+
+		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));
+	}
+
+	/* set dma max burst */
+	writel_be(ch_priv->dma_ring_size,
+		  priv->chan + DMAC_BURST_REG(dma->id));
+
+	/* clear interrupts */
+	writel_be(DMAC_IR_DONE_MASK, priv->chan + DMAC_IR_ST_REG(dma->id));
+	writel_be(0, priv->chan + DMAC_IR_EN_REG(dma->id));
+
+	setbits_be32(priv->chan + DMAC_CFG_REG(dma->id), DMAC_CFG_ENABLE_MASK);
+
+	return 0;
+}

[...]

Quoted 40 lines
drivers/dma/bcm6348-iudma.c new file +40 -0
+
+static int bcm6348_iudma_receive(struct dma *dma, void **dst)
+{
+	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;
+	uint16_t status;
+	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 0;
+
+	/* check dma end */
+	if (!(dma_desc->status & DMAD_ST_EOP_MASK))
+		return -EINVAL;
+
+	/* 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));
+
+	/* get dma data */
+	*dst = dma_buff;
+	ret = dma_desc->length;
+
+	/* reinit dma descriptor */
+	status = dma_desc->status & DMAD_ST_WRAP_MASK;
+	status |= DMAD_ST_OWN_MASK;
Quoted 8 lines

drivers/dma/bcm6348-iudma.c line 335

Quoted 7 lines
drivers/dma/bcm6348-iudma.c new file +7 -0
+
+	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));

Could you clarify pls, if you do return dma_desc to RX ring here or not?

Yes.

Quoted 10 lines

if yes, wouldn't it cause potential problem on Net RX path

		ret = eth_get_ops(current)->recv(current, flags, &packet);

^^ (1) here buffer will be received from DMA ( and pushed back to RX ring ?? )

		flags = 0;
		if (ret > 0)
			net_process_received_packet(packet, ret);

^^ (2) here it will be passed in Net stack

Quoted 8 lines
		if (ret >= 0 && eth_get_ops(current)->free_pkt)
			eth_get_ops(current)->free_pkt(current, packet, ret);

^^ at this point it should be safe to return buffer in DMA RX ring.

		if (ret <= 0)
			break;

Can DMA overwrite packet after point (1) while packet is still processed (2)?

I don't think so, because as far as I know u-boot is not processing more than one packet at once, is it?
But yeah, I see your point and if it does process more than one packet at once this is not the proper way to do that.
I will use free_pkt in next version and lock the packet until it's processed.

Quoted 19 lines
Quoted 7 lines
drivers/dma/bcm6348-iudma.c new file +6 -0
+
+	/* set flow control buffer alloc */
+	writel_be(1, priv->base + DMA_FLOWC_ALLOC_REG(dma->id));
+
+	/* enable dma */
+	setbits_be32(priv->chan + DMAC_CFG_REG(dma->id), DMAC_CFG_ENABLE_MASK);

drivers/dma/bcm6348-iudma.c line 351

Quoted 10 lines
drivers/dma/bcm6348-iudma.c new file +10 -0
+
+	/* set interrupt */
+	writel_be(DMAC_IR_DONE_MASK, priv->chan + DMAC_IR_EN_REG(dma->id));
+
+	/* increment dma descriptor */
+	ch_priv->desc_id = (ch_priv->desc_id + 1) % ch_priv->dma_ring_size;
+
+	return ret - 4;
+}
+

Regards,
Álvaro.

#48 lore raw

RFC v3 3/15 dma: add bcm6348-iudma support

Hi

thanks for your comments.

Quoted 35 lines · Álvaro Fernández Rojas
Quoted 26 lines · Grygorii Strashko
Quoted 14 lines · Álvaro Fernández Rojas

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

---
   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 | 505
++++++++++++++++++++++++++++++++++++++++++++

   3 files changed, 515 insertions(+)

   create mode 100644 drivers/dma/bcm6348-iudma.c

[...]

Quoted 10 lines
drivers/dma/bcm6348-iudma.c new file +10 -0
+static int bcm6348_iudma_enable(struct dma *dma)
+{
+    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;
+    uint8_t i;
+
+    /* init dma rings */
+    dma_desc = ch_priv->dma_ring;
+    for (i = 0; i < ch_priv->dma_ring_size; i++) {
Quoted 8 lines
Quoted 4 lines

+        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(net_rx_packets[i]);

You are filling RX queue/ring with buffers defined in Net core. Does it mean that this DMA driver will not be usable for other purposes, as
Net can be compiled out?

Quoted 6 lines

As far as I know, and depending on the specific SoC, BCM63xx IUDMA is used for Ethernet, USB (device only) and xDSL.
So yes, in u-boot it will be used for ethernet only.
BTW, my first attempt didn't use net_rx_packets, but I saw that in pic32_eth implementation and dropped the dma specific buffers. I will add them again ;).

it is really net specific :)

Quoted 8 lines
Quoted 6 lines

Wouldn't it be reasonable to have some sort of .receive_prepare() callback in
DMA dma_ops, so DMA user can control which buffers to push in RX DMA channel?
And it also can be used in eth_ops.free_pkt() callback (see below).

Yes, probably, but maybe we can achieve that without adding another call.

Quoted 1 line

I'm looking at this patch set from our HW point of view. In my case, DMA channel can be used with different IPs (not only networking), so it would be really great if DMA user can pass RX buffers in DMA driver - network driver can use net_rx_packets, other drivers might use own buffers. So hard-codding RX buffers in DMA driver looks like not a good choice.

Quoted 21 lines
Quoted 5 lines
Quoted 4 lines

+
+    /* flush cache */
+    flush_dcache_range((ulong)dma_desc,
+        ALIGN_END_ADDR(struct bcm6348_dma_desc, dma_desc, 1));

Could you clarify pls, if you do return dma_desc to RX ring here or not?

Yes.

Quoted 15 lines

if yes, wouldn't it cause potential problem on Net RX path ret = eth_get_ops(current)->recv(current, flags, &packet); ^^ (1) here buffer will be received from DMA ( and pushed back to RX ring ?? )

        flags = 0;
        if (ret > 0) net_process_received_packet(packet, ret); ^^ (2) here it will be passed in Net stack

        if (ret >= 0 && eth_get_ops(current)->free_pkt) eth_get_ops(current)->free_pkt(current, packet, ret); ^^ at this point it should be safe to return buffer in DMA RX ring.

Quoted 7 lines
Quoted 5 lines

        if (ret <= 0)
            break;

Can DMA overwrite packet after point (1) while packet is still processed (2)?

I don't think so, because as far as I know u-boot is not processing more than one packet at once, is it?

u-boot can't process more than one packet, but dma does. if buffer returned to DMA and there are some traffic on the line - DMA can potentially refill all buffers in its RX ring while u-boot still processing one packet.

Quoted 4 lines

But yeah, I see your point and if it does process more than one packet at once this is not the proper way to do that.
I will use free_pkt in next version and lock the packet until it's processed.

Signature · 2 lines
regards,
-grygorii
#49 lore raw

RFC v3 3/15 dma: add bcm6348-iudma support

Hi Grygorii,

Quoted 83 lines · Grygorii Strashko

Hi

thanks for your comments.

Quoted 35 lines · Álvaro Fernández Rojas
Quoted 26 lines · Grygorii Strashko
Quoted 14 lines · Álvaro Fernández Rojas

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

---
   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 | 505
++++++++++++++++++++++++++++++++++++++++++++
    3 files changed, 515 insertions(+)

   create mode 100644 drivers/dma/bcm6348-iudma.c

[...]

Quoted 10 lines
drivers/dma/bcm6348-iudma.c new file +10 -0
+static int bcm6348_iudma_enable(struct dma *dma)
+{
+    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;
+    uint8_t i;
+
+    /* init dma rings */
+    dma_desc = ch_priv->dma_ring;
+    for (i = 0; i < ch_priv->dma_ring_size; i++) {
Quoted 8 lines
Quoted 4 lines

+        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(net_rx_packets[i]);

You are filling RX queue/ring with buffers defined in Net core. Does it mean that this DMA driver will not be usable for other purposes, as
Net can be compiled out?

Quoted 6 lines

As far as I know, and depending on the specific SoC, BCM63xx IUDMA is used for Ethernet, USB (device only) and xDSL.
So yes, in u-boot it will be used for ethernet only.
BTW, my first attempt didn't use net_rx_packets, but I saw that in pic32_eth implementation and dropped the dma specific buffers. I will add them again ;).

it is really net specific :)

Quoted 6 lines
Quoted 5 lines

Wouldn't it be reasonable to have some sort of .receive_prepare() callback in
DMA dma_ops, so DMA user can control which buffers to push in RX DMA channel?
And it also can be used in eth_ops.free_pkt() callback (see below).

Yes, probably, but maybe we can achieve that without adding another call.

I'm looking at this patch set from our HW point of view. In my case, DMA channel can be used with different IPs (not only networking), so it would be really great if DMA user can pass RX buffers in DMA driver - network driver can use net_rx_packets, other drivers might use own buffers. So hard-codding RX buffers in DMA driver looks like not a good choice.

Quoted 23 lines
Quoted 5 lines
Quoted 4 lines

+
+    /* flush cache */
+    flush_dcache_range((ulong)dma_desc,
+        ALIGN_END_ADDR(struct bcm6348_dma_desc, dma_desc, 1));

Could you clarify pls, if you do return dma_desc to RX ring here or not?

Yes.

Quoted 17 lines

if yes, wouldn't it cause potential problem on Net RX path
        ret = eth_get_ops(current)->recv(current, flags, &packet);
^^ (1) here buffer will be received from DMA ( and pushed back to RX ring ?? )

        flags = 0;
        if (ret > 0) net_process_received_packet(packet, ret);
^^ (2) here it will be passed in Net stack

        if (ret >= 0 && eth_get_ops(current)->free_pkt) eth_get_ops(current)->free_pkt(current, packet, ret);
^^ at this point it should be safe to return buffer in DMA RX ring.

        if (ret <= 0)
            break;

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

Can DMA overwrite packet after point (1) while packet is still processed (2)?

I don't think so, because as far as I know u-boot is not processing more than one packet at once, is it?

u-boot can't process more than one packet, but dma does. if buffer returned to DMA and there are some traffic on the line - DMA can potentially refill all buffers in its RX ring while u-boot still processing one packet.

I just sent a new version of the patches which doesn't use net_rx_packets in bcm6348-iudma.
However, after several tests it turns out that dma received buffers must be processed as soon as possible in order to avoid flow control issues. Considering that, releasing the buffer by using free_pkt after the packet is processed isn't a valid option, since it makes ethernet unusable. That's why I decided to allocate a dynamic buffer on bcm6348-iudma, saving the received packets on net_rx_packets and immediately returning the dma descriptor to the RX ring.

However, you can still add dma_receive_prepare to dma ops if you need it for your HW.

Quoted 7 lines
Quoted 6 lines

But yeah, I see your point and if it does process more than one packet at once this is not the proper way to do that.
I will use free_pkt in next version and lock the packet until it's processed.

Regards,
Álvaro.

#50 lore raw

RFC v3 4/15 bmips: bcm6338: add bcm6348-iudma support

In reply to Álvaro Fernández Rojas

---
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
arch/mips/dts/brcm,bcm6338.dtsi +14 -0
index 0cab44cb8d..4125f71d9f 100644
@@ -5,6 +5,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"
@@ -131,5 +132,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>;
+		};
 	};
 };
include/dt-bindings/dma/bcm6338-dma.h new file +15 -0
new file mode 100644
index 0000000000..5dd66239b4
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ *
+ * 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 */
Signature · 1 line
2.11.0
#51 lore raw

RFC v3 5/15 bmips: bcm6348: add bcm6348-iudma support

In reply to Álvaro Fernández Rojas

---
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
arch/mips/dts/brcm,bcm6348.dtsi +16 -0
index 92fb91afc1..d774c59665 100644
@@ -5,6 +5,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"
@@ -160,5 +161,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>;
+		};
 	};
 };
include/dt-bindings/dma/bcm6348-dma.h new file +17 -0
new file mode 100644
index 0000000000..a1d3a6456d
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ *
+ * 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 */
Signature · 1 line
2.11.0
#52 lore raw

RFC v3 6/15 bmips: bcm6358: add bcm6348-iudma support

In reply to Álvaro Fernández Rojas

---
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
arch/mips/dts/brcm,bcm6358.dtsi +18 -0
index b63b53baee..1468e4f63a 100644
@@ -5,6 +5,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"
@@ -191,5 +192,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>;
+		};
 	};
 };
include/dt-bindings/dma/bcm6358-dma.h new file +17 -0
new file mode 100644
index 0000000000..3b1fcf8540
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ *
+ * 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 */
Signature · 1 line
2.11.0
#53 lore raw

RFC v3 7/15 phy: add support for internal phys

In reply to Álvaro Fernández Rojas

---
v3: no changes
v2: no changes

 include/phy.h | 2 ++
 1 file changed, 2 insertions(+)
include/phy.h +2 -0
index 0543ec10c2..8f3e53db01 100644
@@ -50,6 +50,7 @@
 
 
 typedef enum {
+	PHY_INTERFACE_MODE_INTERNAL,
 	PHY_INTERFACE_MODE_MII,
 	PHY_INTERFACE_MODE_GMII,
 	PHY_INTERFACE_MODE_SGMII,
@@ -72,6 +73,7 @@ typedef enum {
 } phy_interface_t;
 
 static const char *phy_interface_strings[] = {
+	[PHY_INTERFACE_MODE_INTERNAL]		= "internal",
 	[PHY_INTERFACE_MODE_MII]		= "mii",
 	[PHY_INTERFACE_MODE_GMII]		= "gmii",
 	[PHY_INTERFACE_MODE_SGMII]		= "sgmii",
Signature · 1 line
2.11.0
#54 lore raw

RFC v3 8/15 net: add support for bcm6348-enet

In reply to Álvaro Fernández Rojas

---
v3: no changes
v2: select DMA_CHANNELS.

 drivers/net/Kconfig            |  10 +
 drivers/net/Makefile           |   1 +
 drivers/net/bcm6348-eth.c      | 517 +++++++++++++++++++++++++++++++++++++++++
 include/configs/bmips_common.h |   5 +-
 4 files changed, 532 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/bcm6348-eth.c
drivers/net/Kconfig +10 -0
index de1947ccc1..e532332d78 100644
@@ -71,6 +71,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
drivers/net/Makefile +1 -0
index ac5443c752..282adbc775 100644
@@ -8,6 +8,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
drivers/net/bcm6348-eth.c new file +517 -0

517 lines not on this page · raw message

include/configs/bmips_common.h +4 -1
index 38bf7a272b..eb66512f67 100644
@@ -7,6 +7,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 }
@@ -17,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
 
Signature · 1 line
2.11.0
#55 lore raw

RFC v3 9/15 bmips: bcm6338: add support for bcm6348-enet

In reply to Álvaro Fernández Rojas

---
v3: no changes
v2: no changes

 arch/mips/dts/brcm,bcm6338.dtsi | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
arch/mips/dts/brcm,bcm6338.dtsi +15 -0
index 4125f71d9f..621278c9d1 100644
@@ -145,5 +145,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";
+		};
 	};
 };
Signature · 1 line
2.11.0
#56 lore raw

RFC v3 10/15 bmips: enable f@st1704 enet support

In reply to Álvaro Fernández Rojas

---
v3: no changes
v2: no changes

 arch/mips/dts/sagem,f at st1704.dts     | 12 ++++++++++++
 configs/sagem_f at st1704_ram_defconfig |  9 ++++++++-
 2 files changed, 20 insertions(+), 1 deletion(-)
arch/mips/dts/sagem,f at st1704.dts +12 -0
index dd0e5b8b7c..99d031f10a 100644
@@ -40,6 +40,18 @@
 	};
 };
 
+&enet {
+	status = "okay";
+	phy = <&enetphy>;
+	phy-mode = "mii";
+
+	enetphy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio {
 	status = "okay";
 };
configs/sagem_f at st1704_ram_defconfig +8 -1
index 0adcd46d51..1a640781b7 100644
@@ -28,11 +28,15 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
-# CONFIG_CMD_NET is not set
+CONFIG_CMD_DHCP=y
 # CONFIG_CMD_NFS is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
+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
@@ -41,6 +45,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
Signature · 1 line
2.11.0
#57 lore raw

RFC v3 11/15 bmips: bcm6348: add support for bcm6348-enet

In reply to Álvaro Fernández Rojas

---
v3: no changes
v2: no changes

 arch/mips/dts/brcm,bcm6348.dtsi | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
arch/mips/dts/brcm,bcm6348.dtsi +26 -0
index d774c59665..e540865019 100644
@@ -162,6 +162,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>,
Signature · 1 line
2.11.0
#58 lore raw

RFC v3 12/15 bmips: enable ct-5361 enet support

In reply to Álvaro Fernández Rojas

---
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(-)
arch/mips/dts/comtrend,ct-5361.dts +12 -0
index 74dc09046c..a78aa877fc 100644
@@ -35,6 +35,18 @@
 	};
 };
 
+&enet1 {
+	status = "okay";
+	phy = <&enet1phy>;
+	phy-mode = "mii";
+
+	enet1phy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
configs/comtrend_ct5361_ram_defconfig +7 -1
index 8b842606f5..0737772dd2 100644
@@ -26,11 +26,14 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FPGA is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
-# CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
+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
@@ -38,6 +41,9 @@ CONFIG_LED_GPIO=y
 CONFIG_MTD=y
 CONFIG_MTD_NOR_FLASH=y
 CONFIG_CFI_FLASH=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
Signature · 1 line
2.11.0
#59 lore raw

RFC v3 13/15 bmips: bcm6358: add support for bcm6348-enet

In reply to Álvaro Fernández Rojas

---
v3: no changes
v2: no changes

 arch/mips/dts/brcm,bcm6358.dtsi | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)
arch/mips/dts/brcm,bcm6358.dtsi +28 -0
index 1468e4f63a..04329864c2 100644
@@ -193,6 +193,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>,
Signature · 1 line
2.11.0
#60 lore raw

RFC v3 14/15 bmips: enable hg556a enet support

In reply to Álvaro Fernández Rojas

---
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(-)
arch/mips/dts/huawei,hg556a.dts +12 -0
index a1e9c15ab9..2f99e0905c 100644
@@ -94,6 +94,18 @@
 	status = "okay";
 };
 
+&enet1 {
+	status = "okay";
+	phy = <&enet1phy>;
+	phy-mode = "mii";
+
+	enet1phy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
configs/huawei_hg556a_ram_defconfig +7 -1
index 7f7f34ed61..c7c7c6554f 100644
@@ -26,11 +26,14 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FPGA is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
-# CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
+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
@@ -38,6 +41,9 @@ CONFIG_LED_GPIO=y
 CONFIG_MTD=y
 CONFIG_MTD_NOR_FLASH=y
 CONFIG_CFI_FLASH=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
Signature · 1 line
2.11.0
#61 lore raw

RFC v3 15/15 bmips: enable nb4-ser enet support

In reply to Álvaro Fernández Rojas

---
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(-)
arch/mips/dts/sfr,nb4-ser.dts +24 -0
index 473372faa1..73db45f9ea 100644
@@ -54,6 +54,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";
 };
configs/sfr_nb4-ser_ram_defconfig +7 -1
index fc323d879d..07b49a1a77 100644
@@ -27,11 +27,14 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FPGA is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
-# CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
+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_LED_GPIO=y
 CONFIG_MTD=y
 CONFIG_MTD_NOR_FLASH=y
 CONFIG_CFI_FLASH=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
Signature · 1 line
2.11.0
#62 lore raw

v4 cover bmips: add bcm6348-enet support

In reply to Á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...).

This is a RFC, so please give you feedback on the things that I should fix or rework.

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.

Álvaro Fernández Rojas (15):
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
phy: add support for internal phys
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

 arch/mips/dts/brcm,bcm6338.dtsi       |  29 ++
 arch/mips/dts/brcm,bcm6348.dtsi       |  42 +++
 arch/mips/dts/brcm,bcm6358.dtsi       |  46 +++
 arch/mips/dts/comtrend,ct-5361.dts    |  12 +
 arch/mips/dts/huawei,hg556a.dts       |  12 +
 arch/mips/dts/sagem,f at st1704.dts      |  12 +
 arch/mips/dts/sfr,nb4-ser.dts         |  24 ++
 configs/comtrend_ct5361_ram_defconfig |   8 +-
 configs/huawei_hg556a_ram_defconfig   |   8 +-
 configs/sagem_f at st1704_ram_defconfig  |   9 +-
 configs/sfr_nb4-ser_ram_defconfig     |   8 +-
 drivers/dma/Kconfig                   |  16 +
 drivers/dma/Makefile                  |   1 +
 drivers/dma/bcm6348-iudma.c           | 545 ++++++++++++++++++++++++++++++++++
 drivers/dma/dma-uclass.c              | 191 +++++++++++-
 drivers/net/Kconfig                   |  10 +
 drivers/net/Makefile                  |   1 +
 drivers/net/bcm6348-eth.c             | 530 +++++++++++++++++++++++++++++++++
 include/configs/bmips_common.h        |   5 +-
 include/dma-uclass.h                  | 117 ++++++++
 include/dma.h                         | 196 ++++++++++--
 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/phy.h                         |   2 +
 25 files changed, 1837 insertions(+), 36 deletions(-)
 create mode 100644 drivers/dma/bcm6348-iudma.c
 create mode 100644 drivers/net/bcm6348-eth.c
 create mode 100644 include/dma-uclass.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
Signature · 1 line
2.11.0
#63 lore raw

RFC v4 1/15 dma: move dma_ops to dma-uclass.h

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

---
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 |  3 ++-
 include/dma-uclass.h     | 39 +++++++++++++++++++++++++++++++++++++++
 include/dma.h            | 22 ----------------------
 3 files changed, 41 insertions(+), 23 deletions(-)
 create mode 100644 include/dma-uclass.h
drivers/dma/dma-uclass.c +2 -1
index 3d0ce22fbc..6fd4e1b35d 100644
@@ -10,10 +10,11 @@
  */
 
 #include <common.h>
-#include <dma.h>
 #include <dm.h>
 #include <dm/uclass-internal.h>
 #include <dm/device-internal.h>
+#include <dma.h>
+#include <dma-uclass.h>
 #include <errno.h>
 
 DECLARE_GLOBAL_DATA_PTR;
include/dma-uclass.h new file +39 -0
new file mode 100644
index 0000000000..3429f65ec4
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ * Copyright (C) 2015 Texas Instruments Incorporated <www.ti.com>
+ * Written by Mugunthan V N <[email protected]>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#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 */
include/dma.h +0 -22
index 71fa77f2ea..89320f10d9 100644
@@ -28,28 +28,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
Signature · 1 line
2.11.0
#64 lore raw

RFC v4 1/15 dma: move dma_ops to dma-uclass.h

Hi

Quoted 11 lines · Álvaro Fernández Rojas

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

---
v4: no changes
v3: Introduce changes reported by Simon Glass:
- Improve dma-uclass.h documentation.
- Switch to live tree API.

Quoted 6 lines
  drivers/dma/dma-uclass.c |  3 ++-
  include/dma-uclass.h     | 39 +++++++++++++++++++++++++++++++++++++++
  include/dma.h            | 22 ----------------------
  3 files changed, 41 insertions(+), 23 deletions(-)

create mode 100644 include/dma-uclass.h

I've sent the same comment for prev patch version also.

this patch will break build of existing DMA drivers, as the do not have #include <dma-uclass.h>.

drivers/dma/ti-edma3.c:563:21: error: variable 'ti_edma3_ops' has initializer but incomplete type

 static const struct dma_ops ti_edma3_ops = {
                     ^~~~~~~

drivers/dma/ti-edma3.c:564:2: error: unknown field 'transfer' specified in initializer
.transfer = ti_edma3_transfer,
^
drivers/dma/ti-edma3.c:564:14: warning: excess elements in struct initializer
.transfer = ti_edma3_transfer,

              ^~~~~~~~~~~~~~~~~
drivers/dma/ti-edma3.c:564:14: note: (near initialization for 'ti_edma3_ops')
drivers/dma/ti-edma3.c:563:29: error: storage size of 'ti_edma3_ops' isn't known
 static const struct dma_ops ti_edma3_ops = {
                             ^~~~~~~~~~~~

make[1]: *** [drivers/dma/ti-edma3.o] Error 1

Signature · 2 lines
regards,
-grygorii
#65 lore raw

RFC v4 2/15 dma: add channels support

In reply to Álvaro Fernández Rojas

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

---
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 | 188 +++++++++++++++++++++++++++++++++++++++++++++--
 include/dma-uclass.h     |  78 ++++++++++++++++++++
 include/dma.h            | 174 ++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 439 insertions(+), 8 deletions(-)
drivers/dma/Kconfig +7 -0
index 1b92c7789d..21b2c0dcaa 100644
@@ -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
drivers/dma/dma-uclass.c +182 -6

206 lines not on this page · raw message

include/dma-uclass.h +78 -0

90 lines not on this page · raw message

include/dma.h +172 -2

190 lines not on this page · raw message

Signature · 1 line
2.11.0
#66 lore raw

RFC v4 3/15 dma: add bcm6348-iudma support

In reply to Álvaro Fernández Rojas

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

---
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 | 545 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 555 insertions(+)
 create mode 100644 drivers/dma/bcm6348-iudma.c
drivers/dma/Kconfig +9 -0
index 21b2c0dcaa..9afa158b51 100644
@@ -19,6 +19,15 @@ config DMA_CHANNELS
 	  Enable channels support for DMA. Some DMA controllers have multiple
 	  channels which can either transfer data to/from different devices.
 
+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
drivers/dma/Makefile +1 -0
index 39b78b2a3d..b2b4147349 100644
@@ -9,6 +9,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_TI_KSNAV) += keystone_nav.o keystone_nav_cfg.o
 obj-$(CONFIG_TI_EDMA3) += ti-edma3.o
drivers/dma/bcm6348-iudma.c new file +545 -0

545 lines not on this page · raw message

Signature · 1 line
2.11.0
#67 lore raw

RFC v4 4/15 bmips: bcm6338: add bcm6348-iudma support

In reply to Álvaro Fernández Rojas

---
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
arch/mips/dts/brcm,bcm6338.dtsi +14 -0
index 0cab44cb8d..4125f71d9f 100644
@@ -5,6 +5,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"
@@ -131,5 +132,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>;
+		};
 	};
 };
include/dt-bindings/dma/bcm6338-dma.h new file +15 -0
new file mode 100644
index 0000000000..5dd66239b4
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ *
+ * 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 */
Signature · 1 line
2.11.0
#68 lore raw

RFC v4 5/15 bmips: bcm6348: add bcm6348-iudma support

In reply to Álvaro Fernández Rojas

---
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
arch/mips/dts/brcm,bcm6348.dtsi +16 -0
index 92fb91afc1..d774c59665 100644
@@ -5,6 +5,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"
@@ -160,5 +161,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>;
+		};
 	};
 };
include/dt-bindings/dma/bcm6348-dma.h new file +17 -0
new file mode 100644
index 0000000000..a1d3a6456d
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ *
+ * 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 */
Signature · 1 line
2.11.0
#69 lore raw

RFC v4 6/15 bmips: bcm6358: add bcm6348-iudma support

In reply to Álvaro Fernández Rojas

---
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
arch/mips/dts/brcm,bcm6358.dtsi +18 -0
index b63b53baee..1468e4f63a 100644
@@ -5,6 +5,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"
@@ -191,5 +192,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>;
+		};
 	};
 };
include/dt-bindings/dma/bcm6358-dma.h new file +17 -0
new file mode 100644
index 0000000000..3b1fcf8540
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ *
+ * 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 */
Signature · 1 line
2.11.0
#70 lore raw

RFC v4 7/15 phy: add support for internal phys

In reply to Álvaro Fernández Rojas

---
v4: no changes
v3: no changes
v2: no changes

 include/phy.h | 2 ++
 1 file changed, 2 insertions(+)
include/phy.h +2 -0
index 0543ec10c2..8f3e53db01 100644
@@ -50,6 +50,7 @@
 
 
 typedef enum {
+	PHY_INTERFACE_MODE_INTERNAL,
 	PHY_INTERFACE_MODE_MII,
 	PHY_INTERFACE_MODE_GMII,
 	PHY_INTERFACE_MODE_SGMII,
@@ -72,6 +73,7 @@ typedef enum {
 } phy_interface_t;
 
 static const char *phy_interface_strings[] = {
+	[PHY_INTERFACE_MODE_INTERNAL]		= "internal",
 	[PHY_INTERFACE_MODE_MII]		= "mii",
 	[PHY_INTERFACE_MODE_GMII]		= "gmii",
 	[PHY_INTERFACE_MODE_SGMII]		= "sgmii",
Signature · 1 line
2.11.0
#71 lore raw

RFC v4 8/15 net: add support for bcm6348-enet

In reply to Álvaro Fernández Rojas

---
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      | 530 +++++++++++++++++++++++++++++++++++++++++
 include/configs/bmips_common.h |   5 +-
 4 files changed, 545 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/bcm6348-eth.c
drivers/net/Kconfig +10 -0
index de1947ccc1..e532332d78 100644
@@ -71,6 +71,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
drivers/net/Makefile +1 -0
index ac5443c752..282adbc775 100644
@@ -8,6 +8,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
drivers/net/bcm6348-eth.c new file +530 -0

530 lines not on this page · raw message

include/configs/bmips_common.h +4 -1
index 38bf7a272b..eb66512f67 100644
@@ -7,6 +7,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 }
@@ -17,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
 
Signature · 1 line
2.11.0
#72 lore raw

RFC v4 9/15 bmips: bcm6338: add support for bcm6348-enet

In reply to Álvaro Fernández Rojas

---
v4: no changes
v3: no changes
v2: no changes

 arch/mips/dts/brcm,bcm6338.dtsi | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
arch/mips/dts/brcm,bcm6338.dtsi +15 -0
index 4125f71d9f..621278c9d1 100644
@@ -145,5 +145,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";
+		};
 	};
 };
Signature · 1 line
2.11.0
#73 lore raw

RFC v4 10/15 bmips: enable f@st1704 enet support

In reply to Álvaro Fernández Rojas

---
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 |  9 ++++++++-
 2 files changed, 20 insertions(+), 1 deletion(-)
arch/mips/dts/sagem,f at st1704.dts +12 -0
index dd0e5b8b7c..99d031f10a 100644
@@ -40,6 +40,18 @@
 	};
 };
 
+&enet {
+	status = "okay";
+	phy = <&enetphy>;
+	phy-mode = "mii";
+
+	enetphy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio {
 	status = "okay";
 };
configs/sagem_f at st1704_ram_defconfig +8 -1
index 0adcd46d51..1a640781b7 100644
@@ -28,11 +28,15 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
-# CONFIG_CMD_NET is not set
+CONFIG_CMD_DHCP=y
 # CONFIG_CMD_NFS is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
+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
@@ -41,6 +45,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
Signature · 1 line
2.11.0
#74 lore raw

RFC v4 11/15 bmips: bcm6348: add support for bcm6348-enet

In reply to Álvaro Fernández Rojas

---
v4: no changes
v3: no changes
v2: no changes

 arch/mips/dts/brcm,bcm6348.dtsi | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
arch/mips/dts/brcm,bcm6348.dtsi +26 -0
index d774c59665..e540865019 100644
@@ -162,6 +162,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>,
Signature · 1 line
2.11.0
#75 lore raw

RFC v4 12/15 bmips: enable ct-5361 enet support

In reply to Álvaro Fernández Rojas

---
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(-)
arch/mips/dts/comtrend,ct-5361.dts +12 -0
index 74dc09046c..a78aa877fc 100644
@@ -35,6 +35,18 @@
 	};
 };
 
+&enet1 {
+	status = "okay";
+	phy = <&enet1phy>;
+	phy-mode = "mii";
+
+	enet1phy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
configs/comtrend_ct5361_ram_defconfig +7 -1
index 8b842606f5..0737772dd2 100644
@@ -26,11 +26,14 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FPGA is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
-# CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
+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
@@ -38,6 +41,9 @@ CONFIG_LED_GPIO=y
 CONFIG_MTD=y
 CONFIG_MTD_NOR_FLASH=y
 CONFIG_CFI_FLASH=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
Signature · 1 line
2.11.0
#76 lore raw

RFC v4 13/15 bmips: bcm6358: add support for bcm6348-enet

In reply to Álvaro Fernández Rojas

---
v4: no changes
v3: no changes
v2: no changes

 arch/mips/dts/brcm,bcm6358.dtsi | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)
arch/mips/dts/brcm,bcm6358.dtsi +28 -0
index 1468e4f63a..04329864c2 100644
@@ -193,6 +193,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>,
Signature · 1 line
2.11.0
#77 lore raw

RFC v4 14/15 bmips: enable hg556a enet support

In reply to Álvaro Fernández Rojas

---
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(-)
arch/mips/dts/huawei,hg556a.dts +12 -0
index a1e9c15ab9..2f99e0905c 100644
@@ -94,6 +94,18 @@
 	status = "okay";
 };
 
+&enet1 {
+	status = "okay";
+	phy = <&enet1phy>;
+	phy-mode = "mii";
+
+	enet1phy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
configs/huawei_hg556a_ram_defconfig +7 -1
index 7f7f34ed61..c7c7c6554f 100644
@@ -26,11 +26,14 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FPGA is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
-# CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
+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
@@ -38,6 +41,9 @@ CONFIG_LED_GPIO=y
 CONFIG_MTD=y
 CONFIG_MTD_NOR_FLASH=y
 CONFIG_CFI_FLASH=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
Signature · 1 line
2.11.0
#78 lore raw

RFC v4 15/15 bmips: enable nb4-ser enet support

In reply to Álvaro Fernández Rojas

---
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(-)
arch/mips/dts/sfr,nb4-ser.dts +24 -0
index 473372faa1..73db45f9ea 100644
@@ -54,6 +54,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";
 };
configs/sfr_nb4-ser_ram_defconfig +7 -1
index fc323d879d..07b49a1a77 100644
@@ -27,11 +27,14 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FPGA is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
-# CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
+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_LED_GPIO=y
 CONFIG_MTD=y
 CONFIG_MTD_NOR_FLASH=y
 CONFIG_CFI_FLASH=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
Signature · 1 line
2.11.0
#79 lore raw

v5 cover bmips: add bcm6348-enet support

In reply to Á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...).

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.

Álvaro Fernández Rojas (15):
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
phy: add support for internal phys
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

 arch/mips/dts/brcm,bcm6338.dtsi       |  29 ++
 arch/mips/dts/brcm,bcm6348.dtsi       |  42 +++
 arch/mips/dts/brcm,bcm6358.dtsi       |  46 +++
 arch/mips/dts/comtrend,ct-5361.dts    |  12 +
 arch/mips/dts/huawei,hg556a.dts       |  12 +
 arch/mips/dts/sagem,f at st1704.dts      |  12 +
 arch/mips/dts/sfr,nb4-ser.dts         |  24 ++
 configs/comtrend_ct5361_ram_defconfig |   8 +-
 configs/huawei_hg556a_ram_defconfig   |   8 +-
 configs/sagem_f at st1704_ram_defconfig  |   9 +-
 configs/sfr_nb4-ser_ram_defconfig     |   8 +-
 drivers/dma/Kconfig                   |  16 +
 drivers/dma/Makefile                  |   1 +
 drivers/dma/bcm6348-iudma.c           | 532 +++++++++++++++++++++++++++++++
 drivers/dma/dma-uclass.c              | 190 ++++++++++-
 drivers/dma/ti-edma3.c                |   2 +-
 drivers/net/Kconfig                   |  10 +
 drivers/net/Makefile                  |   1 +
 drivers/net/bcm6348-eth.c             | 575 ++++++++++++++++++++++++++++++++++
 include/configs/bmips_common.h        |   5 +-
 include/dma-uclass.h                  | 117 +++++++
 include/dma.h                         | 196 ++++++++++--
 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/phy.h                         |   2 +
 26 files changed, 1869 insertions(+), 37 deletions(-)
 create mode 100644 drivers/dma/bcm6348-iudma.c
 create mode 100644 drivers/net/bcm6348-eth.c
 create mode 100644 include/dma-uclass.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
Signature · 1 line
2.11.0
#80 lore raw

PATCH v5 1/15 dma: move dma_ops to dma-uclass.h

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

---
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
drivers/dma/dma-uclass.c +1 -1
index 3d0ce22fbc..faa27a3a56 100644
@@ -10,10 +10,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>
 
 DECLARE_GLOBAL_DATA_PTR;
drivers/dma/ti-edma3.c +1 -1
index 852c9e1fd7..64f9a61b49 100644
@@ -12,7 +12,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>
 
include/dma-uclass.h new file +39 -0
new file mode 100644
index 0000000000..3429f65ec4
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ * Copyright (C) 2015 Texas Instruments Incorporated <www.ti.com>
+ * Written by Mugunthan V N <[email protected]>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#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 */
include/dma.h +0 -22
index 71fa77f2ea..89320f10d9 100644
@@ -28,28 +28,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
Signature · 1 line
2.11.0
#81 lore raw

PATCH v5 1/15 dma: move dma_ops to dma-uclass.h

Quoted 13 lines · Álvaro Fernández Rojas

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

---
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.

Quoted 6 lines
  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

Signature · 2 lines
regards,
-grygorii
#82 lore raw

PATCH v5 2/15 dma: add channels support

In reply to Álvaro Fernández Rojas

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

---
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 | 188 +++++++++++++++++++++++++++++++++++++++++++++--
 include/dma-uclass.h     |  78 ++++++++++++++++++++
 include/dma.h            | 174 ++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 439 insertions(+), 8 deletions(-)
drivers/dma/Kconfig +7 -0
index 1b92c7789d..21b2c0dcaa 100644
@@ -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
drivers/dma/dma-uclass.c +182 -6

205 lines not on this page · raw message

include/dma-uclass.h +78 -0

90 lines not on this page · raw message

include/dma.h +172 -2

190 lines not on this page · raw message

Signature · 1 line
2.11.0
#83 lore raw

PATCH v5 2/15 dma: add channels support

Quoted 216 lines · Álvaro Fernández Rojas

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

---
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 | 188 +++++++++++++++++++++++++++++++++++++++++++++--
 include/dma-uclass.h     |  78 ++++++++++++++++++++
 include/dma.h            | 174 ++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 439 insertions(+), 8 deletions(-)
drivers/dma/Kconfig +7 -0
index 1b92c7789d..21b2c0dcaa 100644
@@ -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
drivers/dma/dma-uclass.c +155 -6
index faa27a3a56..b5109aafc9 100644
@@ -1,23 +1,199 @@
 /*
  * Direct Memory Access U-Class driver
  *
- * (C) Copyright 2015
- *     Texas Instruments Incorporated, <www.ti.com>
- *
- * Author: Mugunthan V N <[email protected]>
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ * Copyright (C) 2015 Texas Instruments Incorporated <www.ti.com>
+ * Written by Mugunthan V N <[email protected]>
  *
  * SPDX-License-Identifier:     GPL-2.0+
  */
 
 #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>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#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)
+#  if CONFIG_IS_ENABLED(OF_PLATDATA)
+int dma_get_by_index_platdata(struct udevice *dev, int index,
+                             struct phandle_1_arg *cells, struct dma *dma)
+{
+       int ret;
+
+       if (index != 0)
+               return -ENOSYS;
+       ret = uclass_get_device(UCLASS_DMA, 0, &dma->dev);
+       if (ret)
+               return ret;
+       dma->id = cells[0].id;
+
+       return 0;
+}
+#  else
+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);
+}
+#  endif /* OF_PLATDATA */
+
+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);

drivers/dma/dma-uclass.c line 179

Quoted 10 lines
drivers/dma/dma-uclass.c +10 -0
+}
+
+int dma_receive(struct dma *dma, void **dst)
+{
+       struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+       debug("%s(dma=%p)\n", __func__, dma);
+
+       if (!ops->receive)
+               return -1;

Isn't there a better error code you could return? Such as -ENOSYS like above?

drivers/dma/dma-uclass.c line 191

Quoted 12 lines
drivers/dma/dma-uclass.c +12 -0
+
+       return ops->receive(dma, dst);
+}
+
+int dma_send(struct dma *dma, void *src, size_t len)
+{
+       struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+       debug("%s(dma=%p)\n", __func__, dma);
+
+       if (!ops->send)
+               return -1;

Same here.

Quoted 80 lines
drivers/dma/dma-uclass.c +5 -0
+
+       return ops->send(dma, src, len);
+}
+#endif /* CONFIG_DMA_CHANNELS */
+
 int dma_get_device(u32 transfer_type, struct udevice **devp)
 {
        struct udevice *dev;
include/dma-uclass.h +57 -0
index 3429f65ec4..b334adb68b 100644
@@ -13,6 +13,8 @@
 
 #include <dma.h>
 
+struct ofnode_phandle_args;
+
 /*
  * struct dma_ops - Driver model DMA operations
  *
@@ -20,6 +22,82 @@
  * 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.

include/dma-uclass.h line 89

Quoted 10 lines
include/dma-uclass.h +10 -0
+        * @return zero on success, or -ve error code.
+        */
+       int (*disable)(struct dma *dma);
+       /**
+        * receive() - Receive a DMA transfer.
+        *
+        * @dma: The DMA Channel to manipulate.
+        * @dst: The destination pointer.
+        * @return zero on success, or -ve error code.
+        */

I haven't seen any implementation of this. Will it return -EAGAIN in the case where the packet isn't available?

Quoted 218 lines
include/dma-uclass.h +11 -0
+       int (*receive)(struct dma *dma, void **dst);
+       /**
+        * 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).
+        * @return zero on success, or -ve error code.
+        */
+       int (*send)(struct dma *dma, void *src, size_t len);
+#endif /* CONFIG_DMA_CHANNELS */
        /**
         * transfer() - Issue a DMA transfer. The implementation must
         *   wait until the transfer is done.
include/dma.h +172 -3
index 89320f10d9..bf8123fa9e 100644
@@ -1,6 +1,7 @@
 /*
- * (C) Copyright 2015
- *     Texas Instruments Incorporated, <www.ti.com>
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ * Copyright (C) 2015 Texas Instruments Incorporated <www.ti.com>
+ * Written by Mugunthan V N <[email protected]>
  *
  * SPDX-License-Identifier:     GPL-2.0+
  */
@@ -8,6 +9,9 @@
 #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
@@ -37,6 +41,172 @@ 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.
+ */
+
+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)
+struct phandle_1_arg;
+int dma_get_by_index_platdata(struct udevice *dev, int index,
+                             struct phandle_1_arg *cells, struct dma *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_receive() - Receive a DMA transfer.
+ *
+ * @dma: A DMA struct that was previously successfully requested by
+ *      dma_request/get_by_*().
+ * @dst: The destination pointer.
+ * @return zero on success, or -ve error code.
+ */
+int dma_receive(struct dma *dma, void **dst);
+
+/**
+ * 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).
+ * @return zero on success, or -ve error code.
+ */
+int dma_send(struct dma *dma, void *src, size_t len);
+#endif /* CONFIG_DMA_CHANNELS */
+
 /*
  * dma_get_device - get a DMA device which supports transfer
  * type of transfer_type
--

2.11.0

_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
https://lists.denx.de/listinfo/u-boot

#84 lore raw

PATCH v5 2/15 dma: add channels support

Hi Joe,

Quoted 221 lines · Joe Hershberger
Quoted 219 lines · Álvaro Fernández Rojas

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

---
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 | 188 +++++++++++++++++++++++++++++++++++++++++++++--
  include/dma-uclass.h     |  78 ++++++++++++++++++++
  include/dma.h            | 174 ++++++++++++++++++++++++++++++++++++++++++-
  4 files changed, 439 insertions(+), 8 deletions(-)
drivers/dma/Kconfig +7 -0
index 1b92c7789d..21b2c0dcaa 100644
@@ -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
drivers/dma/dma-uclass.c +158 -6
index faa27a3a56..b5109aafc9 100644
@@ -1,23 +1,199 @@
  /*
   * Direct Memory Access U-Class driver
   *
- * (C) Copyright 2015
- *     Texas Instruments Incorporated, <www.ti.com>
- *
- * Author: Mugunthan V N <[email protected]>
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ * Copyright (C) 2015 Texas Instruments Incorporated <www.ti.com>
+ * Written by Mugunthan V N <[email protected]>
   *
   * SPDX-License-Identifier:     GPL-2.0+
   */
 
  #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>
 
  DECLARE_GLOBAL_DATA_PTR;
 
+#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)
+#  if CONFIG_IS_ENABLED(OF_PLATDATA)
+int dma_get_by_index_platdata(struct udevice *dev, int index,
+                             struct phandle_1_arg *cells, struct dma *dma)
+{
+       int ret;
+
+       if (index != 0)
+               return -ENOSYS;
+       ret = uclass_get_device(UCLASS_DMA, 0, &dma->dev);
+       if (ret)
+               return ret;
+       dma->id = cells[0].id;
+
+       return 0;
+}
+#  else
+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);
+}
+#  endif /* OF_PLATDATA */
+
+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_receive(struct dma *dma, void **dst)
Quoted 8 lines

drivers/dma/dma-uclass.c line 179

Quoted 7 lines
drivers/dma/dma-uclass.c +7 -0
+{
+       struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+       debug("%s(dma=%p)\n", __func__, dma);
+
+       if (!ops->receive)
+               return -1;

Isn't there a better error code you could return? Such as -ENOSYS like above?

Ok, I will fix that in the next version.

Quoted 14 lines

drivers/dma/dma-uclass.c line 191

Quoted 13 lines
drivers/dma/dma-uclass.c +12 -0
+
+       return ops->receive(dma, dst);
+}
+
+int dma_send(struct dma *dma, void *src, size_t len)
+{
+       struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+       debug("%s(dma=%p)\n", __func__, dma);
+
+       if (!ops->send)
+               return -1;

Same here.

Ok, I will fix that in the next version.

Quoted 85 lines
Quoted 85 lines
drivers/dma/dma-uclass.c +5 -0
+
+       return ops->send(dma, src, len);
+}
+#endif /* CONFIG_DMA_CHANNELS */
+
  int dma_get_device(u32 transfer_type, struct udevice **devp)
  {
         struct udevice *dev;
include/dma-uclass.h +61 -0
index 3429f65ec4..b334adb68b 100644
@@ -13,6 +13,8 @@
 
  #include <dma.h>
 
+struct ofnode_phandle_args;
+
  /*
   * struct dma_ops - Driver model DMA operations
   *
@@ -20,6 +22,82 @@
   * 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);
+       /**
Quoted 8 lines

include/dma-uclass.h line 89

Quoted 6 lines
include/dma-uclass.h +6 -0
+        * receive() - Receive a DMA transfer.
+        *
+        * @dma: The DMA Channel to manipulate.
+        * @dst: The destination pointer.
+        * @return zero on success, or -ve error code.
+        */

I haven't seen any implementation of this. Will it return -EAGAIN in the case where the packet isn't available?

First of all, this documentation is wrong, because it doesn't return zero on success, but the received packet length, and it returns -EAGAIN when packet is not available in order to facilitate enet implementations, but it can return something different and handle it from enet drivers.
I will fix that in the next version.

Quoted 219 lines
Quoted 219 lines
include/dma-uclass.h +11 -0
+       int (*receive)(struct dma *dma, void **dst);
+       /**
+        * 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).
+        * @return zero on success, or -ve error code.
+        */
+       int (*send)(struct dma *dma, void *src, size_t len);
+#endif /* CONFIG_DMA_CHANNELS */
         /**
          * transfer() - Issue a DMA transfer. The implementation must
          *   wait until the transfer is done.
include/dma.h +172 -3
index 89320f10d9..bf8123fa9e 100644
@@ -1,6 +1,7 @@
  /*
- * (C) Copyright 2015
- *     Texas Instruments Incorporated, <www.ti.com>
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ * Copyright (C) 2015 Texas Instruments Incorporated <www.ti.com>
+ * Written by Mugunthan V N <[email protected]>
   *
   * SPDX-License-Identifier:     GPL-2.0+
   */
@@ -8,6 +9,9 @@
  #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
@@ -37,6 +41,172 @@ 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.
+ */
+
+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)
+struct phandle_1_arg;
+int dma_get_by_index_platdata(struct udevice *dev, int index,
+                             struct phandle_1_arg *cells, struct dma *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_receive() - Receive a DMA transfer.
+ *
+ * @dma: A DMA struct that was previously successfully requested by
+ *      dma_request/get_by_*().
+ * @dst: The destination pointer.
+ * @return zero on success, or -ve error code.
+ */
+int dma_receive(struct dma *dma, void **dst);
+
+/**
+ * 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).
+ * @return zero on success, or -ve error code.
+ */
+int dma_send(struct dma *dma, void *src, size_t len);
+#endif /* CONFIG_DMA_CHANNELS */
+
  /*
   * dma_get_device - get a DMA device which supports transfer
   * type of transfer_type
--

2.11.0

_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
https://lists.denx.de/listinfo/u-boot

#85 lore raw

PATCH v5 2/15 dma: add channels support

In reply to Álvaro Fernández Rojas

Hi Álvaro,

Quoted 12 lines · Álvaro Fernández Rojas

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

---
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.

Quoted 5 lines
  drivers/dma/Kconfig      |   7 ++
  drivers/dma/dma-uclass.c | 188 +++++++++++++++++++++++++++++++++++++++++++++--
  include/dma-uclass.h     |  78 ++++++++++++++++++++
  include/dma.h            | 174 ++++++++++++++++++++++++++++++++++++++++++-
  4 files changed, 439 insertions(+), 8 deletions(-)

Small note first. I don't know if this is common practice for u-boot -
but Isn't it preferable to send new version of the series *not as reply* to the old one?

I've tried this and, in general, it works for me (unfortunately I can't post code yet). Thanks a lot for you work.

But... (it's always but ;)
[...]

Quoted 7 lines
include/dma-uclass.h +7 -0
+	/**
+	 * receive() - Receive a DMA transfer.
+	 *
+	 * @dma: The DMA Channel to manipulate.
+	 * @dst: The destination pointer.
+	 * @return zero on success, or -ve error code.
+	 */

include/dma-uclass.h line 99

Quoted 10 lines
include/dma-uclass.h +10 -0
+	int (*receive)(struct dma *dma, void **dst);
+	/**
+	 * 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).
+	 * @return zero on success, or -ve error code.
+	 */
+	int (*send)(struct dma *dma, void *src, size_t len);

Can we have additional *optional* parameter in above two callbacks and in dma_receive/dma_send() API? Like:
int (*send)(struct dma *dma, void *src, size_t len, void *metadata)
int (*receive)(struct dma *dma, void **dst, void **metadata);

Reason:
It's not a common practice to implement Networking DMA using generic DMA frameworks, simply because Networking DMA HW is terribly different between different SoCs :(, so it's mostly impossible to fit all of them in any generic DMA framework (at least this has never ever worked for Linux kernel):
- totally different HW rings/queues impl, multi-queues & multi DMA channels
- special requirements for IRQ handling
- necessity to pass additional information within each Net DMA descriptor
- availability and support of different Net traffic HW acceleration features

But in case of u-boot, it, theoretically, might work because most of Net drivers have much more simplified implementation comparing to Linux kernel
- UP, polling, one RX/TX channel and disabled Net traffic HW acceleration features.

As result, Proposed here interface can be used with much more different HW and drivers (and especially Net drivers), but only if it will be possible to pass additional DMA driver's specific information from DMA user to DMA driver per each send/rsv request.
For example, two TI driver cpsw.c and keystone_net.c required to pass minimum one additional parameter with each sending packet - Destination Port number, which must be passed to DMA in DMA descriptor. And Source Port number has to be passed back with each received packet.

! I'm not insisting here ! and be happy to hear third opinion.

(if proposition will not be accepted - .. :( I'll just need to do the same later,
but there might be hight number of active users of this interface in u-boot already)

Quoted 202 lines
include/dma-uclass.h +1 -0
+#endif /* CONFIG_DMA_CHANNELS */
  	/**
  	 * transfer() - Issue a DMA transfer. The implementation must
  	 *   wait until the transfer is done.
include/dma.h +172 -2
index 89320f10d9..bf8123fa9e 100644
@@ -1,6 +1,7 @@
  /*
- * (C) Copyright 2015
- *     Texas Instruments Incorporated, <www.ti.com>
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ * Copyright (C) 2015 Texas Instruments Incorporated <www.ti.com>
+ * Written by Mugunthan V N <[email protected]>
   *
   * SPDX-License-Identifier:     GPL-2.0+
   */
@@ -8,6 +9,9 @@
  #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
@@ -37,6 +41,172 @@ 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.
+ */
+
+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)
+struct phandle_1_arg;
+int dma_get_by_index_platdata(struct udevice *dev, int index,
+			      struct phandle_1_arg *cells, struct dma *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_receive() - Receive a DMA transfer.
+ *
+ * @dma: A DMA struct that was previously successfully requested by
+ *	 dma_request/get_by_*().
+ * @dst: The destination pointer.
+ * @return zero on success, or -ve error code.
+ */
+int dma_receive(struct dma *dma, void **dst);
+
+/**
+ * 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).
+ * @return zero on success, or -ve error code.
+ */
+int dma_send(struct dma *dma, void *src, size_t len);
+#endif /* CONFIG_DMA_CHANNELS */
+
  /*
   * dma_get_device - get a DMA device which supports transfer
   * type of transfer_type
Signature · 2 lines
regards,
-grygorii
#86 lore raw

PATCH v5 2/15 dma: add channels support

Hi Grygorii,

Quoted 15 lines · Grygorii Strashko

Hi Álvaro,

Quoted 12 lines · Álvaro Fernández Rojas

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

---
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.

Quoted 7 lines
Quoted 5 lines
   drivers/dma/Kconfig      |   7 ++
   drivers/dma/dma-uclass.c | 188 +++++++++++++++++++++++++++++++++++++++++++++--
   include/dma-uclass.h     |  78 ++++++++++++++++++++
   include/dma.h            | 174 ++++++++++++++++++++++++++++++++++++++++++-
   4 files changed, 439 insertions(+), 8 deletions(-)

Small note first. I don't know if this is common practice for u-boot -
but Isn't it preferable to send new version of the series *not as reply* to the old one?

I was sending it as a reply to the first version, not the last one, but I will do that from now on.

Quoted 3 lines

I've tried this and, in general, it works for me (unfortunately I can't post code yet). Thanks a lot for you work.

Thanks to you for testing :).

Quoted 2 lines

But... (it's always but ;)

¯\_(ツ)_/¯

Quoted 45 lines

[...]

Quoted 7 lines
include/dma-uclass.h +7 -0
+	/**
+	 * receive() - Receive a DMA transfer.
+	 *
+	 * @dma: The DMA Channel to manipulate.
+	 * @dst: The destination pointer.
+	 * @return zero on success, or -ve error code.
+	 */

include/dma-uclass.h line 99

Quoted 10 lines
include/dma-uclass.h +10 -0
+	int (*receive)(struct dma *dma, void **dst);
+	/**
+	 * 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).
+	 * @return zero on success, or -ve error code.
+	 */
+	int (*send)(struct dma *dma, void *src, size_t len);

Can we have additional *optional* parameter in above two callbacks and in dma_receive/dma_send() API? Like:
int (*send)(struct dma *dma, void *src, size_t len, void *metadata)
int (*receive)(struct dma *dma, void **dst, void **metadata);

Reason:
It's not a common practice to implement Networking DMA using generic DMA frameworks, simply because Networking DMA HW is terribly different between different SoCs :(, so it's mostly impossible to fit all of them in any generic DMA framework (at least this has never ever worked for Linux kernel):
- totally different HW rings/queues impl, multi-queues & multi DMA channels
- special requirements for IRQ handling
- necessity to pass additional information within each Net DMA descriptor
- availability and support of different Net traffic HW acceleration features

But in case of u-boot, it, theoretically, might work because most of Net drivers have much more simplified implementation comparing to Linux kernel
- UP, polling, one RX/TX channel and disabled Net traffic HW acceleration features.

As result, Proposed here interface can be used with much more different HW and drivers (and especially Net drivers), but only if it will be possible to pass additional DMA driver's specific information from DMA user to DMA driver per each send/rsv request.
For example, two TI driver cpsw.c and keystone_net.c required to pass minimum one additional parameter with each sending packet - Destination Port number, which must be passed to DMA in DMA descriptor. And Source Port number has to be passed back with each received packet.

Quoted 4 lines

! I'm not insisting here ! and be happy to hear third opinion.

(if proposition will not be accepted - .. :( I'll just need to do the same later,
but there might be hight number of active users of this interface in u-boot already)

If everyone else agrees I can add those two parameters in the next version even though my implementation doesn't need them.

Quoted 195 lines
Quoted 195 lines
include/dma-uclass.h +1 -0
+#endif /* CONFIG_DMA_CHANNELS */
   	/**
   	 * transfer() - Issue a DMA transfer. The implementation must
   	 *   wait until the transfer is done.
include/dma.h +168 -2
index 89320f10d9..bf8123fa9e 100644
@@ -1,6 +1,7 @@
   /*
- * (C) Copyright 2015
- *     Texas Instruments Incorporated, <www.ti.com>
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ * Copyright (C) 2015 Texas Instruments Incorporated <www.ti.com>
+ * Written by Mugunthan V N <[email protected]>
    *
    * SPDX-License-Identifier:     GPL-2.0+
    */
@@ -8,6 +9,9 @@
   #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
@@ -37,6 +41,172 @@ 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.
+ */
+
+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)
+struct phandle_1_arg;
+int dma_get_by_index_platdata(struct udevice *dev, int index,
+			      struct phandle_1_arg *cells, struct dma *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_receive() - Receive a DMA transfer.
+ *
+ * @dma: A DMA struct that was previously successfully requested by
+ *	 dma_request/get_by_*().
+ * @dst: The destination pointer.
+ * @return zero on success, or -ve error code.
+ */
+int dma_receive(struct dma *dma, void **dst);
+
+/**
+ * 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).
+ * @return zero on success, or -ve error code.
Quoted 8 lines

include/dma.h struct dma_dev_priv { · line 212

Quoted 8 lines
include/dma.h +4 -0
+ */
+int dma_send(struct dma *dma, void *src, size_t len);
+#endif /* CONFIG_DMA_CHANNELS */
+
   /*
    * dma_get_device - get a DMA device which supports transfer
    * type of transfer_type

~Álvaro.

#87 lore raw

PATCH v5 2/15 dma: add channels support

In reply to Álvaro Fernández Rojas

Hi Álvaro,

sorry for the late response.

Quoted 329 lines · Álvaro Fernández Rojas

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

---
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 | 188 +++++++++++++++++++++++++++++++++++++++++++++--
 include/dma-uclass.h     |  78 ++++++++++++++++++++
 include/dma.h            | 174 ++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 439 insertions(+), 8 deletions(-)
drivers/dma/Kconfig +7 -0
index 1b92c7789d..21b2c0dcaa 100644
@@ -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
drivers/dma/dma-uclass.c +182 -6
index faa27a3a56..b5109aafc9 100644
@@ -1,23 +1,199 @@
 /*
  * Direct Memory Access U-Class driver
  *
- * (C) Copyright 2015
- *     Texas Instruments Incorporated, <www.ti.com>
- *
- * Author: Mugunthan V N <[email protected]>
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ * Copyright (C) 2015 Texas Instruments Incorporated <www.ti.com>
+ * Written by Mugunthan V N <[email protected]>
  *
  * SPDX-License-Identifier:     GPL-2.0+
  */
 
 #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>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#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)
+#  if CONFIG_IS_ENABLED(OF_PLATDATA)
+int dma_get_by_index_platdata(struct udevice *dev, int index,
+			      struct phandle_1_arg *cells, struct dma *dma)
+{
+	int ret;
+
+	if (index != 0)
+		return -ENOSYS;
+	ret = uclass_get_device(UCLASS_DMA, 0, &dma->dev);
+	if (ret)
+		return ret;
+	dma->id = cells[0].id;
+
+	return 0;
+}
+#  else
+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);
+}
+#  endif /* OF_PLATDATA */
+
+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_receive(struct dma *dma, void **dst)
+{
+	struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (!ops->receive)
+		return -1;
+
+	return ops->receive(dma, dst);
+}
+
+int dma_send(struct dma *dma, void *src, size_t len)
+{
+	struct dma_ops *ops = dma_dev_ops(dma->dev);
+
+	debug("%s(dma=%p)\n", __func__, dma);
+
+	if (!ops->send)
+		return -1;
+
+	return ops->send(dma, src, len);
+}
+#endif /* CONFIG_DMA_CHANNELS */
+
 int dma_get_device(u32 transfer_type, struct udevice **devp)
 {
 	struct udevice *dev;
include/dma-uclass.h +68 -0
index 3429f65ec4..b334adb68b 100644
@@ -13,6 +13,8 @@
 
 #include <dma.h>
 
+struct ofnode_phandle_args;
+
 /*
  * struct dma_ops - Driver model DMA operations
  *
@@ -20,6 +22,82 @@
  * 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);
+	/**
+	 * receive() - Receive a DMA transfer.
+	 *
+	 * @dma: The DMA Channel to manipulate.
+	 * @dst: The destination pointer.
+	 * @return zero on success, or -ve error code.
+	 */
+	int (*receive)(struct dma *dma, void **dst);

include/dma-uclass.h line 100

Quoted 10 lines
include/dma-uclass.h +10 -0
+	/**
+	 * 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).
+	 * @return zero on success, or -ve error code.
+	 */
+	int (*send)(struct dma *dma, void *src, size_t len);
+#endif /* CONFIG_DMA_CHANNELS */

IMHO a DMA driver should not implement receive() and send() directly as this involves generic code like flushing/invalidating caches, synchronous waiting on descriptor status etc. This could be better handled by dma-uclass code than repeating it in each driver.

I think a heavily simplified design of Linux's dmaengine would help. For instance the driver interface could be modelled with prepare_cyclic(), prepare_memcpy() and status(). The dma-uclass can then provide an interface for those functions as well as additional wrapper functions like dma_is_complete(), dma_sync_wait(), dma_receive() or dma_send().

Regardless of the design, I'd like to have at least separate functions for preparing the buffers and polling the descriptor. For instance I have a DMA-capable NAND controller, where the DMA transfer is only started by writing some HW registers. This must happen between preparing the buffers and DMA descriptors and polling the descriptors until the transaction has finished.

Could you do that?

Quoted 201 lines
include/dma-uclass.h +0 -0
 	/**
 	 * transfer() - Issue a DMA transfer. The implementation must
 	 *   wait until the transfer is done.
include/dma.h +172 -2
index 89320f10d9..bf8123fa9e 100644
@@ -1,6 +1,7 @@
 /*
- * (C) Copyright 2015
- *     Texas Instruments Incorporated, <www.ti.com>
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ * Copyright (C) 2015 Texas Instruments Incorporated <www.ti.com>
+ * Written by Mugunthan V N <[email protected]>
  *
  * SPDX-License-Identifier:     GPL-2.0+
  */
@@ -8,6 +9,9 @@
 #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
@@ -37,6 +41,172 @@ 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.
+ */
+
+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)
+struct phandle_1_arg;
+int dma_get_by_index_platdata(struct udevice *dev, int index,
+			      struct phandle_1_arg *cells, struct dma *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_receive() - Receive a DMA transfer.
+ *
+ * @dma: A DMA struct that was previously successfully requested by
+ *	 dma_request/get_by_*().
+ * @dst: The destination pointer.
+ * @return zero on success, or -ve error code.
+ */
+int dma_receive(struct dma *dma, void **dst);
+
+/**
+ * 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).
+ * @return zero on success, or -ve error code.
+ */
+int dma_send(struct dma *dma, void *src, size_t len);
+#endif /* CONFIG_DMA_CHANNELS */
+
 /*
  * dma_get_device - get a DMA device which supports transfer
  * type of transfer_type
Signature · 9 lines
- Daniel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20180311/5111c25b/attachment.sig>
#88 lore raw

PATCH v5 3/15 dma: add bcm6348-iudma support

In reply to Álvaro Fernández Rojas

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

---
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 | 532 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 542 insertions(+)
 create mode 100644 drivers/dma/bcm6348-iudma.c
drivers/dma/Kconfig +9 -0
index 21b2c0dcaa..9afa158b51 100644
@@ -19,6 +19,15 @@ config DMA_CHANNELS
 	  Enable channels support for DMA. Some DMA controllers have multiple
 	  channels which can either transfer data to/from different devices.
 
+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
drivers/dma/Makefile +1 -0
index 39b78b2a3d..b2b4147349 100644
@@ -9,6 +9,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_TI_KSNAV) += keystone_nav.o keystone_nav_cfg.o
 obj-$(CONFIG_TI_EDMA3) += ti-edma3.o
drivers/dma/bcm6348-iudma.c new file +532 -0

532 lines not on this page · raw message

Signature · 1 line
2.11.0
#89 lore raw

PATCH v5 4/15 bmips: bcm6338: add bcm6348-iudma support

In reply to Álvaro Fernández Rojas

---
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
arch/mips/dts/brcm,bcm6338.dtsi +14 -0
index 0cab44cb8d..4125f71d9f 100644
@@ -5,6 +5,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"
@@ -131,5 +132,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>;
+		};
 	};
 };
include/dt-bindings/dma/bcm6338-dma.h new file +15 -0
new file mode 100644
index 0000000000..5dd66239b4
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ *
+ * 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 */
Signature · 1 line
2.11.0
#90 lore raw

PATCH v5 5/15 bmips: bcm6348: add bcm6348-iudma support

In reply to Álvaro Fernández Rojas

---
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
arch/mips/dts/brcm,bcm6348.dtsi +16 -0
index 92fb91afc1..d774c59665 100644
@@ -5,6 +5,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"
@@ -160,5 +161,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>;
+		};
 	};
 };
include/dt-bindings/dma/bcm6348-dma.h new file +17 -0
new file mode 100644
index 0000000000..a1d3a6456d
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ *
+ * 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 */
Signature · 1 line
2.11.0
#91 lore raw

PATCH v5 6/15 bmips: bcm6358: add bcm6348-iudma support

In reply to Álvaro Fernández Rojas

---
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
arch/mips/dts/brcm,bcm6358.dtsi +18 -0
index b63b53baee..1468e4f63a 100644
@@ -5,6 +5,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"
@@ -191,5 +192,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>;
+		};
 	};
 };
include/dt-bindings/dma/bcm6358-dma.h new file +17 -0
new file mode 100644
index 0000000000..3b1fcf8540
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ *
+ * 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 */
Signature · 1 line
2.11.0
#92 lore raw

PATCH v5 7/15 phy: add support for internal phys

In reply to Álvaro Fernández Rojas

---
v5: no changes
v4: no changes
v3: no changes
v2: no changes

 include/phy.h | 2 ++
 1 file changed, 2 insertions(+)
include/phy.h +2 -0
index 0543ec10c2..8f3e53db01 100644
@@ -50,6 +50,7 @@
 
 
 typedef enum {
+	PHY_INTERFACE_MODE_INTERNAL,
 	PHY_INTERFACE_MODE_MII,
 	PHY_INTERFACE_MODE_GMII,
 	PHY_INTERFACE_MODE_SGMII,
@@ -72,6 +73,7 @@ typedef enum {
 } phy_interface_t;
 
 static const char *phy_interface_strings[] = {
+	[PHY_INTERFACE_MODE_INTERNAL]		= "internal",
 	[PHY_INTERFACE_MODE_MII]		= "mii",
 	[PHY_INTERFACE_MODE_GMII]		= "gmii",
 	[PHY_INTERFACE_MODE_SGMII]		= "sgmii",
Signature · 1 line
2.11.0
#93 lore raw

PATCH v5 7/15 phy: add support for internal phys

Quoted 15 lines · Álvaro Fernández Rojas

---
v5: no changes
v4: no changes
v3: no changes
v2: no changes

 include/phy.h | 2 ++
 1 file changed, 2 insertions(+)
include/phy.h +0 -0
index 0543ec10c2..8f3e53db01 100644

include/phy.h line 53

Quoted 4 lines
include/phy.h +1 -0
@@ -50,6 +50,7 @@
 
 
 typedef enum {
+       PHY_INTERFACE_MODE_INTERNAL,

In Linux this is handled as a flag instead of a different mode. It seems we should do it the same way.

Quoted 18 lines
include/phy.h +1 -1
        PHY_INTERFACE_MODE_MII,
        PHY_INTERFACE_MODE_GMII,
        PHY_INTERFACE_MODE_SGMII,
@@ -72,6 +73,7 @@ typedef enum {
 } phy_interface_t;
 
 static const char *phy_interface_strings[] = {
+       [PHY_INTERFACE_MODE_INTERNAL]           = "internal",
        [PHY_INTERFACE_MODE_MII]                = "mii",
        [PHY_INTERFACE_MODE_GMII]               = "gmii",
        [PHY_INTERFACE_MODE_SGMII]              = "sgmii",
--

2.11.0

_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
https://lists.denx.de/listinfo/u-boot

#94 lore raw

PATCH v5 7/15 phy: add support for internal phys

Hi Joe,

Quoted 19 lines · Joe Hershberger
Quoted 17 lines · Álvaro Fernández Rojas

---
v5: no changes
v4: no changes
v3: no changes
v2: no changes

  include/phy.h | 2 ++
  1 file changed, 2 insertions(+)
include/phy.h +0 -0
index 0543ec10c2..8f3e53db01 100644
@@ -50,6 +50,7 @@
 
 
Quoted 4 lines

include/phy.h line 53

Quoted 2 lines
include/phy.h +1 -0
  typedef enum {
+       PHY_INTERFACE_MODE_INTERNAL,

In Linux this is handled as a flag instead of a different mode. It seems we should do it the same way.

Not really, in Linux this is handled as both:
- As a flag (https://elixir.bootlin.com/linux/latest/ident/PHY_IS_INTERNAL):
https://github.com/torvalds/linux/blob/master/include/linux/phy.h#L61
https://github.com/torvalds/linux/blob/master/drivers/net/phy/phy_device.c#L1792
https://github.com/torvalds/linux/blob/master/include/linux/phy.h#L832
- As a mode
(https://elixir.bootlin.com/linux/latest/ident/PHY_INTERFACE_MODE_INTERNAL):
https://github.com/torvalds/linux/blob/master/include/linux/phy.h#L68
https://github.com/torvalds/linux/blob/master/include/linux/phy.h#L119

Quoted 15 lines
Quoted 15 lines
include/phy.h +1 -1
         PHY_INTERFACE_MODE_MII,
         PHY_INTERFACE_MODE_GMII,
         PHY_INTERFACE_MODE_SGMII,
@@ -72,6 +73,7 @@ typedef enum {
  } phy_interface_t;
 
  static const char *phy_interface_strings[] = {
+       [PHY_INTERFACE_MODE_INTERNAL]           = "internal",
         [PHY_INTERFACE_MODE_MII]                = "mii",
         [PHY_INTERFACE_MODE_GMII]               = "gmii",
         [PHY_INTERFACE_MODE_SGMII]              = "sgmii",
--

2.11.0

Quoted 4 lines
Quoted 4 lines

_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
https://lists.denx.de/listinfo/u-boot

~Álvaro.

#95 lore raw

PATCH v5 7/15 phy: add support for internal phys

Quoted 30 lines · Álvaro Fernández Rojas

Hi Joe,

Quoted 21 lines · Joe Hershberger
Quoted 18 lines · Álvaro Fernández Rojas

---
v5: no changes
v4: no changes
v3: no changes
v2: no changes

  include/phy.h | 2 ++
  1 file changed, 2 insertions(+)
include/phy.h +0 -0
index 0543ec10c2..8f3e53db01 100644
@@ -50,6 +50,7 @@
 
 
Quoted 5 lines

include/phy.h line 53

Quoted 2 lines
include/phy.h +1 -0
  typedef enum {
+       PHY_INTERFACE_MODE_INTERNAL,

In Linux this is handled as a flag instead of a different mode. It seems we should do it the same way.

Quoted 10 lines

Not really, in Linux this is handled as both:
- As a flag (https://elixir.bootlin.com/linux/latest/ident/PHY_IS_INTERNAL):
https://github.com/torvalds/linux/blob/master/include/linux/phy.h#L61
https://github.com/torvalds/linux/blob/master/drivers/net/phy/phy_device.c#L1792
https://github.com/torvalds/linux/blob/master/include/linux/phy.h#L832
- As a mode
(https://elixir.bootlin.com/linux/latest/ident/PHY_INTERFACE_MODE_INTERNAL):
https://github.com/torvalds/linux/blob/master/include/linux/phy.h#L68
https://github.com/torvalds/linux/blob/master/include/linux/phy.h#L119

OK, I was looking at an older kernel where there was only the flag.

Quoted 26 lines
Quoted 15 lines
Quoted 15 lines
include/phy.h +1 -1
         PHY_INTERFACE_MODE_MII,
         PHY_INTERFACE_MODE_GMII,
         PHY_INTERFACE_MODE_SGMII,
@@ -72,6 +73,7 @@ typedef enum {
  } phy_interface_t;
 
  static const char *phy_interface_strings[] = {
+       [PHY_INTERFACE_MODE_INTERNAL]           = "internal",
         [PHY_INTERFACE_MODE_MII]                = "mii",
         [PHY_INTERFACE_MODE_GMII]               = "gmii",
         [PHY_INTERFACE_MODE_SGMII]              = "sgmii",
--

2.11.0

Quoted 4 lines
Quoted 4 lines

_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
https://lists.denx.de/listinfo/u-boot

~Álvaro.

_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
https://lists.denx.de/listinfo/u-boot

#96 lore raw

PATCH v5 8/15 net: add support for bcm6348-enet

In reply to Álvaro Fernández Rojas

---
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      | 575 +++++++++++++++++++++++++++++++++++++++++
 include/configs/bmips_common.h |   5 +-
 4 files changed, 590 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/bcm6348-eth.c
drivers/net/Kconfig +10 -0
index de1947ccc1..e532332d78 100644
@@ -71,6 +71,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
drivers/net/Makefile +1 -0
index ac5443c752..282adbc775 100644
@@ -8,6 +8,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
drivers/net/bcm6348-eth.c new file +575 -0

575 lines not on this page · raw message

include/configs/bmips_common.h +4 -1
index 38bf7a272b..eb66512f67 100644
@@ -7,6 +7,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 }
@@ -17,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
 
Signature · 1 line
2.11.0
#97 lore raw

PATCH v5 8/15 net: add support for bcm6348-enet

Quoted 265 lines · Álvaro Fernández Rojas

---
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      | 575 +++++++++++++++++++++++++++++++++++++++++
 include/configs/bmips_common.h |   5 +-
 4 files changed, 590 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/bcm6348-eth.c
drivers/net/Kconfig +10 -0
index de1947ccc1..e532332d78 100644
@@ -71,6 +71,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
drivers/net/Makefile +1 -0
index ac5443c752..282adbc775 100644
@@ -8,6 +8,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
drivers/net/bcm6348-eth.c new file +206 -0
new file mode 100644
index 0000000000..43518f7b2d
@@ -0,0 +1,575 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c:
+ *     Copyright (C) 2008 Maxime Bizon <[email protected]>
+ *
+ * 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]);
+       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];
+

drivers/net/bcm6348-eth.c line 216

Quoted 10 lines
drivers/net/bcm6348-eth.c new file +10 -0
+       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);

Why. Please include reasoning in the comment.

Quoted 389 lines
drivers/net/bcm6348-eth.c new file +359 -0
+
+       return dma_send(&priv->tx_dma, (void *)packet, length);
+}
+
+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,
+};
include/configs/bmips_common.h +4 -2
index 38bf7a272b..eb66512f67 100644
@@ -7,6 +7,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 }
@@ -17,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

_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
https://lists.denx.de/listinfo/u-boot

#98 lore raw

PATCH v5 8/15 net: add support for bcm6348-enet

Hi Joe,

Quoted 270 lines · Joe Hershberger
Quoted 268 lines · Álvaro Fernández Rojas

---
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      | 575 +++++++++++++++++++++++++++++++++++++++++
  include/configs/bmips_common.h |   5 +-
  4 files changed, 590 insertions(+), 1 deletion(-)

create mode 100644 drivers/net/bcm6348-eth.c

drivers/net/Kconfig +10 -0
index de1947ccc1..e532332d78 100644
@@ -71,6 +71,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
drivers/net/Makefile +1 -0
index ac5443c752..282adbc775 100644
@@ -8,6 +8,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
drivers/net/bcm6348-eth.c new file +209 -0
new file mode 100644
index 0000000000..43518f7b2d
@@ -0,0 +1,575 @@
+/*
+ * Copyright (C) 2018 Álvaro Fernández Rojas <[email protected]>
+ *
+ * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c:
+ *     Copyright (C) 2008 Maxime Bizon <[email protected]>
+ *
+ * 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]);
+       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;
+}
+
Quoted 8 lines

drivers/net/bcm6348-eth.c line 216

Quoted 7 lines
drivers/net/bcm6348-eth.c new file +7 -0
+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);

Why. Please include reasoning in the comment.

For what I've seen flow control is a bit tricky on this dma controller and when you don't process a received packet in a short period of time, it may get into a an state where no new packets are correctly received. However, resetting the dma channel here prevents that from hapenning.

Quoted 383 lines
Quoted 383 lines
drivers/net/bcm6348-eth.c new file +359 -0
+
+       return dma_send(&priv->tx_dma, (void *)packet, length);
+}
+
+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,
+};
include/configs/bmips_common.h +4 -1
index 38bf7a272b..eb66512f67 100644
@@ -7,6 +7,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 }
@@ -17,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
 
Quoted 7 lines
Quoted 7 lines

--
2.11.0

_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
https://lists.denx.de/listinfo/u-boot

~Álvaro.

#99 lore raw

PATCH v5 9/15 bmips: bcm6338: add support for bcm6348-enet

In reply to Álvaro Fernández Rojas

---
v5: no changes
v4: no changes
v3: no changes
v2: no changes

 arch/mips/dts/brcm,bcm6338.dtsi | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
arch/mips/dts/brcm,bcm6338.dtsi +15 -0
index 4125f71d9f..621278c9d1 100644
@@ -145,5 +145,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";
+		};
 	};
 };
Signature · 1 line
2.11.0
#100 lore raw

PATCH v5 10/15 bmips: enable f@st1704 enet support

In reply to Álvaro Fernández Rojas

---
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 |  9 ++++++++-
 2 files changed, 20 insertions(+), 1 deletion(-)
arch/mips/dts/sagem,f at st1704.dts +12 -0
index dd0e5b8b7c..99d031f10a 100644
@@ -40,6 +40,18 @@
 	};
 };
 
+&enet {
+	status = "okay";
+	phy = <&enetphy>;
+	phy-mode = "mii";
+
+	enetphy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio {
 	status = "okay";
 };
configs/sagem_f at st1704_ram_defconfig +8 -1
index 0adcd46d51..1a640781b7 100644
@@ -28,11 +28,15 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
-# CONFIG_CMD_NET is not set
+CONFIG_CMD_DHCP=y
 # CONFIG_CMD_NFS is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
+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
@@ -41,6 +45,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
Signature · 1 line
2.11.0
#101 lore raw

PATCH v5 11/15 bmips: bcm6348: add support for bcm6348-enet

In reply to Álvaro Fernández Rojas

---
v5: no changes
v4: no changes
v3: no changes
v2: no changes

 arch/mips/dts/brcm,bcm6348.dtsi | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
arch/mips/dts/brcm,bcm6348.dtsi +26 -0
index d774c59665..e540865019 100644
@@ -162,6 +162,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>,
Signature · 1 line
2.11.0
#102 lore raw

PATCH v5 12/15 bmips: enable ct-5361 enet support

In reply to Álvaro Fernández Rojas

---
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(-)
arch/mips/dts/comtrend,ct-5361.dts +12 -0
index 74dc09046c..a78aa877fc 100644
@@ -35,6 +35,18 @@
 	};
 };
 
+&enet1 {
+	status = "okay";
+	phy = <&enet1phy>;
+	phy-mode = "mii";
+
+	enet1phy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
configs/comtrend_ct5361_ram_defconfig +7 -1
index 8b842606f5..0737772dd2 100644
@@ -26,11 +26,14 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FPGA is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
-# CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
+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
@@ -38,6 +41,9 @@ CONFIG_LED_GPIO=y
 CONFIG_MTD=y
 CONFIG_MTD_NOR_FLASH=y
 CONFIG_CFI_FLASH=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
Signature · 1 line
2.11.0
#103 lore raw

PATCH v5 13/15 bmips: bcm6358: add support for bcm6348-enet

In reply to Álvaro Fernández Rojas

---
v5: no changes
v4: no changes
v3: no changes
v2: no changes

 arch/mips/dts/brcm,bcm6358.dtsi | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)
arch/mips/dts/brcm,bcm6358.dtsi +28 -0
index 1468e4f63a..04329864c2 100644
@@ -193,6 +193,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>,
Signature · 1 line
2.11.0
#104 lore raw

PATCH v5 14/15 bmips: enable hg556a enet support

In reply to Álvaro Fernández Rojas

---
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(-)
arch/mips/dts/huawei,hg556a.dts +12 -0
index a1e9c15ab9..2f99e0905c 100644
@@ -94,6 +94,18 @@
 	status = "okay";
 };
 
+&enet1 {
+	status = "okay";
+	phy = <&enet1phy>;
+	phy-mode = "mii";
+
+	enet1phy: fixed-link {
+		reg = <1>;
+		speed = <100>;
+		full-duplex;
+	};
+};
+
 &gpio0 {
 	status = "okay";
 };
configs/huawei_hg556a_ram_defconfig +7 -1
index 7f7f34ed61..c7c7c6554f 100644
@@ -26,11 +26,14 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FPGA is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
-# CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
+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
@@ -38,6 +41,9 @@ CONFIG_LED_GPIO=y
 CONFIG_MTD=y
 CONFIG_MTD_NOR_FLASH=y
 CONFIG_CFI_FLASH=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
Signature · 1 line
2.11.0
#105 lore raw

PATCH v5 15/15 bmips: enable nb4-ser enet support

In reply to Álvaro Fernández Rojas

---
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(-)
arch/mips/dts/sfr,nb4-ser.dts +24 -0
index 473372faa1..73db45f9ea 100644
@@ -54,6 +54,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";
 };
configs/sfr_nb4-ser_ram_defconfig +7 -1
index fc323d879d..07b49a1a77 100644
@@ -27,11 +27,14 @@ CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FPGA is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_USB=y
-# CONFIG_CMD_NET is not set
 # CONFIG_CMD_NFS is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_OF_EMBED=y
+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_LED_GPIO=y
 CONFIG_MTD=y
 CONFIG_MTD_NOR_FLASH=y
 CONFIG_CFI_FLASH=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
Signature · 1 line
2.11.0