1use crate::clocks::{phclk, Stm32f4Clocks};
6use core::cell::Cell;
7use kernel::deferred_call::{DeferredCall, DeferredCallClient};
8use kernel::hil::bus8080::{Bus8080, BusAddr8080, BusWidth, Client};
9use kernel::platform::chip::ClockInterface;
10use kernel::utilities::cells::{OptionalCell, TakeCell};
11use kernel::utilities::registers::interfaces::{ReadWriteable, Readable};
12use kernel::utilities::registers::{register_bitfields, ReadWrite};
13use kernel::utilities::StaticRef;
14use kernel::ErrorCode;
15
16#[repr(C)]
18struct FsmcBankRegisters {
19 bcr1: ReadWrite<u32, BCR::Register>,
21 btr1: ReadWrite<u32, BTR::Register>,
23 bcr2: ReadWrite<u32, BCR::Register>,
25 btr2: ReadWrite<u32, BTR::Register>,
27 bcr3: ReadWrite<u32, BCR::Register>,
29 btr3: ReadWrite<u32, BTR::Register>,
31 bcr4: ReadWrite<u32, BCR::Register>,
33 btr4: ReadWrite<u32, BTR::Register>,
35 _reseved: [u8; 228],
36 bwtr1: ReadWrite<u32, BWTR::Register>,
38 bwtr2: ReadWrite<u32, BWTR::Register>,
40 bwtr3: ReadWrite<u32, BWTR::Register>,
42 bwtr4: ReadWrite<u32, BWTR::Register>,
44}
45
46register_bitfields![u32,
47 BCR [
48 WFDIS OFFSET(21) NUMBITS(1) [],
50 CCLKEN OFFSET(20) NUMBITS(1) [],
52 CBURSTRW OFFSET(19) NUMBITS(1) [],
54 CPSIZE OFFSET(16) NUMBITS(3) [
56 NO_BURST = 0b000,
57 BYTES_128 = 0b001,
58 BYTES_256 = 0b010,
59 BYTES_1024 = 0b011
60 ],
61 ASYNCWAIT OFFSET(15) NUMBITS(1) [],
63 EXTMOD OFFSET(14) NUMBITS(1) [],
65 WAITEN OFFSET(13) NUMBITS(1) [],
67 WREN OFFSET(12) NUMBITS(1) [],
69 WAITCFG OFFSET(11) NUMBITS(1) [],
71 WAITPOL OFFSET(9) NUMBITS(1) [],
73 BURSTEN OFFSET(8) NUMBITS(1) [],
75 FACCEN OFFSET(6) NUMBITS(1) [],
78 MWID OFFSET(4) NUMBITS(2) [
80 BITS_8 = 0b00,
81 BITS_16 = 0b01
82 ],
83 MTYP OFFSET(2) NUMBITS(2) [
85 SRAM = 0b00,
86 PSRAM = 0b01,
87 NOR = 0b10
88 ],
89 MUXEN OFFSET(1) NUMBITS(1) [],
91 MBKEN OFFSET(0) NUMBITS(1) []
93 ],
94 BTR [
95 ACCMOD OFFSET(28) NUMBITS(2) [
97 A = 0b00,
98 B = 0b01,
99 C = 0b10,
100 D = 0b11
101 ],
102 DATLAT OFFSET(24) NUMBITS(4) [],
104 CLKDIV OFFSET(20) NUMBITS(4) [],
106 BUSTURN OFFSET(16) NUMBITS(4) [],
108 DATAST OFFSET(8) NUMBITS(8) [],
110 ADDHLD OFFSET(4) NUMBITS(4) [],
112 ADDSET OFFSET(0) NUMBITS(4) []
114 ],
115 BWTR [
116 ACCMOD OFFSET(28) NUMBITS(2) [
118 A = 0b00,
119 B = 0b01,
120 C = 0b10,
121 D = 0b11
122 ],
123 BUSTURN OFFSET(16) NUMBITS(4) [],
124 DATAST OFFSET(8) NUMBITS(8) [],
126 ADDHLD OFFSET(4) NUMBITS(4) [],
128 ADDSET OFFSET(0) NUMBITS(4) []
130 ]
131];
132
133const FSMC_BASE: StaticRef<FsmcBankRegisters> =
134 unsafe { StaticRef::new(0xA000_0000 as *const FsmcBankRegisters) };
135
136#[repr(C)]
138pub struct FsmcBank {
139 reg: ReadWrite<u16>,
141 ram: ReadWrite<u16>,
143}
144
145#[repr(usize)]
146pub enum FsmcBanks {
147 Bank1 = 0,
148 Bank2 = 1,
149 Bank3 = 2,
150 Bank4 = 3,
151}
152
153pub const FSMC_BANK1: StaticRef<FsmcBank> =
154 unsafe { StaticRef::new(0x60000000 as *const FsmcBank) };
155pub const FSMC_BANK3: StaticRef<FsmcBank> =
157 unsafe { StaticRef::new(0x68000000 as *const FsmcBank) };
158pub struct Fsmc<'a> {
161 registers: StaticRef<FsmcBankRegisters>,
162 bank: [Option<StaticRef<FsmcBank>>; 4],
163 clock: FsmcClock<'a>,
164
165 client: OptionalCell<&'static dyn Client>,
166
167 buffer: TakeCell<'static, [u8]>,
168 bus_width: Cell<usize>,
169 len: Cell<usize>,
170
171 deferred_call: DeferredCall,
172}
173
174impl<'a> Fsmc<'a> {
175 pub fn new(bank_addr: [Option<StaticRef<FsmcBank>>; 4], clocks: &'a dyn Stm32f4Clocks) -> Self {
176 Self {
177 registers: FSMC_BASE,
178 bank: bank_addr,
179 clock: FsmcClock(phclk::PeripheralClock::new(
180 phclk::PeripheralClockType::AHB3(phclk::HCLK3::FMC),
181 clocks,
182 )),
183 client: OptionalCell::empty(),
184
185 buffer: TakeCell::empty(),
186 bus_width: Cell::new(1),
187 len: Cell::new(0),
188
189 deferred_call: DeferredCall::new(),
190 }
191 }
192
193 pub fn enable(&self) {
194 self.registers.bcr1.modify(
195 BCR::MBKEN::SET
196 + BCR::MUXEN::CLEAR
197 + BCR::MTYP::SRAM
198 + BCR::MWID::BITS_16
199 + BCR::BURSTEN::CLEAR
200 + BCR::WAITPOL::CLEAR
201 + BCR::WAITCFG::CLEAR
202 + BCR::WREN::SET
203 + BCR::WAITEN::CLEAR
204 + BCR::EXTMOD::SET
205 + BCR::ASYNCWAIT::CLEAR
206 + BCR::CBURSTRW::CLEAR
207 + BCR::WFDIS::SET
208 + BCR::CPSIZE::NO_BURST
209 + BCR::CCLKEN::CLEAR,
210 );
211 self.registers.btr1.modify(
212 BTR::ADDSET.val(9)
213 + BTR::ADDHLD.val(1)
214 + BTR::DATAST.val(36)
215 + BTR::BUSTURN.val(1)
216 + BTR::CLKDIV.val(2)
217 + BTR::DATLAT.val(2)
218 + BTR::ACCMOD::A,
219 );
220 self.registers.bwtr1.modify(
221 BWTR::ADDSET.val(1)
222 + BWTR::ADDHLD.val(1)
223 + BWTR::DATAST.val(7)
224 + BWTR::BUSTURN.val(0)
225 + BWTR::ACCMOD::A,
226 );
227 self.enable_clock();
228 }
229
230 pub fn disable(&self) {
231 self.disable_clock();
232 }
233
234 pub fn enable_clock(&self) {
235 self.clock.enable();
236 }
237
238 pub fn disable_clock(&self) {
239 self.clock.disable();
240 }
241
242 #[inline]
243 pub fn read_reg(&self, bank: FsmcBanks) -> Option<u16> {
244 self.bank[bank as usize].map_or(None, |bank| Some(bank.ram.get()))
245 }
246
247 #[cfg(any(doc, all(target_arch = "arm", target_os = "none")))]
248 #[inline]
249 fn write_reg(&self, bank: FsmcBanks, addr: u16) {
250 use kernel::utilities::registers::interfaces::Writeable;
251 self.bank[bank as usize].map(|bank| bank.reg.set(addr));
252 unsafe {
253 use core::arch::asm;
254 asm!("dsb 0xf");
255 }
256 }
257
258 #[cfg(any(doc, all(target_arch = "arm", target_os = "none")))]
259 #[inline]
260 fn write_data(&self, bank: FsmcBanks, data: u16) {
261 use kernel::utilities::registers::interfaces::Writeable;
262 self.bank[bank as usize].map(|bank| bank.ram.set(data));
263 unsafe {
264 use core::arch::asm;
265 asm!("dsb 0xf");
266 }
267 }
268
269 #[cfg(not(any(doc, all(target_arch = "arm", target_os = "none"))))]
270 fn write_reg(&self, _bank: FsmcBanks, _addr: u16) {
271 unimplemented!()
272 }
273
274 #[cfg(not(any(doc, all(target_arch = "arm", target_os = "none"))))]
275 fn write_data(&self, _bank: FsmcBanks, _data: u16) {
276 unimplemented!()
277 }
278}
279
280impl DeferredCallClient for Fsmc<'_> {
281 fn register(&'static self) {
282 self.deferred_call.register(self);
283 }
284
285 fn handle_deferred_call(&self) {
286 self.buffer.take().map_or_else(
287 || {
288 self.client.map(move |client| {
289 client.command_complete(None, 0, Ok(()));
290 });
291 },
292 |buffer| {
293 self.client.map(move |client| {
294 client.command_complete(Some(buffer), self.len.get(), Ok(()));
295 });
296 },
297 );
298 }
299}
300
301struct FsmcClock<'a>(phclk::PeripheralClock<'a>);
302
303impl ClockInterface for FsmcClock<'_> {
304 fn is_enabled(&self) -> bool {
305 self.0.is_enabled()
306 }
307
308 fn enable(&self) {
309 self.0.enable();
310 }
311
312 fn disable(&self) {
313 self.0.disable();
314 }
315}
316
317impl Bus8080<'static> for Fsmc<'_> {
318 fn set_addr(&self, addr: BusAddr8080) -> Result<(), ErrorCode> {
319 match addr {
320 BusAddr8080::BusAddr8(addr) => {
321 self.write_reg(FsmcBanks::Bank1, addr as u16);
322 self.deferred_call.set();
323 Ok(())
324 }
325 _ => Err(ErrorCode::NOSUPPORT),
326 }
327 }
328
329 fn write(
330 &self,
331 data_width: BusWidth,
332 buffer: &'static mut [u8],
333 len: usize,
334 ) -> Result<(), (ErrorCode, &'static mut [u8])> {
335 let bytes = data_width.width_in_bytes();
336 if buffer.len() >= len * bytes {
337 for pos in 0..len {
338 let mut data: u16 = 0;
339 for byte in 0..bytes {
340 data |= (buffer[bytes * pos
341 + match data_width {
342 BusWidth::Bits8 | BusWidth::Bits16LE => byte,
343 BusWidth::Bits16BE => bytes - byte - 1,
344 }] as u16)
345 << (8 * byte);
346 }
347 self.write_data(FsmcBanks::Bank1, data);
348 }
349 self.buffer.replace(buffer);
350 self.bus_width.set(bytes);
351 self.len.set(len);
352 self.deferred_call.set();
353 Ok(())
354 } else {
355 Err((ErrorCode::NOMEM, buffer))
356 }
357 }
358
359 fn read(
360 &self,
361 data_width: BusWidth,
362 buffer: &'static mut [u8],
363 len: usize,
364 ) -> Result<(), (ErrorCode, &'static mut [u8])> {
365 let bytes = data_width.width_in_bytes();
366 if buffer.len() >= len * bytes {
367 for pos in 0..len {
368 if let Some(data) = self.read_reg(FsmcBanks::Bank1) {
369 for byte in 0..bytes {
370 buffer[bytes * pos
371 + match data_width {
372 BusWidth::Bits8 | BusWidth::Bits16LE => byte,
373 BusWidth::Bits16BE => bytes - byte - 1,
374 }] = (data >> (8 * byte)) as u8;
375 }
376 } else {
377 return Err((ErrorCode::NOMEM, buffer));
378 }
379 }
380 self.buffer.replace(buffer);
381 self.bus_width.set(bytes);
382 self.len.set(len);
383 self.deferred_call.set();
384 Ok(())
385 } else {
386 Err((ErrorCode::NOMEM, buffer))
387 }
388 }
389
390 fn set_client(&self, client: &'static dyn Client) {
391 self.client.replace(client);
392 }
393}