aboutsummaryrefslogtreecommitdiff
path: root/drivers/edma/src/tcd.rs
diff options
context:
space:
mode:
authorIan McIntyre <me@mciantyre.dev>2025-11-30 18:52:34 -0500
committerIan McIntyre <me@mciantyre.dev>2025-11-30 19:10:51 -0500
commit76199f21616ad86cf68f3b063c1ce23c6fc5a52f (patch)
tree4c076d0afd649803a2bd9a5ed5cbb1f1c74fb459 /drivers/edma/src/tcd.rs
First commit
Diffstat (limited to 'drivers/edma/src/tcd.rs')
-rw-r--r--drivers/edma/src/tcd.rs174
1 files changed, 174 insertions, 0 deletions
diff --git a/drivers/edma/src/tcd.rs b/drivers/edma/src/tcd.rs
new file mode 100644
index 0000000..1e76533
--- /dev/null
+++ b/drivers/edma/src/tcd.rs
@@ -0,0 +1,174 @@
+//! Transfer control descriptor.
+
+/// Common TCD layout for all eDMA implementations.
+///
+/// Fields may vary. See inline notes.
+mod common {
+ #[repr(C, align(32))]
+ #[allow(non_snake_case)]
+ pub struct RegisterBlock {
+ pub SADDR: u32,
+ // Signed numbers for offsets / 'last' members intentional.
+ // The hardware treats them as signed numbers.
+ pub SOFF: i16,
+ pub ATTR: u16,
+ pub NBYTES: u32,
+ pub SLAST: i32,
+ pub DADDR: u32,
+ pub DOFF: i16,
+ /// The minor loop channel link field may vary in size
+ /// depending on the implementation. Not worried right
+ /// now, since we don't support minor loop linking.
+ pub CITER: u16,
+ pub DLAST_SGA: i32,
+ /// These fields vary across all of eDMA, eDMA3 and
+ /// eDMA4!
+ ///
+ /// Major loop channel linking field size changes as
+ /// a function of the number of DMA channels.
+ ///
+ /// eDMA and eDMA3 have bandwidth control. eDMA4 has
+ /// transfer mode control for read-only / write-only
+ /// DMA transfers. Field is the same size.
+ ///
+ /// In the low byte, high nibble, eDMA has DONE and
+ /// ACTIVE. eDMA3 and eDMA4 have things we probably don't
+ /// need. Low byte, low nibble is the same.
+ ///
+ /// So we'll need to change how we handle DONE and
+ /// ACTIVE access. They can't always dispatch to this
+ /// register.
+ pub CSR: u16,
+ /// See CITER documentation note about eDMA3 bitfield
+ /// size when minor loop channel linking is enabled.
+ pub BITER: u16,
+ }
+
+ const _: () = assert!(32 == size_of::<RegisterBlock>());
+
+ ral_registers::register! {
+ pub SADDR<u32> RW []
+ }
+
+ ral_registers::register! {
+ pub SOFF<i16> RW []
+ }
+
+ ral_registers::register! {
+ pub ATTR<u16> RW [
+ #[doc = "Destination data transfer size"]
+ DSIZE start(0) width(3) RW {}
+ #[doc = "Destination Address Modulo"]
+ DMOD start(3) width(5) RW {}
+ #[doc = "Source data transfer size"]
+ SSIZE start(8) width(3) RW {}
+ #[doc = "Source Address Modulo"]
+ SMOD start(11) width(5) RW {}
+ ]
+ }
+
+ ral_registers::register! {
+ pub NBYTES<u32> RW []
+ }
+
+ ral_registers::register! {
+ pub SLAST<i32> RW []
+ }
+
+ ral_registers::register! {
+ pub DADDR<u32> RW []
+ }
+
+ ral_registers::register! {
+ pub DOFF<i16> RW []
+ }
+
+ ral_registers::register! {
+ pub CITER<u16> RW []
+ }
+
+ ral_registers::register! {
+ pub DLAST_SGA<i32> RW []
+ }
+
+ ral_registers::register! {
+ pub CSR<u16> RW [
+ START start(0) width(1) RW {}
+ INTMAJOR start(1) width(1) RW {}
+ DREQ start(3) width(1) RW {}
+ ACTIVE start(6) width(1) RW {}
+ DONE start(7) width(1) RW {}
+ ]
+ }
+
+ ral_registers::register! {
+ pub BITER<u16> RW []
+ }
+}
+
+pub mod edma {
+ pub use super::common::*;
+}
+
+pub mod edma34 {
+ #[repr(C, align(32))]
+ #[allow(non_snake_case)]
+ pub struct RegisterBlock {
+ pub CSR: u32,
+ pub ES: u32,
+ pub INT: u32,
+ pub SBR: u32,
+ pub PRI: u32,
+ pub MUX: u32,
+ /// Available on eDMA4, and reserved on eDMA3.
+ _mattr: u32,
+ pub TCD: super::common::RegisterBlock,
+ _reserved: [u8; 0x1_0000 - (4 * 8 + size_of::<super::common::RegisterBlock>())],
+ }
+
+ const _: () = assert!(core::mem::offset_of!(RegisterBlock, TCD) == 0x20);
+ const _: () = assert!(size_of::<RegisterBlock>() == 0x1_0000);
+
+ ral_registers::register! {
+ pub CSR<u32> RW [
+ ACTIVE start(31) width(1) RW {}
+ DONE start(30) width(1) RW {}
+ ERQ start(0) width(1) RW {}
+ ]
+ }
+
+ ral_registers::register! {
+ pub SBR<u32> RW [
+ EMI start(16) width(1) RW {}
+ PAL start(15) width(1) RW {}
+ SEC start(14) width(1) RW {}
+ ]
+ }
+
+ ral_registers::register! {
+ pub INT<u32> RW []
+ }
+
+ ral_registers::register! {
+ pub ES<u32> RW [
+ ERR start(31) width(1) RW {}
+ ]
+ }
+
+ ral_registers::register! {
+ pub MUX<u32> RW [
+ SRC start(0) width(6) RW {}
+ ]
+ }
+
+ #[allow(non_snake_case)]
+ pub mod TCD {
+ pub use crate::tcd::common::{
+ ATTR, BITER, CITER, DADDR, DLAST_SGA, DOFF, NBYTES, SADDR, SLAST, SOFF,
+ };
+
+ pub mod CSR {
+ pub use crate::tcd::common::CSR::{DREQ, INTMAJOR, START, access};
+ }
+ }
+}