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