aboutsummaryrefslogtreecommitdiff
path: root/drivers/edma/src/tcd.rs
blob: 1e76533e581462e08bc8aa93ec0956256d31eb77 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
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};
        }
    }
}