From mboxrd@z Thu Jan 1 00:00:00 1970 From: Mugunthan V N Date: Wed, 6 Jan 2016 12:00:25 +0530 Subject: [U-Boot] [PATCH v2 1/6] dm: implement a DMA uclass In-Reply-To: References: <1450888983-21855-1-git-send-email-mugunthanvnm@ti.com> <1450888983-21855-2-git-send-email-mugunthanvnm@ti.com> Message-ID: <568CB481.2050301@ti.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de On Wednesday 06 January 2016 05:54 AM, Simon Glass wrote: > Hi Mugunthan, > > On 23 December 2015 at 09:42, Mugunthan V N 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 >> --- >> 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, >> + * >> + * Author: Mugunthan V N >> + * >> + * SPDX-License-Identifier: GPL-2.0+ >> + */ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +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, >> + * >> + * 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 >