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();