1use crate::pm;
28use core::cell::Cell;
29use core::ops::{Index, IndexMut};
30use kernel::ErrorCode;
31use kernel::deferred_call::{DeferredCall, DeferredCallClient};
32use kernel::hil;
33use kernel::utilities::StaticRef;
34use kernel::utilities::cells::{OptionalCell, TakeCell};
35use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
36use kernel::utilities::registers::{
37 ReadOnly, ReadWrite, WriteOnly, register_bitfields, register_structs,
38};
39
40register_structs! {
41 FlashcalwRegisters {
43 (0x000 => fcr: ReadWrite<u32, FlashControl::Register>),
44 (0x004 => fcmd: ReadWrite<u32, FlashCommand::Register>),
45 (0x008 => fsr: ReadOnly<u32, FlashStatus::Register>),
46 (0x00C => fpr: ReadOnly<u32, FlashParameter::Register>),
47 (0x010 => fvr: ReadOnly<u32, FlashVersion::Register>),
48 (0x014 => fgpfrhi: ReadOnly<u32, FlashGeneralPurposeFuseHigh::Register>),
49 (0x018 => fgpfrlo: ReadOnly<u32, FlashGeneralPurposeFuseLow::Register>),
50 (0x01C => _reserved1: [u32; 251]),
51 (0x408 => ctrl: WriteOnly<u32, PicoCacheControl::Register>),
52 (0x40C => sr: ReadWrite<u32, PicoCacheStatus::Register>),
53 (0x410 => _reserved2: [u32; 4]),
54 (0x420 => maint0: WriteOnly<u32, PicoCacheMaintenance0::Register>),
55 (0x424 => maint1: WriteOnly<u32, PicoCacheMaintenance1::Register>),
56 (0x428 => mcfg: ReadWrite<u32, PicoCacheMonitorConfiguration::Register>),
57 (0x42C => men: ReadWrite<u32, PicoCacheMonitorEnable::Register>),
58 (0x430 => mctrl: WriteOnly<u32, PicoCacheMonitorStatus::Register>),
59 (0x434 => msr: ReadOnly<u32, PicoCacheMonitorStatus::Register>),
60 (0x438 => @END),
61 }
62}
63
64register_bitfields![u32,
65 FlashControl [
66 WS1OPT OFFSET(7) NUMBITS(1) [
68 NoOptimize = 0,
69 Optimize = 1
70 ],
71 FWS OFFSET(6) NUMBITS(1) [
73 ZeroWaitStates = 0,
74 OneWaitState = 1
75 ],
76 ECCE OFFSET(4) NUMBITS(1) [],
78 PROGE OFFSET(3) NUMBITS(1) [],
80 LOCKE OFFSET(2) NUMBITS(1) [],
82 FRDY OFFSET(0) NUMBITS(1) []
84 ],
85
86 FlashCommand [
87 KEY OFFSET(24) NUMBITS(8) [],
89 PAGEN OFFSET(8) NUMBITS(16) [],
91 CMD OFFSET(0) NUMBITS(6) [
93 NOP = 0,
94 WP = 1,
95 EP = 2,
96 CPB = 3,
97 LP = 4,
98 UP = 5,
99 EA = 6,
100 WGPB = 7,
101 EGPB = 8,
102 SSB = 9,
103 PGPFB = 10,
104 EAGPF = 11,
105 QPR = 12,
106 WUP = 13,
107 EUP = 14,
108 QPRUP = 15,
109 HSEN = 16,
110 HSDIS = 17
111 ]
112 ],
113
114 FlashStatus [
115 LOCK15 31,
117 LOCK14 30,
118 LOCK13 29,
119 LOCK12 28,
120 LOCK11 27,
121 LOCK10 26,
122 LOCK9 25,
123 LOCK8 24,
124 LOCK7 23,
125 LOCK6 22,
126 LOCK5 21,
127 LOCK4 20,
128 LOCK3 19,
129 LOCK2 18,
130 LOCK1 17,
131 LOCK0 16,
132 ECCERR 9,
136 HSMODE 6,
138 QPRR 5,
140 SECURITY 4,
142 PROGE 3,
144 LOCKE 2,
146 FRDY 0
148 ],
149
150 FlashParameter [
151 PSZ OFFSET(8) NUMBITS(3) [
153 Bytes32 = 0,
154 Bytes64 = 1,
155 Bytes128 = 2,
156 Bytes256 = 3,
157 Bytes512 = 4,
158 Bytes1024 = 5,
159 Bytes2048 = 6,
160 Bytes4096 = 7
161 ],
162 FSZ OFFSET(0) NUMBITS(4) [
164 KBytes4 = 0,
165 KBytes8 = 1,
166 KBytes16 = 2,
167 KBytes32 = 3,
168 KBytes48 = 4,
169 KBytes64 = 5,
170 KBytes96 = 6,
171 KBytes128 = 7,
172 KBytes192 = 8,
173 KBytes256 = 9,
174 KBytes384 = 10,
175 KBytes512 = 11,
176 KBytes768 = 12,
177 KBytes1024 = 13,
178 KBytes2048 = 14
179 ]
180 ],
181
182 FlashVersion [
183 VARIANT OFFSET(16) NUMBITS(4) [],
185 VERSION OFFSET(0) NUMBITS(12) []
187 ],
188
189 FlashGeneralPurposeFuseHigh [
190 GPF63 31,
192 GPF62 30,
193 GPF61 29,
194 GPF60 28,
195 GPF59 27,
196 GPF58 26,
197 GPF57 25,
198 GPF56 24,
199 GPF55 23,
200 GPF54 22,
201 GPF53 21,
202 GPF52 20,
203 GPF51 19,
204 GPF50 18,
205 GPF49 17,
206 GPF48 16,
207 GPF47 15,
208 GPF46 14,
209 GPF45 13,
210 GPF44 12,
211 GPF43 11,
212 GPF42 10,
213 GPF41 9,
214 GPF40 8,
215 GPF39 7,
216 GPF38 6,
217 GPF37 5,
218 GPF36 4,
219 GPF35 3,
220 GPF34 2,
221 GPF33 1,
222 GPF32 0
223 ],
224
225 FlashGeneralPurposeFuseLow [
226 GPF31 31,
227 GPF30 30,
228 GPF29 29,
229 GPF28 28,
230 GPF27 27,
231 GPF26 26,
232 GPF25 25,
233 GPF24 24,
234 GPF23 23,
235 GPF22 22,
236 GPF21 21,
237 GPF20 20,
238 GPF19 19,
239 GPF18 18,
240 GPF17 17,
241 GPF16 16,
242 GPF15 15,
243 GPF14 14,
244 GPF13 13,
245 GPF12 12,
246 GPF11 11,
247 GPF10 10,
248 GPF9 9,
249 GPF8 8,
250 GPF7 7,
251 GPF6 6,
252 GPF5 5,
253 GPF4 4,
254 GPF3 3,
255 GPF2 2,
256 GPF1 1,
257 GPF0 0
258 ],
259
260 PicoCacheControl [
261 CEN OFFSET(0) NUMBITS(1) [
263 Disable = 0,
264 Enable = 1
265 ]
266 ],
267
268 PicoCacheStatus [
269 CSTS OFFSET(0) NUMBITS(1) [
271 Disabled = 0,
272 Enabled = 1
273 ]
274 ],
275
276 PicoCacheMaintenance0 [
277 INVALL 0
279 ],
280
281 PicoCacheMaintenance1 [
282 INDEX OFFSET(4) NUMBITS(4) []
284 ],
285
286 PicoCacheMonitorConfiguration [
287 MODE OFFSET(0) NUMBITS(1) [
289 CycleCount = 0,
290 IhitCount = 1,
291 DhitCount = 2
292 ]
293 ],
294
295 PicoCacheMonitorEnable [
296 MENABLE OFFSET(0) NUMBITS(1) [
298 Disable = 0,
299 Enable = 1
300 ]
301 ],
302
303 PicoCacheMonitorControl [
304 SWRST 0
306 ],
307
308 PicoCacheMonitorStatus [
309 EVENTCNT OFFSET(0) NUMBITS(32) []
311 ]
312];
313
314const FLASHCALW_ADDRESS: StaticRef<FlashcalwRegisters> =
315 unsafe { StaticRef::new(0x400A0000 as *const FlashcalwRegisters) };
316
317#[allow(dead_code)]
318enum RegKey {
319 CONTROL,
320 COMMAND,
321 STATUS,
322 PARAMETER,
323 VERSION,
324 GPFRHI,
325 GPFRLO,
326}
327
328#[derive(Clone, Copy, PartialEq)]
332#[allow(dead_code)]
333enum FlashCMD {
334 NOP,
335 WP,
336 EP,
337 CPB,
338 LP,
339 UP,
340 EA,
341 WGPB,
342 EGPB,
343 SSB,
344 PGPFB,
345 EAGPF,
346 QPR,
347 WUP,
348 EUP,
349 QPRUP,
350 HSEN,
351 HSDIS,
352}
353
354#[derive(Clone, Copy, PartialEq)]
356enum FlashState {
357 Unconfigured, Ready, Read, WriteUnlocking { page: i32 }, WriteErasing { page: i32 }, WriteWriting, EraseUnlocking { page: i32 }, EraseErasing, }
366
367pub struct Sam4lPage(pub [u8; PAGE_SIZE as usize]);
381
382impl Default for Sam4lPage {
383 fn default() -> Self {
384 Self([0; PAGE_SIZE as usize])
385 }
386}
387
388impl Sam4lPage {
389 fn len(&self) -> usize {
390 self.0.len()
391 }
392}
393
394impl Index<usize> for Sam4lPage {
395 type Output = u8;
396
397 fn index(&self, idx: usize) -> &u8 {
398 &self.0[idx]
399 }
400}
401
402impl IndexMut<usize> for Sam4lPage {
403 fn index_mut(&mut self, idx: usize) -> &mut u8 {
404 &mut self.0[idx]
405 }
406}
407
408impl AsMut<[u8]> for Sam4lPage {
409 fn as_mut(&mut self) -> &mut [u8] {
410 &mut self.0
411 }
412}
413
414pub struct FLASHCALW {
416 registers: StaticRef<FlashcalwRegisters>,
417 ahb_clock: pm::Clock,
418 hramc1_clock: pm::Clock,
419 pb_clock: pm::Clock,
420 client: OptionalCell<&'static dyn hil::flash::Client<FLASHCALW>>,
421 current_state: Cell<FlashState>,
422 buffer: TakeCell<'static, Sam4lPage>,
423 deferred_call: DeferredCall,
424}
425
426const PAGE_SIZE: u32 = 512;
428
429const FREQ_PS2_FWS_0_MAX_FREQ: u32 = 24000000;
430
431impl FLASHCALW {
432 pub fn new(ahb_clk: pm::HSBClock, hramc1_clk: pm::HSBClock, pb_clk: pm::PBBClock) -> FLASHCALW {
433 FLASHCALW {
434 registers: FLASHCALW_ADDRESS,
435 ahb_clock: pm::Clock::HSB(ahb_clk),
436 hramc1_clock: pm::Clock::HSB(hramc1_clk),
437 pb_clock: pm::Clock::PBB(pb_clk),
438 client: OptionalCell::empty(),
439 current_state: Cell::new(FlashState::Unconfigured),
440 buffer: TakeCell::empty(),
441 deferred_call: DeferredCall::new(),
442 }
443 }
444
445 fn invalidate_cache(&self) {
448 self.registers
449 .maint0
450 .write(PicoCacheMaintenance0::INVALL::SET);
451 }
452
453 fn enable_picocache(&self, enable: bool) {
454 if enable {
455 self.registers.ctrl.write(PicoCacheControl::CEN::Enable);
456 } else {
457 self.registers.ctrl.write(PicoCacheControl::CEN::Disable);
458 }
459 }
460
461 pub fn enable_cache(&self) {
463 pm::enable_clock(pm::Clock::HSB(pm::HSBClock::FLASHCALWP));
465 pm::enable_clock(pm::Clock::PBB(pm::PBBClock::HRAMC1));
466
467 self.enable_picocache(true);
469 while !self.pico_enabled() {}
470 }
471
472 fn pico_enabled(&self) -> bool {
473 self.registers.sr.is_set(PicoCacheStatus::CSTS)
474 }
475
476 pub fn handle_interrupt(&self) {
477 self.registers.fcr.modify(FlashControl::FRDY::CLEAR);
479
480 if self.is_error() {
485 let attempted_operation = self.current_state.get();
486
487 self.current_state.set(FlashState::Ready);
489
490 self.client.map(|client| match attempted_operation {
491 FlashState::Read => {
492 self.buffer.take().map(|buffer| {
493 client.read_complete(buffer, Err(hil::flash::Error::FlashError));
494 });
495 }
496 FlashState::WriteUnlocking { .. }
497 | FlashState::WriteErasing { .. }
498 | FlashState::WriteWriting => {
499 self.buffer.take().map(|buffer| {
500 client.write_complete(buffer, Err(hil::flash::Error::FlashError));
501 });
502 }
503 FlashState::EraseUnlocking { .. } | FlashState::EraseErasing => {
504 client.erase_complete(Err(hil::flash::Error::FlashError));
505 }
506 _ => {}
507 });
508 }
509
510 match self.current_state.get() {
512 FlashState::Read => {
513 self.current_state.set(FlashState::Ready);
514
515 self.client.map(|client| {
516 self.buffer.take().map(|buffer| {
517 client.read_complete(buffer, Ok(()));
518 });
519 });
520 }
521 FlashState::WriteUnlocking { page } => {
522 self.current_state.set(FlashState::WriteErasing { page });
523 self.flashcalw_erase_page(page);
524 }
525 FlashState::WriteErasing { page } => {
526 self.clear_page_buffer();
531 self.write_to_page_buffer(page as usize * PAGE_SIZE as usize);
532
533 self.current_state.set(FlashState::WriteWriting);
534 self.flashcalw_write_page(page);
535 }
536 FlashState::WriteWriting => {
537 self.invalidate_cache();
539
540 self.current_state.set(FlashState::Ready);
541
542 self.client.map(|client| {
543 self.buffer.take().map(|buffer| {
544 client.write_complete(buffer, Ok(()));
545 });
546 });
547 }
548 FlashState::EraseUnlocking { page } => {
549 self.current_state.set(FlashState::EraseErasing);
550 self.flashcalw_erase_page(page);
551 }
552 FlashState::EraseErasing => {
553 self.invalidate_cache();
555
556 self.current_state.set(FlashState::Ready);
557
558 self.client.map(|client| {
559 client.erase_complete(Ok(()));
560 });
561 }
562 _ => {
563 self.current_state.set(FlashState::Ready);
564 }
565 }
566 }
567
568 fn get_flash_size(&self) -> u32 {
570 let flash_sizes = [
571 4, 8, 16, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 2048,
572 ];
573 flash_sizes[self.registers.fpr.read(FlashParameter::FSZ) as usize] << 10
575 }
576
577 pub fn set_wait_state(&self, wait_state: u32) {
579 self.registers.fcr.modify(FlashControl::FWS.val(wait_state));
580 }
581
582 fn enable_ws1_read_opt(&self, enable: bool) {
583 if enable {
584 self.registers.fcr.modify(FlashControl::WS1OPT::Optimize);
585 } else {
586 self.registers.fcr.modify(FlashControl::WS1OPT::NoOptimize);
587 }
588 }
589
590 fn set_flash_waitstate_and_readmode(&self, cpu_freq: u32, _ps_val: u32, _is_fwu_enabled: bool) {
593 if cpu_freq > FREQ_PS2_FWS_0_MAX_FREQ {
595 self.set_wait_state(1);
596 } else {
597 self.set_wait_state(0);
598 }
599
600 self.issue_command(FlashCMD::HSEN, -1);
601 }
602
603 pub fn enable_high_speed_flash(&self) {
605 self.registers.fcr.modify(FlashControl::FWS::OneWaitState);
608
609 self.registers
611 .fcmd
612 .modify(FlashCommand::KEY.val(0xA5) + FlashCommand::CMD::HSEN);
613
614 while !self.registers.fsr.is_set(FlashStatus::FRDY) {}
616 }
617
618 fn is_error(&self) -> bool {
620 pm::enable_clock(self.pb_clock);
621 self.registers.fsr.is_set(FlashStatus::LOCKE)
622 | self.registers.fsr.is_set(FlashStatus::PROGE)
623 }
624
625 fn issue_command(&self, command: FlashCMD, page_number: i32) {
627 pm::enable_clock(self.pb_clock);
628 if command != FlashCMD::QPRUP
633 && command != FlashCMD::QPR
634 && command != FlashCMD::CPB
635 && command != FlashCMD::HSEN
636 {
637 self.registers.fcr.modify(FlashControl::FRDY::SET);
639 }
640
641 let mut cmd = FlashCommand::KEY.val(0xA5) + FlashCommand::CMD.val(command as u32);
643
644 if page_number >= 0 {
647 cmd += FlashCommand::PAGEN.val(page_number as u32);
648 }
649
650 self.registers.fcmd.write(cmd);
651
652 if command == FlashCMD::QPRUP
656 || command == FlashCMD::QPR
657 || command == FlashCMD::CPB
658 || command == FlashCMD::HSEN
659 {
660 while !self.registers.fsr.is_set(FlashStatus::FRDY) {}
661 }
662 }
663
664 fn lock_page_region(&self, page_number: i32, lock: bool) {
666 if lock {
667 self.issue_command(FlashCMD::LP, page_number);
668 } else {
669 self.issue_command(FlashCMD::UP, page_number);
670 }
671 }
672
673 fn clear_page_buffer(&self) {
675 self.issue_command(FlashCMD::CPB, -1);
676 }
677
678 fn is_page_erased(&self) -> bool {
679 self.registers.fsr.is_set(FlashStatus::QPRR)
680 }
681
682 fn flashcalw_erase_page(&self, page_number: i32) {
683 self.issue_command(FlashCMD::EP, page_number);
684 }
685
686 fn flashcalw_write_page(&self, page_number: i32) {
687 self.issue_command(FlashCMD::WP, page_number);
688 }
689
690 #[allow(dead_code)]
693 fn quick_user_page_read(&self) -> bool {
694 self.issue_command(FlashCMD::QPRUP, -1);
695 self.is_page_erased()
696 }
697
698 #[allow(dead_code)]
699 fn erase_user_page(&self, check: bool) -> bool {
700 self.issue_command(FlashCMD::EUP, -1);
701 if check {
702 self.quick_user_page_read()
703 } else {
704 true
705 }
706 }
707
708 #[allow(dead_code)]
709 fn write_user_page(&self) {
710 self.issue_command(FlashCMD::WUP, -1);
711 }
712
713 fn write_to_page_buffer(&self, pg_buff_addr: usize) {
716 let mut page_buffer: *mut u8 = pg_buff_addr as *mut u8;
717
718 let cleared_double_word: [u8; 8] = [255; 8];
721 let clr_ptr: *const u8 = core::ptr::from_ref::<u8>(&cleared_double_word[0]);
722
723 self.buffer.map(|buffer| {
724 unsafe {
725 use core::ptr;
726
727 let mut start_buffer: *const u8 = core::ptr::from_ref::<u8>(&buffer[0]);
728 let mut data_transfered: u32 = 0;
729 while data_transfered < PAGE_SIZE {
730 ptr::copy(clr_ptr, page_buffer, 8);
732
733 ptr::copy(start_buffer, page_buffer, 8);
735 page_buffer = page_buffer.add(8);
736 start_buffer = start_buffer.add(8);
737 data_transfered += 8;
738 }
739 }
740 });
741 }
742}
743
744impl FLASHCALW {
746 pub fn configure(&self) {
747 pm::enable_clock(self.ahb_clock);
749 pm::enable_clock(self.hramc1_clock);
750 pm::enable_clock(self.pb_clock);
751
752 self.registers.fcr.modify(
755 FlashControl::FRDY::CLEAR
756 + FlashControl::LOCKE::CLEAR
757 + FlashControl::PROGE::CLEAR
758 + FlashControl::ECCE::CLEAR,
759 );
760
761 self.enable_ws1_read_opt(true);
763 self.set_flash_waitstate_and_readmode(48_000_000, 0, false);
765
766 self.enable_picocache(true);
770
771 self.current_state.set(FlashState::Ready);
772 }
773
774 fn read_range(
776 &self,
777 address: usize,
778 size: usize,
779 buffer: &'static mut Sam4lPage,
780 ) -> Result<(), (ErrorCode, &'static mut Sam4lPage)> {
781 if self.current_state.get() == FlashState::Unconfigured {
782 self.configure();
783 }
784
785 pm::enable_clock(self.ahb_clock);
787
788 let Some(end_address) = address.checked_add(size) else {
790 return Err((ErrorCode::INVAL, buffer));
791 };
792 if end_address > (self.get_flash_size() as usize) || buffer.len() < size {
793 return Err((ErrorCode::INVAL, buffer));
794 }
795
796 let mut byte: *const u8 = address as *const u8;
798 unsafe {
799 for i in 0..size {
800 buffer[i] = *byte;
801 byte = byte.add(1);
802 }
803 }
804
805 self.current_state.set(FlashState::Read);
806 self.buffer.replace(buffer);
808
809 self.deferred_call.set();
813
814 Ok(())
815 }
816
817 fn write_page(
818 &self,
819 page_num: i32,
820 data: &'static mut Sam4lPage,
821 ) -> Result<(), (ErrorCode, &'static mut Sam4lPage)> {
822 pm::enable_clock(self.ahb_clock);
824
825 match self.current_state.get() {
826 FlashState::Unconfigured => self.configure(),
827 FlashState::Ready => {}
828 _ => return Err((ErrorCode::BUSY, data)),
830 }
831
832 self.buffer.replace(data);
834
835 self.current_state
836 .set(FlashState::WriteUnlocking { page: page_num });
837 self.lock_page_region(page_num, false);
838 Ok(())
839 }
840
841 fn erase_page(&self, page_num: i32) -> Result<(), ErrorCode> {
842 pm::enable_clock(self.ahb_clock);
844
845 match self.current_state.get() {
846 FlashState::Unconfigured => self.configure(),
847 FlashState::Ready => {}
848 _ => return Err(ErrorCode::BUSY),
850 }
851
852 self.current_state
853 .set(FlashState::EraseUnlocking { page: page_num });
854 self.lock_page_region(page_num, false);
855 Ok(())
856 }
857}
858
859impl DeferredCallClient for FLASHCALW {
860 fn handle_deferred_call(&self) {
861 self.handle_interrupt();
862 }
863
864 fn register(&'static self) {
865 self.deferred_call.register(self);
866 }
867}
868
869impl<C: hil::flash::Client<Self>> hil::flash::HasClient<'static, C> for FLASHCALW {
870 fn set_client(&self, client: &'static C) {
871 self.client.set(client);
872 }
873}
874
875impl hil::flash::Flash for FLASHCALW {
876 type Page = Sam4lPage;
877
878 fn read_page(
879 &self,
880 page_number: usize,
881 buf: &'static mut Self::Page,
882 ) -> Result<(), (ErrorCode, &'static mut Self::Page)> {
883 self.read_range(page_number * (PAGE_SIZE as usize), buf.len(), buf)
884 }
885
886 fn write_page(
887 &self,
888 page_number: usize,
889 buf: &'static mut Self::Page,
890 ) -> Result<(), (ErrorCode, &'static mut Self::Page)> {
891 self.write_page(page_number as i32, buf)
892 }
893
894 fn erase_page(&self, page_number: usize) -> Result<(), ErrorCode> {
895 self.erase_page(page_number as i32)
896 }
897}