commit
b625fab706
@ -0,0 +1,22 @@ |
||||
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. |
||||
|
||||
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" |
@ -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), |
||||
}; |
@ -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