[U-Boot] [PATCH v2 0/6] add dma uclass implementation and adopt ti-edma3 to it

this patch series enables adds support for dma driver model and to adopt driver model. this has been tested on am437x-sk evms (logs [1]). also pushed a branch for testing [2]
[1]: http://pastebin.ubuntu.com/14167595/ [2]: git://git.ti.com/~mugunthanvnm/ti-u-boot/mugunth-ti-u-boot.git dm-dma-v2
changes from initial->v2: * changed config_dm_dma to config_dma. * removed un-wanted enums. * added dma_get_device(). * removed post_bind in uclass driver and added device_probe in dma_get_device()
Mugunthan V N (6): dm: implement a DMA uclass dma: Kconfig: Add TI_EDMA3 entry sf: spi_flash: use dma to copy data from mmap region if platform supports spi: ti_qspi: compile out spi_flash_copy_mmap when CONFIG_DMA is defined drivers: dma: ti-edma3: convert driver to adopt driver model defconfig: am437x_sk_evm: enable dma driver model
configs/am437x_sk_evm_defconfig | 1 + drivers/dma/Kconfig | 22 +++++++++++ drivers/dma/Makefile | 2 + drivers/dma/dma-uclass.c | 78 +++++++++++++++++++++++++++++++++++++++ drivers/dma/ti-edma3.c | 74 ++++++++++++++++++++++++++++++++++++- drivers/mtd/spi/spi_flash.c | 9 +++++ drivers/spi/ti_qspi.c | 2 +- include/dm/uclass-id.h | 1 + include/dma.h | 81 +++++++++++++++++++++++++++++++++++++++++ 9 files changed, 267 insertions(+), 3 deletions(-) create mode 100644 drivers/dma/dma-uclass.c create mode 100644 include/dma.h

