Re: [U-Boot] [RFC 01/14] dma: add dma channels support and improve uclass

2018-02-20 Thread Vignesh R
Please add a commit message as this is a pretty big change providing a
overview what is being added and why?

On Monday 12 February 2018 10:08 PM, Álvaro Fernández Rojas wrote:
> Signed-off-by: Álvaro Fernández Rojas 
> ---
>  drivers/dma/dma-uclass.c| 212 ++---


This patch definitely breaks drivers/dma/ti-edma3.c which implements
current definition of dma-uclass.

One of the assumption of current dma_memcpy() implementation is that the
client's DT node need not have "dmas" entry to specify which DMA
provider and DMA channel to use for dma memcpy. (This is true in linux
kernel as well). Most DMA HWs have general purpose channels that are not
tied to any peripherals and can be used for mem to mem transfers.
So, if the client device's DT node does not populate "dmas" property
then dma_memcpy() API should try to find a DMA provider that supports
memcpy operation, request a memcpy capable channel from the provider and
use it to transfer data. Please keep the current behavior as is.
Or, provide a API for clients to request such a channel.

>  drivers/mtd/spi/sf-uclass.c |  17 
>  drivers/mtd/spi/spi_flash.c |  11 ++-
>  include/dma-uclass.h| 110 +
>  include/dma.h   | 226 
> +---
>  include/spi_flash.h |   3 +
>  6 files changed, 485 insertions(+), 94 deletions(-)
>  create mode 100644 include/dma-uclass.h
> 
> diff --git a/drivers/dma/dma-uclass.c b/drivers/dma/dma-uclass.c
> index 3d0ce22fbc..7d04d98493 100644
> --- a/drivers/dma/dma-uclass.c
> +++ b/drivers/dma/dma-uclass.c
> @@ -1,59 +1,176 @@
>  /*
> - * Direct Memory Access U-Class driver
> + * Copyright (C) 2018 Álvaro Fernández Rojas 
> + * Copyright (C) 2015 Texas Instruments Incorporated, 
> + * Written by Mugunthan V N 
>   *
> - * (C) Copyright 2015
> - * Texas Instruments Incorporated, 
> - *
> - * Author: Mugunthan V N 
> - *
> - * SPDX-License-Identifier: GPL-2.0+
> + * SPDX-License-Identifier:  GPL-2.0+
>   */
>  
>  #include 
> -#include 
>  #include 
> -#include 
> -#include 
> +#include 
> +#include 
> +#include 
>  #include 
>  
>  DECLARE_GLOBAL_DATA_PTR;
>  
> -int dma_get_device(u32 transfer_type, struct udevice **devp)
> +static inline struct dma_ops *dma_dev_ops(struct udevice *dev)
> +{
> + return (struct dma_ops *)dev->driver->ops;
> +}
> +
> +#if CONFIG_IS_ENABLED(OF_CONTROL)
> +# if CONFIG_IS_ENABLED(OF_PLATDATA)
> +int dma_get_by_index_platdata(struct udevice *dev, int index,
> +   struct phandle_2_cell *cells, struct dma *dma)
>  {
> - 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;
> + if (index != 0)
> + return -ENOSYS;
> + ret = uclass_get_device(UCLASS_DMA, 0, &dma->dev);
> + if (ret)
> + return ret;
> + dma->id = cells[0].id;
>  
> - uc_priv = dev_get_uclass_priv(dev);
> - if (uc_priv->supported & transfer_type)
> - break;
> - }
> + return 0;
> +}
> +# else
> +static int dma_of_xlate_default(struct dma *dma,
> + struct fdtdec_phandle_args *args)
> +{
> + debug("%s(dma=%p)\n", __func__, dma);
>  
> - if (!dev) {
> - pr_err("No DMA device found that supports %x type\n",
> -   transfer_type);
> - return -EPROTONOSUPPORT;
> + if (args->args_count > 1) {
> + pr_err("Invaild args_count: %d\n", args->args_count);
> + return -EINVAL;
>   }
>  
> - *devp = dev;
> + if (args->args_count)
> + dma->id = args->args[0];
> + else
> + dma->id = 0;
>  
> - return ret;
> + return 0;
>  }
>  
> -int dma_memcpy(void *dst, void *src, size_t len)
> +int dma_get_by_index(struct udevice *dev, int index, struct dma *dma)
>  {
> - struct udevice *dev;
> - const struct dma_ops *ops;
>   int ret;
> + struct fdtdec_phandle_args args;
> + struct udevice *dev_dma;
> + struct dma_ops *ops;
> +
> + debug("%s(dev=%p, index=%d, dma=%p)\n", __func__, dev, index, dma);
>  
> - ret = dma_get_device(DMA_SUPPORTS_MEM_TO_MEM, &dev);
> - if (ret < 0)
> + assert(dma);
> + ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev),
> +  "dmas", "#dma-cells", 0, index,
> +  &args);
> + if (ret) {
> + pr_err("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
> +   __func__, ret);
>   return ret;
> + }
> +
> + ret = uclass_get_device_by_of_offset(UCLASS_DMA, args.node, &dev_dma);
> + if (ret) {
> + pr_err("%s: uclass_get_device_by_of_offset failed: err=%d\n",
> +   __func__, ret);
> + 

[U-Boot] [RFC 01/14] dma: add dma channels support and improve uclass

2018-02-12 Thread Álvaro Fernández Rojas
Signed-off-by: Álvaro Fernández Rojas 
---
 drivers/dma/dma-uclass.c| 212 ++---
 drivers/mtd/spi/sf-uclass.c |  17 
 drivers/mtd/spi/spi_flash.c |  11 ++-
 include/dma-uclass.h| 110 +
 include/dma.h   | 226 +---
 include/spi_flash.h |   3 +
 6 files changed, 485 insertions(+), 94 deletions(-)
 create mode 100644 include/dma-uclass.h

diff --git a/drivers/dma/dma-uclass.c b/drivers/dma/dma-uclass.c
index 3d0ce22fbc..7d04d98493 100644
--- a/drivers/dma/dma-uclass.c
+++ b/drivers/dma/dma-uclass.c
@@ -1,59 +1,176 @@
 /*
- * Direct Memory Access U-Class driver
+ * Copyright (C) 2018 Álvaro Fernández Rojas 
+ * Copyright (C) 2015 Texas Instruments Incorporated, 
+ * Written by Mugunthan V N 
  *
- * (C) Copyright 2015
- * Texas Instruments Incorporated, 
- *
- * Author: Mugunthan V N 
- *
- * SPDX-License-Identifier: GPL-2.0+
+ * SPDX-License-Identifier:GPL-2.0+
  */
 
 #include 
-#include 
 #include 
-#include 
-#include 
+#include 
+#include 
+#include 
 #include 
 
 DECLARE_GLOBAL_DATA_PTR;
 
-int dma_get_device(u32 transfer_type, struct udevice **devp)
+static inline struct dma_ops *dma_dev_ops(struct udevice *dev)
+{
+   return (struct dma_ops *)dev->driver->ops;
+}
+
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+# if CONFIG_IS_ENABLED(OF_PLATDATA)
+int dma_get_by_index_platdata(struct udevice *dev, int index,
+ struct phandle_2_cell *cells, struct dma *dma)
 {
-   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;
+   if (index != 0)
+   return -ENOSYS;
+   ret = uclass_get_device(UCLASS_DMA, 0, &dma->dev);
+   if (ret)
+   return ret;
+   dma->id = cells[0].id;
 
-   uc_priv = dev_get_uclass_priv(dev);
-   if (uc_priv->supported & transfer_type)
-   break;
-   }
+   return 0;
+}
+# else
+static int dma_of_xlate_default(struct dma *dma,
+   struct fdtdec_phandle_args *args)
+{
+   debug("%s(dma=%p)\n", __func__, dma);
 
-   if (!dev) {
-   pr_err("No DMA device found that supports %x type\n",
- transfer_type);
-   return -EPROTONOSUPPORT;
+   if (args->args_count > 1) {
+   pr_err("Invaild args_count: %d\n", args->args_count);
+   return -EINVAL;
}
 
-   *devp = dev;
+   if (args->args_count)
+   dma->id = args->args[0];
+   else
+   dma->id = 0;
 
-   return ret;
+   return 0;
 }
 
-int dma_memcpy(void *dst, void *src, size_t len)
+int dma_get_by_index(struct udevice *dev, int index, struct dma *dma)
 {
-   struct udevice *dev;
-   const struct dma_ops *ops;
int ret;
+   struct fdtdec_phandle_args args;
+   struct udevice *dev_dma;
+   struct dma_ops *ops;
+
+   debug("%s(dev=%p, index=%d, dma=%p)\n", __func__, dev, index, dma);
 
-   ret = dma_get_device(DMA_SUPPORTS_MEM_TO_MEM, &dev);
-   if (ret < 0)
+   assert(dma);
+   ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev),
+"dmas", "#dma-cells", 0, index,
+&args);
+   if (ret) {
+   pr_err("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
+ __func__, ret);
return ret;
+   }
+
+   ret = uclass_get_device_by_of_offset(UCLASS_DMA, args.node, &dev_dma);
+   if (ret) {
+   pr_err("%s: uclass_get_device_by_of_offset failed: err=%d\n",
+ __func__, ret);
+   return ret;
+   }
+
+   dma->dev = dev_dma;
+
+   ops = dma_dev_ops(dev_dma);
+
+   if (ops->of_xlate)
+   ret = ops->of_xlate(dma, &args);
+   else
+   ret = dma_of_xlate_default(dma, &args);
+   if (ret) {
+   pr_err("of_xlate() failed: %d\n", ret);
+   return ret;
+   }
+
+   return dma_request(dev_dma, dma);
+}
+# endif /* OF_PLATDATA */
+
+int dma_get_by_name(struct udevice *dev, const char *name, struct dma *dma)
+{
+   int index;
+
+   debug("%s(dev=%p, name=%s, dma=%p)\n", __func__, dev, name, dma);
+
+   index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev),
+ "dma-names", name);
+   if (index < 0) {
+   pr_err("fdt_stringlist_search() failed: %d\n", index);
+   return index;
+   }
+
+   return dma_get_by_index(dev, index, dma);
+}
+#endif /* OF_CONTROL */
+
+int dma_request(struct udevice *dev, struct dma *dma)
+{
+   struct dma_ops *ops = dma_dev_ops(dev);
+
+   debug("%s(dev=%p, dma=%p)\n",