1use core::fmt;
15use kernel::utilities::registers::interfaces::Readable;
16use kernel::utilities::registers::{register_bitfields, ReadOnly};
17use kernel::utilities::StaticRef;
18
19const FICR_BASE: StaticRef<FicrRegisters> =
20    unsafe { StaticRef::new(0x10000000 as *const FicrRegisters) };
21
22#[repr(C)]
29struct FicrRegisters {
30    _reserved0: [u32; 4],
32    codepagesize: ReadOnly<u32, CodePageSize::Register>,
35    codesize: ReadOnly<u32, CodeSize::Register>,
38    _reserved1: [u32; 18],
40    deviceid0: ReadOnly<u32, DeviceId0::Register>,
43    deviceid1: ReadOnly<u32, DeviceId1::Register>,
46    _reserved2: [u32; 6],
48    er: [ReadOnly<u32, EncryptionRoot::Register>; 4],
51    ir: [ReadOnly<u32, IdentityRoot::Register>; 4],
54    deviceaddrtype: ReadOnly<u32, DeviceAddressType::Register>,
57    deviceaddr0: ReadOnly<u32, DeviceAddress0::Register>,
60    deviceaddr1: ReadOnly<u32, DeviceAddress1::Register>,
63    _reserved3: [u32; 21],
65    info_part: ReadOnly<u32, InfoPart::Register>,
68    info_variant: ReadOnly<u32, InfoVariant::Register>,
71    info_package: ReadOnly<u32, InfoPackage::Register>,
74    info_ram: ReadOnly<u32, InfoRam::Register>,
77    info_flash: ReadOnly<u32, InfoFlash::Register>,
80}
81
82register_bitfields! [u32,
83    CodePageSize [
85        CODEPAGESIZE OFFSET(0) NUMBITS(32)
87    ],
88    CodeSize [
90        CODESIZE OFFSET(0) NUMBITS(32)
92    ],
93    DeviceId0 [
95        DEVICEID OFFSET(0) NUMBITS(32)
97    ],
98    DeviceId1 [
100        DEVICEID OFFSET(0) NUMBITS(32)
102    ],
103    EncryptionRoot [
105        ER OFFSET(0) NUMBITS(32)
107    ],
108    IdentityRoot [
110        IR OFFSET(0) NUMBITS(32)
112    ],
113    DeviceAddressType [
115        DEVICEADDRESSTYPE OFFSET(0) NUMBITS(1) [
117            PUBLIC = 0,
119            RANDOM = 1
121        ]
122    ],
123    DeviceAddress0 [
125        DEVICEADDRESS OFFSET(0) NUMBITS(32)
127    ],
128    DeviceAddress1 [
130        DEVICEADDRESS OFFSET(0) NUMBITS(16)
132    ],
133    InfoPart [
135        PART OFFSET(0) NUMBITS(32) [
136            N52832 = 0x52832,
138            N52833 = 0x52833,
140            N52840 = 0x52840,
142            Unspecified = 0xffffffff
144        ]
145    ],
146    InfoVariant [
148        VARIANT OFFSET(0) NUMBITS(32) [
152            AAA0 = 0x41414130,
154            AAAA = 0x41414141,
156            AAAB = 0x41414142,
158            AAB0 = 0x41414230,
160            AABA = 0x41414241,
162            AABB = 0x41414242,
164            AAC0 = 0x41414330,
166            AACA = 0x41414341,
168            AACB = 0x41414342,
170            ABBA = 0x41424241,
172            AAD0 = 0x41414430,
174            AAD1 = 0x41414431,
176            AADA = 0x41414441,
178            AAE0 = 0x41414530,
180            AAEA = 0x41414541,
182            AAF0 = 0x41414630,
184            BAAA = 0x42414141,
186            CAAA = 0x43414141,
188            Unspecified = 0xffffffff
190        ]
191    ],
192    InfoPackage [
195        PACKAGE OFFSET(0) NUMBITS(32) [
196            QF = 0x2000,
198            CH = 0x2001,
200            CI = 0x2002,
202            QI = 0x2004,
204            CK = 0x2005,
206            Unspecified = 0xffffffff
208        ]
209    ],
210    InfoRam [
212        RAM OFFSET(0) NUMBITS(32) [
213            K16 = 0x10,
215            K32 = 0x20,
217            K64 = 0x40,
219            K128 = 0x80,
221            K256 = 0x100,
223            Unspecified = 0xffffffff
224
225        ]
226    ],
227    InfoFlash [
229        FLASH OFFSET(0) NUMBITS(32) [
230            K128 = 0x80,
232            K256 = 0x100,
234            K512 = 0x200,
236            K1024 = 0x400,
238            K2048 = 0x800,
240            Unspecified = 0xffffffff
242        ]
243    ]
244];
245
246#[derive(PartialEq, Debug)]
248#[repr(u32)]
249pub(crate) enum Variant {
250    AAA0 = 0x41414130,
251    AAAA = 0x41414141,
252    AAAB = 0x41414142,
253    AAB0 = 0x41414230,
254    AABA = 0x41414241,
255    AABB = 0x41414242,
256    AAC0 = 0x41414330,
257    AACA = 0x41414341,
258    AACB = 0x41414342,
259    AAD0 = 0x41414430,
260    AAD1 = 0x41414431,
261    AADA = 0x41414441,
262    AAE0 = 0x41414530,
263    AAEA = 0x41414541,
264    AAF0 = 0x41414630,
265    ABBA = 0x41424241,
266    BAAA = 0x42414141,
267    CAAA = 0x43414141,
268    Unspecified = 0xffffffff,
269}
270
271#[derive(PartialEq, Debug)]
272#[repr(u32)]
273enum Part {
274    N52832 = 0x52832,
275    N52833 = 0x52833,
276    N52840 = 0x52840,
277    Unspecified = 0xffffffff,
278}
279
280#[derive(PartialEq, Debug)]
281#[repr(u32)]
282enum Package {
283    QF = 0x2000,
284    CH = 0x2001,
285    CI = 0x2002,
286    QI = 0x2004,
287    CK = 0x2005,
288    Unspecified = 0xffffffff,
289}
290
291#[derive(PartialEq, Debug)]
292#[repr(u32)]
293enum Ram {
294    K16 = 0x10,
295    K32 = 0x20,
296    K64 = 0x40,
297    K128 = 0x80,
298    K256 = 0x100,
299    Unspecified = 0xffffffff,
300}
301
302#[derive(Debug)]
303#[repr(u32)]
304enum Flash {
305    K128 = 0x80,
306    K256 = 0x100,
307    K512 = 0x200,
308    K1024 = 0x400,
309    K2048 = 0x800,
310    Unspecified = 0xffffffff,
311}
312
313#[derive(Debug)]
314#[repr(u32)]
315pub enum AddressType {
316    Public = 0x0,
317    Random = 0x1,
318}
319
320pub struct Ficr {
321    registers: StaticRef<FicrRegisters>,
322}
323
324impl Ficr {
325    pub(crate) const fn new() -> Ficr {
326        Ficr {
327            registers: FICR_BASE,
328        }
329    }
330
331    fn part(&self) -> Part {
332        match self.registers.info_part.get() {
333            0x52832 => Part::N52832,
334            0x52833 => Part::N52833,
335            0x52840 => Part::N52840,
336            _ => Part::Unspecified,
337        }
338    }
339
340    pub(crate) fn variant(&self) -> Variant {
341        match self.registers.info_variant.get() {
344            0x41414130 => Variant::AAA0,
345            0x41414141 => Variant::AAAA,
346            0x41414142 => Variant::AAAB,
347            0x41414230 => Variant::AAB0,
348            0x41414241 => Variant::AABA,
349            0x41414242 => Variant::AABB,
350            0x41414330 => Variant::AAC0,
351            0x41414341 => Variant::AACA,
352            0x41414342 => Variant::AACB,
353            0x41424241 => Variant::ABBA,
354            0x41414430 => Variant::AAD0,
355            0x41414431 => Variant::AAD1,
356            0x41414441 => Variant::AADA,
357            0x41414530 => Variant::AAE0,
358            0x41414541 => Variant::AAEA,
359            0x41414630 => Variant::AAF0,
360            0x42414141 => Variant::BAAA,
361            0x43414141 => Variant::CAAA,
362            _ => Variant::Unspecified,
363        }
364    }
365
366    pub(crate) fn has_updated_approtect_logic(&self) -> bool {
373        match self.variant() {
376            Variant::AAF0 | Variant::Unspecified => true,
377            _ => false,
378        }
379    }
380
381    fn package(&self) -> Package {
382        match self.registers.info_package.get() {
383            0x2000 => Package::QF,
384            0x2001 => Package::CH,
385            0x2002 => Package::CI,
386            0x2004 => Package::QI,
387            0x2005 => Package::CK,
388            _ => Package::Unspecified,
389        }
390    }
391
392    fn ram(&self) -> Ram {
393        match self.registers.info_ram.get() {
394            0x10 => Ram::K16,
395            0x20 => Ram::K32,
396            0x40 => Ram::K64,
397            0x80 => Ram::K128,
398            0x100 => Ram::K256,
399            _ => Ram::Unspecified,
400        }
401    }
402
403    fn flash(&self) -> Flash {
404        match self.registers.info_flash.get() {
405            0x80 => Flash::K128,
406            0x100 => Flash::K256,
407            0x200 => Flash::K512,
408            0x400 => Flash::K1024,
409            0x800 => Flash::K2048,
410            _ => Flash::Unspecified,
411        }
412    }
413
414    pub fn id(&self) -> [u8; 8] {
415        let lo = self.registers.deviceid0.read(DeviceId0::DEVICEID);
416        let hi = self.registers.deviceid1.read(DeviceId1::DEVICEID);
417        let mut addr = [0; 8];
418        addr[..4].copy_from_slice(&lo.to_le_bytes());
419        addr[4..].copy_from_slice(&hi.to_le_bytes());
420        addr
421    }
422
423    pub fn address(&self) -> [u8; 6] {
424        let lo = self
425            .registers
426            .deviceaddr0
427            .read(DeviceAddress0::DEVICEADDRESS);
428        let hi = self
429            .registers
430            .deviceaddr1
431            .read(DeviceAddress1::DEVICEADDRESS) as u16;
432        let mut addr = [0; 6];
433        addr[..4].copy_from_slice(&lo.to_le_bytes());
434        addr[4..].copy_from_slice(&hi.to_le_bytes());
435        addr
436    }
437
438    pub fn address_type(&self) -> AddressType {
439        match self
440            .registers
441            .deviceaddrtype
442            .read(DeviceAddressType::DEVICEADDRESSTYPE)
443        {
444            0x0 => AddressType::Public,
445            _ => AddressType::Random,
446        }
447    }
448
449    pub fn address_str(&self, buf: &'static mut [u8; 17]) -> &'static str {
452        let lo = self
453            .registers
454            .deviceaddr0
455            .read(DeviceAddress0::DEVICEADDRESS);
456        let hi = self
457            .registers
458            .deviceaddr1
459            .read(DeviceAddress1::DEVICEADDRESS);
460
461        let h: [u8; 16] = *b"0123456789abcdef";
462
463        buf[0] = h[((hi >> 12) & 0xf) as usize];
464        buf[1] = h[((hi >> 8) & 0xf) as usize];
465        buf[2] = b':';
466        buf[3] = h[((hi >> 4) & 0xf) as usize];
467        buf[4] = h[((hi >> 0) & 0xf) as usize];
468        buf[5] = b':';
469        buf[6] = h[((lo >> 28) & 0xf) as usize];
470        buf[7] = h[((lo >> 24) & 0xf) as usize];
471        buf[8] = b':';
472        buf[9] = h[((lo >> 20) & 0xf) as usize];
473        buf[10] = h[((lo >> 16) & 0xf) as usize];
474        buf[11] = b':';
475        buf[12] = h[((lo >> 12) & 0xf) as usize];
476        buf[13] = h[((lo >> 8) & 0xf) as usize];
477        buf[14] = b':';
478        buf[15] = h[((lo >> 4) & 0xf) as usize];
479        buf[16] = h[((lo >> 0) & 0xf) as usize];
480
481        unsafe { &*(core::ptr::from_ref::<[u8]>(buf) as *const str) }
483    }
484}
485
486impl fmt::Display for Ficr {
487    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
488        write!(
489            f,
490            "NRF52 HW INFO: Variant: {:?}, Part: {:?}, Package: {:?}, Ram: {:?}, Flash: {:?}",
491            self.variant(),
492            self.part(),
493            self.package(),
494            self.ram(),
495            self.flash()
496        )
497    }
498}
499
500pub static mut FICR_INSTANCE: Ficr = Ficr::new();