Implement a DMA uclass so that the devices like ethernet, spi, mmc etc can offload the data transfers from/to the device and memory.
Signed-off-by: Mugunthan V N mugunthanvnm@ti.com --- drivers/dma/Kconfig | 15 +++++++++ drivers/dma/Makefile | 2 ++ drivers/dma/dma-uclass.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++ include/dm/uclass-id.h | 1 + include/dma.h | 81 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 177 insertions(+) create mode 100644 drivers/dma/dma-uclass.c create mode 100644 include/dma.h
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index e69de29..58cb6e9 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -0,0 +1,15 @@ +menu "DMA Support" + +config DMA + bool "Enable Driver Model for DMA drivers" + depends on DM + help + Enable driver model for DMA. DMA engines can do + asynchronous data transfers without involving the host + CPU. Currently, this framework can be used to offload + memory copies to and from devices like qspi, ethernet + etc Drivers provide methods to access the DMA devices + buses that is used to transfer data to and from memory. + The uclass interface is defined in include/dma.h. + +endmenu # menu "DMA Support" diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index f95fe70..39b78b2 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -5,6 +5,8 @@ # SPDX-License-Identifier: GPL-2.0+ #
+obj-$(CONFIG_DMA) += dma-uclass.o + obj-$(CONFIG_FSLDMAFEC) += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o obj-$(CONFIG_APBH_DMA) += apbh_dma.o obj-$(CONFIG_FSL_DMA) += fsl_dma.o diff --git a/drivers/dma/dma-uclass.c b/drivers/dma/dma-uclass.c new file mode 100644 index 0000000..0b3044e --- /dev/null +++ b/drivers/dma/dma-uclass.c @@ -0,0 +1,78 @@ +/* + * Direct Memory Access U-Class driver + * + * (C) Copyright 2015 + * Texas Instruments Incorporated, <www.ti.com> + * + * Author: Mugunthan V N mugunthanvnm@ti.com + * + * 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 <errno.h> + +DECLARE_GLOBAL_DATA_PTR; + +int dma_get_device(struct udevice **devp, u32 transfer_type) +{ + struct udevice *dev = NULL; + int ret; + + for (ret = uclass_find_first_device(UCLASS_DMA, &dev); dev && !ret; + ret = uclass_find_next_device(&dev)) { + struct dma_dev_priv *uc_priv; + + ret = device_probe(dev); + if (ret) { + error("device probe error\n"); + continue; + } + + uc_priv = dev_get_uclass_priv(dev); + if (uc_priv->supported & transfer_type) + break; + } + + if (!dev) { + error("No DMA device found that supports %x type\n", + transfer_type); + return -ENODEV; + } + + *devp = dev; + + return ret; +} + +int dma_memcpy(void *dst, void *src, size_t len) +{ + struct udevice *dev; + const struct dma_ops *ops; + int ret; + + ret = dma_get_device(&dev, DMA_SUPPORTS_MEM_TO_MEM); + if (ret < 0) + return ret; + + ops = device_get_ops(dev); + if (!ops->transfer) + return -ENOSYS; + + /* Invalidate the area, so no writeback into the RAM races with DMA */ + 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); +} + +UCLASS_DRIVER(dma) = { + .id = UCLASS_DMA, + .name = "dma", + .flags = DM_UC_FLAG_SEQ_ALIAS, + .per_device_auto_alloc_size = sizeof(struct dma_dev_priv), +}; diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index 27fa0b6..9f5fcae 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -30,6 +30,7 @@ enum uclass_id { UCLASS_CPU, /* CPU, typically part of an SoC */ UCLASS_CROS_EC, /* Chrome OS EC */ UCLASS_DISPLAY_PORT, /* Display port video */ + UCLASS_DMA, /* Direct Memory Access */ UCLASS_RAM, /* RAM controller */ UCLASS_ETH, /* Ethernet device */ UCLASS_GPIO, /* Bank of general-purpose I/O pins */ diff --git a/include/dma.h b/include/dma.h new file mode 100644 index 0000000..4b7016f --- /dev/null +++ b/include/dma.h @@ -0,0 +1,81 @@ +/* + * (C) Copyright 2015 + * Texas Instruments Incorporated, <www.ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _DMA_H_ +#define _DMA_H_ + +/* + * enum dma_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 { + 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) + +/* + * 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 + */ +struct dma_dev_priv { + u32 supported; +}; + +/* + * dma_get_device - get a DMA device which supports transfer + * type of transfer_type + * + * @devp - udevice pointer to return the found device + * @transfer_type - transfer type should be one/multiple of + * DMA_SUPPORTS_* + */ +int dma_get_device(struct udevice **devp, u32 transfer_type); + +/* + * 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 + */ +int dma_memcpy(void *dst, void *src, size_t len); + +#endif /* _DMA_H_ */

Hi Mugunthan,
On 23 December 2015 at 09:42, Mugunthan V N mugunthanvnm@ti.com wrote:
Implement a DMA uclass so that the devices like ethernet, spi, mmc etc can offload the data transfers from/to the device and memory.
Signed-off-by: Mugunthan V N mugunthanvnm@ti.com
drivers/dma/Kconfig | 15 +++++++++ drivers/dma/Makefile | 2 ++ drivers/dma/dma-uclass.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++ include/dm/uclass-id.h | 1 + include/dma.h | 81 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 177 insertions(+) create mode 100644 drivers/dma/dma-uclass.c create mode 100644 include/dma.h
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index e69de29..58cb6e9 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -0,0 +1,15 @@ +menu "DMA Support"
+config DMA
bool "Enable Driver Model for DMA drivers"
depends on DM
help
Enable driver model for DMA. DMA engines can do
asynchronous data transfers without involving the host
CPU. Currently, this framework can be used to offload
memory copies to and from devices like qspi, ethernet
etc Drivers provide methods to access the DMA devices
buses that is used to transfer data to and from memory.
The uclass interface is defined in include/dma.h.
+endmenu # menu "DMA Support" diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index f95fe70..39b78b2 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -5,6 +5,8 @@ # SPDX-License-Identifier: GPL-2.0+ #
+obj-$(CONFIG_DMA) += dma-uclass.o
obj-$(CONFIG_FSLDMAFEC) += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o obj-$(CONFIG_APBH_DMA) += apbh_dma.o obj-$(CONFIG_FSL_DMA) += fsl_dma.o diff --git a/drivers/dma/dma-uclass.c b/drivers/dma/dma-uclass.c new file mode 100644 index 0000000..0b3044e --- /dev/null +++ b/drivers/dma/dma-uclass.c @@ -0,0 +1,78 @@ +/*
- Direct Memory Access U-Class driver
- (C) Copyright 2015
Texas Instruments Incorporated, <www.ti.com>
- Author: Mugunthan V N mugunthanvnm@ti.com
- 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 <errno.h>
+DECLARE_GLOBAL_DATA_PTR;
+int dma_get_device(struct udevice **devp, u32 transfer_type)
nit: can you please put devp last? That's the way most of the DM code is.
+{
struct udevice *dev = NULL;
Should be able to drop the assignment.
int ret;
for (ret = uclass_find_first_device(UCLASS_DMA, &dev); dev && !ret;
ret = uclass_find_next_device(&dev)) {
struct dma_dev_priv *uc_priv;
ret = device_probe(dev);
If you are probing it anyway, why not just do:
for (ret = uclass_first_device(...) ... uclass_next_device(...) )
It does the probe for you.
if (ret) {
error("device probe error\n");
continue;
}
uc_priv = dev_get_uclass_priv(dev);
if (uc_priv->supported & transfer_type)
break;
}
if (!dev) {
error("No DMA device found that supports %x type\n",
transfer_type);
return -ENODEV;
-ENOPROTOSUPPORT?
-ENODEV means no device was found. It might be nice to distinguish between having no devices at all, and not having one that suits.
}
*devp = dev;
return ret;
+}
+int dma_memcpy(void *dst, void *src, size_t len) +{
struct udevice *dev;
const struct dma_ops *ops;
int ret;
ret = dma_get_device(&dev, DMA_SUPPORTS_MEM_TO_MEM);
if (ret < 0)
return ret;
ops = device_get_ops(dev);
if (!ops->transfer)
return -ENOSYS;
/* Invalidate the area, so no writeback into the RAM races with DMA */
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);
+}
+UCLASS_DRIVER(dma) = {
.id = UCLASS_DMA,
.name = "dma",
.flags = DM_UC_FLAG_SEQ_ALIAS,
.per_device_auto_alloc_size = sizeof(struct dma_dev_priv),
+}; diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index 27fa0b6..9f5fcae 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -30,6 +30,7 @@ enum uclass_id { UCLASS_CPU, /* CPU, typically part of an SoC */ UCLASS_CROS_EC, /* Chrome OS EC */ UCLASS_DISPLAY_PORT, /* Display port video */
UCLASS_DMA, /* Direct Memory Access */ UCLASS_RAM, /* RAM controller */ UCLASS_ETH, /* Ethernet device */ UCLASS_GPIO, /* Bank of general-purpose I/O pins */
diff --git a/include/dma.h b/include/dma.h new file mode 100644 index 0000000..4b7016f --- /dev/null +++ b/include/dma.h @@ -0,0 +1,81 @@ +/*
- (C) Copyright 2015
Texas Instruments Incorporated, <www.ti.com>
- SPDX-License-Identifier: GPL-2.0+
- */
+#ifndef _DMA_H_ +#define _DMA_H_
+/*
- enum dma_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 {
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)
+/*
- 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
Reference the DMA_SUPPORTS thing above.
- */
+struct dma_dev_priv {
u32 supported;
+};
+/*
- dma_get_device - get a DMA device which supports transfer
- type of transfer_type
- @devp - udevice pointer to return the found device
- @transfer_type - transfer type should be one/multiple of
DMA_SUPPORTS_*
@return
- */
+int dma_get_device(struct udevice **devp, u32 transfer_type);
+/*
- 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
- */
+int dma_memcpy(void *dst, void *src, size_t len);
+#endif /* _DMA_H_ */
2.7.0.rc1.5.gf3adf45
Regards, Simon

On Wednesday 06 January 2016 05:54 AM, Simon Glass wrote:
Hi Mugunthan,
On 23 December 2015 at 09:42, Mugunthan V N mugunthanvnm@ti.com wrote:
Implement a DMA uclass so that the devices like ethernet, spi, mmc etc can offload the data transfers from/to the device and memory.
Signed-off-by: Mugunthan V N mugunthanvnm@ti.com
drivers/dma/Kconfig | 15 +++++++++ drivers/dma/Makefile | 2 ++ drivers/dma/dma-uclass.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++ include/dm/uclass-id.h | 1 + include/dma.h | 81 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 177 insertions(+) create mode 100644 drivers/dma/dma-uclass.c create mode 100644 include/dma.h
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index e69de29..58cb6e9 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -0,0 +1,15 @@ +menu "DMA Support"
+config DMA
bool "Enable Driver Model for DMA drivers"
depends on DM
help
Enable driver model for DMA. DMA engines can do
asynchronous data transfers without involving the host
CPU. Currently, this framework can be used to offload
memory copies to and from devices like qspi, ethernet
etc Drivers provide methods to access the DMA devices
buses that is used to transfer data to and from memory.
The uclass interface is defined in include/dma.h.
+endmenu # menu "DMA Support" diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index f95fe70..39b78b2 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -5,6 +5,8 @@ # SPDX-License-Identifier: GPL-2.0+ #
+obj-$(CONFIG_DMA) += dma-uclass.o
obj-$(CONFIG_FSLDMAFEC) += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o obj-$(CONFIG_APBH_DMA) += apbh_dma.o obj-$(CONFIG_FSL_DMA) += fsl_dma.o diff --git a/drivers/dma/dma-uclass.c b/drivers/dma/dma-uclass.c new file mode 100644 index 0000000..0b3044e --- /dev/null +++ b/drivers/dma/dma-uclass.c @@ -0,0 +1,78 @@ +/*
- Direct Memory Access U-Class driver
- (C) Copyright 2015
Texas Instruments Incorporated, <www.ti.com>
- Author: Mugunthan V N mugunthanvnm@ti.com
- 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 <errno.h>
+DECLARE_GLOBAL_DATA_PTR;
+int dma_get_device(struct udevice **devp, u32 transfer_type)
nit: can you please put devp last? That's the way most of the DM code is.
Will fix it in v3
+{
struct udevice *dev = NULL;
Should be able to drop the assignment.
Okay
int ret;
for (ret = uclass_find_first_device(UCLASS_DMA, &dev); dev && !ret;
ret = uclass_find_next_device(&dev)) {
struct dma_dev_priv *uc_priv;
ret = device_probe(dev);
If you are probing it anyway, why not just do:
for (ret = uclass_first_device(...) ... uclass_next_device(...) )
It does the probe for you.
Okay, will simplify the code.
if (ret) {
error("device probe error\n");
continue;
}
uc_priv = dev_get_uclass_priv(dev);
if (uc_priv->supported & transfer_type)
break;
}
if (!dev) {
error("No DMA device found that supports %x type\n",
transfer_type);
return -ENODEV;
-ENOPROTOSUPPORT?
-ENODEV means no device was found. It might be nice to distinguish between having no devices at all, and not having one that suits.
Okay, will fix in next version.
}
*devp = dev;
return ret;
+}
+int dma_memcpy(void *dst, void *src, size_t len) +{
struct udevice *dev;
const struct dma_ops *ops;
int ret;
ret = dma_get_device(&dev, DMA_SUPPORTS_MEM_TO_MEM);
if (ret < 0)
return ret;
ops = device_get_ops(dev);
if (!ops->transfer)
return -ENOSYS;
/* Invalidate the area, so no writeback into the RAM races with DMA */
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);
+}
+UCLASS_DRIVER(dma) = {
.id = UCLASS_DMA,
.name = "dma",
.flags = DM_UC_FLAG_SEQ_ALIAS,
.per_device_auto_alloc_size = sizeof(struct dma_dev_priv),
+}; diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index 27fa0b6..9f5fcae 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -30,6 +30,7 @@ enum uclass_id { UCLASS_CPU, /* CPU, typically part of an SoC */ UCLASS_CROS_EC, /* Chrome OS EC */ UCLASS_DISPLAY_PORT, /* Display port video */
UCLASS_DMA, /* Direct Memory Access */ UCLASS_RAM, /* RAM controller */ UCLASS_ETH, /* Ethernet device */ UCLASS_GPIO, /* Bank of general-purpose I/O pins */
diff --git a/include/dma.h b/include/dma.h new file mode 100644 index 0000000..4b7016f --- /dev/null +++ b/include/dma.h @@ -0,0 +1,81 @@ +/*
- (C) Copyright 2015
Texas Instruments Incorporated, <www.ti.com>
- SPDX-License-Identifier: GPL-2.0+
- */
+#ifndef _DMA_H_ +#define _DMA_H_
+/*
- enum dma_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 {
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)
+/*
- 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
Reference the DMA_SUPPORTS thing above.
Okay.
- */
+struct dma_dev_priv {
u32 supported;
+};
+/*
- dma_get_device - get a DMA device which supports transfer
- type of transfer_type
- @devp - udevice pointer to return the found device
- @transfer_type - transfer type should be one/multiple of
DMA_SUPPORTS_*
@return
- */
+int dma_get_device(struct udevice **devp, u32 transfer_type);
+/*
- 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
Will add return documentation in next revision.
Regards Mugunthan V N
- */
+int dma_memcpy(void *dst, void *src, size_t len);
+#endif /* _DMA_H_ */
2.7.0.rc1.5.gf3adf45
Regards, Simon

Add TI_EDMA3 entry on Kconfig with help description.
Signed-off-by: Mugunthan V N mugunthanvnm@ti.com Reviewed-by: Simon Glass sjg@chromium.org --- drivers/dma/Kconfig | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 58cb6e9..1b92c77 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -12,4 +12,11 @@ config DMA buses that is used to transfer data to and from memory. The uclass interface is defined in include/dma.h.
+config TI_EDMA3 + bool "TI EDMA3 driver" + help + Enable the TI EDMA3 driver for DRA7xx and AM43xx evms. + This driver support data transfer between memory + regions. + endmenu # menu "DMA Support"

Add dma memcpy api to the default spi_flash_copy_mmap(), so that dma will be used to copy data when CONFIG_DMA is defined for the platform.
Signed-off-by: Mugunthan V N mugunthanvnm@ti.com Reviewed-by: Simon Glass sjg@chromium.org --- drivers/mtd/spi/spi_flash.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index f300b07..6da8bdb 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -16,6 +16,7 @@ #include <spi.h> #include <spi_flash.h> #include <linux/log2.h> +#include <dma.h>
#include "sf_internal.h"
@@ -454,8 +455,16 @@ int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, return ret; }
+/* + * TODO: remove the weak after all the other spi_flash_copy_mmap + * implementations removed from drivers + */ 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); }

