44
55use core:: {
66 array,
7- mem:: size_of, //
7+ mem:: {
8+ size_of,
9+ size_of_val, //
10+ } ,
811} ;
912
1013use kernel:: {
1114 device,
15+ io:: poll:: read_poll_timeout,
1216 prelude:: * ,
1317 time:: Delta ,
1418 transmute:: FromBytes ,
@@ -29,6 +33,7 @@ use crate::{
2933 } ,
3034 fw,
3135 } ,
36+ num:: FromSafeCast ,
3237 sbuffer:: SBufferIter ,
3338} ;
3439
@@ -61,18 +66,50 @@ const CMD_SIZE: usize = size_of::<fw::SequencerBufferCmd>();
6166
6267/// GSP Sequencer Command types with payload data.
6368/// Commands have an opcode and an opcode-dependent struct.
64- #[ allow( dead_code) ]
65- pub ( crate ) enum GspSeqCmd { }
69+ #[ allow( clippy:: enum_variant_names) ]
70+ pub ( crate ) enum GspSeqCmd {
71+ RegWrite ( fw:: RegWritePayload ) ,
72+ RegModify ( fw:: RegModifyPayload ) ,
73+ RegPoll ( fw:: RegPollPayload ) ,
74+ RegStore ( fw:: RegStorePayload ) ,
75+ }
6676
6777impl GspSeqCmd {
6878 /// Creates a new `GspSeqCmd` from raw data returning the command and its size in bytes.
69- pub ( crate ) fn new ( data : & [ u8 ] , _dev : & device:: Device ) -> Result < ( Self , usize ) > {
70- let _fw_cmd = fw:: SequencerBufferCmd :: from_bytes ( data) . ok_or ( EINVAL ) ?;
71- let _opcode_size = core:: mem:: size_of :: < u32 > ( ) ;
79+ pub ( crate ) fn new ( data : & [ u8 ] , dev : & device:: Device ) -> Result < ( Self , usize ) > {
80+ let fw_cmd = fw:: SequencerBufferCmd :: from_bytes ( data) . ok_or ( EINVAL ) ?;
81+ let opcode_size = core:: mem:: size_of :: < u32 > ( ) ;
7282
73- // NOTE: At this commit, NO opcodes exist yet, so just return error.
74- // Later commits will add match arms here.
75- Err ( EINVAL )
83+ let ( cmd, size) = match fw_cmd. opcode ( ) ? {
84+ fw:: SeqBufOpcode :: RegWrite => {
85+ let payload = fw_cmd. reg_write_payload ( ) ?;
86+ let size = opcode_size + size_of_val ( & payload) ;
87+ ( GspSeqCmd :: RegWrite ( payload) , size)
88+ }
89+ fw:: SeqBufOpcode :: RegModify => {
90+ let payload = fw_cmd. reg_modify_payload ( ) ?;
91+ let size = opcode_size + size_of_val ( & payload) ;
92+ ( GspSeqCmd :: RegModify ( payload) , size)
93+ }
94+ fw:: SeqBufOpcode :: RegPoll => {
95+ let payload = fw_cmd. reg_poll_payload ( ) ?;
96+ let size = opcode_size + size_of_val ( & payload) ;
97+ ( GspSeqCmd :: RegPoll ( payload) , size)
98+ }
99+ fw:: SeqBufOpcode :: RegStore => {
100+ let payload = fw_cmd. reg_store_payload ( ) ?;
101+ let size = opcode_size + size_of_val ( & payload) ;
102+ ( GspSeqCmd :: RegStore ( payload) , size)
103+ }
104+ _ => return Err ( EINVAL ) ,
105+ } ;
106+
107+ if data. len ( ) < size {
108+ dev_err ! ( dev, "Data is not enough for command" ) ;
109+ return Err ( EINVAL ) ;
110+ }
111+
112+ Ok ( ( cmd, size) )
76113 }
77114}
78115
@@ -100,9 +137,67 @@ pub(crate) trait GspSeqCmdRunner {
100137 fn run ( & self , sequencer : & GspSequencer < ' _ > ) -> Result ;
101138}
102139
140+ impl GspSeqCmdRunner for fw:: RegWritePayload {
141+ fn run ( & self , sequencer : & GspSequencer < ' _ > ) -> Result {
142+ let addr = usize:: from_safe_cast ( self . addr ( ) ) ;
143+
144+ sequencer. bar . try_write32 ( self . val ( ) , addr)
145+ }
146+ }
147+
148+ impl GspSeqCmdRunner for fw:: RegModifyPayload {
149+ fn run ( & self , sequencer : & GspSequencer < ' _ > ) -> Result {
150+ let addr = usize:: from_safe_cast ( self . addr ( ) ) ;
151+
152+ sequencer. bar . try_read32 ( addr) . and_then ( |val| {
153+ sequencer
154+ . bar
155+ . try_write32 ( ( val & !self . mask ( ) ) | self . val ( ) , addr)
156+ } )
157+ }
158+ }
159+
160+ impl GspSeqCmdRunner for fw:: RegPollPayload {
161+ fn run ( & self , sequencer : & GspSequencer < ' _ > ) -> Result {
162+ let addr = usize:: from_safe_cast ( self . addr ( ) ) ;
163+
164+ // Default timeout to 4 seconds.
165+ let timeout_us = if self . timeout ( ) == 0 {
166+ 4_000_000
167+ } else {
168+ i64:: from ( self . timeout ( ) )
169+ } ;
170+
171+ // First read.
172+ sequencer. bar . try_read32 ( addr) ?;
173+
174+ // Poll the requested register with requested timeout.
175+ read_poll_timeout (
176+ || sequencer. bar . try_read32 ( addr) ,
177+ |current| ( current & self . mask ( ) ) == self . val ( ) ,
178+ Delta :: ZERO ,
179+ Delta :: from_micros ( timeout_us) ,
180+ )
181+ . map ( |_| ( ) )
182+ }
183+ }
184+
185+ impl GspSeqCmdRunner for fw:: RegStorePayload {
186+ fn run ( & self , sequencer : & GspSequencer < ' _ > ) -> Result {
187+ let addr = usize:: from_safe_cast ( self . addr ( ) ) ;
188+
189+ sequencer. bar . try_read32 ( addr) . map ( |_| ( ) )
190+ }
191+ }
192+
103193impl GspSeqCmdRunner for GspSeqCmd {
104- fn run ( & self , _seq : & GspSequencer < ' _ > ) -> Result {
105- Ok ( ( ) )
194+ fn run ( & self , seq : & GspSequencer < ' _ > ) -> Result {
195+ match self {
196+ GspSeqCmd :: RegWrite ( cmd) => cmd. run ( seq) ,
197+ GspSeqCmd :: RegModify ( cmd) => cmd. run ( seq) ,
198+ GspSeqCmd :: RegPoll ( cmd) => cmd. run ( seq) ,
199+ GspSeqCmd :: RegStore ( cmd) => cmd. run ( seq) ,
200+ }
106201 }
107202}
108203
0 commit comments