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

Merge tag 'mtk-soc-for-v6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/mediatek/linux into soc/drivers

MediaTek driver updates for v6.10

This adds a much needed cleanup for the MediaTek CMDQ helper driver and
also some more helper functions which will be used in drivers using the
MediaTek Global Command Engine (GCE) HW.

Also adds support for MT8188's VPPSYS mutex for MDP3 support, a new SoC
in the mtk-socinfo driver and changes the marketing name for the pre
existing MT8188 SoC.

* tag 'mtk-soc-for-v6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/mediatek/linux:
soc: mediatek: mtk-socinfo: Correct the marketing name for MT8188GV
soc: mediatek: mtk-socinfo: Add entry for MT8395AV/ZA Genio 1200
soc: mediatek: mtk-mutex: Add support for MT8188 VPPSYS
soc: mediatek: socinfo: Advertise about unknown MediaTek SoC
soc: mediatek: cmdq: Don't log an error when gce-client-reg is not found
soc: mediatek: mtk-cmdq: Add cmdq_pkt_acquire_event() function
soc: mediatek: mtk-cmdq: Add cmdq_pkt_poll_addr() function
soc: mediatek: mtk-cmdq: Add cmdq_pkt_mem_move() function
soc: mediatek: mtk-cmdq: Add specific purpose register definitions for GCE
soc: mediatek: cmdq: Refine cmdq_pkt_create() and cmdq_pkt_destroy()
soc: mediatek: cmdq: Remove cmdq_pkt_flush_async() helper function
soc: mediatek: cmdq: Add cmdq_pkt_eoc() helper function
soc: mediatek: cmdq: Add cmdq_pkt_jump_rel() helper function
soc: mediatek: cmdq: Rename cmdq_pkt_jump() to cmdq_pkt_jump_abs()
soc: mediatek: cmdq: Add parameter shift_pa to cmdq_pkt_jump()
soc: mediatek: cmdq: Fix typo of CMDQ_JUMP_RELATIVE

Link: https://lore.kernel.org/r/20240429140245.238210-2-angelogioacchino.delregno@collabora.com
Signed-off-by: Arnd Bergmann <arnd@arndb.de>