When CONFIG_DMA is defined the default spi_flash_copy_mmap() can handle dma memory copy, so compile out spi_flash_copy_mmap() from ti_qspi driver when CONFIG_DMA config is defined.
Signed-off-by: Mugunthan V N mugunthanvnm@ti.com --- drivers/spi/ti_qspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/spi/ti_qspi.c b/drivers/spi/ti_qspi.c index 78d8b13..32cc07b 100644 --- a/drivers/spi/ti_qspi.c +++ b/drivers/spi/ti_qspi.c @@ -277,7 +277,7 @@ static int __ti_qspi_xfer(struct ti_qspi_priv *priv, unsigned int bitlen, }
/* TODO: control from sf layer to here through dm-spi */ -#ifdef CONFIG_TI_EDMA3 +#if defined(CONFIG_TI_EDMA3) && !defined(CONFIG_DMA) void spi_flash_copy_mmap(void *data, void *offset, size_t len) { unsigned int addr = (unsigned int) (data);

On 23 December 2015 at 09:43, Mugunthan V N mugunthanvnm@ti.com wrote:
When CONFIG_DMA is defined the default spi_flash_copy_mmap() can handle dma memory copy, so compile out spi_flash_copy_mmap() from ti_qspi driver when CONFIG_DMA config is defined.
Signed-off-by: Mugunthan V N mugunthanvnm@ti.com
drivers/spi/ti_qspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Reviewed-by: Simon Glass sjg@chromium.org

