1
use super::*;
2
use crate::RegisterToggle;
3

            
4
impl AhbGdmaTxChannel<'_> {
5
    #[inline(always)]
6
    pub(super) fn ch(&self) -> &pac::dma::ch::CH {
7
315
        DMA::regs().ch(self.0.info.channel as usize)
8
    }
9

            
10
    #[cfg(any(esp32c2, esp32c3))]
11
    #[inline(always)]
12
    pub(super) fn int(&self) -> &pac::dma::int_ch::INT_CH {
13
317
        DMA::regs().int_ch(self.0.info.channel as usize)
14
    }
15

            
16
    #[inline(always)]
17
    #[cfg(any(esp32c6, esp32h2))]
18
    pub(super) fn int(&self) -> &pac::dma::out_int_ch::OUT_INT_CH {
19
        DMA::regs().out_int_ch(self.0.info.channel as usize)
20
    }
21

            
22
    #[cfg(esp32s3)]
23
    #[inline(always)]
24
    pub(super) fn int(&self) -> &pac::dma::ch::out_int::OUT_INT {
25
        DMA::regs().ch(self.0.info.channel as usize).out_int()
26
    }
27
}
28

            
29
impl RegisterAccess for AhbGdmaTxChannel<'_> {
30
    #[allow(private_interfaces)]
31
    fn enable(&self) -> Option<PeripheralGuard> {
32
        Some(PeripheralGuard::new_with(
33
            Peripheral::AhbGdma,
34
            init_dma_racey,
35
        ))
36
    }
37

            
38
    fn reset(&self) {
39
        self.ch().out_conf0().toggle(|w, bit| w.out_rst().bit(bit));
40
49
    }
41

            
42
    fn set_burst_mode(&self, burst_mode: BurstConfig) {
43
        self.ch()
44
            .out_conf0()
45
            .modify(|_, w| w.out_data_burst_en().bit(burst_mode.is_burst_enabled()));
46
49
    }
47

            
48
    fn set_descr_burst_mode(&self, burst_mode: bool) {
49
        self.ch()
50
            .out_conf0()
51
            .modify(|_, w| w.outdscr_burst_en().bit(burst_mode));
52
49
    }
53

            
54
    fn set_priority(&self, priority: DmaPriority) {
55
        self.ch()
56
            .out_pri()
57
            .write(|w| unsafe { w.tx_pri().bits(priority as u8) });
58
    }
59

            
60
    fn set_peripheral(&self, peripheral: u8) {
61
        self.ch()
62
            .out_peri_sel()
63
            .modify(|_, w| unsafe { w.peri_out_sel().bits(peripheral) });
64
49
    }
65

            
66
    fn set_link_addr(&self, address: u32) {
67
        self.ch()
68
            .out_link()
69
            .modify(|_, w| unsafe { w.outlink_addr().bits(address) });
70
49
    }
71

            
72
    fn start(&self) {
73
        self.ch()
74
            .out_link()
75
            .modify(|_, w| w.outlink_start().set_bit());
76
49
    }
77

            
78
    fn stop(&self) {
79
        self.ch()
80
            .out_link()
81
            .modify(|_, w| w.outlink_stop().set_bit());
82
7
    }
83

            
84
    fn restart(&self) {
85
        self.ch()
86
            .out_link()
87
            .modify(|_, w| w.outlink_restart().set_bit());
88
    }
89

            
90
    fn set_check_owner(&self, check_owner: Option<bool>) {
91
        self.ch()
92
            .out_conf1()
93
            .modify(|_, w| w.out_check_owner().bit(check_owner.unwrap_or(true)));
94
49
    }
95

            
96
    #[cfg(dma_ext_mem_configurable_block_size)]
97
    fn set_ext_mem_block_size(&self, size: DmaExtMemBKSize) {
98
        self.ch()
99
            .out_conf1()
100
            .modify(|_, w| unsafe { w.out_ext_mem_bk_size().bits(size as u8) });
101
    }
102

            
103
    #[cfg(dma_can_access_psram)]
104
    fn can_access_psram(&self) -> bool {
105
        true
106
    }
107

            
108
    fn compatible_peripherals(&self) -> &[u8] {
109
        self.0.info.compatible_peripherals
110
    }
111
}
112

            
113
impl TxRegisterAccess for AhbGdmaTxChannel<'_> {
114
    fn is_fifo_empty(&self) -> bool {
115
        cfg_select! {
116
            esp32s3 => self
117
                .ch()
118
                .outfifo_status()
119
                .read()
120
                .outfifo_empty_l3()
121
                .bit_is_set(),
122
            _ => self
123
                .ch()
124
                .outfifo_status()
125
                .read()
126
                .outfifo_empty()
127
                .bit_is_set(),
128
        }
129
49
    }
