1use crate::peripherals::SfcCfg;
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub enum SpiIfType {
23 Standard = 0,
25 DualIO = 1,
27 DualIOCont = 2,
29 QuadIO = 3,
31 QuadIOCont = 4,
33}
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37pub enum AddressMode {
38 ThreeByte = 0,
40 FourByte = 1,
42}
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq)]
46pub enum FlashSpiMode {
47 Mode0 = 0,
49 Mode3 = 1,
51}
52
53#[derive(Debug, Clone, Copy, PartialEq, Eq)]
55pub enum ReadDelay {
56 Delay0,
58 DelayHalf,
60 Delay1,
62 Delay1_5,
64}
65
66#[derive(Debug, Clone, Copy)]
68pub struct BusConfig {
69 pub read_if_type: SpiIfType,
71 pub read_dummy_bytes: u8,
73 pub read_instruction: u8,
75 pub read_prefetch_cnt: u8,
77 pub write_if_type: SpiIfType,
79 pub write_dummy_bytes: u8,
81 pub write_instruction: u8,
83}
84
85impl Default for BusConfig {
86 fn default() -> Self {
87 Self {
88 read_if_type: SpiIfType::Standard,
89 read_dummy_bytes: 0,
90 read_instruction: 0x03, read_prefetch_cnt: 0,
92 write_if_type: SpiIfType::Standard,
93 write_dummy_bytes: 0,
94 write_instruction: 0x02, }
96 }
97}
98
99pub struct SfcDriver<'d> {
101 _sfc: SfcCfg<'d>,
102}
103
104const MIN_TSHSL: u32 = 5;
106
107impl<'d> SfcDriver<'d> {
108 pub fn new(sfc: SfcCfg<'d>) -> Self {
110 Self { _sfc: sfc }
111 }
112
113 fn regs(&self) -> &'static ws63_pac::sfc_cfg::RegisterBlock {
114 unsafe { &*SfcCfg::ptr() }
116 }
117
118 pub fn configure_global(
122 &mut self,
123 spi_mode: FlashSpiMode,
124 addr_mode: AddressMode,
125 read_delay: ReadDelay,
126 write_protect: bool,
127 ) {
128 let mut val: u32 = 0;
129 val |= spi_mode as u32; if write_protect {
131 val |= 1 << 1; }
133 if matches!(addr_mode, AddressMode::FourByte) {
134 val |= 1 << 2; }
136 val |= (read_delay as u32) << 3; unsafe {
139 self.regs().global_config().write(|w| w.bits(val));
140 }
141 }
142
143 pub fn configure_timing(&mut self, tshsl: u8, tcss: u8, tcsh: u8) {
149 let tshsl = (tshsl.max(MIN_TSHSL as u8 - 2) as u32) & 0x0F;
151 let tcss = (tcss as u32) & 0x07;
152 let tcsh = (tcsh as u32) & 0x07;
153
154 let val = tshsl | (tcss << 8) | (tcsh << 12);
155
156 unsafe {
157 self.regs().timing().write(|w| w.bits(val));
158 }
159 }
160
161 pub fn configure_bus(&mut self, config: &BusConfig) {
165 let r = self.regs();
166
167 let mut cfg1: u32 = 0;
169 cfg1 |= (config.read_if_type as u32) & 0x07; cfg1 |= ((config.read_dummy_bytes as u32) & 0x07) << 3; cfg1 |= ((config.read_prefetch_cnt as u32) & 0x03) << 6; cfg1 |= ((config.read_instruction as u32) & 0xFF) << 8; cfg1 |= ((config.write_if_type as u32) & 0x07) << 16; cfg1 |= ((config.write_dummy_bytes as u32) & 0x07) << 19; cfg1 |= ((config.write_instruction as u32) & 0xFF) << 22; unsafe {
178 r.bus_config1().write(|w| w.bits(cfg1));
179 }
180 }
181
182 pub fn release_bus_reset(&mut self) {
184 unsafe {
185 self.regs().soft_rst_mask().write(|w| w.bits(0x01));
186 }
187 }
188
189 pub fn hold_bus_reset(&mut self) {
191 unsafe {
192 self.regs().soft_rst_mask().write(|w| w.bits(0x00));
193 }
194 }
195
196 fn write_databuf(r: &ws63_pac::sfc_cfg::RegisterBlock, idx: usize, word: u32) {
200 unsafe {
201 match idx {
202 0 => {
203 r.cmd_databuf_0().write(|w| w.bits(word));
204 }
205 1 => {
206 r.cmd_databuf_1().write(|w| w.bits(word));
207 }
208 2 => {
209 r.cmd_databuf_2().write(|w| w.bits(word));
210 }
211 3 => {
212 r.cmd_databuf_3().write(|w| w.bits(word));
213 }
214 4 => {
215 r.cmd_databuf_4().write(|w| w.bits(word));
216 }
217 5 => {
218 r.cmd_databuf_5().write(|w| w.bits(word));
219 }
220 6 => {
221 r.cmd_databuf_6().write(|w| w.bits(word));
222 }
223 7 => {
224 r.cmd_databuf_7().write(|w| w.bits(word));
225 }
226 8 => {
227 r.cmd_databuf_8().write(|w| w.bits(word));
228 }
229 9 => {
230 r.cmd_databuf_9().write(|w| w.bits(word));
231 }
232 10 => {
233 r.cmd_databuf_10().write(|w| w.bits(word));
234 }
235 11 => {
236 r.cmd_databuf_11().write(|w| w.bits(word));
237 }
238 12 => {
239 r.cmd_databuf_12().write(|w| w.bits(word));
240 }
241 13 => {
242 r.cmd_databuf_13().write(|w| w.bits(word));
243 }
244 14 => {
245 r.cmd_databuf_14().write(|w| w.bits(word));
246 }
247 15 => {
248 r.cmd_databuf_15().write(|w| w.bits(word));
249 }
250 _ => {}
251 }
252 }
253 }
254
255 fn read_databuf(r: &ws63_pac::sfc_cfg::RegisterBlock, idx: usize) -> u32 {
257 match idx {
258 0 => r.cmd_databuf_0().read().bits(),
259 1 => r.cmd_databuf_1().read().bits(),
260 2 => r.cmd_databuf_2().read().bits(),
261 3 => r.cmd_databuf_3().read().bits(),
262 4 => r.cmd_databuf_4().read().bits(),
263 5 => r.cmd_databuf_5().read().bits(),
264 6 => r.cmd_databuf_6().read().bits(),
265 7 => r.cmd_databuf_7().read().bits(),
266 8 => r.cmd_databuf_8().read().bits(),
267 9 => r.cmd_databuf_9().read().bits(),
268 10 => r.cmd_databuf_10().read().bits(),
269 11 => r.cmd_databuf_11().read().bits(),
270 12 => r.cmd_databuf_12().read().bits(),
271 13 => r.cmd_databuf_13().read().bits(),
272 14 => r.cmd_databuf_14().read().bits(),
273 15 => r.cmd_databuf_15().read().bits(),
274 _ => 0,
275 }
276 }
277
278 pub fn send_command(&mut self, instruction: u8, address: u32, address_enable: bool) {
284 let r = self.regs();
285
286 unsafe {
288 r.cmd_ins().write(|w| w.bits(instruction as u32));
289 }
290
291 if address_enable {
293 unsafe {
294 r.cmd_addr().write(|w| w.bits(address));
295 }
296 }
297
298 let mut cmd_cfg: u32 = 0;
300 cmd_cfg |= 0x01; if address_enable {
302 cmd_cfg |= 1 << 2; }
304 cmd_cfg |= 0 << 17; unsafe {
307 r.cmd_config().write(|w| w.bits(cmd_cfg));
308 }
309
310 while !self.command_done() {}
312 self.clear_interrupts();
313 }
314
315 pub fn command_with_data(
324 &mut self,
325 instruction: u8,
326 address: u32,
327 write_data: &[u8],
328 read: bool,
329 ) -> Result<[u8; 64], SfcError> {
330 let r = self.regs();
331 let data_len = write_data.len().min(64);
332
333 if !read && !write_data.is_empty() {
334 for (i, chunk) in write_data[..data_len].chunks(4).enumerate() {
336 let mut word: u32 = 0;
337 for (j, &b) in chunk.iter().enumerate() {
338 word |= (b as u32) << (j * 8);
339 }
340 Self::write_databuf(r, i, word);
341 }
342 }
343
344 unsafe {
346 r.cmd_ins().write(|w| w.bits(instruction as u32));
347 r.cmd_addr().write(|w| w.bits(address));
348 }
349
350 let mut cmd_cfg: u32 = 0;
352 cmd_cfg |= 0x01; cmd_cfg |= 1 << 2; cmd_cfg |= 1 << 7; if read {
356 cmd_cfg |= 1 << 8; }
358 cmd_cfg |= (((data_len.saturating_sub(1)) as u32) & 0x3F) << 9; cmd_cfg |= 0 << 17; unsafe {
362 r.cmd_config().write(|w| w.bits(cmd_cfg));
363 }
364
365 while !self.command_done() {}
367 self.clear_interrupts();
368
369 let mut result = [0u8; 64];
371 if read {
372 let mut idx = 0;
373 for i in 0..data_len.div_ceil(4) {
374 let word = Self::read_databuf(r, i);
375 let bytes = word.to_le_bytes();
376 for &b in &bytes {
377 if idx < data_len {
378 result[idx] = b;
379 idx += 1;
380 }
381 }
382 }
383 }
384
385 Ok(result)
386 }
387
388 pub fn bus_dma_start(&mut self, mem_addr: u32, flash_addr: u32, length: u32, read: bool) {
397 let r = self.regs();
398
399 unsafe {
400 r.bus_dma_mem_saddr().write(|w| w.bits(mem_addr));
401 r.bus_dma_flash_saddr().write(|w| w.bits(flash_addr));
402 r.bus_dma_len().write(|w| w.bits(length & 0x3FFF_FFFF));
403 }
404
405 let mut ctrl: u32 = 0;
406 ctrl |= 0x01; if read {
408 ctrl |= 1 << 1; }
410
411 unsafe {
412 r.bus_dma_ctrl().write(|w| w.bits(ctrl));
413 }
414 }
415
416 pub fn bus_dma_wait(&self) {
418 while !self.dma_done() {}
419 self.clear_interrupts();
420 }
421
422 pub fn dma_done(&self) -> bool {
424 self.regs().int_status().read().bits() & 0x02 != 0
425 }
426
427 pub fn command_done(&self) -> bool {
429 self.regs().int_status().read().bits() & 0x01 != 0
430 }
431
432 pub fn clear_interrupts(&self) {
434 unsafe {
435 self.regs().int_clear().write(|w| w.bits(0x03));
436 }
437 }
438
439 pub fn enable_interrupts(&mut self, cmd_done: bool, dma_done: bool) {
444 let mut mask: u32 = 0;
445 if cmd_done {
446 mask |= 0x01;
447 }
448 if dma_done {
449 mask |= 0x02;
450 }
451 unsafe {
452 self.regs().int_mask().write(|w| w.bits(mask));
453 }
454 }
455
456 pub fn raw_interrupt_status(&self) -> (bool, bool) {
460 let sts = self.regs().int_raw_status().read().bits();
461 ((sts & 0x01) != 0, (sts & 0x02) != 0)
462 }
463
464 pub fn enable_aes_low_power(&mut self) {
468 unsafe {
469 self.regs().lea_lp_en().write(|w| w.bits(0x01));
470 }
471 }
472
473 pub fn disable_aes_low_power(&mut self) {
475 unsafe {
476 self.regs().lea_lp_en().write(|w| w.bits(0x00));
477 }
478 }
479
480 pub fn set_iv_valid(&mut self) {
482 unsafe {
483 self.regs().lea_iv_vld().write(|w| w.bits(0x01));
484 }
485 }
486
487 pub fn read_aes_dfx(&self) -> u32 {
489 self.regs().lea_dfx_info().read().bits()
490 }
491}
492
493#[derive(Debug)]
495pub enum SfcError {
496 Timeout,
498 DmaError,
500}