uboot/drivers/dma/dma-uclass.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Direct Memory Access U-Class driver
   4 *
   5 * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
   6 * Copyright (C) 2015 - 2018 Texas Instruments Incorporated <www.ti.com>
   7 * Written by Mugunthan V N <mugunthanvnm@ti.com>
   8 *
   9 * Author: Mugunthan V N <mugunthanvnm@ti.com>
  10 */
  11
  12#include <common.h>
  13#include <dm.h>
  14#include <dm/read.h>
  15#include <dma-uclass.h>
  16#include <dt-structs.h>
  17#include <errno.h>
  18
  19#ifdef CONFIG_DMA_CHANNELS
  20static inline struct dma_ops *dma_dev_ops(struct udevice *dev)
  21{
  22        return (struct dma_ops *)dev->driver->ops;
  23}
  24
  25# if CONFIG_IS_ENABLED(OF_CONTROL)
  26static int dma_of_xlate_default(struct dma *dma,
  27                                struct ofnode_phandle_args *args)
  28{
  29        debug("%s(dma=%p)\n", __func__, dma);
  30
  31        if (args->args_count > 1) {
  32                pr_err("Invaild args_count: %d\n", args->args_count);
  33                return -EINVAL;
  34        }
  35
  36        if (args->args_count)
  37                dma->id = args->args[0];
  38        else
  39                dma->id = 0;
  40
  41        return 0;
  42}
  43
  44int dma_get_by_index(struct udevice *dev, int index, struct dma *dma)
  45{
  46        int ret;
  47        struct ofnode_phandle_args args;
  48        struct udevice *dev_dma;
  49        const struct dma_ops *ops;
  50
  51        debug("%s(dev=%p, index=%d, dma=%p)\n", __func__, dev, index, dma);
  52
  53        assert(dma);
  54        dma->dev = NULL;
  55
  56        ret = dev_read_phandle_with_args(dev, "dmas", "#dma-cells", 0, index,
  57                                         &args);
  58        if (ret) {
  59                pr_err("%s: dev_read_phandle_with_args failed: err=%d\n",
  60                       __func__, ret);
  61                return ret;
  62        }
  63
  64        ret = uclass_get_device_by_ofnode(UCLASS_DMA, args.node, &dev_dma);
  65        if (ret) {
  66                pr_err("%s: uclass_get_device_by_ofnode failed: err=%d\n",
  67                       __func__, ret);
  68                return ret;
  69        }
  70
  71        dma->dev = dev_dma;
  72
  73        ops = dma_dev_ops(dev_dma);
  74
  75        if (ops->of_xlate)
  76                ret = ops->of_xlate(dma, &args);
  77        else
  78                ret = dma_of_xlate_default(dma, &args);
  79        if (ret) {
  80                pr_err("of_xlate() failed: %d\n", ret);
  81                return ret;
  82        }
  83
  84        return dma_request(dev_dma, dma);
  85}
  86
  87int dma_get_by_name(struct udevice *dev, const char *name, struct dma *dma)
  88{
  89        int index;
  90
  91        debug("%s(dev=%p, name=%s, dma=%p)\n", __func__, dev, name, dma);
  92        dma->dev = NULL;
  93
  94        index = dev_read_stringlist_search(dev, "dma-names", name);
  95        if (index < 0) {
  96                pr_err("dev_read_stringlist_search() failed: %d\n", index);
  97                return index;
  98        }
  99
 100        return dma_get_by_index(dev, index, dma);
 101}
 102# endif /* OF_CONTROL */
 103
 104int dma_request(struct udevice *dev, struct dma *dma)
 105{
 106        struct dma_ops *ops = dma_dev_ops(dev);
 107
 108        debug("%s(dev=%p, dma=%p)\n", __func__, dev, dma);
 109
 110        dma->dev = dev;
 111
 112        if (!ops->request)
 113                return 0;
 114
 115        return ops->request(dma);
 116}
 117
 118int dma_free(struct dma *dma)
 119{
 120        struct dma_ops *ops = dma_dev_ops(dma->dev);
 121
 122        debug("%s(dma=%p)\n", __func__, dma);
 123
 124        if (!ops->free)
 125                return 0;
 126
 127        return ops->free(dma);
 128}
 129
 130int dma_enable(struct dma *dma)
 131{
 132        struct dma_ops *ops = dma_dev_ops(dma->dev);
 133
 134        debug("%s(dma=%p)\n", __func__, dma);
 135
 136        if (!ops->enable)
 137                return -ENOSYS;
 138
 139        return ops->enable(dma);
 140}
 141
 142int dma_disable(struct dma *dma)
 143{
 144        struct dma_ops *ops = dma_dev_ops(dma->dev);
 145
 146        debug("%s(dma=%p)\n", __func__, dma);
 147
 148        if (!ops->disable)
 149                return -ENOSYS;
 150
 151        return ops->disable(dma);
 152}
 153
 154int dma_prepare_rcv_buf(struct dma *dma, void *dst, size_t size)
 155{
 156        struct dma_ops *ops = dma_dev_ops(dma->dev);
 157
 158        debug("%s(dma=%p)\n", __func__, dma);
 159
 160        if (!ops->prepare_rcv_buf)
 161                return -1;
 162
 163        return ops->prepare_rcv_buf(dma, dst, size);
 164}
 165
 166int dma_receive(struct dma *dma, void **dst, void *metadata)
 167{
 168        struct dma_ops *ops = dma_dev_ops(dma->dev);
 169
 170        debug("%s(dma=%p)\n", __func__, dma);
 171
 172        if (!ops->receive)
 173                return -ENOSYS;
 174
 175        return ops->receive(dma, dst, metadata);
 176}
 177
 178int dma_send(struct dma *dma, void *src, size_t len, void *metadata)
 179{
 180        struct dma_ops *ops = dma_dev_ops(dma->dev);
 181
 182        debug("%s(dma=%p)\n", __func__, dma);
 183
 184        if (!ops->send)
 185                return -ENOSYS;
 186
 187        return ops->send(dma, src, len, metadata);
 188}
 189#endif /* CONFIG_DMA_CHANNELS */
 190
 191int dma_get_device(u32 transfer_type, struct udevice **devp)
 192{
 193        struct udevice *dev;
 194        int ret;
 195
 196        for (ret = uclass_first_device(UCLASS_DMA, &dev); dev && !ret;
 197             ret = uclass_next_device(&dev)) {
 198                struct dma_dev_priv *uc_priv;
 199
 200                uc_priv = dev_get_uclass_priv(dev);
 201                if (uc_priv->supported & transfer_type)
 202                        break;
 203        }
 204
 205        if (!dev) {
 206                pr_err("No DMA device found that supports %x type\n",
 207                      transfer_type);
 208                return -EPROTONOSUPPORT;
 209        }
 210
 211        *devp = dev;
 212
 213        return ret;
 214}
 215
 216int dma_memcpy(void *dst, void *src, size_t len)
 217{
 218        struct udevice *dev;
 219        const struct dma_ops *ops;
 220        int ret;
 221
 222        ret = dma_get_device(DMA_SUPPORTS_MEM_TO_MEM, &dev);
 223        if (ret < 0)
 224                return ret;
 225
 226        ops = device_get_ops(dev);
 227        if (!ops->transfer)
 228                return -ENOSYS;
 229
 230        /* Invalidate the area, so no writeback into the RAM races with DMA */
 231        invalidate_dcache_range((unsigned long)dst, (unsigned long)dst +
 232                                roundup(len, ARCH_DMA_MINALIGN));
 233
 234        return ops->transfer(dev, DMA_MEM_TO_MEM, dst, src, len);
 235}
 236
 237UCLASS_DRIVER(dma) = {
 238        .id             = UCLASS_DMA,
 239        .name           = "dma",
 240        .flags          = DM_UC_FLAG_SEQ_ALIAS,
 241        .per_device_auto_alloc_size = sizeof(struct dma_dev_priv),
 242};
 243