xref: /linux/drivers/gpu/nova-core/gsp/sequencer.rs (revision 24f171c7e145f43b9f187578e89b0982ce87e54c)
16ddfc892SJoel Fernandes // SPDX-License-Identifier: GPL-2.0
26ddfc892SJoel Fernandes 
36ddfc892SJoel Fernandes //! GSP Sequencer implementation for Pre-hopper GSP boot sequence.
46ddfc892SJoel Fernandes 
56ddfc892SJoel Fernandes use core::{
66ddfc892SJoel Fernandes     array,
72367ce2eSJoel Fernandes     mem::{
82367ce2eSJoel Fernandes         size_of,
92367ce2eSJoel Fernandes         size_of_val, //
102367ce2eSJoel Fernandes     },
116ddfc892SJoel Fernandes };
126ddfc892SJoel Fernandes 
136ddfc892SJoel Fernandes use kernel::{
146ddfc892SJoel Fernandes     device,
152367ce2eSJoel Fernandes     io::poll::read_poll_timeout,
166ddfc892SJoel Fernandes     prelude::*,
17e386680eSJoel Fernandes     time::{
18e386680eSJoel Fernandes         delay::fsleep,
19e386680eSJoel Fernandes         Delta, //
20e386680eSJoel Fernandes     },
216ddfc892SJoel Fernandes     transmute::FromBytes,
226ddfc892SJoel Fernandes     types::ARef, //
236ddfc892SJoel Fernandes };
246ddfc892SJoel Fernandes 
256ddfc892SJoel Fernandes use crate::{
266ddfc892SJoel Fernandes     driver::Bar0,
276ddfc892SJoel Fernandes     falcon::{
286ddfc892SJoel Fernandes         gsp::Gsp,
296ddfc892SJoel Fernandes         sec2::Sec2,
306ddfc892SJoel Fernandes         Falcon, //
316ddfc892SJoel Fernandes     },
326ddfc892SJoel Fernandes     gsp::{
336ddfc892SJoel Fernandes         cmdq::{
346ddfc892SJoel Fernandes             Cmdq,
356ddfc892SJoel Fernandes             MessageFromGsp, //
366ddfc892SJoel Fernandes         },
376ddfc892SJoel Fernandes         fw,
386ddfc892SJoel Fernandes     },
392367ce2eSJoel Fernandes     num::FromSafeCast,
406ddfc892SJoel Fernandes     sbuffer::SBufferIter,
416ddfc892SJoel Fernandes };
426ddfc892SJoel Fernandes 
436ddfc892SJoel Fernandes /// GSP Sequencer information containing the command sequence and data.
446ddfc892SJoel Fernandes struct GspSequence {
456ddfc892SJoel Fernandes     /// Current command index for error reporting.
466ddfc892SJoel Fernandes     cmd_index: u32,
476ddfc892SJoel Fernandes     /// Command data buffer containing the sequence of commands.
486ddfc892SJoel Fernandes     cmd_data: KVec<u8>,
496ddfc892SJoel Fernandes }
506ddfc892SJoel Fernandes 
516ddfc892SJoel Fernandes impl MessageFromGsp for GspSequence {
526ddfc892SJoel Fernandes     const FUNCTION: fw::MsgFunction = fw::MsgFunction::GspRunCpuSequencer;
536ddfc892SJoel Fernandes     type InitError = Error;
546ddfc892SJoel Fernandes     type Message = fw::RunCpuSequencer;
556ddfc892SJoel Fernandes 
566ddfc892SJoel Fernandes     fn read(
576ddfc892SJoel Fernandes         msg: &Self::Message,
586ddfc892SJoel Fernandes         sbuffer: &mut SBufferIter<array::IntoIter<&[u8], 2>>,
596ddfc892SJoel Fernandes     ) -> Result<Self, Self::InitError> {
606ddfc892SJoel Fernandes         let cmd_data = sbuffer.flush_into_kvec(GFP_KERNEL)?;
616ddfc892SJoel Fernandes         Ok(GspSequence {
626ddfc892SJoel Fernandes             cmd_index: msg.cmd_index(),
636ddfc892SJoel Fernandes             cmd_data,
646ddfc892SJoel Fernandes         })
656ddfc892SJoel Fernandes     }
666ddfc892SJoel Fernandes }
676ddfc892SJoel Fernandes 
686ddfc892SJoel Fernandes const CMD_SIZE: usize = size_of::<fw::SequencerBufferCmd>();
696ddfc892SJoel Fernandes 
706ddfc892SJoel Fernandes /// GSP Sequencer Command types with payload data.
716ddfc892SJoel Fernandes /// Commands have an opcode and an opcode-dependent struct.
722367ce2eSJoel Fernandes #[allow(clippy::enum_variant_names)]
732367ce2eSJoel Fernandes pub(crate) enum GspSeqCmd {
742367ce2eSJoel Fernandes     RegWrite(fw::RegWritePayload),
752367ce2eSJoel Fernandes     RegModify(fw::RegModifyPayload),
762367ce2eSJoel Fernandes     RegPoll(fw::RegPollPayload),
77e386680eSJoel Fernandes     DelayUs(fw::DelayUsPayload),
782367ce2eSJoel Fernandes     RegStore(fw::RegStorePayload),
799641f052SJoel Fernandes     CoreReset,
809641f052SJoel Fernandes     CoreStart,
819641f052SJoel Fernandes     CoreWaitForHalt,
82*77410985SJoel Fernandes     CoreResume,
832367ce2eSJoel Fernandes }
846ddfc892SJoel Fernandes 
856ddfc892SJoel Fernandes impl GspSeqCmd {
866ddfc892SJoel Fernandes     /// Creates a new `GspSeqCmd` from raw data returning the command and its size in bytes.
872367ce2eSJoel Fernandes     pub(crate) fn new(data: &[u8], dev: &device::Device) -> Result<(Self, usize)> {
882367ce2eSJoel Fernandes         let fw_cmd = fw::SequencerBufferCmd::from_bytes(data).ok_or(EINVAL)?;
892367ce2eSJoel Fernandes         let opcode_size = core::mem::size_of::<u32>();
906ddfc892SJoel Fernandes 
912367ce2eSJoel Fernandes         let (cmd, size) = match fw_cmd.opcode()? {
922367ce2eSJoel Fernandes             fw::SeqBufOpcode::RegWrite => {
932367ce2eSJoel Fernandes                 let payload = fw_cmd.reg_write_payload()?;
942367ce2eSJoel Fernandes                 let size = opcode_size + size_of_val(&payload);
952367ce2eSJoel Fernandes                 (GspSeqCmd::RegWrite(payload), size)
962367ce2eSJoel Fernandes             }
972367ce2eSJoel Fernandes             fw::SeqBufOpcode::RegModify => {
982367ce2eSJoel Fernandes                 let payload = fw_cmd.reg_modify_payload()?;
992367ce2eSJoel Fernandes                 let size = opcode_size + size_of_val(&payload);
1002367ce2eSJoel Fernandes                 (GspSeqCmd::RegModify(payload), size)
1012367ce2eSJoel Fernandes             }
1022367ce2eSJoel Fernandes             fw::SeqBufOpcode::RegPoll => {
1032367ce2eSJoel Fernandes                 let payload = fw_cmd.reg_poll_payload()?;
1042367ce2eSJoel Fernandes                 let size = opcode_size + size_of_val(&payload);
1052367ce2eSJoel Fernandes                 (GspSeqCmd::RegPoll(payload), size)
1062367ce2eSJoel Fernandes             }
107e386680eSJoel Fernandes             fw::SeqBufOpcode::DelayUs => {
108e386680eSJoel Fernandes                 let payload = fw_cmd.delay_us_payload()?;
109e386680eSJoel Fernandes                 let size = opcode_size + size_of_val(&payload);
110e386680eSJoel Fernandes                 (GspSeqCmd::DelayUs(payload), size)
111e386680eSJoel Fernandes             }
1122367ce2eSJoel Fernandes             fw::SeqBufOpcode::RegStore => {
1132367ce2eSJoel Fernandes                 let payload = fw_cmd.reg_store_payload()?;
1142367ce2eSJoel Fernandes                 let size = opcode_size + size_of_val(&payload);
1152367ce2eSJoel Fernandes                 (GspSeqCmd::RegStore(payload), size)
1162367ce2eSJoel Fernandes             }
1179641f052SJoel Fernandes             fw::SeqBufOpcode::CoreReset => (GspSeqCmd::CoreReset, opcode_size),
1189641f052SJoel Fernandes             fw::SeqBufOpcode::CoreStart => (GspSeqCmd::CoreStart, opcode_size),
1199641f052SJoel Fernandes             fw::SeqBufOpcode::CoreWaitForHalt => (GspSeqCmd::CoreWaitForHalt, opcode_size),
120*77410985SJoel Fernandes             fw::SeqBufOpcode::CoreResume => (GspSeqCmd::CoreResume, opcode_size),
1212367ce2eSJoel Fernandes         };
1222367ce2eSJoel Fernandes 
1232367ce2eSJoel Fernandes         if data.len() < size {
1242367ce2eSJoel Fernandes             dev_err!(dev, "Data is not enough for command");
1252367ce2eSJoel Fernandes             return Err(EINVAL);
1262367ce2eSJoel Fernandes         }
1272367ce2eSJoel Fernandes 
1282367ce2eSJoel Fernandes         Ok((cmd, size))
1296ddfc892SJoel Fernandes     }
1306ddfc892SJoel Fernandes }
1316ddfc892SJoel Fernandes 
1326ddfc892SJoel Fernandes /// GSP Sequencer for executing firmware commands during boot.
1336ddfc892SJoel Fernandes pub(crate) struct GspSequencer<'a> {
1346ddfc892SJoel Fernandes     /// Sequencer information with command data.
1356ddfc892SJoel Fernandes     seq_info: GspSequence,
1366ddfc892SJoel Fernandes     /// `Bar0` for register access.
1376ddfc892SJoel Fernandes     bar: &'a Bar0,
1386ddfc892SJoel Fernandes     /// SEC2 falcon for core operations.
1396ddfc892SJoel Fernandes     sec2_falcon: &'a Falcon<Sec2>,
1406ddfc892SJoel Fernandes     /// GSP falcon for core operations.
1416ddfc892SJoel Fernandes     gsp_falcon: &'a Falcon<Gsp>,
1426ddfc892SJoel Fernandes     /// LibOS DMA handle address.
1436ddfc892SJoel Fernandes     libos_dma_handle: u64,
1446ddfc892SJoel Fernandes     /// Bootloader application version.
1456ddfc892SJoel Fernandes     bootloader_app_version: u32,
1466ddfc892SJoel Fernandes     /// Device for logging.
1476ddfc892SJoel Fernandes     dev: ARef<device::Device>,
1486ddfc892SJoel Fernandes }
1496ddfc892SJoel Fernandes 
1506ddfc892SJoel Fernandes /// Trait for running sequencer commands.
1516ddfc892SJoel Fernandes pub(crate) trait GspSeqCmdRunner {
1526ddfc892SJoel Fernandes     fn run(&self, sequencer: &GspSequencer<'_>) -> Result;
1536ddfc892SJoel Fernandes }
1546ddfc892SJoel Fernandes 
1552367ce2eSJoel Fernandes impl GspSeqCmdRunner for fw::RegWritePayload {
1562367ce2eSJoel Fernandes     fn run(&self, sequencer: &GspSequencer<'_>) -> Result {
1572367ce2eSJoel Fernandes         let addr = usize::from_safe_cast(self.addr());
1582367ce2eSJoel Fernandes 
1592367ce2eSJoel Fernandes         sequencer.bar.try_write32(self.val(), addr)
1602367ce2eSJoel Fernandes     }
1612367ce2eSJoel Fernandes }
1622367ce2eSJoel Fernandes 
1632367ce2eSJoel Fernandes impl GspSeqCmdRunner for fw::RegModifyPayload {
1642367ce2eSJoel Fernandes     fn run(&self, sequencer: &GspSequencer<'_>) -> Result {
1652367ce2eSJoel Fernandes         let addr = usize::from_safe_cast(self.addr());
1662367ce2eSJoel Fernandes 
1672367ce2eSJoel Fernandes         sequencer.bar.try_read32(addr).and_then(|val| {
1682367ce2eSJoel Fernandes             sequencer
1692367ce2eSJoel Fernandes                 .bar
1702367ce2eSJoel Fernandes                 .try_write32((val & !self.mask()) | self.val(), addr)
1712367ce2eSJoel Fernandes         })
1722367ce2eSJoel Fernandes     }
1732367ce2eSJoel Fernandes }
1742367ce2eSJoel Fernandes 
1752367ce2eSJoel Fernandes impl GspSeqCmdRunner for fw::RegPollPayload {
1762367ce2eSJoel Fernandes     fn run(&self, sequencer: &GspSequencer<'_>) -> Result {
1772367ce2eSJoel Fernandes         let addr = usize::from_safe_cast(self.addr());
1782367ce2eSJoel Fernandes 
1792367ce2eSJoel Fernandes         // Default timeout to 4 seconds.
1802367ce2eSJoel Fernandes         let timeout_us = if self.timeout() == 0 {
1812367ce2eSJoel Fernandes             4_000_000
1822367ce2eSJoel Fernandes         } else {
1832367ce2eSJoel Fernandes             i64::from(self.timeout())
1842367ce2eSJoel Fernandes         };
1852367ce2eSJoel Fernandes 
1862367ce2eSJoel Fernandes         // First read.
1872367ce2eSJoel Fernandes         sequencer.bar.try_read32(addr)?;
1882367ce2eSJoel Fernandes 
1892367ce2eSJoel Fernandes         // Poll the requested register with requested timeout.
1902367ce2eSJoel Fernandes         read_poll_timeout(
1912367ce2eSJoel Fernandes             || sequencer.bar.try_read32(addr),
1922367ce2eSJoel Fernandes             |current| (current & self.mask()) == self.val(),
1932367ce2eSJoel Fernandes             Delta::ZERO,
1942367ce2eSJoel Fernandes             Delta::from_micros(timeout_us),
1952367ce2eSJoel Fernandes         )
1962367ce2eSJoel Fernandes         .map(|_| ())
1972367ce2eSJoel Fernandes     }
1982367ce2eSJoel Fernandes }
1992367ce2eSJoel Fernandes 
200e386680eSJoel Fernandes impl GspSeqCmdRunner for fw::DelayUsPayload {
201e386680eSJoel Fernandes     fn run(&self, _sequencer: &GspSequencer<'_>) -> Result {
202e386680eSJoel Fernandes         fsleep(Delta::from_micros(i64::from(self.val())));
203e386680eSJoel Fernandes         Ok(())
204e386680eSJoel Fernandes     }
205e386680eSJoel Fernandes }
206e386680eSJoel Fernandes 
2072367ce2eSJoel Fernandes impl GspSeqCmdRunner for fw::RegStorePayload {
2082367ce2eSJoel Fernandes     fn run(&self, sequencer: &GspSequencer<'_>) -> Result {
2092367ce2eSJoel Fernandes         let addr = usize::from_safe_cast(self.addr());
2102367ce2eSJoel Fernandes 
2112367ce2eSJoel Fernandes         sequencer.bar.try_read32(addr).map(|_| ())
2122367ce2eSJoel Fernandes     }
2132367ce2eSJoel Fernandes }
2142367ce2eSJoel Fernandes 
2156ddfc892SJoel Fernandes impl GspSeqCmdRunner for GspSeqCmd {
2162367ce2eSJoel Fernandes     fn run(&self, seq: &GspSequencer<'_>) -> Result {
2172367ce2eSJoel Fernandes         match self {
2182367ce2eSJoel Fernandes             GspSeqCmd::RegWrite(cmd) => cmd.run(seq),
2192367ce2eSJoel Fernandes             GspSeqCmd::RegModify(cmd) => cmd.run(seq),
2202367ce2eSJoel Fernandes             GspSeqCmd::RegPoll(cmd) => cmd.run(seq),
221e386680eSJoel Fernandes             GspSeqCmd::DelayUs(cmd) => cmd.run(seq),
2222367ce2eSJoel Fernandes             GspSeqCmd::RegStore(cmd) => cmd.run(seq),
2239641f052SJoel Fernandes             GspSeqCmd::CoreReset => {
2249641f052SJoel Fernandes                 seq.gsp_falcon.reset(seq.bar)?;
2259641f052SJoel Fernandes                 seq.gsp_falcon.dma_reset(seq.bar);
2269641f052SJoel Fernandes                 Ok(())
2279641f052SJoel Fernandes             }
2289641f052SJoel Fernandes             GspSeqCmd::CoreStart => {
2299641f052SJoel Fernandes                 seq.gsp_falcon.start(seq.bar)?;
2309641f052SJoel Fernandes                 Ok(())
2319641f052SJoel Fernandes             }
2329641f052SJoel Fernandes             GspSeqCmd::CoreWaitForHalt => {
2339641f052SJoel Fernandes                 seq.gsp_falcon.wait_till_halted(seq.bar)?;
2349641f052SJoel Fernandes                 Ok(())
2359641f052SJoel Fernandes             }
236*77410985SJoel Fernandes             GspSeqCmd::CoreResume => {
237*77410985SJoel Fernandes                 // At this point, 'SEC2-RTOS' has been loaded into SEC2 by the sequencer
238*77410985SJoel Fernandes                 // but neither SEC2-RTOS nor GSP-RM is running yet. This part of the
239*77410985SJoel Fernandes                 // sequencer will start both.
240*77410985SJoel Fernandes 
241*77410985SJoel Fernandes                 // Reset the GSP to prepare it for resuming.
242*77410985SJoel Fernandes                 seq.gsp_falcon.reset(seq.bar)?;
243*77410985SJoel Fernandes 
244*77410985SJoel Fernandes                 // Write the libOS DMA handle to GSP mailboxes.
245*77410985SJoel Fernandes                 seq.gsp_falcon.write_mailboxes(
246*77410985SJoel Fernandes                     seq.bar,
247*77410985SJoel Fernandes                     Some(seq.libos_dma_handle as u32),
248*77410985SJoel Fernandes                     Some((seq.libos_dma_handle >> 32) as u32),
249*77410985SJoel Fernandes                 );
250*77410985SJoel Fernandes 
251*77410985SJoel Fernandes                 // Start the SEC2 falcon which will trigger GSP-RM to resume on the GSP.
252*77410985SJoel Fernandes                 seq.sec2_falcon.start(seq.bar)?;
253*77410985SJoel Fernandes 
254*77410985SJoel Fernandes                 // Poll until GSP-RM reload/resume has completed (up to 2 seconds).
255*77410985SJoel Fernandes                 seq.gsp_falcon
256*77410985SJoel Fernandes                     .check_reload_completed(seq.bar, Delta::from_secs(2))?;
257*77410985SJoel Fernandes 
258*77410985SJoel Fernandes                 // Verify SEC2 completed successfully by checking its mailbox for errors.
259*77410985SJoel Fernandes                 let mbox0 = seq.sec2_falcon.read_mailbox0(seq.bar);
260*77410985SJoel Fernandes                 if mbox0 != 0 {
261*77410985SJoel Fernandes                     dev_err!(seq.dev, "Sequencer: sec2 errors: {:?}\n", mbox0);
262*77410985SJoel Fernandes                     return Err(EIO);
263*77410985SJoel Fernandes                 }
264*77410985SJoel Fernandes 
265*77410985SJoel Fernandes                 // Configure GSP with the bootloader version.
266*77410985SJoel Fernandes                 seq.gsp_falcon
267*77410985SJoel Fernandes                     .write_os_version(seq.bar, seq.bootloader_app_version);
268*77410985SJoel Fernandes 
269*77410985SJoel Fernandes                 // Verify the GSP's RISC-V core is active indicating successful GSP boot.
270*77410985SJoel Fernandes                 if !seq.gsp_falcon.is_riscv_active(seq.bar) {
271*77410985SJoel Fernandes                     dev_err!(seq.dev, "Sequencer: RISC-V core is not active\n");
272*77410985SJoel Fernandes                     return Err(EIO);
273*77410985SJoel Fernandes                 }
274*77410985SJoel Fernandes                 Ok(())
275*77410985SJoel Fernandes             }
2762367ce2eSJoel Fernandes         }
2776ddfc892SJoel Fernandes     }
2786ddfc892SJoel Fernandes }
2796ddfc892SJoel Fernandes 
2806ddfc892SJoel Fernandes /// Iterator over GSP sequencer commands.
2816ddfc892SJoel Fernandes pub(crate) struct GspSeqIter<'a> {
2826ddfc892SJoel Fernandes     /// Command data buffer.
2836ddfc892SJoel Fernandes     cmd_data: &'a [u8],
2846ddfc892SJoel Fernandes     /// Current position in the buffer.
2856ddfc892SJoel Fernandes     current_offset: usize,
2866ddfc892SJoel Fernandes     /// Total number of commands to process.
2876ddfc892SJoel Fernandes     total_cmds: u32,
2886ddfc892SJoel Fernandes     /// Number of commands processed so far.
2896ddfc892SJoel Fernandes     cmds_processed: u32,
2906ddfc892SJoel Fernandes     /// Device for logging.
2916ddfc892SJoel Fernandes     dev: ARef<device::Device>,
2926ddfc892SJoel Fernandes }
2936ddfc892SJoel Fernandes 
2946ddfc892SJoel Fernandes impl<'a> Iterator for GspSeqIter<'a> {
2956ddfc892SJoel Fernandes     type Item = Result<GspSeqCmd>;
2966ddfc892SJoel Fernandes 
2976ddfc892SJoel Fernandes     fn next(&mut self) -> Option<Self::Item> {
2986ddfc892SJoel Fernandes         // Stop if we've processed all commands or reached the end of data.
2996ddfc892SJoel Fernandes         if self.cmds_processed >= self.total_cmds || self.current_offset >= self.cmd_data.len() {
3006ddfc892SJoel Fernandes             return None;
3016ddfc892SJoel Fernandes         }
3026ddfc892SJoel Fernandes 
3036ddfc892SJoel Fernandes         // Check if we have enough data for opcode.
3046ddfc892SJoel Fernandes         if self.current_offset + core::mem::size_of::<u32>() > self.cmd_data.len() {
3056ddfc892SJoel Fernandes             return Some(Err(EIO));
3066ddfc892SJoel Fernandes         }
3076ddfc892SJoel Fernandes 
3086ddfc892SJoel Fernandes         let offset = self.current_offset;
3096ddfc892SJoel Fernandes 
3106ddfc892SJoel Fernandes         // Handle command creation based on available data,
3116ddfc892SJoel Fernandes         // zero-pad if necessary (since last command may not be full size).
3126ddfc892SJoel Fernandes         let mut buffer = [0u8; CMD_SIZE];
3136ddfc892SJoel Fernandes         let copy_len = if offset + CMD_SIZE <= self.cmd_data.len() {
3146ddfc892SJoel Fernandes             CMD_SIZE
3156ddfc892SJoel Fernandes         } else {
3166ddfc892SJoel Fernandes             self.cmd_data.len() - offset
3176ddfc892SJoel Fernandes         };
3186ddfc892SJoel Fernandes         buffer[..copy_len].copy_from_slice(&self.cmd_data[offset..offset + copy_len]);
3196ddfc892SJoel Fernandes         let cmd_result = GspSeqCmd::new(&buffer, &self.dev);
3206ddfc892SJoel Fernandes 
3216ddfc892SJoel Fernandes         cmd_result.map_or_else(
3226ddfc892SJoel Fernandes             |_err| {
3236ddfc892SJoel Fernandes                 dev_err!(self.dev, "Error parsing command at offset {}", offset);
3246ddfc892SJoel Fernandes                 None
3256ddfc892SJoel Fernandes             },
3266ddfc892SJoel Fernandes             |(cmd, size)| {
3276ddfc892SJoel Fernandes                 self.current_offset += size;
3286ddfc892SJoel Fernandes                 self.cmds_processed += 1;
3296ddfc892SJoel Fernandes                 Some(Ok(cmd))
3306ddfc892SJoel Fernandes             },
3316ddfc892SJoel Fernandes         )
3326ddfc892SJoel Fernandes     }
3336ddfc892SJoel Fernandes }
3346ddfc892SJoel Fernandes 
3356ddfc892SJoel Fernandes impl<'a> GspSequencer<'a> {
3366ddfc892SJoel Fernandes     fn iter(&self) -> GspSeqIter<'_> {
3376ddfc892SJoel Fernandes         let cmd_data = &self.seq_info.cmd_data[..];
3386ddfc892SJoel Fernandes 
3396ddfc892SJoel Fernandes         GspSeqIter {
3406ddfc892SJoel Fernandes             cmd_data,
3416ddfc892SJoel Fernandes             current_offset: 0,
3426ddfc892SJoel Fernandes             total_cmds: self.seq_info.cmd_index,
3436ddfc892SJoel Fernandes             cmds_processed: 0,
3446ddfc892SJoel Fernandes             dev: self.dev.clone(),
3456ddfc892SJoel Fernandes         }
3466ddfc892SJoel Fernandes     }
3476ddfc892SJoel Fernandes }
3486ddfc892SJoel Fernandes 
3496ddfc892SJoel Fernandes /// Parameters for running the GSP sequencer.
3506ddfc892SJoel Fernandes pub(crate) struct GspSequencerParams<'a> {
3516ddfc892SJoel Fernandes     /// Bootloader application version.
3526ddfc892SJoel Fernandes     pub(crate) bootloader_app_version: u32,
3536ddfc892SJoel Fernandes     /// LibOS DMA handle address.
3546ddfc892SJoel Fernandes     pub(crate) libos_dma_handle: u64,
3556ddfc892SJoel Fernandes     /// GSP falcon for core operations.
3566ddfc892SJoel Fernandes     pub(crate) gsp_falcon: &'a Falcon<Gsp>,
3576ddfc892SJoel Fernandes     /// SEC2 falcon for core operations.
3586ddfc892SJoel Fernandes     pub(crate) sec2_falcon: &'a Falcon<Sec2>,
3596ddfc892SJoel Fernandes     /// Device for logging.
3606ddfc892SJoel Fernandes     pub(crate) dev: ARef<device::Device>,
3616ddfc892SJoel Fernandes     /// BAR0 for register access.
3626ddfc892SJoel Fernandes     pub(crate) bar: &'a Bar0,
3636ddfc892SJoel Fernandes }
3646ddfc892SJoel Fernandes 
3656ddfc892SJoel Fernandes impl<'a> GspSequencer<'a> {
3666ddfc892SJoel Fernandes     pub(crate) fn run(cmdq: &mut Cmdq, params: GspSequencerParams<'a>) -> Result {
3676ddfc892SJoel Fernandes         let seq_info = loop {
3686ddfc892SJoel Fernandes             match cmdq.receive_msg::<GspSequence>(Delta::from_secs(10)) {
3696ddfc892SJoel Fernandes                 Ok(seq_info) => break seq_info,
3706ddfc892SJoel Fernandes                 Err(ERANGE) => continue,
3716ddfc892SJoel Fernandes                 Err(e) => return Err(e),
3726ddfc892SJoel Fernandes             }
3736ddfc892SJoel Fernandes         };
3746ddfc892SJoel Fernandes 
3756ddfc892SJoel Fernandes         let sequencer = GspSequencer {
3766ddfc892SJoel Fernandes             seq_info,
3776ddfc892SJoel Fernandes             bar: params.bar,
3786ddfc892SJoel Fernandes             sec2_falcon: params.sec2_falcon,
3796ddfc892SJoel Fernandes             gsp_falcon: params.gsp_falcon,
3806ddfc892SJoel Fernandes             libos_dma_handle: params.libos_dma_handle,
3816ddfc892SJoel Fernandes             bootloader_app_version: params.bootloader_app_version,
3826ddfc892SJoel Fernandes             dev: params.dev,
3836ddfc892SJoel Fernandes         };
3846ddfc892SJoel Fernandes 
3856ddfc892SJoel Fernandes         dev_dbg!(sequencer.dev, "Running CPU Sequencer commands");
3866ddfc892SJoel Fernandes 
3876ddfc892SJoel Fernandes         for cmd_result in sequencer.iter() {
3886ddfc892SJoel Fernandes             match cmd_result {
3896ddfc892SJoel Fernandes                 Ok(cmd) => cmd.run(&sequencer)?,
3906ddfc892SJoel Fernandes                 Err(e) => {
3916ddfc892SJoel Fernandes                     dev_err!(
3926ddfc892SJoel Fernandes                         sequencer.dev,
3936ddfc892SJoel Fernandes                         "Error running command at index {}",
3946ddfc892SJoel Fernandes                         sequencer.seq_info.cmd_index
3956ddfc892SJoel Fernandes                     );
3966ddfc892SJoel Fernandes                     return Err(e);
3976ddfc892SJoel Fernandes                 }
3986ddfc892SJoel Fernandes             }
3996ddfc892SJoel Fernandes         }
4006ddfc892SJoel Fernandes 
4016ddfc892SJoel Fernandes         dev_dbg!(
4026ddfc892SJoel Fernandes             sequencer.dev,
4036ddfc892SJoel Fernandes             "CPU Sequencer commands completed successfully"
4046ddfc892SJoel Fernandes         );
4056ddfc892SJoel Fernandes         Ok(())
4066ddfc892SJoel Fernandes     }
4076ddfc892SJoel Fernandes }
408