130

            
131
    fn set_auto_write_back(&self, enable: bool) {
132
        self.ch()
133
            .out_conf0()
134
            .modify(|_, w| w.out_auto_wrback().bit(enable));
135
49
    }
136

            
137
    fn last_dscr_address(&self) -> usize {
138
        self.ch()
139
            .out_eof_des_addr()
140
            .read()
141
            .out_eof_des_addr()
142
            .bits() as _
143
    }
144

            
145
    fn async_handler(&self) -> Option<InterruptHandler> {
146
5
        self.0.info.handler_out
147
    }
148

            
149
    fn peripheral_interrupt(&self) -> Option<Interrupt> {
150
337
        self.0.info.isr_out
151
    }
152
}
153

            
154
impl InterruptAccess<DmaTxInterrupt> for AhbGdmaTxChannel<'_> {
155
    fn enable_listen(&self, interrupts: EnumSet<DmaTxInterrupt>, enable: bool) {
156
        self.int().ena().modify(|_, w| {
157
            for interrupt in interrupts {
158
                match interrupt {
159
                    DmaTxInterrupt::TotalEof => w.out_total_eof().bit(enable),
160
                    DmaTxInterrupt::DescriptorError => w.out_dscr_err().bit(enable),
161
                    DmaTxInterrupt::Eof => w.out_eof().bit(enable),
162
                    DmaTxInterrupt::Done => w.out_done().bit(enable),
163
                };
164
            }
165
            w
166
        });
167
    }
168

            
169
    fn is_listening(&self) -> EnumSet<DmaTxInterrupt> {
170
        let mut result = EnumSet::new();
171

            
172
        let int_ena = self.int().ena().read();
173
5
        if int_ena.out_total_eof().bit_is_set() {
174
            result |= DmaTxInterrupt::TotalEof;
175
        }
176
5
        if int_ena.out_dscr_err().bit_is_set() {
177
            result |= DmaTxInterrupt::DescriptorError;
178
        }
179
5
        if int_ena.out_eof().bit_is_set() {
180
            result |= DmaTxInterrupt::Eof;
181
        }
182
5
        if int_ena.out_done().bit_is_set() {
183
            result |= DmaTxInterrupt::Done;
184
        }
185

            
186
        result
187
    }
188

            
189
    fn clear(&self, interrupts: impl Into<EnumSet<DmaTxInterrupt>>) {
190
        self.int().clr().write(|w| {
191
49
            for interrupt in interrupts.into() {
192
                match interrupt {
193
                    DmaTxInterrupt::TotalEof => w.out_total_eof().clear_bit_by_one(),
194
                    DmaTxInterrupt::DescriptorError => w.out_dscr_err().clear_bit_by_one(),
195
                    DmaTxInterrupt::Eof => w.out_eof().clear_bit_by_one(),
196
                    DmaTxInterrupt::Done => w.out_done().clear_bit_by_one(),
197
                };
198
            }
199
            w
200
        });
201
    }
202

            
203
    fn pending_interrupts(&self) -> EnumSet<DmaTxInterrupt> {
204
        let mut result = EnumSet::new();
205

            
206
        let int_raw = self.int().raw().read();
207
51
        if int_raw.out_total_eof().bit_is_set() {
208
            result |= DmaTxInterrupt::TotalEof;
209
        }
210
51
        if int_raw.out_dscr_err().bit_is_set() {
211
            result |= DmaTxInterrupt::DescriptorError;
212
        }
213
51
        if int_raw.out_eof().bit_is_set() {
214
            result |= DmaTxInterrupt::Eof;
215
        }
216
51
        if int_raw.out_done().bit_is_set() {
217
            result |= DmaTxInterrupt::Done;
218
        }
219

            
220
        result
221
51
    }
222

            
223
    fn waker(&self) -> &'static AtomicWaker {
224
        &self.0.state.tx_waker
225
    }
226

            
227
    fn is_async(&self) -> bool {
228
        cfg_select! {
229
            any(esp32c2, esp32c3) => self
230
                .0
231
                .state
232
                .tx_is_async
233
                .load(portable_atomic::Ordering::Acquire),
234
            _ => true,
235
        }
236
    }
237

            
238
27
    fn set_async(&self, _is_async: bool) {
239
        #[cfg(any(esp32c2, esp32c3))]
240
        {
241
32
            self.0
242
                .state
243
                .tx_is_async
244
                .store(_is_async, portable_atomic::Ordering::Release);
245
        }
246
27
    }
