dm: implement a DMA uclass
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> Reviewed-by: Simon Glass <sjg@chromium.org> Reviewed-by: Jagan Teki <jteki@openedev.com>
This commit is contained in:
parent
18c61e9571
commit
a0594cefb7
|
@ -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"
|
|
@ -5,6 +5,8 @@
|
||||||
# SPDX-License-Identifier: GPL-2.0+
|
# 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_FSLDMAFEC) += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o
|
||||||
obj-$(CONFIG_APBH_DMA) += apbh_dma.o
|
obj-$(CONFIG_APBH_DMA) += apbh_dma.o
|
||||||
obj-$(CONFIG_FSL_DMA) += fsl_dma.o
|
obj-$(CONFIG_FSL_DMA) += fsl_dma.o
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* 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(u32 transfer_type, struct udevice **devp)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
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 -EPROTONOSUPPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
*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(DMA_SUPPORTS_MEM_TO_MEM, &dev);
|
||||||
|
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),
|
||||||
|
};
|
|
@ -31,6 +31,7 @@ enum uclass_id {
|
||||||
UCLASS_CROS_EC, /* Chrome OS EC */
|
UCLASS_CROS_EC, /* Chrome OS EC */
|
||||||
UCLASS_DISK, /* Disk controller, e.g. SATA */
|
UCLASS_DISK, /* Disk controller, e.g. SATA */
|
||||||
UCLASS_DISPLAY, /* Display (e.g. DisplayPort, HDMI) */
|
UCLASS_DISPLAY, /* Display (e.g. DisplayPort, HDMI) */
|
||||||
|
UCLASS_DMA, /* Direct Memory Access */
|
||||||
UCLASS_RAM, /* RAM controller */
|
UCLASS_RAM, /* RAM controller */
|
||||||
UCLASS_ETH, /* Ethernet device */
|
UCLASS_ETH, /* Ethernet device */
|
||||||
UCLASS_GPIO, /* Bank of general-purpose I/O pins */
|
UCLASS_GPIO, /* Bank of general-purpose I/O pins */
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* (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, should be
|
||||||
|
* one/multiple of DMA_SUPPORTS_*
|
||||||
|
*/
|
||||||
|
struct dma_dev_priv {
|
||||||
|
u32 supported;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
int dma_get_device(u32 transfer_type, struct udevice **devp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
int dma_memcpy(void *dst, void *src, size_t len);
|
||||||
|
|
||||||
|
#endif /* _DMA_H_ */
|
Loading…
Reference in New Issue