Re: [PATCH v2 08/14] soc: mediatek: cmdq: add write_s function
From: CK Hu
Date: Tue Dec 10 2019 - 00:18:50 EST
Hi, Dennis:
On Wed, 2019-11-27 at 09:58 +0800, Dennis YC Hsieh wrote:
> add write_s function in cmdq helper functions which
> writes value contains in internal register to address
> with large dma access support.
>
> Signed-off-by: Dennis YC Hsieh <dennis-yc.hsieh@xxxxxxxxxxxx>
> ---
> drivers/soc/mediatek/mtk-cmdq-helper.c | 40 ++++++++++++++++++++++++
> include/linux/mailbox/mtk-cmdq-mailbox.h | 2 ++
> include/linux/soc/mediatek/mtk-cmdq.h | 12 +++++++
> 3 files changed, 54 insertions(+)
>
> diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c
> index 9cc234f08ec5..2edbc0954d97 100644
> --- a/drivers/soc/mediatek/mtk-cmdq-helper.c
> +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c
> @@ -15,11 +15,18 @@
> #define CMDQ_EOC_CMD ((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \
> << 32 | CMDQ_EOC_IRQ_EN)
> #define CMDQ_REG_TYPE 1
> +#define CMDQ_ADDR_HIGH(addr) ((u32)(((addr) >> 16) & GENMASK(31, 0)))
> +#define CMDQ_ADDR_LOW_BIT BIT(1)
> +#define CMDQ_ADDR_LOW(addr) ((u16)(addr) | CMDQ_ADDR_LOW_BIT)
>
> struct cmdq_instruction {
> union {
> u32 value;
> u32 mask;
> + struct {
> + u16 arg_c;
> + u16 arg_b;
> + };
> };
> union {
> u16 offset;
> @@ -224,6 +231,39 @@ int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys,
> }
> EXPORT_SYMBOL(cmdq_pkt_write_mask);
>
> +int cmdq_pkt_write_s(struct cmdq_pkt *pkt, phys_addr_t addr, u16 reg_idx,
> + u32 mask)
> +{
> + struct cmdq_instruction inst = { {0} };
> + const u16 dst_reg_idx = CMDQ_SPR_TEMP;
> + int err;
> +
> + if (mask != U32_MAX) {
> + inst.op = CMDQ_CODE_MASK;
> + inst.mask = ~mask;
> + err = cmdq_pkt_append_command(pkt, inst);
> + if (err < 0)
> + return err;
> +
> + inst.mask = 0;
> + inst.op = CMDQ_CODE_WRITE_S_MASK;
> + } else {
> + inst.op = CMDQ_CODE_WRITE_S;
> + }
> +
> + err = cmdq_pkt_assign(pkt, dst_reg_idx, CMDQ_ADDR_HIGH(addr));
You combine assign and write_s in this function, so you always occupy
register CMDQ_SPR_TEMP for this purpose, client could not use
CMDQ_SPR_TEMP for other purpose. So I would like you just do write_s in
this function. So the code in client would be:
cmdq_pkt_assign(pkt, high_addr_reg_idx, CMDQ_ADDR_HIGH(addr));
cmdq_pkt_write_s(pkt, high_addr_reg_idx, CMDQ_ADDR_LOW(addr),
src_reg_idx, mask);
Let client to decide which register for high address.
Another benefit of not combining instruction is that client driver owner
would be more clear about which command is in command buffer and it's
easier for them to debug.
> + if (err < 0)
> + return err;
> +
> + inst.arg_b_t = CMDQ_REG_TYPE;
> + inst.sop = dst_reg_idx;
> + inst.offset = CMDQ_ADDR_LOW(addr);
> + inst.arg_b = reg_idx;
I seems arg_b has a meaningful name.
Regards,
CK
> +
> + return cmdq_pkt_append_command(pkt, inst);
> +}
> +EXPORT_SYMBOL(cmdq_pkt_write_s);
> +
> int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event)
> {
> struct cmdq_instruction inst = { {0} };
> diff --git a/include/linux/mailbox/mtk-cmdq-mailbox.h b/include/linux/mailbox/mtk-cmdq-mailbox.h
> index 121c3bb6d3de..8ef87e1bd03b 100644
> --- a/include/linux/mailbox/mtk-cmdq-mailbox.h
> +++ b/include/linux/mailbox/mtk-cmdq-mailbox.h
> @@ -59,6 +59,8 @@ enum cmdq_code {
> CMDQ_CODE_JUMP = 0x10,
> CMDQ_CODE_WFE = 0x20,
> CMDQ_CODE_EOC = 0x40,
> + CMDQ_CODE_WRITE_S = 0x90,
> + CMDQ_CODE_WRITE_S_MASK = 0x91,
> CMDQ_CODE_LOGIC = 0xa0,
> };
>
> diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h
> index c66b3a0da2a2..56ff1970197c 100644
> --- a/include/linux/soc/mediatek/mtk-cmdq.h
> +++ b/include/linux/soc/mediatek/mtk-cmdq.h
> @@ -106,6 +106,18 @@ int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value);
> int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys,
> u16 offset, u32 value, u32 mask);
>
> +/**
> + * cmdq_pkt_write_s_mask() - append write_s command to the CMDQ packet
> + * @pkt: the CMDQ packet
> + * @addr: the physical address of register or dma
> + * @reg_idx: the CMDQ internal register ID which cache source value
> + * @mask: the specified target register mask
> + *
> + * Return: 0 for success; else the error code is returned
> + */
> +int cmdq_pkt_write_s(struct cmdq_pkt *pkt, phys_addr_t addr, u16 reg_idx,
> + u32 mask);
> +
> /**
> * cmdq_pkt_wfe() - append wait for event command to the CMDQ packet
> * @pkt: the CMDQ packet