sdmmc_driver/
config.rs

1use sdmmc::register::csd::Csd;
2use sdmmc::register::ext_csd::ExtCsd;
3
4use crate::{BusMode, BusWidth, PowerMode, Timing};
5
6mod address_mode;
7mod erase_mode;
8
9pub use address_mode::AddressMode;
10pub use erase_mode::EraseMode;
11
12/// Represents the SD/MMC state-machine.
13#[repr(C)]
14#[derive(Clone, Copy, Debug, Eq, PartialEq)]
15pub struct MmcConfig {
16    bus_mode: BusMode,
17    bus_width: BusWidth,
18    power_mode: PowerMode,
19    timing: Timing,
20    slot: usize,
21    wp_grp_size: u32,
22    erase_size: usize,
23    erase_mode: EraseMode,
24    address_mode: AddressMode,
25    csd: Csd,
26    ext_csd: ExtCsd,
27}
28
29impl MmcConfig {
30    /// Creates a new [MmcConfig].
31    pub const fn new() -> Self {
32        Self {
33            bus_mode: BusMode::new(),
34            bus_width: BusWidth::new(),
35            power_mode: PowerMode::new(),
36            timing: Timing::new(),
37            slot: 0,
38            wp_grp_size: 0,
39            erase_size: 0,
40            erase_mode: EraseMode::new(),
41            address_mode: AddressMode::new(),
42            csd: Csd::new(),
43            ext_csd: ExtCsd::new(),
44        }
45    }
46
47    /// Gets the [BusMode] for the [MmcConfig].
48    pub const fn bus_mode(&self) -> BusMode {
49        self.bus_mode
50    }
51
52    /// Sets the [BusMode] for the [MmcConfig].
53    pub fn set_bus_mode(&mut self, bus_mode: BusMode) {
54        self.bus_mode = bus_mode;
55    }
56
57    /// Builder function that sets the [BusMode] for the [MmcConfig].
58    pub const fn with_bus_mode(self, bus_mode: BusMode) -> Self {
59        Self { bus_mode, ..self }
60    }
61
62    /// Gets the [BusWidth] for the [MmcConfig].
63    pub const fn bus_width(&self) -> BusWidth {
64        self.bus_width
65    }
66
67    /// Sets the [BusWidth] for the [MmcConfig].
68    pub fn set_bus_width(&mut self, bus_width: BusWidth) {
69        self.bus_width = bus_width;
70    }
71
72    /// Builder function that sets the [BusWidth] for the [MmcConfig].
73    pub const fn with_bus_width(self, bus_width: BusWidth) -> Self {
74        Self { bus_width, ..self }
75    }
76
77    /// Gets the [PowerMode] for the [MmcConfig].
78    pub const fn power_mode(&self) -> PowerMode {
79        self.power_mode
80    }
81
82    /// Sets the [PowerMode] for the [MmcConfig].
83    pub fn set_power_mode(&mut self, power_mode: PowerMode) {
84        self.power_mode = power_mode;
85    }
86
87    /// Builder function that sets the [PowerMode] for the [MmcConfig].
88    pub const fn with_power_mode(self, power_mode: PowerMode) -> Self {
89        Self { power_mode, ..self }
90    }
91
92    /// Gets the [Timing] for the [MmcConfig].
93    pub const fn timing(&self) -> Timing {
94        self.timing
95    }
96
97    /// Sets the [Timing] for the [MmcConfig].
98    pub fn set_timing(&mut self, timing: Timing) {
99        self.timing = timing;
100    }
101
102    /// Builder function that sets the [Timing] for the [MmcConfig].
103    pub const fn with_timing(self, timing: Timing) -> Self {
104        Self { timing, ..self }
105    }
106
107    /// Gets the slot for the [MmcConfig].
108    pub const fn slot(&self) -> usize {
109        self.slot
110    }
111
112    /// Sets the slot for the [MmcConfig].
113    pub fn set_slot(&mut self, slot: usize) {
114        self.slot = slot;
115    }
116
117    /// Builder function that sets the slot for the [MmcConfig].
118    pub const fn with_slot(self, slot: usize) -> Self {
119        Self { slot, ..self }
120    }
121
122    /// Gets the [EraseMode] for the [MmcConfig].
123    pub const fn erase_mode(&self) -> EraseMode {
124        self.erase_mode
125    }
126
127    /// Sets the [EraseMode] for the [MmcConfig].
128    pub fn set_erase_mode(&mut self, erase_mode: EraseMode) {
129        self.erase_mode = erase_mode;
130    }
131
132    /// Builder function that sets the [EraseMode] for the [MmcConfig].
133    pub const fn with_erase_mode(self, erase_mode: EraseMode) -> Self {
134        Self { erase_mode, ..self }
135    }
136
137    /// Gets the [AddressMode] for the [MmcConfig].
138    pub const fn address_mode(&self) -> AddressMode {
139        self.address_mode
140    }
141
142    /// Sets the [AddressMode] for the [MmcConfig].
143    pub fn set_address_mode(&mut self, address_mode: AddressMode) {
144        self.address_mode = address_mode;
145    }
146
147    /// Builder function that sets the [AddressMode] for the [MmcConfig].
148    pub const fn with_address_mode(self, address_mode: AddressMode) -> Self {
149        Self {
150            address_mode,
151            ..self
152        }
153    }
154
155    /// Gets a reference to the [Csd] for the [MmcConfig].
156    pub const fn csd(&self) -> &Csd {
157        &self.csd
158    }
159
160    /// Gets a mutable reference to the [Csd] for the [MmcConfig].
161    pub fn csd_mut(&mut self) -> &mut Csd {
162        &mut self.csd
163    }
164
165    /// Sets the [Csd] for the [MmcConfig].
166    pub fn set_csd(&mut self, csd: Csd) {
167        self.csd = csd;
168    }
169
170    /// Builder function that sets the [Csd] for the [MmcConfig].
171    pub const fn with_csd(self, csd: Csd) -> Self {
172        Self { csd, ..self }
173    }
174
175    /// Gets a reference to the [ExtCsd] for the [MmcConfig].
176    pub const fn ext_csd(&self) -> &ExtCsd {
177        &self.ext_csd
178    }
179
180    /// Gets a mutable reference to the [ExtCsd] for the [MmcConfig].
181    pub fn ext_csd_mut(&mut self) -> &mut ExtCsd {
182        &mut self.ext_csd
183    }
184
185    /// Sets the [ExtCsd] for the [MmcConfig].
186    pub fn set_ext_csd(&mut self, ext_csd: ExtCsd) {
187        self.ext_csd = ext_csd;
188    }
189
190    /// Builder function that sets the [ExtCsd] for the [MmcConfig].
191    pub const fn with_ext_csd(self, ext_csd: ExtCsd) -> Self {
192        Self { ext_csd, ..self }
193    }
194
195    /// Gets the `wp_grp_size` for the [MmcConfig].
196    pub const fn wp_grp_size(&self) -> u32 {
197        self.wp_grp_size
198    }
199
200    /// Sets the `wp_grp_size` for the [MmcConfig].
201    pub fn set_wp_grp_size(&mut self) {
202        self.wp_grp_size = if self.ext_csd.erase_group_def().enable() {
203            self.ext_csd.hc_erase_grp_size().size()
204        } else {
205            self.csd.erase_size() * self.csd.wp_grp_size() as u32
206        };
207    }
208
209    /// Gets whether the device supports the `DISCARD` feature.
210    pub const fn can_discard(&self) -> bool {
211        // there is no hardware discard support for MMC/eMMC cards
212        false
213    }
214
215    /// Gets whether the device supports the `TRIM` feature.
216    pub const fn can_trim(&self) -> bool {
217        self.ext_csd.sec_feature_support().sec_gb_cl_en()
218    }
219
220    /// Gets whether the device is configured for HS200 timing.
221    pub const fn hs200(&self) -> bool {
222        match self.ext_csd.device_type() {
223            Ok(d) => d.hs200(),
224            _ => false,
225        }
226    }
227
228    /// Gets whether the device is configured for HS400 timing.
229    pub const fn hs400(&self) -> bool {
230        match self.ext_csd.device_type() {
231            Ok(d) => d.hs400(),
232            _ => false,
233        }
234    }
235
236    /// Gets whether the device is configured for HS400 timing.
237    pub const fn hs400es(&self) -> bool {
238        self.hs400() && self.ext_csd.strobe_support().into_inner() != 0
239    }
240
241    /// Gets the erase size for the device.
242    pub const fn erase_size(&self) -> usize {
243        self.erase_size
244    }
245
246    /// Sets the erase size for the device read from the CSD register.
247    pub fn set_erase_size(&mut self) {
248        self.erase_size = self.csd.erase_size() as usize;
249    }
250}
251
252impl Default for MmcConfig {
253    fn default() -> Self {
254        Self::new()
255    }
256}