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