Skip to content

Commit bb18e35

Browse files
committed
[DM/DMA] Update DMA Engine
1. Add address mask for DMA 2. Change DMA lock to mutex 3. Add pause callback for DMA engine driver Signed-off-by: GuEe-GUI <[email protected]>
1 parent 6ea8e75 commit bb18e35

File tree

2 files changed

+128
-17
lines changed

2 files changed

+128
-17
lines changed

components/drivers/dma/dma.c

Lines changed: 116 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,22 @@
1919
static rt_list_t dmac_nodes = RT_LIST_OBJECT_INIT(dmac_nodes);
2020
static RT_DEFINE_SPINLOCK(dmac_nodes_lock);
2121

22+
static void dma_lock(struct rt_dma_controller *ctrl)
23+
{
24+
if (rt_thread_self())
25+
{
26+
rt_mutex_take(&ctrl->mutex, RT_WAITING_FOREVER);
27+
}
28+
}
29+
30+
static void dma_unlock(struct rt_dma_controller *ctrl)
31+
{
32+
if (rt_thread_self())
33+
{
34+
rt_mutex_release(&ctrl->mutex);
35+
}
36+
}
37+
2238
rt_err_t rt_dma_controller_register(struct rt_dma_controller *ctrl)
2339
{
2440
const char *dev_name;
@@ -64,11 +80,11 @@ rt_err_t rt_dma_controller_unregister(struct rt_dma_controller *ctrl)
6480
return -RT_EINVAL;
6581
}
6682

67-
rt_mutex_take(&ctrl->mutex, RT_WAITING_FOREVER);
83+
dma_lock(ctrl);
6884

6985
if (!rt_list_isempty(&ctrl->channels_nodes))
7086
{
71-
rt_mutex_release(&ctrl->mutex);
87+
dma_unlock(ctrl);
7288
return -RT_EBUSY;
7389
}
7490

@@ -77,7 +93,7 @@ rt_err_t rt_dma_controller_unregister(struct rt_dma_controller *ctrl)
7793
rt_dm_dev_unbind_fwdata(ctrl->dev, RT_NULL);
7894
}
7995

80-
rt_mutex_release(&ctrl->mutex);
96+
dma_unlock(ctrl);
8197
rt_mutex_detach(&ctrl->mutex);
8298

8399
rt_spin_lock(&dmac_nodes_lock);
@@ -106,11 +122,45 @@ rt_err_t rt_dma_chan_start(struct rt_dma_chan *chan)
106122

107123
ctrl = chan->ctrl;
108124

109-
rt_mutex_take(&ctrl->mutex, RT_WAITING_FOREVER);
125+
dma_lock(ctrl);
110126

111127
err = ctrl->ops->start(chan);
112128

113-
rt_mutex_release(&ctrl->mutex);
129+
dma_unlock(ctrl);
130+
131+
return err;
132+
}
133+
134+
rt_err_t rt_dma_chan_pause(struct rt_dma_chan *chan)
135+
{
136+
rt_err_t err;
137+
struct rt_dma_controller *ctrl;
138+
139+
if (!chan)
140+
{
141+
return -RT_EINVAL;
142+
}
143+
144+
if (!chan->ctrl->ops->pause)
145+
{
146+
LOG_D("%s: No pause, try stop", rt_dm_dev_get_name(chan->ctrl->dev));
147+
return rt_dma_chan_stop(chan);
148+
}
149+
150+
if (chan->prep_err)
151+
{
152+
LOG_D("%s: Not config done", rt_dm_dev_get_name(chan->slave));
153+
154+
return chan->prep_err;
155+
}
156+
157+
ctrl = chan->ctrl;
158+
159+
dma_lock(ctrl);
160+
161+
err = ctrl->ops->pause(chan);
162+
163+
dma_unlock(ctrl);
114164

115165
return err;
116166
}
@@ -134,11 +184,11 @@ rt_err_t rt_dma_chan_stop(struct rt_dma_chan *chan)
134184

135185
ctrl = chan->ctrl;
136186

137-
rt_mutex_take(&ctrl->mutex, RT_WAITING_FOREVER);
187+
dma_lock(ctrl);
138188

139189
err = ctrl->ops->stop(chan);
140190

141-
rt_mutex_release(&ctrl->mutex);
191+
dma_unlock(ctrl);
142192

143193
return err;
144194
}
@@ -188,11 +238,11 @@ rt_err_t rt_dma_chan_config(struct rt_dma_chan *chan,
188238
goto _end;
189239
}
190240

