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 
cmdq_dev_get_client_reg(struct device * dev,struct cmdq_client_reg * client_reg,int idx)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 
cmdq_mbox_create(struct device * dev,int index)290 static inline struct cmdq_client *cmdq_mbox_create(struct device *dev, int index)
291 {
292 	return ERR_PTR(-EINVAL);
293 }
294 
cmdq_mbox_destroy(struct cmdq_client * client)295 static inline void cmdq_mbox_destroy(struct cmdq_client *client) { }
296 
cmdq_pkt_create(struct cmdq_client * client,size_t size)297 static inline  struct cmdq_pkt *cmdq_pkt_create(struct cmdq_client *client, size_t size)
298 {
299 	return ERR_PTR(-EINVAL);
300 }
301 
cmdq_pkt_destroy(struct cmdq_pkt * pkt)302 static inline void cmdq_pkt_destroy(struct cmdq_pkt *pkt) { }
303 
cmdq_pkt_write(struct cmdq_pkt * pkt,u8 subsys,u16 offset,u32 value)304 static inline int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value)
305 {
306 	return -ENOENT;
307 }
308 
cmdq_pkt_write_mask(struct cmdq_pkt * pkt,u8 subsys,u16 offset,u32 value,u32 mask)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 
cmdq_pkt_read_s(struct cmdq_pkt * pkt,u16 high_addr_reg_idx,u16 addr_low,u16 reg_idx)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 
cmdq_pkt_write_s(struct cmdq_pkt * pkt,u16 high_addr_reg_idx,u16 addr_low,u16 src_reg_idx)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 
cmdq_pkt_write_s_mask(struct cmdq_pkt * pkt,u16 high_addr_reg_idx,u16 addr_low,u16 src_reg_idx,u32 mask)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 
cmdq_pkt_write_s_value(struct cmdq_pkt * pkt,u8 high_addr_reg_idx,u16 addr_low,u32 value)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 
cmdq_pkt_write_s_mask_value(struct cmdq_pkt * pkt,u8 high_addr_reg_idx,u16 addr_low,u32 value,u32 mask)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 
cmdq_pkt_wfe(struct cmdq_pkt * pkt,u16 event,bool clear)345 static inline int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event, bool clear)
346 {
347 	return -EINVAL;
348 }
349 
cmdq_pkt_clear_event(struct cmdq_pkt * pkt,u16 event)350 static inline int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event)
351 {
352 	return -EINVAL;
353 }
354 
cmdq_pkt_set_event(struct cmdq_pkt * pkt,u16 event)355 static inline int cmdq_pkt_set_event(struct cmdq_pkt *pkt, u16 event)
356 {
357 	return -EINVAL;
358 }
359 
cmdq_pkt_poll(struct cmdq_pkt * pkt,u8 subsys,u16 offset,u32 value)360 static inline int cmdq_pkt_poll(struct cmdq_pkt *pkt, u8 subsys,
361 				u16 offset, u32 value)
362 {
363 	return -EINVAL;
364 }
365 
cmdq_pkt_poll_mask(struct cmdq_pkt * pkt,u8 subsys,u16 offset,u32 value,u32 mask)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 
cmdq_pkt_assign(struct cmdq_pkt * pkt,u16 reg_idx,u32 value)372 static inline int cmdq_pkt_assign(struct cmdq_pkt *pkt, u16 reg_idx, u32 value)
373 {
374 	return -EINVAL;
375 }
376 
cmdq_pkt_jump(struct cmdq_pkt * pkt,dma_addr_t addr)377 static inline int cmdq_pkt_jump(struct cmdq_pkt *pkt, dma_addr_t addr)
378 {
379 	return -EINVAL;
380 }
381 
cmdq_pkt_finalize(struct cmdq_pkt * pkt)382 static inline int cmdq_pkt_finalize(struct cmdq_pkt *pkt)
383 {
384 	return -EINVAL;
385 }
386 
cmdq_pkt_flush_async(struct cmdq_pkt * pkt)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