+299 -72
+124 -39
drivers/soc/mediatek/mtk-cmdq-helper.c
··· 12 12 13 13 #define CMDQ_WRITE_ENABLE_MASK BIT(0) 14 14 #define CMDQ_POLL_ENABLE_MASK BIT(0) 15 + /* dedicate the last GPR_R15 to assign the register address to be poll */ 16 + #define CMDQ_POLL_ADDR_GPR (15) 15 17 #define CMDQ_EOC_IRQ_EN BIT(0) 16 18 #define CMDQ_REG_TYPE 1 17 - #define CMDQ_JUMP_RELATIVE 1 19 + #define CMDQ_JUMP_RELATIVE 0 20 + #define CMDQ_JUMP_ABSOLUTE 1 18 21 19 22 struct cmdq_instruction { 20 23 union { ··· 58 55 "mediatek,gce-client-reg", 59 56 3, idx, &spec); 60 57 if (err < 0) { 61 - dev_err(dev, 58 + dev_warn(dev, 62 59 "error %d can't parse gce-client-reg property (%d)", 63 60 err, idx); 64 61 ··· 108 105 } 109 106 EXPORT_SYMBOL(cmdq_mbox_destroy); 110 107 111 - struct cmdq_pkt *cmdq_pkt_create(struct cmdq_client *client, size_t size) 108 + int cmdq_pkt_create(struct cmdq_client *client, struct cmdq_pkt *pkt, size_t size) 112 109 { 113 - struct cmdq_pkt *pkt; 114 110 struct device *dev; 115 111 dma_addr_t dma_addr; 116 112 117 - pkt = kzalloc(sizeof(*pkt), GFP_KERNEL); 118 - if (!pkt) 119 - return ERR_PTR(-ENOMEM); 120 113 pkt->va_base = kzalloc(size, GFP_KERNEL); 121 - if (!pkt->va_base) { 122 - kfree(pkt); 123 - return ERR_PTR(-ENOMEM); 124 - } 114 + if (!pkt->va_base) 115 + return -ENOMEM; 116 + 125 117 pkt->buf_size = size; 126 - pkt->cl = (void *)client; 127 118 128 119 dev = client->chan->mbox->dev; 129 120 dma_addr = dma_map_single(dev, pkt->va_base, pkt->buf_size, ··· 125 128 if (dma_mapping_error(dev, dma_addr)) { 126 129 dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size); 127 130 kfree(pkt->va_base); 128 - kfree(pkt); 129 - return ERR_PTR(-ENOMEM); 131 + return -ENOMEM; 130 132 } 131 133 132 134 pkt->pa_base = dma_addr; 133 135 134 - return pkt; 136 + return 0; 135 137 } 136 138 EXPORT_SYMBOL(cmdq_pkt_create); 137 139 138 - void cmdq_pkt_destroy(struct cmdq_pkt *pkt) 140 + void cmdq_pkt_destroy(struct cmdq_client *client, struct cmdq_pkt *pkt) 139 141 { 140 - struct cmdq_client *client = (struct cmdq_client *)pkt->cl; 141 - 142 142 dma_unmap_single(client->chan->mbox->dev, pkt->pa_base, pkt->buf_size, 143 143 DMA_TO_DEVICE); 144 144 kfree(pkt->va_base); 145 - kfree(pkt); 146 145 } 147 146 EXPORT_SYMBOL(cmdq_pkt_destroy); 148 147 ··· 292 299 } 293 300 EXPORT_SYMBOL(cmdq_pkt_write_s_mask_value); 294 301 302 + int cmdq_pkt_mem_move(struct cmdq_pkt *pkt, dma_addr_t src_addr, dma_addr_t dst_addr) 303 + { 304 + const u16 high_addr_reg_idx = CMDQ_THR_SPR_IDX0; 305 + const u16 value_reg_idx = CMDQ_THR_SPR_IDX1; 306 + int ret; 307 + 308 + /* read the value of src_addr into high_addr_reg_idx */ 309 + ret = cmdq_pkt_assign(pkt, high_addr_reg_idx, CMDQ_ADDR_HIGH(src_addr)); 310 + if (ret < 0) 311 + return ret; 312 + ret = cmdq_pkt_read_s(pkt, high_addr_reg_idx, CMDQ_ADDR_LOW(src_addr), value_reg_idx); 313 + if (ret < 0) 314 + return ret; 315 + 316 + /* write the value of value_reg_idx into dst_addr */ 317 + ret = cmdq_pkt_assign(pkt, high_addr_reg_idx, CMDQ_ADDR_HIGH(dst_addr)); 318 + if (ret < 0) 319 + return ret; 320 + ret = cmdq_pkt_write_s(pkt, high_addr_reg_idx, CMDQ_ADDR_LOW(dst_addr), value_reg_idx); 321 + if (ret < 0) 322 + return ret; 323 + 324 + return 0; 325 + } 326 + EXPORT_SYMBOL(cmdq_pkt_mem_move); 327 + 295 328 int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event, bool clear) 296 329 { 297 330 struct cmdq_instruction inst = { {0} }; ··· 333 314 return cmdq_pkt_append_command(pkt, inst); 334 315 } 335 316 EXPORT_SYMBOL(cmdq_pkt_wfe); 317 + 318 + int cmdq_pkt_acquire_event(struct cmdq_pkt *pkt, u16 event) 319 + { 320 + struct cmdq_instruction inst = {}; 321 + 322 + if (event >= CMDQ_MAX_EVENT) 323 + return -EINVAL; 324 + 325 + inst.op = CMDQ_CODE_WFE; 326 + inst.value = CMDQ_WFE_UPDATE | CMDQ_WFE_UPDATE_VALUE | CMDQ_WFE_WAIT; 327 + inst.event = event; 328 + 329 + return cmdq_pkt_append_command(pkt, inst); 330 + } 331 + EXPORT_SYMBOL(cmdq_pkt_acquire_event); 336 332 337 333 int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event) 338 334 { ··· 414 380 } 415 381 EXPORT_SYMBOL(cmdq_pkt_poll_mask); 416 382 383 + int cmdq_pkt_poll_addr(struct cmdq_pkt *pkt, dma_addr_t addr, u32 value, u32 mask) 384 + { 385 + struct cmdq_instruction inst = { {0} }; 386 + u8 use_mask = 0; 387 + int ret; 388 + 389 + /* 390 + * Append an MASK instruction to set the mask for following POLL instruction 391 + * which enables use_mask bit. 392 + */ 393 + if (mask != GENMASK(31, 0)) { 394 + inst.op = CMDQ_CODE_MASK; 395 + inst.mask = ~mask; 396 + ret = cmdq_pkt_append_command(pkt, inst); 397 + if (ret < 0) 398 + return ret; 399 + use_mask = CMDQ_POLL_ENABLE_MASK; 400 + } 401 + 402 + /* 403 + * POLL is an legacy operation in GCE and it does not support SPR and CMDQ_CODE_LOGIC, 404 + * so it can not use cmdq_pkt_assign to keep polling register address to SPR. 405 + * If user wants to poll a register address which doesn't have a subsys id, 406 + * user needs to use GPR and CMDQ_CODE_MASK to move polling register address to GPR. 407 + */ 408 + inst.op = CMDQ_CODE_MASK; 409 + inst.dst_t = CMDQ_REG_TYPE; 410 + inst.sop = CMDQ_POLL_ADDR_GPR; 411 + inst.value = addr; 412 + ret = cmdq_pkt_append_command(pkt, inst); 413 + if (ret < 0) 414 + return ret; 415 + 416 + /* Append POLL instruction to poll the register address assign to GPR previously. */ 417 + inst.op = CMDQ_CODE_POLL; 418 + inst.dst_t = CMDQ_REG_TYPE; 419 + inst.sop = CMDQ_POLL_ADDR_GPR; 420 + inst.offset = use_mask; 421 + inst.value = value; 422 + ret = cmdq_pkt_append_command(pkt, inst); 423 + if (ret < 0) 424 + return ret; 425 + 426 + return 0; 427 + } 428 + EXPORT_SYMBOL(cmdq_pkt_poll_addr); 429 + 417 430 int cmdq_pkt_assign(struct cmdq_pkt *pkt, u16 reg_idx, u32 value) 418 431 { 419 432 struct cmdq_instruction inst = {}; ··· 473 392 } 474 393 EXPORT_SYMBOL(cmdq_pkt_assign); 475 394 476 - int cmdq_pkt_jump(struct cmdq_pkt *pkt, dma_addr_t addr) 395 + int cmdq_pkt_jump_abs(struct cmdq_pkt *pkt, dma_addr_t addr, u8 shift_pa) 477 396 { 478 397 struct cmdq_instruction inst = {}; 479 398 480 399 inst.op = CMDQ_CODE_JUMP; 481 - inst.offset = CMDQ_JUMP_RELATIVE; 482 - inst.value = addr >> 483 - cmdq_get_shift_pa(((struct cmdq_client *)pkt->cl)->chan); 400 + inst.offset = CMDQ_JUMP_ABSOLUTE; 401 + inst.value = addr >> shift_pa; 484 402 return cmdq_pkt_append_command(pkt, inst); 485 403 } 486 - EXPORT_SYMBOL(cmdq_pkt_jump); 404 + EXPORT_SYMBOL(cmdq_pkt_jump_abs); 405 + 406 + int cmdq_pkt_jump_rel(struct cmdq_pkt *pkt, s32 offset, u8 shift_pa) 407 + { 408 + struct cmdq_instruction inst = { {0} }; 409 + 410 + inst.op = CMDQ_CODE_JUMP; 411 + inst.value = (u32)offset >> shift_pa; 412 + return cmdq_pkt_append_command(pkt, inst); 413 + } 414 + EXPORT_SYMBOL(cmdq_pkt_jump_rel); 415 + 416 + int cmdq_pkt_eoc(struct cmdq_pkt *pkt) 417 + { 418 + struct cmdq_instruction inst = { {0} }; 419 + 420 + inst.op = CMDQ_CODE_EOC; 421 + inst.value = CMDQ_EOC_IRQ_EN; 422 + return cmdq_pkt_append_command(pkt, inst); 423 + } 424 + EXPORT_SYMBOL(cmdq_pkt_eoc); 487 425 488 426 int cmdq_pkt_finalize(struct cmdq_pkt *pkt) 489 427 { ··· 525 425 return err; 526 426 } 527 427 EXPORT_SYMBOL(cmdq_pkt_finalize); 528 - 529 - int cmdq_pkt_flush_async(struct cmdq_pkt *pkt) 530 - { 531 - int err; 532 - struct cmdq_client *client = (struct cmdq_client *)pkt->cl; 533 - 534 - err = mbox_send_message(client->chan, pkt); 535 - if (err < 0) 536 - return err; 537 - /* We can send next packet immediately, so just call txdone. */ 538 - mbox_client_txdone(client->chan, 0); 539 - 540 - return 0; 541 - } 542 - EXPORT_SYMBOL(cmdq_pkt_flush_async); 543 428 544 429 MODULE_LICENSE("GPL v2");
+41
drivers/soc/mediatek/mtk-mutex.c
··· 496 496 [DDP_COMPONENT_MERGE5] = MT8188_MUTEX_MOD_DISP1_VPP_MERGE4, 497 497 }; 498 498 499 + static const unsigned int mt8188_mdp_mutex_table_mod[MUTEX_MOD_IDX_MAX] = { 500 + [MUTEX_MOD_IDX_MDP_RDMA0] = MT8195_MUTEX_MOD_MDP_RDMA0, 501 + [MUTEX_MOD_IDX_MDP_RDMA2] = MT8195_MUTEX_MOD_MDP_RDMA2, 502 + [MUTEX_MOD_IDX_MDP_RDMA3] = MT8195_MUTEX_MOD_MDP_RDMA3, 503 + [MUTEX_MOD_IDX_MDP_FG0] = MT8195_MUTEX_MOD_MDP_FG0, 504 + [MUTEX_MOD_IDX_MDP_FG2] = MT8195_MUTEX_MOD_MDP_FG2, 505 + [MUTEX_MOD_IDX_MDP_FG3] = MT8195_MUTEX_MOD_MDP_FG3, 506 + [MUTEX_MOD_IDX_MDP_HDR0] = MT8195_MUTEX_MOD_MDP_HDR0, 507 + [MUTEX_MOD_IDX_MDP_HDR2] = MT8195_MUTEX_MOD_MDP_HDR2, 508 + [MUTEX_MOD_IDX_MDP_HDR3] = MT8195_MUTEX_MOD_MDP_HDR3, 509 + [MUTEX_MOD_IDX_MDP_AAL0] = MT8195_MUTEX_MOD_MDP_AAL0, 510 + [MUTEX_MOD_IDX_MDP_AAL2] = MT8195_MUTEX_MOD_MDP_AAL2, 511 + [MUTEX_MOD_IDX_MDP_AAL3] = MT8195_MUTEX_MOD_MDP_AAL3, 512 + [MUTEX_MOD_IDX_MDP_RSZ0] = MT8195_MUTEX_MOD_MDP_RSZ0, 513 + [MUTEX_MOD_IDX_MDP_RSZ2] = MT8195_MUTEX_MOD_MDP_RSZ2, 514 + [MUTEX_MOD_IDX_MDP_RSZ3] = MT8195_MUTEX_MOD_MDP_RSZ3, 515 + [MUTEX_MOD_IDX_MDP_MERGE2] = MT8195_MUTEX_MOD_MDP_MERGE2, 516 + [MUTEX_MOD_IDX_MDP_MERGE3] = MT8195_MUTEX_MOD_MDP_MERGE3, 517 + [MUTEX_MOD_IDX_MDP_TDSHP0] = MT8195_MUTEX_MOD_MDP_TDSHP0, 518 + [MUTEX_MOD_IDX_MDP_TDSHP2] = MT8195_MUTEX_MOD_MDP_TDSHP2, 519 + [MUTEX_MOD_IDX_MDP_TDSHP3] = MT8195_MUTEX_MOD_MDP_TDSHP3, 520 + [MUTEX_MOD_IDX_MDP_COLOR0] = MT8195_MUTEX_MOD_MDP_COLOR0, 521 + [MUTEX_MOD_IDX_MDP_COLOR2] = MT8195_MUTEX_MOD_MDP_COLOR2, 522 + [MUTEX_MOD_IDX_MDP_COLOR3] = MT8195_MUTEX_MOD_MDP_COLOR3, 523 + [MUTEX_MOD_IDX_MDP_OVL0] = MT8195_MUTEX_MOD_MDP_OVL0, 524 + [MUTEX_MOD_IDX_MDP_PAD0] = MT8195_MUTEX_MOD_MDP_PAD0, 525 + [MUTEX_MOD_IDX_MDP_PAD2] = MT8195_MUTEX_MOD_MDP_PAD2, 526 + [MUTEX_MOD_IDX_MDP_PAD3] = MT8195_MUTEX_MOD_MDP_PAD3, 527 + [MUTEX_MOD_IDX_MDP_WROT0] = MT8195_MUTEX_MOD_MDP_WROT0, 528 + [MUTEX_MOD_IDX_MDP_WROT2] = MT8195_MUTEX_MOD_MDP_WROT2, 529 + [MUTEX_MOD_IDX_MDP_WROT3] = MT8195_MUTEX_MOD_MDP_WROT3, 530 + }; 531 + 499 532 static const unsigned int mt8192_mutex_mod[DDP_COMPONENT_ID_MAX] = { 500 533 [DDP_COMPONENT_AAL0] = MT8192_MUTEX_MOD_DISP_AAL0, 501 534 [DDP_COMPONENT_CCORR] = MT8192_MUTEX_MOD_DISP_CCORR0, ··· 766 733 .mutex_sof = mt8188_mutex_sof, 767 734 .mutex_mod_reg = MT8183_MUTEX0_MOD0, 768 735 .mutex_sof_reg = MT8183_MUTEX0_SOF0, 736 + }; 737 + 738 + static const struct mtk_mutex_data mt8188_vpp_mutex_driver_data = { 739 + .mutex_sof = mt8188_mutex_sof, 740 + .mutex_mod_reg = MT8183_MUTEX0_MOD0, 741 + .mutex_sof_reg = MT8183_MUTEX0_SOF0, 742 + .mutex_table_mod = mt8188_mdp_mutex_table_mod, 769 743 }; 770 744 771 745 static const struct mtk_mutex_data mt8192_mutex_driver_data = { ··· 1129 1089 { .compatible = "mediatek,mt8186-disp-mutex", .data = &mt8186_mutex_driver_data }, 1130 1090 { .compatible = "mediatek,mt8186-mdp3-mutex", .data = &mt8186_mdp_mutex_driver_data }, 1131 1091 { .compatible = "mediatek,mt8188-disp-mutex", .data = &mt8188_mutex_driver_data }, 1092 + { .compatible = "mediatek,mt8188-vpp-mutex", .data = &mt8188_vpp_mutex_driver_data }, 1132 1093 { .compatible = "mediatek,mt8192-disp-mutex", .data = &mt8192_mutex_driver_data }, 1133 1094 { .compatible = "mediatek,mt8195-disp-mutex", .data = &mt8195_mutex_driver_data }, 1134 1095 { .compatible = "mediatek,mt8195-vpp-mutex", .data = &mt8195_vpp_mutex_driver_data },
+11 -3
drivers/soc/mediatek/mtk-socinfo.c
··· 48 48 MTK_SOCINFO_ENTRY("MT8183", "MT8183V/AZA", "Kompanio 500", 0x00010043, 0x00000940), 49 49 MTK_SOCINFO_ENTRY("MT8186", "MT8186GV/AZA", "Kompanio 520", 0x81861001, CELL_NOT_USED), 50 50 MTK_SOCINFO_ENTRY("MT8186T", "MT8186TV/AZA", "Kompanio 528", 0x81862001, CELL_NOT_USED), 51 - MTK_SOCINFO_ENTRY("MT8188", "MT8188GV/AZA", "Kompanio 830", 0x81880000, 0x00000010), 52 - MTK_SOCINFO_ENTRY("MT8188", "MT8188GV/HZA", "Kompanio 830", 0x81880000, 0x00000011), 51 + MTK_SOCINFO_ENTRY("MT8188", "MT8188GV/AZA", "Kompanio 838", 0x81880000, 0x00000010), 52 + MTK_SOCINFO_ENTRY("MT8188", "MT8188GV/HZA", "Kompanio 838", 0x81880000, 0x00000011), 53 53 MTK_SOCINFO_ENTRY("MT8192", "MT8192V/AZA", "Kompanio 820", 0x00001100, 0x00040080), 54 54 MTK_SOCINFO_ENTRY("MT8192T", "MT8192V/ATZA", "Kompanio 828", 0x00000100, 0x000400C0), 55 55 MTK_SOCINFO_ENTRY("MT8195", "MT8195GV/EZA", "Kompanio 1200", 0x81950300, CELL_NOT_USED), 56 56 MTK_SOCINFO_ENTRY("MT8195", "MT8195GV/EHZA", "Kompanio 1200", 0x81950304, CELL_NOT_USED), 57 57 MTK_SOCINFO_ENTRY("MT8195", "MT8195TV/EZA", "Kompanio 1380", 0x81950400, CELL_NOT_USED), 58 58 MTK_SOCINFO_ENTRY("MT8195", "MT8195TV/EHZA", "Kompanio 1380", 0x81950404, CELL_NOT_USED), 59 + MTK_SOCINFO_ENTRY("MT8395", "MT8395AV/ZA", "Genio 1200", 0x83950100, CELL_NOT_USED), 59 60 }; 60 61 61 62 static int mtk_socinfo_create_socinfo_node(struct mtk_socinfo *mtk_socinfop) ··· 145 144 } 146 145 } 147 146 148 - return match_socinfo_index >= 0 ? match_socinfo_index : -ENOENT; 147 + if (match_socinfo_index < 0) { 148 + dev_warn(mtk_socinfop->dev, 149 + "Unknown MediaTek SoC with ID 0x%08x 0x%08x\n", 150 + cell_data[0], cell_data[1]); 151 + return -ENOENT; 152 + } 153 + 154 + return match_socinfo_index; 149 155 } 150 156 151 157 static int mtk_socinfo_probe(struct platform_device *pdev)
+123 -30
include/linux/soc/mediatek/mtk-cmdq.h
··· 14 14 #define CMDQ_ADDR_HIGH(addr) ((u32)(((addr) >> 16) & GENMASK(31, 0))) 15 15 #define CMDQ_ADDR_LOW(addr) ((u16)(addr) | BIT(1)) 16 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 + 17 26 struct cmdq_pkt; 18 27 19 28 struct cmdq_client_reg { ··· 71 62 /** 72 63 * cmdq_pkt_create() - create a CMDQ packet 73 64 * @client: the CMDQ mailbox client 65 + * @pkt: the CMDQ packet 74 66 * @size: required CMDQ buffer size 75 67 * 76 - * Return: CMDQ packet pointer 68 + * Return: 0 for success; else the error code is returned 77 69 */ 78 - struct cmdq_pkt *cmdq_pkt_create(struct cmdq_client *client, size_t size); 70 + int cmdq_pkt_create(struct cmdq_client *client, struct cmdq_pkt *pkt, size_t size); 79 71 80 72 /** 81 73 * cmdq_pkt_destroy() - destroy the CMDQ packet 74 + * @client: the CMDQ mailbox client 82 75 * @pkt: the CMDQ packet 83 76 */ 84 - void cmdq_pkt_destroy(struct cmdq_pkt *pkt); 77 + void cmdq_pkt_destroy(struct cmdq_client *client, struct cmdq_pkt *pkt); 85 78 86 79 /** 87 80 * cmdq_pkt_write() - append write command to the CMDQ packet ··· 185 174 u16 addr_low, u32 value, u32 mask); 186 175 187 176 /** 177 + * cmdq_pkt_mem_move() - append memory move command to the CMDQ packet 178 + * @pkt: the CMDQ packet 179 + * @src_addr: source address 180 + * @dst_addr: destination address 181 + * 182 + * Appends a CMDQ command to copy the value found in `src_addr` to `dst_addr`. 183 + * 184 + * Return: 0 for success; else the error code is returned 185 + */ 186 + int cmdq_pkt_mem_move(struct cmdq_pkt *pkt, dma_addr_t src_addr, dma_addr_t dst_addr); 187 + 188 + /** 188 189 * cmdq_pkt_wfe() - append wait for event command to the CMDQ packet 189 190 * @pkt: the CMDQ packet 190 191 * @event: the desired event type to wait ··· 205 182 * Return: 0 for success; else the error code is returned 206 183 */ 207 184 int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event, bool clear); 185 + 186 + /** 187 + * cmdq_pkt_acquire_event() - append acquire event command to the CMDQ packet 188 + * @pkt: the CMDQ packet 189 + * @event: the desired event to be acquired 190 + * 191 + * User can use cmdq_pkt_acquire_event() as `mutex_lock` and cmdq_pkt_clear_event() 192 + * as `mutex_unlock` to protect some `critical section` instructions between them. 193 + * cmdq_pkt_acquire_event() would wait for event to be cleared. 194 + * After event is cleared by cmdq_pkt_clear_event in other GCE threads, 195 + * cmdq_pkt_acquire_event() would set event and keep executing next instruction. 196 + * 197 + * Return: 0 for success; else the error code is returned 198 + */ 199 + int cmdq_pkt_acquire_event(struct cmdq_pkt *pkt, u16 event); 208 200 209 201 /** 210 202 * cmdq_pkt_clear_event() - append clear event command to the CMDQ packet ··· 286 248 int cmdq_pkt_assign(struct cmdq_pkt *pkt, u16 reg_idx, u32 value); 287 249 288 250 /** 289 - * cmdq_pkt_jump() - Append jump command to the CMDQ packet, ask GCE 290 - * to execute an instruction that change current thread PC to 291 - * a physical address which should contains more instruction. 251 + * cmdq_pkt_poll_addr() - Append blocking POLL command to CMDQ packet 252 + * @pkt: the CMDQ packet 253 + * @addr: the hardware register address 254 + * @value: the specified target register value 255 + * @mask: the specified target register mask 256 + * 257 + * Appends a polling (POLL) command to the CMDQ packet and asks the GCE 258 + * to execute an instruction that checks for the specified `value` (with 259 + * or without `mask`) to appear in the specified hardware register `addr`. 260 + * All GCE threads will be blocked by this instruction. 261 + * 262 + * Return: 0 for success or negative error code 263 + */ 264 + int cmdq_pkt_poll_addr(struct cmdq_pkt *pkt, dma_addr_t addr, u32 value, u32 mask); 265 + 266 + /** 267 + * cmdq_pkt_jump_abs() - Append jump command to the CMDQ packet, ask GCE 268 + * to execute an instruction that change current thread 269 + * PC to a absolute physical address which should 270 + * contains more instruction. 292 271 * @pkt: the CMDQ packet 293 - * @addr: physical address of target instruction buffer 272 + * @addr: absolute physical address of target instruction buffer 273 + * @shift_pa: shift bits of physical address in CMDQ instruction. This value 274 + * is got by cmdq_get_shift_pa(). 294 275 * 295 276 * Return: 0 for success; else the error code is returned 296 277 */ 297 - int cmdq_pkt_jump(struct cmdq_pkt *pkt, dma_addr_t addr); 278 + int cmdq_pkt_jump_abs(struct cmdq_pkt *pkt, dma_addr_t addr, u8 shift_pa); 279 + 280 + /* This wrapper has to be removed after all users migrated to jump_abs */ 281 + static inline int cmdq_pkt_jump(struct cmdq_pkt *pkt, dma_addr_t addr, u8 shift_pa) 282 + { 283 + return cmdq_pkt_jump_abs(pkt, addr, shift_pa); 284 + } 285 + 286 + /** 287 + * cmdq_pkt_jump_rel() - Append jump command to the CMDQ packet, ask GCE 288 + * to execute an instruction that change current thread 289 + * PC to a physical address with relative offset. The 290 + * target address should contains more instruction. 291 + * @pkt: the CMDQ packet 292 + * @offset: relative offset of target instruction buffer from current PC. 293 + * @shift_pa: shift bits of physical address in CMDQ instruction. This value 294 + * is got by cmdq_get_shift_pa(). 295 + * 296 + * Return: 0 for success; else the error code is returned 297 + */ 298 + int cmdq_pkt_jump_rel(struct cmdq_pkt *pkt, s32 offset, u8 shift_pa); 299 + 300 + /** 301 + * cmdq_pkt_eoc() - Append EOC and ask GCE to generate an IRQ at end of execution 302 + * @pkt: The CMDQ packet 303 + * 304 + * Appends an End Of Code (EOC) command to the CMDQ packet and asks the GCE 305 + * to generate an interrupt at the end of the execution of all commands in 306 + * the pipeline. 307 + * The EOC command is usually appended to the end of the pipeline to notify 308 + * that all commands are done. 309 + * 310 + * Return: 0 for success or negative error number 311 + */ 312 + int cmdq_pkt_eoc(struct cmdq_pkt *pkt); 298 313 299 314 /** 300 315 * cmdq_pkt_finalize() - Append EOC and jump command to pkt. ··· 356 265 * Return: 0 for success; else the error code is returned 357 266 */ 358 267 int cmdq_pkt_finalize(struct cmdq_pkt *pkt); 359 - 360 - /** 361 - * cmdq_pkt_flush_async() - trigger CMDQ to asynchronously execute the CMDQ 362 - * packet and call back at the end of done packet 363 - * @pkt: the CMDQ packet 364 - * 365 - * Return: 0 for success; else the error code is returned 366 - * 367 - * Trigger CMDQ to asynchronously execute the CMDQ packet and call back 368 - * at the end of done packet. Note that this is an ASYNC function. When the 369 - * function returned, it may or may not be finished. 370 - */ 371 - int cmdq_pkt_flush_async(struct cmdq_pkt *pkt); 372 268 373 269 #else /* IS_ENABLED(CONFIG_MTK_CMDQ) */ 374 270 ··· 372 294 373 295 static inline void cmdq_mbox_destroy(struct cmdq_client *client) { } 374 296 375 - static inline struct cmdq_pkt *cmdq_pkt_create(struct cmdq_client *client, size_t size) 297 + static inline int cmdq_pkt_create(struct cmdq_client *client, struct cmdq_pkt *pkt, size_t size) 376 298 { 377 - return ERR_PTR(-EINVAL); 299 + return -EINVAL; 378 300 } 379 301 380 - static inline void cmdq_pkt_destroy(struct cmdq_pkt *pkt) { } 302 + static inline void cmdq_pkt_destroy(struct cmdq_client *client, struct cmdq_pkt *pkt) { } 381 303 382 304 static inline int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value) 383 305 { ··· 452 374 return -EINVAL; 453 375 } 454 376 455 - static inline int cmdq_pkt_jump(struct cmdq_pkt *pkt, dma_addr_t addr) 377 + static inline int cmdq_pkt_poll_addr(struct cmdq_pkt *pkt, dma_addr_t addr, u32 value, u32 mask) 378 + { 379 + return -EINVAL; 380 + } 381 + 382 + static inline int cmdq_pkt_jump_abs(struct cmdq_pkt *pkt, dma_addr_t addr, u8 shift_pa) 383 + { 384 + return -EINVAL; 385 + } 386 + 387 + static inline int cmdq_pkt_jump(struct cmdq_pkt *pkt, dma_addr_t addr, u8 shift_pa) 388 + { 389 + return -EINVAL; 390 + } 391 + 392 + static inline int cmdq_pkt_jump_rel(struct cmdq_pkt *pkt, s32 offset, u8 shift_pa) 393 + { 394 + return -EINVAL; 395 + } 396 + 397 + static inline int cmdq_pkt_eoc(struct cmdq_pkt *pkt) 456 398 { 457 399 return -EINVAL; 458 400 } 459 401 460 402 static inline int cmdq_pkt_finalize(struct cmdq_pkt *pkt) 461 - { 462 - return -EINVAL; 463 - } 464 - 465 - static inline int cmdq_pkt_flush_async(struct cmdq_pkt *pkt) 466 403 { 467 404 return -EINVAL; 468 405 }