1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * Copyright (c) 2018 MediaTek Inc. |
4 | * |
5 | */ |
6 | |
7 | #ifndef __MTK_CMDQ_H__ |
8 | #define __MTK_CMDQ_H__ |
9 | |
10 | #include <linux/mailbox_client.h> |
11 | #include <linux/mailbox/mtk-cmdq-mailbox.h> |
12 | #include <linux/timer.h> |
13 | |
14 | #define CMDQ_ADDR_HIGH(addr) ((u32)(((addr) >> 16) & GENMASK(31, 0))) |
15 | #define CMDQ_ADDR_LOW(addr) ((u16)(addr) | BIT(1)) |
16 | |
17 | struct cmdq_pkt; |
18 | |
19 | struct cmdq_client_reg { |
20 | u8 subsys; |
21 | u16 offset; |
22 | u16 size; |
23 | }; |
24 | |
25 | struct cmdq_client { |
26 | struct mbox_client client; |
27 | struct mbox_chan *chan; |
28 | }; |
29 | |
30 | #if IS_ENABLED(CONFIG_MTK_CMDQ) |
31 | |
32 | /** |
33 | * cmdq_dev_get_client_reg() - parse cmdq client reg from the device |
34 | * node of CMDQ client |
35 | * @dev: device of CMDQ mailbox client |
36 | * @client_reg: CMDQ client reg pointer |
37 | * @idx: the index of desired reg |
38 | * |
39 | * Return: 0 for success; else the error code is returned |
40 | * |
41 | * Help CMDQ client parsing the cmdq client reg |
42 | * from the device node of CMDQ client. |
43 | */ |
44 | int cmdq_dev_get_client_reg(struct device *dev, |
45 | struct cmdq_client_reg *client_reg, int idx); |
46 | |
47 | /** |
48 | * cmdq_mbox_create() - create CMDQ mailbox client and channel |
49 | * @dev: device of CMDQ mailbox client |
50 | * @index: index of CMDQ mailbox channel |
51 | * |
52 | * Return: CMDQ mailbox client pointer |
53 | */ |
54 | struct cmdq_client *cmdq_mbox_create(struct device *dev, int index); |
55 | |
56 | /** |
57 | * cmdq_mbox_destroy() - destroy CMDQ mailbox client and channel |
58 | * @client: the CMDQ mailbox client |
59 | */ |
60 | void cmdq_mbox_destroy(struct cmdq_client *client); |
61 | |
62 | /** |
63 | * cmdq_pkt_create() - create a CMDQ packet |
64 | * @client: the CMDQ mailbox client |
65 | * @size: required CMDQ buffer size |
66 | * |
67 | * Return: CMDQ packet pointer |
68 | */ |
69 | struct cmdq_pkt *cmdq_pkt_create(struct cmdq_client *client, size_t size); |
70 | |
71 | /** |
72 | * cmdq_pkt_destroy() - destroy the CMDQ packet |
73 | * @pkt: the CMDQ packet |
74 | */ |
75 | void cmdq_pkt_destroy(struct cmdq_pkt *pkt); |
76 | |
77 | /** |
78 | * cmdq_pkt_write() - append write command to the CMDQ packet |
79 | * @pkt: the CMDQ packet |
80 | * @subsys: the CMDQ sub system code |
81 | * @offset: register offset from CMDQ sub system |
82 | * @value: the specified target register value |
83 | * |
84 | * Return: 0 for success; else the error code is returned |
85 | */ |
86 | int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value); |
87 | |
88 | /** |
89 | * cmdq_pkt_write_mask() - append write command with mask to the CMDQ packet |
90 | * @pkt: the CMDQ packet |
91 | * @subsys: the CMDQ sub system code |
92 | * @offset: register offset from CMDQ sub system |
93 | * @value: the specified target register value |
94 | * @mask: the specified target register mask |
95 | * |
96 | * Return: 0 for success; else the error code is returned |
97 | */ |
98 | int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys, |
99 | u16 offset, u32 value, u32 mask); |
100 | |
101 | /* |
102 | * cmdq_pkt_read_s() - append read_s command to the CMDQ packet |
103 | * @pkt: the CMDQ packet |
104 | * @high_addr_reg_idx: internal register ID which contains high address of pa |
105 | * @addr_low: low address of pa |
106 | * @reg_idx: the CMDQ internal register ID to cache read data |
107 | * |
108 | * Return: 0 for success; else the error code is returned |
109 | */ |
110 | int cmdq_pkt_read_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, u16 addr_low, |
111 | u16 reg_idx); |
112 | |
113 | /** |
114 | * cmdq_pkt_write_s() - append write_s command to the CMDQ packet |
115 | * @pkt: the CMDQ packet |
116 | * @high_addr_reg_idx: internal register ID which contains high address of pa |
117 | * @addr_low: low address of pa |
118 | * @src_reg_idx: the CMDQ internal register ID which cache source value |
119 | * |
120 | * Return: 0 for success; else the error code is returned |
121 | * |
122 | * Support write value to physical address without subsys. Use CMDQ_ADDR_HIGH() |
123 | * to get high address and call cmdq_pkt_assign() to assign value into internal |
124 | * reg. Also use CMDQ_ADDR_LOW() to get low address for addr_low parameter when |
125 | * call to this function. |
126 | */ |
127 | int cmdq_pkt_write_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, |
128 | u16 addr_low, u16 src_reg_idx); |
129 | |
130 | /** |
131 | * cmdq_pkt_write_s_mask() - append write_s with mask command to the CMDQ packet |
132 | * @pkt: the CMDQ packet |
133 | * @high_addr_reg_idx: internal register ID which contains high address of pa |
134 | * @addr_low: low address of pa |
135 | * @src_reg_idx: the CMDQ internal register ID which cache source value |
136 | * @mask: the specified target address mask, use U32_MAX if no need |
137 | * |
138 | * Return: 0 for success; else the error code is returned |
139 | * |
140 | * Support write value to physical address without subsys. Use CMDQ_ADDR_HIGH() |
141 | * to get high address and call cmdq_pkt_assign() to assign value into internal |
142 | * reg. Also use CMDQ_ADDR_LOW() to get low address for addr_low parameter when |
143 | * call to this function. |
144 | */ |
145 | int cmdq_pkt_write_s_mask(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, |
146 | u16 addr_low, u16 src_reg_idx, u32 mask); |
147 | |
148 | /** |
149 | * cmdq_pkt_write_s_value() - append write_s command to the CMDQ packet which |
150 | * write value to a physical address |
151 | * @pkt: the CMDQ packet |
152 | * @high_addr_reg_idx: internal register ID which contains high address of pa |
153 | * @addr_low: low address of pa |
154 | * @value: the specified target value |
155 | * |
156 | * Return: 0 for success; else the error code is returned |
157 | */ |
158 | int cmdq_pkt_write_s_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx, |
159 | u16 addr_low, u32 value); |
160 | |
161 | /** |
162 | * cmdq_pkt_write_s_mask_value() - append write_s command with mask to the CMDQ |
163 | * packet which write value to a physical |
164 | * address |
165 | * @pkt: the CMDQ packet |
166 | * @high_addr_reg_idx: internal register ID which contains high address of pa |
167 | * @addr_low: low address of pa |
168 | * @value: the specified target value |
169 | * @mask: the specified target mask |
170 | * |
171 | * Return: 0 for success; else the error code is returned |
172 | */ |
173 | int cmdq_pkt_write_s_mask_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx, |
174 | u16 addr_low, u32 value, u32 mask); |
175 | |
176 | /** |
177 | * cmdq_pkt_wfe() - append wait for event command to the CMDQ packet |
178 | * @pkt: the CMDQ packet |
179 | * @event: the desired event type to wait |
180 | * @clear: clear event or not after event arrive |
181 | * |
182 | * Return: 0 for success; else the error code is returned |
183 | */ |
184 | int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event, bool clear); |
185 | |
186 | /** |
187 | * cmdq_pkt_clear_event() - append clear event command to the CMDQ packet |
188 | * @pkt: the CMDQ packet |
189 | * @event: the desired event to be cleared |
190 | * |
191 | * Return: 0 for success; else the error code is returned |
192 | */ |
193 | int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event); |
194 | |
195 | /** |
196 | * cmdq_pkt_set_event() - append set event command to the CMDQ packet |
197 | * @pkt: the CMDQ packet |
198 | * @event: the desired event to be set |
199 | * |
200 | * Return: 0 for success; else the error code is returned |
201 | */ |
202 | int cmdq_pkt_set_event(struct cmdq_pkt *pkt, u16 event); |
203 | |
204 | /** |
205 | * cmdq_pkt_poll() - Append polling command to the CMDQ packet, ask GCE to |
206 | * execute an instruction that wait for a specified |
207 | * hardware register to check for the value w/o mask. |
208 | * All GCE hardware threads will be blocked by this |
209 | * instruction. |
210 | * @pkt: the CMDQ packet |
211 | * @subsys: the CMDQ sub system code |
212 | * @offset: register offset from CMDQ sub system |
213 | * @value: the specified target register value |
214 | * |
215 | * Return: 0 for success; else the error code is returned |
216 | */ |
217 | int cmdq_pkt_poll(struct cmdq_pkt *pkt, u8 subsys, |
218 | u16 offset, u32 value); |
219 | |
220 | /** |
221 | * cmdq_pkt_poll_mask() - Append polling command to the CMDQ packet, ask GCE to |
222 | * execute an instruction that wait for a specified |
223 | * hardware register to check for the value w/ mask. |
224 | * All GCE hardware threads will be blocked by this |
225 | * instruction. |
226 | * @pkt: the CMDQ packet |
227 | * @subsys: the CMDQ sub system code |
228 | * @offset: register offset from CMDQ sub system |
229 | * @value: the specified target register value |
230 | * @mask: the specified target register mask |
231 | * |
232 | * Return: 0 for success; else the error code is returned |
233 | */ |
234 | int cmdq_pkt_poll_mask(struct cmdq_pkt *pkt, u8 subsys, |
235 | u16 offset, u32 value, u32 mask); |
236 | |
237 | /** |
238 | * cmdq_pkt_assign() - Append logic assign command to the CMDQ packet, ask GCE |
239 | * to execute an instruction that set a constant value into |
240 | * internal register and use as value, mask or address in |
241 | * read/write instruction. |
242 | * @pkt: the CMDQ packet |
243 | * @reg_idx: the CMDQ internal register ID |
244 | * @value: the specified value |
245 | * |
246 | * Return: 0 for success; else the error code is returned |
247 | */ |
248 | int cmdq_pkt_assign(struct cmdq_pkt *pkt, u16 reg_idx, u32 value); |
249 | |
250 | /** |
251 | * cmdq_pkt_jump() - Append jump command to the CMDQ packet, ask GCE |
252 | * to execute an instruction that change current thread PC to |
253 | * a physical address which should contains more instruction. |
254 | * @pkt: the CMDQ packet |
255 | * @addr: physical address of target instruction buffer |
256 | * |
257 | * Return: 0 for success; else the error code is returned |
258 | */ |
259 | int cmdq_pkt_jump(struct cmdq_pkt *pkt, dma_addr_t addr); |
260 | |
261 | /** |
262 | * cmdq_pkt_finalize() - Append EOC and jump command to pkt. |
263 | * @pkt: the CMDQ packet |
264 | * |
265 | * Return: 0 for success; else the error code is returned |
266 | */ |
267 | int cmdq_pkt_finalize(struct cmdq_pkt *pkt); |
268 | |
269 | /** |
270 | * cmdq_pkt_flush_async() - trigger CMDQ to asynchronously execute the CMDQ |
271 | * packet and call back at the end of done packet |
272 | * @pkt: the CMDQ packet |
273 | * |
274 | * Return: 0 for success; else the error code is returned |
275 | * |
276 | * Trigger CMDQ to asynchronously execute the CMDQ packet and call back |
277 | * at the end of done packet. Note that this is an ASYNC function. When the |
278 | * function returned, it may or may not be finished. |
279 | */ |
280 | int cmdq_pkt_flush_async(struct cmdq_pkt *pkt); |
281 | |
282 | #else /* IS_ENABLED(CONFIG_MTK_CMDQ) */ |
283 | |
284 | static inline int cmdq_dev_get_client_reg(struct device *dev, |
285 | struct cmdq_client_reg *client_reg, int idx) |
286 | { |
287 | return -ENODEV; |
288 | } |
289 | |
290 | static inline struct cmdq_client *cmdq_mbox_create(struct device *dev, int index) |
291 | { |
292 | return ERR_PTR(-EINVAL); |
293 | } |
294 | |
295 | static inline void cmdq_mbox_destroy(struct cmdq_client *client) { } |
296 | |
297 | static inline struct cmdq_pkt *cmdq_pkt_create(struct cmdq_client *client, size_t size) |
298 | { |
299 | return ERR_PTR(-EINVAL); |
300 | } |
301 | |
302 | static inline void cmdq_pkt_destroy(struct cmdq_pkt *pkt) { } |
303 | |
304 | static inline int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value) |
305 | { |
306 | return -ENOENT; |
307 | } |
308 | |
309 | static inline int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys, |
310 | u16 offset, u32 value, u32 mask) |
311 | { |
312 | return -ENOENT; |
313 | } |
314 | |
315 | static inline int cmdq_pkt_read_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, |
316 | u16 addr_low, u16 reg_idx) |
317 | { |
318 | return -ENOENT; |
319 | } |
320 | |
321 | static inline int cmdq_pkt_write_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, |
322 | u16 addr_low, u16 src_reg_idx) |
323 | { |
324 | return -ENOENT; |
325 | } |
326 | |
327 | static inline int cmdq_pkt_write_s_mask(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, |
328 | u16 addr_low, u16 src_reg_idx, u32 mask) |
329 | { |
330 | return -ENOENT; |
331 | } |
332 | |
333 | static inline int cmdq_pkt_write_s_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx, |
334 | u16 addr_low, u32 value) |
335 | { |
336 | return -ENOENT; |
337 | } |
338 | |
339 | static inline int cmdq_pkt_write_s_mask_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx, |
340 | u16 addr_low, u32 value, u32 mask) |
341 | { |
342 | return -ENOENT; |
343 | } |
344 | |
345 | static inline int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event, bool clear) |
346 | { |
347 | return -EINVAL; |
348 | } |
349 | |
350 | static inline int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event) |
351 | { |
352 | return -EINVAL; |
353 | } |
354 | |
355 | static inline int cmdq_pkt_set_event(struct cmdq_pkt *pkt, u16 event) |
356 | { |
357 | return -EINVAL; |
358 | } |
359 | |
360 | static inline int cmdq_pkt_poll(struct cmdq_pkt *pkt, u8 subsys, |
361 | u16 offset, u32 value) |
362 | { |
363 | return -EINVAL; |
364 | } |
365 | |
366 | static inline int cmdq_pkt_poll_mask(struct cmdq_pkt *pkt, u8 subsys, |
367 | u16 offset, u32 value, u32 mask) |
368 | { |
369 | return -EINVAL; |
370 | } |
371 | |
372 | static inline int cmdq_pkt_assign(struct cmdq_pkt *pkt, u16 reg_idx, u32 value) |
373 | { |
374 | return -EINVAL; |
375 | } |
376 | |
377 | static inline int cmdq_pkt_jump(struct cmdq_pkt *pkt, dma_addr_t addr) |
378 | { |
379 | return -EINVAL; |
380 | } |
381 | |
382 | static inline int cmdq_pkt_finalize(struct cmdq_pkt *pkt) |
383 | { |
384 | return -EINVAL; |
385 | } |
386 | |
387 | static inline int cmdq_pkt_flush_async(struct cmdq_pkt *pkt) |
388 | { |
389 | return -EINVAL; |
390 | } |
391 | |
392 | #endif /* IS_ENABLED(CONFIG_MTK_CMDQ) */ |
393 | |
394 | #endif /* __MTK_CMDQ_H__ */ |
395 | |