191-
rt_mutex_take(&ctrl->mutex, RT_WAITING_FOREVER);
241+
dma_lock(ctrl);
192242

193243
err = ctrl->ops->config(chan, conf);
194244

195-
rt_mutex_release(&ctrl->mutex);
245+
dma_unlock(ctrl);
196246

197247
if (!err)
198248
{
@@ -233,6 +283,19 @@ static rt_bool_t range_is_illegal(const char *name, const char *desc,
233283
return illegal;
234284
}
235285

286+
static rt_bool_t addr_is_supported(const char *name, const char *desc,
287+
rt_uint64_t mask, rt_ubase_t addr)
288+
{
289+
rt_bool_t illegal = !!(addr & ~mask);
290+
291+
if (illegal)
292+
{
293+
LOG_E("%s: %s %p is out of mask %p", name, desc, addr, mask);
294+
}
295+
296+
return illegal;
297+
}
298+
236299
rt_err_t rt_dma_prep_memcpy(struct rt_dma_chan *chan,
237300
struct rt_dma_slave_transfer *transfer)
238301
{
@@ -262,6 +325,18 @@ rt_err_t rt_dma_prep_memcpy(struct rt_dma_chan *chan,
262325
dma_addr_dst = transfer->dst_addr;
263326
len = transfer->buffer_len;
264327

328+
if (addr_is_supported(rt_dm_dev_get_name(ctrl->dev), "source",
329+
ctrl->addr_mask, conf->src_addr))
330+
{
331+
return -RT_ENOSYS;
332+
}
333+
334+
if (addr_is_supported(rt_dm_dev_get_name(ctrl->dev), "dest",
335+
ctrl->addr_mask, conf->dst_addr))
336+
{
337+
return -RT_ENOSYS;
338+
}
339+
265340
if (range_is_illegal(rt_dm_dev_get_name(ctrl->dev), "source",
266341
dma_addr_src, conf->src_addr))
267342
{
@@ -276,11 +351,11 @@ rt_err_t rt_dma_prep_memcpy(struct rt_dma_chan *chan,
276351

277352
if (ctrl->ops->prep_memcpy)
278353
{
279-
rt_mutex_take(&ctrl->mutex, RT_WAITING_FOREVER);
354+
dma_lock(ctrl);
280355

281356
err = ctrl->ops->prep_memcpy(chan, dma_addr_src, dma_addr_dst, len);
282357

283-
rt_mutex_release(&ctrl->mutex);
358+
dma_unlock(ctrl);
284359
}
285360
else
286361
{
@@ -327,6 +402,12 @@ rt_err_t rt_dma_prep_cyclic(struct rt_dma_chan *chan,
327402
{
328403
dma_buf_addr = transfer->src_addr;
329404

405+
if (addr_is_supported(rt_dm_dev_get_name(ctrl->dev), "source",
406+
ctrl->addr_mask, conf->src_addr))
407+
{
408+
return -RT_ENOSYS;
409+
}
410+
330411
if (range_is_illegal(rt_dm_dev_get_name(ctrl->dev), "source",
331412
dma_buf_addr, conf->src_addr))
332413
{
@@ -337,6 +418,12 @@ rt_err_t rt_dma_prep_cyclic(struct rt_dma_chan *chan,
337418
{
338419
dma_buf_addr = transfer->dst_addr;
339420

421+
if (addr_is_supported(rt_dm_dev_get_name(ctrl->dev), "dest",
422+
ctrl->addr_mask, conf->dst_addr))
423+
{
424+
return -RT_ENOSYS;
425+
}
426+
340427
if (range_is_illegal(rt_dm_dev_get_name(ctrl->dev), "dest",
341428
dma_buf_addr, conf->dst_addr))
342429
{
@@ -350,12 +437,12 @@ rt_err_t rt_dma_prep_cyclic(struct rt_dma_chan *chan,
350437

351438
if (ctrl->ops->prep_cyclic)
352439
{
353-
rt_mutex_take(&ctrl->mutex, RT_WAITING_FOREVER);
440+
dma_lock(ctrl);
354441

355442
err = ctrl->ops->prep_cyclic(chan, dma_buf_addr,
356443
transfer->buffer_len, transfer->period_len, dir);
357444

358-
rt_mutex_release(&ctrl->mutex);
445+
dma_unlock(ctrl);
359446
}
360447
else
361448
{
@@ -402,6 +489,12 @@ rt_err_t rt_dma_prep_single(struct rt_dma_chan *chan,
402489
{
403490
dma_buf_addr = transfer->src_addr;
404491

492+
if (addr_is_supported(rt_dm_dev_get_name(ctrl->dev), "source",
493+
ctrl->addr_mask, conf->src_addr))
494+
{
495+
return -RT_ENOSYS;
496+
}
497+
405498
if (range_is_illegal(rt_dm_dev_get_name(ctrl->dev), "source",
406499
dma_buf_addr, conf->src_addr))
407500
{
@@ -412,6 +505,12 @@ rt_err_t rt_dma_prep_single(struct rt_dma_chan *chan,
412505
{
413506
dma_buf_addr = transfer->dst_addr;
414507

508+
if (addr_is_supported(rt_dm_dev_get_name(ctrl->dev), "dest",
509+
ctrl->addr_mask, conf->dst_addr))
510+
{
511+
return -RT_ENOSYS;
512+
}
513+
415514
if (range_is_illegal(rt_dm_dev_get_name(ctrl->dev), "dest",
416515
dma_buf_addr, conf->dst_addr))
417516
{
@@ -425,12 +524,12 @@ rt_err_t rt_dma_prep_single(struct rt_dma_chan *chan,
425524

426525
if (ctrl->ops->prep_single)
427526
{
428-
rt_mutex_take(&ctrl->mutex, RT_WAITING_FOREVER);
527+
dma_lock(ctrl);
429528

430529
err = ctrl->ops->prep_single(chan, dma_buf_addr,
431530
transfer->buffer_len, dir);
432531

433-
rt_mutex_release(&ctrl->mutex);
532+
dma_unlock(ctrl);
434533
}
435534
else
436535
{
@@ -556,9 +655,9 @@ struct rt_dma_chan *rt_dma_chan_request(struct rt_device *dev, const char *name)
556655
chan->conf_err = -RT_ERROR;
557656
chan->prep_err = -RT_ERROR;
558657

559-
rt_mutex_take(&ctrl->mutex, RT_WAITING_FOREVER);
658+
dma_lock(ctrl);
560659
rt_list_insert_before(&ctrl->channels_nodes, &chan->list);
561-
rt_mutex_release(&ctrl->mutex);
660+
dma_unlock(ctrl);
562661

563662
return chan;
564663
}

components/drivers/include/drivers/dma.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ struct rt_dma_controller
8181

8282
struct rt_device *dev;
8383

84+
#define RT_DMA_ADDR_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL << (n)) - 1))
85+
rt_uint64_t addr_mask;
8486
RT_BITMAP_DECLARE(dir_cap, RT_DMA_DIR_MAX);
8587
const struct rt_dma_controller_ops *ops;
8688

@@ -95,6 +97,7 @@ struct rt_dma_controller_ops
9597
rt_err_t (*release_chan)(struct rt_dma_chan *chan);
9698

9799
rt_err_t (*start)(struct rt_dma_chan *chan);
100+
rt_err_t (*pause)(struct rt_dma_chan *chan);
98101
rt_err_t (*stop)(struct rt_dma_chan *chan);
99102
rt_err_t (*config)(struct rt_dma_chan *chan, struct rt_dma_slave_config *conf);
100103

@@ -164,10 +167,19 @@ rt_inline void rt_dma_controller_add_direction(struct rt_dma_controller *ctrl,
164167
rt_bitmap_set_bit(ctrl->dir_cap, dir);
165168
}
166169

170+
rt_inline void rt_dma_controller_set_addr_mask(struct rt_dma_controller *ctrl,
171+
rt_uint64_t mask)
172+
{
173+
RT_ASSERT(ctrl != RT_NULL);
174+
175+
ctrl->addr_mask = mask;
176+
}
177+
167178
rt_err_t rt_dma_controller_register(struct rt_dma_controller *ctrl);
168179
rt_err_t rt_dma_controller_unregister(struct rt_dma_controller *ctrl);
169180

170181
rt_err_t rt_dma_chan_start(struct rt_dma_chan *chan);
182+
rt_err_t rt_dma_chan_pause(struct rt_dma_chan *chan);
171183
rt_err_t rt_dma_chan_stop(struct rt_dma_chan *chan);
172184
rt_err_t rt_dma_chan_config(struct rt_dma_chan *chan,
173185
struct rt_dma_slave_config *conf);

0 commit comments

Comments
 (0)