1 // SPDX-License-Identifier: GPL-2.0+
3 * Direct Memory Access U-Class Simulation driver
5 * Copyright (C) 2018 Texas Instruments Incorporated <www.ti.com>
15 #include <dma-uclass.h>
16 #include <dt-structs.h>
19 #define SANDBOX_DMA_CH_CNT 3
20 #define SANDBOX_DMA_BUF_SIZE 1024
22 struct sandbox_dma_chan {
23 struct sandbox_dma_dev *ud;
26 enum dma_direction dir;
31 struct sandbox_dma_dev {
34 struct sandbox_dma_chan channels[SANDBOX_DMA_CH_CNT];
35 uchar buf[SANDBOX_DMA_BUF_SIZE];
41 static int sandbox_dma_transfer(struct udevice *dev, int direction,
42 void *dst, void *src, size_t len)
44 memcpy(dst, src, len);
49 static int sandbox_dma_of_xlate(struct dma *dma,
50 struct ofnode_phandle_args *args)
52 struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
53 struct sandbox_dma_chan *uc;
55 debug("%s(dma id=%u)\n", __func__, args->args[0]);
57 if (args->args[0] >= SANDBOX_DMA_CH_CNT)
60 dma->id = args->args[0];
62 uc = &ud->channels[dma->id];
65 uc->dir = DMA_MEM_TO_DEV;
66 else if (dma->id == 2)
67 uc->dir = DMA_DEV_TO_MEM;
69 uc->dir = DMA_MEM_TO_MEM;
70 debug("%s(dma id=%lu dir=%d)\n", __func__, dma->id, uc->dir);
75 static int sandbox_dma_request(struct dma *dma)
77 struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
78 struct sandbox_dma_chan *uc;
80 if (dma->id >= SANDBOX_DMA_CH_CNT)
83 uc = &ud->channels[dma->id];
88 debug("%s(dma id=%lu in_use=%d)\n", __func__, dma->id, uc->in_use);
93 static int sandbox_dma_rfree(struct dma *dma)
95 struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
96 struct sandbox_dma_chan *uc;
98 if (dma->id >= SANDBOX_DMA_CH_CNT)
101 uc = &ud->channels[dma->id];
108 debug("%s(dma id=%lu in_use=%d)\n", __func__, dma->id, uc->in_use);
113 static int sandbox_dma_enable(struct dma *dma)
115 struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
116 struct sandbox_dma_chan *uc;
118 if (dma->id >= SANDBOX_DMA_CH_CNT)
121 uc = &ud->channels[dma->id];
128 debug("%s(dma id=%lu enabled=%d)\n", __func__, dma->id, uc->enabled);
133 static int sandbox_dma_disable(struct dma *dma)
135 struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
136 struct sandbox_dma_chan *uc;
138 if (dma->id >= SANDBOX_DMA_CH_CNT)
141 uc = &ud->channels[dma->id];
148 debug("%s(dma id=%lu enabled=%d)\n", __func__, dma->id, uc->enabled);
153 static int sandbox_dma_send(struct dma *dma,
154 void *src, size_t len, void *metadata)
156 struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
157 struct sandbox_dma_chan *uc;
159 if (dma->id >= SANDBOX_DMA_CH_CNT)
161 if (!src || !metadata)
164 debug("%s(dma id=%lu)\n", __func__, dma->id);
166 uc = &ud->channels[dma->id];
167 if (uc->dir != DMA_MEM_TO_DEV)
173 if (len >= SANDBOX_DMA_BUF_SIZE)
176 memcpy(ud->buf, src, len);
178 ud->meta = *((u32 *)metadata);
180 debug("%s(dma id=%lu len=%zu meta=%08x)\n",
181 __func__, dma->id, len, ud->meta);
186 static int sandbox_dma_receive(struct dma *dma, void **dst, void *metadata)
188 struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
189 struct sandbox_dma_chan *uc;
191 if (dma->id >= SANDBOX_DMA_CH_CNT)
193 if (!dst || !metadata)
196 uc = &ud->channels[dma->id];
197 if (uc->dir != DMA_DEV_TO_MEM)
207 memcpy(ud->buf_rx, ud->buf, ud->data_len);
210 memcpy(*dst, ud->buf, ud->data_len);
213 *((u32 *)metadata) = ud->meta;
215 debug("%s(dma id=%lu len=%zu meta=%08x %p)\n",
216 __func__, dma->id, ud->data_len, ud->meta, *dst);
221 static int sandbox_dma_prepare_rcv_buf(struct dma *dma, void *dst, size_t size)
223 struct sandbox_dma_dev *ud = dev_get_priv(dma->dev);
230 static const struct dma_ops sandbox_dma_ops = {
231 .transfer = sandbox_dma_transfer,
232 .of_xlate = sandbox_dma_of_xlate,
233 .request = sandbox_dma_request,
234 .rfree = sandbox_dma_rfree,
235 .enable = sandbox_dma_enable,
236 .disable = sandbox_dma_disable,
237 .send = sandbox_dma_send,
238 .receive = sandbox_dma_receive,
239 .prepare_rcv_buf = sandbox_dma_prepare_rcv_buf,
242 static int sandbox_dma_probe(struct udevice *dev)
244 struct dma_dev_priv *uc_priv = dev_get_uclass_priv(dev);
245 struct sandbox_dma_dev *ud = dev_get_priv(dev);
248 uc_priv->supported = DMA_SUPPORTS_MEM_TO_MEM |
249 DMA_SUPPORTS_MEM_TO_DEV |
250 DMA_SUPPORTS_DEV_TO_MEM;
252 ud->ch_count = SANDBOX_DMA_CH_CNT;
257 pr_err("Number of channels: %u\n", ud->ch_count);
259 for (i = 0; i < ud->ch_count; i++) {
260 struct sandbox_dma_chan *uc = &ud->channels[i];
264 sprintf(uc->name, "DMA chan%d\n", i);
272 static const struct udevice_id sandbox_dma_ids[] = {
273 { .compatible = "sandbox,dma" },
277 U_BOOT_DRIVER(sandbox_dma) = {
278 .name = "sandbox-dma",
280 .of_match = sandbox_dma_ids,
281 .ops = &sandbox_dma_ops,
282 .probe = sandbox_dma_probe,
283 .priv_auto = sizeof(struct sandbox_dma_dev),