adopt ti-edma3 driver to device driver model
Signed-off-by: Mugunthan V N mugunthanvnm@ti.com --- drivers/dma/ti-edma3.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/ti-edma3.c b/drivers/dma/ti-edma3.c index d6a427f..5a46442 100644 --- a/drivers/dma/ti-edma3.c +++ b/drivers/dma/ti-edma3.c @@ -11,6 +11,9 @@
#include <asm/io.h> #include <common.h> +#include <dma.h> +#include <dm/device.h> +#include <asm/omap_common.h> #include <asm/ti-common/ti-edma3.h>
#define EDMA3_SL_BASE(slot) (0x4000 + ((slot) << 5)) @@ -31,6 +34,10 @@ #define EDMA3_QEESR 0x108c #define EDMA3_QSECR 0x1094
+struct ti_edma3_priv { + u32 base; +}; + /** * qedma3_start - start qdma on a channel * @base: base address of edma @@ -383,8 +390,8 @@ void qedma3_stop(u32 base, struct edma3_channel_config *cfg) __raw_writel(0, base + EDMA3_QCHMAP(cfg->chnum)); }
-void edma3_transfer(unsigned long edma3_base_addr, unsigned int - edma_slot_num, void *dst, void *src, size_t len) +void __edma3_transfer(unsigned long edma3_base_addr, unsigned int edma_slot_num, + void *dst, void *src, size_t len) { struct edma3_slot_config slot; struct edma3_channel_config edma_channel; @@ -460,3 +467,66 @@ void edma3_transfer(unsigned long edma3_base_addr, unsigned int qedma3_stop(edma3_base_addr, &edma_channel); } } + +#ifndef CONFIG_DMA + +void edma3_transfer(unsigned long edma3_base_addr, unsigned int edma_slot_num, + void *dst, void *src, size_t len) +{ + __edma3_transfer(edma3_base_addr, edma_slot_num, dst, src, len); +} + +#else + +static int ti_edma3_transfer(struct udevice *dev, int direction, void *dst, + void *src, size_t len) +{ + struct ti_edma3_priv *priv = dev_get_priv(dev); + + /* enable edma3 clocks */ + enable_edma3_clocks(); + + switch (direction) { + case DMA_MEM_TO_MEM: + __edma3_transfer(priv->base, 1, dst, src, len); + break; + default: + error("Transfer type not implemented in DMA driver\n"); + break; + } + + /* disable edma3 clocks */ + disable_edma3_clocks(); + + return 0; +} + +static int ti_edma3_ofdata_to_platdata(struct udevice *dev) +{ + struct ti_edma3_priv *priv = dev_get_priv(dev); + struct dma_dev_priv *uc_priv = dev_get_uclass_priv(dev); + + priv->base = dev_get_addr(dev); + uc_priv->supported = DMA_SUPPORTS_MEM_TO_MEM; + + return 0; +} + +static const struct dma_ops ti_edma3_ops = { + .transfer = ti_edma3_transfer, +}; + +static const struct udevice_id ti_edma3_ids[] = { + { .compatible = "ti,edma3" }, + { } +}; + +U_BOOT_DRIVER(ti_edma3) = { + .name = "ti_edma3", + .id = UCLASS_DMA, + .of_match = ti_edma3_ids, + .ops = &ti_edma3_ops, + .ofdata_to_platdata = ti_edma3_ofdata_to_platdata, + .priv_auto_alloc_size = sizeof(struct ti_edma3_priv), +}; +#endif /* CONFIG_DMA */

On 23 December 2015 at 09:43, Mugunthan V N mugunthanvnm@ti.com wrote:
adopt ti-edma3 driver to device driver model
Signed-off-by: Mugunthan V N mugunthanvnm@ti.com
drivers/dma/ti-edma3.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 2 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

enable dma driver model for am437x_sk_evm as ti-edma3 supports driver model
Signed-off-by: Mugunthan V N mugunthanvnm@ti.com Reviewed-by: Simon Glass sjg@chromium.org --- configs/am437x_sk_evm_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/configs/am437x_sk_evm_defconfig b/configs/am437x_sk_evm_defconfig index 8f78eeb..cd81e4a 100644 --- a/configs/am437x_sk_evm_defconfig +++ b/configs/am437x_sk_evm_defconfig @@ -21,3 +21,4 @@ CONFIG_TI_QSPI=y CONFIG_DM_SPI=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH_BAR=y +CONFIG_DMA=y
participants (2)
-
Mugunthan V N
-
Simon Glass