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}