247
}
248

            
249
impl AhbGdmaRxChannel<'_> {
250
    #[inline(always)]
251
    fn ch(&self) -> &pac::dma::ch::CH {
252
387
        DMA::regs().ch(self.0.info.channel as usize)
253
    }
254

            
255
    #[cfg(any(esp32c2, esp32c3))]
256
    #[inline(always)]
257
    fn int(&self) -> &pac::dma::int_ch::INT_CH {
258
11431548
        DMA::regs().int_ch(self.0.info.channel as usize)
259
    }
260

            
261
    #[inline(always)]
262
    #[cfg(any(esp32c6, esp32h2))]
263
    fn int(&self) -> &pac::dma::in_int_ch::IN_INT_CH {
264
        DMA::regs().in_int_ch(self.0.info.channel as usize)
265
    }
266

            
267
    #[cfg(esp32s3)]
268
    #[inline(always)]
269
    fn int(&self) -> &pac::dma::ch::in_int::IN_INT {
270
        DMA::regs().ch(self.0.info.channel as usize).in_int()
271
    }
272
}
273

            
274
impl RegisterAccess for AhbGdmaRxChannel<'_> {
275
    #[allow(private_interfaces)]
276
54
    fn enable(&self) -> Option<PeripheralGuard> {
277
        Some(PeripheralGuard::new_with(
278
            Peripheral::AhbGdma,
279
            init_dma_racey,
280
        ))
281
54
    }
282

            
283
    fn reset(&self) {
284
        self.ch().in_conf0().toggle(|w, bit| w.in_rst().bit(bit));
285
93
    }
286

            
287
    fn set_burst_mode(&self, burst_mode: BurstConfig) {
288
        self.ch()
289
            .in_conf0()
290
            .modify(|_, w| w.in_data_burst_en().bit(burst_mode.is_burst_enabled()));
291
93
    }
292

            
293
    fn set_descr_burst_mode(&self, burst_mode: bool) {
294
        self.ch()
295
            .in_conf0()
296
            .modify(|_, w| w.indscr_burst_en().bit(burst_mode));
297
93
    }
298

            
299
    fn set_priority(&self, priority: DmaPriority) {
300
        self.ch()
301
            .in_pri()
302
            .write(|w| unsafe { w.rx_pri().bits(priority as u8) });
303
    }
304

            
305
    fn set_peripheral(&self, peripheral: u8) {
306
        self.ch()
307
            .in_peri_sel()
308
            .modify(|_, w| unsafe { w.peri_in_sel().bits(peripheral) });
309
93
    }
310

            
311
    fn set_link_addr(&self, address: u32) {
312
        self.ch()
313
            .in_link()
314
            .modify(|_, w| unsafe { w.inlink_addr().bits(address) });
315
93
    }
316

            
317
    fn start(&self) {
318
        self.ch()
319
            .in_link()
320
            .modify(|_, w| w.inlink_start().set_bit());
321
93
    }
322

            
323
    fn stop(&self) {
324
        self.ch().in_link().modify(|_, w| w.inlink_stop().set_bit());
325
7
    }
326

            
327
    fn restart(&self) {
328
        self.ch()
329
            .in_link()
330
            .modify(|_, w| w.inlink_restart().set_bit());
331
    }
332

            
333
    fn set_check_owner(&self, check_owner: Option<bool>) {
334
        self.ch()
335
            .in_conf1()
336
            .modify(|_, w| w.in_check_owner().bit(check_owner.unwrap_or(true)));
337
93
    }
338

            
339
    #[cfg(dma_ext_mem_configurable_block_size)]
340
    fn set_ext_mem_block_size(&self, size: DmaExtMemBKSize) {
341
        self.ch()
342
            .in_conf1()
343
            .modify(|_, w| unsafe { w.in_ext_mem_bk_size().bits(size as u8) });
344
    }
345

            
346
    #[cfg(dma_can_access_psram)]
347
    fn can_access_psram(&self) -> bool {
348
        true
349
    }
350

            
351
    fn compatible_peripherals(&self) -> &[u8] {
352
333
        self.0.info.compatible_peripherals
353
    }
354
}
355

            
356
impl RxRegisterAccess for AhbGdmaRxChannel<'_> {
357
    #[cfg(dma_supports_mem2mem)]
358
    fn set_mem2mem_mode(&self, value: bool) {
359
        self.ch()
360
            .in_conf0()
361
            .modify(|_, w| w.mem_trans_en().bit(value));
362
30
    }
363

            
364
    fn async_handler(&self) -> Option<InterruptHandler> {
365
5
        self.0.info.handler_in
366
    }
