mimxrt600_fcb/
lib.rs

1#![no_std]
2
3use bitfield::bitfield;
4use {FlexSpiLutOpcode::*, FlexSpiNumPads::*};
5
6#[repr(C)]
7#[repr(packed)]
8pub struct FlexSPIFlashConfigurationBlock {
9    _tag: u32,
10    _version: u32,
11    _reserved0: [u8; 4],
12    _read_sample_clk: ReadSampleClk,
13    _cs_hold_time: u8,
14    _cs_setup_time: u8,
15    _column_address_width: ColumnAddressWidth,
16    _device_mode_cfg_enable: u8,
17    _reserved1: [u8; 1],
18    _wait_time_cfg_commands: u16,
19    _device_mode_seq: DeviceModeSeq,
20    _device_mode_arg: [u8; 4],
21    _config_cmd_enable: u8,
22    _config_mode_type: [u8; 3],
23    _config_cmd_seqs: [u8; 12],
24    _reserved2: [u8; 4],
25    _config_cmd_args: [u8; 12],
26    _reserved3: [u8; 4],
27    _controller_misc_option: ControllerMiscOption,
28    _device_type: DeviceType,
29    _sflash_pad_type: SFlashPadType,
30    _serial_clk_freq: SerialClkFreq,
31    _lut_custom_seq_enable: u8,
32    _reserved4: [u8; 8],
33    _sflash_a1_size: u32,
34    _sflash_a2_size: u32,
35    _sflash_b1_size: u32,
36    _sflash_b2_size: u32,
37    _cs_pad_override: u32,
38    _sclk_pad_setting_override: u32,
39    _data_pad_setting_override: u32,
40    _dqs_pad_setting_override: u32,
41    _timeout_in_ms: u32,
42    _command_interval: u32,
43    _data_valid_time: u32,
44    _busy_offset: u16,
45    _busy_bit_polarity: BusyBitPolarity,
46    _lookup_table: [u32; 64],
47    _lut_custom_seq: [u8; 48],
48    _reserved5: [u8; 16],
49    _page_size: u32,
50    _sector_size: u32,
51    _ipcmd_serial_clk_freq: u8,
52    _is_uniform_block_size: u8,
53    _is_data_order_swapped: u8,
54    _reserved6: [u8; 1],
55    _serial_nor_type: SerialNORType,
56    _need_exit_no_cmd_mode: u8,
57    _half_clk_for_non_read_cmd: u8,
58    _need_restore_no_cmd_mode: u8,
59    _block_size: u32,
60    _flash_state_ctx: u32,
61    _reserved7: [u8; 40],
62}
63
64impl FlexSPIFlashConfigurationBlock {
65    const TAG: u32 = 0x42464346;
66    const VERSION: u32 = 0x56020000;
67
68    pub const fn build() -> Self {
69        Self {
70            _tag: Self::TAG,
71            _version: Self::VERSION,
72            _reserved0: [0; 4],
73            _read_sample_clk: ReadSampleClk::InternalLoopback,
74            _cs_hold_time: 3,
75            _cs_setup_time: 3,
76            _column_address_width: ColumnAddressWidth::Other,
77            _device_mode_cfg_enable: 1,
78            _reserved1: [2; 1],
79            _wait_time_cfg_commands: 1,
80            _device_mode_seq: DeviceModeSeq::build(),
81            _device_mode_arg: [2, 0, 0, 0],
82            _config_cmd_enable: 0,
83            _config_mode_type: [0; 3],
84            _config_cmd_seqs: [0; 12],
85            _reserved2: [0; 4],
86            _config_cmd_args: [0; 12],
87            _reserved3: [0; 4],
88            _controller_misc_option: ControllerMiscOption(0x50),
89            _device_type: DeviceType::SerialNOR,
90            _sflash_pad_type: SFlashPadType::OctalPads,
91            _serial_clk_freq: SerialClkFreq::SdrDdr30mhz,
92            _lut_custom_seq_enable: 0,
93            _reserved4: [0; 8],
94            _sflash_a1_size: 0,
95            _sflash_a2_size: 0,
96            _sflash_b1_size: 0x04000000,
97            _sflash_b2_size: 0,
98            _cs_pad_override: 0,
99            _sclk_pad_setting_override: 0,
100            _data_pad_setting_override: 0,
101            _dqs_pad_setting_override: 0,
102            _timeout_in_ms: 0,
103            _command_interval: 0,
104            _data_valid_time: 0,
105            _busy_offset: 0,
106            _busy_bit_polarity: BusyBitPolarity::Normal,
107            _lookup_table: [
108                // Read
109                flexspi_lut_seq(CMD_DDR, Octal, 0xee, CMD_DDR, Octal, 0x11),
110                flexspi_lut_seq(RADDR_DDR, Octal, 0x20, DUMMY_DDR, Octal, 0x29),
111                flexspi_lut_seq(READ_DDR, Octal, 0x04, STOP, Single, 0x00),
112                0,
113                // Read status SPI
114                flexspi_lut_seq(CMD_SDR, Single, 0x05, READ_SDR, Single, 0x04),
115                0,
116                0,
117                0,
118                // Read status OPI
119                flexspi_lut_seq(CMD_DDR, Octal, 0x05, CMD_DDR, Octal, 0xFA),
120                flexspi_lut_seq(RADDR_DDR, Octal, 0x20, DUMMY_DDR, Octal, 0x14),
121                flexspi_lut_seq(READ_DDR, Octal, 0x04, STOP, Single, 0x00),
122                0,
123                // Write enable
124                flexspi_lut_seq(CMD_SDR, Single, 0x06, STOP, Single, 0x00),
125                0,
126                0,
127                0,
128                // Write enable - OPI
129                flexspi_lut_seq(CMD_DDR, Octal, 0x06, CMD_DDR, Octal, 0xF9),
130                0,
131                0,
132                0,
133                // Erase Sector
134                flexspi_lut_seq(CMD_DDR, Octal, 0x21, CMD_DDR, Octal, 0xDE),
135                flexspi_lut_seq(RADDR_DDR, Octal, 0x20, STOP, Single, 0x00),
136                0,
137                0,
138                // Enable OPI DDR mode
139                flexspi_lut_seq(CMD_SDR, Single, 0x72, CMD_SDR, Single, 0x00),
140                flexspi_lut_seq(CMD_SDR, Single, 0x00, CMD_SDR, Single, 0x00),
141                flexspi_lut_seq(CMD_SDR, Single, 0x00, WRITE_SDR, Single, 0x01),
142                0,
143                // Unused
144                0,
145                0,
146                0,
147                0,
148                // Erase block
149                flexspi_lut_seq(CMD_DDR, Octal, 0xDC, CMD_DDR, Octal, 0x23),
150                flexspi_lut_seq(RADDR_DDR, Octal, 0x20, STOP, Single, 0x00),
151                0,
152                0,
153                // Page program
154                flexspi_lut_seq(CMD_DDR, Octal, 0x12, CMD_DDR, Octal, 0xED),
155                flexspi_lut_seq(RADDR_DDR, Octal, 0x20, WRITE_DDR, Octal, 0x04),
156                0,
157                0,
158                // Unused
159                0,
160                0,
161                0,
162                0,
163                // Erase chip
164                flexspi_lut_seq(CMD_DDR, Octal, 0x60, CMD_DDR, Octal, 0x9F),
165                0,
166                0,
167                0,
168                // Remainder is unused
169                0,
170                0,
171                0,
172                0,
173                0,
174                0,
175                0,
176                0,
177                0,
178                0,
179                0,
180                0,
181                0,
182                0,
183                0,
184                0,
185            ],
186            _lut_custom_seq: [0; 48],
187            _reserved5: [0; 16],
188            _page_size: 256,
189            _sector_size: 4096,
190            _ipcmd_serial_clk_freq: 1,
191            _is_uniform_block_size: 0,
192            _is_data_order_swapped: 0,
193            _reserved6: [0; 1],
194            _serial_nor_type: SerialNORType::Xpi,
195            _need_exit_no_cmd_mode: 0,
196            _half_clk_for_non_read_cmd: 0,
197            _need_restore_no_cmd_mode: 0,
198            _block_size: 0x10_000,
199            _flash_state_ctx: 0x07008200,
200            _reserved7: [0; 40],
201        }
202    }
203
204    pub const fn read_sample_clk(self, _read_sample_clk: ReadSampleClk) -> Self {
205        Self {
206            _read_sample_clk,
207            ..self
208        }
209    }
210
211    pub const fn cs_hold_time(self, _cs_hold_time: u8) -> Self {
212        Self { _cs_hold_time, ..self }
213    }
214
215    pub const fn cs_setup_time(self, _cs_setup_time: u8) -> Self {
216        Self { _cs_setup_time, ..self }
217    }
218
219    pub const fn column_address_width(self, _column_address_width: ColumnAddressWidth) -> Self {
220        Self {
221            _column_address_width,
222            ..self
223        }
224    }
225
226    pub const fn device_mode_cfg_enable(self, _device_mode_cfg_enable: u8) -> Self {
227        Self {
228            _device_mode_cfg_enable,
229            ..self
230        }
231    }
232
233    pub const fn wait_time_cfg_commands(self, _wait_time_cfg_commands: u16) -> Self {
234        Self {
235            _wait_time_cfg_commands,
236            ..self
237        }
238    }
239
240    pub const fn device_mode_seq(self, _device_mode_seq: DeviceModeSeq) -> Self {
241        Self {
242            _device_mode_seq,
243            ..self
244        }
245    }
246
247    pub const fn device_mode_arg(self, _device_mode_arg: [u8; 4]) -> Self {
248        Self {
249            _device_mode_arg,
250            ..self
251        }
252    }
253
254    pub const fn config_cmd_enable(self, _config_cmd_enable: u8) -> Self {
255        Self {
256            _config_cmd_enable,
257            ..self
258        }
259    }
260
261    pub const fn config_mode_type(self, _config_mode_type: [u8; 3]) -> Self {
262        Self {
263            _config_mode_type,
264            ..self
265        }
266    }
267
268    pub const fn config_cmd_seqs(self, _config_cmd_seqs: [u8; 12]) -> Self {
269        Self {
270            _config_cmd_seqs,
271            ..self
272        }
273    }
274
275    pub const fn config_cmd_args(self, _config_cmd_args: [u8; 12]) -> Self {
276        Self {
277            _config_cmd_args,
278            ..self
279        }
280    }
281
282    pub const fn controller_misc_option(self, _controller_misc_option: ControllerMiscOption) -> Self {
283        Self {
284            _controller_misc_option,
285            ..self
286        }
287    }
288
289    pub const fn device_type(self, _device_type: DeviceType) -> Self {
290        Self { _device_type, ..self }
291    }
292
293    pub const fn sflash_pad_type(self, _sflash_pad_type: SFlashPadType) -> Self {
294        Self {
295            _sflash_pad_type,
296            ..self
297        }
298    }
299
300    pub const fn serial_clk_freq(self, _serial_clk_freq: SerialClkFreq) -> Self {
301        Self {
302            _serial_clk_freq,
303            ..self
304        }
305    }
306
307    pub const fn lut_custom_seq_enable(self, _lut_custom_seq_enable: u8) -> Self {
308        Self {
309            _lut_custom_seq_enable,
310            ..self
311        }
312    }
313
314    pub const fn sflash_a1_size(self, _sflash_a1_size: u32) -> Self {
315        Self {
316            _sflash_a1_size,
317            ..self
318        }
319    }
320
321    pub const fn sflash_a2_size(self, _sflash_a2_size: u32) -> Self {
322        Self {
323            _sflash_a2_size,
324            ..self
325        }
326    }
327
328    pub const fn sflash_b1_size(self, _sflash_b1_size: u32) -> Self {
329        Self {
330            _sflash_b1_size,
331            ..self
332        }
333    }
334
335    pub const fn sflash_b2_size(self, _sflash_b2_size: u32) -> Self {
336        Self {
337            _sflash_b2_size,
338            ..self
339        }
340    }
341
342    pub const fn cs_pad_override(self, _cs_pad_override: u32) -> Self {
343        Self {
344            _cs_pad_override,
345            ..self
346        }
347    }
348
349    pub const fn sclk_pad_setting_override(self, _sclk_pad_setting_override: u32) -> Self {
350        Self {
351            _sclk_pad_setting_override,
352            ..self
353        }
354    }
355
356    pub const fn data_pad_setting_override(self, _data_pad_setting_override: u32) -> Self {
357        Self {
358            _data_pad_setting_override,
359            ..self
360        }
361    }
362
363    pub const fn dqs_pad_setting_override(self, _dqs_pad_setting_override: u32) -> Self {
364        Self {
365            _dqs_pad_setting_override,
366            ..self
367        }
368    }
369
370    pub const fn timeout_in_ms(self, _timeout_in_ms: u32) -> Self {
371        Self { _timeout_in_ms, ..self }
372    }
373
374    pub const fn command_interval(self, _command_interval: u32) -> Self {
375        Self {
376            _command_interval,
377            ..self
378        }
379    }
380
381    pub const fn data_valid_time(self, _data_valid_time: u32) -> Self {
382        Self {
383            _data_valid_time,
384            ..self
385        }
386    }
387
388    pub const fn busy_offset(self, _busy_offset: u16) -> Self {
389        Self { _busy_offset, ..self }
390    }
391
392    pub const fn busy_bit_polarity(self, _busy_bit_polarity: BusyBitPolarity) -> Self {
393        Self {
394            _busy_bit_polarity,
395            ..self
396        }
397    }
398
399    pub const fn lookup_table(self, _lookup_table: [u32; 64]) -> Self {
400        Self { _lookup_table, ..self }
401    }
402
403    pub const fn lut_custom_seq(self, _lut_custom_seq: [u8; 48]) -> Self {
404        Self {
405            _lut_custom_seq,
406            ..self
407        }
408    }
409
410    pub const fn page_size(self, _page_size: u32) -> Self {
411        Self { _page_size, ..self }
412    }
413
414    pub const fn sector_size(self, _sector_size: u32) -> Self {
415        Self { _sector_size, ..self }
416    }
417
418    pub const fn ipcmd_serial_clk_freq(self, _ipcmd_serial_clk_freq: u8) -> Self {
419        Self {
420            _ipcmd_serial_clk_freq,
421            ..self
422        }
423    }
424
425    pub const fn is_uniform_block_size(self, _is_uniform_block_size: u8) -> Self {
426        Self {
427            _is_uniform_block_size,
428            ..self
429        }
430    }
431
432    pub const fn is_data_order_swapped(self, _is_data_order_swapped: u8) -> Self {
433        Self {
434            _is_data_order_swapped,
435            ..self
436        }
437    }
438
439    pub const fn serial_nor_type(self, _serial_nor_type: SerialNORType) -> Self {
440        Self {
441            _serial_nor_type,
442            ..self
443        }
444    }
445
446    pub const fn need_exit_no_cmd_mode(self, _need_exit_no_cmd_mode: u8) -> Self {
447        Self {
448            _need_exit_no_cmd_mode,
449            ..self
450        }
451    }
452
453    pub const fn half_clk_for_non_read_cmd(self, _half_clk_for_non_read_cmd: u8) -> Self {
454        Self {
455            _half_clk_for_non_read_cmd,
456            ..self
457        }
458    }
459
460    pub const fn need_restore_no_cmd_mode(self, _need_restore_no_cmd_mode: u8) -> Self {
461        Self {
462            _need_restore_no_cmd_mode,
463            ..self
464        }
465    }
466
467    pub const fn block_size(self, _block_size: u32) -> Self {
468        Self { _block_size, ..self }
469    }
470
471    pub const fn flash_state_ctx(self, _flash_state_ctx: u32) -> Self {
472        Self {
473            _flash_state_ctx,
474            ..self
475        }
476    }
477}
478
479#[repr(u8)]
480pub enum ReadSampleClk {
481    InternalLoopback = 0,
482    LoopBackFromDQSPad = 1,
483    LoopBackFromSCKPad = 2,
484    ExternalDQSSignal = 3,
485}
486
487#[repr(u8)]
488pub enum ColumnAddressWidth {
489    Other = 0,
490    HyperFlash = 3,
491}
492
493#[repr(C)]
494#[repr(packed)]
495pub struct DeviceModeSeq {
496    num_seq: u8,
497    seq_index: u8,
498    reserved: [u8; 2],
499}
500
501impl DeviceModeSeq {
502    pub const fn build() -> Self {
503        Self {
504            num_seq: 1,
505            seq_index: 6,
506            reserved: [0; 2],
507        }
508    }
509}
510
511bitfield! {
512    pub struct ControllerMiscOption(u32);
513    impl Debug;
514
515    pub differential_clock, set_differential_clock: 0;
516    pub word_addressable, set_word_addressable: 3;
517    pub safe_config_freq, set_safe_config_freq: 4;
518    pub ddr_mode, set_ddr_mode: 6;
519}
520
521#[repr(u8)]
522pub enum DeviceType {
523    SerialNOR = 1,
524}
525
526#[repr(u8)]
527pub enum SFlashPadType {
528    SinglePad = 1,
529    DualPads = 2,
530    QuadPads = 4,
531    OctalPads = 8,
532}
533
534#[repr(u8)]
535pub enum SerialClkFreq {
536    SdrDdr30mhz = 1,
537    SdrDdr50mhz = 2,
538    SdrDdr60mhz = 3,
539    SdrDdr80mhz = 4,
540    SdrDdr100mhz = 5,
541    SdrDdr120mhz = 6,
542    SdrDdr133mhz = 7,
543    SdrDdr166mhz = 8,
544    SdrDdr200mhz = 9,
545}
546
547#[repr(u16)]
548pub enum BusyBitPolarity {
549    Normal = 0,
550    Inverted = 1,
551}
552
553#[repr(u8)]
554#[derive(Clone, Copy, PartialEq, Eq)]
555#[allow(non_camel_case_types)]
556pub enum FlexSpiLutOpcode {
557    CMD_SDR = 0x01,
558    CMD_DDR = 0x21,
559    RADDR_SDR = 0x02,
560    RADDR_DDR = 0x22,
561    CADDR_SDR = 0x03,
562    CADDR_DDR = 0x23,
563    MODE1_SDR = 0x04,
564    MODE1_DDR = 0x24,
565    MODE2_SDR = 0x05,
566    MODE2_DDR = 0x25,
567    MODE4_SDR = 0x06,
568    MODE4_DDR = 0x26,
569    MODE8_SDR = 0x07,
570    MODE8_DDR = 0x27,
571    WRITE_SDR = 0x08,
572    WRITE_DDR = 0x28,
573    READ_SDR = 0x09,
574    READ_DDR = 0x29,
575    LEARN_SDR = 0x0a,
576    LEARN_DDR = 0x2a,
577    DATSZ_SDR = 0x0b,
578    DATSZ_DDR = 0x2b,
579    DUMMY_SDR = 0x0c,
580    DUMMY_DDR = 0x2c,
581    DUMMY_RWDS_SDR = 0x0d,
582    DUMMY_RWDS_DDR = 0x2d,
583    JMP_ON_CS = 0x1f,
584    STOP = 0x00,
585}
586
587#[repr(u8)]
588#[derive(Clone, Copy, PartialEq, Eq)]
589pub enum FlexSpiNumPads {
590    Single = 0,
591    Dual = 1,
592    Quad = 2,
593    Octal = 3,
594}
595
596#[repr(u8)]
597pub enum SerialNORType {
598    StandardSpi = 0,
599    HyperBus = 1,
600    Xpi = 2,
601    NoCmd = 3,
602}
603
604#[inline(always)]
605pub const fn flexspi_lut_seq(
606    opcode0: FlexSpiLutOpcode,
607    num_pads0: FlexSpiNumPads,
608    operand0: u8,
609    opcode1: FlexSpiLutOpcode,
610    num_pads1: FlexSpiNumPads,
611    operand1: u8,
612) -> u32 {
613    let opcode0_raw = ((opcode0 as u32) << 10) & 0xfc00;
614    let num_pads0_raw = ((num_pads0 as u32) << 8) & 0x0300;
615    let operand0_raw = ((operand0 as u32) << 0) & 0xff;
616    let opcode1_raw = ((opcode1 as u32) << 26) & 0xfc000000;
617    let num_pads1_raw = ((num_pads1 as u32) << 24) & 0x3000000;
618    let operand1_raw = ((operand1 as u32) << 16) & 0xff0000;
619
620    opcode0_raw | num_pads0_raw | operand0_raw | opcode1_raw | num_pads1_raw | operand1_raw
621}