sequencer.rs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. // SPDX-License-Identifier: GPL-2.0
  2. //! GSP Sequencer implementation for Pre-hopper GSP boot sequence.
  3. use core::array;
  4. use kernel::{
  5. device,
  6. io::{
  7. poll::read_poll_timeout,
  8. Io, //
  9. },
  10. prelude::*,
  11. sync::aref::ARef,
  12. time::{
  13. delay::fsleep,
  14. Delta, //
  15. },
  16. transmute::FromBytes, //
  17. };
  18. use crate::{
  19. driver::Bar0,
  20. falcon::{
  21. gsp::Gsp,
  22. sec2::Sec2,
  23. Falcon, //
  24. },
  25. gsp::{
  26. cmdq::{
  27. Cmdq,
  28. MessageFromGsp, //
  29. },
  30. fw,
  31. },
  32. num::FromSafeCast,
  33. sbuffer::SBufferIter,
  34. };
  35. /// GSP Sequencer information containing the command sequence and data.
  36. struct GspSequence {
  37. /// Current command index for error reporting.
  38. cmd_index: u32,
  39. /// Command data buffer containing the sequence of commands.
  40. cmd_data: KVec<u8>,
  41. }
  42. impl MessageFromGsp for GspSequence {
  43. const FUNCTION: fw::MsgFunction = fw::MsgFunction::GspRunCpuSequencer;
  44. type InitError = Error;
  45. type Message = fw::RunCpuSequencer;
  46. fn read(
  47. msg: &Self::Message,
  48. sbuffer: &mut SBufferIter<array::IntoIter<&[u8], 2>>,
  49. ) -> Result<Self, Self::InitError> {
  50. let cmd_data = sbuffer.flush_into_kvec(GFP_KERNEL)?;
  51. Ok(GspSequence {
  52. cmd_index: msg.cmd_index(),
  53. cmd_data,
  54. })
  55. }
  56. }
  57. const CMD_SIZE: usize = size_of::<fw::SequencerBufferCmd>();
  58. /// GSP Sequencer Command types with payload data.
  59. /// Commands have an opcode and an opcode-dependent struct.
  60. #[allow(clippy::enum_variant_names)]
  61. pub(crate) enum GspSeqCmd {
  62. RegWrite(fw::RegWritePayload),
  63. RegModify(fw::RegModifyPayload),
  64. RegPoll(fw::RegPollPayload),
  65. DelayUs(fw::DelayUsPayload),
  66. RegStore(fw::RegStorePayload),
  67. CoreReset,
  68. CoreStart,
  69. CoreWaitForHalt,
  70. CoreResume,
  71. }
  72. impl GspSeqCmd {
  73. /// Creates a new `GspSeqCmd` from raw data returning the command and its size in bytes.
  74. pub(crate) fn new(data: &[u8], dev: &device::Device) -> Result<(Self, usize)> {
  75. let fw_cmd = fw::SequencerBufferCmd::from_bytes(data).ok_or(EINVAL)?;
  76. let opcode_size = core::mem::size_of::<u32>();
  77. let (cmd, size) = match fw_cmd.opcode()? {
  78. fw::SeqBufOpcode::RegWrite => {
  79. let payload = fw_cmd.reg_write_payload()?;
  80. let size = opcode_size + size_of_val(&payload);
  81. (GspSeqCmd::RegWrite(payload), size)
  82. }
  83. fw::SeqBufOpcode::RegModify => {
  84. let payload = fw_cmd.reg_modify_payload()?;
  85. let size = opcode_size + size_of_val(&payload);
  86. (GspSeqCmd::RegModify(payload), size)
  87. }
  88. fw::SeqBufOpcode::RegPoll => {
  89. let payload = fw_cmd.reg_poll_payload()?;
  90. let size = opcode_size + size_of_val(&payload);
  91. (GspSeqCmd::RegPoll(payload), size)
  92. }
  93. fw::SeqBufOpcode::DelayUs => {
  94. let payload = fw_cmd.delay_us_payload()?;
  95. let size = opcode_size + size_of_val(&payload);
  96. (GspSeqCmd::DelayUs(payload), size)
  97. }
  98. fw::SeqBufOpcode::RegStore => {
  99. let payload = fw_cmd.reg_store_payload()?;
  100. let size = opcode_size + size_of_val(&payload);
  101. (GspSeqCmd::RegStore(payload), size)
  102. }
  103. fw::SeqBufOpcode::CoreReset => (GspSeqCmd::CoreReset, opcode_size),
  104. fw::SeqBufOpcode::CoreStart => (GspSeqCmd::CoreStart, opcode_size),
  105. fw::SeqBufOpcode::CoreWaitForHalt => (GspSeqCmd::CoreWaitForHalt, opcode_size),
  106. fw::SeqBufOpcode::CoreResume => (GspSeqCmd::CoreResume, opcode_size),
  107. };
  108. if data.len() < size {
  109. dev_err!(dev, "Data is not enough for command\n");
  110. return Err(EINVAL);
  111. }
  112. Ok((cmd, size))
  113. }
  114. }
  115. /// GSP Sequencer for executing firmware commands during boot.
  116. pub(crate) struct GspSequencer<'a> {
  117. /// Sequencer information with command data.
  118. seq_info: GspSequence,
  119. /// `Bar0` for register access.
  120. bar: &'a Bar0,
  121. /// SEC2 falcon for core operations.
  122. sec2_falcon: &'a Falcon<Sec2>,
  123. /// GSP falcon for core operations.
  124. gsp_falcon: &'a Falcon<Gsp>,
  125. /// LibOS DMA handle address.
  126. libos_dma_handle: u64,
  127. /// Bootloader application version.
  128. bootloader_app_version: u32,
  129. /// Device for logging.
  130. dev: ARef<device::Device>,
  131. }
  132. /// Trait for running sequencer commands.
  133. pub(crate) trait GspSeqCmdRunner {
  134. fn run(&self, sequencer: &GspSequencer<'_>) -> Result;
  135. }
  136. impl GspSeqCmdRunner for fw::RegWritePayload {
  137. fn run(&self, sequencer: &GspSequencer<'_>) -> Result {
  138. let addr = usize::from_safe_cast(self.addr());
  139. sequencer.bar.try_write32(self.val(), addr)
  140. }
  141. }
  142. impl GspSeqCmdRunner for fw::RegModifyPayload {
  143. fn run(&self, sequencer: &GspSequencer<'_>) -> Result {
  144. let addr = usize::from_safe_cast(self.addr());
  145. sequencer.bar.try_read32(addr).and_then(|val| {
  146. sequencer
  147. .bar
  148. .try_write32((val & !self.mask()) | self.val(), addr)
  149. })
  150. }
  151. }
  152. impl GspSeqCmdRunner for fw::RegPollPayload {
  153. fn run(&self, sequencer: &GspSequencer<'_>) -> Result {
  154. let addr = usize::from_safe_cast(self.addr());
  155. // Default timeout to 4 seconds.
  156. let timeout_us = if self.timeout() == 0 {
  157. 4_000_000
  158. } else {
  159. i64::from(self.timeout())
  160. };
  161. // First read.
  162. sequencer.bar.try_read32(addr)?;
  163. // Poll the requested register with requested timeout.
  164. read_poll_timeout(
  165. || sequencer.bar.try_read32(addr),
  166. |current| (current & self.mask()) == self.val(),
  167. Delta::ZERO,
  168. Delta::from_micros(timeout_us),
  169. )
  170. .map(|_| ())
  171. }
  172. }
  173. impl GspSeqCmdRunner for fw::DelayUsPayload {
  174. fn run(&self, _sequencer: &GspSequencer<'_>) -> Result {
  175. fsleep(Delta::from_micros(i64::from(self.val())));
  176. Ok(())
  177. }
  178. }
  179. impl GspSeqCmdRunner for fw::RegStorePayload {
  180. fn run(&self, sequencer: &GspSequencer<'_>) -> Result {
  181. let addr = usize::from_safe_cast(self.addr());
  182. sequencer.bar.try_read32(addr).map(|_| ())
  183. }
  184. }
  185. impl GspSeqCmdRunner for GspSeqCmd {
  186. fn run(&self, seq: &GspSequencer<'_>) -> Result {
  187. match self {
  188. GspSeqCmd::RegWrite(cmd) => cmd.run(seq),
  189. GspSeqCmd::RegModify(cmd) => cmd.run(seq),
  190. GspSeqCmd::RegPoll(cmd) => cmd.run(seq),
  191. GspSeqCmd::DelayUs(cmd) => cmd.run(seq),
  192. GspSeqCmd::RegStore(cmd) => cmd.run(seq),
  193. GspSeqCmd::CoreReset => {
  194. seq.gsp_falcon.reset(seq.bar)?;
  195. seq.gsp_falcon.dma_reset(seq.bar);
  196. Ok(())
  197. }
  198. GspSeqCmd::CoreStart => {
  199. seq.gsp_falcon.start(seq.bar)?;
  200. Ok(())
  201. }
  202. GspSeqCmd::CoreWaitForHalt => {
  203. seq.gsp_falcon.wait_till_halted(seq.bar)?;
  204. Ok(())
  205. }
  206. GspSeqCmd::CoreResume => {
  207. // At this point, 'SEC2-RTOS' has been loaded into SEC2 by the sequencer
  208. // but neither SEC2-RTOS nor GSP-RM is running yet. This part of the
  209. // sequencer will start both.
  210. // Reset the GSP to prepare it for resuming.
  211. seq.gsp_falcon.reset(seq.bar)?;
  212. // Write the libOS DMA handle to GSP mailboxes.
  213. seq.gsp_falcon.write_mailboxes(
  214. seq.bar,
  215. Some(seq.libos_dma_handle as u32),
  216. Some((seq.libos_dma_handle >> 32) as u32),
  217. );
  218. // Start the SEC2 falcon which will trigger GSP-RM to resume on the GSP.
  219. seq.sec2_falcon.start(seq.bar)?;
  220. // Poll until GSP-RM reload/resume has completed (up to 2 seconds).
  221. seq.gsp_falcon
  222. .check_reload_completed(seq.bar, Delta::from_secs(2))?;
  223. // Verify SEC2 completed successfully by checking its mailbox for errors.
  224. let mbox0 = seq.sec2_falcon.read_mailbox0(seq.bar);
  225. if mbox0 != 0 {
  226. dev_err!(seq.dev, "Sequencer: sec2 errors: {:?}\n", mbox0);
  227. return Err(EIO);
  228. }
  229. // Configure GSP with the bootloader version.
  230. seq.gsp_falcon
  231. .write_os_version(seq.bar, seq.bootloader_app_version);
  232. // Verify the GSP's RISC-V core is active indicating successful GSP boot.
  233. if !seq.gsp_falcon.is_riscv_active(seq.bar) {
  234. dev_err!(seq.dev, "Sequencer: RISC-V core is not active\n");
  235. return Err(EIO);
  236. }
  237. Ok(())
  238. }
  239. }
  240. }
  241. }
  242. /// Iterator over GSP sequencer commands.
  243. pub(crate) struct GspSeqIter<'a> {
  244. /// Command data buffer.
  245. cmd_data: &'a [u8],
  246. /// Current position in the buffer.
  247. current_offset: usize,
  248. /// Total number of commands to process.
  249. total_cmds: u32,
  250. /// Number of commands processed so far.
  251. cmds_processed: u32,
  252. /// Device for logging.
  253. dev: ARef<device::Device>,
  254. }
  255. impl<'a> Iterator for GspSeqIter<'a> {
  256. type Item = Result<GspSeqCmd>;
  257. fn next(&mut self) -> Option<Self::Item> {
  258. // Stop if we've processed all commands or reached the end of data.
  259. if self.cmds_processed >= self.total_cmds || self.current_offset >= self.cmd_data.len() {
  260. return None;
  261. }
  262. // Check if we have enough data for opcode.
  263. if self.current_offset + core::mem::size_of::<u32>() > self.cmd_data.len() {
  264. return Some(Err(EIO));
  265. }
  266. let offset = self.current_offset;
  267. // Handle command creation based on available data,
  268. // zero-pad if necessary (since last command may not be full size).
  269. let mut buffer = [0u8; CMD_SIZE];
  270. let copy_len = if offset + CMD_SIZE <= self.cmd_data.len() {
  271. CMD_SIZE
  272. } else {
  273. self.cmd_data.len() - offset
  274. };
  275. buffer[..copy_len].copy_from_slice(&self.cmd_data[offset..offset + copy_len]);
  276. let cmd_result = GspSeqCmd::new(&buffer, &self.dev);
  277. cmd_result.map_or_else(
  278. |_err| {
  279. dev_err!(self.dev, "Error parsing command at offset {}\n", offset);
  280. None
  281. },
  282. |(cmd, size)| {
  283. self.current_offset += size;
  284. self.cmds_processed += 1;
  285. Some(Ok(cmd))
  286. },
  287. )
  288. }
  289. }
  290. impl<'a> GspSequencer<'a> {
  291. fn iter(&self) -> GspSeqIter<'_> {
  292. let cmd_data = &self.seq_info.cmd_data[..];
  293. GspSeqIter {
  294. cmd_data,
  295. current_offset: 0,
  296. total_cmds: self.seq_info.cmd_index,
  297. cmds_processed: 0,
  298. dev: self.dev.clone(),
  299. }
  300. }
  301. }
  302. /// Parameters for running the GSP sequencer.
  303. pub(crate) struct GspSequencerParams<'a> {
  304. /// Bootloader application version.
  305. pub(crate) bootloader_app_version: u32,
  306. /// LibOS DMA handle address.
  307. pub(crate) libos_dma_handle: u64,
  308. /// GSP falcon for core operations.
  309. pub(crate) gsp_falcon: &'a Falcon<Gsp>,
  310. /// SEC2 falcon for core operations.
  311. pub(crate) sec2_falcon: &'a Falcon<Sec2>,
  312. /// Device for logging.
  313. pub(crate) dev: ARef<device::Device>,
  314. /// BAR0 for register access.
  315. pub(crate) bar: &'a Bar0,
  316. }
  317. impl<'a> GspSequencer<'a> {
  318. pub(crate) fn run(cmdq: &mut Cmdq, params: GspSequencerParams<'a>) -> Result {
  319. let seq_info = loop {
  320. match cmdq.receive_msg::<GspSequence>(Delta::from_secs(10)) {
  321. Ok(seq_info) => break seq_info,
  322. Err(ERANGE) => continue,
  323. Err(e) => return Err(e),
  324. }
  325. };
  326. let sequencer = GspSequencer {
  327. seq_info,
  328. bar: params.bar,
  329. sec2_falcon: params.sec2_falcon,
  330. gsp_falcon: params.gsp_falcon,
  331. libos_dma_handle: params.libos_dma_handle,
  332. bootloader_app_version: params.bootloader_app_version,
  333. dev: params.dev,
  334. };
  335. dev_dbg!(sequencer.dev, "Running CPU Sequencer commands\n");
  336. for cmd_result in sequencer.iter() {
  337. match cmd_result {
  338. Ok(cmd) => cmd.run(&sequencer)?,
  339. Err(e) => {
  340. dev_err!(
  341. sequencer.dev,
  342. "Error running command at index {}\n",
  343. sequencer.seq_info.cmd_index
  344. );
  345. return Err(e);
  346. }
  347. }
  348. }
  349. dev_dbg!(
  350. sequencer.dev,
  351. "CPU Sequencer commands completed successfully\n"
  352. );
  353. Ok(())
  354. }
  355. }