at master 16 kB view raw
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/* 18 * Every cmdq thread has its own SPRs (Specific Purpose Registers), 19 * so there are 4 * N (threads) SPRs in GCE that shares the same indexes below. 20 */ 21#define CMDQ_THR_SPR_IDX0 (0) 22#define CMDQ_THR_SPR_IDX1 (1) 23#define CMDQ_THR_SPR_IDX2 (2) 24#define CMDQ_THR_SPR_IDX3 (3) 25 26struct cmdq_pkt; 27 28enum cmdq_logic_op { 29 CMDQ_LOGIC_ASSIGN = 0, 30 CMDQ_LOGIC_ADD = 1, 31 CMDQ_LOGIC_SUBTRACT = 2, 32 CMDQ_LOGIC_MULTIPLY = 3, 33 CMDQ_LOGIC_XOR = 8, 34 CMDQ_LOGIC_NOT = 9, 35 CMDQ_LOGIC_OR = 10, 36 CMDQ_LOGIC_AND = 11, 37 CMDQ_LOGIC_LEFT_SHIFT = 12, 38 CMDQ_LOGIC_RIGHT_SHIFT = 13, 39 CMDQ_LOGIC_MAX, 40}; 41 42struct cmdq_operand { 43 /* register type */ 44 bool reg; 45 union { 46 /* index */ 47 u16 idx; 48 /* value */ 49 u16 value; 50 }; 51}; 52 53struct cmdq_client_reg { 54 u8 subsys; 55 u16 offset; 56 u16 size; 57}; 58 59struct cmdq_client { 60 struct mbox_client client; 61 struct mbox_chan *chan; 62}; 63 64#if IS_ENABLED(CONFIG_MTK_CMDQ) 65 66/** 67 * cmdq_dev_get_client_reg() - parse cmdq client reg from the device 68 * node of CMDQ client 69 * @dev: device of CMDQ mailbox client 70 * @client_reg: CMDQ client reg pointer 71 * @idx: the index of desired reg 72 * 73 * Return: 0 for success; else the error code is returned 74 * 75 * Help CMDQ client parsing the cmdq client reg 76 * from the device node of CMDQ client. 77 */ 78int cmdq_dev_get_client_reg(struct device *dev, 79 struct cmdq_client_reg *client_reg, int idx); 80 81/** 82 * cmdq_mbox_create() - create CMDQ mailbox client and channel 83 * @dev: device of CMDQ mailbox client 84 * @index: index of CMDQ mailbox channel 85 * 86 * Return: CMDQ mailbox client pointer 87 */ 88struct cmdq_client *cmdq_mbox_create(struct device *dev, int index); 89 90/** 91 * cmdq_mbox_destroy() - destroy CMDQ mailbox client and channel 92 * @client: the CMDQ mailbox client 93 */ 94void cmdq_mbox_destroy(struct cmdq_client *client); 95 96/** 97 * cmdq_pkt_create() - create a CMDQ packet 98 * @client: the CMDQ mailbox client 99 * @pkt: the CMDQ packet 100 * @size: required CMDQ buffer size 101 * 102 * Return: 0 for success; else the error code is returned 103 */ 104int cmdq_pkt_create(struct cmdq_client *client, struct cmdq_pkt *pkt, size_t size); 105 106/** 107 * cmdq_pkt_destroy() - destroy the CMDQ packet 108 * @client: the CMDQ mailbox client 109 * @pkt: the CMDQ packet 110 */ 111void cmdq_pkt_destroy(struct cmdq_client *client, struct cmdq_pkt *pkt); 112 113/** 114 * cmdq_pkt_write() - append write command to the CMDQ packet 115 * @pkt: the CMDQ packet 116 * @subsys: the CMDQ sub system code 117 * @offset: register offset from CMDQ sub system 118 * @value: the specified target register value 119 * 120 * Return: 0 for success; else the error code is returned 121 */ 122int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value); 123 124/** 125 * cmdq_pkt_write_mask() - append write command with mask to the CMDQ packet 126 * @pkt: the CMDQ packet 127 * @subsys: the CMDQ sub system code 128 * @offset: register offset from CMDQ sub system 129 * @value: the specified target register value 130 * @mask: the specified target register mask 131 * 132 * Return: 0 for success; else the error code is returned 133 */ 134int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys, 135 u16 offset, u32 value, u32 mask); 136 137/* 138 * cmdq_pkt_read_s() - append read_s command to the CMDQ packet 139 * @pkt: the CMDQ packet 140 * @high_addr_reg_idx: internal register ID which contains high address of pa 141 * @addr_low: low address of pa 142 * @reg_idx: the CMDQ internal register ID to cache read data 143 * 144 * Return: 0 for success; else the error code is returned 145 */ 146int cmdq_pkt_read_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, u16 addr_low, 147 u16 reg_idx); 148 149/** 150 * cmdq_pkt_write_s() - append write_s command to the CMDQ packet 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 * @src_reg_idx: the CMDQ internal register ID which cache source value 155 * 156 * Return: 0 for success; else the error code is returned 157 * 158 * Support write value to physical address without subsys. Use CMDQ_ADDR_HIGH() 159 * to get high address and call cmdq_pkt_assign() to assign value into internal 160 * reg. Also use CMDQ_ADDR_LOW() to get low address for addr_low parameter when 161 * call to this function. 162 */ 163int cmdq_pkt_write_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, 164 u16 addr_low, u16 src_reg_idx); 165 166/** 167 * cmdq_pkt_write_s_mask() - append write_s with mask command to the CMDQ packet 168 * @pkt: the CMDQ packet 169 * @high_addr_reg_idx: internal register ID which contains high address of pa 170 * @addr_low: low address of pa 171 * @src_reg_idx: the CMDQ internal register ID which cache source value 172 * @mask: the specified target address mask, use U32_MAX if no need 173 * 174 * Return: 0 for success; else the error code is returned 175 * 176 * Support write value to physical address without subsys. Use CMDQ_ADDR_HIGH() 177 * to get high address and call cmdq_pkt_assign() to assign value into internal 178 * reg. Also use CMDQ_ADDR_LOW() to get low address for addr_low parameter when 179 * call to this function. 180 */ 181int cmdq_pkt_write_s_mask(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, 182 u16 addr_low, u16 src_reg_idx, u32 mask); 183 184/** 185 * cmdq_pkt_write_s_value() - append write_s command to the CMDQ packet which 186 * write value to a physical address 187 * @pkt: the CMDQ packet 188 * @high_addr_reg_idx: internal register ID which contains high address of pa 189 * @addr_low: low address of pa 190 * @value: the specified target value 191 * 192 * Return: 0 for success; else the error code is returned 193 */ 194int cmdq_pkt_write_s_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx, 195 u16 addr_low, u32 value); 196 197/** 198 * cmdq_pkt_write_s_mask_value() - append write_s command with mask to the CMDQ 199 * packet which write value to a physical 200 * address 201 * @pkt: the CMDQ packet 202 * @high_addr_reg_idx: internal register ID which contains high address of pa 203 * @addr_low: low address of pa 204 * @value: the specified target value 205 * @mask: the specified target mask 206 * 207 * Return: 0 for success; else the error code is returned 208 */ 209int cmdq_pkt_write_s_mask_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx, 210 u16 addr_low, u32 value, u32 mask); 211 212/** 213 * cmdq_pkt_mem_move() - append memory move command to the CMDQ packet 214 * @pkt: the CMDQ packet 215 * @src_addr: source address 216 * @dst_addr: destination address 217 * 218 * Appends a CMDQ command to copy the value found in `src_addr` to `dst_addr`. 219 * 220 * Return: 0 for success; else the error code is returned 221 */ 222int cmdq_pkt_mem_move(struct cmdq_pkt *pkt, dma_addr_t src_addr, dma_addr_t dst_addr); 223 224/** 225 * cmdq_pkt_wfe() - append wait for event command to the CMDQ packet 226 * @pkt: the CMDQ packet 227 * @event: the desired event type to wait 228 * @clear: clear event or not after event arrive 229 * 230 * Return: 0 for success; else the error code is returned 231 */ 232int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event, bool clear); 233 234/** 235 * cmdq_pkt_acquire_event() - append acquire event command to the CMDQ packet 236 * @pkt: the CMDQ packet 237 * @event: the desired event to be acquired 238 * 239 * User can use cmdq_pkt_acquire_event() as `mutex_lock` and cmdq_pkt_clear_event() 240 * as `mutex_unlock` to protect some `critical section` instructions between them. 241 * cmdq_pkt_acquire_event() would wait for event to be cleared. 242 * After event is cleared by cmdq_pkt_clear_event in other GCE threads, 243 * cmdq_pkt_acquire_event() would set event and keep executing next instruction. 244 * 245 * Return: 0 for success; else the error code is returned 246 */ 247int cmdq_pkt_acquire_event(struct cmdq_pkt *pkt, u16 event); 248 249/** 250 * cmdq_pkt_clear_event() - append clear event command to the CMDQ packet 251 * @pkt: the CMDQ packet 252 * @event: the desired event to be cleared 253 * 254 * Return: 0 for success; else the error code is returned 255 */ 256int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event); 257 258/** 259 * cmdq_pkt_set_event() - append set event command to the CMDQ packet 260 * @pkt: the CMDQ packet 261 * @event: the desired event to be set 262 * 263 * Return: 0 for success; else the error code is returned 264 */ 265int cmdq_pkt_set_event(struct cmdq_pkt *pkt, u16 event); 266 267/** 268 * cmdq_pkt_poll() - Append polling command to the CMDQ packet, ask GCE to 269 * execute an instruction that wait for a specified 270 * hardware register to check for the value w/o mask. 271 * All GCE hardware threads will be blocked by this 272 * instruction. 273 * @pkt: the CMDQ packet 274 * @subsys: the CMDQ sub system code 275 * @offset: register offset from CMDQ sub system 276 * @value: the specified target register value 277 * 278 * Return: 0 for success; else the error code is returned 279 */ 280int cmdq_pkt_poll(struct cmdq_pkt *pkt, u8 subsys, 281 u16 offset, u32 value); 282 283/** 284 * cmdq_pkt_poll_mask() - Append polling command to the CMDQ packet, ask GCE to 285 * execute an instruction that wait for a specified 286 * hardware register to check for the value w/ mask. 287 * All GCE hardware threads will be blocked by this 288 * instruction. 289 * @pkt: the CMDQ packet 290 * @subsys: the CMDQ sub system code 291 * @offset: register offset from CMDQ sub system 292 * @value: the specified target register value 293 * @mask: the specified target register mask 294 * 295 * Return: 0 for success; else the error code is returned 296 */ 297int cmdq_pkt_poll_mask(struct cmdq_pkt *pkt, u8 subsys, 298 u16 offset, u32 value, u32 mask); 299 300/** 301 * cmdq_pkt_logic_command() - Append logic command to the CMDQ packet, ask GCE to 302 * execute an instruction that store the result of logic operation 303 * with left and right operand into result_reg_idx. 304 * @pkt: the CMDQ packet 305 * @result_reg_idx: SPR index that store operation result of left_operand and right_operand 306 * @left_operand: left operand 307 * @s_op: the logic operator enum 308 * @right_operand: right operand 309 * 310 * Return: 0 for success; else the error code is returned 311 */ 312int cmdq_pkt_logic_command(struct cmdq_pkt *pkt, u16 result_reg_idx, 313 struct cmdq_operand *left_operand, 314 enum cmdq_logic_op s_op, 315 struct cmdq_operand *right_operand); 316 317/** 318 * cmdq_pkt_assign() - Append logic assign command to the CMDQ packet, ask GCE 319 * to execute an instruction that set a constant value into 320 * internal register and use as value, mask or address in 321 * read/write instruction. 322 * @pkt: the CMDQ packet 323 * @reg_idx: the CMDQ internal register ID 324 * @value: the specified value 325 * 326 * Return: 0 for success; else the error code is returned 327 */ 328int cmdq_pkt_assign(struct cmdq_pkt *pkt, u16 reg_idx, u32 value); 329 330/** 331 * cmdq_pkt_poll_addr() - Append blocking POLL command to CMDQ packet 332 * @pkt: the CMDQ packet 333 * @addr: the hardware register address 334 * @value: the specified target register value 335 * @mask: the specified target register mask 336 * 337 * Appends a polling (POLL) command to the CMDQ packet and asks the GCE 338 * to execute an instruction that checks for the specified `value` (with 339 * or without `mask`) to appear in the specified hardware register `addr`. 340 * All GCE threads will be blocked by this instruction. 341 * 342 * Return: 0 for success or negative error code 343 */ 344int cmdq_pkt_poll_addr(struct cmdq_pkt *pkt, dma_addr_t addr, u32 value, u32 mask); 345 346/** 347 * cmdq_pkt_jump_abs() - Append jump command to the CMDQ packet, ask GCE 348 * to execute an instruction that change current thread 349 * PC to a absolute physical address which should 350 * contains more instruction. 351 * @pkt: the CMDQ packet 352 * @addr: absolute physical address of target instruction buffer 353 * @shift_pa: shift bits of physical address in CMDQ instruction. This value 354 * is got by cmdq_get_shift_pa(). 355 * 356 * Return: 0 for success; else the error code is returned 357 */ 358int cmdq_pkt_jump_abs(struct cmdq_pkt *pkt, dma_addr_t addr, u8 shift_pa); 359 360/* This wrapper has to be removed after all users migrated to jump_abs */ 361static inline int cmdq_pkt_jump(struct cmdq_pkt *pkt, dma_addr_t addr, u8 shift_pa) 362{ 363 return cmdq_pkt_jump_abs(pkt, addr, shift_pa); 364} 365 366/** 367 * cmdq_pkt_jump_rel() - Append jump command to the CMDQ packet, ask GCE 368 * to execute an instruction that change current thread 369 * PC to a physical address with relative offset. The 370 * target address should contains more instruction. 371 * @pkt: the CMDQ packet 372 * @offset: relative offset of target instruction buffer from current PC. 373 * @shift_pa: shift bits of physical address in CMDQ instruction. This value 374 * is got by cmdq_get_shift_pa(). 375 * 376 * Return: 0 for success; else the error code is returned 377 */ 378int cmdq_pkt_jump_rel(struct cmdq_pkt *pkt, s32 offset, u8 shift_pa); 379 380/** 381 * cmdq_pkt_eoc() - Append EOC and ask GCE to generate an IRQ at end of execution 382 * @pkt: The CMDQ packet 383 * 384 * Appends an End Of Code (EOC) command to the CMDQ packet and asks the GCE 385 * to generate an interrupt at the end of the execution of all commands in 386 * the pipeline. 387 * The EOC command is usually appended to the end of the pipeline to notify 388 * that all commands are done. 389 * 390 * Return: 0 for success or negative error number 391 */ 392int cmdq_pkt_eoc(struct cmdq_pkt *pkt); 393 394#else /* IS_ENABLED(CONFIG_MTK_CMDQ) */ 395 396static inline int cmdq_dev_get_client_reg(struct device *dev, 397 struct cmdq_client_reg *client_reg, int idx) 398{ 399 return -ENODEV; 400} 401 402static inline struct cmdq_client *cmdq_mbox_create(struct device *dev, int index) 403{ 404 return ERR_PTR(-EINVAL); 405} 406 407static inline void cmdq_mbox_destroy(struct cmdq_client *client) { } 408 409static inline int cmdq_pkt_create(struct cmdq_client *client, struct cmdq_pkt *pkt, size_t size) 410{ 411 return -EINVAL; 412} 413 414static inline void cmdq_pkt_destroy(struct cmdq_client *client, struct cmdq_pkt *pkt) { } 415 416static inline int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value) 417{ 418 return -ENOENT; 419} 420 421static inline int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys, 422 u16 offset, u32 value, u32 mask) 423{ 424 return -ENOENT; 425} 426 427static inline int cmdq_pkt_read_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, 428 u16 addr_low, u16 reg_idx) 429{ 430 return -ENOENT; 431} 432 433static inline int cmdq_pkt_write_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, 434 u16 addr_low, u16 src_reg_idx) 435{ 436 return -ENOENT; 437} 438 439static inline int cmdq_pkt_write_s_mask(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, 440 u16 addr_low, u16 src_reg_idx, u32 mask) 441{ 442 return -ENOENT; 443} 444 445static inline int cmdq_pkt_write_s_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx, 446 u16 addr_low, u32 value) 447{ 448 return -ENOENT; 449} 450 451static inline int cmdq_pkt_write_s_mask_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx, 452 u16 addr_low, u32 value, u32 mask) 453{ 454 return -ENOENT; 455} 456 457static inline int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event, bool clear) 458{ 459 return -EINVAL; 460} 461 462static inline int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event) 463{ 464 return -EINVAL; 465} 466 467static inline int cmdq_pkt_set_event(struct cmdq_pkt *pkt, u16 event) 468{ 469 return -EINVAL; 470} 471 472static inline int cmdq_pkt_poll(struct cmdq_pkt *pkt, u8 subsys, 473 u16 offset, u32 value) 474{ 475 return -EINVAL; 476} 477 478static inline int cmdq_pkt_poll_mask(struct cmdq_pkt *pkt, u8 subsys, 479 u16 offset, u32 value, u32 mask) 480{ 481 return -EINVAL; 482} 483 484static inline int cmdq_pkt_assign(struct cmdq_pkt *pkt, u16 reg_idx, u32 value) 485{ 486 return -EINVAL; 487} 488 489static inline int cmdq_pkt_poll_addr(struct cmdq_pkt *pkt, dma_addr_t addr, u32 value, u32 mask) 490{ 491 return -EINVAL; 492} 493 494static inline int cmdq_pkt_jump_abs(struct cmdq_pkt *pkt, dma_addr_t addr, u8 shift_pa) 495{ 496 return -EINVAL; 497} 498 499static inline int cmdq_pkt_jump(struct cmdq_pkt *pkt, dma_addr_t addr, u8 shift_pa) 500{ 501 return -EINVAL; 502} 503 504static inline int cmdq_pkt_jump_rel(struct cmdq_pkt *pkt, s32 offset, u8 shift_pa) 505{ 506 return -EINVAL; 507} 508 509static inline int cmdq_pkt_eoc(struct cmdq_pkt *pkt) 510{ 511 return -EINVAL; 512} 513 514#endif /* IS_ENABLED(CONFIG_MTK_CMDQ) */ 515 516#endif /* __MTK_CMDQ_H__ */