Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

soc: mtk-cmdq: Add cmdq_pkt_logic_command to support math operation

Add cmdq_pkt_logic_command to support math operation.

cmdq_pkt_logic_command can append logic command to the CMDQ packet,
ask GCE to execute a arithmetic calculate instruction,
such as add, subtract, multiply, AND, OR and NOT, etc.

Note that all arithmetic instructions are unsigned calculations.
If there are any overflows, GCE will sent the invalid IRQ to notify
CMDQ driver.

Signed-off-by: Jason-JH.Lin <jason-jh.lin@mediatek.com>
Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
Link: https://lore.kernel.org/r/20240625083957.3540-1-jason-jh.lin@mediatek.com
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>

authored by

Jason-JH.Lin and committed by
AngeloGioacchino Del Regno
58de63dd 7cc069d9

+76
+34
drivers/soc/mediatek/mtk-cmdq-helper.c
··· 15 15 /* dedicate the last GPR_R15 to assign the register address to be poll */ 16 16 #define CMDQ_POLL_ADDR_GPR (15) 17 17 #define CMDQ_EOC_IRQ_EN BIT(0) 18 + #define CMDQ_IMMEDIATE_VALUE 0 18 19 #define CMDQ_REG_TYPE 1 19 20 #define CMDQ_JUMP_RELATIVE 0 20 21 #define CMDQ_JUMP_ABSOLUTE 1 ··· 45 44 }; 46 45 u8 op; 47 46 }; 47 + 48 + static inline u8 cmdq_operand_get_type(struct cmdq_operand *op) 49 + { 50 + return op->reg ? CMDQ_REG_TYPE : CMDQ_IMMEDIATE_VALUE; 51 + } 52 + 53 + static inline u16 cmdq_operand_get_idx_value(struct cmdq_operand *op) 54 + { 55 + return op->reg ? op->idx : op->value; 56 + } 48 57 49 58 int cmdq_dev_get_client_reg(struct device *dev, 50 59 struct cmdq_client_reg *client_reg, int idx) ··· 471 460 return 0; 472 461 } 473 462 EXPORT_SYMBOL(cmdq_pkt_poll_addr); 463 + 464 + int cmdq_pkt_logic_command(struct cmdq_pkt *pkt, u16 result_reg_idx, 465 + struct cmdq_operand *left_operand, 466 + enum cmdq_logic_op s_op, 467 + struct cmdq_operand *right_operand) 468 + { 469 + struct cmdq_instruction inst = { {0} }; 470 + 471 + if (!left_operand || !right_operand || s_op >= CMDQ_LOGIC_MAX) 472 + return -EINVAL; 473 + 474 + inst.op = CMDQ_CODE_LOGIC; 475 + inst.dst_t = CMDQ_REG_TYPE; 476 + inst.src_t = cmdq_operand_get_type(left_operand); 477 + inst.arg_c_t = cmdq_operand_get_type(right_operand); 478 + inst.sop = s_op; 479 + inst.reg_dst = result_reg_idx; 480 + inst.src_reg = cmdq_operand_get_idx_value(left_operand); 481 + inst.arg_c = cmdq_operand_get_idx_value(right_operand); 482 + 483 + return cmdq_pkt_append_command(pkt, inst); 484 + } 485 + EXPORT_SYMBOL(cmdq_pkt_logic_command); 474 486 475 487 int cmdq_pkt_assign(struct cmdq_pkt *pkt, u16 reg_idx, u32 value) 476 488 {
+42
include/linux/soc/mediatek/mtk-cmdq.h
··· 25 25 26 26 struct cmdq_pkt; 27 27 28 + enum 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 + 42 + struct cmdq_operand { 43 + /* register type */ 44 + bool reg; 45 + union { 46 + /* index */ 47 + u16 idx; 48 + /* value */ 49 + u16 value; 50 + }; 51 + }; 52 + 28 53 struct cmdq_client_reg { 29 54 u8 subsys; 30 55 u16 offset; ··· 296 271 */ 297 272 int cmdq_pkt_poll_mask(struct cmdq_pkt *pkt, u8 subsys, 298 273 u16 offset, u32 value, u32 mask); 274 + 275 + /** 276 + * cmdq_pkt_logic_command() - Append logic command to the CMDQ packet, ask GCE to 277 + * execute an instruction that store the result of logic operation 278 + * with left and right operand into result_reg_idx. 279 + * @pkt: the CMDQ packet 280 + * @result_reg_idx: SPR index that store operation result of left_operand and right_operand 281 + * @left_operand: left operand 282 + * @s_op: the logic operator enum 283 + * @right_operand: right operand 284 + * 285 + * Return: 0 for success; else the error code is returned 286 + */ 287 + int cmdq_pkt_logic_command(struct cmdq_pkt *pkt, u16 result_reg_idx, 288 + struct cmdq_operand *left_operand, 289 + enum cmdq_logic_op s_op, 290 + struct cmdq_operand *right_operand); 299 291 300 292 /** 301 293 * cmdq_pkt_assign() - Append logic assign command to the CMDQ packet, ask GCE