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 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 flexspi_lut_seq(CMD_SDR, Single, 0x05, READ_SDR, Single, 0x04),
115 0,
116 0,
117 0,
118 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 flexspi_lut_seq(CMD_SDR, Single, 0x06, STOP, Single, 0x00),
125 0,
126 0,
127 0,
128 flexspi_lut_seq(CMD_DDR, Octal, 0x06, CMD_DDR, Octal, 0xF9),
130 0,
131 0,
132 0,
133 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 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 0,
145 0,
146 0,
147 0,
148 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 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 0,
160 0,
161 0,
162 0,
163 flexspi_lut_seq(CMD_DDR, Octal, 0x60, CMD_DDR, Octal, 0x9F),
165 0,
166 0,
167 0,
168 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}