1use super::common;
6use super::State as BusState;
7use super::{CYW4343xBus, CYW4343xBusClient, Function, RegLen, Type};
8use crate::cyw4343::constants;
9use crate::cyw4343::macros::{backplane_window_bits, reset_and_restore_bufs};
10use core::cell::Cell;
11use kernel::hil::spi::{SpiMasterClient, SpiMasterDevice};
12use kernel::hil::time::ConvertTicks;
13use kernel::hil::{gpio, time};
14use kernel::utilities::leasable_buffer::SubSliceMut;
15use kernel::utilities::registers::register_bitfields;
16use kernel::{utilities::cells::OptionalCell, ErrorCode};
17use task::GspiTask;
18
19pub const MAX_PACKET_SIZE: usize = MAX_PAYLOAD_SIZE + CMD_SIZE;
21
22const MAX_PAYLOAD_SIZE: usize = 2048;
27
28pub const WORD_SIZE: usize = 4;
30const CMD_SIZE: usize = WORD_SIZE;
32const STATUS_SIZE: usize = WORD_SIZE;
34
35register_bitfields![u32,
37 CYW43SPI_CMD [
38 COMMAND OFFSET(31) NUMBITS(1) [],
39 ACCESS OFFSET(30) NUMBITS(1) [
40 IncAddr = 1,
41 ],
42 FUNCTION_NUM OFFSET(28) NUMBITS(2) [],
43 ADDRESS OFFSET(11) NUMBITS(17) [],
44 LENGTH OFFSET(0) NUMBITS(11) [],
45 ]
46];
47
48const fn cmd32(command: Type, function: Function, address: u32, length: u32) -> u32 {
50 CYW43SPI_CMD::COMMAND.val(command as u32).value
51 | CYW43SPI_CMD::ACCESS::IncAddr.value
52 | CYW43SPI_CMD::FUNCTION_NUM.val(function as u32).value
53 | CYW43SPI_CMD::ADDRESS.val(address).value
54 | CYW43SPI_CMD::LENGTH.val(length).value
55}
56
57const fn cmd16(command: Type, function: Function, address: u32, length: u32) -> u32 {
59 cmd32(command, function, address, length).rotate_left(16)
60}
61
62#[derive(Clone, Copy, Debug, Default)]
63enum State {
64 NotInit,
65 Init(u8),
66 Irq,
67 Write,
68 Read,
69 #[default]
70 Idle,
71}
72
73struct Backplane {
74 curr_window: Cell<u32>,
76 pending_window: OptionalCell<(u32, u8)>,
78 transfer_offset: Cell<usize>,
81 pending: Cell<bool>,
83}
84
85impl Backplane {
86 fn new() -> Self {
87 Self {
88 curr_window: Cell::new(0xAAAA_AAAA),
89 pending_window: OptionalCell::empty(),
90 transfer_offset: Cell::new(0),
91 pending: Cell::new(false),
92 }
93 }
94}
95
96pub struct CYW4343xSpiBus<'a, S: SpiMasterDevice<'a>, A: kernel::hil::time::Alarm<'a>> {
100 gspi: &'a S,
101 alarm: &'a A,
102 client: OptionalCell<&'a dyn CYW4343xBusClient>,
103 backplane: Backplane,
105 inner_state: Cell<State>,
107 state: Cell<BusState>,
109 read: OptionalCell<(fn(u32, &mut u8), u8)>,
112 extra: OptionalCell<SubSliceMut<'static, u8>>,
114 data: OptionalCell<SubSliceMut<'static, u8>>,
116 wlan: OptionalCell<SubSliceMut<'static, u8>>,
118 fw: &'static [u8],
120 len: OptionalCell<usize>,
122 nvram: (&'static [u8], u32, u32),
124 irq_fired: Cell<bool>,
126}
127
128impl<'a, S: SpiMasterDevice<'a>, A: kernel::hil::time::Alarm<'a>> CYW4343xSpiBus<'a, S, A> {
129 pub fn new(
130 gspi: &'a S,
131 alarm: &'a A,
132 extra: &'static mut [u8; CMD_SIZE],
133 buffer: &'static mut [u8; MAX_PACKET_SIZE],
134 fw: &'static [u8],
135 nvram: &'static [u8],
136 ) -> Self {
137 let nvram_len = nvram.len().div_ceil(4) * 4;
138 let nvram_words = nvram_len / 4;
139 let nvram_magic = (!nvram_words << 16) | nvram_words;
140 Self {
141 gspi,
142 alarm,
143 backplane: Backplane::new(),
144 extra: OptionalCell::new(SubSliceMut::new(extra)),
145 data: OptionalCell::new(SubSliceMut::new(buffer)),
146 client: OptionalCell::empty(),
147 inner_state: Cell::new(State::NotInit),
148 state: Cell::new(BusState::Idle),
149 read: OptionalCell::empty(),
150 wlan: OptionalCell::empty(),
151 nvram: (
152 nvram,
153 constants::NVRAM_END - (nvram_len as u32),
154 nvram_magic as u32,
155 ),
156 fw,
157 irq_fired: Cell::new(false),
158 len: OptionalCell::empty(),
159 }
160 }
161}
162
163impl<'a, S: SpiMasterDevice<'a>, A: kernel::hil::time::Alarm<'a>> CYW4343xSpiBus<'a, S, A> {
164 fn do_task(&self, task: GspiTask) -> Result<(), ErrorCode> {
166 match task {
167 GspiTask::ReadBackplane(cmd, addr, jmp) => {
168 self.update_bp_window_or_else(backplane_window_bits!(addr), || {
169 self.read.insert(jmp.map(|jmp| (jmp, WORD_SIZE as _)));
170 self.read(Function::Backplane, cmd)
171 })
172 }
173 GspiTask::WriteBackplane(cmd, addr, val) => {
174 self.update_bp_window_or_else(backplane_window_bits!(addr), || self.write(cmd, val))
175 }
176 GspiTask::Read(fun, cmd, jmp) => {
177 let pos = if matches!(fun, Function::Backplane) {
178 4
181 } else {
182 0
183 };
184
185 self.read.insert(jmp.map(|jmp| (jmp, pos)));
186 self.read(fun, cmd)
187 }
188 GspiTask::Write(cmd, val) => self.write(cmd, val),
189 GspiTask::Fw => self.write_bp(constants::RAM_BASE_ADDR, self.fw),
190 GspiTask::Nvram => self.write_bp(self.nvram.1, self.nvram.0),
191 GspiTask::NvramMagic => self
192 .update_bp_window_or_else(backplane_window_bits!(constants::NVRAM_END), || {
193 self.write(NVRAM_MAGIC_CMD, self.nvram.2)
194 }),
195 GspiTask::WaitMs(ms) => {
196 self.alarm
197 .set_alarm(self.alarm.now(), self.alarm.ticks_from_ms(ms));
198 Ok(())
199 }
200 }
201 }
202}
203
204impl<'a, S: SpiMasterDevice<'a>, A: kernel::hil::time::Alarm<'a>> CYW4343xSpiBus<'a, S, A> {
205 fn write_bp(&self, base_address: u32, base_buffer: &[u8]) -> Result<(), ErrorCode> {
209 let offset = self.backplane.transfer_offset.get();
210 let address = base_address + offset as u32;
211
212 self.update_bp_window_or_else(backplane_window_bits!(address), || {
214 let Some((mut extra, mut buf)) = Option::zip(self.extra.take(), self.data.take())
215 else {
216 return Err(ErrorCode::NOMEM);
217 };
218
219 let window_offset = address & constants::BACKPLANE_ADDRESS_MASK;
220 let window_remaining = (constants::BACKPLANE_WINDOW_SIZE - window_offset) as usize;
221
222 let len = (base_buffer.len() - offset)
228 .min(constants::MAX_SPI_BP_CHUNK_SIZE)
229 .min(window_remaining);
230
231 let cmd = cmd32(Type::Write, Function::Backplane, window_offset, len as u32);
232
233 buf.slice(0..CMD_SIZE + len.div_ceil(4) * 4);
235 extra.slice(0..STATUS_SIZE);
236
237 buf.as_mut_slice()[0..CMD_SIZE].copy_from_slice(&cmd.to_le_bytes());
238 buf.as_mut_slice()[CMD_SIZE..][..len].copy_from_slice(&base_buffer[offset..][..len]);
239
240 self.gspi
241 .read_write_bytes(buf, Some(extra))
242 .map_err(|(err, mut data, extra)| {
243 let mut extra = extra.unwrap();
244 reset_and_restore_bufs!(self, extra, data);
245 err
246 })?;
247
248 let pending = len + offset < base_buffer.len();
252
253 self.backplane.pending.set(pending);
254 self.backplane
255 .transfer_offset
256 .set(if pending { offset + len } else { 0 });
257 Ok(())
258 })
259 }
260
261 fn read(&self, fun: Function, cmd: u32) -> Result<(), ErrorCode> {
263 let Some((mut extra, mut data)) = Option::zip(self.extra.take(), self.data.take()) else {
264 return Err(ErrorCode::NOMEM);
265 };
266
267 extra.slice(..CMD_SIZE);
268 let mut size = STATUS_SIZE + WORD_SIZE;
269 if let Function::Backplane = fun {
270 size += WORD_SIZE;
272 }
273 data.slice(0..size);
274 extra.as_mut_slice()[0..CMD_SIZE].copy_from_slice(&cmd.to_le_bytes());
275
276 self.gspi
277 .read_write_bytes(extra, Some(data))
278 .map_err(|(err, mut extra, data)| {
279 let mut data = data.unwrap();
280 reset_and_restore_bufs!(self, extra, data);
281 err
282 })
283 }
284
285 fn write(&self, cmd: u32, val: u32) -> Result<(), ErrorCode> {
287 let Some((mut extra, mut buffer)) = Option::zip(self.extra.take(), self.data.take()) else {
288 return Err(ErrorCode::NOMEM);
289 };
290
291 buffer.slice(..CMD_SIZE + WORD_SIZE);
292 extra.slice(..STATUS_SIZE);
293
294 buffer.as_mut_slice()[..CMD_SIZE].copy_from_slice(&cmd.to_le_bytes());
295 buffer.as_mut_slice()[CMD_SIZE..][..WORD_SIZE].copy_from_slice(&val.to_le_bytes());
296
297 self.gspi
298 .read_write_bytes(buffer, Some(extra))
299 .map_err(|(err, mut data, extra)| {
300 let mut extra = extra.unwrap();
301 reset_and_restore_bufs!(self, extra, data);
302 err
303 })
304 }
305
306 fn update_bp_window_or_else(
308 &self,
309 window: u32,
310 f: impl FnOnce() -> Result<(), ErrorCode>,
311 ) -> Result<(), ErrorCode> {
312 let update_byte = |idx: u8| {
314 let extract = |val: u32| -> u8 { (val >> ((idx as u32) * 8)) as u8 };
315 let extr = extract(window);
316 let curr = self.backplane.curr_window.get();
317 let extr_curr = extract(curr);
318 (extr != extr_curr).then(|| {
319 (
320 cmd32(
321 Type::Write,
322 Function::Backplane,
323 constants::REG_BACKPLANE_BACKPLANE_ADDRESS_LOW + idx as u32,
324 RegLen::Byte as _,
325 ),
326 extr,
327 )
328 })
329 };
330
331 let byte = self.backplane.pending_window.take().map(|(_, b)| b - 1);
333 let byte = byte.unwrap_or(2) as _;
335
336 for b in (0..=byte).rev() {
337 if let Some((cmd, val)) = update_byte(b) {
338 self.backplane.pending_window.set((window, b));
339 return self.write(cmd, val as u32);
340 }
341 }
342
343 self.backplane.curr_window.set(window);
344 f()
345 }
346}
347
348impl<'a, S: SpiMasterDevice<'a>, A: kernel::hil::time::Alarm<'a>> CYW4343xBus<'a>
349 for CYW4343xSpiBus<'a, S, A>
350{
351 fn set_client(&self, client: &'a dyn CYW4343xBusClient) {
352 self.client.set(client);
353 }
354
355 fn state(&self) -> Result<BusState, kernel::ErrorCode> {
356 if let State::NotInit = self.inner_state.get() {
357 return Err(ErrorCode::BUSY);
358 }
359 Ok(self.state.get())
360 }
361
362 fn init(&self) -> Result<(), ErrorCode> {
363 let State::NotInit = self.inner_state.get() else {
364 return Err(ErrorCode::ALREADY);
365 };
366
367 const CMD: u32 = cmd16(
368 Type::Read,
369 Function::Bus,
370 constants::REG_BUS_TEST_RO,
371 RegLen::Word as _,
372 );
373
374 self.read(Function::Bus, CMD)?;
375 self.inner_state.set(State::Init(0));
376 self.read.set((common::eq::<0xBEADFEED, 1, 0>, 0));
377 Ok(())
378 }
379
380 fn write_bytes(
381 &self,
382 mut buffer: SubSliceMut<'static, u8>,
383 ) -> Result<(), (kernel::ErrorCode, SubSliceMut<'static, u8>)> {
384 let Some((mut data, mut extra)) = Option::zip(self.data.take(), self.extra.take()) else {
385 return Err((ErrorCode::NOMEM, buffer));
386 };
387
388 let mut total_len = (buffer.len() + 3) & !3;
389 if total_len > MAX_PAYLOAD_SIZE {
390 return Err((ErrorCode::NOMEM, buffer));
391 } else if total_len == MAX_PACKET_SIZE {
392 total_len = 0;
393 }
394
395 let cmd = cmd32(Type::Write, Function::Wlan, 0x0, total_len as _);
397
398 let slice = data.as_mut_slice();
399 slice[..CMD_SIZE].copy_from_slice(&cmd.to_le_bytes());
400 slice[CMD_SIZE..][..buffer.len()].copy_from_slice(buffer.as_mut_slice());
401
402 extra.slice(..STATUS_SIZE);
403 data.slice(..CMD_SIZE + total_len);
404
405 if let Err((err, mut data, extra)) = self.gspi.read_write_bytes(data, Some(extra)) {
406 let mut extra = extra.unwrap();
407 reset_and_restore_bufs!(self, data, extra);
408 Err((err, buffer))
409 } else {
410 self.inner_state.set(State::Write);
411 self.wlan.set(buffer);
412 Ok(())
413 }
414 }
415
416 fn read_bytes(
417 &self,
418 mut buffer: SubSliceMut<'static, u8>,
419 len: usize,
420 ) -> Result<(), (kernel::ErrorCode, SubSliceMut<'static, u8>)> {
421 let Some((mut extra, mut data)) = Option::zip(self.extra.take(), self.data.take()) else {
422 return Err((ErrorCode::NOMEM, buffer));
423 };
424
425 let total_len = (len + 3) & !3;
426 if total_len > MAX_PACKET_SIZE {
427 return Err((ErrorCode::NOMEM, buffer));
428 }
429
430 let cmd = cmd32(
431 Type::Read,
432 Function::Wlan,
433 0,
434 if total_len == MAX_PAYLOAD_SIZE {
435 0
436 } else {
437 total_len as _
438 },
439 );
440
441 extra.slice(..CMD_SIZE);
442 extra[..CMD_SIZE].copy_from_slice(&cmd.to_le_bytes());
443 data.slice(0..total_len + STATUS_SIZE);
444
445 if let Err((err, mut extra, data)) = self.gspi.read_write_bytes(extra, Some(data)) {
446 let mut data = data.unwrap();
447 reset_and_restore_bufs!(self, data, extra);
448 Err((err, buffer))
449 } else {
450 buffer.slice(0..len);
451 self.wlan.set(buffer);
452
453 self.len.set(len);
454 self.inner_state.set(State::Read);
455 Ok(())
456 }
457 }
458}
459
460pub(super) const IRQ_CAUSE_CMD: u32 = cmd32(
462 Type::Read,
463 Function::Bus,
464 constants::REG_BUS_INTERRUPT,
465 RegLen::HalfWord as _,
466);
467
468pub(super) const NVRAM_MAGIC_CMD: u32 = cmd32(
470 Type::Write,
471 Function::Backplane,
472 constants::NVRAM_END & constants::BACKPLANE_ADDRESS_MASK | constants::BACKPLANE_WINDOW_SIZE,
473 RegLen::Word as _,
474);
475
476impl<'a, S: SpiMasterDevice<'a>, A: kernel::hil::time::Alarm<'a>> SpiMasterClient
477 for CYW4343xSpiBus<'a, S, A>
478{
479 fn read_write_done(
480 &self,
481 write_buffer: SubSliceMut<'static, u8>,
482 read_buffer: Option<SubSliceMut<'static, u8>>,
483 rval: Result<usize, ErrorCode>,
484 ) {
485 let rval = rval.map(|_| ());
486 let read_buffer = read_buffer.unwrap();
487
488 let (packet_available, packet_len) = {
489 let end = &read_buffer[read_buffer.len() - STATUS_SIZE..];
490 let status = u32::from_le_bytes([end[0], end[1], end[2], end[3]]);
491
492 (
495 status & constants::STATUS_F2_PKT_AVAILABLE != 0,
496 (status & constants::STATUS_F2_PKT_LEN_MASK) >> constants::STATUS_F2_PKT_LEN_SHIFT,
497 )
498 };
499
500 let irq_fired = self.irq_fired.take() && !packet_available;
501
502 self.state.set(if packet_available {
503 BusState::Available(packet_len as _)
504 } else if irq_fired {
505 BusState::Incoming
506 } else {
507 BusState::Idle
508 });
509
510 let (mut extra, mut data) = if write_buffer.len() == CMD_SIZE {
512 (write_buffer, read_buffer)
513 } else {
514 (read_buffer, write_buffer)
515 };
516
517 match self.inner_state.take() {
518 State::Init(mut idx) => {
519 if let Err(err) = rval {
520 reset_and_restore_bufs!(self, extra, data);
521 self.client.map(|client| client.init_done(Err(err)));
522 self.inner_state.set(State::NotInit);
523 return;
524 }
525
526 if let Some((window, byte)) = self.backplane.pending_window.get() {
527 if byte == 0 {
528 self.backplane.curr_window.set(window);
529 self.backplane.pending_window.clear();
530 }
531 } else if !self.backplane.pending.take() {
532 if let Some((jmp, pos)) = self.read.take() {
533 let val = &data[pos as usize..];
534 let val = u32::from_le_bytes([val[0], val[1], val[2], val[3]]);
535 jmp(val, &mut idx)
536 } else {
537 idx += 1
538 }
539 }
540
541 reset_and_restore_bufs!(self, extra, data);
542 if (idx as usize) < init::OPS.len() {
543 self.do_task(init::OPS[idx as usize]).map_or_else(
544 |err| {
545 self.inner_state.set(State::NotInit);
546 self.client.map(|client| client.init_done(Err(err)));
547 },
548 |()| self.inner_state.set(State::Init(idx)),
549 )
550 } else {
551 self.client.map(|client| {
552 client.init_done(Ok(()));
553 });
554 }
555 }
556 State::Write => {
557 let Some(wlan) = self.wlan.take() else {
558 return;
559 };
560
561 reset_and_restore_bufs!(self, extra, data);
562 self.client.map(|client| {
563 if irq_fired && self.read(Function::Bus, IRQ_CAUSE_CMD).is_ok() {
564 self.inner_state.set(State::Irq);
565 }
566 client.write_bytes_done(wlan, rval);
567 });
568 }
569 State::Read => {
570 let Some(mut wlan) = self.wlan.take() else {
571 return;
572 };
573 let len = wlan.len();
574 wlan.as_mut_slice()
575 .copy_from_slice(&data.as_mut_slice()[..len]);
576
577 reset_and_restore_bufs!(self, extra, data);
578 self.client.map(|client| {
579 if irq_fired && self.read(Function::Bus, IRQ_CAUSE_CMD).is_ok() {
580 self.inner_state.set(State::Irq);
581 }
582 client.read_bytes_done(wlan, rval);
583 });
584 }
585 State::Irq => {
586 let irq = u16::from_le_bytes([data[0], data[1]]);
587 let pending = irq & constants::IRQ_F2_PACKET_AVAILABLE as u16 != 0;
588
589 reset_and_restore_bufs!(self, extra, data);
590 self.client.map(|client| {
591 client.packet_available(if pending || packet_available {
592 packet_len as _
593 } else {
594 0
595 })
596 });
597 }
598 _ => unreachable!(),
599 }
600 }
601}
602
603impl<'a, S: SpiMasterDevice<'a>, A: kernel::hil::time::Alarm<'a>> time::AlarmClient
604 for CYW4343xSpiBus<'a, S, A>
605{
606 fn alarm(&self) {
607 let State::Init(mut idx) = self.inner_state.get() else {
608 return;
609 };
610
611 idx += 1;
612
613 self.do_task(init::OPS[idx as usize]).map_or_else(
614 |err| {
615 self.client.map(|client| client.init_done(Err(err)));
616 self.inner_state.set(State::NotInit);
617 },
618 |()| self.inner_state.set(State::Init(idx)),
619 )
620 }
621}
622
623impl<'a, S: SpiMasterDevice<'a>, A: kernel::hil::time::Alarm<'a>> gpio::Client
626 for CYW4343xSpiBus<'a, S, A>
627{
628 fn fired(&self) {
629 if let State::Init(_) | State::NotInit = self.inner_state.get() {
630 return;
631 }
632
633 if let State::Idle = self.inner_state.get() {
634 if self.read(Function::Bus, IRQ_CAUSE_CMD).is_ok() {
635 self.inner_state.set(State::Irq);
636 self.state.set(BusState::Incoming);
637 }
638 } else {
639 self.irq_fired.set(true)
640 }
641 }
642}
643
644mod init {
645 use crate::cyw4343::{bus, constants};
646 use bus::common;
647 use bus::spi::{bus_init, wakeup};
648 use bus::RegLen::Word;
649
650 macro_rules! copy_from_arr {
651 (task => $curr:expr, $to:expr, $from:expr) => {
652 let mut __idx = 0;
653 while __idx < $from.len() {
654 $to[$curr + __idx] = GspiTask::from($from[__idx]);
655 __idx += 1;
656 }
657 $curr += __idx;
658 };
659
660 ($curr:expr, $to:expr, $from:expr) => {
661 let mut __idx = 0;
662 while __idx < $from.len() {
663 $to[$curr + __idx] = $from[__idx];
664 __idx += 1;
665 }
666 $curr += __idx;
667 };
668 }
669 use super::task::GspiTask;
670
671 pub(crate) static OPS: [GspiTask; 55] = const {
672 let mut curr = 0;
673 let mut bytes = [GspiTask::WaitMs(0);
674 bus_init::OPS.len()
675 + WLAN_DISABLE.len()
676 + SOCRAM_DISABLE.len()
677 + SOCRAM_RESET.len()
678 + 5
679 + WLAN_RESET.len()
680 + wakeup::OPS.len()];
681 copy_from_arr!(curr, bytes, bus_init::OPS); const WLAN_DISABLE: [common::BackplaneTask; 7] =
686 common::core_disable::ops::<{ constants::WLAN_ARM_CORE_BASE_ADDR }>();
687 copy_from_arr!(task => curr, bytes, WLAN_DISABLE); const SOCRAM_DISABLE: [common::BackplaneTask; 7] =
691 common::core_disable::ops::<{ constants::SOCRAM_CORE_BASE_ADDR }>();
692 copy_from_arr!(task => curr, bytes, SOCRAM_DISABLE); const SOCRAM_RESET: [common::BackplaneTask; 7] =
696 common::core_reset::ops::<{ constants::SOCRAM_CORE_BASE_ADDR }>();
697 copy_from_arr!(task => curr, bytes, SOCRAM_RESET); bytes[curr] = GspiTask::write_bp(0x18004000 + 0x10, Word, 3); bytes[curr + 1] = GspiTask::write_bp(0x18004000 + 0x44, Word, 0); bytes[curr + 2] = GspiTask::Fw; bytes[curr + 3] = GspiTask::Nvram; bytes[curr + 4] = GspiTask::NvramMagic; curr += 5;
708
709 const WLAN_RESET: [common::BackplaneTask; 7] =
711 common::core_reset::ops::<{ constants::WLAN_ARM_CORE_BASE_ADDR }>();
712 copy_from_arr!(task => curr, bytes, WLAN_RESET); copy_from_arr!(curr, bytes, wakeup::OPS); let _ = curr;
717
718 bytes
719 };
720}
721
722mod bus_init {
723 use super::task::GspiTask;
724 use crate::cyw4343::{bus, constants};
725 use bus::common::{eq, mask};
726 use bus::Function::{Backplane as Bp, Bus};
727 use bus::RegLen::{Byte, Word};
728
729 pub(super) static OPS: [GspiTask; 12] = [
730 GspiTask::read16(
732 Bus,
733 constants::REG_BUS_TEST_RO,
734 Word,
735 Some(eq::<0xBEADFEED, 1, 0>),
736 ),
737 GspiTask::write16(Bus, constants::REG_BUS_TEST_RW, Word, 0x12345678),
738 GspiTask::read16(
739 Bus,
740 constants::REG_BUS_TEST_RW,
741 Word,
742 Some(eq::<0x56781234, 1, 0>),
743 ),
744 GspiTask::write16(Bus, constants::REG_BUS_CTRL, Word, constants::CONFIG_DATA),
746 GspiTask::read32(
748 Bus,
749 constants::REG_BUS_TEST_RO,
750 Word,
751 Some(eq::<0xFEEDBEAD, 1, 0>),
752 ),
753 GspiTask::write32(
755 Bus,
756 constants::REG_BUS_INTERRUPT,
757 Byte,
758 constants::INTR_STATUS_RESET,
759 ),
760 GspiTask::write32(
761 Bus,
762 constants::REG_BUS_INTERRUPT_ENABLE,
763 Byte,
764 constants::INTR_ENABLE_RESET,
765 ),
766 GspiTask::write32(
767 Bp,
768 constants::REG_BACKPLANE_CHIP_CLOCK_CSR,
769 Byte,
770 constants::BACKPLANE_ALP_AVAIL_REQ as u32,
771 ),
772 GspiTask::write32(Bp, constants::REG_BACKPLANE_FUNCTION2_WATERMARK, Byte, 0x10),
773 GspiTask::read32(Bp, constants::REG_BACKPLANE_FUNCTION2_WATERMARK, Byte, None),
774 GspiTask::read32(
775 Bp,
776 constants::REG_BACKPLANE_CHIP_CLOCK_CSR,
777 Byte,
778 Some(mask::<{ constants::BACKPLANE_ALP_AVAIL }, 0, 1>),
779 ),
780 GspiTask::write32(Bp, constants::REG_BACKPLANE_CHIP_CLOCK_CSR, Byte, 0x0),
781 ];
782}
783
784mod wakeup {
785 use super::task::GspiTask;
786 use crate::cyw4343::{bus, constants};
787 use bus::common::mask;
788 use bus::Function::{Backplane as Bp, Bus};
789 use bus::RegLen::{Byte, HalfWord, Word};
790
791 pub(super) static OPS: [GspiTask; 10] = [
792 GspiTask::WaitMs(30),
793 GspiTask::read32(
794 Bp,
795 constants::REG_BACKPLANE_CHIP_CLOCK_CSR,
796 Byte,
797 Some(mask::<0x80, 0, 1>),
798 ),
799 GspiTask::write_bp(
800 constants::SDIOD_CORE_BASE_ADDRESS + constants::SDIO_INT_HOST_MASK,
801 Word,
802 constants::I_HMB_SW_MASK,
803 ),
804 GspiTask::write32(
805 Bus,
806 constants::REG_BUS_INTERRUPT_ENABLE,
807 HalfWord,
808 constants::IRQ_F2_PACKET_AVAILABLE,
809 ),
810 GspiTask::write32(
811 Bp,
812 constants::REG_BACKPLANE_FUNCTION2_WATERMARK,
813 Byte,
814 constants::SPI_F2_WATERMARK,
815 ),
816 GspiTask::read32(
817 Bus,
818 constants::REG_BUS_STATUS,
819 Word,
820 Some(mask::<{ constants::STATUS_F2_RX_READY }, 0, 1>),
821 ),
822 GspiTask::write32(Bp, constants::REG_BACKPLANE_PULL_UP, Byte, 0x0),
823 GspiTask::read32(Bp, constants::REG_BACKPLANE_PULL_UP, Byte, None),
824 GspiTask::write32(Bp, constants::REG_BACKPLANE_CHIP_CLOCK_CSR, Byte, 0x10),
825 GspiTask::read32(
826 Bp,
827 constants::REG_BACKPLANE_CHIP_CLOCK_CSR,
828 Byte,
829 Some(mask::<0x80, 0, 1>),
830 ),
831 ];
832}
833
834mod task {
835 use super::{cmd16, cmd32};
836 use crate::cyw4343::{bus, constants};
837 use bus::{common, Function, RegLen, Type};
838
839 type Cmd = u32;
840 type Addr = u32;
841
842 #[derive(Clone, Copy, Debug)]
844 pub(super) enum GspiTask {
845 Read(Function, Cmd, Option<fn(u32, &mut u8) -> ()>),
846 Write(Cmd, u32),
847 ReadBackplane(Cmd, Addr, Option<fn(u32, &mut u8) -> ()>),
848 WriteBackplane(Cmd, Addr, u32),
849 WaitMs(u32),
850 Fw,
851 Nvram,
852 NvramMagic,
853 }
854
855 impl GspiTask {
856 pub(super) const fn from(value: common::BackplaneTask) -> Self {
857 match value {
858 common::BackplaneTask::Read(len, addr, jmp) => Self::read_bp(addr, len, jmp),
859 common::BackplaneTask::Write(len, addr, val) => Self::write_bp(addr, len, val),
860 common::BackplaneTask::WaitMs(ms) => Self::WaitMs(ms),
861 }
862 }
863
864 pub(super) const fn read16(
865 fun: Function,
866 addr: u32,
867 len: RegLen,
868 jmp: Option<fn(u32, &mut u8) -> ()>,
869 ) -> Self {
870 Self::Read(fun, cmd16(Type::Read, fun, addr, len as _), jmp)
871 }
872
873 pub(super) const fn write16(fun: Function, addr: u32, len: RegLen, mut val: u32) -> Self {
874 if let RegLen::Word = len {
875 val = val.rotate_left(16);
876 }
877 Self::Write(cmd16(Type::Write, fun, addr, len as _), val)
878 }
879
880 pub(super) const fn read32(
881 fun: Function,
882 addr: u32,
883 len: RegLen,
884 jmp: Option<fn(u32, &mut u8)>,
885 ) -> Self {
886 Self::Read(fun, cmd32(Type::Read, fun, addr, len as _), jmp)
887 }
888
889 pub(super) const fn write32(fun: Function, addr: u32, len: RegLen, val: u32) -> Self {
890 Self::Write(cmd32(Type::Write, fun, addr, len as _), val)
891 }
892
893 pub(super) const fn read_bp(addr: u32, len: RegLen, jmp: Option<fn(u32, &mut u8)>) -> Self {
894 let mut cmd_addr = addr & constants::BACKPLANE_ADDRESS_MASK;
895 if let RegLen::Word = len {
896 cmd_addr |= constants::BACKPLANE_WINDOW_SIZE
897 }
898
899 Self::ReadBackplane(
900 cmd32(Type::Read, Function::Backplane, cmd_addr, len as _),
901 addr,
902 jmp,
903 )
904 }
905
906 pub(super) const fn write_bp(addr: u32, len: RegLen, val: u32) -> Self {
907 assert!(addr.is_multiple_of(4));
908
909 let mut cmd_addr = addr & constants::BACKPLANE_ADDRESS_MASK;
910 if let RegLen::Word = len {
911 cmd_addr |= constants::BACKPLANE_WINDOW_SIZE
912 }
913
914 Self::WriteBackplane(
915 cmd32(Type::Write, Function::Backplane, cmd_addr, len as _),
916 addr,
917 val,
918 )
919 }
920 }
921}