Skip to content

Commit eaf0989

Browse files
Joel FernandesGnurou
authored andcommitted
gpu: nova-core: Add bindings required by GSP sequencer
Add several firmware bindings required by GSP sequencer code. Co-developed-by: Alistair Popple <apopple@nvidia.com> Signed-off-by: Alistair Popple <apopple@nvidia.com> Reviewed-by: Lyude Paul <lyude@redhat.com> Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com> [acourbot@nvidia.com: remove a couple stray lines/unwanted comment changes.] Signed-off-by: Alexandre Courbot <acourbot@nvidia.com> Message-ID: <20251114195552.739371-7-joelagnelf@nvidia.com>
1 parent f77be04 commit eaf0989

2 files changed

Lines changed: 407 additions & 0 deletions

File tree

drivers/gpu/nova-core/gsp/fw.rs

Lines changed: 323 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,329 @@ impl From<MsgFunction> for u32 {
312312
}
313313
}
314314

315+
/// Sequencer buffer opcode for GSP sequencer commands.
316+
#[derive(Copy, Clone, Debug, PartialEq)]
317+
#[repr(u32)]
318+
pub(crate) enum SeqBufOpcode {
319+
// Core operation opcodes
320+
CoreReset = r570_144::GSP_SEQ_BUF_OPCODE_GSP_SEQ_BUF_OPCODE_CORE_RESET,
321+
CoreResume = r570_144::GSP_SEQ_BUF_OPCODE_GSP_SEQ_BUF_OPCODE_CORE_RESUME,
322+
CoreStart = r570_144::GSP_SEQ_BUF_OPCODE_GSP_SEQ_BUF_OPCODE_CORE_START,
323+
CoreWaitForHalt = r570_144::GSP_SEQ_BUF_OPCODE_GSP_SEQ_BUF_OPCODE_CORE_WAIT_FOR_HALT,
324+
325+
// Delay opcode
326+
DelayUs = r570_144::GSP_SEQ_BUF_OPCODE_GSP_SEQ_BUF_OPCODE_DELAY_US,
327+
328+
// Register operation opcodes
329+
RegModify = r570_144::GSP_SEQ_BUF_OPCODE_GSP_SEQ_BUF_OPCODE_REG_MODIFY,
330+
RegPoll = r570_144::GSP_SEQ_BUF_OPCODE_GSP_SEQ_BUF_OPCODE_REG_POLL,
331+
RegStore = r570_144::GSP_SEQ_BUF_OPCODE_GSP_SEQ_BUF_OPCODE_REG_STORE,
332+
RegWrite = r570_144::GSP_SEQ_BUF_OPCODE_GSP_SEQ_BUF_OPCODE_REG_WRITE,
333+
}
334+
335+
impl fmt::Display for SeqBufOpcode {
336+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
337+
match self {
338+
SeqBufOpcode::CoreReset => write!(f, "CORE_RESET"),
339+
SeqBufOpcode::CoreResume => write!(f, "CORE_RESUME"),
340+
SeqBufOpcode::CoreStart => write!(f, "CORE_START"),
341+
SeqBufOpcode::CoreWaitForHalt => write!(f, "CORE_WAIT_FOR_HALT"),
342+
SeqBufOpcode::DelayUs => write!(f, "DELAY_US"),
343+
SeqBufOpcode::RegModify => write!(f, "REG_MODIFY"),
344+
SeqBufOpcode::RegPoll => write!(f, "REG_POLL"),
345+
SeqBufOpcode::RegStore => write!(f, "REG_STORE"),
346+
SeqBufOpcode::RegWrite => write!(f, "REG_WRITE"),
347+
}
348+
}
349+
}
350+
351+
impl TryFrom<u32> for SeqBufOpcode {
352+
type Error = kernel::error::Error;
353+
354+
fn try_from(value: u32) -> Result<SeqBufOpcode> {
355+
match value {
356+
r570_144::GSP_SEQ_BUF_OPCODE_GSP_SEQ_BUF_OPCODE_CORE_RESET => {
357+
Ok(SeqBufOpcode::CoreReset)
358+
}
359+
r570_144::GSP_SEQ_BUF_OPCODE_GSP_SEQ_BUF_OPCODE_CORE_RESUME => {
360+
Ok(SeqBufOpcode::CoreResume)
361+
}
362+
r570_144::GSP_SEQ_BUF_OPCODE_GSP_SEQ_BUF_OPCODE_CORE_START => {
363+
Ok(SeqBufOpcode::CoreStart)
364+
}
365+
r570_144::GSP_SEQ_BUF_OPCODE_GSP_SEQ_BUF_OPCODE_CORE_WAIT_FOR_HALT => {
366+
Ok(SeqBufOpcode::CoreWaitForHalt)
367+
}
368+
r570_144::GSP_SEQ_BUF_OPCODE_GSP_SEQ_BUF_OPCODE_DELAY_US => Ok(SeqBufOpcode::DelayUs),
369+
r570_144::GSP_SEQ_BUF_OPCODE_GSP_SEQ_BUF_OPCODE_REG_MODIFY => {
370+
Ok(SeqBufOpcode::RegModify)
371+
}
372+
r570_144::GSP_SEQ_BUF_OPCODE_GSP_SEQ_BUF_OPCODE_REG_POLL => Ok(SeqBufOpcode::RegPoll),
373+
r570_144::GSP_SEQ_BUF_OPCODE_GSP_SEQ_BUF_OPCODE_REG_STORE => Ok(SeqBufOpcode::RegStore),
374+
r570_144::GSP_SEQ_BUF_OPCODE_GSP_SEQ_BUF_OPCODE_REG_WRITE => Ok(SeqBufOpcode::RegWrite),
375+
_ => Err(EINVAL),
376+
}
377+
}
378+
}
379+
380+
impl From<SeqBufOpcode> for u32 {
381+
fn from(value: SeqBufOpcode) -> Self {
382+
// CAST: `SeqBufOpcode` is `repr(u32)` and can thus be cast losslessly.
383+
value as u32
384+
}
385+
}
386+
387+
/// Wrapper for GSP sequencer register write payload.
388+
#[repr(transparent)]
389+
#[derive(Copy, Clone)]
390+
pub(crate) struct RegWritePayload(r570_144::GSP_SEQ_BUF_PAYLOAD_REG_WRITE);
391+
392+
#[expect(unused)]
393+
impl RegWritePayload {
394+
/// Returns the register address.
395+
pub(crate) fn addr(&self) -> u32 {
396+
self.0.addr
397+
}
398+
399+
/// Returns the value to write.
400+
pub(crate) fn val(&self) -> u32 {
401+
self.0.val
402+
}
403+
}
404+
405+
// SAFETY: This struct only contains integer types for which all bit patterns are valid.
406+
unsafe impl FromBytes for RegWritePayload {}
407+
408+
// SAFETY: Padding is explicit and will not contain uninitialized data.
409+
unsafe impl AsBytes for RegWritePayload {}
410+
411+
/// Wrapper for GSP sequencer register modify payload.
412+
#[repr(transparent)]
413+
#[derive(Copy, Clone)]
414+
pub(crate) struct RegModifyPayload(r570_144::GSP_SEQ_BUF_PAYLOAD_REG_MODIFY);
415+
416+
#[expect(unused)]
417+
impl RegModifyPayload {
418+
/// Returns the register address.
419+
pub(crate) fn addr(&self) -> u32 {
420+
self.0.addr
421+
}
422+
423+
/// Returns the mask to apply.
424+
pub(crate) fn mask(&self) -> u32 {
425+
self.0.mask
426+
}
427+
428+
/// Returns the value to write.
429+
pub(crate) fn val(&self) -> u32 {
430+
self.0.val
431+
}
432+
}
433+
434+
// SAFETY: This struct only contains integer types for which all bit patterns are valid.
435+
unsafe impl FromBytes for RegModifyPayload {}
436+
437+
// SAFETY: Padding is explicit and will not contain uninitialized data.
438+
unsafe impl AsBytes for RegModifyPayload {}
439+
440+
/// Wrapper for GSP sequencer register poll payload.
441+
#[repr(transparent)]
442+
#[derive(Copy, Clone)]
443+
pub(crate) struct RegPollPayload(r570_144::GSP_SEQ_BUF_PAYLOAD_REG_POLL);
444+
445+
#[expect(unused)]
446+
impl RegPollPayload {
447+
/// Returns the register address.
448+
pub(crate) fn addr(&self) -> u32 {
449+
self.0.addr
450+
}
451+
452+
/// Returns the mask to apply.
453+
pub(crate) fn mask(&self) -> u32 {
454+
self.0.mask
455+
}
456+
457+
/// Returns the expected value.
458+
pub(crate) fn val(&self) -> u32 {
459+
self.0.val
460+
}
461+
462+
/// Returns the timeout in microseconds.
463+
pub(crate) fn timeout(&self) -> u32 {
464+
self.0.timeout
465+
}
466+
}
467+
468+
// SAFETY: This struct only contains integer types for which all bit patterns are valid.
469+
unsafe impl FromBytes for RegPollPayload {}
470+
471+
// SAFETY: Padding is explicit and will not contain uninitialized data.
472+
unsafe impl AsBytes for RegPollPayload {}
473+
474+
/// Wrapper for GSP sequencer delay payload.
475+
#[repr(transparent)]
476+
#[derive(Copy, Clone)]
477+
pub(crate) struct DelayUsPayload(r570_144::GSP_SEQ_BUF_PAYLOAD_DELAY_US);
478+
479+
#[expect(unused)]
480+
impl DelayUsPayload {
481+
/// Returns the delay value in microseconds.
482+
pub(crate) fn val(&self) -> u32 {
483+
self.0.val
484+
}
485+
}
486+
487+
// SAFETY: This struct only contains integer types for which all bit patterns are valid.
488+
unsafe impl FromBytes for DelayUsPayload {}
489+
490+
// SAFETY: Padding is explicit and will not contain uninitialized data.
491+
unsafe impl AsBytes for DelayUsPayload {}
492+
493+
/// Wrapper for GSP sequencer register store payload.
494+
#[repr(transparent)]
495+
#[derive(Copy, Clone)]
496+
pub(crate) struct RegStorePayload(r570_144::GSP_SEQ_BUF_PAYLOAD_REG_STORE);
497+
498+
#[expect(unused)]
499+
impl RegStorePayload {
500+
/// Returns the register address.
501+
pub(crate) fn addr(&self) -> u32 {
502+
self.0.addr
503+
}
504+
505+
/// Returns the storage index.
506+
pub(crate) fn index(&self) -> u32 {
507+
self.0.index
508+
}
509+
}
510+
511+
// SAFETY: This struct only contains integer types for which all bit patterns are valid.
512+
unsafe impl FromBytes for RegStorePayload {}
513+
514+
// SAFETY: Padding is explicit and will not contain uninitialized data.
515+
unsafe impl AsBytes for RegStorePayload {}
516+
517+
/// Wrapper for GSP sequencer buffer command.
518+
#[repr(transparent)]
519+
pub(crate) struct SequencerBufferCmd(r570_144::GSP_SEQUENCER_BUFFER_CMD);
520+
521+
#[expect(unused)]
522+
impl SequencerBufferCmd {
523+
/// Returns the opcode as a `SeqBufOpcode` enum, or error if invalid.
524+
pub(crate) fn opcode(&self) -> Result<SeqBufOpcode> {
525+
self.0.opCode.try_into()
526+
}
527+
528+
/// Returns the register write payload by value.
529+
///
530+
/// Returns an error if the opcode is not `SeqBufOpcode::RegWrite`.
531+
pub(crate) fn reg_write_payload(&self) -> Result<RegWritePayload> {
532+
if self.opcode()? != SeqBufOpcode::RegWrite {
533+
return Err(EINVAL);
534+
}
535+
// SAFETY: Opcode is verified to be `RegWrite`, so union contains valid `RegWritePayload`.
536+
let payload_bytes = unsafe {
537+
core::slice::from_raw_parts(
538+
core::ptr::addr_of!(self.0.payload.regWrite).cast::<u8>(),
539+
core::mem::size_of::<RegWritePayload>(),
540+
)
541+
};
542+
Ok(*RegWritePayload::from_bytes(payload_bytes).ok_or(EINVAL)?)
543+
}
544+
545+
/// Returns the register modify payload by value.
546+
///
547+
/// Returns an error if the opcode is not `SeqBufOpcode::RegModify`.
548+
pub(crate) fn reg_modify_payload(&self) -> Result<RegModifyPayload> {
549+
if self.opcode()? != SeqBufOpcode::RegModify {
550+
return Err(EINVAL);
551+
}
552+
// SAFETY: Opcode is verified to be `RegModify`, so union contains valid `RegModifyPayload`.
553+
let payload_bytes = unsafe {
554+
core::slice::from_raw_parts(
555+
core::ptr::addr_of!(self.0.payload.regModify).cast::<u8>(),
556+
core::mem::size_of::<RegModifyPayload>(),
557+
)
558+
};
559+
Ok(*RegModifyPayload::from_bytes(payload_bytes).ok_or(EINVAL)?)
560+
}
561+
562+
/// Returns the register poll payload by value.
563+
///
564+
/// Returns an error if the opcode is not `SeqBufOpcode::RegPoll`.
565+
pub(crate) fn reg_poll_payload(&self) -> Result<RegPollPayload> {
566+
if self.opcode()? != SeqBufOpcode::RegPoll {
567+
return Err(EINVAL);
568+
}
569+
// SAFETY: Opcode is verified to be `RegPoll`, so union contains valid `RegPollPayload`.
570+
let payload_bytes = unsafe {
571+
core::slice::from_raw_parts(
572+
core::ptr::addr_of!(self.0.payload.regPoll).cast::<u8>(),
573+
core::mem::size_of::<RegPollPayload>(),
574+
)
575+
};
576+
Ok(*RegPollPayload::from_bytes(payload_bytes).ok_or(EINVAL)?)
577+
}
578+
579+
/// Returns the delay payload by value.
580+
///
581+
/// Returns an error if the opcode is not `SeqBufOpcode::DelayUs`.
582+
pub(crate) fn delay_us_payload(&self) -> Result<DelayUsPayload> {
583+
if self.opcode()? != SeqBufOpcode::DelayUs {
584+
return Err(EINVAL);
585+
}
586+
// SAFETY: Opcode is verified to be `DelayUs`, so union contains valid `DelayUsPayload`.
587+
let payload_bytes = unsafe {
588+
core::slice::from_raw_parts(
589+
core::ptr::addr_of!(self.0.payload.delayUs).cast::<u8>(),
590+
core::mem::size_of::<DelayUsPayload>(),
591+
)
592+
};
593+
Ok(*DelayUsPayload::from_bytes(payload_bytes).ok_or(EINVAL)?)
594+
}
595+
596+
/// Returns the register store payload by value.
597+
///
598+
/// Returns an error if the opcode is not `SeqBufOpcode::RegStore`.
599+
pub(crate) fn reg_store_payload(&self) -> Result<RegStorePayload> {
600+
if self.opcode()? != SeqBufOpcode::RegStore {
601+
return Err(EINVAL);
602+
}
603+
// SAFETY: Opcode is verified to be `RegStore`, so union contains valid `RegStorePayload`.
604+
let payload_bytes = unsafe {
605+
core::slice::from_raw_parts(
606+
core::ptr::addr_of!(self.0.payload.regStore).cast::<u8>(),
607+
core::mem::size_of::<RegStorePayload>(),
608+
)
609+
};
610+
Ok(*RegStorePayload::from_bytes(payload_bytes).ok_or(EINVAL)?)
611+
}
612+
}
613+
614+
// SAFETY: This struct only contains integer types for which all bit patterns are valid.
615+
unsafe impl FromBytes for SequencerBufferCmd {}
616+
617+
// SAFETY: Padding is explicit and will not contain uninitialized data.
618+
unsafe impl AsBytes for SequencerBufferCmd {}
619+
620+
/// Wrapper for GSP run CPU sequencer RPC.
621+
#[repr(transparent)]
622+
pub(crate) struct RunCpuSequencer(r570_144::rpc_run_cpu_sequencer_v17_00);
623+
624+
#[expect(unused)]
625+
impl RunCpuSequencer {
626+
/// Returns the command index.
627+
pub(crate) fn cmd_index(&self) -> u32 {
628+
self.0.cmdIndex
629+
}
630+
}
631+
632+
// SAFETY: This struct only contains integer types for which all bit patterns are valid.
633+
unsafe impl FromBytes for RunCpuSequencer {}
634+
635+
// SAFETY: Padding is explicit and will not contain uninitialized data.
636+
unsafe impl AsBytes for RunCpuSequencer {}
637+
315638
/// Struct containing the arguments required to pass a memory buffer to the GSP
316639
/// for use during initialisation.
317640
///

0 commit comments

Comments
 (0)