Skip to content

Commit c901551

Browse files
Martinhoff-makerkartben
authored andcommitted
driver: dma: silabs: Add signal binding to support P2M and M2P transfer
Improve the silabs ldma driver to support P2M and M2P transfer. It also adds signal binding to support source request binding in the dts. Signed-off-by: Martin Hoff <[email protected]>
1 parent 11ca616 commit c901551

File tree

17 files changed

+430
-13
lines changed

17 files changed

+430
-13
lines changed

drivers/dma/dma_silabs_ldma.c

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include <zephyr/device.h>
1111
#include <zephyr/drivers/dma.h>
12+
#include <zephyr/drivers/dma/dma_silabs_ldma.h>
1213
#include <zephyr/logging/log.h>
1314
#include <zephyr/irq.h>
1415
#include <zephyr/sys/mem_blocks.h>
@@ -104,7 +105,9 @@ static int dma_silabs_block_to_descriptor(struct dma_config *config,
104105

105106
memset(desc, 0, sizeof(*desc));
106107

107-
desc->xfer.structReq = 1;
108+
if (config->channel_direction == MEMORY_TO_MEMORY) {
109+
desc->xfer.structReq = 1;
110+
}
108111

109112
if (config->source_data_size != config->dest_data_size) {
110113
LOG_ERR("Source data size(%u) and destination data size(%u) must be equal",
@@ -146,8 +149,17 @@ static int dma_silabs_block_to_descriptor(struct dma_config *config,
146149
* in the list (block for zephyr)
147150
*/
148151
desc->xfer.doneIfs = config->complete_callback_en;
149-
desc->xfer.reqMode = ldmaCtrlReqModeAll;
150-
desc->xfer.ignoreSrec = block->flow_control_mode;
152+
153+
if (config->channel_direction == PERIPHERAL_TO_MEMORY ||
154+
config->channel_direction == MEMORY_TO_PERIPHERAL) {
155+
if (block->flow_control_mode) {
156+
desc->xfer.reqMode = ldmaCtrlReqModeAll;
157+
} else {
158+
desc->xfer.reqMode = ldmaCtrlReqModeBlock;
159+
}
160+
} else {
161+
desc->xfer.reqMode = ldmaCtrlReqModeAll;
162+
}
151163

152164
/* In silabs LDMA, increment sign is managed with the transfer configuration
153165
* which is common for all descs of the channel. Zephyr DMA API allows
@@ -257,10 +269,9 @@ static int dma_silabs_configure_descriptor(struct dma_config *config, struct dma
257269
return 0;
258270
err:
259271
/* Free all eventually allocated descriptor */
260-
(void)dma_silabs_release_descriptor(data, chan_conf->desc);
272+
dma_silabs_release_descriptor(data, chan_conf->desc);
261273

262274
return ret;
263-
264275
}
265276

266277
static void dma_silabs_irq_handler(const struct device *dev, uint32_t id)
@@ -350,7 +361,7 @@ static int dma_silabs_configure(const struct device *dev, uint32_t channel,
350361
break;
351362
case PERIPHERAL_TO_MEMORY:
352363
case MEMORY_TO_PERIPHERAL:
353-
xfer_config->ldmaReqSel = config->dma_slot;
364+
xfer_config->ldmaReqSel = SILABS_LDMA_SLOT_TO_REQSEL(config->dma_slot);
354365
break;
355366
case PERIPHERAL_TO_PERIPHERAL:
356367
case HOST_TO_MEMORY:
@@ -407,7 +418,6 @@ static int dma_silabs_configure(const struct device *dev, uint32_t channel,
407418

408419
static int dma_silabs_start(const struct device *dev, uint32_t channel)
409420
{
410-
411421
const struct dma_silabs_data *data = dev->data;
412422
struct dma_silabs_channel *chan = &data->dma_chan_table[channel];
413423

@@ -453,6 +463,7 @@ static int dma_silabs_get_status(const struct device *dev, uint32_t channel,
453463
return -EINVAL;
454464
}
455465

466+
status->pending_length = LDMA_TransferRemainingCount(channel);
456467
status->busy = data->dma_chan_table[channel].busy;
457468
status->dir = data->dma_chan_table[channel].dir;
458469

@@ -469,7 +480,6 @@ static int dma_silabs_init(const struct device *dev)
469480
};
470481

471482
/* Clock is managed by em_ldma */
472-
473483
LDMA_Init(&dmaInit);
474484

475485
/* LDMA_Init configure IRQ but we want IRQ to match with configured one in the dts*/

dts/arm/silabs/efr32bg22.dtsi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include "efr32bg2x.dtsi"
88
#include <dt-bindings/clock/silabs/xg22-clock.h>
9+
#include <dt-bindings/dma/silabs/xg22-dma.h>
910
#include <mem.h>
1011

1112
/ {

dts/arm/silabs/efr32bg27.dtsi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include "efr32bg2x.dtsi"
88
#include <dt-bindings/clock/silabs/xg27-clock.h>
9+
#include <dt-bindings/dma/silabs/xg27-dma.h>
910
#include <mem.h>
1011

1112
/ {

dts/arm/silabs/efr32bg2x.dtsi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@
344344
dma0: dma@40040000{
345345
compatible = "silabs,ldma";
346346
reg = <0x40040000 0x4000>;
347-
#dma-cells = <3>;
347+
#dma-cells = <1>;
348348
dma_channels = <8>;
349349
status = "disabled";
350350
};

dts/arm/silabs/efr32mg21.dtsi

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <zephyr/dt-bindings/gpio/gpio.h>
1010
#include <zephyr/dt-bindings/i2c/i2c.h>
1111
#include <dt-bindings/clock/silabs/xg21-clock.h>
12+
#include <dt-bindings/dma/silabs/xg21-dma.h>
1213
#include <freq.h>
1314

1415
/ {
@@ -331,7 +332,7 @@
331332
compatible = "silabs,ldma";
332333
reg = <0x40040000 0x4000>;
333334
interrupts = <21 0>;
334-
#dma-cells = <3>;
335+
#dma-cells = <1>;
335336
dma_channels = <8>;
336337
status = "disabled";
337338
};

dts/arm/silabs/efr32mg24.dtsi

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <dt-bindings/i2c/i2c.h>
1010
#include <dt-bindings/adc/adc.h>
1111
#include <dt-bindings/clock/silabs/xg24-clock.h>
12+
#include <dt-bindings/dma/silabs/xg24-dma.h>
1213
#include <freq.h>
1314

1415
/ {
@@ -396,7 +397,7 @@
396397
compatible = "silabs,ldma";
397398
reg = <0x40040000 0x4000>;
398399
interrupts = <21 0>;
399-
#dma-cells = <3>;
400+
#dma-cells = <1>;
400401
dma_channels = <8>;
401402
status = "disabled";
402403
};

dts/arm/silabs/efr32xg23.dtsi

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <dt-bindings/i2c/i2c.h>
1010
#include <dt-bindings/adc/adc.h>
1111
#include <dt-bindings/clock/silabs/xg23-clock.h>
12+
#include <dt-bindings/dma/silabs/xg23-dma.h>
1213
#include <freq.h>
1314

1415
/ {
@@ -426,7 +427,7 @@
426427
compatible = "silabs,ldma";
427428
reg = <0x50040000 0x4000>;
428429
interrupts = <22 0>;
429-
#dma-cells = <3>;
430+
#dma-cells = <1>;
430431
dma_channels = <8>;
431432
status = "disabled";
432433
};

dts/arm/silabs/xg29/xg29.dtsi

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <dt-bindings/i2c/i2c.h>
1010
#include <dt-bindings/adc/adc.h>
1111
#include <dt-bindings/clock/silabs/xg29-clock.h>
12+
#include <dt-bindings/dma/silabs/xg29-dma.h>
1213
#include <freq.h>
1314

1415
/ {
@@ -324,7 +325,7 @@
324325
reg = <0x40040000 0x4000>;
325326
interrupts = <26 0>;
326327
interrupt-names = "ldma";
327-
#dma-cells = <3>;
328+
#dma-cells = <1>;
328329
dma_channels = <8>;
329330
status = "disabled";
330331
};

dts/bindings/dma/silabs,ldma.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,9 @@ properties:
2424
dma_channels:
2525
type: int
2626
required: true
27+
28+
"#dma-cells":
29+
const: 1
30+
31+
dma-cells:
32+
- slot
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright (c) 2025 Silicon Laboratories Inc.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef ZEPHYR_INCLUDE_DRIVERS_DMA_SILABS_LDMA_H_
8+
#define ZEPHYR_INCLUDE_DRIVERS_DMA_SILABS_LDMA_H_
9+
10+
#include <zephyr/drivers/dma.h>
11+
12+
#define SILABS_LDMA_SOURCE_MASK GENMASK(21, 16)
13+
#define SILABS_LDMA_SIG_MASK GENMASK(3, 0)
14+
15+
#define SILABS_DMA_SLOT_SOURCE_MASK GENMASK(7, 3)
16+
#define SILABS_DMA_SLOT_SIG_MASK GENMASK(2, 0)
17+
18+
#define SILABS_LDMA_REQSEL_TO_SLOT(signal) \
19+
FIELD_PREP(SILABS_DMA_SLOT_SOURCE_MASK, FIELD_GET(SILABS_LDMA_SOURCE_MASK, signal)) | \
20+
FIELD_PREP(SILABS_DMA_SLOT_SIG_MASK, FIELD_GET(SILABS_LDMA_SIG_MASK, signal))
21+
22+
#define SILABS_LDMA_SLOT_TO_REQSEL(slot) \
23+
FIELD_PREP(SILABS_LDMA_SOURCE_MASK, FIELD_GET(SILABS_DMA_SLOT_SOURCE_MASK, slot)) | \
24+
FIELD_PREP(SILABS_LDMA_SIG_MASK, FIELD_GET(SILABS_DMA_SLOT_SIG_MASK, slot))
25+
26+
#endif /* ZEPHYR_INCLUDE_DRIVERS_DMA_SILABS_LDMA_H_*/

0 commit comments

Comments
 (0)