1 /* TSI 2023.xmo */
2 /*******************************************************************************
3  * Copyright (c) 2023 Think Silicon Single Member PC
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this header file and/or associated documentation files to use, copy,
7  * modify, merge, publish, distribute, sublicense, and/or sell copies of the
8  * Materials, and to permit persons to whom the Materials are furnished to do
9  * so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Materials.
13  *
14  * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
15  * NEMAGFX API. THE UNMODIFIED, NORMATIVE VERSIONS OF THINK-SILICON NEMAGFX
16  * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT:
17  *   https://think-silicon.com/products/software/nemagfx-api
18  *
19  *  The software is provided 'as is', without warranty of any kind, express or
20  *  implied, including but not limited to the warranties of merchantability,
21  *  fitness for a particular purpose and noninfringement. In no event shall
22  *  Think Silicon Single Member PC be liable for any claim, damages or other
23  *  liability, whether in an action of contract, tort or otherwise, arising
24  *  from, out of or in connection with the software or the use or other dealings
25  *  in the software.
26  ******************************************************************************/
27 
28 
29 #ifndef NEMA_CMDLIST_H__
30 #define NEMA_CMDLIST_H__
31 
32 #include "nema_sys_defs.h"
33 #include "nema_hal.h"
34 
35 #ifdef __cplusplus
36 extern "C" {
37 #endif
38 
39 #define CL_NOP      0x010000U
40 #define CL_PUSH     0x020000U
41 #define CL_RETURN   0x040000U
42 #define CL_ABORT    0x080000U
43 
44 #define CL_BATCH_SHIFT      12
45 #define CL_BATCH_LOOP       0x8000
46 
47 #define SUBMISSION_ID_MASK 0xffffff
48 
49 #define CL_ALIGNMENT_MASK  (0x00000007U) // CL buffer must be 8 byte aligned
50 
51 //---------------------------------------------------------------------------
52 typedef struct nema_cmdlist_t_ {
53     nema_buffer_t bo;
54     int size;                       /**< Number of entries in the command list */
55     int offset;                     /**< Points to the next address to write */
56     uint32_t flags;                 /**< Flags */
57     int32_t  submission_id;
58     struct nema_cmdlist_t_ *next;   /**< Points to next command list */
59     struct nema_cmdlist_t_ *root;   /**< Points to the head of the list */
60 } nema_cmdlist_t;
61 
62 /** \brief Create a new Command List into a preallocated space
63  *
64  * \param addr_virt  Command List's address (preallocated)
65  * \param size_bytes Command List's size in bytes
66  * \return The instance of the new Command List
67  *
68  */
69 nema_cmdlist_t nema_cl_create_prealloc(nema_buffer_t *bo);
70 
71 /** \brief Create a new, non expandable Command List of specific size
72  *
73  * \param size_bytes Command List's size in bytes
74  * \return The instance of the new Command List
75  *
76  */
77 nema_cmdlist_t nema_cl_create_sized(int size_bytes);
78 
79 /** \brief Create a new expandable Command List
80  *
81  * \return The instance of the new Command List
82  *
83  */
84 nema_cmdlist_t nema_cl_create(void);
85 
86 /** \brief Destroy/Free a Command List
87  *
88  * \param cl Pointer to the Command List
89  *
90  */
91 void nema_cl_destroy(nema_cmdlist_t *cl);
92 
93 /** \brief Reset position of next command to be written to the beginning. Doesn't clear the List's contents.
94  *
95  * \param cl Pointer to the Command List
96  *
97  */
98 void nema_cl_rewind(nema_cmdlist_t *cl);
99 
100 /** \brief Define in which Command List each subsequent commands are going to be inserted.
101  *
102  * \param cl Pointer to the Command List
103  *
104  */
105 void nema_cl_bind(nema_cmdlist_t *cl);
106 
107 /** \brief Define in which Command List each subsequent commands are going to be inserted.
108  *         Bind this command list as Circular. It never gets full, it never expands,
109  *         it may get implicitly submitted, it cannot be reused. No other CL should be submitted
110  *         while a circular CL is bound
111  *
112  * \param cl Pointer to the Command List
113  *
114  */
115 void nema_cl_bind_circular(nema_cmdlist_t *cl);
116 
117 /** \brief Unbind current bound Command List, if any.
118  *
119  *
120  */
121 void nema_cl_unbind(void);
122 
123 
124 /** \brief Get bound Command List
125  *
126  * \return Pointer to the bound Command List
127  *
128  */
129 nema_cmdlist_t *nema_cl_get_bound(void);
130 
131 /** \private */
132 void nema_cl_submit_no_irq(nema_cmdlist_t *cl);
133 
134 /** \brief Enqueue Command List to the Ring Buffer for execution
135  *
136  * \param cl Pointer to the Command List
137  *
138  */
139 void nema_cl_submit(nema_cmdlist_t *cl);
140 
141 /** \brief Wait for Command List to finish
142  *
143  * \param cl Pointer to the Command List
144  * \return 0 if no error has occurred
145  *
146  */
147 int nema_cl_wait(nema_cmdlist_t *cl);
148 
149 /** \brief Add a command to the bound Command List
150  *
151  * \param reg Hardware register to be written
152  * \param data Data to be written
153  *
154  */
155 void nema_cl_add_cmd(uint32_t reg, uint32_t data);
156 
157 /** \brief Add multiple commands to the bound Command List
158  *
159  * \param cmd_no Numbers of commands to add
160  * \param cmd Pointer to the commands to be added
161  * \return 0 if no error has occurred
162  *
163  */
164 int nema_cl_add_multiple_cmds(int cmd_no, uint32_t *cmd);
165 
166 /** private */
167 uint32_t * nema_cl_get_space(int cmd_no);
168 
169 /** \brief Branch from the bound Command List to a different one. Return is implied.
170  *
171  * \param cl Pointer to the Command List to branch to
172  *
173  */
174 void nema_cl_branch(nema_cmdlist_t *cl);
175 
176 /** \brief Jump from the bound Command List to a different one. No return is implied.
177  *
178  * \param cl Pointer to the Command List to jump to
179  *
180  */
181 void nema_cl_jump(nema_cmdlist_t *cl);
182 
183 /** \brief Add an explicit return command to the bound Command List
184  *
185  *
186  */
187 void nema_cl_return(void);
188 
189 /** \brief Returns positive number if the Command List is almost full, otherwise returns 0.
190  *
191  * \param cl Pointer to the Command List
192  *
193  */
194 int nema_cl_almost_full(nema_cmdlist_t *cl);
195 
196 /** \brief Check if there is enough space or expansion can be performed for
197  * required commands.
198  *
199  * \param cmd_no Numbers of commands to be checked if they fit
200  * \reurn zero is commands fit or expansion xan be performed else return negative
201  */
202 int nema_cl_enough_space(int cmd_no);
203 
204 #ifdef __cplusplus
205 }
206 #endif
207 
208 #endif
209