From mboxrd@z Thu Jan 1 00:00:00 1970 From: Mugunthan V N Date: Wed, 2 Dec 2015 13:47:36 +0530 Subject: [U-Boot] [PATCH 1/6] dm: implement a DMA uclass In-Reply-To: References: <1448968398-8270-1-git-send-email-mugunthanvnm@ti.com> <1448968398-8270-2-git-send-email-mugunthanvnm@ti.com> Message-ID: <565EA920.9000405@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 02 December 2015 03:24 AM, Simon Glass wrote: > Hi Mugunthan, > > On 1 December 2015 at 04:13, 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 | 63 +++++++++++++++++++++++++++++++++++++++++++++++ >> include/dm/uclass-id.h | 1 + >> include/dma.h | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ >> 5 files changed, 145 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..af15199 100644 >> --- a/drivers/dma/Kconfig >> +++ b/drivers/dma/Kconfig >> @@ -0,0 +1,15 @@ >> +menu "DMA Support" >> + >> +config DM_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..4ff22aa 100644 >> --- a/drivers/dma/Makefile >> +++ b/drivers/dma/Makefile >> @@ -5,6 +5,8 @@ >> # SPDX-License-Identifier: GPL-2.0+ >> # >> >> +obj-$(CONFIG_DM_DMA) += dma-uclass.o > > You can just use CONFIG_DMA. The DM_ prefix is for when we have an > existing pre-DM interface. Eventually all the CONFIG_DM_... options > will be removed. Unless you have a special reason? For consistency I used CONFIG_DM_DMA, will rename it to CONFIG_DMA. > >> + >> 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..1afcbaa4 >> --- /dev/null >> +++ b/drivers/dma/dma-uclass.c >> @@ -0,0 +1,63 @@ >> +/* >> + * 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 >> + >> +DECLARE_GLOBAL_DATA_PTR; >> + >> +int dma_memcpy(void *dst, void *src, size_t len) >> +{ >> + struct udevice *dev; >> + const struct dma_ops *ops; >> + 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 = dev_get_uclass_priv(dev); >> + >> + if (uc_priv->supported & SUPPORTS_MEM_TO_MEM) >> + break; >> + } >> + >> + if (!dev) { >> + printf("No DMA device found that supports mem to mem transfers\n"); >> + return -ENODEV; >> + } > > Can you put the above code in a separate function like: > > static int get_dma_device(struct udevice **devp) > > also also please call device_probe() on it before returning it. Okay, will do it in next version. > >> + >> + 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); >> +} >> + >> +int dma_post_bind(struct udevice *dev) >> +{ >> + struct udevice *devp; >> + uclass_get_device_by_of_offset(UCLASS_DMA, dev->of_offset, &devp); > > You are not allowed to do this in the post_bind() method. See above > for how it should get probed. > Okay, agreed. >> + return 0; >> +} >> + >> +UCLASS_DRIVER(dma) = { >> + .id = UCLASS_DMA, >> + .name = "dma", >> + .flags = DM_UC_FLAG_SEQ_ALIAS, >> + .per_device_auto_alloc_size = sizeof(struct dma_dev_priv), >> + .post_bind = dma_post_bind, >> +}; >> 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..d53e435 >> --- /dev/null >> +++ b/include/dma.h >> @@ -0,0 +1,64 @@ >> +/* >> + * (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, >> + DMA_TRANS_NONE, > > What does that mean? DMA driver will be having only one transfer api and to identify what kind of transfer that the user driver is expecting, these enums are used. > >> +}; >> + >> +#define SUPPORTS_MEM_TO_MEM BIT(0) >> +#define SUPPORTS_MEM_TO_DEV BIT(1) >> +#define SUPPORTS_DEV_TO_MEM BIT(2) >> +#define SUPPORTS_DEV_TO_DEV BIT(3) > > DMA_ prefix on these. Also you could put them in an enum so they are grouped. Will add DMA prefix to these defines. Since a dma driver can support multiple transfer types I kept this as bit level definitions, so that driver can intimate DMA framework like uc_priv->supported = SUPPORTS_MEM_TO_MEM | SUPPORTS_MEM_TO_DEV; > >> + >> +/* >> + * 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 > > Incorrect comment. > >> + * >> + * @dev: The DMA device >> + * @direction: direction of data transfer should be one from >> + enum dma_direction >> + * @dst: Destination pointer >> + * @src: Source pointer > > Any alignment restructions? I should be aligned to DMA device alignment restrictions. > >> + * @len: Length of the data to be copied. > > In bytes? Okay > >> + * @return: 0 if OK, -ve on error >> + */ >> + int (*transfer)(struct udevice *dev, int direction, void *dst, > > s/int direction/enum dma_direction direction/ Okay > >> + 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 > > Please reference where these flags come from. Okay > >> + */ >> +struct dma_dev_priv { >> + unsigned long supported; > > int or uint should be enough. Will used uint. > >> +}; >> + >> +int dma_memcpy(void *dst, void *src, size_t len); >> + >> +#endif /* _DMA_H_ */ >> -- >> 2.6.3.368.gf34be46 >> > > Regards, > Simon > Regards Mugunthan V N