367

            
368
    fn peripheral_interrupt(&self) -> Option<Interrupt> {
369
337
        self.0.info.isr_in
370
    }
371
}
372

            
373
impl InterruptAccess<DmaRxInterrupt> for AhbGdmaRxChannel<'_> {
374
10
    fn enable_listen(&self, interrupts: EnumSet<DmaRxInterrupt>, enable: bool) {
375
10
        self.int().ena().modify(|_, w| {
376
40
            for interrupt in interrupts {
377
                match interrupt {
378
10
                    DmaRxInterrupt::SuccessfulEof => w.in_suc_eof().bit(enable),
379
10
                    DmaRxInterrupt::ErrorEof => w.in_err_eof().bit(enable),
380
10
                    DmaRxInterrupt::DescriptorError => w.in_dscr_err().bit(enable),
381
                    DmaRxInterrupt::DescriptorEmpty => w.in_dscr_empty().bit(enable),
382
                    DmaRxInterrupt::Done => w.in_done().bit(enable),
383
                };
384
            }
385
            w
386
        });
387
10
    }
388

            
389
    fn is_listening(&self) -> EnumSet<DmaRxInterrupt> {
390
        let mut result = EnumSet::new();
391

            
392
        let int_ena = self.int().ena().read();
393
5
        if int_ena.in_dscr_err().bit_is_set() {
394
            result |= DmaRxInterrupt::DescriptorError;
395
        }
396
5
        if int_ena.in_dscr_empty().bit_is_set() {
397
            result |= DmaRxInterrupt::DescriptorEmpty;
398
        }
399
5
        if int_ena.in_suc_eof().bit_is_set() {
400
            result |= DmaRxInterrupt::SuccessfulEof;
401
        }
402
5
        if int_ena.in_err_eof().bit_is_set() {
403
            result |= DmaRxInterrupt::ErrorEof;
404
        }
405
5
        if int_ena.in_done().bit_is_set() {
406
            result |= DmaRxInterrupt::Done;
407
        }
408

            
409
        result
410
    }
411

            
412
    fn clear(&self, interrupts: impl Into<EnumSet<DmaRxInterrupt>>) {
413
        self.int().clr().write(|w| {
414
93
            for interrupt in interrupts.into() {
415
                match interrupt {
416
                    DmaRxInterrupt::SuccessfulEof => w.in_suc_eof().clear_bit_by_one(),
417
                    DmaRxInterrupt::ErrorEof => w.in_err_eof().clear_bit_by_one(),
418
                    DmaRxInterrupt::DescriptorError => w.in_dscr_err().clear_bit_by_one(),
419
                    DmaRxInterrupt::DescriptorEmpty => w.in_dscr_empty().clear_bit_by_one(),
420
                    DmaRxInterrupt::Done => w.in_done().clear_bit_by_one(),
421
                };
422
            }
423
            w
424
        });
425
    }
426

            
427
    fn pending_interrupts(&self) -> EnumSet<DmaRxInterrupt> {
428
        let mut result = EnumSet::new();
429

            
430
        let int_raw = self.int().raw().read();
431
11431286
        if int_raw.in_dscr_err().bit_is_set() {
432
            result |= DmaRxInterrupt::DescriptorError;
433
        }
434
11431286
        if int_raw.in_dscr_empty().bit_is_set() {
435
            result |= DmaRxInterrupt::DescriptorEmpty;
436
        }
437
11431286
        if int_raw.in_suc_eof().bit_is_set() {
438
            result |= DmaRxInterrupt::SuccessfulEof;
439
        }
440
11431285
        if int_raw.in_err_eof().bit_is_set() {
441
            result |= DmaRxInterrupt::ErrorEof;
442
        }
443
11431285
        if int_raw.in_done().bit_is_set() {
444
            result |= DmaRxInterrupt::Done;
445
        }
446

            
447
        result
448
11431285
    }
449

            
450
    fn waker(&self) -> &'static AtomicWaker {
451
        &self.0.state.rx_waker
452
    }
453

            
454
    fn is_async(&self) -> bool {
455
        cfg_select! {
456
            any(esp32c2, esp32c3) => self
457
                .0
458
                .state
459
                .rx_is_async
460
                .load(portable_atomic::Ordering::Acquire),
461
            _ => true,
462
        }
463
    }
464

            
465
27
    fn set_async(&self, _is_async: bool) {
466
        #[cfg(any(esp32c2, esp32c3))]
467
        {
468
32
            self.0
469
                .state
470
                .rx_is_async
471
                .store(_is_async, portable_atomic::Ordering::Release);
472
        }
473
27
    }
474
}
475

            
476
pub(crate) fn setup() {}