mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 15:14:43 +00:00
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
5 changed files with 176 additions and 0 deletions
|
@ -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+
|
||||
#
|
||||
|
||||
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
|
||||
|
|
72
drivers/dma/dma-uclass.c
Normal file
72
drivers/dma/dma-uclass.c
Normal file
|
@ -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_DISK, /* Disk controller, e.g. SATA */
|
||||
UCLASS_DISPLAY, /* Display (e.g. DisplayPort, HDMI) */
|
||||
UCLASS_DMA, /* Direct Memory Access */
|
||||
UCLASS_RAM, /* RAM controller */
|
||||
UCLASS_ETH, /* Ethernet device */
|
||||
UCLASS_GPIO, /* Bank of general-purpose I/O pins */
|
||||
|
|
86
include/dma.h
Normal file
86
include/dma.h
Normal file
|
@ -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 a new issue