1use crate::pm;
9use kernel::ErrorCode;
10use kernel::hil::entropy::{self, Continue};
11use kernel::utilities::StaticRef;
12use kernel::utilities::cells::OptionalCell;
13use kernel::utilities::registers::interfaces::{Readable, Writeable};
14use kernel::utilities::registers::{ReadOnly, WriteOnly, register_bitfields, register_structs};
15
16register_structs! {
17 TrngRegisters {
18 (0x000 => cr: WriteOnly<u32, Control::Register>),
19 (0x004 => _reserved0: [u32; 3]),
20 (0x010 => ier: WriteOnly<u32, Interrupt::Register>),
21 (0x014 => idr: WriteOnly<u32, Interrupt::Register>),
22 (0x018 => imr: ReadOnly<u32, Interrupt::Register>),
23 (0x01C => isr: ReadOnly<u32, Interrupt::Register>),
24 (0x020 => _reserved1: [u32; 12]),
25 (0x050 => odata: ReadOnly<u32, OutputData::Register>),
26 (0x054 => @END),
27 }
28}
29
30register_bitfields![u32,
31 Control [
32 KEY OFFSET(8) NUMBITS(24) [],
34 ENABLE OFFSET(0) NUMBITS(1) [
36 Disable = 0,
37 Enable = 1
38 ]
39 ],
40
41 Interrupt [
42 DATRDY 0
44 ],
45
46 OutputData [
47 ODATA OFFSET(0) NUMBITS(32) []
49 ]
50];
51
52const BASE_ADDRESS: StaticRef<TrngRegisters> =
53 unsafe { StaticRef::new(0x40068000 as *const TrngRegisters) };
54
55pub struct Trng<'a> {
56 regs: StaticRef<TrngRegisters>,
57 client: OptionalCell<&'a dyn entropy::Client32>,
58}
59
60const KEY: u32 = 0x524e47;
61
62impl<'a> Trng<'a> {
63 pub const fn new() -> Trng<'a> {
64 Trng {
65 regs: BASE_ADDRESS,
66 client: OptionalCell::empty(),
67 }
68 }
69
70 pub fn handle_interrupt(&self) {
71 self.regs.idr.write(Interrupt::DATRDY::SET);
72
73 self.client.map(|client| {
74 let result = client.entropy_available(&mut TrngIter(self), Ok(()));
75 if let Continue::Done = result {
76 self.regs
78 .cr
79 .write(Control::KEY.val(KEY) + Control::ENABLE::Disable);
80 pm::disable_clock(pm::Clock::PBA(pm::PBAClock::TRNG));
81 } else {
82 self.regs.ier.write(Interrupt::DATRDY::SET);
83 }
84 });
85 }
86}
87
88struct TrngIter<'a, 'b: 'a>(&'a Trng<'b>);
89
90impl Iterator for TrngIter<'_, '_> {
91 type Item = u32;
92
93 fn next(&mut self) -> Option<u32> {
94 if self.0.regs.isr.is_set(Interrupt::DATRDY) {
95 Some(self.0.regs.odata.read(OutputData::ODATA))
96 } else {
97 None
98 }
99 }
100}
101
102impl<'a> entropy::Entropy32<'a> for Trng<'a> {
103 fn get(&self) -> Result<(), ErrorCode> {
104 pm::enable_clock(pm::Clock::PBA(pm::PBAClock::TRNG));
105
106 self.regs
107 .cr
108 .write(Control::KEY.val(KEY) + Control::ENABLE::Enable);
109 self.regs.ier.write(Interrupt::DATRDY::SET);
110 Ok(())
111 }
112
113 fn cancel(&self) -> Result<(), ErrorCode> {
114 Err(ErrorCode::FAIL)
115 }
116
117 fn set_client(&'a self, client: &'a dyn entropy::Client32) {
118 self.client.set(client);
119 }
120}