Re: [PATCH] [media] mtk-mdp: Fix g_/s_selection capture/compose logic
On Thu, 2017-04-13 at 14:50 +0800, Wu-Cheng Li (李務誠) wrote: > Reviewed-by: Wu-Cheng Li> > On Thu, Apr 13, 2017 at 12:18 PM, Minghsiu Tsai > wrote: > > From: Daniel Kurtz > > > > Experiments show that the: > > (1) mtk-mdp uses the _MPLANE form of CAPTURE/OUTPUT > > (2) CAPTURE types use CROP targets, and OUTPUT types use COMPOSE targets > > > > Signed-off-by: Daniel Kurtz > > Signed-off-by: Minghsiu Tsai Acked-by:Houlong Wei > > > > --- > > drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c | 18 +- > > 1 file changed, 9 insertions(+), 9 deletions(-) > > > > diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c > > b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c > > index 13afe48..8ab7ca0 100644 > > --- a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c > > +++ b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c > > @@ -837,12 +837,12 @@ static int mtk_mdp_m2m_g_selection(struct file *file, > > void *fh, > > struct mtk_mdp_ctx *ctx = fh_to_ctx(fh); > > bool valid = false; > > > > - if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { > > - if (mtk_mdp_is_target_compose(s->target)) > > - valid = true; > > - } else if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { > > + if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { > > if (mtk_mdp_is_target_crop(s->target)) > > valid = true; > > + } else if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { > > + if (mtk_mdp_is_target_compose(s->target)) > > + valid = true; > > } > > if (!valid) { > > mtk_mdp_dbg(1, "[%d] invalid type:%d,%u", ctx->id, s->type, > > @@ -907,12 +907,12 @@ static int mtk_mdp_m2m_s_selection(struct file *file, > > void *fh, > > int ret; > > bool valid = false; > > > > - if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { > > - if (s->target == V4L2_SEL_TGT_COMPOSE) > > - valid = true; > > - } else if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { > > + if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { > > if (s->target == V4L2_SEL_TGT_CROP) > > valid = true; > > + } else if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { > > + if (s->target == V4L2_SEL_TGT_COMPOSE) > > + valid = true; > > } > > if (!valid) { > > mtk_mdp_dbg(1, "[%d] invalid type:%d,%u", ctx->id, s->type, > > @@ -925,7 +925,7 @@ static int mtk_mdp_m2m_s_selection(struct file *file, > > void *fh, > > if (ret) > > return ret; > > > > - if (mtk_mdp_is_target_crop(s->target)) > > + if (mtk_mdp_is_target_compose(s->target)) > > frame = >s_frame; > > else > > frame = >d_frame; > > -- > > 1.9.1 > >
[PATCH v22 2/4] mailbox: mediatek: Add Mediatek CMDQ driver
This patch is first version of Mediatek Command Queue(CMDQ) driver. The CMDQ is used to help write registers with critical time limitation, such as updating display configuration during the vblank. It controls Global Command Engine (GCE) hardware to achieve this requirement. Currently, CMDQ only supports display related hardwares, but we expect it can be extended to other hardwares for future requirements. Signed-off-by: Houlong Wei Signed-off-by: HS Liao Signed-off-by: CK Hu --- drivers/mailbox/Kconfig | 10 + drivers/mailbox/Makefile |2 + drivers/mailbox/mtk-cmdq-mailbox.c | 634 ++ include/linux/mailbox/mtk-cmdq-mailbox.h | 70 4 files changed, 716 insertions(+) create mode 100644 drivers/mailbox/mtk-cmdq-mailbox.c create mode 100644 include/linux/mailbox/mtk-cmdq-mailbox.h diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index e63d29a..2bbabc9 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -189,4 +189,14 @@ config STM32_IPCC Mailbox implementation for STMicroelectonics STM32 family chips with hardware for Inter-Processor Communication Controller (IPCC) between processors. Say Y here if you want to have this support. + +config MTK_CMDQ_MBOX + tristate "MediaTek CMDQ Mailbox Support" + depends on ARCH_MEDIATEK || COMPILE_TEST + select MTK_INFRACFG + help + Say yes here to add support for the MediaTek Command Queue (CMDQ) + mailbox driver. The CMDQ is used to help read/write registers with + critical time limitation, such as updating display configuration + during the vblank. endif diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index 4d501be..4b00804 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -40,3 +40,5 @@ obj-$(CONFIG_QCOM_APCS_IPC) += qcom-apcs-ipc-mailbox.o obj-$(CONFIG_TEGRA_HSP_MBOX) += tegra-hsp.o obj-$(CONFIG_STM32_IPCC) += stm32-ipcc.o + +obj-$(CONFIG_MTK_CMDQ_MBOX)+= mtk-cmdq-mailbox.o diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c new file mode 100644 index 000..93d87cb --- /dev/null +++ b/drivers/mailbox/mtk-cmdq-mailbox.c @@ -0,0 +1,634 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 MediaTek Inc. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CMDQ_OP_CODE_MASK (0xff << CMDQ_OP_CODE_SHIFT) +#define CMDQ_TIMEOUT_MS1000 +#define CMDQ_IRQ_MASK 0x +#define CMDQ_NUM_CMD(t)(t->cmd_buf_size / CMDQ_INST_SIZE) + +#define CMDQ_CURR_IRQ_STATUS 0x10 +#define CMDQ_THR_SLOT_CYCLES 0x30 +#define CMDQ_THR_BASE 0x100 +#define CMDQ_THR_SIZE 0x80 +#define CMDQ_THR_WARM_RESET0x00 +#define CMDQ_THR_ENABLE_TASK 0x04 +#define CMDQ_THR_SUSPEND_TASK 0x08 +#define CMDQ_THR_CURR_STATUS 0x0c +#define CMDQ_THR_IRQ_STATUS0x10 +#define CMDQ_THR_IRQ_ENABLE0x14 +#define CMDQ_THR_CURR_ADDR 0x20 +#define CMDQ_THR_END_ADDR 0x24 +#define CMDQ_THR_WAIT_TOKEN0x30 +#define CMDQ_THR_PRIORITY 0x40 + +#define CMDQ_NO_TIMEOUT0xu +#define CMDQ_THR_ACTIVE_SLOT_CYCLES0x3200 +#define CMDQ_THR_ENABLED 0x1 +#define CMDQ_THR_DISABLED 0x0 +#define CMDQ_THR_SUSPEND 0x1 +#define CMDQ_THR_RESUME0x0 +#define CMDQ_THR_STATUS_SUSPENDED BIT(1) +#define CMDQ_THR_DO_WARM_RESET BIT(0) +#define CMDQ_THR_IRQ_DONE 0x1 +#define CMDQ_THR_IRQ_ERROR 0x12 +#define CMDQ_THR_IRQ_EN(CMDQ_THR_IRQ_ERROR | CMDQ_THR_IRQ_DONE) +#define CMDQ_THR_IS_WAITINGBIT(31) + +#define CMDQ_JUMP_BY_OFFSET0x1000 +#define CMDQ_JUMP_BY_PA0x1001 + +struct cmdq_thread { + struct mbox_chan*chan; + void __iomem*base; + struct list_headtask_busy_list; + struct timer_list timeout; + u32 timeout_ms; + u32 priority; + boolatomic_exec; +}; + +struct cmdq_task { + struct cmdq *cmdq; + struct list_headlist_entry; + dma_addr_t pa_base; + struct cmdq_thread *thread; + struct cmdq_pkt *pkt; /* the packet sent from mailbox client */ +}; + +struct cmdq { + struct mbox_controller mbox; + void __iomem*base; + u32 irq; + u32 thread_nr; + struct cmdq_thread *thread;
[PATCH v22 4/4] soc: mediatek: Add Mediatek CMDQ helper
Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. Signed-off-by: Houlong Wei Signed-off-by: HS Liao --- drivers/soc/mediatek/Kconfig | 12 ++ drivers/soc/mediatek/Makefile |1 + drivers/soc/mediatek/mtk-cmdq-helper.c | 258 include/linux/soc/mediatek/mtk-cmdq.h | 132 4 files changed, 403 insertions(+) create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig index a7d0667..17bd759 100644 --- a/drivers/soc/mediatek/Kconfig +++ b/drivers/soc/mediatek/Kconfig @@ -4,6 +4,18 @@ menu "MediaTek SoC drivers" depends on ARCH_MEDIATEK || COMPILE_TEST +config MTK_CMDQ + tristate "MediaTek CMDQ Support" + depends on ARCH_MEDIATEK || COMPILE_TEST + select MAILBOX + select MTK_CMDQ_MBOX + select MTK_INFRACFG + help + Say yes here to add support for the MediaTek Command Queue (CMDQ) + driver. The CMDQ is used to help read/write registers with critical + time limitation, such as updating display configuration during the + vblank. + config MTK_INFRACFG bool "MediaTek INFRACFG Support" select REGMAP diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile index 12998b0..64ce5ee 100644 --- a/drivers/soc/mediatek/Makefile +++ b/drivers/soc/mediatek/Makefile @@ -1,3 +1,4 @@ +obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c new file mode 100644 index 000..6c66091 --- /dev/null +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -0,0 +1,258 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 MediaTek Inc. + * + */ + +#include +#include +#include +#include +#include + +#define CMDQ_ARG_A_WRITE_MASK 0x +#define CMDQ_WRITE_ENABLE_MASK BIT(0) +#define CMDQ_EOC_IRQ_ENBIT(0) +#define CMDQ_EOC_CMD ((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \ + << 32 | CMDQ_EOC_IRQ_EN) + +int cmdq_pkt_realloc_cmd_buffer(struct cmdq_pkt *pkt, size_t size) +{ + void *new_buf; + + new_buf = krealloc(pkt->va_base, size, GFP_KERNEL | __GFP_ZERO); + if (!new_buf) + return -ENOMEM; + pkt->va_base = new_buf; + pkt->buf_size = size; + + return 0; +} +EXPORT_SYMBOL(cmdq_pkt_realloc_cmd_buffer); + +struct cmdq_client *cmdq_mbox_create(struct device *dev, int index) +{ + struct cmdq_client *client; + long err = 0; + + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client) + return (struct cmdq_client *)-ENOMEM; + + client->client.dev = dev; + client->client.tx_block = false; + client->chan = mbox_request_channel(>client, index); + + if (IS_ERR(client->chan)) { + dev_err(dev, "failed to request channel\n"); + err = PTR_ERR(client->chan); + kfree(client); + + return (struct cmdq_client *)err; + } + + return client; +} +EXPORT_SYMBOL(cmdq_mbox_create); + +void cmdq_mbox_destroy(struct cmdq_client *client) +{ + mbox_free_channel(client->chan); + kfree(client); +} +EXPORT_SYMBOL(cmdq_mbox_destroy); + +int cmdq_pkt_create(struct cmdq_pkt **pkt_ptr) +{ + struct cmdq_pkt *pkt; + int err; + + pkt = kzalloc(sizeof(*pkt), GFP_KERNEL); + if (!pkt) + return -ENOMEM; + err = cmdq_pkt_realloc_cmd_buffer(pkt, PAGE_SIZE); + if (err < 0) { + kfree(pkt); + return err; + } + *pkt_ptr = pkt; + + return 0; +} +EXPORT_SYMBOL(cmdq_pkt_create); + +void cmdq_pkt_destroy(struct cmdq_pkt *pkt) +{ + kfree(pkt->va_base); + kfree(pkt); +} +EXPORT_SYMBOL(cmdq_pkt_destroy); + +static bool cmdq_pkt_is_finalized(struct cmdq_pkt *pkt) +{ + u64 *expect_eoc; + + if (pkt->cmd_buf_size < CMDQ_INST_SIZE << 1) + return false; + + expect_eoc = pkt->va_base + pkt->cmd_buf_size - (CMDQ_INST_SIZE << 1); + if (*expect_eoc == CMDQ_EOC_CMD) + return true; + + return false; +} + +static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, enum cmdq_code code, + u32 arg_a, u32 arg_b) +{ + u64 *cmd_ptr; + int err; + + if (WARN_ON(cmdq_pkt_is_finalized(pkt))) + return -EBUSY; + if (unlikely(pkt->cmd_buf_size + CMDQ_INST_SIZE > pkt->buf_size)) { + err = cmdq_pkt_realloc_cmd_buffer(pkt, pkt->buf_size <<
[PATCH v22 3/4] arm64: dts: mt8173: Add GCE node
This patch adds the device node of the GCE hardware for CMDQ module. Signed-off-by: Houlong Wei Signed-off-by: HS Liao --- arch/arm64/boot/dts/mediatek/mt8173.dtsi | 11 +++ 1 file changed, 11 insertions(+) diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi index 94597e3..d180a6d 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi @@ -18,6 +18,7 @@ #include #include #include +#include #include "mt8173-pinfunc.h" / { @@ -519,6 +520,16 @@ status = "disabled"; }; + gce: gce@10212000 { + compatible = "mediatek,mt8173-gce"; + reg = <0 0x10212000 0 0x1000>; + interrupts = ; + clocks = < CLK_INFRA_GCE>; + clock-names = "gce"; + thread-num = ; + #mbox-cells = <4>; + }; + mipi_tx0: mipi-dphy@10215000 { compatible = "mediatek,mt8173-mipi-tx"; reg = <0 0x10215000 0 0x1000>; -- 1.7.9.5
[PATCH v22 1/4] dt-bindings: soc: Add documentation for the MediaTek GCE unit
This adds documentation for the MediaTek Global Command Engine (GCE) unit found in MT8173 SoCs. Signed-off-by: Houlong Wei Signed-off-by: HS Liao --- Hi Rob, I don't add your ACK in this version since the dt-binding description has been changed. Thanks. --- .../devicetree/bindings/mailbox/mtk-gce.txt| 65 include/dt-bindings/gce/mt8173-gce.h | 48 +++ 2 files changed, 113 insertions(+) create mode 100644 Documentation/devicetree/bindings/mailbox/mtk-gce.txt create mode 100644 include/dt-bindings/gce/mt8173-gce.h diff --git a/Documentation/devicetree/bindings/mailbox/mtk-gce.txt b/Documentation/devicetree/bindings/mailbox/mtk-gce.txt new file mode 100644 index 000..26f65a4 --- /dev/null +++ b/Documentation/devicetree/bindings/mailbox/mtk-gce.txt @@ -0,0 +1,65 @@ +MediaTek GCE +=== + +The Global Command Engine (GCE) is used to help read/write registers with +critical time limitation, such as updating display configuration during the +vblank. The GCE can be used to implement the Command Queue (CMDQ) driver. + +CMDQ driver uses mailbox framework for communication. Please refer to +mailbox.txt for generic information about mailbox device-tree bindings. + +Required properties: +- compatible: Must be "mediatek,mt8173-gce" +- reg: Address range of the GCE unit +- interrupts: The interrupt signal from the GCE block +- clock: Clocks according to the common clock binding +- clock-names: Must be "gce" to stand for GCE clock +- thread-num: Maximum threads count of GCE. +- #mbox-cells: Should be 4. + < channel timeout priority atomic_exec> + phandle: Label name of a gce node. + channel: Channel of mailbox. Be equal to the thread id of GCE. + timeout: Maximum time of software waiting GCE processing done, in unit + of millisecond. + priority: Priority of GCE thread. + atomic_exec: GCE processing continuous packets of commands in atomic + way. + +Required properties for a client device: +- mboxes: Client use mailbox to communicate with GCE, it should have this + property and list of phandle, mailbox specifiers. +- gce-subsys: Specify the sub-system id which is corresponding to the register + address. + +Optional properties for a client device: +- gce-event: Specify the event if the client has any. Because the event is + parsed by client, so client can replace 'gce-event' with other meaningful + name. + +Some vaules of properties are defined in 'dt-bindings/gce/mt8173-gce.h'. Such as +thread number, sub-system ids, thread priority, event ids. + +Example: + + gce: gce@10212000 { + compatible = "mediatek,mt8173-gce"; + reg = <0 0x10212000 0 0x1000>; + interrupts = ; + clocks = < CLK_INFRA_GCE>; + clock-names = "gce"; + thread-num = CMDQ_THR_MAX_COUNT; + #mbox-cells = <4>; + }; + +Example for a client device: + + mmsys: clock-controller@1400 { + compatible = "mediatek,mt8173-mmsys"; + mboxes = < 0 2000 CMDQ_THR_PRIO_LOWEST 1>, +< 1 2000 CMDQ_THR_PRIO_LOWEST 1>; + gce-subsys = ; + mutex-event-eof = ; + + ... + }; diff --git a/include/dt-bindings/gce/mt8173-gce.h b/include/dt-bindings/gce/mt8173-gce.h new file mode 100644 index 000..89eb3b8 --- /dev/null +++ b/include/dt-bindings/gce/mt8173-gce.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Houlong Wei + * + */ + +#ifndef _DT_BINDINGS_GCE_MT8173_H +#define _DT_BINDINGS_GCE_MT8173_H + +#define CMDQ_NO_TIMEOUT0x + +#define CMDQ_THR_MAX_COUNT 16 + +/* GCE HW thread priority */ +#define CMDQ_THR_PRIO_LOWEST 0 +#define CMDQ_THR_PRIO_HIGHEST 1 + +/* GCE SUBSYS */ +#define SUBSYS_14001 +#define SUBSYS_14012 +#define SUBSYS_14023 + +/* GCE HW EVENT */ +#define CMDQ_EVENT_DISP_OVL0_SOF 11 +#define CMDQ_EVENT_DISP_OVL1_SOF 12 +#define CMDQ_EVENT_DISP_RDMA0_SOF 13 +#define CMDQ_EVENT_DISP_RDMA1_SOF 14 +#define CMDQ_EVENT_DISP_RDMA2_SOF 15 +#define CMDQ_EVENT_DISP_WDMA0_SOF 16 +#define CMDQ_EVENT_DISP_WDMA1_SOF 17 +#define CMDQ_EVENT_DISP_OVL0_EOF 39 +#define CMDQ_EVENT_DISP_OVL1_EOF 40 +#define CMDQ_EVENT_DISP_RDMA0_EOF 41 +#define CMDQ_EVENT_DISP_RDMA1_EOF 42 +#define CMDQ_EVENT_DISP_RDMA2_EOF 43 +#define CMDQ_EVENT_DISP_WDMA0_EOF 44 +#define CMDQ_EVENT_DISP_WDMA1_EOF 45 +#define CMDQ_EVENT_MUTEX0_STREAM_EOF 53 +#define CMDQ_EVENT_MUTEX1_STREAM_EOF 54 +#define CMDQ_EVENT_MUTE
[PATCH v22 0/4] MediaTek MT8173 CMDQ support
Hi, This is Mediatek MT8173 Command Queue(CMDQ) driver. The CMDQ is used to help write registers with critical time limitation, such as updating display configuration during the vblank. It controls Global Command Engine (GCE) hardware to achieve this requirement. Changes since v21: -rebase on v4.18-rc1 -remove subsys code and event id definition from mtk-cmdq-helper.c -add mt8173-gce.h to define the subsys code and envent id Changes since v20: -rebase on v4.15-rc1 -move dma_map_single outside of spinlock Changes since v19: - rebase to v4.10-rc2 Houlong Wei (4): dt-bindings: soc: Add documentation for the MediaTek GCE unit mailbox: mediatek: Add Mediatek CMDQ driver arm64: dts: mt8173: Add GCE node soc: mediatek: Add Mediatek CMDQ helper .../devicetree/bindings/mailbox/mtk-gce.txt| 65 ++ arch/arm64/boot/dts/mediatek/mt8173.dtsi | 11 + drivers/mailbox/Kconfig| 10 + drivers/mailbox/Makefile |2 + drivers/mailbox/mtk-cmdq-mailbox.c | 633 drivers/soc/mediatek/Kconfig | 12 + drivers/soc/mediatek/Makefile |1 + drivers/soc/mediatek/mtk-cmdq-helper.c | 258 include/dt-bindings/gce/mt8173-gce.h | 48 ++ include/linux/mailbox/mtk-cmdq-mailbox.h | 70 +++ include/linux/soc/mediatek/mtk-cmdq.h | 132 11 files changed, 1242 insertions(+) create mode 100644 Documentation/devicetree/bindings/mailbox/mtk-gce.txt create mode 100644 drivers/mailbox/mtk-cmdq-mailbox.c create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c create mode 100644 include/dt-bindings/gce/mt8173-gce.h create mode 100644 include/linux/mailbox/mtk-cmdq-mailbox.h create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h -- 1.7.9.5
Re: [PATCH v21 4/4] soc: mediatek: Add Mediatek CMDQ helper
On Tue, 2018-02-06 at 10:52 +0800, CK Hu wrote: > Hi, Houlong: > > I've some inline comment. > > On Wed, 2018-01-31 at 15:28 +0800, houlong@mediatek.com wrote: > > From: "hs.l...@mediatek.com" > > > > Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. > > > > Signed-off-by: Houlong Wei > > Signed-off-by: HS Liao > > --- > > drivers/soc/mediatek/Kconfig | 12 ++ > > drivers/soc/mediatek/Makefile |1 + > > drivers/soc/mediatek/mtk-cmdq-helper.c | 322 > > > > include/linux/soc/mediatek/mtk-cmdq.h | 174 + > > 4 files changed, 509 insertions(+) > > create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c > > create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h > > > > diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig > > index a7d0667..e66582e 100644 > > --- a/drivers/soc/mediatek/Kconfig > > +++ b/drivers/soc/mediatek/Kconfig > > @@ -4,6 +4,18 @@ > > menu "MediaTek SoC drivers" > > depends on ARCH_MEDIATEK || COMPILE_TEST > > > > +config MTK_CMDQ > > +bool "MediaTek CMDQ Support" > > +depends on ARM64 && ( ARCH_MEDIATEK || COMPILE_TEST ) > > +select MAILBOX > > +select MTK_CMDQ_MBOX > > +select MTK_INFRACFG > > +help > > + Say yes here to add support for the MediaTek Command Queue (CMDQ) > > + driver. The CMDQ is used to help read/write registers with critical > > + time limitation, such as updating display configuration during the > > + vblank. > > + > > config MTK_INFRACFG > > bool "MediaTek INFRACFG Support" > > select REGMAP > > diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile > > index 12998b0..64ce5ee 100644 > > --- a/drivers/soc/mediatek/Makefile > > +++ b/drivers/soc/mediatek/Makefile > > @@ -1,3 +1,4 @@ > > +obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o > > obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o > > obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o > > obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o > > diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c > > b/drivers/soc/mediatek/mtk-cmdq-helper.c > > new file mode 100644 > > index 000..80d0558 > > --- /dev/null > > +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c > > @@ -0,0 +1,322 @@ > > +/* > > + * Copyright (c) 2015 MediaTek Inc. > > + * > > + * This program is free software; you can redistribute it and/or modify > > + * it under the terms of the GNU General Public License version 2 as > > + * published by the Free Software Foundation. > > + * > > + * This program is distributed in the hope that it will be useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#define CMDQ_ARG_A_WRITE_MASK0x > > +#define CMDQ_WRITE_ENABLE_MASKBIT(0) > > +#define CMDQ_EOC_IRQ_ENBIT(0) > > +#define CMDQ_EOC_CMD((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \ > > +<< 32 | CMDQ_EOC_IRQ_EN) > > + > > +struct cmdq_subsys { > > +u32base; > > +intid; > > +}; > > + > > +static const struct cmdq_subsys gce_subsys[] = { > > +{0x1400, 1}, > > +{0x1401, 2}, > > +{0x1402, 3}, > > +}; > > I think subsys definition varies by different SoC, so it's better to > pass these definition from device tree to driver (client driver), and > client driver pass this subsys in the related interface. For example, > > in include/dt-bindings/gce/mt8173-gce.h, you define > > #define GCE_SUBSYS_14001 > #define GCE_SUBSYS_14012 > #define GCE_SUBSYS_14023 > > in device tree, place the subsys definition in client device node, > > #include "dt-bindings/gce/mt8173-gce.h" > > ovl0: ovl@1400c000 { > compatible = "mediatek,mt8173-disp-ovl"; > gce-subsys = ; > ... > }; > > And client driver pass subsys in the related interface, > > int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 > value); > > So, for another SoC, you just need to modify device tree and you do not > need to modify driver. Hi CK, thanks for your suggestion. I do it in v22. > > + > > +static int cmdq_subsys_base_to_id(u32 base) > >
Re: [PATCH v21 4/4] soc: mediatek: Add Mediatek CMDQ helper
On Wed, 2018-02-21 at 16:05 +0800, CK Hu wrote: > Hi, Houlong: > > I've one more inline comment. > > On Wed, 2018-01-31 at 15:28 +0800, houlong@mediatek.com wrote: > > From: "hs.l...@mediatek.com" > > > > Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. > > > > Signed-off-by: Houlong Wei > > Signed-off-by: HS Liao > > --- > > drivers/soc/mediatek/Kconfig | 12 ++ > > drivers/soc/mediatek/Makefile |1 + > > drivers/soc/mediatek/mtk-cmdq-helper.c | 322 > > > > include/linux/soc/mediatek/mtk-cmdq.h | 174 + > > 4 files changed, 509 insertions(+) > > create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c > > create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h > > > > diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig > > index a7d0667..e66582e 100644 > > --- a/drivers/soc/mediatek/Kconfig > > +++ b/drivers/soc/mediatek/Kconfig > > @@ -4,6 +4,18 @@ > > menu "MediaTek SoC drivers" > > depends on ARCH_MEDIATEK || COMPILE_TEST > > > > +config MTK_CMDQ > > + bool "MediaTek CMDQ Support" > > + depends on ARM64 && ( ARCH_MEDIATEK || COMPILE_TEST ) > > + select MAILBOX > > + select MTK_CMDQ_MBOX > > + select MTK_INFRACFG > > + help > > + Say yes here to add support for the MediaTek Command Queue (CMDQ) > > + driver. The CMDQ is used to help read/write registers with critical > > + time limitation, such as updating display configuration during the > > + vblank. > > + > > config MTK_INFRACFG > > bool "MediaTek INFRACFG Support" > > select REGMAP > > diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile > > index 12998b0..64ce5ee 100644 > > --- a/drivers/soc/mediatek/Makefile > > +++ b/drivers/soc/mediatek/Makefile > > @@ -1,3 +1,4 @@ > > +obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o > > obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o > > obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o > > obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o > > diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c > > b/drivers/soc/mediatek/mtk-cmdq-helper.c > > new file mode 100644 > > index 000..80d0558 > > --- /dev/null > > +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c > > @@ -0,0 +1,322 @@ > > +/* > > + * Copyright (c) 2015 MediaTek Inc. > > + * > > + * This program is free software; you can redistribute it and/or modify > > + * it under the terms of the GNU General Public License version 2 as > > + * published by the Free Software Foundation. > > + * > > + * This program is distributed in the hope that it will be useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#define CMDQ_ARG_A_WRITE_MASK 0x > > +#define CMDQ_WRITE_ENABLE_MASK BIT(0) > > +#define CMDQ_EOC_IRQ_ENBIT(0) > > +#define CMDQ_EOC_CMD ((u64)((CMDQ_CODE_EOC << > > CMDQ_OP_CODE_SHIFT)) \ > > + << 32 | CMDQ_EOC_IRQ_EN) > > + > > +struct cmdq_subsys { > > + u32 base; > > + int id; > > +}; > > + > > +static const struct cmdq_subsys gce_subsys[] = { > > + {0x1400, 1}, > > + {0x1401, 2}, > > + {0x1402, 3}, > > +}; > > + > > +static int cmdq_subsys_base_to_id(u32 base) > > +{ > > + int i; > > + > > + for (i = 0; i < ARRAY_SIZE(gce_subsys); i++) > > + if (gce_subsys[i].base == base) > > + return gce_subsys[i].id; > > + return -EFAULT; > > +} > > + > > +static int cmdq_pkt_realloc_cmd_buffer(struct cmdq_pkt *pkt, size_t size) > > +{ > > + void *new_buf; > > + > > + new_buf = krealloc(pkt->va_base, size, GFP_KERNEL | __GFP_ZERO); > > + if (!new_buf) > > + return -ENOMEM; > > + pkt->va_base = new_buf; > > + pkt->buf_size = size; > > + return 0; > > +} > > + > > +struct cmdq_base *cmdq_register_device(struct device *dev) > > +{ > > + struct cmdq_base *cmdq_base; > > + struct resource res; >
Re: [PATCH v21 2/4] mailbox: mediatek: Add Mediatek CMDQ driver
On Wed, 2018-02-21 at 11:53 +0800, CK Hu wrote: > Hi, Houlong: > > I've one inline comment. > > On Wed, 2018-01-31 at 15:28 +0800, houlong@mediatek.com wrote: > > From: "hs.l...@mediatek.com" > > > > This patch is first version of Mediatek Command Queue(CMDQ) driver. The > > CMDQ is used to help write registers with critical time limitation, > > such as updating display configuration during the vblank. It controls > > Global Command Engine (GCE) hardware to achieve this requirement. > > Currently, CMDQ only supports display related hardwares, but we expect > > it can be extended to other hardwares for future requirements. > > > > Signed-off-by: Houlong Wei > > Signed-off-by: HS Liao > > Signed-off-by: CK Hu > > --- > > drivers/mailbox/Kconfig | 10 + > > drivers/mailbox/Makefile |2 + > > drivers/mailbox/mtk-cmdq-mailbox.c | 594 > > ++ > > include/linux/mailbox/mtk-cmdq-mailbox.h | 77 > > 4 files changed, 683 insertions(+) > > create mode 100644 drivers/mailbox/mtk-cmdq-mailbox.c > > create mode 100644 include/linux/mailbox/mtk-cmdq-mailbox.h > > > > diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig > > index ba2f152..43bb26f 100644 > > --- a/drivers/mailbox/Kconfig > > +++ b/drivers/mailbox/Kconfig > > @@ -171,4 +171,14 @@ config BCM_FLEXRM_MBOX > > Mailbox implementation of the Broadcom FlexRM ring manager, > > which provides access to various offload engines on Broadcom > > SoCs. Say Y here if you want to use the Broadcom FlexRM. > > + > > +config MTK_CMDQ_MBOX > > + bool "MediaTek CMDQ Mailbox Support" > > + depends on ARM64 && ( ARCH_MEDIATEK || COMPILE_TEST ) > > + select MTK_INFRACFG > > + help > > + Say yes here to add support for the MediaTek Command Queue (CMDQ) > > + mailbox driver. The CMDQ is used to help read/write registers with > > + critical time limitation, such as updating display configuration > > + during the vblank. > > endif > > diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile > > index 4896f8d..484d341 100644 > > --- a/drivers/mailbox/Makefile > > +++ b/drivers/mailbox/Makefile > > @@ -36,3 +36,5 @@ obj-$(CONFIG_BCM_FLEXRM_MBOX) += bcm-flexrm-mailbox.o > > obj-$(CONFIG_QCOM_APCS_IPC)+= qcom-apcs-ipc-mailbox.o > > > > obj-$(CONFIG_TEGRA_HSP_MBOX) += tegra-hsp.o > > + > > +obj-$(CONFIG_MTK_CMDQ_MBOX)+= mtk-cmdq-mailbox.o > > diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c > > b/drivers/mailbox/mtk-cmdq-mailbox.c > > new file mode 100644 > > index 000..394a335 > > --- /dev/null > > +++ b/drivers/mailbox/mtk-cmdq-mailbox.c > > @@ -0,0 +1,594 @@ > > +/* > > + * Copyright (c) 2015 MediaTek Inc. > > + * > > + * This program is free software; you can redistribute it and/or modify > > + * it under the terms of the GNU General Public License version 2 as > > + * published by the Free Software Foundation. > > + * > > + * This program is distributed in the hope that it will be useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#define CMDQ_THR_MAX_COUNT 16 > > +#define CMDQ_OP_CODE_MASK (0xff << CMDQ_OP_CODE_SHIFT) > > +#define CMDQ_TIMEOUT_MS1000 > > +#define CMDQ_IRQ_MASK 0x > > +#define CMDQ_NUM_CMD(t)(t->cmd_buf_size / > > CMDQ_INST_SIZE) > > + > > +#define CMDQ_CURR_IRQ_STATUS 0x10 > > +#define CMDQ_THR_SLOT_CYCLES 0x30 > > + > > +#define CMDQ_THR_BASE 0x100 > > +#define CMDQ_THR_SIZE 0x80 > > +#define CMDQ_THR_WARM_RESET0x00 > > +#define CMDQ_THR_ENABLE_TASK 0x04 > > +#define CMDQ_THR_SUSPEND_TASK 0x08 > > +#define CMDQ_THR_CURR_STATUS 0x0c > > +#define CMDQ_THR_IRQ_STATUS0x10 > > +#define CMDQ_THR_IRQ_ENABLE0x14 > > +#define CMDQ_THR_CURR_ADDR 0
Re: [PATCH v22 4/4] soc: mediatek: Add Mediatek CMDQ helper
On Fri, 2018-06-29 at 17:22 +0800, CK Hu wrote: > Hi, Houlong: > > On Fri, 2018-06-29 at 07:32 +0800, houlong wei wrote: > > On Thu, 2018-06-28 at 18:41 +0800, CK Hu wrote: > > > Hi, Houlong: > > > > > > Some inline comment. > > > > > > On Wed, 2018-06-27 at 19:16 +0800, Houlong Wei wrote: > > > > Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. > > > > > > > > Signed-off-by: Houlong Wei > > > > Signed-off-by: HS Liao > > > > --- > > > > drivers/soc/mediatek/Kconfig | 12 ++ > > > > drivers/soc/mediatek/Makefile |1 + > > > > drivers/soc/mediatek/mtk-cmdq-helper.c | 258 > > > > > > > > include/linux/soc/mediatek/mtk-cmdq.h | 132 > > > > 4 files changed, 403 insertions(+) > > > > create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c > > > > create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h > > > > > > > > diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig > > > > index a7d0667..17bd759 100644 > > > > --- a/drivers/soc/mediatek/Kconfig > > > > +++ b/drivers/soc/mediatek/Kconfig > > > > @@ -4,6 +4,18 @@ > > > > menu "MediaTek SoC drivers" > > > > depends on ARCH_MEDIATEK || COMPILE_TEST > > > > > > > > > [...] > > > > > + > > > > +static int cmdq_pkt_finalize(struct cmdq_pkt *pkt) > > > > +{ > > > > + int err; > > > > + > > > > + if (cmdq_pkt_is_finalized(pkt)) > > > > + return 0; > > > > + > > > > + /* insert EOC and generate IRQ for each command iteration */ > > > > + err = cmdq_pkt_append_command(pkt, CMDQ_CODE_EOC, 0, > > > > CMDQ_EOC_IRQ_EN); > > > > + if (err < 0) > > > > + return err; > > > > + > > > > + /* JUMP to end */ > > > > + err = cmdq_pkt_append_command(pkt, CMDQ_CODE_JUMP, 0, > > > > CMDQ_JUMP_PASS); > > > > + if (err < 0) > > > > + return err; > > > > + > > > > + return 0; > > > > +} > > > > + > > > > +int cmdq_pkt_flush_async(struct cmdq_client *client, struct cmdq_pkt > > > > *pkt, > > > > +cmdq_async_flush_cb cb, void *data) > > > > +{ > > > > + int err; > > > > + struct device *dev; > > > > + dma_addr_t dma_addr; > > > > + > > > > + err = cmdq_pkt_finalize(pkt); > > > > + if (err < 0) > > > > + return err; > > > > + > > > > + dev = client->chan->mbox->dev; > > > > + dma_addr = dma_map_single(dev, pkt->va_base, pkt->cmd_buf_size, > > > > + DMA_TO_DEVICE); > > > > > > You map here, but I could not find unmap, so the unmap should be done in > > > client driver. I would prefer a symmetric map/unmap which means that > > > both map and unmap are done in client driver. I think you put map here > > > because you should map after finalize. > > > > The unmap is done before callback to client, in function > > cmdq_task_exec_done, mtk-cmdq-mailbox.c. > > You put unmap in mailbox controller, and map here (here would be mailbox > client), so this is not symmetric. If the code is asymmetric, it's easy > to cause bug and not easy to maintain. So I would like move both > map/unmap to client driver. > Since map/unmap is common code for client drivers, can we move unmap to CMDQ helper and do not put in client driver? > > > > > Therefore, export > > > cmdq_pkt_finalize() to client driver and let client do finalize, so > > > there is no finalize in flush function. This method have a benefit that > > > if client reuse command buffer, it need not to map/unmap frequently. > > > > If client reuse command buffer or cmdq_pkt(command queue packet), client > > will add new commands to the cmdq_pkt, so map/unmap are necessary for > > each cmdq_pkt flush. > > If the buffer size is 4K bytes, client driver could map the whole 4K at > initialization. Before it write new command, it call > dma_sync_single_for_cpu(), after it write new command, it call > dma_sync_single_for_dev
Re: [PATCH v22 2/4] mailbox: mediatek: Add Mediatek CMDQ driver
On Fri, 2018-06-29 at 15:08 +0800, CK Hu wrote: > Hi, Houlong: > > Some inline comment. > > On Wed, 2018-06-27 at 19:16 +0800, Houlong Wei wrote: > > This patch is first version of Mediatek Command Queue(CMDQ) driver. The > > CMDQ is used to help write registers with critical time limitation, > > such as updating display configuration during the vblank. It controls > > Global Command Engine (GCE) hardware to achieve this requirement. > > Currently, CMDQ only supports display related hardwares, but we expect > > it can be extended to other hardwares for future requirements. > > > > Signed-off-by: Houlong Wei > > Signed-off-by: HS Liao > > Signed-off-by: CK Hu > > --- > > drivers/mailbox/Kconfig | 10 + > > drivers/mailbox/Makefile |2 + > > drivers/mailbox/mtk-cmdq-mailbox.c | 634 > > ++ > > include/linux/mailbox/mtk-cmdq-mailbox.h | 70 > > 4 files changed, 716 insertions(+) > > create mode 100644 drivers/mailbox/mtk-cmdq-mailbox.c > > create mode 100644 include/linux/mailbox/mtk-cmdq-mailbox.h > > > > [...] > > > + > > +static int cmdq_thread_reset(struct cmdq *cmdq, struct cmdq_thread *thread) > > +{ > > + u32 warm_reset; > > + > > + writel(CMDQ_THR_DO_WARM_RESET, thread->base + CMDQ_THR_WARM_RESET); > > + if (readl_poll_timeout_atomic(thread->base + CMDQ_THR_WARM_RESET, > > + warm_reset, !(warm_reset & CMDQ_THR_DO_WARM_RESET), > > + 0, 10)) { > > + dev_err(cmdq->mbox.dev, "reset GCE thread 0x%x failed\n", > > + (u32)(thread->base - cmdq->base)); > > + return -EFAULT; > > + } > > + writel(CMDQ_THR_ACTIVE_SLOT_CYCLES, cmdq->base + CMDQ_THR_SLOT_CYCLES); > > The CMDQ_THR_SLOT_CYCLES looks like not relevant to reset. Maybe you > just need to set this value when startup. Will move configuration of CMDQ_THR_SLOT_CYCLES to cmdq_xlate() where is startup of a GCE thread. > > > + > > + return 0; > > +} > > + > > [...] > > > + > > +static void cmdq_task_exec(struct cmdq_pkt *pkt, struct cmdq_thread > > *thread) > > +{ > > + struct cmdq *cmdq; > > + struct cmdq_task *task; > > + unsigned long curr_pa, end_pa; > > + > > + cmdq = dev_get_drvdata(thread->chan->mbox->dev); > > + > > + /* Client should not flush new tasks if suspended. */ > > + WARN_ON(cmdq->suspended); > > + > > + task = kzalloc(sizeof(*task), GFP_ATOMIC); > > + task->cmdq = cmdq; > > + INIT_LIST_HEAD(>list_entry); > > + task->pa_base = pkt->pa_base; > > + task->thread = thread; > > + task->pkt = pkt; > > + > > + if (list_empty(>task_busy_list)) { > > + WARN_ON(clk_enable(cmdq->clock) < 0); > > + WARN_ON(cmdq_thread_reset(cmdq, thread) < 0); > > + > > + writel(task->pa_base, thread->base + CMDQ_THR_CURR_ADDR); > > + writel(task->pa_base + pkt->cmd_buf_size, > > + thread->base + CMDQ_THR_END_ADDR); > > + writel(thread->priority, thread->base + CMDQ_THR_PRIORITY); > > + writel(CMDQ_THR_IRQ_EN, thread->base + CMDQ_THR_IRQ_ENABLE); > > + writel(CMDQ_THR_ENABLED, thread->base + CMDQ_THR_ENABLE_TASK); > > + > > + if (thread->timeout_ms != CMDQ_NO_TIMEOUT) > > + mod_timer(>timeout, > > + jiffies + msecs_to_jiffies(thread->timeout_ms)); > > I think the timeout processing should be done by client driver. The > total time to execute a command buffer does not depend on GCE HW speed > because the WFE (wait for event) command would wait for client HW event, > so the total time depend on how long a client HW send this event to GCE > and the timeout processing should be client driver's job. Each client > may have different timeout processing mechanism, for example, if display > could dynamic change panel frame rate between 120Hz and 60Hz, and the > timeout time is 2 frame, so it may dynamically change timeout time > between 17ms and 33ms. Another reason is that display have interrupt > every vblank, and it could check timeout in that interrupt, so the timer > in cmdq driver looks redundant. Because each client would define its own > timeout processing mechanism, so it's not wise to put timeout processing > in cmdq driver. The client drivers' owners strongly hope to keep th
Re: [PATCH v22 1/4] dt-bindings: soc: Add documentation for the MediaTek GCE unit
On Tue, 2018-07-03 at 10:30 +0800, Rob Herring wrote: > On Wed, Jun 27, 2018 at 07:16:09PM +0800, Houlong Wei wrote: > > This adds documentation for the MediaTek Global Command Engine (GCE) unit > > found in MT8173 SoCs. > > > > Signed-off-by: Houlong Wei > > Signed-off-by: HS Liao > > --- > > Hi Rob, > > I don't add your ACK in this version since the dt-binding description > > has been changed. Thanks. > > --- > > .../devicetree/bindings/mailbox/mtk-gce.txt| 65 > > > > include/dt-bindings/gce/mt8173-gce.h | 48 +++ > > 2 files changed, 113 insertions(+) > > create mode 100644 Documentation/devicetree/bindings/mailbox/mtk-gce.txt > > create mode 100644 include/dt-bindings/gce/mt8173-gce.h > > > > diff --git a/Documentation/devicetree/bindings/mailbox/mtk-gce.txt > > b/Documentation/devicetree/bindings/mailbox/mtk-gce.txt > > new file mode 100644 > > index 000..26f65a4 > > --- /dev/null > > +++ b/Documentation/devicetree/bindings/mailbox/mtk-gce.txt > > @@ -0,0 +1,65 @@ > > +MediaTek GCE > > +=== > > + > > +The Global Command Engine (GCE) is used to help read/write registers with > > +critical time limitation, such as updating display configuration during the > > +vblank. The GCE can be used to implement the Command Queue (CMDQ) driver. > > + > > +CMDQ driver uses mailbox framework for communication. Please refer to > > +mailbox.txt for generic information about mailbox device-tree bindings. > > + > > +Required properties: > > +- compatible: Must be "mediatek,mt8173-gce" > > +- reg: Address range of the GCE unit > > +- interrupts: The interrupt signal from the GCE block > > +- clock: Clocks according to the common clock binding > > +- clock-names: Must be "gce" to stand for GCE clock > > +- thread-num: Maximum threads count of GCE. > > mediatek,thread-num > > Is this needed for anything other than error checking the thread id in > the mbox cells? if that's it, then drop it. > 'thread-num' is used to configure the GCE thread number, which is the channel number of gce mailbox. This property is read in cmdq_probe()/mtk-cmdq-mailbox.c and a mailbox's channel array is allocated according to the number. Since the thread number may be different on different SoC, we wish it could be configured in device tree. > > +- #mbox-cells: Should be 4. > > + < channel timeout priority atomic_exec> > > + phandle: Label name of a gce node. > > + channel: Channel of mailbox. Be equal to the thread id of GCE. > > + timeout: Maximum time of software waiting GCE processing done, in unit > > + of millisecond. > > + priority: Priority of GCE thread. > > + atomic_exec: GCE processing continuous packets of commands in atomic > > + way. > > + > > +Required properties for a client device: > > +- mboxes: Client use mailbox to communicate with GCE, it should have this > > + property and list of phandle, mailbox specifiers. > > +- gce-subsys: Specify the sub-system id which is corresponding to the > > register > > + address. > > What is this for? You mean the new added property 'gce-subsys'? It is used for GCE to distinguish the high 16-bit of a hardware register address. When a client driver packets a register setting into a GCE instruction, it uses a sub-system code and register offset instead of the 32-bit register address. Since sub-system code may be different on different SoC, we wish it could be configured in device tree. > > > + > > +Optional properties for a client device: > > +- gce-event: Specify the event if the client has any. Because the event is > > + parsed by client, so client can replace 'gce-event' with other meaningful > > + name. > > If the client sets the name, then no point having here. It must be > documented in the client binding. But then, what is this for in the > first place? Since display driver will use GCE firstly, so we will move the description to 'Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt' when display driver start using the GCE driver. Is that ok? > > > + > > +Some vaules of properties are defined in 'dt-bindings/gce/mt8173-gce.h'. > > Such as > > +thread number, sub-system ids, thread priority, event ids. > > + > > +Example: > > + > > + gce: gce@10212000 { > > mailbox@... Will do. > > > + compatible = "mediatek,mt8173-gce"; > > + reg = <0 0x10212000 0 0x1000>; &
Re: FW: [PATCH v20 2/4] mailbox: mediatek: Add Mediatek CMDQ driver
Hi Jassi, Sorry for reply so late. According to previous discussion, there are two methods to move dma_map_single() outside of spin_lock. (1) put in mtk-cmdq-helper.c, as described by HS on 2017-02-09. > I think a trade-off solution is to put in mtk-cmdq-helper.c. > Although it is a mailbox client, it is not a CMDQ client. > We can include mailbox_controller.h in mtk-cmdq-helper.c (instead of mtk-cmdq.h), and then map dma at cmdq_pkt_flush_async before mbox_send_message. > pkt->pa_base = dma_map_single(client->chan->mbox->dev, pkt->va_base, > pkt->cmd_buf_size, DMA_TO_DEVICE); (2) schedule a tasklet in send_data(). After internal discussion with HS and other experts, now we prefer method (1). How do you think about it? Thanks Houlong > -Original Message- > From: Horng-Shyang Liao [mailto:hs.l...@mediatek.com] > Sent: Thursday, February 23, 2017 8:48 PM > To: Jassi Brar <jassisinghb...@gmail.com> > Cc: Rob Herring <robh...@kernel.org>; Matthias Brugger > <matthias@gmail.com>; Daniel Kurtz <djku...@chromium.org>; Sascha Hauer > <s.ha...@pengutronix.de>; Devicetree List <devicet...@vger.kernel.org>; Linux > Kernel Mailing List <linux-kernel@vger.kernel.org>; > linux-arm-ker...@lists.infradead.org; linux-media...@lists.infradead.org; > srv_heupstream <srv_heupstr...@mediatek.com>; Sascha Hauer > <ker...@pengutronix.de>; Philipp Zabel <p.za...@pengutronix.de>; Nicolas > Boichat <drink...@chromium.org>; CK Hu (胡俊光) <ck...@mediatek.com>; Cawa Cheng > (鄭曄禧) <cawa.ch...@mediatek.com>; Bibby Hsieh (謝濟遠) > <bibby.hs...@mediatek.com>; YT Shen (沈岳霆) <yt.s...@mediatek.com>; Daoyuan > Huang (黃道原) <daoyuan.hu...@mediatek.com>; Damon Chu (朱峻賢) > <damon@mediatek.com>; Josh-YC Liu (劉育誠) <josh-yc@mediatek.com>; Glory > Hung (洪智瑋) <glory.h...@mediatek.com>; Jiaguang Zhang (张加广) > <jiaguang.zh...@mediatek.com>; Dennis-YC Hsieh (謝宇哲) > <dennis-yc.hs...@mediatek.com>; Monica Wang (王孟婷) <monica.w...@mediatek.com>; > Houlong Wei (魏厚龙) <houlong@mediatek.com>; Hs Liao (廖宏祥) > <hs.l...@mediatek.com> > Subject: Re: [PATCH v20 2/4] mailbox: mediatek: Add Mediatek CMDQ driver > > On Thu, 2017-02-23 at 09:40 +0530, Jassi Brar wrote: > > On Wed, Feb 22, 2017 at 8:42 AM, Horng-Shyang Liao <hs.l...@mediatek.com> > > wrote: > > > On Thu, 2017-02-16 at 21:02 +0530, Jassi Brar wrote: > > >> On Mon, Feb 6, 2017 at 11:07 AM, Horng-Shyang Liao > > >> <hs.l...@mediatek.com> wrote: > > >> > Hi Jassi, > > >> > > > >> > On Wed, 2017-02-01 at 10:52 +0530, Jassi Brar wrote: > > >> >> On Thu, Jan 26, 2017 at 2:07 PM, Horng-Shyang Liao > > >> >> <hs.l...@mediatek.com> wrote: > > >> >> > Hi Jassi, > > >> >> > > > >> >> > On Thu, 2017-01-26 at 10:08 +0530, Jassi Brar wrote: > > >> >> >> On Wed, Jan 4, 2017 at 8:36 AM, HS Liao <hs.l...@mediatek.com> > > >> >> >> wrote: > > >> >> >> > > >> >> >> > diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c > > >> >> >> > b/drivers/mailbox/mtk-cmdq-mailbox.c > > >> >> >> > new file mode 100644 > > >> >> >> > index 000..747bcd3 > > >> >> >> > --- /dev/null > > >> >> >> > +++ b/drivers/mailbox/mtk-cmdq-mailbox.c > > >> >> >> > > >> >> >> ... > > >> >> >> > > >> >> >> > +static void cmdq_task_exec(struct cmdq_pkt *pkt, struct > > >> >> >> > +cmdq_thread *thread) { > > >> >> >> > + struct cmdq *cmdq; > > >> >> >> > + struct cmdq_task *task; > > >> >> >> > + unsigned long curr_pa, end_pa; > > >> >> >> > + > > >> >> >> > + cmdq = dev_get_drvdata(thread->chan->mbox->dev); > > >> >> >> > + > > >> >> >> > + /* Client should not flush new tasks if suspended. */ > > >> >> >> > + WARN_ON(cmdq->suspended); > > >> >> >> > + > > >> >> >> > + task = kzalloc(sizeof(*task), GFP_ATOMIC); > > >> >> >> > + task->cmdq = cmdq; > > >> >> >> > +
Re: FW: [PATCH v20 2/4] mailbox: mediatek: Add Mediatek CMDQ driver
Hi Jassi, There is one request for one GCE h/w buffer which contains a list of registers operation. I will resubmit a version and please review again. Thanks, Houlong On Thu, 2018-01-18 at 16:01 +0800, Jassi Brar wrote: > On Mon, Jan 8, 2018 at 2:08 PM, houlong wei <houlong@mediatek.com> wrote: > > Hi Jassi, > > > > Sorry for reply so late. > > According to previous discussion, there are two methods to move > > dma_map_single() outside of spin_lock. > > (1) put in mtk-cmdq-helper.c, as described by HS on 2017-02-09. > > > I think a trade-off solution is to put in mtk-cmdq-helper.c. > > > Although it is a mailbox client, it is not a CMDQ client. > > > We can include mailbox_controller.h in mtk-cmdq-helper.c (instead of > > mtk-cmdq.h), and then map dma at cmdq_pkt_flush_async before > > mbox_send_message. > > > > > pkt->pa_base = dma_map_single(client->chan->mbox->dev, pkt->va_base, > > > pkt->cmd_buf_size, DMA_TO_DEVICE); > > (2) schedule a tasklet in send_data(). > > > > After internal discussion with HS and other experts, now we prefer > > method (1). > > How do you think about it? > > > I don't exactly see how you mean but please remember send_data() > callback is supposed to be atomic ... it is protected by > spin_lock_irqsave/restore in drivers/mailbox/mailbox.c:msg_submit() > > BTW, how many requests max can be queued in the GCE h/w buffer? > And since it's been over a year now, could you please resubmit after > checking for checkpatch with the --strict option? > > Thanks.
Re: [PATCH v20 2/4] mailbox: mediatek: Add Mediatek CMDQ driver
Hi Jassi, We prefer to use method (1) to move dma_map_single() outside of spin_lock. Do you have any comment about this? Thanks, Houlong On Mon, 2018-01-08 at 16:38 +0800, houlong wei wrote: > Hi Jassi, > > Sorry for reply so late. > According to previous discussion, there are two methods to move > dma_map_single() outside of spin_lock. > (1) put in mtk-cmdq-helper.c, as described by HS on 2017-02-09. > > I think a trade-off solution is to put in mtk-cmdq-helper.c. > > Although it is a mailbox client, it is not a CMDQ client. > > We can include mailbox_controller.h in mtk-cmdq-helper.c (instead of > mtk-cmdq.h), and then map dma at cmdq_pkt_flush_async before > mbox_send_message. > > > pkt->pa_base = dma_map_single(client->chan->mbox->dev, pkt->va_base, > > pkt->cmd_buf_size, DMA_TO_DEVICE); > (2) schedule a tasklet in send_data(). > > After internal discussion with HS and other experts, now we prefer > method (1). > How do you think about it? > > Thanks > Houlong > > > > -Original Message- > > From: Horng-Shyang Liao [mailto:hs.l...@mediatek.com] > > Sent: Thursday, February 23, 2017 8:48 PM > > To: Jassi Brar <jassisinghb...@gmail.com> > > Cc: Rob Herring <robh...@kernel.org>; Matthias Brugger > > <matthias@gmail.com>; Daniel Kurtz <djku...@chromium.org>; Sascha Hauer > > <s.ha...@pengutronix.de>; Devicetree List <devicet...@vger.kernel.org>; > > Linux Kernel Mailing List <linux-kernel@vger.kernel.org>; > > linux-arm-ker...@lists.infradead.org; linux-media...@lists.infradead.org; > > srv_heupstream <srv_heupstr...@mediatek.com>; Sascha Hauer > > <ker...@pengutronix.de>; Philipp Zabel <p.za...@pengutronix.de>; Nicolas > > Boichat <drink...@chromium.org>; CK Hu (胡俊光) <ck...@mediatek.com>; Cawa > > Cheng (鄭曄禧) <cawa.ch...@mediatek.com>; Bibby Hsieh (謝濟遠) > > <bibby.hs...@mediatek.com>; YT Shen (沈岳霆) <yt.s...@mediatek.com>; Daoyuan > > Huang (黃道原) <daoyuan.hu...@mediatek.com>; Damon Chu (朱峻賢) > > <damon@mediatek.com>; Josh-YC Liu (劉育誠) <josh-yc@mediatek.com>; > > Glory Hung (洪智瑋) <glory.h...@mediatek.com>; Jiaguang Zhang (张加广) > > <jiaguang.zh...@mediatek.com>; Dennis-YC Hsieh (謝宇哲) > > <dennis-yc.hs...@mediatek.com>; Monica Wang (王孟婷) > > <monica.w...@mediatek.com>; Houlong Wei (魏厚龙) <houlong@mediatek.com>; > > Hs Liao (廖宏祥) <hs.l...@mediatek.com> > > Subject: Re: [PATCH v20 2/4] mailbox: mediatek: Add Mediatek CMDQ driver > > > > On Thu, 2017-02-23 at 09:40 +0530, Jassi Brar wrote: > > > On Wed, Feb 22, 2017 at 8:42 AM, Horng-Shyang Liao <hs.l...@mediatek.com> > > > wrote: > > > > On Thu, 2017-02-16 at 21:02 +0530, Jassi Brar wrote: > > > >> On Mon, Feb 6, 2017 at 11:07 AM, Horng-Shyang Liao > > > >> <hs.l...@mediatek.com> wrote: > > > >> > Hi Jassi, > > > >> > > > > >> > On Wed, 2017-02-01 at 10:52 +0530, Jassi Brar wrote: > > > >> >> On Thu, Jan 26, 2017 at 2:07 PM, Horng-Shyang Liao > > > >> >> <hs.l...@mediatek.com> wrote: > > > >> >> > Hi Jassi, > > > >> >> > > > > >> >> > On Thu, 2017-01-26 at 10:08 +0530, Jassi Brar wrote: > > > >> >> >> On Wed, Jan 4, 2017 at 8:36 AM, HS Liao <hs.l...@mediatek.com> > > > >> >> >> wrote: > > > >> >> >> > > > >> >> >> > diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c > > > >> >> >> > b/drivers/mailbox/mtk-cmdq-mailbox.c > > > >> >> >> > new file mode 100644 > > > >> >> >> > index 000..747bcd3 > > > >> >> >> > --- /dev/null > > > >> >> >> > +++ b/drivers/mailbox/mtk-cmdq-mailbox.c > > > >> >> >> > > > >> >> >> ... > > > >> >> >> > > > >> >> >> > +static void cmdq_task_exec(struct cmdq_pkt *pkt, struct > > > >> >> >> > +cmdq_thread *thread) { > > > >> >> >> > + struct cmdq *cmdq; > > > >> >> >> > + struct cmdq_task *task; > > > >> >> >> > + unsigned long curr_pa, end_pa; > > > >> >> >> > + > > > >>
Re: FW: [PATCH v20 2/4] mailbox: mediatek: Add Mediatek CMDQ driver
Sorry to send the mail again because I missed some mail lists by mistake. Hi Jassi, We prefer to use method (1) to move dma_map_single() outside of spin_lock. Do you have any comment about this? Thanks, Houlong On Mon, 2018-01-08 at 16:38 +0800, houlong wei wrote: > Hi Jassi, > > Sorry for reply so late. > According to previous discussion, there are two methods to move > dma_map_single() outside of spin_lock. > (1) put in mtk-cmdq-helper.c, as described by HS on 2017-02-09. > > I think a trade-off solution is to put in mtk-cmdq-helper.c. > > Although it is a mailbox client, it is not a CMDQ client. > > We can include mailbox_controller.h in mtk-cmdq-helper.c (instead of > mtk-cmdq.h), and then map dma at cmdq_pkt_flush_async before > mbox_send_message. > > > pkt->pa_base = dma_map_single(client->chan->mbox->dev, pkt->va_base, > > pkt->cmd_buf_size, DMA_TO_DEVICE); > (2) schedule a tasklet in send_data(). > > After internal discussion with HS and other experts, now we prefer > method (1). > How do you think about it? > > Thanks > Houlong > > > > -Original Message- > > From: Horng-Shyang Liao [mailto:hs.l...@mediatek.com] > > Sent: Thursday, February 23, 2017 8:48 PM > > To: Jassi Brar <jassisinghb...@gmail.com> > > Cc: Rob Herring <robh...@kernel.org>; Matthias Brugger > > <matthias@gmail.com>; Daniel Kurtz <djku...@chromium.org>; Sascha Hauer > > <s.ha...@pengutronix.de>; Devicetree List <devicet...@vger.kernel.org>; > > Linux Kernel Mailing List <linux-kernel@vger.kernel.org>; > > linux-arm-ker...@lists.infradead.org; linux-media...@lists.infradead.org; > > srv_heupstream <srv_heupstr...@mediatek.com>; Sascha Hauer > > <ker...@pengutronix.de>; Philipp Zabel <p.za...@pengutronix.de>; Nicolas > > Boichat <drink...@chromium.org>; CK Hu (胡俊光) <ck...@mediatek.com>; Cawa > > Cheng (鄭曄禧) <cawa.ch...@mediatek.com>; Bibby Hsieh (謝濟遠) > > <bibby.hs...@mediatek.com>; YT Shen (沈岳霆) <yt.s...@mediatek.com>; Daoyuan > > Huang (黃道原) <daoyuan.hu...@mediatek.com>; Damon Chu (朱峻賢) > > <damon@mediatek.com>; Josh-YC Liu (劉育誠) <josh-yc@mediatek.com>; > > Glory Hung (洪智瑋) <glory.h...@mediatek.com>; Jiaguang Zhang (张加广) > > <jiaguang.zh...@mediatek.com>; Dennis-YC Hsieh (謝宇哲) > > <dennis-yc.hs...@mediatek.com>; Monica Wang (王孟婷) > > <monica.w...@mediatek.com>; Houlong Wei (魏厚龙) <houlong@mediatek.com>; > > Hs Liao (廖宏祥) <hs.l...@mediatek.com> > > Subject: Re: [PATCH v20 2/4] mailbox: mediatek: Add Mediatek CMDQ driver > > > > On Thu, 2017-02-23 at 09:40 +0530, Jassi Brar wrote: > > > On Wed, Feb 22, 2017 at 8:42 AM, Horng-Shyang Liao <hs.l...@mediatek.com> > > > wrote: > > > > On Thu, 2017-02-16 at 21:02 +0530, Jassi Brar wrote: > > > >> On Mon, Feb 6, 2017 at 11:07 AM, Horng-Shyang Liao > > > >> <hs.l...@mediatek.com> wrote: > > > >> > Hi Jassi, > > > >> > > > > >> > On Wed, 2017-02-01 at 10:52 +0530, Jassi Brar wrote: > > > >> >> On Thu, Jan 26, 2017 at 2:07 PM, Horng-Shyang Liao > > > >> >> <hs.l...@mediatek.com> wrote: > > > >> >> > Hi Jassi, > > > >> >> > > > > >> >> > On Thu, 2017-01-26 at 10:08 +0530, Jassi Brar wrote: > > > >> >> >> On Wed, Jan 4, 2017 at 8:36 AM, HS Liao <hs.l...@mediatek.com> > > > >> >> >> wrote: > > > >> >> >> > > > >> >> >> > diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c > > > >> >> >> > b/drivers/mailbox/mtk-cmdq-mailbox.c > > > >> >> >> > new file mode 100644 > > > >> >> >> > index 000..747bcd3 > > > >> >> >> > --- /dev/null > > > >> >> >> > +++ b/drivers/mailbox/mtk-cmdq-mailbox.c > > > >> >> >> > > > >> >> >> ... > > > >> >> >> > > > >> >> >> > +static void cmdq_task_exec(struct cmdq_pkt *pkt, struct > > > >> >> >> > +cmdq_thread *thread) { > > > >> >> >> > + struct cmdq *cmdq; > > > >> >> >> > + struct cmdq_task *task; > > > >> >> >> > + unsigned long curr_p
Re: [PATCH v21 4/4] soc: mediatek: Add Mediatek CMDQ helper
On Tue, 2018-02-06 at 10:52 +0800, CK Hu wrote: > Hi, Houlong: > > I've some inline comment. > > On Wed, 2018-01-31 at 15:28 +0800, houlong@mediatek.com wrote: > > From: "hs.l...@mediatek.com" <hs.l...@mediatek.com> > > > > Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. > > > > Signed-off-by: Houlong Wei <houlong@mediatek.com> > > Signed-off-by: HS Liao <hs.l...@mediatek.com> > > --- > > drivers/soc/mediatek/Kconfig | 12 ++ > > drivers/soc/mediatek/Makefile |1 + > > drivers/soc/mediatek/mtk-cmdq-helper.c | 322 > > > > include/linux/soc/mediatek/mtk-cmdq.h | 174 + > > 4 files changed, 509 insertions(+) > > create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c > > create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h > > > > diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig > > index a7d0667..e66582e 100644 > > --- a/drivers/soc/mediatek/Kconfig > > +++ b/drivers/soc/mediatek/Kconfig > > @@ -4,6 +4,18 @@ > > menu "MediaTek SoC drivers" > > depends on ARCH_MEDIATEK || COMPILE_TEST > > > > +config MTK_CMDQ > > +bool "MediaTek CMDQ Support" > > +depends on ARM64 && ( ARCH_MEDIATEK || COMPILE_TEST ) > > +select MAILBOX > > +select MTK_CMDQ_MBOX > > +select MTK_INFRACFG > > +help > > + Say yes here to add support for the MediaTek Command Queue (CMDQ) > > + driver. The CMDQ is used to help read/write registers with critical > > + time limitation, such as updating display configuration during the > > + vblank. > > + > > config MTK_INFRACFG > > bool "MediaTek INFRACFG Support" > > select REGMAP > > diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile > > index 12998b0..64ce5ee 100644 > > --- a/drivers/soc/mediatek/Makefile > > +++ b/drivers/soc/mediatek/Makefile > > @@ -1,3 +1,4 @@ > > +obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o > > obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o > > obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o > > obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o > > diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c > > b/drivers/soc/mediatek/mtk-cmdq-helper.c > > new file mode 100644 > > index 000..80d0558 > > --- /dev/null > > +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c > > @@ -0,0 +1,322 @@ > > +/* > > + * Copyright (c) 2015 MediaTek Inc. > > + * > > + * This program is free software; you can redistribute it and/or modify > > + * it under the terms of the GNU General Public License version 2 as > > + * published by the Free Software Foundation. > > + * > > + * This program is distributed in the hope that it will be useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#define CMDQ_ARG_A_WRITE_MASK0x > > +#define CMDQ_WRITE_ENABLE_MASKBIT(0) > > +#define CMDQ_EOC_IRQ_ENBIT(0) > > +#define CMDQ_EOC_CMD((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \ > > +<< 32 | CMDQ_EOC_IRQ_EN) > > + > > +struct cmdq_subsys { > > +u32base; > > +intid; > > +}; > > + > > +static const struct cmdq_subsys gce_subsys[] = { > > +{0x1400, 1}, > > +{0x1401, 2}, > > +{0x1402, 3}, > > +}; > > I think subsys definition varies by different SoC, so it's better to > pass these definition from device tree to driver (client driver), and > client driver pass this subsys in the related interface. For example, > > in include/dt-bindings/gce/mt8173-gce.h, you define > > #define GCE_SUBSYS_14001 > #define GCE_SUBSYS_14012 > #define GCE_SUBSYS_14023 > > in device tree, place the subsys definition in client device node, > > #include "dt-bindings/gce/mt8173-gce.h" > > ovl0: ovl@1400c000 { > compatible = "mediatek,mt8173-disp-ovl"; > gce-subsys = ; > ... > }; > > And client driver pass subsys in the related interface, > > int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 > value); > > So, for another SoC, you just need to modify device tree and you do not > need to modify driver. > > + > > +static int cmdq_sub
Re: [PATCH v23 3/4] arm64: dts: mt8173: Add GCE node
On Wed, 2018-07-25 at 09:26 +0800, Houlong Wei wrote: > This patch adds the device node of the GCE hardware for CMDQ module. > > Signed-off-by: Houlong Wei > Signed-off-by: HS Liao > --- > arch/arm64/boot/dts/mediatek/mt8173.dtsi | 10 ++ > 1 file changed, 10 insertions(+) > > diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi > b/arch/arm64/boot/dts/mediatek/mt8173.dtsi > index 94597e3..97b1ec6 100644 > --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi > +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi > @@ -18,6 +18,7 @@ > #include > #include > #include > +#include > #include "mt8173-pinfunc.h" > > / { > @@ -519,6 +520,15 @@ > status = "disabled"; > }; > > + gce: mailbox@10212000 { > + compatible = "mediatek,mt8173-gce"; > + reg = <0 0x10212000 0 0x1000>; > + interrupts = ; > + clocks = < CLK_INFRA_GCE>; > + clock-names = "gce"; > + #mbox-cells = <3>; > + }; > + > mipi_tx0: mipi-dphy@10215000 { > compatible = "mediatek,mt8173-mipi-tx"; > reg = <0 0x10215000 0 0x1000>; Hi Matthias, Could you please review this patch when you are available? Thanks a lot.
Re: [PATCH v23 4/4] soc: mediatek: Add Mediatek CMDQ helper
On Wed, 2018-07-25 at 09:26 +0800, Houlong Wei wrote: > Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. > > Signed-off-by: Houlong Wei > Signed-off-by: HS Liao > --- > drivers/soc/mediatek/Kconfig | 12 ++ > drivers/soc/mediatek/Makefile |1 + > drivers/soc/mediatek/mtk-cmdq-helper.c | 291 > > include/linux/soc/mediatek/mtk-cmdq.h | 135 +++ > 4 files changed, 439 insertions(+) > create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c > create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h > > diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig > index a7d0667..17bd759 100644 > --- a/drivers/soc/mediatek/Kconfig > +++ b/drivers/soc/mediatek/Kconfig > @@ -4,6 +4,18 @@ > menu "MediaTek SoC drivers" > depends on ARCH_MEDIATEK || COMPILE_TEST > > +config MTK_CMDQ > + tristate "MediaTek CMDQ Support" > + depends on ARCH_MEDIATEK || COMPILE_TEST > + select MAILBOX > + select MTK_CMDQ_MBOX > + select MTK_INFRACFG > + help > + Say yes here to add support for the MediaTek Command Queue (CMDQ) > + driver. The CMDQ is used to help read/write registers with critical > + time limitation, such as updating display configuration during the > + vblank. > + > config MTK_INFRACFG > bool "MediaTek INFRACFG Support" > select REGMAP > diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile > index 12998b0..64ce5ee 100644 > --- a/drivers/soc/mediatek/Makefile > +++ b/drivers/soc/mediatek/Makefile > @@ -1,3 +1,4 @@ > +obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o > obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o > obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o > obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o > diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c > b/drivers/soc/mediatek/mtk-cmdq-helper.c > new file mode 100644 > index 000..e4dbb7e > --- /dev/null > +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c > @@ -0,0 +1,291 @@ > +// SPDX-License-Identifier: GPL-2.0 > +// > +// Copyright (c) 2018 MediaTek Inc. > + > +#include > +#include > +#include > +#include > +#include > + > +#define CMDQ_ARG_A_WRITE_MASK0x > +#define CMDQ_WRITE_ENABLE_MASK BIT(0) > +#define CMDQ_EOC_IRQ_EN BIT(0) > +#define CMDQ_EOC_CMD ((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \ > + << 32 | CMDQ_EOC_IRQ_EN) > + > +static void cmdq_client_timeout(struct timer_list *t) > +{ > + struct cmdq_client *client = from_timer(client, t, timer); > + > + dev_err(client->client.dev, "cmdq timeout!\n"); > +} > + > +struct cmdq_client *cmdq_mbox_create(struct device *dev, int index, u32 > timeout) > +{ > + struct cmdq_client *client; > + > + client = kzalloc(sizeof(*client), GFP_KERNEL); > + if (!client) > + return (struct cmdq_client *)-ENOMEM; > + > + client->timeout_ms = timeout; > + if (timeout != CMDQ_NO_TIMEOUT) { > + spin_lock_init(>lock); > + timer_setup(>timer, cmdq_client_timeout, 0); > + } > + client->pkt_cnt = 0; > + client->client.dev = dev; > + client->client.tx_block = false; > + client->chan = mbox_request_channel(>client, index); > + > + if (IS_ERR(client->chan)) { > + long err = 0; > + > + dev_err(dev, "failed to request channel\n"); > + err = PTR_ERR(client->chan); > + kfree(client); > + > + return (struct cmdq_client *)err; > + } > + > + return client; > +} > +EXPORT_SYMBOL(cmdq_mbox_create); > + > +void cmdq_mbox_destroy(struct cmdq_client *client) > +{ > + if (client->timeout_ms != CMDQ_NO_TIMEOUT) { > + spin_lock(>lock); > + del_timer_sync(>timer); > + spin_unlock(>lock); > + } > + mbox_free_channel(client->chan); > + kfree(client); > +} > +EXPORT_SYMBOL(cmdq_mbox_destroy); > + > +int cmdq_pkt_create(struct cmdq_client *client, struct cmdq_pkt **pkt_ptr, > + size_t size) > +{ > + struct cmdq_pkt *pkt; > + struct device *dev; > + dma_addr_t dma_addr; > + > + pkt = kzalloc(sizeof(*pkt), GFP_KERNEL); > + if (!pkt) > + return -ENOMEM; > + pkt->va_base = kzalloc(size, GFP_KERNEL); > + if (!pkt->va_base) { > + kfree(pkt); > + return -ENOMEM; > + } > + pkt-&g
[PATCH] mailbox: mediatek: Add check for possible failure of kzalloc
The patch 623a6143a845("mailbox: mediatek: Add Mediatek CMDQ driver") introduce the following static checker warning: drivers/mailbox/mtk-cmdq-mailbox.c:366 cmdq_mbox_send_data() error: potential null dereference 'task'. (kzalloc returns null) Fixes: 623a6143a845 ("mailbox: mediatek: Add Mediatek CMDQ driver") Reported-by: Dan Carpenter Signed-off-by: Houlong Wei --- drivers/mailbox/mtk-cmdq-mailbox.c |3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c index aec46d5..f7cc29c 100644 --- a/drivers/mailbox/mtk-cmdq-mailbox.c +++ b/drivers/mailbox/mtk-cmdq-mailbox.c @@ -363,6 +363,9 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data) WARN_ON(cmdq->suspended); task = kzalloc(sizeof(*task), GFP_ATOMIC); + if (!task) + return -ENOMEM; + task->cmdq = cmdq; INIT_LIST_HEAD(>list_entry); task->pa_base = pkt->pa_base; -- 1.7.9.5
[PATCH v23 4/4] soc: mediatek: Add Mediatek CMDQ helper
Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. Signed-off-by: Houlong Wei Signed-off-by: HS Liao --- drivers/soc/mediatek/Kconfig | 12 ++ drivers/soc/mediatek/Makefile |1 + drivers/soc/mediatek/mtk-cmdq-helper.c | 291 include/linux/soc/mediatek/mtk-cmdq.h | 135 +++ 4 files changed, 439 insertions(+) create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig index a7d0667..17bd759 100644 --- a/drivers/soc/mediatek/Kconfig +++ b/drivers/soc/mediatek/Kconfig @@ -4,6 +4,18 @@ menu "MediaTek SoC drivers" depends on ARCH_MEDIATEK || COMPILE_TEST +config MTK_CMDQ + tristate "MediaTek CMDQ Support" + depends on ARCH_MEDIATEK || COMPILE_TEST + select MAILBOX + select MTK_CMDQ_MBOX + select MTK_INFRACFG + help + Say yes here to add support for the MediaTek Command Queue (CMDQ) + driver. The CMDQ is used to help read/write registers with critical + time limitation, such as updating display configuration during the + vblank. + config MTK_INFRACFG bool "MediaTek INFRACFG Support" select REGMAP diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile index 12998b0..64ce5ee 100644 --- a/drivers/soc/mediatek/Makefile +++ b/drivers/soc/mediatek/Makefile @@ -1,3 +1,4 @@ +obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c new file mode 100644 index 000..e4dbb7e --- /dev/null +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -0,0 +1,291 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2018 MediaTek Inc. + +#include +#include +#include +#include +#include + +#define CMDQ_ARG_A_WRITE_MASK 0x +#define CMDQ_WRITE_ENABLE_MASK BIT(0) +#define CMDQ_EOC_IRQ_ENBIT(0) +#define CMDQ_EOC_CMD ((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \ + << 32 | CMDQ_EOC_IRQ_EN) + +static void cmdq_client_timeout(struct timer_list *t) +{ + struct cmdq_client *client = from_timer(client, t, timer); + + dev_err(client->client.dev, "cmdq timeout!\n"); +} + +struct cmdq_client *cmdq_mbox_create(struct device *dev, int index, u32 timeout) +{ + struct cmdq_client *client; + + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client) + return (struct cmdq_client *)-ENOMEM; + + client->timeout_ms = timeout; + if (timeout != CMDQ_NO_TIMEOUT) { + spin_lock_init(>lock); + timer_setup(>timer, cmdq_client_timeout, 0); + } + client->pkt_cnt = 0; + client->client.dev = dev; + client->client.tx_block = false; + client->chan = mbox_request_channel(>client, index); + + if (IS_ERR(client->chan)) { + long err = 0; + + dev_err(dev, "failed to request channel\n"); + err = PTR_ERR(client->chan); + kfree(client); + + return (struct cmdq_client *)err; + } + + return client; +} +EXPORT_SYMBOL(cmdq_mbox_create); + +void cmdq_mbox_destroy(struct cmdq_client *client) +{ + if (client->timeout_ms != CMDQ_NO_TIMEOUT) { + spin_lock(>lock); + del_timer_sync(>timer); + spin_unlock(>lock); + } + mbox_free_channel(client->chan); + kfree(client); +} +EXPORT_SYMBOL(cmdq_mbox_destroy); + +int cmdq_pkt_create(struct cmdq_client *client, struct cmdq_pkt **pkt_ptr, + size_t size) +{ + struct cmdq_pkt *pkt; + struct device *dev; + dma_addr_t dma_addr; + + pkt = kzalloc(sizeof(*pkt), GFP_KERNEL); + if (!pkt) + return -ENOMEM; + pkt->va_base = kzalloc(size, GFP_KERNEL); + if (!pkt->va_base) { + kfree(pkt); + return -ENOMEM; + } + pkt->buf_size = size; + pkt->cl = (void *)client; + + dev = client->chan->mbox->dev; + dma_addr = dma_map_single(dev, pkt->va_base, pkt->buf_size, + DMA_TO_DEVICE); + if (dma_mapping_error(dev, dma_addr)) { + dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size); + kfree(pkt->va_base); + kfree(pkt); + return -ENOMEM; + } + + pkt->pa_base = dma_addr; + *pkt_ptr = pkt; + + return 0; +} +EXPORT_SYMBOL(cmdq_pkt_create); + +void cmdq_pkt_destroy(struct cmdq_pkt *pk
[PATCH v23 1/4] dt-bindings: soc: Add documentation for the MediaTek GCE unit
This adds documentation for the MediaTek Global Command Engine (GCE) unit found in MT8173 SoCs. Signed-off-by: Houlong Wei Signed-off-by: HS Liao --- .../devicetree/bindings/mailbox/mtk-gce.txt| 57 include/dt-bindings/gce/mt8173-gce.h | 44 +++ 2 files changed, 101 insertions(+) create mode 100644 Documentation/devicetree/bindings/mailbox/mtk-gce.txt create mode 100644 include/dt-bindings/gce/mt8173-gce.h diff --git a/Documentation/devicetree/bindings/mailbox/mtk-gce.txt b/Documentation/devicetree/bindings/mailbox/mtk-gce.txt new file mode 100644 index 000..7d72b21 --- /dev/null +++ b/Documentation/devicetree/bindings/mailbox/mtk-gce.txt @@ -0,0 +1,57 @@ +MediaTek GCE +=== + +The Global Command Engine (GCE) is used to help read/write registers with +critical time limitation, such as updating display configuration during the +vblank. The GCE can be used to implement the Command Queue (CMDQ) driver. + +CMDQ driver uses mailbox framework for communication. Please refer to +mailbox.txt for generic information about mailbox device-tree bindings. + +Required properties: +- compatible: Must be "mediatek,mt8173-gce" +- reg: Address range of the GCE unit +- interrupts: The interrupt signal from the GCE block +- clock: Clocks according to the common clock binding +- clock-names: Must be "gce" to stand for GCE clock +- #mbox-cells: Should be 3. + < channel priority atomic_exec> + phandle: Label name of a gce node. + channel: Channel of mailbox. Be equal to the thread id of GCE. + priority: Priority of GCE thread. + atomic_exec: GCE processing continuous packets of commands in atomic + way. + +Required properties for a client device: +- mboxes: Client use mailbox to communicate with GCE, it should have this + property and list of phandle, mailbox specifiers. +- mediatek,gce-subsys: u32, specify the sub-system id which is corresponding + to the register address. + +Some vaules of properties are defined in 'dt-bindings/gce/mt8173-gce.h'. Such as +sub-system ids, thread priority, event ids. + +Example: + + gce: gce@10212000 { + compatible = "mediatek,mt8173-gce"; + reg = <0 0x10212000 0 0x1000>; + interrupts = ; + clocks = < CLK_INFRA_GCE>; + clock-names = "gce"; + thread-num = CMDQ_THR_MAX_COUNT; + #mbox-cells = <3>; + }; + +Example for a client device: + + mmsys: clock-controller@1400 { + compatible = "mediatek,mt8173-mmsys"; + mboxes = < 0 CMDQ_THR_PRIO_LOWEST 1>, +< 1 CMDQ_THR_PRIO_LOWEST 1>; + mediatek,gce-subsys = ; + mutex-event-eof = ; + + ... + }; diff --git a/include/dt-bindings/gce/mt8173-gce.h b/include/dt-bindings/gce/mt8173-gce.h new file mode 100644 index 000..ffcf94b --- /dev/null +++ b/include/dt-bindings/gce/mt8173-gce.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Houlong Wei + * + */ + +#ifndef _DT_BINDINGS_GCE_MT8173_H +#define _DT_BINDINGS_GCE_MT8173_H + +/* GCE HW thread priority */ +#define CMDQ_THR_PRIO_LOWEST 0 +#define CMDQ_THR_PRIO_HIGHEST 1 + +/* GCE SUBSYS */ +#define SUBSYS_14001 +#define SUBSYS_14012 +#define SUBSYS_14023 + +/* GCE HW EVENT */ +#define CMDQ_EVENT_DISP_OVL0_SOF 11 +#define CMDQ_EVENT_DISP_OVL1_SOF 12 +#define CMDQ_EVENT_DISP_RDMA0_SOF 13 +#define CMDQ_EVENT_DISP_RDMA1_SOF 14 +#define CMDQ_EVENT_DISP_RDMA2_SOF 15 +#define CMDQ_EVENT_DISP_WDMA0_SOF 16 +#define CMDQ_EVENT_DISP_WDMA1_SOF 17 +#define CMDQ_EVENT_DISP_OVL0_EOF 39 +#define CMDQ_EVENT_DISP_OVL1_EOF 40 +#define CMDQ_EVENT_DISP_RDMA0_EOF 41 +#define CMDQ_EVENT_DISP_RDMA1_EOF 42 +#define CMDQ_EVENT_DISP_RDMA2_EOF 43 +#define CMDQ_EVENT_DISP_WDMA0_EOF 44 +#define CMDQ_EVENT_DISP_WDMA1_EOF 45 +#define CMDQ_EVENT_MUTEX0_STREAM_EOF 53 +#define CMDQ_EVENT_MUTEX1_STREAM_EOF 54 +#define CMDQ_EVENT_MUTEX2_STREAM_EOF 55 +#define CMDQ_EVENT_MUTEX3_STREAM_EOF 56 +#define CMDQ_EVENT_MUTEX4_STREAM_EOF 57 +#define CMDQ_EVENT_DISP_RDMA0_UNDERRUN 63 +#define CMDQ_EVENT_DISP_RDMA1_UNDERRUN 64 +#define CMDQ_EVENT_DISP_RDMA2_UNDERRUN 65 + +#endif -- 1.7.9.5
[PATCH v23 0/4] MediaTek MT8173 CMDQ support
Hi, This is Mediatek MT8173 Command Queue(CMDQ) driver. The CMDQ is used to help write registers with critical time limitation, such as updating display configuration during the vblank. It controls Global Command Engine (GCE) hardware to achieve this requirement. Changes since v22: -remove properties 'timeout' and 'thread-num' from device tree -move timer from CMDQ driver to CMDQ helper -move dma unmap from CMDQ driver to CMDQ helper -config thread number in CMDQ match table -remove reallocate mechanism and let client specify the cmdq buffer size -let client specify the timeout time Changes since v21: -rebase on v4.18-rc1 -remove subsys code and event id definition from mtk-cmdq-helper.c -add mt8173-gce.h to define the subsys code and envent id Changes since v20: -rebase on v4.15-rc1 -move dma_map_single outside of spinlock Changes since v19: - rebase to v4.10-rc2 Houlong Wei (4): dt-bindings: soc: Add documentation for the MediaTek GCE unit mailbox: mediatek: Add Mediatek CMDQ driver arm64: dts: mt8173: Add GCE node soc: mediatek: Add Mediatek CMDQ helper .../devicetree/bindings/mailbox/mtk-gce.txt| 57 +++ arch/arm64/boot/dts/mediatek/mt8173.dtsi | 10 + drivers/mailbox/Kconfig| 10 + drivers/mailbox/Makefile | 2 + drivers/mailbox/mtk-cmdq-mailbox.c | 569 + drivers/soc/mediatek/Kconfig | 12 + drivers/soc/mediatek/Makefile | 1 + drivers/soc/mediatek/mtk-cmdq-helper.c | 291 +++ include/dt-bindings/gce/mt8173-gce.h | 44 ++ include/linux/mailbox/mtk-cmdq-mailbox.h | 77 +++ include/linux/soc/mediatek/mtk-cmdq.h | 135 + 11 files changed, 1208 insertions(+) create mode 100644 Documentation/devicetree/bindings/mailbox/mtk-gce.txt create mode 100644 drivers/mailbox/mtk-cmdq-mailbox.c create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c create mode 100644 include/dt-bindings/gce/mt8173-gce.h create mode 100644 include/linux/mailbox/mtk-cmdq-mailbox.h create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h -- 2.12.5
[PATCH v23 3/4] arm64: dts: mt8173: Add GCE node
This patch adds the device node of the GCE hardware for CMDQ module. Signed-off-by: Houlong Wei Signed-off-by: HS Liao --- arch/arm64/boot/dts/mediatek/mt8173.dtsi | 10 ++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi index 94597e3..97b1ec6 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi @@ -18,6 +18,7 @@ #include #include #include +#include #include "mt8173-pinfunc.h" / { @@ -519,6 +520,15 @@ status = "disabled"; }; + gce: mailbox@10212000 { + compatible = "mediatek,mt8173-gce"; + reg = <0 0x10212000 0 0x1000>; + interrupts = ; + clocks = < CLK_INFRA_GCE>; + clock-names = "gce"; + #mbox-cells = <3>; + }; + mipi_tx0: mipi-dphy@10215000 { compatible = "mediatek,mt8173-mipi-tx"; reg = <0 0x10215000 0 0x1000>; -- 1.7.9.5
[PATCH v23 2/4] mailbox: mediatek: Add Mediatek CMDQ driver
This patch is first version of Mediatek Command Queue(CMDQ) driver. The CMDQ is used to help write registers with critical time limitation, such as updating display configuration during the vblank. It controls Global Command Engine (GCE) hardware to achieve this requirement. Currently, CMDQ only supports display related hardwares, but we expect it can be extended to other hardwares for future requirements. Signed-off-by: Houlong Wei Signed-off-by: HS Liao Signed-off-by: CK Hu --- drivers/mailbox/Kconfig | 10 + drivers/mailbox/Makefile |2 + drivers/mailbox/mtk-cmdq-mailbox.c | 569 ++ include/linux/mailbox/mtk-cmdq-mailbox.h | 77 4 files changed, 658 insertions(+) create mode 100644 drivers/mailbox/mtk-cmdq-mailbox.c create mode 100644 include/linux/mailbox/mtk-cmdq-mailbox.h diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index e63d29a..2bbabc9 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -189,4 +189,14 @@ config STM32_IPCC Mailbox implementation for STMicroelectonics STM32 family chips with hardware for Inter-Processor Communication Controller (IPCC) between processors. Say Y here if you want to have this support. + +config MTK_CMDQ_MBOX + tristate "MediaTek CMDQ Mailbox Support" + depends on ARCH_MEDIATEK || COMPILE_TEST + select MTK_INFRACFG + help + Say yes here to add support for the MediaTek Command Queue (CMDQ) + mailbox driver. The CMDQ is used to help read/write registers with + critical time limitation, such as updating display configuration + during the vblank. endif diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index 4d501be..4b00804 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -40,3 +40,5 @@ obj-$(CONFIG_QCOM_APCS_IPC) += qcom-apcs-ipc-mailbox.o obj-$(CONFIG_TEGRA_HSP_MBOX) += tegra-hsp.o obj-$(CONFIG_STM32_IPCC) += stm32-ipcc.o + +obj-$(CONFIG_MTK_CMDQ_MBOX)+= mtk-cmdq-mailbox.o diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c new file mode 100644 index 000..6f92c5e --- /dev/null +++ b/drivers/mailbox/mtk-cmdq-mailbox.c @@ -0,0 +1,569 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2018 MediaTek Inc. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CMDQ_OP_CODE_MASK (0xff << CMDQ_OP_CODE_SHIFT) +#define CMDQ_IRQ_MASK 0x +#define CMDQ_NUM_CMD(t)(t->cmd_buf_size / CMDQ_INST_SIZE) + +#define CMDQ_CURR_IRQ_STATUS 0x10 +#define CMDQ_THR_SLOT_CYCLES 0x30 +#define CMDQ_THR_BASE 0x100 +#define CMDQ_THR_SIZE 0x80 +#define CMDQ_THR_WARM_RESET0x00 +#define CMDQ_THR_ENABLE_TASK 0x04 +#define CMDQ_THR_SUSPEND_TASK 0x08 +#define CMDQ_THR_CURR_STATUS 0x0c +#define CMDQ_THR_IRQ_STATUS0x10 +#define CMDQ_THR_IRQ_ENABLE0x14 +#define CMDQ_THR_CURR_ADDR 0x20 +#define CMDQ_THR_END_ADDR 0x24 +#define CMDQ_THR_WAIT_TOKEN0x30 +#define CMDQ_THR_PRIORITY 0x40 + +#define CMDQ_THR_ACTIVE_SLOT_CYCLES0x3200 +#define CMDQ_THR_ENABLED 0x1 +#define CMDQ_THR_DISABLED 0x0 +#define CMDQ_THR_SUSPEND 0x1 +#define CMDQ_THR_RESUME0x0 +#define CMDQ_THR_STATUS_SUSPENDED BIT(1) +#define CMDQ_THR_DO_WARM_RESET BIT(0) +#define CMDQ_THR_IRQ_DONE 0x1 +#define CMDQ_THR_IRQ_ERROR 0x12 +#define CMDQ_THR_IRQ_EN(CMDQ_THR_IRQ_ERROR | CMDQ_THR_IRQ_DONE) +#define CMDQ_THR_IS_WAITINGBIT(31) + +#define CMDQ_JUMP_BY_OFFSET0x1000 +#define CMDQ_JUMP_BY_PA0x1001 + +struct cmdq_thread { + struct mbox_chan*chan; + void __iomem*base; + struct list_headtask_busy_list; + u32 priority; + boolatomic_exec; +}; + +struct cmdq_task { + struct cmdq *cmdq; + struct list_headlist_entry; + dma_addr_t pa_base; + struct cmdq_thread *thread; + struct cmdq_pkt *pkt; /* the packet sent from mailbox client */ +}; + +struct cmdq { + struct mbox_controller mbox; + void __iomem*base; + u32 irq; + u32 thread_nr; + struct cmdq_thread *thread; + struct clk *clock; + boolsuspended; +}; + +static int cmdq_thread_suspend(struct cmdq *cmdq, struct cmdq_thread *thread) +{ + u32 status; + + writel(CMDQ_
Re: [PATCH v23 3/4] arm64: dts: mt8173: Add GCE node
On Wed, 2018-08-15 at 09:48 +0800, houlong wei wrote: > On Wed, 2018-07-25 at 09:26 +0800, Houlong Wei wrote: > > This patch adds the device node of the GCE hardware for CMDQ module. > > [...] Hello Matthias, Sorry to disturb you. Are you availabe to review this patch and give your comment? Thanks a lot. Regards Houlong
Re: [PATCH v23 4/4] soc: mediatek: Add Mediatek CMDQ helper
On Wed, 2018-08-15 at 09:46 +0800, houlong wei wrote: > On Wed, 2018-07-25 at 09:26 +0800, Houlong Wei wrote: > > Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. > >[...] Hello Matthias, Sorry to disturb you. Could you please review this patch and give your comment? Thanks a lot. Regards Houlong
Re: [PATCH v22 2/4] mailbox: mediatek: Add Mediatek CMDQ driver
On Wed, 2018-07-04 at 17:03 +0800, CK Hu wrote: > Hi, Houlong: > > On Wed, 2018-07-04 at 08:10 +0800, houlong wei wrote: > > On Fri, 2018-06-29 at 15:08 +0800, CK Hu wrote: > > > Hi, Houlong: > > > > > > Some inline comment. > > > > > > On Wed, 2018-06-27 at 19:16 +0800, Houlong Wei wrote: > > > > This patch is first version of Mediatek Command Queue(CMDQ) driver. The > > > > CMDQ is used to help write registers with critical time limitation, > > > > such as updating display configuration during the vblank. It controls > > > > Global Command Engine (GCE) hardware to achieve this requirement. > > > > Currently, CMDQ only supports display related hardwares, but we expect > > > > it can be extended to other hardwares for future requirements. > > > > > > > > Signed-off-by: Houlong Wei > > > > Signed-off-by: HS Liao > > > > Signed-off-by: CK Hu > > > > --- > > > > drivers/mailbox/Kconfig | 10 + > > > > drivers/mailbox/Makefile |2 + > > > > drivers/mailbox/mtk-cmdq-mailbox.c | 634 > > > > ++ > > > > include/linux/mailbox/mtk-cmdq-mailbox.h | 70 > > > > 4 files changed, 716 insertions(+) > > > > create mode 100644 drivers/mailbox/mtk-cmdq-mailbox.c > > > > create mode 100644 include/linux/mailbox/mtk-cmdq-mailbox.h > > > > > > > > > > [...] > > > > > > > + > > > > +static int cmdq_thread_reset(struct cmdq *cmdq, struct cmdq_thread > > > > *thread) > > > > +{ > > > > + u32 warm_reset; > > > > + > > > > + writel(CMDQ_THR_DO_WARM_RESET, thread->base + > > > > CMDQ_THR_WARM_RESET); > > > > + if (readl_poll_timeout_atomic(thread->base + > > > > CMDQ_THR_WARM_RESET, > > > > + warm_reset, !(warm_reset & > > > > CMDQ_THR_DO_WARM_RESET), > > > > + 0, 10)) { > > > > + dev_err(cmdq->mbox.dev, "reset GCE thread 0x%x > > > > failed\n", > > > > + (u32)(thread->base - cmdq->base)); > > > > + return -EFAULT; > > > > + } > > > > + writel(CMDQ_THR_ACTIVE_SLOT_CYCLES, cmdq->base + > > > > CMDQ_THR_SLOT_CYCLES); > > > > > > The CMDQ_THR_SLOT_CYCLES looks like not relevant to reset. Maybe you > > > just need to set this value when startup. > > > > Will move configuration of CMDQ_THR_SLOT_CYCLES to cmdq_xlate() where is > > startup of a GCE thread. > > Since cmdq_xlate() is called when a client requests a channel, it may be called more than once. Will move it to cmdq_probe(). > > > > > > > + > > > > + return 0; > > > > +} > > > > + > > > > > > [...] > > > > > > > + > > > > +static void cmdq_task_exec(struct cmdq_pkt *pkt, struct cmdq_thread > > > > *thread) > > > > +{ > > > > + struct cmdq *cmdq; > > > > + struct cmdq_task *task; > > > > + unsigned long curr_pa, end_pa; > > > > + > > > > + cmdq = dev_get_drvdata(thread->chan->mbox->dev); > > > > + > > > > + /* Client should not flush new tasks if suspended. */ > > > > + WARN_ON(cmdq->suspended); > > > > + > > > > + task = kzalloc(sizeof(*task), GFP_ATOMIC); > > > > + task->cmdq = cmdq; > > > > + INIT_LIST_HEAD(>list_entry); > > > > + task->pa_base = pkt->pa_base; > > > > + task->thread = thread; > > > > + task->pkt = pkt; > > > > + > > > > + if (list_empty(>task_busy_list)) { > > > > + WARN_ON(clk_enable(cmdq->clock) < 0); > > > > + WARN_ON(cmdq_thread_reset(cmdq, thread) < 0); > > > > + > > > > + writel(task->pa_base, thread->base + > > > > CMDQ_THR_CURR_ADDR); > > > > + writel(task->pa_base + pkt->cmd_buf_size, > > > > + thread->base + CMDQ_THR_END_ADDR); > > > > + writel(thread->priority, thread->base + > > > > CMDQ_THR_PRIORITY);
Re: [PATCH v22 4/4] soc: mediatek: Add Mediatek CMDQ helper
On Wed, 2018-07-04 at 10:39 +0800, CK Hu wrote: > Hi, Houlong: > > On Wed, 2018-07-04 at 08:47 +0800, houlong wei wrote: > > On Fri, 2018-06-29 at 17:22 +0800, CK Hu wrote: > > > Hi, Houlong: > > > > > > On Fri, 2018-06-29 at 07:32 +0800, houlong wei wrote: > > > > On Thu, 2018-06-28 at 18:41 +0800, CK Hu wrote: > > > > > Hi, Houlong: > > > > > > > > > > Some inline comment. > > > > > > > > > > On Wed, 2018-06-27 at 19:16 +0800, Houlong Wei wrote: > > > > > > Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op > > > > > > code. > > > > > > > > > > > > Signed-off-by: Houlong Wei > > > > > > Signed-off-by: HS Liao > > > > > > --- > > > > > > drivers/soc/mediatek/Kconfig | 12 ++ > > > > > > drivers/soc/mediatek/Makefile |1 + > > > > > > drivers/soc/mediatek/mtk-cmdq-helper.c | 258 > > > > > > > > > > > > include/linux/soc/mediatek/mtk-cmdq.h | 132 > > > > > > 4 files changed, 403 insertions(+) > > > > > > create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c > > > > > > create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h > > > > > > > > > > > > diff --git a/drivers/soc/mediatek/Kconfig > > > > > > b/drivers/soc/mediatek/Kconfig > > > > > > index a7d0667..17bd759 100644 > > > > > > --- a/drivers/soc/mediatek/Kconfig > > > > > > +++ b/drivers/soc/mediatek/Kconfig > > > > > > @@ -4,6 +4,18 @@ > > > > > > menu "MediaTek SoC drivers" > > > > > > depends on ARCH_MEDIATEK || COMPILE_TEST > > > > > > > > > > > > > > > > > [...] > > > > > > > > > + > > > > > > +static int cmdq_pkt_finalize(struct cmdq_pkt *pkt) > > > > > > +{ > > > > > > + int err; > > > > > > + > > > > > > + if (cmdq_pkt_is_finalized(pkt)) > > > > > > + return 0; > > > > > > + > > > > > > + /* insert EOC and generate IRQ for each command iteration */ > > > > > > + err = cmdq_pkt_append_command(pkt, CMDQ_CODE_EOC, 0, > > > > > > CMDQ_EOC_IRQ_EN); > > > > > > + if (err < 0) > > > > > > + return err; > > > > > > + > > > > > > + /* JUMP to end */ > > > > > > + err = cmdq_pkt_append_command(pkt, CMDQ_CODE_JUMP, 0, > > > > > > CMDQ_JUMP_PASS); > > > > > > + if (err < 0) > > > > > > + return err; > > > > > > + > > > > > > + return 0; > > > > > > +} > > > > > > + > > > > > > +int cmdq_pkt_flush_async(struct cmdq_client *client, struct > > > > > > cmdq_pkt *pkt, > > > > > > +cmdq_async_flush_cb cb, void *data) > > > > > > +{ > > > > > > + int err; > > > > > > + struct device *dev; > > > > > > + dma_addr_t dma_addr; > > > > > > + > > > > > > + err = cmdq_pkt_finalize(pkt); > > > > > > + if (err < 0) > > > > > > + return err; > > > > > > + > > > > > > + dev = client->chan->mbox->dev; > > > > > > + dma_addr = dma_map_single(dev, pkt->va_base, pkt->cmd_buf_size, > > > > > > + DMA_TO_DEVICE); > > > > > > > > > > You map here, but I could not find unmap, so the unmap should be done > > > > > in > > > > > client driver. I would prefer a symmetric map/unmap which means that > > > > > both map and unmap are done in client driver. I think you put map here > > > > > because you should map after finalize. > > > > > > > > The unmap is done before callback to client, in function > > > > cmdq_task_exec_done, mtk-cmdq-mailbox.c. > > > > > > You put unmap in mailbox controller, and map here (here would be mailbox > > > client), so this is not symmetric. If the code is asymmetric, it's easy >
Re: [PATCH v22 1/4] dt-bindings: soc: Add documentation for the MediaTek GCE unit
On Fri, 2018-07-06 at 04:08 +0800, Rob Herring wrote: > On Tue, Jul 3, 2018 at 5:39 PM houlong wei wrote: > > > > On Tue, 2018-07-03 at 10:30 +0800, Rob Herring wrote: > > > On Wed, Jun 27, 2018 at 07:16:09PM +0800, Houlong Wei wrote: > > > > This adds documentation for the MediaTek Global Command Engine (GCE) > > > > unit > > > > found in MT8173 SoCs. > > > > > > > > Signed-off-by: Houlong Wei > > > > Signed-off-by: HS Liao > > > > --- > > > > Hi Rob, > > > > I don't add your ACK in this version since the dt-binding description > > > > has been changed. Thanks. > > > > --- > > > > .../devicetree/bindings/mailbox/mtk-gce.txt| 65 > > > > > > > > include/dt-bindings/gce/mt8173-gce.h | 48 > > > > +++ > > > > 2 files changed, 113 insertions(+) > > > > create mode 100644 > > > > Documentation/devicetree/bindings/mailbox/mtk-gce.txt > > > > create mode 100644 include/dt-bindings/gce/mt8173-gce.h > > > > > > > > diff --git a/Documentation/devicetree/bindings/mailbox/mtk-gce.txt > > > > b/Documentation/devicetree/bindings/mailbox/mtk-gce.txt > > > > new file mode 100644 > > > > index 000..26f65a4 > > > > --- /dev/null > > > > +++ b/Documentation/devicetree/bindings/mailbox/mtk-gce.txt > > > > @@ -0,0 +1,65 @@ > > > > +MediaTek GCE > > > > +=== > > > > + > > > > +The Global Command Engine (GCE) is used to help read/write registers > > > > with > > > > +critical time limitation, such as updating display configuration > > > > during the > > > > +vblank. The GCE can be used to implement the Command Queue (CMDQ) > > > > driver. > > > > + > > > > +CMDQ driver uses mailbox framework for communication. Please refer to > > > > +mailbox.txt for generic information about mailbox device-tree bindings. > > > > + > > > > +Required properties: > > > > +- compatible: Must be "mediatek,mt8173-gce" > > > > +- reg: Address range of the GCE unit > > > > +- interrupts: The interrupt signal from the GCE block > > > > +- clock: Clocks according to the common clock binding > > > > +- clock-names: Must be "gce" to stand for GCE clock > > > > +- thread-num: Maximum threads count of GCE. > > > > > > mediatek,thread-num > > > > > > Is this needed for anything other than error checking the thread id in > > > the mbox cells? if that's it, then drop it. > > > > > > > 'thread-num' is used to configure the GCE thread number, which is the > > channel number of gce mailbox. This property is read in > > cmdq_probe()/mtk-cmdq-mailbox.c and a mailbox's channel array is > > allocated according to the number. > > Since the thread number may be different on different SoC, we wish it > > could be configured in device tree. > > You should have different compatible strings for different SoCs and > can imply the number of threads from that. > Thanks. Will remove 'thread-num' form device tree and put it in match table of cmdq dirver. > Or if the number of threads doesn't vary greatly, just allocate the > max # of channels. Or allocate the per thread data when a thread is > actually in use. > > > > > > > +- #mbox-cells: Should be 4. > > > > + < channel timeout priority atomic_exec> > > > > + phandle: Label name of a gce node. > > > > + channel: Channel of mailbox. Be equal to the thread id of GCE. > > > > + timeout: Maximum time of software waiting GCE processing done, in > > > > unit > > > > + of millisecond. > > > > + priority: Priority of GCE thread. > > > > + atomic_exec: GCE processing continuous packets of commands in atomic > > > > + way. > > > > + > > > > +Required properties for a client device: > > > > +- mboxes: Client use mailbox to communicate with GCE, it should have > > > > this > > > > + property and list of phandle, mailbox specifiers. > > > > +- gce-subsys: Specify the sub-system id which is corresponding to the > > > > register > > > > + address. > > > > > > What is this for? > > > > You mean the new added property 'gce-subsys'? > > I
Re: [PATCH v22 4/4] soc: mediatek: Add Mediatek CMDQ helper
On Thu, 2018-06-28 at 18:41 +0800, CK Hu wrote: > Hi, Houlong: > > Some inline comment. > > On Wed, 2018-06-27 at 19:16 +0800, Houlong Wei wrote: > > Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. > > > > Signed-off-by: Houlong Wei > > Signed-off-by: HS Liao > > --- > > drivers/soc/mediatek/Kconfig | 12 ++ > > drivers/soc/mediatek/Makefile |1 + > > drivers/soc/mediatek/mtk-cmdq-helper.c | 258 > > > > include/linux/soc/mediatek/mtk-cmdq.h | 132 > > 4 files changed, 403 insertions(+) > > create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c > > create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h > > > > diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig > > index a7d0667..17bd759 100644 > > --- a/drivers/soc/mediatek/Kconfig > > +++ b/drivers/soc/mediatek/Kconfig > > @@ -4,6 +4,18 @@ > > menu "MediaTek SoC drivers" > > depends on ARCH_MEDIATEK || COMPILE_TEST > > > > [...] > > > + > > +int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u32 event) > > +{ > > + u32 arg_b; > > + > > + if (event >= CMDQ_MAX_EVENT || event < 0) > > The type of event is 'u32', so checking 'event < 0' is redundant. will fix. > > > + return -EINVAL; > > + > > + /* > > +* WFE arg_b > > +* bit 0-11: wait value > > +* bit 15: 1 - wait, 0 - no wait > > +* bit 16-27: update value > > +* bit 31: 1 - update, 0 - no update > > +*/ > > + arg_b = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE; > > + > > + return cmdq_pkt_append_command(pkt, CMDQ_CODE_WFE, event, arg_b); > > +} > > +EXPORT_SYMBOL(cmdq_pkt_wfe); > > + > > +int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u32 event) > > +{ > > + if (event >= CMDQ_MAX_EVENT || event < 0) > > The type of event is 'u32', so checking 'event < 0' is redundant. Will fix. > > > + return -EINVAL; > > + > > + return cmdq_pkt_append_command(pkt, CMDQ_CODE_WFE, event, > > + CMDQ_WFE_UPDATE); > > +} > > +EXPORT_SYMBOL(cmdq_pkt_clear_event); > > + > > +static int cmdq_pkt_finalize(struct cmdq_pkt *pkt) > > +{ > > + int err; > > + > > + if (cmdq_pkt_is_finalized(pkt)) > > + return 0; > > + > > + /* insert EOC and generate IRQ for each command iteration */ > > + err = cmdq_pkt_append_command(pkt, CMDQ_CODE_EOC, 0, CMDQ_EOC_IRQ_EN); > > + if (err < 0) > > + return err; > > + > > + /* JUMP to end */ > > + err = cmdq_pkt_append_command(pkt, CMDQ_CODE_JUMP, 0, CMDQ_JUMP_PASS); > > + if (err < 0) > > + return err; > > + > > + return 0; > > +} > > + > > +int cmdq_pkt_flush_async(struct cmdq_client *client, struct cmdq_pkt *pkt, > > +cmdq_async_flush_cb cb, void *data) > > +{ > > + int err; > > + struct device *dev; > > + dma_addr_t dma_addr; > > + > > + err = cmdq_pkt_finalize(pkt); > > + if (err < 0) > > + return err; > > + > > + dev = client->chan->mbox->dev; > > + dma_addr = dma_map_single(dev, pkt->va_base, pkt->cmd_buf_size, > > + DMA_TO_DEVICE); > > You map here, but I could not find unmap, so the unmap should be done in > client driver. I would prefer a symmetric map/unmap which means that > both map and unmap are done in client driver. I think you put map here > because you should map after finalize. The unmap is done before callback to client, in function cmdq_task_exec_done, mtk-cmdq-mailbox.c. > Therefore, export > cmdq_pkt_finalize() to client driver and let client do finalize, so > there is no finalize in flush function. This method have a benefit that > if client reuse command buffer, it need not to map/unmap frequently. If client reuse command buffer or cmdq_pkt(command queue packet), client will add new commands to the cmdq_pkt, so map/unmap are necessary for each cmdq_pkt flush. > > Regards, > CK > > > + if (dma_mapping_error(dev, dma_addr)) { > > + dev_err(client->chan->mbox->dev, "dma map failed\n"); > > + return -ENOMEM; > > + } > > + > > + pkt->pa_base = dma_addr; > > + pkt->cb.cb = cb; > > + pkt->cb.data = data; > > + > > + mbox_send_message(client->chan, pkt); > > + /*
Re: [PATCH v21 2/4] mailbox: mediatek: Add Mediatek CMDQ driver
On Thu, 2018-06-28 at 09:57 +0800, CK Hu wrote: > Hi, Houlong: > > On Wed, 2018-06-27 at 19:53 +0800, houlong wei wrote: > > On Wed, 2018-02-21 at 11:53 +0800, CK Hu wrote: > > > Hi, Houlong: > > > > > > I've one inline comment. > > > > > > On Wed, 2018-01-31 at 15:28 +0800, houlong@mediatek.com wrote: > > > > From: "hs.l...@mediatek.com" > > > > > > > > This patch is first version of Mediatek Command Queue(CMDQ) driver. The > > > > CMDQ is used to help write registers with critical time limitation, > > > > such as updating display configuration during the vblank. It controls > > > > Global Command Engine (GCE) hardware to achieve this requirement. > > > > Currently, CMDQ only supports display related hardwares, but we expect > > > > it can be extended to other hardwares for future requirements. > > > > > > > > Signed-off-by: Houlong Wei > > > > Signed-off-by: HS Liao > > > > Signed-off-by: CK Hu > > > > --- > > > > drivers/mailbox/Kconfig | 10 + > > > > drivers/mailbox/Makefile |2 + > > > > drivers/mailbox/mtk-cmdq-mailbox.c | 594 > > > > ++ > > > > include/linux/mailbox/mtk-cmdq-mailbox.h | 77 > > > > 4 files changed, 683 insertions(+) > > > > create mode 100644 drivers/mailbox/mtk-cmdq-mailbox.c > > > > create mode 100644 include/linux/mailbox/mtk-cmdq-mailbox.h > > > > > > > > diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig > > > > index ba2f152..43bb26f 100644 > > > > --- a/drivers/mailbox/Kconfig > > > > +++ b/drivers/mailbox/Kconfig > > > > @@ -171,4 +171,14 @@ config BCM_FLEXRM_MBOX > > > > Mailbox implementation of the Broadcom FlexRM ring manager, > > > > which provides access to various offload engines on Broadcom > > > > SoCs. Say Y here if you want to use the Broadcom FlexRM. > > > > + > > [...] > > > > > + > > > > +static void cmdq_task_exec(struct cmdq_pkt *pkt, struct cmdq_thread > > > > *thread) > > > > +{ > > > > + struct cmdq *cmdq; > > > > + struct cmdq_task *task; > > > > + unsigned long curr_pa, end_pa; > > > > + > > > > + cmdq = dev_get_drvdata(thread->chan->mbox->dev); > > > > + > > > > + /* Client should not flush new tasks if suspended. */ > > > > + WARN_ON(cmdq->suspended); > > > > + > > > > + task = kzalloc(sizeof(*task), GFP_ATOMIC); > > > > + task->cmdq = cmdq; > > > > + INIT_LIST_HEAD(>list_entry); > > > > + task->pa_base = pkt->pa_base; > > > > + task->thread = thread; > > > > + task->pkt = pkt; > > > > + > > > > + if (list_empty(>task_busy_list)) { > > > > + WARN_ON(clk_enable(cmdq->clock) < 0); > > > > + WARN_ON(cmdq_thread_reset(cmdq, thread) < 0); > > > > + > > > > + writel(task->pa_base, thread->base + > > > > CMDQ_THR_CURR_ADDR); > > > > + writel(task->pa_base + pkt->cmd_buf_size, > > > > + thread->base + CMDQ_THR_END_ADDR); > > > > + writel(CMDQ_THR_IRQ_EN, thread->base + > > > > CMDQ_THR_IRQ_ENABLE); > > > > + writel(CMDQ_THR_ENABLED, thread->base + > > > > CMDQ_THR_ENABLE_TASK); > > > > + > > > > + mod_timer(>timeout, > > > > + jiffies + msecs_to_jiffies(CMDQ_TIMEOUT_MS)); > > > > + } else { > > > > + WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0); > > > > + curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR); > > > > + end_pa = readl(thread->base + CMDQ_THR_END_ADDR); > > > > + > > > > + /* > > > > +* Atomic execution should remove the following wfe, > > > > i.e. only > > > > +* wait event at first task, and prevent to pause when > > > > running. > > > > +*/ > > > > + if (thread->atomic_exec
[PATCH v26 2/2] soc: mediatek: Add Mediatek CMDQ helper
Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. Signed-off-by: Houlong Wei Signed-off-by: HS Liao --- drivers/soc/mediatek/Kconfig | 12 ++ drivers/soc/mediatek/Makefile |1 + drivers/soc/mediatek/mtk-cmdq-helper.c | 292 include/linux/soc/mediatek/mtk-cmdq.h | 133 +++ 4 files changed, 438 insertions(+) create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig index a7d0667..17bd759 100644 --- a/drivers/soc/mediatek/Kconfig +++ b/drivers/soc/mediatek/Kconfig @@ -4,6 +4,18 @@ menu "MediaTek SoC drivers" depends on ARCH_MEDIATEK || COMPILE_TEST +config MTK_CMDQ + tristate "MediaTek CMDQ Support" + depends on ARCH_MEDIATEK || COMPILE_TEST + select MAILBOX + select MTK_CMDQ_MBOX + select MTK_INFRACFG + help + Say yes here to add support for the MediaTek Command Queue (CMDQ) + driver. The CMDQ is used to help read/write registers with critical + time limitation, such as updating display configuration during the + vblank. + config MTK_INFRACFG bool "MediaTek INFRACFG Support" select REGMAP diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile index 12998b0..64ce5ee 100644 --- a/drivers/soc/mediatek/Makefile +++ b/drivers/soc/mediatek/Makefile @@ -1,3 +1,4 @@ +obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c new file mode 100644 index 000..45aa0cf --- /dev/null +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -0,0 +1,292 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2018 MediaTek Inc. + +#include +#include +#include +#include +#include +#include + +#define CMDQ_ARG_A_WRITE_MASK 0x +#define CMDQ_WRITE_ENABLE_MASK BIT(0) +#define CMDQ_EOC_IRQ_ENBIT(0) +#define CMDQ_EOC_CMD ((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \ + << 32 | CMDQ_EOC_IRQ_EN) + +static void cmdq_client_timeout(struct timer_list *t) +{ + struct cmdq_client *client = from_timer(client, t, timer); + + dev_err(client->client.dev, "cmdq timeout!\n"); +} + +struct cmdq_client *cmdq_mbox_create(struct device *dev, int index, u32 timeout) +{ + struct cmdq_client *client; + + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client) + return (struct cmdq_client *)-ENOMEM; + + client->timeout_ms = timeout; + if (timeout != CMDQ_NO_TIMEOUT) { + spin_lock_init(>lock); + timer_setup(>timer, cmdq_client_timeout, 0); + } + client->pkt_cnt = 0; + client->client.dev = dev; + client->client.tx_block = false; + client->chan = mbox_request_channel(>client, index); + + if (IS_ERR(client->chan)) { + long err; + + dev_err(dev, "failed to request channel\n"); + err = PTR_ERR(client->chan); + kfree(client); + + return ERR_PTR(err); + } + + return client; +} +EXPORT_SYMBOL(cmdq_mbox_create); + +void cmdq_mbox_destroy(struct cmdq_client *client) +{ + if (client->timeout_ms != CMDQ_NO_TIMEOUT) { + spin_lock(>lock); + del_timer_sync(>timer); + spin_unlock(>lock); + } + mbox_free_channel(client->chan); + kfree(client); +} +EXPORT_SYMBOL(cmdq_mbox_destroy); + +struct cmdq_pkt *cmdq_pkt_create(struct cmdq_client *client, size_t size) +{ + struct cmdq_pkt *pkt; + struct device *dev; + dma_addr_t dma_addr; + + pkt = kzalloc(sizeof(*pkt), GFP_KERNEL); + if (!pkt) + return ERR_PTR(-ENOMEM); + pkt->va_base = kzalloc(size, GFP_KERNEL); + if (!pkt->va_base) { + kfree(pkt); + return ERR_PTR(-ENOMEM); + } + pkt->buf_size = size; + pkt->cl = (void *)client; + + dev = client->chan->mbox->dev; + dma_addr = dma_map_single(dev, pkt->va_base, pkt->buf_size, + DMA_TO_DEVICE); + if (dma_mapping_error(dev, dma_addr)) { + dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size); + kfree(pkt->va_base); + kfree(pkt); + return ERR_PTR(-ENOMEM); + } + + pkt->pa_base = dma_addr; + + return pkt; +} +EXPORT_SYMBOL(cmdq_pkt_create); + +void cmdq_pkt_destroy(struct cmdq_pkt *pk
[PATCH v26 1/2] arm64: dts: mt8173: Add GCE node
This patch adds the device node of the GCE hardware for CMDQ module. Signed-off-by: Houlong Wei Signed-off-by: HS Liao --- arch/arm64/boot/dts/mediatek/mt8173.dtsi | 10 ++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi index abd2f15..412ffd4 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi @@ -18,6 +18,7 @@ #include #include #include +#include #include "mt8173-pinfunc.h" / { @@ -521,6 +522,15 @@ status = "disabled"; }; + gce: mailbox@10212000 { + compatible = "mediatek,mt8173-gce"; + reg = <0 0x10212000 0 0x1000>; + interrupts = ; + clocks = < CLK_INFRA_GCE>; + clock-names = "gce"; + #mbox-cells = <3>; + }; + mipi_tx0: mipi-dphy@10215000 { compatible = "mediatek,mt8173-mipi-tx"; reg = <0 0x10215000 0 0x1000>; -- 1.7.9.5
[PATCH v26 0/2] MediaTek MT8173 CMDQ support
Hi, This is Mediatek MT8173 Command Queue(CMDQ) driver. The CMDQ is used to help write registers with critical time limitation, such as updating display configuration during the vblank. It controls Global Command Engine (GCE) hardware to achieve this requirement. Changes since v25: -Replace WARN_ON() with WARN_ONCE() and add debug information. Changes since v24: -move WARN_ON() into cmdq_pkt_append_command() from outside Changes since v23: -rebase on v4.19-rc1 -revise return value of cmdq_mbox_create() -revise cmdq_pkt_create() -add MODULE_LICENSE() for mtk-cmdq-helper.c -adjust functions order in mtk-cmdq.h Changes since v22: -remove properties 'timeout' and 'thread-num' from device tree -move timer from CMDQ driver to CMDQ helper -move dma unmap from CMDQ driver to CMDQ helper -config thread number in CMDQ match table -remove reallocate mechanism and let client specify the cmdq buffer size -let client specify the timeout time Changes since v21: -rebase on v4.18-rc1 -remove subsys code and event id definition from mtk-cmdq-helper.c -add mt8173-gce.h to define the subsys code and envent id Changes since v20: -rebase on v4.15-rc1 -move dma_map_single outside of spinlock Changes since v19: -rebase to v4.10-rc2 Houlong Wei (2): arm64: dts: mt8173: Add GCE node soc: mediatek: Add Mediatek CMDQ helper arch/arm64/boot/dts/mediatek/mt8173.dtsi | 10 + drivers/soc/mediatek/Kconfig | 12 ++ drivers/soc/mediatek/Makefile|1 + drivers/soc/mediatek/mtk-cmdq-helper.c | 292 ++ include/linux/soc/mediatek/mtk-cmdq.h| 133 ++ 5 files changed, 448 insertions(+) create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h -- 1.7.9.5
Re: [PATCH v25 2/2] soc: mediatek: Add Mediatek CMDQ helper
On Sat, 2018-09-29 at 20:50 +0800, Matthias Brugger wrote: > > On 29/09/2018 11:21, Houlong Wei wrote: > [...] > > > +static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, enum cmdq_code > > code, > > + u32 arg_a, u32 arg_b) > > +{ > > + u64 *cmd_ptr; > > + > > + if (unlikely(pkt->cmd_buf_size + CMDQ_INST_SIZE > pkt->buf_size)) { > > + pkt->cmd_buf_size += CMDQ_INST_SIZE; > > Can you plesae provide some example code of a driver that will use this API, I > still don't understand why you need to update the cmd_buf_size here. In our previous design, when appending a new command to buffer and the buffer gets overflow, we will re-allocate a larger buffer to use. CK.Hu had concern about the performance of buffer re-allocation. Please refer: http://lists.infradead.org/pipermail/linux-mediatek/2018-June/013797.html One of his suggestions is that the consumer dynamically allocates buffer with a initial size. Because the consumer doesn't know how to calculate the buffer size. So we increase cmdq_buf_size here, that will help the consumer get the buffer size in developing phase. In release driver code, consumer passes a constant value to function call cmdq_pkt_create(client, cmdq_buffer_size), cmdq_buffer_size is the specified command queue buffer size. > > > + WARN_ON(1); > > can we add some debug information: > WARN_ON(1, "%s: buffer size too small for the amount of commands", __func__); > > Would it make sense to use WARN_ONCE()? > Yes, I will add debug information and use WARN_ONCE(). > > + return -ENOMEM; > > + } > > + cmd_ptr = pkt->va_base + pkt->cmd_buf_size; > > + (*cmd_ptr) = (u64)((code << CMDQ_OP_CODE_SHIFT) | arg_a) << 32 | arg_b; > > + pkt->cmd_buf_size += CMDQ_INST_SIZE; > > + > > + return 0; > > +} > > Thanks, > Matthias
Re: [PATCH v26 2/2] soc: mediatek: Add Mediatek CMDQ helper
On Mon, 2018-10-08 at 11:43 +0800, Houlong Wei wrote: > Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. > > Signed-off-by: Houlong Wei > Signed-off-by: HS Liao > --- > drivers/soc/mediatek/Kconfig | 12 ++ > drivers/soc/mediatek/Makefile |1 + > drivers/soc/mediatek/mtk-cmdq-helper.c | 292 > > include/linux/soc/mediatek/mtk-cmdq.h | 133 +++ > 4 files changed, 438 insertions(+) > create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c > create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h > > diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig > index a7d0667..17bd759 100644 > --- a/drivers/soc/mediatek/Kconfig > +++ b/drivers/soc/mediatek/Kconfig > @@ -4,6 +4,18 @@ > menu "MediaTek SoC drivers" > depends on ARCH_MEDIATEK || COMPILE_TEST > > +config MTK_CMDQ > +tristate "MediaTek CMDQ Support" > +depends on ARCH_MEDIATEK || COMPILE_TEST > +select MAILBOX > +select MTK_CMDQ_MBOX > +select MTK_INFRACFG > +help > + Say yes here to add support for the MediaTek Command Queue (CMDQ) > + driver. The CMDQ is used to help read/write registers with critical > + time limitation, such as updating display configuration during the > + vblank. > + > config MTK_INFRACFG > bool "MediaTek INFRACFG Support" > select REGMAP > diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile > index 12998b0..64ce5ee 100644 > --- a/drivers/soc/mediatek/Makefile > +++ b/drivers/soc/mediatek/Makefile > @@ -1,3 +1,4 @@ > +obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o > obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o > obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o > obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o > diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c > b/drivers/soc/mediatek/mtk-cmdq-helper.c > new file mode 100644 > index 000..45aa0cf > --- /dev/null > +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c > @@ -0,0 +1,292 @@ > +// SPDX-License-Identifier: GPL-2.0 > +// > +// Copyright (c) 2018 MediaTek Inc. > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define CMDQ_ARG_A_WRITE_MASK0x > +#define CMDQ_WRITE_ENABLE_MASKBIT(0) > +#define CMDQ_EOC_IRQ_ENBIT(0) > +#define CMDQ_EOC_CMD((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \ > +<< 32 | CMDQ_EOC_IRQ_EN) > + > +static void cmdq_client_timeout(struct timer_list *t) > +{ > +struct cmdq_client *client = from_timer(client, t, timer); > + > +dev_err(client->client.dev, "cmdq timeout!\n"); > +} > + > +struct cmdq_client *cmdq_mbox_create(struct device *dev, int index, u32 > timeout) > +{ > +struct cmdq_client *client; > + > +client = kzalloc(sizeof(*client), GFP_KERNEL); > +if (!client) > +return (struct cmdq_client *)-ENOMEM; > + > +client->timeout_ms = timeout; > +if (timeout != CMDQ_NO_TIMEOUT) { > +spin_lock_init(>lock); > +timer_setup(>timer, cmdq_client_timeout, 0); > +} > +client->pkt_cnt = 0; > +client->client.dev = dev; > +client->client.tx_block = false; > +client->chan = mbox_request_channel(>client, index); > + > +if (IS_ERR(client->chan)) { > +long err; > + > +dev_err(dev, "failed to request channel\n"); > +err = PTR_ERR(client->chan); > +kfree(client); > + > +return ERR_PTR(err); > +} > + > +return client; > +} > +EXPORT_SYMBOL(cmdq_mbox_create); > + > +void cmdq_mbox_destroy(struct cmdq_client *client) > +{ > +if (client->timeout_ms != CMDQ_NO_TIMEOUT) { > +spin_lock(>lock); > +del_timer_sync(>timer); > +spin_unlock(>lock); > +} > +mbox_free_channel(client->chan); > +kfree(client); > +} > +EXPORT_SYMBOL(cmdq_mbox_destroy); > + > +struct cmdq_pkt *cmdq_pkt_create(struct cmdq_client *client, size_t size) > +{ > +struct cmdq_pkt *pkt; > +struct device *dev; > +dma_addr_t dma_addr; > + > +pkt = kzalloc(sizeof(*pkt), GFP_KERNEL); > +if (!pkt) > +return ERR_PTR(-ENOMEM); > +pkt->va_base = kzalloc(size, GFP_KERNEL); > +if (!pkt->va_base) { > +kfree(pkt); > +return ERR_PTR(-ENOMEM); > +} > +pkt->buf_size = size; > +pkt->cl = (void *)client; > + > +dev = client->chan->mbox->dev; > +dma_addr = dma_map_single(dev, pkt->va_base, pkt->buf_size, > + DMA_TO_DEVICE); > +if (dma_mapping_error(dev, dma_addr)) { > +dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size); > +kfree(pkt->va_base); > +kfree(pkt); > +return ERR_PTR(-ENOMEM); > +} > + > +pkt->pa_base = dma_addr; > + > +return pk
[PATCH v25 1/2] arm64: dts: mt8173: Add GCE node
This patch adds the device node of the GCE hardware for CMDQ module. Signed-off-by: Houlong Wei Signed-off-by: HS Liao --- arch/arm64/boot/dts/mediatek/mt8173.dtsi | 10 ++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi index abd2f15..412ffd4 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi @@ -18,6 +18,7 @@ #include #include #include +#include #include "mt8173-pinfunc.h" / { @@ -521,6 +522,15 @@ status = "disabled"; }; + gce: mailbox@10212000 { + compatible = "mediatek,mt8173-gce"; + reg = <0 0x10212000 0 0x1000>; + interrupts = ; + clocks = < CLK_INFRA_GCE>; + clock-names = "gce"; + #mbox-cells = <3>; + }; + mipi_tx0: mipi-dphy@10215000 { compatible = "mediatek,mt8173-mipi-tx"; reg = <0 0x10215000 0 0x1000>; -- 1.7.9.5
[PATCH v25 2/2] soc: mediatek: Add Mediatek CMDQ helper
Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. Signed-off-by: Houlong Wei Signed-off-by: HS Liao --- drivers/soc/mediatek/Kconfig | 12 ++ drivers/soc/mediatek/Makefile |1 + drivers/soc/mediatek/mtk-cmdq-helper.c | 291 include/linux/soc/mediatek/mtk-cmdq.h | 133 +++ 4 files changed, 437 insertions(+) create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig index a7d0667..17bd759 100644 --- a/drivers/soc/mediatek/Kconfig +++ b/drivers/soc/mediatek/Kconfig @@ -4,6 +4,18 @@ menu "MediaTek SoC drivers" depends on ARCH_MEDIATEK || COMPILE_TEST +config MTK_CMDQ + tristate "MediaTek CMDQ Support" + depends on ARCH_MEDIATEK || COMPILE_TEST + select MAILBOX + select MTK_CMDQ_MBOX + select MTK_INFRACFG + help + Say yes here to add support for the MediaTek Command Queue (CMDQ) + driver. The CMDQ is used to help read/write registers with critical + time limitation, such as updating display configuration during the + vblank. + config MTK_INFRACFG bool "MediaTek INFRACFG Support" select REGMAP diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile index 12998b0..64ce5ee 100644 --- a/drivers/soc/mediatek/Makefile +++ b/drivers/soc/mediatek/Makefile @@ -1,3 +1,4 @@ +obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c new file mode 100644 index 000..86a7ab5 --- /dev/null +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -0,0 +1,291 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2018 MediaTek Inc. + +#include +#include +#include +#include +#include +#include + +#define CMDQ_ARG_A_WRITE_MASK 0x +#define CMDQ_WRITE_ENABLE_MASK BIT(0) +#define CMDQ_EOC_IRQ_ENBIT(0) +#define CMDQ_EOC_CMD ((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \ + << 32 | CMDQ_EOC_IRQ_EN) + +static void cmdq_client_timeout(struct timer_list *t) +{ + struct cmdq_client *client = from_timer(client, t, timer); + + dev_err(client->client.dev, "cmdq timeout!\n"); +} + +struct cmdq_client *cmdq_mbox_create(struct device *dev, int index, u32 timeout) +{ + struct cmdq_client *client; + + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client) + return (struct cmdq_client *)-ENOMEM; + + client->timeout_ms = timeout; + if (timeout != CMDQ_NO_TIMEOUT) { + spin_lock_init(>lock); + timer_setup(>timer, cmdq_client_timeout, 0); + } + client->pkt_cnt = 0; + client->client.dev = dev; + client->client.tx_block = false; + client->chan = mbox_request_channel(>client, index); + + if (IS_ERR(client->chan)) { + long err; + + dev_err(dev, "failed to request channel\n"); + err = PTR_ERR(client->chan); + kfree(client); + + return ERR_PTR(err); + } + + return client; +} +EXPORT_SYMBOL(cmdq_mbox_create); + +void cmdq_mbox_destroy(struct cmdq_client *client) +{ + if (client->timeout_ms != CMDQ_NO_TIMEOUT) { + spin_lock(>lock); + del_timer_sync(>timer); + spin_unlock(>lock); + } + mbox_free_channel(client->chan); + kfree(client); +} +EXPORT_SYMBOL(cmdq_mbox_destroy); + +struct cmdq_pkt *cmdq_pkt_create(struct cmdq_client *client, size_t size) +{ + struct cmdq_pkt *pkt; + struct device *dev; + dma_addr_t dma_addr; + + pkt = kzalloc(sizeof(*pkt), GFP_KERNEL); + if (!pkt) + return ERR_PTR(-ENOMEM); + pkt->va_base = kzalloc(size, GFP_KERNEL); + if (!pkt->va_base) { + kfree(pkt); + return ERR_PTR(-ENOMEM); + } + pkt->buf_size = size; + pkt->cl = (void *)client; + + dev = client->chan->mbox->dev; + dma_addr = dma_map_single(dev, pkt->va_base, pkt->buf_size, + DMA_TO_DEVICE); + if (dma_mapping_error(dev, dma_addr)) { + dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size); + kfree(pkt->va_base); + kfree(pkt); + return ERR_PTR(-ENOMEM); + } + + pkt->pa_base = dma_addr; + + return pkt; +} +EXPORT_SYMBOL(cmdq_pkt_create); + +void cmdq_pkt_destroy(struct cmdq_pkt *pk
MediaTek MT8173 CMDQ support
Hi, This is Mediatek MT8173 Command Queue(CMDQ) driver. The CMDQ is used to help write registers with critical time limitation, such as updating display configuration during the vblank. It controls Global Command Engine (GCE) hardware to achieve this requirement. Changes since v24: -move WARN_ON() into cmdq_pkt_append_command() from outside Changes since v23: -rebase on v4.19-rc1 -revise return value of cmdq_mbox_create() -revise cmdq_pkt_create() -add MODULE_LICENSE() for mtk-cmdq-helper.c -adjust functions order in mtk-cmdq.h Changes since v22: -remove properties 'timeout' and 'thread-num' from device tree -move timer from CMDQ driver to CMDQ helper -move dma unmap from CMDQ driver to CMDQ helper -config thread number in CMDQ match table -remove reallocate mechanism and let client specify the cmdq buffer size -let client specify the timeout time Changes since v21: -rebase on v4.18-rc1 -remove subsys code and event id definition from mtk-cmdq-helper.c -add mt8173-gce.h to define the subsys code and envent id Changes since v20: -rebase on v4.15-rc1 -move dma_map_single outside of spinlock Changes since v19: -rebase to v4.10-rc2 Houlong Wei (2): arm64: dts: mt8173: Add GCE node soc: mediatek: Add Mediatek CMDQ helper arch/arm64/boot/dts/mediatek/mt8173.dtsi | 10 + drivers/soc/mediatek/Kconfig | 12 ++ drivers/soc/mediatek/Makefile|1 + drivers/soc/mediatek/mtk-cmdq-helper.c | 291 ++ include/linux/soc/mediatek/mtk-cmdq.h| 133 ++ 5 files changed, 447 insertions(+) create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h -- 1.7.9.5
Re: [PATCH v23 4/4] soc: mediatek: Add Mediatek CMDQ helper
On Wed, 2018-09-26 at 23:53 +0800, Matthias Brugger wrote: > > On 25/07/2018 03:26, Houlong Wei wrote: > > Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. > > > > Signed-off-by: Houlong Wei > > Signed-off-by: HS Liao > > --- > > drivers/soc/mediatek/Kconfig | 12 ++ > > drivers/soc/mediatek/Makefile |1 + > > drivers/soc/mediatek/mtk-cmdq-helper.c | 291 > > > > include/linux/soc/mediatek/mtk-cmdq.h | 135 +++ > > 4 files changed, 439 insertions(+) > > create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c > > create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h [...] > > + > > +struct cmdq_client *cmdq_mbox_create(struct device *dev, int index, u32 > > timeout) > > +{ > > + struct cmdq_client *client; > > + > > + client = kzalloc(sizeof(*client), GFP_KERNEL); > > + if (!client) > > + return (struct cmdq_client *)-ENOMEM; > > + > > + client->timeout_ms = timeout; > > + if (timeout != CMDQ_NO_TIMEOUT) { > > + spin_lock_init(>lock); > > + timer_setup(>timer, cmdq_client_timeout, 0); > > + } > > + client->pkt_cnt = 0; > > + client->client.dev = dev; > > + client->client.tx_block = false; > > + client->chan = mbox_request_channel(>client, index); > > + > > + if (IS_ERR(client->chan)) { > > + long err = 0; > > + > > + dev_err(dev, "failed to request channel\n"); > > + err = PTR_ERR(client->chan); > > + kfree(client); > > + > > + return (struct cmdq_client *)err; > > Can't we use > return ERR_PTR(err); > here? Sure, will fix it. > > > + } > > + > > + return client; > > +} > > +EXPORT_SYMBOL(cmdq_mbox_create); > > + > > +void cmdq_mbox_destroy(struct cmdq_client *client) > > +{ > > + if (client->timeout_ms != CMDQ_NO_TIMEOUT) { > > + spin_lock(>lock); > > + del_timer_sync(>timer); > > + spin_unlock(>lock); > > + } > > + mbox_free_channel(client->chan); > > + kfree(client); > > +} > > +EXPORT_SYMBOL(cmdq_mbox_destroy); > > + > > +int cmdq_pkt_create(struct cmdq_client *client, struct cmdq_pkt **pkt_ptr, > > + size_t size) > > I suppose you are not returning the allocated cmdq_pkt to avoid checks for > IS_ERR() logic in the consumer of this API. Am I correct? > Do we really need a pointer to a pointer here? Can't we just use a struct > cmdq_pkt *pkt as argument? That would make things easier. Do you mean we change the argument 'struct cmdq_pkt **pkt_ptr' to 'struct cmdq_pkt *pkt', and the consumer allocate a struct cmdq_pkt *pkt, then pass pkt as argument of this API? If yes, the consumer still need to check the return value of this API. For the current implementation, the consumer doesn't need check IS_ERR(*pkt_ptr) if the return value equals to 0. Since the consumer has to check the return value of this API once, to make it simpler, I shall change the prototype to 'struct cmdq_pkt *cmdq_pkt_create(struct cmdq_client *client, size_t size)' and change its implementation. > > > +{ > > + struct cmdq_pkt *pkt; > > + struct device *dev; > > + dma_addr_t dma_addr; > > + > > + pkt = kzalloc(sizeof(*pkt), GFP_KERNEL); > > + if (!pkt) > > + return -ENOMEM; > > + pkt->va_base = kzalloc(size, GFP_KERNEL); > > + if (!pkt->va_base) { > > + kfree(pkt); > > + return -ENOMEM; > > + } > > + pkt->buf_size = size; > > + pkt->cl = (void *)client; > > + > > + dev = client->chan->mbox->dev; > > + dma_addr = dma_map_single(dev, pkt->va_base, pkt->buf_size, > > + DMA_TO_DEVICE); > > + if (dma_mapping_error(dev, dma_addr)) { > > + dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size); > > + kfree(pkt->va_base); > > + kfree(pkt); > > + return -ENOMEM; > > + } > > + > > + pkt->pa_base = dma_addr; > > + *pkt_ptr = pkt; > > + > > + return 0; > > +} > > +EXPORT_SYMBOL(cmdq_pkt_create); > > + > > +void cmdq_pkt_destroy(struct cmdq_pkt *pkt) > > +{ > > + struct cmdq_client *client = (struct cmdq_client *)pkt->cl; > > + > > + dma_unmap_single(client->chan->mbox->dev, pkt->pa_base, pkt->buf_size, > > +
[PATCH v24 0/2] MediaTek MT8173 CMDQ support
Hi, This is Mediatek MT8173 Command Queue(CMDQ) driver. The CMDQ is used to help write registers with critical time limitation, such as updating display configuration during the vblank. It controls Global Command Engine (GCE) hardware to achieve this requirement. Changes since v23: -rebase on v4.19-rc1 -revise return value of cmdq_mbox_create() -revise cmdq_pkt_create() -add MODULE_LICENSE() for mtk-cmdq-helper.c -adjust functions order in mtk-cmdq.h Changes since v22: -remove properties 'timeout' and 'thread-num' from device tree -move timer from CMDQ driver to CMDQ helper -move dma unmap from CMDQ driver to CMDQ helper -config thread number in CMDQ match table -remove reallocate mechanism and let client specify the cmdq buffer size -let client specify the timeout time Changes since v21: -rebase on v4.18-rc1 -remove subsys code and event id definition from mtk-cmdq-helper.c -add mt8173-gce.h to define the subsys code and envent id Changes since v20: -rebase on v4.15-rc1 -move dma_map_single outside of spinlock Changes since v19: -rebase to v4.10-rc2 Houlong Wei (2): arm64: dts: mt8173: Add GCE node soc: mediatek: Add Mediatek CMDQ helper arch/arm64/boot/dts/mediatek/mt8173.dtsi | 10 + drivers/soc/mediatek/Kconfig | 12 ++ drivers/soc/mediatek/Makefile|1 + drivers/soc/mediatek/mtk-cmdq-helper.c | 292 ++ include/linux/soc/mediatek/mtk-cmdq.h| 133 ++ 5 files changed, 448 insertions(+) create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h -- 1.7.9.5
[PATCH v24 2/2] soc: mediatek: Add Mediatek CMDQ helper
Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. Signed-off-by: Houlong Wei Signed-off-by: HS Liao --- drivers/soc/mediatek/Kconfig | 12 ++ drivers/soc/mediatek/Makefile |1 + drivers/soc/mediatek/mtk-cmdq-helper.c | 292 include/linux/soc/mediatek/mtk-cmdq.h | 133 +++ 4 files changed, 438 insertions(+) create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig index a7d0667..17bd759 100644 --- a/drivers/soc/mediatek/Kconfig +++ b/drivers/soc/mediatek/Kconfig @@ -4,6 +4,18 @@ menu "MediaTek SoC drivers" depends on ARCH_MEDIATEK || COMPILE_TEST +config MTK_CMDQ + tristate "MediaTek CMDQ Support" + depends on ARCH_MEDIATEK || COMPILE_TEST + select MAILBOX + select MTK_CMDQ_MBOX + select MTK_INFRACFG + help + Say yes here to add support for the MediaTek Command Queue (CMDQ) + driver. The CMDQ is used to help read/write registers with critical + time limitation, such as updating display configuration during the + vblank. + config MTK_INFRACFG bool "MediaTek INFRACFG Support" select REGMAP diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile index 12998b0..64ce5ee 100644 --- a/drivers/soc/mediatek/Makefile +++ b/drivers/soc/mediatek/Makefile @@ -1,3 +1,4 @@ +obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c new file mode 100644 index 000..3482dd7 --- /dev/null +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -0,0 +1,292 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2018 MediaTek Inc. + +#include +#include +#include +#include +#include +#include + +#define CMDQ_ARG_A_WRITE_MASK 0x +#define CMDQ_WRITE_ENABLE_MASK BIT(0) +#define CMDQ_EOC_IRQ_ENBIT(0) +#define CMDQ_EOC_CMD ((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \ + << 32 | CMDQ_EOC_IRQ_EN) + +static void cmdq_client_timeout(struct timer_list *t) +{ + struct cmdq_client *client = from_timer(client, t, timer); + + dev_err(client->client.dev, "cmdq timeout!\n"); +} + +struct cmdq_client *cmdq_mbox_create(struct device *dev, int index, u32 timeout) +{ + struct cmdq_client *client; + + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client) + return (struct cmdq_client *)-ENOMEM; + + client->timeout_ms = timeout; + if (timeout != CMDQ_NO_TIMEOUT) { + spin_lock_init(>lock); + timer_setup(>timer, cmdq_client_timeout, 0); + } + client->pkt_cnt = 0; + client->client.dev = dev; + client->client.tx_block = false; + client->chan = mbox_request_channel(>client, index); + + if (IS_ERR(client->chan)) { + long err; + + dev_err(dev, "failed to request channel\n"); + err = PTR_ERR(client->chan); + kfree(client); + + return ERR_PTR(err); + } + + return client; +} +EXPORT_SYMBOL(cmdq_mbox_create); + +void cmdq_mbox_destroy(struct cmdq_client *client) +{ + if (client->timeout_ms != CMDQ_NO_TIMEOUT) { + spin_lock(>lock); + del_timer_sync(>timer); + spin_unlock(>lock); + } + mbox_free_channel(client->chan); + kfree(client); +} +EXPORT_SYMBOL(cmdq_mbox_destroy); + +struct cmdq_pkt *cmdq_pkt_create(struct cmdq_client *client, size_t size) +{ + struct cmdq_pkt *pkt; + struct device *dev; + dma_addr_t dma_addr; + + pkt = kzalloc(sizeof(*pkt), GFP_KERNEL); + if (!pkt) + return ERR_PTR(-ENOMEM); + pkt->va_base = kzalloc(size, GFP_KERNEL); + if (!pkt->va_base) { + kfree(pkt); + return ERR_PTR(-ENOMEM); + } + pkt->buf_size = size; + pkt->cl = (void *)client; + + dev = client->chan->mbox->dev; + dma_addr = dma_map_single(dev, pkt->va_base, pkt->buf_size, + DMA_TO_DEVICE); + if (dma_mapping_error(dev, dma_addr)) { + dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size); + kfree(pkt->va_base); + kfree(pkt); + return ERR_PTR(-ENOMEM); + } + + pkt->pa_base = dma_addr; + + return pkt; +} +EXPORT_SYMBOL(cmdq_pkt_create); + +void cmdq_pkt_destroy(struct cmdq_pkt *pk
[PATCH v24 1/2] arm64: dts: mt8173: Add GCE node
This patch adds the device node of the GCE hardware for CMDQ module. Signed-off-by: Houlong Wei Signed-off-by: HS Liao --- arch/arm64/boot/dts/mediatek/mt8173.dtsi | 10 ++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi index abd2f15..412ffd4 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi @@ -18,6 +18,7 @@ #include #include #include +#include #include "mt8173-pinfunc.h" / { @@ -521,6 +522,15 @@ status = "disabled"; }; + gce: mailbox@10212000 { + compatible = "mediatek,mt8173-gce"; + reg = <0 0x10212000 0 0x1000>; + interrupts = ; + clocks = < CLK_INFRA_GCE>; + clock-names = "gce"; + #mbox-cells = <3>; + }; + mipi_tx0: mipi-dphy@10215000 { compatible = "mediatek,mt8173-mipi-tx"; reg = <0 0x10215000 0 0x1000>; -- 1.7.9.5
Re: [PATCH v23 4/4] soc: mediatek: Add Mediatek CMDQ helper
On Thu, 2018-09-27 at 15:50 +0800, Matthias Brugger wrote: > > On 27/09/2018 03:57, houlong wei wrote: [...] > >>> + > >>> +static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, enum cmdq_code > >>> code, > >>> +u32 arg_a, u32 arg_b) > >>> +{ > >>> + u64 *cmd_ptr; > >>> + > >>> + if (unlikely(pkt->cmd_buf_size + CMDQ_INST_SIZE > pkt->buf_size)) { > >>> + pkt->cmd_buf_size += CMDQ_INST_SIZE; > >> > >> Why do we update the cmd_buf_size here? > > > > Because in developing phase of consumer driver, the consumer has to know > > the real command buffer size after adding command failure. Then the > > consumer will increase the size and run the cmdq flow (cmdq_pkt_create, > > cmdq_pkt_write/wfe...) again. Finally, the consumer get the real size > > and fix it. > > > > But the consumer should know the size it needs for it's buffer and if not it > should be able to decide on it's own how much space it needs. If he get's a > -ENOMEM he implicitly knows that he has to increase the buf_size. Now the size > depends on how many command he has pending and wasn't able to write to the > cmdq_pkt. > > Regards, > Matthias The consumer doesn't know how to calculate the command buffer size that he needs. When the consumer driver is developing, he could ignore the return value of cmdq_pkt_write and other command appending functions. He can print the pkt->cmdq_buf_size after cmdq_pkt_flush() or cmdq_pkt_flush_async() failure. Now he can get the buffer size he needs. I copy your another comment here, so I can reply in one mail. >>If we want to write out a warning to the kernel log, then we should >>but that in the if (unlikely(pkt->cmd_buf_size + CMDQ_INST_SIZE >>pkt->buf_size)) from cmdq_pkt_append_command to make it consistent >>between cmdq_pkt_write, cmdq_pkt_write_mask and cmdq_pkt_finalize. Thanks, I will move WARN_ON() into cmdq_pkt_append_command() before returning -ENOMEM. After your confirmation of the comments above, I will re-send a new patch.
[PATCH v27 0/2] MediaTek MT8173 CMDQ support
Hi, This is Mediatek MT8173 Command Queue(CMDQ) driver. The CMDQ is used to help write registers with critical time limitation, such as updating display configuration during the vblank. It controls Global Command Engine (GCE) hardware to achieve this requirement. Changes since v26: -rebase on v4.20-rc1 -add comment to explain why cmdq_buf_size is increased in case of appending command failure Changes since v25: -Replace WARN_ON() with WARN_ONCE() and add debug information. Changes since v24: -move WARN_ON() into cmdq_pkt_append_command() from outside Changes since v23: -rebase on v4.19-rc1 -revise return value of cmdq_mbox_create() -revise cmdq_pkt_create() -add MODULE_LICENSE() for mtk-cmdq-helper.c -adjust functions order in mtk-cmdq.h Changes since v22: -remove properties 'timeout' and 'thread-num' from device tree -move timer from CMDQ driver to CMDQ helper -move dma unmap from CMDQ driver to CMDQ helper -config thread number in CMDQ match table -remove reallocate mechanism and let client specify the cmdq buffer size -let client specify the timeout time Changes since v21: -rebase on v4.18-rc1 -remove subsys code and event id definition from mtk-cmdq-helper.c -add mt8173-gce.h to define the subsys code and envent id Changes since v20: -rebase on v4.15-rc1 -move dma_map_single outside of spinlock Changes since v19: -rebase to v4.10-rc2 Houlong Wei (2): arm64: dts: mt8173: Add GCE node soc: mediatek: Add Mediatek CMDQ helper arch/arm64/boot/dts/mediatek/mt8173.dtsi | 10 + drivers/soc/mediatek/Kconfig | 12 + drivers/soc/mediatek/Makefile| 1 + drivers/soc/mediatek/mtk-cmdq-helper.c | 300 +++ include/linux/soc/mediatek/mtk-cmdq.h| 133 ++ 5 files changed, 456 insertions(+) create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h -- 2.19.1
[PATCH v27 1/2] arm64: dts: mt8173: Add GCE node
This patch adds the device node of the GCE hardware for CMDQ module. Signed-off-by: Houlong Wei Signed-off-by: HS Liao --- arch/arm64/boot/dts/mediatek/mt8173.dtsi | 10 ++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi index abd2f15..412ffd4 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi @@ -18,6 +18,7 @@ #include #include #include +#include #include "mt8173-pinfunc.h" / { @@ -521,6 +522,15 @@ status = "disabled"; }; + gce: mailbox@10212000 { + compatible = "mediatek,mt8173-gce"; + reg = <0 0x10212000 0 0x1000>; + interrupts = ; + clocks = < CLK_INFRA_GCE>; + clock-names = "gce"; + #mbox-cells = <3>; + }; + mipi_tx0: mipi-dphy@10215000 { compatible = "mediatek,mt8173-mipi-tx"; reg = <0 0x10215000 0 0x1000>; -- 1.7.9.5
[PATCH v27 2/2] soc: mediatek: Add Mediatek CMDQ helper
Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. Signed-off-by: Houlong Wei Signed-off-by: HS Liao --- drivers/soc/mediatek/Kconfig | 12 ++ drivers/soc/mediatek/Makefile |1 + drivers/soc/mediatek/mtk-cmdq-helper.c | 300 include/linux/soc/mediatek/mtk-cmdq.h | 133 ++ 4 files changed, 446 insertions(+) create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig index a7d0667..17bd759 100644 --- a/drivers/soc/mediatek/Kconfig +++ b/drivers/soc/mediatek/Kconfig @@ -4,6 +4,18 @@ menu "MediaTek SoC drivers" depends on ARCH_MEDIATEK || COMPILE_TEST +config MTK_CMDQ + tristate "MediaTek CMDQ Support" + depends on ARCH_MEDIATEK || COMPILE_TEST + select MAILBOX + select MTK_CMDQ_MBOX + select MTK_INFRACFG + help + Say yes here to add support for the MediaTek Command Queue (CMDQ) + driver. The CMDQ is used to help read/write registers with critical + time limitation, such as updating display configuration during the + vblank. + config MTK_INFRACFG bool "MediaTek INFRACFG Support" select REGMAP diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile index 12998b0..64ce5ee 100644 --- a/drivers/soc/mediatek/Makefile +++ b/drivers/soc/mediatek/Makefile @@ -1,3 +1,4 @@ +obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c new file mode 100644 index 000..ff9fef5 --- /dev/null +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -0,0 +1,300 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2018 MediaTek Inc. + +#include +#include +#include +#include +#include +#include + +#define CMDQ_ARG_A_WRITE_MASK 0x +#define CMDQ_WRITE_ENABLE_MASK BIT(0) +#define CMDQ_EOC_IRQ_ENBIT(0) +#define CMDQ_EOC_CMD ((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \ + << 32 | CMDQ_EOC_IRQ_EN) + +static void cmdq_client_timeout(struct timer_list *t) +{ + struct cmdq_client *client = from_timer(client, t, timer); + + dev_err(client->client.dev, "cmdq timeout!\n"); +} + +struct cmdq_client *cmdq_mbox_create(struct device *dev, int index, u32 timeout) +{ + struct cmdq_client *client; + + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client) + return (struct cmdq_client *)-ENOMEM; + + client->timeout_ms = timeout; + if (timeout != CMDQ_NO_TIMEOUT) { + spin_lock_init(>lock); + timer_setup(>timer, cmdq_client_timeout, 0); + } + client->pkt_cnt = 0; + client->client.dev = dev; + client->client.tx_block = false; + client->chan = mbox_request_channel(>client, index); + + if (IS_ERR(client->chan)) { + long err; + + dev_err(dev, "failed to request channel\n"); + err = PTR_ERR(client->chan); + kfree(client); + + return ERR_PTR(err); + } + + return client; +} +EXPORT_SYMBOL(cmdq_mbox_create); + +void cmdq_mbox_destroy(struct cmdq_client *client) +{ + if (client->timeout_ms != CMDQ_NO_TIMEOUT) { + spin_lock(>lock); + del_timer_sync(>timer); + spin_unlock(>lock); + } + mbox_free_channel(client->chan); + kfree(client); +} +EXPORT_SYMBOL(cmdq_mbox_destroy); + +struct cmdq_pkt *cmdq_pkt_create(struct cmdq_client *client, size_t size) +{ + struct cmdq_pkt *pkt; + struct device *dev; + dma_addr_t dma_addr; + + pkt = kzalloc(sizeof(*pkt), GFP_KERNEL); + if (!pkt) + return ERR_PTR(-ENOMEM); + pkt->va_base = kzalloc(size, GFP_KERNEL); + if (!pkt->va_base) { + kfree(pkt); + return ERR_PTR(-ENOMEM); + } + pkt->buf_size = size; + pkt->cl = (void *)client; + + dev = client->chan->mbox->dev; + dma_addr = dma_map_single(dev, pkt->va_base, pkt->buf_size, + DMA_TO_DEVICE); + if (dma_mapping_error(dev, dma_addr)) { + dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size); + kfree(pkt->va_base); + kfree(pkt); + return ERR_PTR(-ENOMEM); + } + + pkt->pa_base = dma_addr; + + return pkt; +} +EXPORT_SYMBOL(cmdq_pkt_create); + +void cmdq_pkt_destroy(struct cmdq_pkt *pk
Re: FW: [PATCH v20 2/4] mailbox: mediatek: Add Mediatek CMDQ driver
Hi Jassi, Sorry for reply so late. According to previous discussion, there are two methods to move dma_map_single() outside of spin_lock. (1) put in mtk-cmdq-helper.c, as described by HS on 2017-02-09. > I think a trade-off solution is to put in mtk-cmdq-helper.c. > Although it is a mailbox client, it is not a CMDQ client. > We can include mailbox_controller.h in mtk-cmdq-helper.c (instead of mtk-cmdq.h), and then map dma at cmdq_pkt_flush_async before mbox_send_message. > pkt->pa_base = dma_map_single(client->chan->mbox->dev, pkt->va_base, > pkt->cmd_buf_size, DMA_TO_DEVICE); (2) schedule a tasklet in send_data(). After internal discussion with HS and other experts, now we prefer method (1). How do you think about it? Thanks Houlong > -Original Message- > From: Horng-Shyang Liao [mailto:hs.l...@mediatek.com] > Sent: Thursday, February 23, 2017 8:48 PM > To: Jassi Brar > Cc: Rob Herring ; Matthias Brugger > ; Daniel Kurtz ; Sascha Hauer > ; Devicetree List ; Linux > Kernel Mailing List ; > linux-arm-ker...@lists.infradead.org; linux-media...@lists.infradead.org; > srv_heupstream ; Sascha Hauer > ; Philipp Zabel ; Nicolas > Boichat ; CK Hu (胡俊光) ; Cawa Cheng > (鄭曄禧) ; Bibby Hsieh (謝濟遠) > ; YT Shen (沈岳霆) ; Daoyuan > Huang (黃道原) ; Damon Chu (朱峻賢) > ; Josh-YC Liu (劉育誠) ; Glory > Hung (洪智瑋) ; Jiaguang Zhang (张加广) > ; Dennis-YC Hsieh (謝宇哲) > ; Monica Wang (王孟婷) ; > Houlong Wei (魏厚龙) ; Hs Liao (廖宏祥) > > Subject: Re: [PATCH v20 2/4] mailbox: mediatek: Add Mediatek CMDQ driver > > On Thu, 2017-02-23 at 09:40 +0530, Jassi Brar wrote: > > On Wed, Feb 22, 2017 at 8:42 AM, Horng-Shyang Liao > > wrote: > > > On Thu, 2017-02-16 at 21:02 +0530, Jassi Brar wrote: > > >> On Mon, Feb 6, 2017 at 11:07 AM, Horng-Shyang Liao > > >> wrote: > > >> > Hi Jassi, > > >> > > > >> > On Wed, 2017-02-01 at 10:52 +0530, Jassi Brar wrote: > > >> >> On Thu, Jan 26, 2017 at 2:07 PM, Horng-Shyang Liao > > >> >> wrote: > > >> >> > Hi Jassi, > > >> >> > > > >> >> > On Thu, 2017-01-26 at 10:08 +0530, Jassi Brar wrote: > > >> >> >> On Wed, Jan 4, 2017 at 8:36 AM, HS Liao > > >> >> >> wrote: > > >> >> >> > > >> >> >> > diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c > > >> >> >> > b/drivers/mailbox/mtk-cmdq-mailbox.c > > >> >> >> > new file mode 100644 > > >> >> >> > index 000..747bcd3 > > >> >> >> > --- /dev/null > > >> >> >> > +++ b/drivers/mailbox/mtk-cmdq-mailbox.c > > >> >> >> > > >> >> >> ... > > >> >> >> > > >> >> >> > +static void cmdq_task_exec(struct cmdq_pkt *pkt, struct > > >> >> >> > +cmdq_thread *thread) { > > >> >> >> > + struct cmdq *cmdq; > > >> >> >> > + struct cmdq_task *task; > > >> >> >> > + unsigned long curr_pa, end_pa; > > >> >> >> > + > > >> >> >> > + cmdq = dev_get_drvdata(thread->chan->mbox->dev); > > >> >> >> > + > > >> >> >> > + /* Client should not flush new tasks if suspended. */ > > >> >> >> > + WARN_ON(cmdq->suspended); > > >> >> >> > + > > >> >> >> > + task = kzalloc(sizeof(*task), GFP_ATOMIC); > > >> >> >> > + task->cmdq = cmdq; > > >> >> >> > + INIT_LIST_HEAD(>list_entry); > > >> >> >> > + task->pa_base = dma_map_single(cmdq->mbox.dev, > > >> >> >> > pkt->va_base, > > >> >> >> > + pkt->cmd_buf_size, > > >> >> >> > + DMA_TO_DEVICE); > > >> >> >> > > > >> >> >> You seem to parse the requests and responses, that should > > >> >> >> ideally be done in client driver. > > >> >> >> Also, we are here in atomic context, can you move it in > > >> >> >> client driver (before the spin_lock)? > > >> >> >> Maybe by adding a new 'pa_base' member as well in 'cmdq_pkt'. > > >> >> > > > >> >> > will do > > >> > > > >> > I agree with moving dma_map_single out from spin_lock. > > >> > > > >> > However, mailbox clients cannot map virtual memory to mailbox > > >> > controller's device for DMA. > > >> > > > >> If DMA is a resource used by MBox to transfer data, then yes the > > >> mapping needs to be done in the Mbox controller driver. To map > > >> memory outside of spinlock, you could schedule a tasklet in send_data() ? > > > > > > Hi Jassi, > > > > > > For CMDQ, the order of CMDQ tasks should be guaranteed. > > > However, it seems tasklet cannot ensure this requirement. > > > > > > Quote from Linux Device Drivers 3rd edition ch7. > > > "void tasklet_schedule(struct tasklet_struct *t); > > > Schedule the tasklet for execution. If a tasklet is scheduled > > > again before it has a chance to run, it runs only once" > > > > > Not sure what bothers you. > > If you only add requests to a list, protected by some spinlock, during > > send_datam you could always iterate over (submit) requests in the > > order you queued them. > > Hi Jassi, > > OK. I will do it. > > Thanks, > HS > > >
[PATCH] soc: mediatek: cmdq: fixup possible timeout issue
Fixes: 576f1b4bc802 ("soc: mediatek: Add Mediatek CMDQ helper") There may be possible timeout issue when lots of cmdq packets are flushed to the same cmdq client. The necessary modifications are as below. 1.Adjust the timer timeout period as client->timeout_ms * client->pkt_cnt. 2.Optimize the time to start the timer. Signed-off-by: Houlong Wei --- drivers/soc/mediatek/mtk-cmdq-helper.c | 22 ++ 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index dc644cfb6419..31142c193527 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -350,7 +350,8 @@ static void cmdq_pkt_flush_async_cb(struct cmdq_cb_data data) del_timer(>timer); else mod_timer(>timer, jiffies + - msecs_to_jiffies(client->timeout_ms)); + msecs_to_jiffies(client->timeout_ms * + client->pkt_cnt)); spin_unlock_irqrestore(>lock, flags); } @@ -379,9 +380,7 @@ int cmdq_pkt_flush_async(struct cmdq_pkt *pkt, cmdq_async_flush_cb cb, if (client->timeout_ms != CMDQ_NO_TIMEOUT) { spin_lock_irqsave(>lock, flags); - if (client->pkt_cnt++ == 0) - mod_timer(>timer, jiffies + - msecs_to_jiffies(client->timeout_ms)); + client->pkt_cnt++; spin_unlock_irqrestore(>lock, flags); } @@ -391,6 +390,21 @@ int cmdq_pkt_flush_async(struct cmdq_pkt *pkt, cmdq_async_flush_cb cb, /* We can send next packet immediately, so just call txdone. */ mbox_client_txdone(client->chan, 0); + if (client->timeout_ms != CMDQ_NO_TIMEOUT) { + spin_lock_irqsave(>lock, flags); + /* +* GCE HW maybe execute too quickly and the callback function +* may be invoked earlier. If this happens, pkt_cnt is reduced +* by 1 in cmdq_pkt_flush_async_cb(). The timer is set only if +* pkt_cnt is greater than 0. +*/ + if (client->pkt_cnt > 0) + mod_timer(>timer, jiffies + + msecs_to_jiffies(client->timeout_ms * + client->pkt_cnt)); + spin_unlock_irqrestore(>lock, flags); + } + return 0; } EXPORT_SYMBOL(cmdq_pkt_flush_async); -- 2.18.0
Re: [PATCH v12 09/12] soc: mediatek: cmdq: define the instruction struct
On Mon, 2019-08-19 at 10:53 +0800, Bibby Hsieh wrote: > Define an instruction structure for gce driver to append command. > This structure can make the client's code more readability. > > Signed-off-by: Bibby Hsieh > Reviewed-by: CK Hu > --- > drivers/soc/mediatek/mtk-cmdq-helper.c | 105 +++ > include/linux/mailbox/mtk-cmdq-mailbox.h | 2 + > 2 files changed, 73 insertions(+), 34 deletions(-) > > diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c > b/drivers/soc/mediatek/mtk-cmdq-helper.c > index 7aa0517ff2f3..e1e41914ed7a 100644 > --- a/drivers/soc/mediatek/mtk-cmdq-helper.c > +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c > @@ -9,12 +9,24 @@ > #include > #include > > -#define CMDQ_ARG_A_WRITE_MASK0x > #define CMDQ_WRITE_ENABLE_MASK BIT(0) > #define CMDQ_EOC_IRQ_EN BIT(0) > #define CMDQ_EOC_CMD ((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \ > << 32 | CMDQ_EOC_IRQ_EN) > > +struct cmdq_instruction { > + union { > + u32 value; > + u32 mask; > + }; > + union { > + u16 offset; > + u16 event; > + }; > + u8 subsys; > + u8 op; > +}; > + > static void cmdq_client_timeout(struct timer_list *t) > { > struct cmdq_client *client = from_timer(client, t, timer); > @@ -110,10 +122,8 @@ void cmdq_pkt_destroy(struct cmdq_pkt *pkt) > } > EXPORT_SYMBOL(cmdq_pkt_destroy); > > -static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, enum cmdq_code code, > -u32 arg_a, u32 arg_b) > +static struct cmdq_instruction *cmdq_pkt_append_command(struct cmdq_pkt *pkt) > { > - u64 *cmd_ptr; > > if (unlikely(pkt->cmd_buf_size + CMDQ_INST_SIZE > pkt->buf_size)) { > /* > @@ -127,81 +137,108 @@ static int cmdq_pkt_append_command(struct cmdq_pkt > *pkt, enum cmdq_code code, > pkt->cmd_buf_size += CMDQ_INST_SIZE; > WARN_ONCE(1, "%s: buffer size %u is too small !\n", > __func__, (u32)pkt->buf_size); > - return -ENOMEM; > + return NULL; > } > - cmd_ptr = pkt->va_base + pkt->cmd_buf_size; > - (*cmd_ptr) = (u64)((code << CMDQ_OP_CODE_SHIFT) | arg_a) << 32 | arg_b; > + > pkt->cmd_buf_size += CMDQ_INST_SIZE; > > - return 0; > + return pkt->va_base + pkt->cmd_buf_size - CMDQ_INST_SIZE; > } > > int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value) > { > - u32 arg_a = (offset & CMDQ_ARG_A_WRITE_MASK) | > - (subsys << CMDQ_SUBSYS_SHIFT); > + struct cmdq_instruction *inst; > + > + inst = cmdq_pkt_append_command(pkt); > + if (!inst) > + return -ENOMEM; > + > + inst->op = CMDQ_CODE_WRITE; > + inst->value = value; > + inst->offset = offset; > + inst->subsys = subsys; > > - return cmdq_pkt_append_command(pkt, CMDQ_CODE_WRITE, arg_a, value); > + return 0; > } > EXPORT_SYMBOL(cmdq_pkt_write); > > int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys, > u16 offset, u32 value, u32 mask) > { > - u32 offset_mask = offset; > - int err = 0; > + struct cmdq_instruction *inst; > + u16 offset_mask = offset; > > if (mask != 0x) { > - err = cmdq_pkt_append_command(pkt, CMDQ_CODE_MASK, 0, ~mask); > + inst = cmdq_pkt_append_command(pkt); > + if (!inst) > + return -ENOMEM; > + > + inst->op = CMDQ_CODE_MASK; > + inst->mask = ~mask; > offset_mask |= CMDQ_WRITE_ENABLE_MASK; I think we should consider the reusing command packet case, I commented via link below and there were discussion before. http://lists.infradead.org/pipermail/linux-mediatek/2019-August/022052.html Before this patch, each 64-bit of an instruction is set. But now some bits may be ignored and keep the original values. That may make us confused when we analyze the instruction for debugging. > } > - err |= cmdq_pkt_write(pkt, value, subsys, offset_mask); > > - return err; > + return cmdq_pkt_write(pkt, subsys, offset_mask, value); > } > EXPORT_SYMBOL(cmdq_pkt_write_mask); > > int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event) > { > - u32 arg_b; > + struct cmdq_instruction *inst; > > if (event >= CMDQ_MAX_EVENT) > return -EINVAL; > > - /* > - * WFE arg_b > - * bit 0-11: wait value > - * bit 15: 1 - wait, 0 - no wait > - * bit 16-27: update value > - * bit 31: 1 - update, 0 - no update > - */ > - arg_b = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE; > + inst = cmdq_pkt_append_command(pkt); > + if (!inst) > + return -ENOMEM; > + > + inst->op = CMDQ_CODE_WFE; > + inst->value = CMDQ_WFE_OPTION; > + inst->event = event; > > - return cmdq_pkt_append_command(pkt, CMDQ_CODE_WFE,
Re: [PATCH v12 11/12] soc: mediatek: cmdq: add cmdq_dev_get_client_reg function
On Mon, 2019-08-19 at 10:53 +0800, Bibby Hsieh wrote: > GCE cannot know the register base address, this function > can help cmdq client to get the cmdq_client_reg structure. > > Signed-off-by: Bibby Hsieh > --- > drivers/soc/mediatek/mtk-cmdq-helper.c | 29 ++ > include/linux/soc/mediatek/mtk-cmdq.h | 21 +++ > 2 files changed, 50 insertions(+) > [...] > > +/** > + * cmdq_dev_get_client_reg() - parse cmdq client reg from the device > + * node of CMDQ client > + * @dev: device of CMDQ mailbox clienti 'clienti' looks like a typo, 'client'? > + * @client_reg: CMDQ client reg pointer > + * @idx: the index of desired reg > + * > + * Return: 0 for success; else the error code is returned > + * > + * Help CMDQ client pasing the cmdq client reg 'pasing' looks like a typo, 'parsing'? > + * from the device node of CMDQ client. > + */ > +int cmdq_dev_get_client_reg(struct device *dev, > + struct cmdq_client_reg *client_reg, int idx); > + > /** > * cmdq_mbox_create() - create CMDQ mailbox client and channel > * @dev: device of CMDQ mailbox client
Re: [RESEND, PATCH v13 09/12] soc: mediatek: cmdq: define the instruction struct
Reviewed-by: Houlong Wei On Tue, 2019-08-20 at 16:49 +0800, Bibby Hsieh wrote: > Define an instruction structure for gce driver to append command. > This structure can make the client's code more readability. > > Signed-off-by: Bibby Hsieh > Reviewed-by: CK Hu > --- > drivers/soc/mediatek/mtk-cmdq-helper.c | 106 +++ > include/linux/mailbox/mtk-cmdq-mailbox.h | 2 + > 2 files changed, 74 insertions(+), 34 deletions(-) > > diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c > b/drivers/soc/mediatek/mtk-cmdq-helper.c > index 7aa0517ff2f3..e3d5b0be8e79 100644 > --- a/drivers/soc/mediatek/mtk-cmdq-helper.c > +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c > @@ -9,12 +9,24 @@ > #include > #include > > -#define CMDQ_ARG_A_WRITE_MASK0x > #define CMDQ_WRITE_ENABLE_MASK BIT(0) > #define CMDQ_EOC_IRQ_EN BIT(0) > #define CMDQ_EOC_CMD ((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \ > << 32 | CMDQ_EOC_IRQ_EN) > > +struct cmdq_instruction { > + union { > + u32 value; > + u32 mask; > + }; > + union { > + u16 offset; > + u16 event; > + }; > + u8 subsys; > + u8 op; > +}; > + > static void cmdq_client_timeout(struct timer_list *t) > { > struct cmdq_client *client = from_timer(client, t, timer); > @@ -110,10 +122,8 @@ void cmdq_pkt_destroy(struct cmdq_pkt *pkt) > } > EXPORT_SYMBOL(cmdq_pkt_destroy); > > -static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, enum cmdq_code code, > -u32 arg_a, u32 arg_b) > +static struct cmdq_instruction *cmdq_pkt_append_command(struct cmdq_pkt *pkt) > { > - u64 *cmd_ptr; > > if (unlikely(pkt->cmd_buf_size + CMDQ_INST_SIZE > pkt->buf_size)) { > /* > @@ -127,81 +137,109 @@ static int cmdq_pkt_append_command(struct cmdq_pkt > *pkt, enum cmdq_code code, > pkt->cmd_buf_size += CMDQ_INST_SIZE; > WARN_ONCE(1, "%s: buffer size %u is too small !\n", > __func__, (u32)pkt->buf_size); > - return -ENOMEM; > + return NULL; > } > - cmd_ptr = pkt->va_base + pkt->cmd_buf_size; > - (*cmd_ptr) = (u64)((code << CMDQ_OP_CODE_SHIFT) | arg_a) << 32 | arg_b; > + > + *(u64 *)(pkt->va_base + pkt->cmd_buf_size) = 0; > pkt->cmd_buf_size += CMDQ_INST_SIZE; > > - return 0; > + return pkt->va_base + pkt->cmd_buf_size - CMDQ_INST_SIZE; > } > > int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value) > { > - u32 arg_a = (offset & CMDQ_ARG_A_WRITE_MASK) | > - (subsys << CMDQ_SUBSYS_SHIFT); > + struct cmdq_instruction *inst; > + > + inst = cmdq_pkt_append_command(pkt); > + if (!inst) > + return -ENOMEM; > + > + inst->op = CMDQ_CODE_WRITE; > + inst->value = value; > + inst->offset = offset; > + inst->subsys = subsys; > > - return cmdq_pkt_append_command(pkt, CMDQ_CODE_WRITE, arg_a, value); > + return 0; > } > EXPORT_SYMBOL(cmdq_pkt_write); > > int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys, > u16 offset, u32 value, u32 mask) > { > - u32 offset_mask = offset; > - int err = 0; > + struct cmdq_instruction *inst; > + u16 offset_mask = offset; > > if (mask != 0x) { > - err = cmdq_pkt_append_command(pkt, CMDQ_CODE_MASK, 0, ~mask); > + inst = cmdq_pkt_append_command(pkt); > + if (!inst) > + return -ENOMEM; > + > + inst->op = CMDQ_CODE_MASK; > + inst->mask = ~mask; > offset_mask |= CMDQ_WRITE_ENABLE_MASK; > } > - err |= cmdq_pkt_write(pkt, value, subsys, offset_mask); > > - return err; > + return cmdq_pkt_write(pkt, subsys, offset_mask, value); > } > EXPORT_SYMBOL(cmdq_pkt_write_mask); > > int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event) > { > - u32 arg_b; > + struct cmdq_instruction *inst; > > if (event >= CMDQ_MAX_EVENT) > return -EINVAL; > > - /* > - * WFE arg_b > - * bit 0-11: wait value > - * bit 15: 1 - wait, 0 - no wait > - * bit 16-27: update value > - * bit 31: 1 - update, 0 - no update > - */ > - arg_b = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE; > + inst = cmdq_pkt_append_command(pkt); > + if (!in
Re: [RESEND, PATCH v13 11/12] soc: mediatek: cmdq: add cmdq_dev_get_client_reg function
Reviewed-by: Houlong Wei
Re: [RESEND, PATCH v13 11/12] soc: mediatek: cmdq: add cmdq_dev_get_client_reg function
On Tue, 2019-08-20 at 16:49 +0800, Bibby Hsieh wrote: > GCE cannot know the register base address, this function > can help cmdq client to get the cmdq_client_reg structure. > > Signed-off-by: Bibby Hsieh > Reviewed-by: CK Hu > --- > drivers/soc/mediatek/mtk-cmdq-helper.c | 29 ++ > include/linux/soc/mediatek/mtk-cmdq.h | 21 +++ > 2 files changed, 50 insertions(+) > > diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c > b/drivers/soc/mediatek/mtk-cmdq-helper.c > index c53f8476c68d..80f75a1075b4 100644 > --- a/drivers/soc/mediatek/mtk-cmdq-helper.c > +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c > @@ -27,6 +27,35 @@ struct cmdq_instruction { > u8 op; > }; > > +int cmdq_dev_get_client_reg(struct device *dev, > + struct cmdq_client_reg *client_reg, int idx) > +{ > + struct of_phandle_args spec; > + int err; > + > + if (!client_reg) > + return -ENOENT; > + > + err = of_parse_phandle_with_fixed_args(dev->of_node, > +"mediatek,gce-client-reg", > +3, idx, ); > + if (err < 0) { > + dev_err(dev, > + "error %d can't parse gce-client-reg property (%d)", > + err, idx); > + > + return err; > + } > + > + client_reg->subsys = (u8)spec.args[0]; > + client_reg->offset = (u16)spec.args[1]; > + client_reg->size = (u16)spec.args[2]; > + of_node_put(spec.np); > + > + return 0; > +} > +EXPORT_SYMBOL(cmdq_dev_get_client_reg); > + > static void cmdq_client_timeout(struct timer_list *t) > { > struct cmdq_client *client = from_timer(client, t, timer); > diff --git a/include/linux/soc/mediatek/mtk-cmdq.h > b/include/linux/soc/mediatek/mtk-cmdq.h > index a345870a6d10..02ddd60b212f 100644 > --- a/include/linux/soc/mediatek/mtk-cmdq.h > +++ b/include/linux/soc/mediatek/mtk-cmdq.h > @@ -15,6 +15,12 @@ > > struct cmdq_pkt; > > +struct cmdq_client_reg { > + u8 subsys; > + u16 offset; > + u16 size; > +}; > + > struct cmdq_client { > spinlock_t lock; > u32 pkt_cnt; > @@ -24,6 +30,21 @@ struct cmdq_client { > u32 timeout_ms; /* in unit of microsecond */ > }; > > +/** > + * cmdq_dev_get_client_reg() - parse cmdq client reg from the device > + * node of CMDQ client > + * @dev: device of CMDQ mailbox client > + * @client_reg: CMDQ client reg pointer > + * @idx: the index of desired reg > + * > + * Return: 0 for success; else the error code is returned > + * > + * Help CMDQ client parsing the cmdq client reg > + * from the device node of CMDQ client. > + */ > +int cmdq_dev_get_client_reg(struct device *dev, > + struct cmdq_client_reg *client_reg, int idx); > + > /** > * cmdq_mbox_create() - create CMDQ mailbox client and channel > * @dev: device of CMDQ mailbox client Reviewed-by: Houlong Wei
Re: [RESEND, PATCH v13 10/12] soc: mediatek: cmdq: add polling function
On Tue, 2019-08-20 at 16:49 +0800, Bibby Hsieh wrote: > add polling function in cmdq helper functions > > Signed-off-by: Bibby Hsieh > Reviewed-by: CK Hu > --- > drivers/soc/mediatek/mtk-cmdq-helper.c | 28 > include/linux/mailbox/mtk-cmdq-mailbox.h | 1 + > include/linux/soc/mediatek/mtk-cmdq.h| 15 + > 3 files changed, 44 insertions(+) > > diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c > b/drivers/soc/mediatek/mtk-cmdq-helper.c > index e3d5b0be8e79..c53f8476c68d 100644 > --- a/drivers/soc/mediatek/mtk-cmdq-helper.c > +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c > @@ -221,6 +221,34 @@ int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event) > } > EXPORT_SYMBOL(cmdq_pkt_clear_event); > > +int cmdq_pkt_poll(struct cmdq_pkt *pkt, u8 subsys, > + u16 offset, u32 value, u32 mask) > +{ > + struct cmdq_instruction *inst; > + > + if (mask != 0x) { > + inst = cmdq_pkt_append_command(pkt); > + if (!inst) > + return -ENOMEM; > + > + inst->op = CMDQ_CODE_MASK; > + inst->value = ~mask; > + offset = offset | 0x1; > + } > + > + inst = cmdq_pkt_append_command(pkt); > + if (!inst) > + return -ENOMEM; > + > + inst->op = CMDQ_CODE_POLL; > + inst->value = value; > + inst->offset = offset; > + inst->subsys = subsys; > + > + return 0; > +} > +EXPORT_SYMBOL(cmdq_pkt_poll); > + > static int cmdq_pkt_finalize(struct cmdq_pkt *pkt) > { > struct cmdq_instruction *inst; > diff --git a/include/linux/mailbox/mtk-cmdq-mailbox.h > b/include/linux/mailbox/mtk-cmdq-mailbox.h > index c8adedefaf42..9e3502945bc1 100644 > --- a/include/linux/mailbox/mtk-cmdq-mailbox.h > +++ b/include/linux/mailbox/mtk-cmdq-mailbox.h > @@ -46,6 +46,7 @@ > enum cmdq_code { > CMDQ_CODE_MASK = 0x02, > CMDQ_CODE_WRITE = 0x04, > + CMDQ_CODE_POLL = 0x08, > CMDQ_CODE_JUMP = 0x10, > CMDQ_CODE_WFE = 0x20, > CMDQ_CODE_EOC = 0x40, > diff --git a/include/linux/soc/mediatek/mtk-cmdq.h > b/include/linux/soc/mediatek/mtk-cmdq.h > index 9618debb9ceb..a345870a6d10 100644 > --- a/include/linux/soc/mediatek/mtk-cmdq.h > +++ b/include/linux/soc/mediatek/mtk-cmdq.h > @@ -99,6 +99,21 @@ int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event); > */ > int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event); > > +/** > + * cmdq_pkt_poll() - Append polling command to the CMDQ packet, ask GCE to > + *execute an instruction that wait for a specified hardware > + *register to check for the value. All GCE hardware > + *threads will be blocked by this instruction. > + * @pkt: the CMDQ packet > + * @subsys: the CMDQ sub system code > + * @offset: register offset from CMDQ sub system > + * @value: the specified target register value > + * @mask:the specified target register mask > + * > + * Return: 0 for success; else the error code is returned > + */ > +int cmdq_pkt_poll(struct cmdq_pkt *pkt, u8 subsys, > + u16 offset, u32 value, u32 mask); > /** > * cmdq_pkt_flush_async() - trigger CMDQ to asynchronously execute the CMDQ > * packet and call back at the end of done packet Reviewed-by: Houlong Wei
Re: [PATCH v21 4/4] soc: mediatek: Add Mediatek CMDQ helper
On Tue, 2018-02-06 at 10:52 +0800, CK Hu wrote: > Hi, Houlong: > > I've some inline comment. > > On Wed, 2018-01-31 at 15:28 +0800, houlong@mediatek.com wrote: > > From: "hs.l...@mediatek.com" > > > > Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. > > > > Signed-off-by: Houlong Wei > > Signed-off-by: HS Liao > > --- > > drivers/soc/mediatek/Kconfig | 12 ++ > > drivers/soc/mediatek/Makefile |1 + > > drivers/soc/mediatek/mtk-cmdq-helper.c | 322 > > > > include/linux/soc/mediatek/mtk-cmdq.h | 174 + > > 4 files changed, 509 insertions(+) > > create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c > > create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h > > > > diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig > > index a7d0667..e66582e 100644 > > --- a/drivers/soc/mediatek/Kconfig > > +++ b/drivers/soc/mediatek/Kconfig > > @@ -4,6 +4,18 @@ > > menu "MediaTek SoC drivers" > > depends on ARCH_MEDIATEK || COMPILE_TEST > > > > +config MTK_CMDQ > > +bool "MediaTek CMDQ Support" > > +depends on ARM64 && ( ARCH_MEDIATEK || COMPILE_TEST ) > > +select MAILBOX > > +select MTK_CMDQ_MBOX > > +select MTK_INFRACFG > > +help > > + Say yes here to add support for the MediaTek Command Queue (CMDQ) > > + driver. The CMDQ is used to help read/write registers with critical > > + time limitation, such as updating display configuration during the > > + vblank. > > + > > config MTK_INFRACFG > > bool "MediaTek INFRACFG Support" > > select REGMAP > > diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile > > index 12998b0..64ce5ee 100644 > > --- a/drivers/soc/mediatek/Makefile > > +++ b/drivers/soc/mediatek/Makefile > > @@ -1,3 +1,4 @@ > > +obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o > > obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o > > obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o > > obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o > > diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c > > b/drivers/soc/mediatek/mtk-cmdq-helper.c > > new file mode 100644 > > index 000..80d0558 > > --- /dev/null > > +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c > > @@ -0,0 +1,322 @@ > > +/* > > + * Copyright (c) 2015 MediaTek Inc. > > + * > > + * This program is free software; you can redistribute it and/or modify > > + * it under the terms of the GNU General Public License version 2 as > > + * published by the Free Software Foundation. > > + * > > + * This program is distributed in the hope that it will be useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#define CMDQ_ARG_A_WRITE_MASK0x > > +#define CMDQ_WRITE_ENABLE_MASKBIT(0) > > +#define CMDQ_EOC_IRQ_ENBIT(0) > > +#define CMDQ_EOC_CMD((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \ > > +<< 32 | CMDQ_EOC_IRQ_EN) > > + > > +struct cmdq_subsys { > > +u32base; > > +intid; > > +}; > > + > > +static const struct cmdq_subsys gce_subsys[] = { > > +{0x1400, 1}, > > +{0x1401, 2}, > > +{0x1402, 3}, > > +}; > > I think subsys definition varies by different SoC, so it's better to > pass these definition from device tree to driver (client driver), and > client driver pass this subsys in the related interface. For example, > > in include/dt-bindings/gce/mt8173-gce.h, you define > > #define GCE_SUBSYS_14001 > #define GCE_SUBSYS_14012 > #define GCE_SUBSYS_14023 > > in device tree, place the subsys definition in client device node, > > #include "dt-bindings/gce/mt8173-gce.h" > > ovl0: ovl@1400c000 { > compatible = "mediatek,mt8173-disp-ovl"; > gce-subsys = ; > ... > }; > > And client driver pass subsys in the related interface, > > int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 > value); > > So, for another SoC, you just need to modify device tree and you do not > need to modify driver. > > + > > +static int cmdq_subsys_base_to_id(u32 base) > > +{ > > +int i; > > + > > +for (i = 0;
Re: [PATCH v20 2/4] mailbox: mediatek: Add Mediatek CMDQ driver
Hi Jassi, We prefer to use method (1) to move dma_map_single() outside of spin_lock. Do you have any comment about this? Thanks, Houlong On Mon, 2018-01-08 at 16:38 +0800, houlong wei wrote: > Hi Jassi, > > Sorry for reply so late. > According to previous discussion, there are two methods to move > dma_map_single() outside of spin_lock. > (1) put in mtk-cmdq-helper.c, as described by HS on 2017-02-09. > > I think a trade-off solution is to put in mtk-cmdq-helper.c. > > Although it is a mailbox client, it is not a CMDQ client. > > We can include mailbox_controller.h in mtk-cmdq-helper.c (instead of > mtk-cmdq.h), and then map dma at cmdq_pkt_flush_async before > mbox_send_message. > > > pkt->pa_base = dma_map_single(client->chan->mbox->dev, pkt->va_base, > > pkt->cmd_buf_size, DMA_TO_DEVICE); > (2) schedule a tasklet in send_data(). > > After internal discussion with HS and other experts, now we prefer > method (1). > How do you think about it? > > Thanks > Houlong > > > > -Original Message- > > From: Horng-Shyang Liao [mailto:hs.l...@mediatek.com] > > Sent: Thursday, February 23, 2017 8:48 PM > > To: Jassi Brar > > Cc: Rob Herring ; Matthias Brugger > > ; Daniel Kurtz ; Sascha Hauer > > ; Devicetree List ; > > Linux Kernel Mailing List ; > > linux-arm-ker...@lists.infradead.org; linux-media...@lists.infradead.org; > > srv_heupstream ; Sascha Hauer > > ; Philipp Zabel ; Nicolas > > Boichat ; CK Hu (胡俊光) ; Cawa > > Cheng (鄭曄禧) ; Bibby Hsieh (謝濟遠) > > ; YT Shen (沈岳霆) ; Daoyuan > > Huang (黃道原) ; Damon Chu (朱峻賢) > > ; Josh-YC Liu (劉育誠) ; > > Glory Hung (洪智瑋) ; Jiaguang Zhang (张加广) > > ; Dennis-YC Hsieh (謝宇哲) > > ; Monica Wang (王孟婷) > > ; Houlong Wei (魏厚龙) ; > > Hs Liao (廖宏祥) > > Subject: Re: [PATCH v20 2/4] mailbox: mediatek: Add Mediatek CMDQ driver > > > > On Thu, 2017-02-23 at 09:40 +0530, Jassi Brar wrote: > > > On Wed, Feb 22, 2017 at 8:42 AM, Horng-Shyang Liao > > > wrote: > > > > On Thu, 2017-02-16 at 21:02 +0530, Jassi Brar wrote: > > > >> On Mon, Feb 6, 2017 at 11:07 AM, Horng-Shyang Liao > > > >> wrote: > > > >> > Hi Jassi, > > > >> > > > > >> > On Wed, 2017-02-01 at 10:52 +0530, Jassi Brar wrote: > > > >> >> On Thu, Jan 26, 2017 at 2:07 PM, Horng-Shyang Liao > > > >> >> wrote: > > > >> >> > Hi Jassi, > > > >> >> > > > > >> >> > On Thu, 2017-01-26 at 10:08 +0530, Jassi Brar wrote: > > > >> >> >> On Wed, Jan 4, 2017 at 8:36 AM, HS Liao > > > >> >> >> wrote: > > > >> >> >> > > > >> >> >> > diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c > > > >> >> >> > b/drivers/mailbox/mtk-cmdq-mailbox.c > > > >> >> >> > new file mode 100644 > > > >> >> >> > index 000..747bcd3 > > > >> >> >> > --- /dev/null > > > >> >> >> > +++ b/drivers/mailbox/mtk-cmdq-mailbox.c > > > >> >> >> > > > >> >> >> ... > > > >> >> >> > > > >> >> >> > +static void cmdq_task_exec(struct cmdq_pkt *pkt, struct > > > >> >> >> > +cmdq_thread *thread) { > > > >> >> >> > + struct cmdq *cmdq; > > > >> >> >> > + struct cmdq_task *task; > > > >> >> >> > + unsigned long curr_pa, end_pa; > > > >> >> >> > + > > > >> >> >> > + cmdq = dev_get_drvdata(thread->chan->mbox->dev); > > > >> >> >> > + > > > >> >> >> > + /* Client should not flush new tasks if suspended. */ > > > >> >> >> > + WARN_ON(cmdq->suspended); > > > >> >> >> > + > > > >> >> >> > + task = kzalloc(sizeof(*task), GFP_ATOMIC); > > > >> >> >> > + task->cmdq = cmdq; > > > >> >> >> > + INIT_LIST_HEAD(>list_entry); > > > >> >> >> > + task->pa_base = dma_map_single(cmdq->mbox.dev, > > > >> >> >> > pkt->va_base, > > > >> >>
Re: FW: [PATCH v20 2/4] mailbox: mediatek: Add Mediatek CMDQ driver
Sorry to send the mail again because I missed some mail lists by mistake. Hi Jassi, We prefer to use method (1) to move dma_map_single() outside of spin_lock. Do you have any comment about this? Thanks, Houlong On Mon, 2018-01-08 at 16:38 +0800, houlong wei wrote: > Hi Jassi, > > Sorry for reply so late. > According to previous discussion, there are two methods to move > dma_map_single() outside of spin_lock. > (1) put in mtk-cmdq-helper.c, as described by HS on 2017-02-09. > > I think a trade-off solution is to put in mtk-cmdq-helper.c. > > Although it is a mailbox client, it is not a CMDQ client. > > We can include mailbox_controller.h in mtk-cmdq-helper.c (instead of > mtk-cmdq.h), and then map dma at cmdq_pkt_flush_async before > mbox_send_message. > > > pkt->pa_base = dma_map_single(client->chan->mbox->dev, pkt->va_base, > > pkt->cmd_buf_size, DMA_TO_DEVICE); > (2) schedule a tasklet in send_data(). > > After internal discussion with HS and other experts, now we prefer > method (1). > How do you think about it? > > Thanks > Houlong > > > > -Original Message- > > From: Horng-Shyang Liao [mailto:hs.l...@mediatek.com] > > Sent: Thursday, February 23, 2017 8:48 PM > > To: Jassi Brar > > Cc: Rob Herring ; Matthias Brugger > > ; Daniel Kurtz ; Sascha Hauer > > ; Devicetree List ; > > Linux Kernel Mailing List ; > > linux-arm-ker...@lists.infradead.org; linux-media...@lists.infradead.org; > > srv_heupstream ; Sascha Hauer > > ; Philipp Zabel ; Nicolas > > Boichat ; CK Hu (胡俊光) ; Cawa > > Cheng (鄭曄禧) ; Bibby Hsieh (謝濟遠) > > ; YT Shen (沈岳霆) ; Daoyuan > > Huang (黃道原) ; Damon Chu (朱峻賢) > > ; Josh-YC Liu (劉育誠) ; > > Glory Hung (洪智瑋) ; Jiaguang Zhang (张加广) > > ; Dennis-YC Hsieh (謝宇哲) > > ; Monica Wang (王孟婷) > > ; Houlong Wei (魏厚龙) ; > > Hs Liao (廖宏祥) > > Subject: Re: [PATCH v20 2/4] mailbox: mediatek: Add Mediatek CMDQ driver > > > > On Thu, 2017-02-23 at 09:40 +0530, Jassi Brar wrote: > > > On Wed, Feb 22, 2017 at 8:42 AM, Horng-Shyang Liao > > > wrote: > > > > On Thu, 2017-02-16 at 21:02 +0530, Jassi Brar wrote: > > > >> On Mon, Feb 6, 2017 at 11:07 AM, Horng-Shyang Liao > > > >> wrote: > > > >> > Hi Jassi, > > > >> > > > > >> > On Wed, 2017-02-01 at 10:52 +0530, Jassi Brar wrote: > > > >> >> On Thu, Jan 26, 2017 at 2:07 PM, Horng-Shyang Liao > > > >> >> wrote: > > > >> >> > Hi Jassi, > > > >> >> > > > > >> >> > On Thu, 2017-01-26 at 10:08 +0530, Jassi Brar wrote: > > > >> >> >> On Wed, Jan 4, 2017 at 8:36 AM, HS Liao > > > >> >> >> wrote: > > > >> >> >> > > > >> >> >> > diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c > > > >> >> >> > b/drivers/mailbox/mtk-cmdq-mailbox.c > > > >> >> >> > new file mode 100644 > > > >> >> >> > index 000..747bcd3 > > > >> >> >> > --- /dev/null > > > >> >> >> > +++ b/drivers/mailbox/mtk-cmdq-mailbox.c > > > >> >> >> > > > >> >> >> ... > > > >> >> >> > > > >> >> >> > +static void cmdq_task_exec(struct cmdq_pkt *pkt, struct > > > >> >> >> > +cmdq_thread *thread) { > > > >> >> >> > + struct cmdq *cmdq; > > > >> >> >> > + struct cmdq_task *task; > > > >> >> >> > + unsigned long curr_pa, end_pa; > > > >> >> >> > + > > > >> >> >> > + cmdq = dev_get_drvdata(thread->chan->mbox->dev); > > > >> >> >> > + > > > >> >> >> > + /* Client should not flush new tasks if suspended. */ > > > >> >> >> > + WARN_ON(cmdq->suspended); > > > >> >> >> > + > > > >> >> >> > + task = kzalloc(sizeof(*task), GFP_ATOMIC); > > > >> >> >> > + task->cmdq = cmdq; > > > >> >> >> > + INIT_LIST_HEAD(>list_entry); > > > >> >> >> > + task->pa_base = dma_map_single(cmdq->mbox.dev, > > > >> &g
Re: FW: [PATCH v20 2/4] mailbox: mediatek: Add Mediatek CMDQ driver
Hi Jassi, There is one request for one GCE h/w buffer which contains a list of registers operation. I will resubmit a version and please review again. Thanks, Houlong On Thu, 2018-01-18 at 16:01 +0800, Jassi Brar wrote: > On Mon, Jan 8, 2018 at 2:08 PM, houlong wei wrote: > > Hi Jassi, > > > > Sorry for reply so late. > > According to previous discussion, there are two methods to move > > dma_map_single() outside of spin_lock. > > (1) put in mtk-cmdq-helper.c, as described by HS on 2017-02-09. > > > I think a trade-off solution is to put in mtk-cmdq-helper.c. > > > Although it is a mailbox client, it is not a CMDQ client. > > > We can include mailbox_controller.h in mtk-cmdq-helper.c (instead of > > mtk-cmdq.h), and then map dma at cmdq_pkt_flush_async before > > mbox_send_message. > > > > > pkt->pa_base = dma_map_single(client->chan->mbox->dev, pkt->va_base, > > > pkt->cmd_buf_size, DMA_TO_DEVICE); > > (2) schedule a tasklet in send_data(). > > > > After internal discussion with HS and other experts, now we prefer > > method (1). > > How do you think about it? > > > I don't exactly see how you mean but please remember send_data() > callback is supposed to be atomic ... it is protected by > spin_lock_irqsave/restore in drivers/mailbox/mailbox.c:msg_submit() > > BTW, how many requests max can be queued in the GCE h/w buffer? > And since it's been over a year now, could you please resubmit after > checking for checkpatch with the --strict option? > > Thanks.
Re: [PATCH] [media] media: mtk-mdp: fix reference count on old device tree
On Mon, 2019-07-08 at 17:06 +0800, Matthias Brugger wrote: > > On 21/06/2019 13:32, Matthias Brugger wrote: > > of_get_next_child() increments the reference count of the returning > > device_node. Decrement it in the check if we are using the old or the > > new DTB. > > > > Fixes: ba1f1f70c2c0 ("[media] media: mtk-mdp: Fix mdp device tree") > > Signed-off-by: Matthias Brugger > > Any comments on that? > Hi Matthias, Thanks for fixing the bug. Sorry to reply late~ Acked-by: Houlong Wei > > --- > > drivers/media/platform/mtk-mdp/mtk_mdp_core.c | 4 +++- > > 1 file changed, 3 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_core.c > > b/drivers/media/platform/mtk-mdp/mtk_mdp_core.c > > index bbb24fb95b95..bafe53c5d54a 100644 > > --- a/drivers/media/platform/mtk-mdp/mtk_mdp_core.c > > +++ b/drivers/media/platform/mtk-mdp/mtk_mdp_core.c > > @@ -118,7 +118,9 @@ static int mtk_mdp_probe(struct platform_device *pdev) > > mutex_init(>vpulock); > > > > /* Old dts had the components as child nodes */ > > - if (of_get_next_child(dev->of_node, NULL)) { > > + parent = of_get_next_child(dev->of_node, NULL); > > + if (parent) { > > + of_node_put(parent); > > parent = dev->of_node; > > dev_warn(dev, "device tree is out of date\n"); > > } else { > >
Re: [PATCH v14 07/10] soc: mediatek: cmdq: define the instruction struct
On Thu, 2019-08-29 at 09:48 +0800, Bibby Hsieh wrote: > Define an instruction structure for gce driver to append command. > This structure can make the client's code more readability. > > Signed-off-by: Bibby Hsieh > Reviewed-by: CK Hu > Reviewed-by: Houlong Wei > --- > drivers/soc/mediatek/mtk-cmdq-helper.c | 77 > include/linux/mailbox/mtk-cmdq-mailbox.h | 10 +++ > 2 files changed, 61 insertions(+), 26 deletions(-) > > diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c > b/drivers/soc/mediatek/mtk-cmdq-helper.c > index 7aa0517ff2f3..9472526ab076 100644 > --- a/drivers/soc/mediatek/mtk-cmdq-helper.c > +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c > @@ -9,12 +9,24 @@ > #include > #include > > -#define CMDQ_ARG_A_WRITE_MASK0x > #define CMDQ_WRITE_ENABLE_MASK BIT(0) > #define CMDQ_EOC_IRQ_EN BIT(0) > #define CMDQ_EOC_CMD ((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \ > << 32 | CMDQ_EOC_IRQ_EN) > > +struct cmdq_instruction { > + union { > + u32 value; > + u32 mask; > + }; > + union { > + u16 offset; > + u16 event; > + }; > + u8 subsys; > + u8 op; > +}; > + > static void cmdq_client_timeout(struct timer_list *t) > { > struct cmdq_client *client = from_timer(client, t, timer); > @@ -110,10 +122,10 @@ void cmdq_pkt_destroy(struct cmdq_pkt *pkt) > } > EXPORT_SYMBOL(cmdq_pkt_destroy); > > -static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, enum cmdq_code code, > -u32 arg_a, u32 arg_b) > +static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, > +struct cmdq_instruction inst) Can we use 'struct cmdq_instruction *inst' instead of 'struct cmdq_instruction inst' to reduce stack memory consumption a bit? > { > - u64 *cmd_ptr; > + struct cmdq_instruction *cmd_ptr; > > if (unlikely(pkt->cmd_buf_size + CMDQ_INST_SIZE > pkt->buf_size)) { > /* > @@ -129,8 +141,9 @@ static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, > enum cmdq_code code, > __func__, (u32)pkt->buf_size); > return -ENOMEM; > } > + > cmd_ptr = pkt->va_base + pkt->cmd_buf_size; > - (*cmd_ptr) = (u64)((code << CMDQ_OP_CODE_SHIFT) | arg_a) << 32 | arg_b; > + *cmd_ptr = inst; > pkt->cmd_buf_size += CMDQ_INST_SIZE; > > return 0; > @@ -138,24 +151,31 @@ static int cmdq_pkt_append_command(struct cmdq_pkt > *pkt, enum cmdq_code code, > > int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value) > { > - u32 arg_a = (offset & CMDQ_ARG_A_WRITE_MASK) | > - (subsys << CMDQ_SUBSYS_SHIFT); > + struct cmdq_instruction inst; > + > + inst.op = CMDQ_CODE_WRITE; > + inst.value = value; > + inst.offset = offset; > + inst.subsys = subsys; > > - return cmdq_pkt_append_command(pkt, CMDQ_CODE_WRITE, arg_a, value); > + return cmdq_pkt_append_command(pkt, inst); > } > EXPORT_SYMBOL(cmdq_pkt_write); > > int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys, > u16 offset, u32 value, u32 mask) > { > - u32 offset_mask = offset; > + struct cmdq_instruction inst = { {0} }; > + u16 offset_mask = offset; > int err = 0; > > if (mask != 0x) { > - err = cmdq_pkt_append_command(pkt, CMDQ_CODE_MASK, 0, ~mask); > + inst.op = CMDQ_CODE_MASK; > + inst.mask = ~mask; > + err = cmdq_pkt_append_command(pkt, inst); > offset_mask |= CMDQ_WRITE_ENABLE_MASK; > } > - err |= cmdq_pkt_write(pkt, value, subsys, offset_mask); > + err |= cmdq_pkt_write(pkt, subsys, offset_mask, value); > > return err; > } > @@ -163,43 +183,48 @@ EXPORT_SYMBOL(cmdq_pkt_write_mask); > > int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event) > { > - u32 arg_b; > + struct cmdq_instruction inst = { {0} }; > > if (event >= CMDQ_MAX_EVENT) > return -EINVAL; > > - /* > - * WFE arg_b > - * bit 0-11: wait value > - * bit 15: 1 - wait, 0 - no wait > - * bit 16-27: update value > - * bit 31: 1 - update, 0 - no update > - */ > - arg_b = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE; > + inst.op = CMDQ_CODE_WFE; > + inst.value = CMDQ_WFE_OPTION; > + inst.event = event; > > - return cmdq_pkt_append_command(pkt, CMD
Re: [PATCH v11 09/12] soc: mediatek: cmdq: define the instruction struct
Hi Bibby, I have inline comment in function cmdq_pkt_write_mask(). On Mon, 2019-07-29 at 15:01 +0800, Bibby Hsieh wrote: > Define an instruction structure for gce driver to append command. > This structure can make the client's code more readability. > > Signed-off-by: Bibby Hsieh > Reviewed-by: CK Hu > --- > drivers/soc/mediatek/mtk-cmdq-helper.c | 103 +++ > include/linux/mailbox/mtk-cmdq-mailbox.h | 2 + > 2 files changed, 72 insertions(+), 33 deletions(-) > > diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c > b/drivers/soc/mediatek/mtk-cmdq-helper.c > index 7aa0517ff2f3..0886c4967ca4 100644 > --- a/drivers/soc/mediatek/mtk-cmdq-helper.c > +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c > @@ -9,12 +9,24 @@ > #include > #include > > -#define CMDQ_ARG_A_WRITE_MASK0x > #define CMDQ_WRITE_ENABLE_MASK BIT(0) > #define CMDQ_EOC_IRQ_EN BIT(0) > #define CMDQ_EOC_CMD ((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \ > << 32 | CMDQ_EOC_IRQ_EN) > > +struct cmdq_instruction { > + union { > + u32 value; > + u32 mask; > + }; > + union { > + u16 offset; > + u16 event; > + }; > + u8 subsys; > + u8 op; > +}; > + > static void cmdq_client_timeout(struct timer_list *t) > { > struct cmdq_client *client = from_timer(client, t, timer); > @@ -110,10 +122,8 @@ void cmdq_pkt_destroy(struct cmdq_pkt *pkt) > } > EXPORT_SYMBOL(cmdq_pkt_destroy); > > -static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, enum cmdq_code code, > -u32 arg_a, u32 arg_b) > +static struct cmdq_instruction *cmdq_pkt_append_command(struct cmdq_pkt *pkt) > { > - u64 *cmd_ptr; > > if (unlikely(pkt->cmd_buf_size + CMDQ_INST_SIZE > pkt->buf_size)) { > /* > @@ -127,81 +137,108 @@ static int cmdq_pkt_append_command(struct cmdq_pkt > *pkt, enum cmdq_code code, > pkt->cmd_buf_size += CMDQ_INST_SIZE; > WARN_ONCE(1, "%s: buffer size %u is too small !\n", > __func__, (u32)pkt->buf_size); > - return -ENOMEM; > + return NULL; > } > - cmd_ptr = pkt->va_base + pkt->cmd_buf_size; > - (*cmd_ptr) = (u64)((code << CMDQ_OP_CODE_SHIFT) | arg_a) << 32 | arg_b; > + > pkt->cmd_buf_size += CMDQ_INST_SIZE; > > - return 0; > + return pkt->va_base + pkt->cmd_buf_size - CMDQ_INST_SIZE; > } > > int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value) > { > - u32 arg_a = (offset & CMDQ_ARG_A_WRITE_MASK) | > - (subsys << CMDQ_SUBSYS_SHIFT); > + struct cmdq_instruction *inst; > + > + inst = cmdq_pkt_append_command(pkt); > + if (!inst) > + return -ENOMEM; > + > + inst->op = CMDQ_CODE_WRITE; > + inst->value = value; > + inst->offset = offset; > + inst->subsys = subsys; > > - return cmdq_pkt_append_command(pkt, CMDQ_CODE_WRITE, arg_a, value); > + return 0; > } > EXPORT_SYMBOL(cmdq_pkt_write); > > int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys, > u16 offset, u32 value, u32 mask) > { > + struct cmdq_instruction *inst; > u32 offset_mask = offset; > - int err = 0; > > if (mask != 0x) { > - err = cmdq_pkt_append_command(pkt, CMDQ_CODE_MASK, 0, ~mask); > + inst = cmdq_pkt_append_command(pkt); > + if (!inst) > + return -ENOMEM; > + > + inst->op = CMDQ_CODE_MASK; > + inst->mask = ~mask; There were some discussion about how to reduce cmdq buffer allocation times reuse a cmdq packet.Please refer to the below links. https://patchwork.kernel.org/patch/10193349/ https://patchwork.kernel.org/patch/10491161/ If we reuse a cmdq packet, we get the cmdq instruction buffer which may contains previous data. To generate correct instructions, we may need consider how to clear the previous data. 1.Set all members of a cmdq_instruction instance. e.g. Add two lines of code below for this case. inst->offset = 0; inst->subsys = 0; 2. Before reuse a packet, do memset() for the command buffer. How do you think about it? > offset_mask |= CMDQ_WRITE_ENABLE_MASK; > } > - err |= cmdq_pkt_write(pkt, value, subsys, offset_mask); > > - return err; > + return cmdq_pkt_write(pkt, subsys, offset_mask, value); > } > EXPORT_SYMBOL(cmdq_pkt_write_mask); > > int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event) > { > - u32 arg_b; > + struct cmdq_instruction *inst; > > if (event >= CMDQ_MAX_EVENT) > return -EINVAL; > > - /* > - * WFE arg_b > - * bit 0-11: wait value > - * bit 15: 1 - wait, 0 - no wait > - * bit 16-27: update value > - * bit 31: 1 - update, 0 - no update > - */ > - arg_b = CMDQ_WFE_UPDATE |
Re: [PATCH v11 11/12] soc: mediatek: cmdq: add cmdq_dev_get_client_reg function
On Mon, 2019-07-29 at 15:01 +0800, Bibby Hsieh wrote: > GCE cannot know the register base address, this function > can help cmdq client to get the cmdq_client_reg structure. > > Signed-off-by: Bibby Hsieh > --- > drivers/soc/mediatek/mtk-cmdq-helper.c | 29 ++ > include/linux/soc/mediatek/mtk-cmdq.h | 21 +++ > 2 files changed, 50 insertions(+) > > diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c > b/drivers/soc/mediatek/mtk-cmdq-helper.c > index 70ad4d806fac..9695b75cfc89 100644 > --- a/drivers/soc/mediatek/mtk-cmdq-helper.c > +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c > @@ -27,6 +27,35 @@ struct cmdq_instruction { > u8 op; > }; > > +int cmdq_dev_get_client_reg(struct device *dev, > + struct cmdq_client_reg *client_reg, int idx) > +{ > + struct of_phandle_args spec; > + int err; > + > + if (!client_reg) > + return -ENOENT; > + > + err = of_parse_phandle_with_fixed_args(dev->of_node, > +"mediatek,gce-client-reg", > +3, idx, ); > + if (err < 0) { > + dev_err(dev, > + "error %d can't parse gce-client-reg property (%d)", > + err, idx); > + > + return err; > + } > + > + client_reg->subsys = spec.args[0]; > + client_reg->offset = spec.args[1]; > + client_reg->size = spec.args[2]; Maybe we need add type conversion to avoid compiling warnings. client_reg->subsys = (u8)spec.args[0]; client_reg->offset = (u16)spec.args[1]; client_reg->size = (u16)spec.args[2]; > + of_node_put(spec.np); > + > + return 0; > +} > +EXPORT_SYMBOL(cmdq_dev_get_client_reg); > + > static void cmdq_client_timeout(struct timer_list *t) > { > struct cmdq_client *client = from_timer(client, t, timer); > diff --git a/include/linux/soc/mediatek/mtk-cmdq.h > b/include/linux/soc/mediatek/mtk-cmdq.h > index a345870a6d10..be402c4c740e 100644 > --- a/include/linux/soc/mediatek/mtk-cmdq.h > +++ b/include/linux/soc/mediatek/mtk-cmdq.h > @@ -15,6 +15,12 @@ > > struct cmdq_pkt; > > +struct cmdq_client_reg { > + u8 subsys; > + u16 offset; > + u16 size; > +}; > + > struct cmdq_client { > spinlock_t lock; > u32 pkt_cnt; > @@ -142,4 +148,19 @@ int cmdq_pkt_flush_async(struct cmdq_pkt *pkt, > cmdq_async_flush_cb cb, > */ > int cmdq_pkt_flush(struct cmdq_pkt *pkt); > > +/** > + * cmdq_dev_get_client_reg() - parse cmdq client reg from the device > + * node of CMDQ client > + * @dev: device of CMDQ mailbox clienti > + * @client_reg: CMDQ client reg pointer > + * @idx: the index of desired reg > + * > + * Return: 0 for success; else the error code is returned > + * > + * Help CMDQ client pasing the cmdq client reg > + * from the device node of CMDQ client. > + */ > +int cmdq_dev_get_client_reg(struct device *dev, > + struct cmdq_client_reg *client_reg, int idx); > + Could we keep the same order of function declaration and implementation? > #endif /* __MTK_CMDQ_H__ */
Re: [PATCH v11 12/12] arm64: dts: add gce node for mt8183
On Mon, 2019-07-29 at 15:01 +0800, Bibby Hsieh wrote: > add gce device node for mt8183 > > Signed-off-by: Bibby Hsieh > --- > arch/arm64/boot/dts/mediatek/mt8183.dtsi | 10 ++ > 1 file changed, 10 insertions(+) > > diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi > b/arch/arm64/boot/dts/mediatek/mt8183.dtsi > index 08274bfcebd8..98d17d0bdebf 100644 > --- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi > +++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi > @@ -8,6 +8,7 @@ > #include > #include > #include > +#include > > / { > compatible = "mediatek,mt8183"; > @@ -212,6 +213,15 @@ > clock-names = "spi", "wrap"; > }; > > + gce: gce@10238000 { Use mailbox@ instead of gce@, Rob suggested in https://patchwork.kernel.org/patch/10491213/ > + compatible = "mediatek,mt8183-gce"; > + reg = <0 0x10238000 0 0x4000>; > + interrupts = ; > + #mbox-cells = <3>; > + clocks = < CLK_INFRA_GCE>; > + clock-names = "gce"; > + }; > + > uart0: serial@11002000 { > compatible = "mediatek,mt8183-uart", >"mediatek,mt6577-uart";
Re: [PATCH v11 09/12] soc: mediatek: cmdq: define the instruction struct
On Sun, 2019-08-11 at 00:12 +0800, houlong wei wrote: > Hi Bibby, I have inline comment in function cmdq_pkt_write_mask(). > > On Mon, 2019-07-29 at 15:01 +0800, Bibby Hsieh wrote: > > Define an instruction structure for gce driver to append command. > > This structure can make the client's code more readability. > > > > Signed-off-by: Bibby Hsieh > > Reviewed-by: CK Hu > > --- > > drivers/soc/mediatek/mtk-cmdq-helper.c | 103 +++ > > include/linux/mailbox/mtk-cmdq-mailbox.h | 2 + > > 2 files changed, 72 insertions(+), 33 deletions(-) > > > > diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c > > b/drivers/soc/mediatek/mtk-cmdq-helper.c > > index 7aa0517ff2f3..0886c4967ca4 100644 > > --- a/drivers/soc/mediatek/mtk-cmdq-helper.c > > +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c > > @@ -9,12 +9,24 @@ > > #include > > #include [...] > > > > int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys, > > u16 offset, u32 value, u32 mask) > > { > > + struct cmdq_instruction *inst; > > u32 offset_mask = offset; > > - int err = 0; > > > > if (mask != 0x) { > > - err = cmdq_pkt_append_command(pkt, CMDQ_CODE_MASK, 0, ~mask); > > + inst = cmdq_pkt_append_command(pkt); > > + if (!inst) > > + return -ENOMEM; > > + > > + inst->op = CMDQ_CODE_MASK; > > + inst->mask = ~mask; > > offset_mask |= CMDQ_WRITE_ENABLE_MASK; > > } > > - err |= cmdq_pkt_write(pkt, value, subsys, offset_mask); > > > > - return err; > > + return cmdq_pkt_write(pkt, subsys, offset_mask, value); We need add a type conversion here, (u8)offset_mask, for your new function type. Er... it's better to remove local variable 'offset_mask' and replace it with 'offset'. > > } [...]
[PATCH v22 0/4] MediaTek MT8173 CMDQ support
Hi, This is Mediatek MT8173 Command Queue(CMDQ) driver. The CMDQ is used to help write registers with critical time limitation, such as updating display configuration during the vblank. It controls Global Command Engine (GCE) hardware to achieve this requirement. Changes since v21: -rebase on v4.18-rc1 -remove subsys code and event id definition from mtk-cmdq-helper.c -add mt8173-gce.h to define the subsys code and envent id Changes since v20: -rebase on v4.15-rc1 -move dma_map_single outside of spinlock Changes since v19: - rebase to v4.10-rc2 Houlong Wei (4): dt-bindings: soc: Add documentation for the MediaTek GCE unit mailbox: mediatek: Add Mediatek CMDQ driver arm64: dts: mt8173: Add GCE node soc: mediatek: Add Mediatek CMDQ helper .../devicetree/bindings/mailbox/mtk-gce.txt| 65 ++ arch/arm64/boot/dts/mediatek/mt8173.dtsi | 11 + drivers/mailbox/Kconfig| 10 + drivers/mailbox/Makefile |2 + drivers/mailbox/mtk-cmdq-mailbox.c | 633 drivers/soc/mediatek/Kconfig | 12 + drivers/soc/mediatek/Makefile |1 + drivers/soc/mediatek/mtk-cmdq-helper.c | 258 include/dt-bindings/gce/mt8173-gce.h | 48 ++ include/linux/mailbox/mtk-cmdq-mailbox.h | 70 +++ include/linux/soc/mediatek/mtk-cmdq.h | 132 11 files changed, 1242 insertions(+) create mode 100644 Documentation/devicetree/bindings/mailbox/mtk-gce.txt create mode 100644 drivers/mailbox/mtk-cmdq-mailbox.c create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c create mode 100644 include/dt-bindings/gce/mt8173-gce.h create mode 100644 include/linux/mailbox/mtk-cmdq-mailbox.h create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h -- 1.7.9.5
[PATCH v22 1/4] dt-bindings: soc: Add documentation for the MediaTek GCE unit
This adds documentation for the MediaTek Global Command Engine (GCE) unit found in MT8173 SoCs. Signed-off-by: Houlong Wei Signed-off-by: HS Liao --- Hi Rob, I don't add your ACK in this version since the dt-binding description has been changed. Thanks. --- .../devicetree/bindings/mailbox/mtk-gce.txt| 65 include/dt-bindings/gce/mt8173-gce.h | 48 +++ 2 files changed, 113 insertions(+) create mode 100644 Documentation/devicetree/bindings/mailbox/mtk-gce.txt create mode 100644 include/dt-bindings/gce/mt8173-gce.h diff --git a/Documentation/devicetree/bindings/mailbox/mtk-gce.txt b/Documentation/devicetree/bindings/mailbox/mtk-gce.txt new file mode 100644 index 000..26f65a4 --- /dev/null +++ b/Documentation/devicetree/bindings/mailbox/mtk-gce.txt @@ -0,0 +1,65 @@ +MediaTek GCE +=== + +The Global Command Engine (GCE) is used to help read/write registers with +critical time limitation, such as updating display configuration during the +vblank. The GCE can be used to implement the Command Queue (CMDQ) driver. + +CMDQ driver uses mailbox framework for communication. Please refer to +mailbox.txt for generic information about mailbox device-tree bindings. + +Required properties: +- compatible: Must be "mediatek,mt8173-gce" +- reg: Address range of the GCE unit +- interrupts: The interrupt signal from the GCE block +- clock: Clocks according to the common clock binding +- clock-names: Must be "gce" to stand for GCE clock +- thread-num: Maximum threads count of GCE. +- #mbox-cells: Should be 4. + < channel timeout priority atomic_exec> + phandle: Label name of a gce node. + channel: Channel of mailbox. Be equal to the thread id of GCE. + timeout: Maximum time of software waiting GCE processing done, in unit + of millisecond. + priority: Priority of GCE thread. + atomic_exec: GCE processing continuous packets of commands in atomic + way. + +Required properties for a client device: +- mboxes: Client use mailbox to communicate with GCE, it should have this + property and list of phandle, mailbox specifiers. +- gce-subsys: Specify the sub-system id which is corresponding to the register + address. + +Optional properties for a client device: +- gce-event: Specify the event if the client has any. Because the event is + parsed by client, so client can replace 'gce-event' with other meaningful + name. + +Some vaules of properties are defined in 'dt-bindings/gce/mt8173-gce.h'. Such as +thread number, sub-system ids, thread priority, event ids. + +Example: + + gce: gce@10212000 { + compatible = "mediatek,mt8173-gce"; + reg = <0 0x10212000 0 0x1000>; + interrupts = ; + clocks = < CLK_INFRA_GCE>; + clock-names = "gce"; + thread-num = CMDQ_THR_MAX_COUNT; + #mbox-cells = <4>; + }; + +Example for a client device: + + mmsys: clock-controller@1400 { + compatible = "mediatek,mt8173-mmsys"; + mboxes = < 0 2000 CMDQ_THR_PRIO_LOWEST 1>, +< 1 2000 CMDQ_THR_PRIO_LOWEST 1>; + gce-subsys = ; + mutex-event-eof = ; + + ... + }; diff --git a/include/dt-bindings/gce/mt8173-gce.h b/include/dt-bindings/gce/mt8173-gce.h new file mode 100644 index 000..89eb3b8 --- /dev/null +++ b/include/dt-bindings/gce/mt8173-gce.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Houlong Wei + * + */ + +#ifndef _DT_BINDINGS_GCE_MT8173_H +#define _DT_BINDINGS_GCE_MT8173_H + +#define CMDQ_NO_TIMEOUT0x + +#define CMDQ_THR_MAX_COUNT 16 + +/* GCE HW thread priority */ +#define CMDQ_THR_PRIO_LOWEST 0 +#define CMDQ_THR_PRIO_HIGHEST 1 + +/* GCE SUBSYS */ +#define SUBSYS_14001 +#define SUBSYS_14012 +#define SUBSYS_14023 + +/* GCE HW EVENT */ +#define CMDQ_EVENT_DISP_OVL0_SOF 11 +#define CMDQ_EVENT_DISP_OVL1_SOF 12 +#define CMDQ_EVENT_DISP_RDMA0_SOF 13 +#define CMDQ_EVENT_DISP_RDMA1_SOF 14 +#define CMDQ_EVENT_DISP_RDMA2_SOF 15 +#define CMDQ_EVENT_DISP_WDMA0_SOF 16 +#define CMDQ_EVENT_DISP_WDMA1_SOF 17 +#define CMDQ_EVENT_DISP_OVL0_EOF 39 +#define CMDQ_EVENT_DISP_OVL1_EOF 40 +#define CMDQ_EVENT_DISP_RDMA0_EOF 41 +#define CMDQ_EVENT_DISP_RDMA1_EOF 42 +#define CMDQ_EVENT_DISP_RDMA2_EOF 43 +#define CMDQ_EVENT_DISP_WDMA0_EOF 44 +#define CMDQ_EVENT_DISP_WDMA1_EOF 45 +#define CMDQ_EVENT_MUTEX0_STREAM_EOF 53 +#define CMDQ_EVENT_MUTEX1_STREAM_EOF 54 +#define CMDQ_EVENT_MUTE
[PATCH v22 2/4] mailbox: mediatek: Add Mediatek CMDQ driver
This patch is first version of Mediatek Command Queue(CMDQ) driver. The CMDQ is used to help write registers with critical time limitation, such as updating display configuration during the vblank. It controls Global Command Engine (GCE) hardware to achieve this requirement. Currently, CMDQ only supports display related hardwares, but we expect it can be extended to other hardwares for future requirements. Signed-off-by: Houlong Wei Signed-off-by: HS Liao Signed-off-by: CK Hu --- drivers/mailbox/Kconfig | 10 + drivers/mailbox/Makefile |2 + drivers/mailbox/mtk-cmdq-mailbox.c | 634 ++ include/linux/mailbox/mtk-cmdq-mailbox.h | 70 4 files changed, 716 insertions(+) create mode 100644 drivers/mailbox/mtk-cmdq-mailbox.c create mode 100644 include/linux/mailbox/mtk-cmdq-mailbox.h diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index e63d29a..2bbabc9 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -189,4 +189,14 @@ config STM32_IPCC Mailbox implementation for STMicroelectonics STM32 family chips with hardware for Inter-Processor Communication Controller (IPCC) between processors. Say Y here if you want to have this support. + +config MTK_CMDQ_MBOX + tristate "MediaTek CMDQ Mailbox Support" + depends on ARCH_MEDIATEK || COMPILE_TEST + select MTK_INFRACFG + help + Say yes here to add support for the MediaTek Command Queue (CMDQ) + mailbox driver. The CMDQ is used to help read/write registers with + critical time limitation, such as updating display configuration + during the vblank. endif diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index 4d501be..4b00804 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -40,3 +40,5 @@ obj-$(CONFIG_QCOM_APCS_IPC) += qcom-apcs-ipc-mailbox.o obj-$(CONFIG_TEGRA_HSP_MBOX) += tegra-hsp.o obj-$(CONFIG_STM32_IPCC) += stm32-ipcc.o + +obj-$(CONFIG_MTK_CMDQ_MBOX)+= mtk-cmdq-mailbox.o diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c new file mode 100644 index 000..93d87cb --- /dev/null +++ b/drivers/mailbox/mtk-cmdq-mailbox.c @@ -0,0 +1,634 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 MediaTek Inc. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CMDQ_OP_CODE_MASK (0xff << CMDQ_OP_CODE_SHIFT) +#define CMDQ_TIMEOUT_MS1000 +#define CMDQ_IRQ_MASK 0x +#define CMDQ_NUM_CMD(t)(t->cmd_buf_size / CMDQ_INST_SIZE) + +#define CMDQ_CURR_IRQ_STATUS 0x10 +#define CMDQ_THR_SLOT_CYCLES 0x30 +#define CMDQ_THR_BASE 0x100 +#define CMDQ_THR_SIZE 0x80 +#define CMDQ_THR_WARM_RESET0x00 +#define CMDQ_THR_ENABLE_TASK 0x04 +#define CMDQ_THR_SUSPEND_TASK 0x08 +#define CMDQ_THR_CURR_STATUS 0x0c +#define CMDQ_THR_IRQ_STATUS0x10 +#define CMDQ_THR_IRQ_ENABLE0x14 +#define CMDQ_THR_CURR_ADDR 0x20 +#define CMDQ_THR_END_ADDR 0x24 +#define CMDQ_THR_WAIT_TOKEN0x30 +#define CMDQ_THR_PRIORITY 0x40 + +#define CMDQ_NO_TIMEOUT0xu +#define CMDQ_THR_ACTIVE_SLOT_CYCLES0x3200 +#define CMDQ_THR_ENABLED 0x1 +#define CMDQ_THR_DISABLED 0x0 +#define CMDQ_THR_SUSPEND 0x1 +#define CMDQ_THR_RESUME0x0 +#define CMDQ_THR_STATUS_SUSPENDED BIT(1) +#define CMDQ_THR_DO_WARM_RESET BIT(0) +#define CMDQ_THR_IRQ_DONE 0x1 +#define CMDQ_THR_IRQ_ERROR 0x12 +#define CMDQ_THR_IRQ_EN(CMDQ_THR_IRQ_ERROR | CMDQ_THR_IRQ_DONE) +#define CMDQ_THR_IS_WAITINGBIT(31) + +#define CMDQ_JUMP_BY_OFFSET0x1000 +#define CMDQ_JUMP_BY_PA0x1001 + +struct cmdq_thread { + struct mbox_chan*chan; + void __iomem*base; + struct list_headtask_busy_list; + struct timer_list timeout; + u32 timeout_ms; + u32 priority; + boolatomic_exec; +}; + +struct cmdq_task { + struct cmdq *cmdq; + struct list_headlist_entry; + dma_addr_t pa_base; + struct cmdq_thread *thread; + struct cmdq_pkt *pkt; /* the packet sent from mailbox client */ +}; + +struct cmdq { + struct mbox_controller mbox; + void __iomem*base; + u32 irq; + u32 thread_nr; + struct cmdq_thread *thread;
[PATCH v22 4/4] soc: mediatek: Add Mediatek CMDQ helper
Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. Signed-off-by: Houlong Wei Signed-off-by: HS Liao --- drivers/soc/mediatek/Kconfig | 12 ++ drivers/soc/mediatek/Makefile |1 + drivers/soc/mediatek/mtk-cmdq-helper.c | 258 include/linux/soc/mediatek/mtk-cmdq.h | 132 4 files changed, 403 insertions(+) create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig index a7d0667..17bd759 100644 --- a/drivers/soc/mediatek/Kconfig +++ b/drivers/soc/mediatek/Kconfig @@ -4,6 +4,18 @@ menu "MediaTek SoC drivers" depends on ARCH_MEDIATEK || COMPILE_TEST +config MTK_CMDQ + tristate "MediaTek CMDQ Support" + depends on ARCH_MEDIATEK || COMPILE_TEST + select MAILBOX + select MTK_CMDQ_MBOX + select MTK_INFRACFG + help + Say yes here to add support for the MediaTek Command Queue (CMDQ) + driver. The CMDQ is used to help read/write registers with critical + time limitation, such as updating display configuration during the + vblank. + config MTK_INFRACFG bool "MediaTek INFRACFG Support" select REGMAP diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile index 12998b0..64ce5ee 100644 --- a/drivers/soc/mediatek/Makefile +++ b/drivers/soc/mediatek/Makefile @@ -1,3 +1,4 @@ +obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c new file mode 100644 index 000..6c66091 --- /dev/null +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -0,0 +1,258 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 MediaTek Inc. + * + */ + +#include +#include +#include +#include +#include + +#define CMDQ_ARG_A_WRITE_MASK 0x +#define CMDQ_WRITE_ENABLE_MASK BIT(0) +#define CMDQ_EOC_IRQ_ENBIT(0) +#define CMDQ_EOC_CMD ((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \ + << 32 | CMDQ_EOC_IRQ_EN) + +int cmdq_pkt_realloc_cmd_buffer(struct cmdq_pkt *pkt, size_t size) +{ + void *new_buf; + + new_buf = krealloc(pkt->va_base, size, GFP_KERNEL | __GFP_ZERO); + if (!new_buf) + return -ENOMEM; + pkt->va_base = new_buf; + pkt->buf_size = size; + + return 0; +} +EXPORT_SYMBOL(cmdq_pkt_realloc_cmd_buffer); + +struct cmdq_client *cmdq_mbox_create(struct device *dev, int index) +{ + struct cmdq_client *client; + long err = 0; + + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client) + return (struct cmdq_client *)-ENOMEM; + + client->client.dev = dev; + client->client.tx_block = false; + client->chan = mbox_request_channel(>client, index); + + if (IS_ERR(client->chan)) { + dev_err(dev, "failed to request channel\n"); + err = PTR_ERR(client->chan); + kfree(client); + + return (struct cmdq_client *)err; + } + + return client; +} +EXPORT_SYMBOL(cmdq_mbox_create); + +void cmdq_mbox_destroy(struct cmdq_client *client) +{ + mbox_free_channel(client->chan); + kfree(client); +} +EXPORT_SYMBOL(cmdq_mbox_destroy); + +int cmdq_pkt_create(struct cmdq_pkt **pkt_ptr) +{ + struct cmdq_pkt *pkt; + int err; + + pkt = kzalloc(sizeof(*pkt), GFP_KERNEL); + if (!pkt) + return -ENOMEM; + err = cmdq_pkt_realloc_cmd_buffer(pkt, PAGE_SIZE); + if (err < 0) { + kfree(pkt); + return err; + } + *pkt_ptr = pkt; + + return 0; +} +EXPORT_SYMBOL(cmdq_pkt_create); + +void cmdq_pkt_destroy(struct cmdq_pkt *pkt) +{ + kfree(pkt->va_base); + kfree(pkt); +} +EXPORT_SYMBOL(cmdq_pkt_destroy); + +static bool cmdq_pkt_is_finalized(struct cmdq_pkt *pkt) +{ + u64 *expect_eoc; + + if (pkt->cmd_buf_size < CMDQ_INST_SIZE << 1) + return false; + + expect_eoc = pkt->va_base + pkt->cmd_buf_size - (CMDQ_INST_SIZE << 1); + if (*expect_eoc == CMDQ_EOC_CMD) + return true; + + return false; +} + +static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, enum cmdq_code code, + u32 arg_a, u32 arg_b) +{ + u64 *cmd_ptr; + int err; + + if (WARN_ON(cmdq_pkt_is_finalized(pkt))) + return -EBUSY; + if (unlikely(pkt->cmd_buf_size + CMDQ_INST_SIZE > pkt->buf_size)) { + err = cmdq_pkt_realloc_cmd_buffer(pkt, pkt->buf_size <<
[PATCH v22 3/4] arm64: dts: mt8173: Add GCE node
This patch adds the device node of the GCE hardware for CMDQ module. Signed-off-by: Houlong Wei Signed-off-by: HS Liao --- arch/arm64/boot/dts/mediatek/mt8173.dtsi | 11 +++ 1 file changed, 11 insertions(+) diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi index 94597e3..d180a6d 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi @@ -18,6 +18,7 @@ #include #include #include +#include #include "mt8173-pinfunc.h" / { @@ -519,6 +520,16 @@ status = "disabled"; }; + gce: gce@10212000 { + compatible = "mediatek,mt8173-gce"; + reg = <0 0x10212000 0 0x1000>; + interrupts = ; + clocks = < CLK_INFRA_GCE>; + clock-names = "gce"; + thread-num = ; + #mbox-cells = <4>; + }; + mipi_tx0: mipi-dphy@10215000 { compatible = "mediatek,mt8173-mipi-tx"; reg = <0 0x10215000 0 0x1000>; -- 1.7.9.5
Re: [PATCH v21 4/4] soc: mediatek: Add Mediatek CMDQ helper
On Tue, 2018-02-06 at 10:52 +0800, CK Hu wrote: > Hi, Houlong: > > I've some inline comment. > > On Wed, 2018-01-31 at 15:28 +0800, houlong@mediatek.com wrote: > > From: "hs.l...@mediatek.com" > > > > Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. > > > > Signed-off-by: Houlong Wei > > Signed-off-by: HS Liao > > --- > > drivers/soc/mediatek/Kconfig | 12 ++ > > drivers/soc/mediatek/Makefile |1 + > > drivers/soc/mediatek/mtk-cmdq-helper.c | 322 > > > > include/linux/soc/mediatek/mtk-cmdq.h | 174 + > > 4 files changed, 509 insertions(+) > > create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c > > create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h > > > > diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig > > index a7d0667..e66582e 100644 > > --- a/drivers/soc/mediatek/Kconfig > > +++ b/drivers/soc/mediatek/Kconfig > > @@ -4,6 +4,18 @@ > > menu "MediaTek SoC drivers" > > depends on ARCH_MEDIATEK || COMPILE_TEST > > > > +config MTK_CMDQ > > +bool "MediaTek CMDQ Support" > > +depends on ARM64 && ( ARCH_MEDIATEK || COMPILE_TEST ) > > +select MAILBOX > > +select MTK_CMDQ_MBOX > > +select MTK_INFRACFG > > +help > > + Say yes here to add support for the MediaTek Command Queue (CMDQ) > > + driver. The CMDQ is used to help read/write registers with critical > > + time limitation, such as updating display configuration during the > > + vblank. > > + > > config MTK_INFRACFG > > bool "MediaTek INFRACFG Support" > > select REGMAP > > diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile > > index 12998b0..64ce5ee 100644 > > --- a/drivers/soc/mediatek/Makefile > > +++ b/drivers/soc/mediatek/Makefile > > @@ -1,3 +1,4 @@ > > +obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o > > obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o > > obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o > > obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o > > diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c > > b/drivers/soc/mediatek/mtk-cmdq-helper.c > > new file mode 100644 > > index 000..80d0558 > > --- /dev/null > > +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c > > @@ -0,0 +1,322 @@ > > +/* > > + * Copyright (c) 2015 MediaTek Inc. > > + * > > + * This program is free software; you can redistribute it and/or modify > > + * it under the terms of the GNU General Public License version 2 as > > + * published by the Free Software Foundation. > > + * > > + * This program is distributed in the hope that it will be useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#define CMDQ_ARG_A_WRITE_MASK0x > > +#define CMDQ_WRITE_ENABLE_MASKBIT(0) > > +#define CMDQ_EOC_IRQ_ENBIT(0) > > +#define CMDQ_EOC_CMD((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \ > > +<< 32 | CMDQ_EOC_IRQ_EN) > > + > > +struct cmdq_subsys { > > +u32base; > > +intid; > > +}; > > + > > +static const struct cmdq_subsys gce_subsys[] = { > > +{0x1400, 1}, > > +{0x1401, 2}, > > +{0x1402, 3}, > > +}; > > I think subsys definition varies by different SoC, so it's better to > pass these definition from device tree to driver (client driver), and > client driver pass this subsys in the related interface. For example, > > in include/dt-bindings/gce/mt8173-gce.h, you define > > #define GCE_SUBSYS_14001 > #define GCE_SUBSYS_14012 > #define GCE_SUBSYS_14023 > > in device tree, place the subsys definition in client device node, > > #include "dt-bindings/gce/mt8173-gce.h" > > ovl0: ovl@1400c000 { > compatible = "mediatek,mt8173-disp-ovl"; > gce-subsys = ; > ... > }; > > And client driver pass subsys in the related interface, > > int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 > value); > > So, for another SoC, you just need to modify device tree and you do not > need to modify driver. Hi CK, thanks for your suggestion. I do it in v22. > > + > > +static int cmdq_subsys_base_to_id(u32 base) > >
Re: [PATCH v21 4/4] soc: mediatek: Add Mediatek CMDQ helper
On Wed, 2018-02-21 at 16:05 +0800, CK Hu wrote: > Hi, Houlong: > > I've one more inline comment. > > On Wed, 2018-01-31 at 15:28 +0800, houlong@mediatek.com wrote: > > From: "hs.l...@mediatek.com" > > > > Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. > > > > Signed-off-by: Houlong Wei > > Signed-off-by: HS Liao > > --- > > drivers/soc/mediatek/Kconfig | 12 ++ > > drivers/soc/mediatek/Makefile |1 + > > drivers/soc/mediatek/mtk-cmdq-helper.c | 322 > > > > include/linux/soc/mediatek/mtk-cmdq.h | 174 + > > 4 files changed, 509 insertions(+) > > create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c > > create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h > > > > diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig > > index a7d0667..e66582e 100644 > > --- a/drivers/soc/mediatek/Kconfig > > +++ b/drivers/soc/mediatek/Kconfig > > @@ -4,6 +4,18 @@ > > menu "MediaTek SoC drivers" > > depends on ARCH_MEDIATEK || COMPILE_TEST > > > > +config MTK_CMDQ > > + bool "MediaTek CMDQ Support" > > + depends on ARM64 && ( ARCH_MEDIATEK || COMPILE_TEST ) > > + select MAILBOX > > + select MTK_CMDQ_MBOX > > + select MTK_INFRACFG > > + help > > + Say yes here to add support for the MediaTek Command Queue (CMDQ) > > + driver. The CMDQ is used to help read/write registers with critical > > + time limitation, such as updating display configuration during the > > + vblank. > > + > > config MTK_INFRACFG > > bool "MediaTek INFRACFG Support" > > select REGMAP > > diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile > > index 12998b0..64ce5ee 100644 > > --- a/drivers/soc/mediatek/Makefile > > +++ b/drivers/soc/mediatek/Makefile > > @@ -1,3 +1,4 @@ > > +obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o > > obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o > > obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o > > obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o > > diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c > > b/drivers/soc/mediatek/mtk-cmdq-helper.c > > new file mode 100644 > > index 000..80d0558 > > --- /dev/null > > +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c > > @@ -0,0 +1,322 @@ > > +/* > > + * Copyright (c) 2015 MediaTek Inc. > > + * > > + * This program is free software; you can redistribute it and/or modify > > + * it under the terms of the GNU General Public License version 2 as > > + * published by the Free Software Foundation. > > + * > > + * This program is distributed in the hope that it will be useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#define CMDQ_ARG_A_WRITE_MASK 0x > > +#define CMDQ_WRITE_ENABLE_MASK BIT(0) > > +#define CMDQ_EOC_IRQ_ENBIT(0) > > +#define CMDQ_EOC_CMD ((u64)((CMDQ_CODE_EOC << > > CMDQ_OP_CODE_SHIFT)) \ > > + << 32 | CMDQ_EOC_IRQ_EN) > > + > > +struct cmdq_subsys { > > + u32 base; > > + int id; > > +}; > > + > > +static const struct cmdq_subsys gce_subsys[] = { > > + {0x1400, 1}, > > + {0x1401, 2}, > > + {0x1402, 3}, > > +}; > > + > > +static int cmdq_subsys_base_to_id(u32 base) > > +{ > > + int i; > > + > > + for (i = 0; i < ARRAY_SIZE(gce_subsys); i++) > > + if (gce_subsys[i].base == base) > > + return gce_subsys[i].id; > > + return -EFAULT; > > +} > > + > > +static int cmdq_pkt_realloc_cmd_buffer(struct cmdq_pkt *pkt, size_t size) > > +{ > > + void *new_buf; > > + > > + new_buf = krealloc(pkt->va_base, size, GFP_KERNEL | __GFP_ZERO); > > + if (!new_buf) > > + return -ENOMEM; > > + pkt->va_base = new_buf; > > + pkt->buf_size = size; > > + return 0; > > +} > > + > > +struct cmdq_base *cmdq_register_device(struct device *dev) > > +{ > > + struct cmdq_base *cmdq_base; > > + struct resource res; >
Re: [PATCH v21 2/4] mailbox: mediatek: Add Mediatek CMDQ driver
On Wed, 2018-02-21 at 11:53 +0800, CK Hu wrote: > Hi, Houlong: > > I've one inline comment. > > On Wed, 2018-01-31 at 15:28 +0800, houlong@mediatek.com wrote: > > From: "hs.l...@mediatek.com" > > > > This patch is first version of Mediatek Command Queue(CMDQ) driver. The > > CMDQ is used to help write registers with critical time limitation, > > such as updating display configuration during the vblank. It controls > > Global Command Engine (GCE) hardware to achieve this requirement. > > Currently, CMDQ only supports display related hardwares, but we expect > > it can be extended to other hardwares for future requirements. > > > > Signed-off-by: Houlong Wei > > Signed-off-by: HS Liao > > Signed-off-by: CK Hu > > --- > > drivers/mailbox/Kconfig | 10 + > > drivers/mailbox/Makefile |2 + > > drivers/mailbox/mtk-cmdq-mailbox.c | 594 > > ++ > > include/linux/mailbox/mtk-cmdq-mailbox.h | 77 > > 4 files changed, 683 insertions(+) > > create mode 100644 drivers/mailbox/mtk-cmdq-mailbox.c > > create mode 100644 include/linux/mailbox/mtk-cmdq-mailbox.h > > > > diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig > > index ba2f152..43bb26f 100644 > > --- a/drivers/mailbox/Kconfig > > +++ b/drivers/mailbox/Kconfig > > @@ -171,4 +171,14 @@ config BCM_FLEXRM_MBOX > > Mailbox implementation of the Broadcom FlexRM ring manager, > > which provides access to various offload engines on Broadcom > > SoCs. Say Y here if you want to use the Broadcom FlexRM. > > + > > +config MTK_CMDQ_MBOX > > + bool "MediaTek CMDQ Mailbox Support" > > + depends on ARM64 && ( ARCH_MEDIATEK || COMPILE_TEST ) > > + select MTK_INFRACFG > > + help > > + Say yes here to add support for the MediaTek Command Queue (CMDQ) > > + mailbox driver. The CMDQ is used to help read/write registers with > > + critical time limitation, such as updating display configuration > > + during the vblank. > > endif > > diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile > > index 4896f8d..484d341 100644 > > --- a/drivers/mailbox/Makefile > > +++ b/drivers/mailbox/Makefile > > @@ -36,3 +36,5 @@ obj-$(CONFIG_BCM_FLEXRM_MBOX) += bcm-flexrm-mailbox.o > > obj-$(CONFIG_QCOM_APCS_IPC)+= qcom-apcs-ipc-mailbox.o > > > > obj-$(CONFIG_TEGRA_HSP_MBOX) += tegra-hsp.o > > + > > +obj-$(CONFIG_MTK_CMDQ_MBOX)+= mtk-cmdq-mailbox.o > > diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c > > b/drivers/mailbox/mtk-cmdq-mailbox.c > > new file mode 100644 > > index 000..394a335 > > --- /dev/null > > +++ b/drivers/mailbox/mtk-cmdq-mailbox.c > > @@ -0,0 +1,594 @@ > > +/* > > + * Copyright (c) 2015 MediaTek Inc. > > + * > > + * This program is free software; you can redistribute it and/or modify > > + * it under the terms of the GNU General Public License version 2 as > > + * published by the Free Software Foundation. > > + * > > + * This program is distributed in the hope that it will be useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#define CMDQ_THR_MAX_COUNT 16 > > +#define CMDQ_OP_CODE_MASK (0xff << CMDQ_OP_CODE_SHIFT) > > +#define CMDQ_TIMEOUT_MS1000 > > +#define CMDQ_IRQ_MASK 0x > > +#define CMDQ_NUM_CMD(t)(t->cmd_buf_size / > > CMDQ_INST_SIZE) > > + > > +#define CMDQ_CURR_IRQ_STATUS 0x10 > > +#define CMDQ_THR_SLOT_CYCLES 0x30 > > + > > +#define CMDQ_THR_BASE 0x100 > > +#define CMDQ_THR_SIZE 0x80 > > +#define CMDQ_THR_WARM_RESET0x00 > > +#define CMDQ_THR_ENABLE_TASK 0x04 > > +#define CMDQ_THR_SUSPEND_TASK 0x08 > > +#define CMDQ_THR_CURR_STATUS 0x0c > > +#define CMDQ_THR_IRQ_STATUS0x10 > > +#define CMDQ_THR_IRQ_ENABLE0x14 > > +#define CMDQ_THR_CURR_ADDR 0
Re: [PATCH v21 2/4] mailbox: mediatek: Add Mediatek CMDQ driver
On Thu, 2018-06-28 at 09:57 +0800, CK Hu wrote: > Hi, Houlong: > > On Wed, 2018-06-27 at 19:53 +0800, houlong wei wrote: > > On Wed, 2018-02-21 at 11:53 +0800, CK Hu wrote: > > > Hi, Houlong: > > > > > > I've one inline comment. > > > > > > On Wed, 2018-01-31 at 15:28 +0800, houlong@mediatek.com wrote: > > > > From: "hs.l...@mediatek.com" > > > > > > > > This patch is first version of Mediatek Command Queue(CMDQ) driver. The > > > > CMDQ is used to help write registers with critical time limitation, > > > > such as updating display configuration during the vblank. It controls > > > > Global Command Engine (GCE) hardware to achieve this requirement. > > > > Currently, CMDQ only supports display related hardwares, but we expect > > > > it can be extended to other hardwares for future requirements. > > > > > > > > Signed-off-by: Houlong Wei > > > > Signed-off-by: HS Liao > > > > Signed-off-by: CK Hu > > > > --- > > > > drivers/mailbox/Kconfig | 10 + > > > > drivers/mailbox/Makefile |2 + > > > > drivers/mailbox/mtk-cmdq-mailbox.c | 594 > > > > ++ > > > > include/linux/mailbox/mtk-cmdq-mailbox.h | 77 > > > > 4 files changed, 683 insertions(+) > > > > create mode 100644 drivers/mailbox/mtk-cmdq-mailbox.c > > > > create mode 100644 include/linux/mailbox/mtk-cmdq-mailbox.h > > > > > > > > diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig > > > > index ba2f152..43bb26f 100644 > > > > --- a/drivers/mailbox/Kconfig > > > > +++ b/drivers/mailbox/Kconfig > > > > @@ -171,4 +171,14 @@ config BCM_FLEXRM_MBOX > > > > Mailbox implementation of the Broadcom FlexRM ring manager, > > > > which provides access to various offload engines on Broadcom > > > > SoCs. Say Y here if you want to use the Broadcom FlexRM. > > > > + > > [...] > > > > > + > > > > +static void cmdq_task_exec(struct cmdq_pkt *pkt, struct cmdq_thread > > > > *thread) > > > > +{ > > > > + struct cmdq *cmdq; > > > > + struct cmdq_task *task; > > > > + unsigned long curr_pa, end_pa; > > > > + > > > > + cmdq = dev_get_drvdata(thread->chan->mbox->dev); > > > > + > > > > + /* Client should not flush new tasks if suspended. */ > > > > + WARN_ON(cmdq->suspended); > > > > + > > > > + task = kzalloc(sizeof(*task), GFP_ATOMIC); > > > > + task->cmdq = cmdq; > > > > + INIT_LIST_HEAD(>list_entry); > > > > + task->pa_base = pkt->pa_base; > > > > + task->thread = thread; > > > > + task->pkt = pkt; > > > > + > > > > + if (list_empty(>task_busy_list)) { > > > > + WARN_ON(clk_enable(cmdq->clock) < 0); > > > > + WARN_ON(cmdq_thread_reset(cmdq, thread) < 0); > > > > + > > > > + writel(task->pa_base, thread->base + > > > > CMDQ_THR_CURR_ADDR); > > > > + writel(task->pa_base + pkt->cmd_buf_size, > > > > + thread->base + CMDQ_THR_END_ADDR); > > > > + writel(CMDQ_THR_IRQ_EN, thread->base + > > > > CMDQ_THR_IRQ_ENABLE); > > > > + writel(CMDQ_THR_ENABLED, thread->base + > > > > CMDQ_THR_ENABLE_TASK); > > > > + > > > > + mod_timer(>timeout, > > > > + jiffies + msecs_to_jiffies(CMDQ_TIMEOUT_MS)); > > > > + } else { > > > > + WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0); > > > > + curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR); > > > > + end_pa = readl(thread->base + CMDQ_THR_END_ADDR); > > > > + > > > > + /* > > > > +* Atomic execution should remove the following wfe, > > > > i.e. only > > > > +* wait event at first task, and prevent to pause when > > > > running. > > > > +*/ > > > > + if (thread->atomic_exec
Re: [PATCH v22 4/4] soc: mediatek: Add Mediatek CMDQ helper
On Thu, 2018-06-28 at 18:41 +0800, CK Hu wrote: > Hi, Houlong: > > Some inline comment. > > On Wed, 2018-06-27 at 19:16 +0800, Houlong Wei wrote: > > Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. > > > > Signed-off-by: Houlong Wei > > Signed-off-by: HS Liao > > --- > > drivers/soc/mediatek/Kconfig | 12 ++ > > drivers/soc/mediatek/Makefile |1 + > > drivers/soc/mediatek/mtk-cmdq-helper.c | 258 > > > > include/linux/soc/mediatek/mtk-cmdq.h | 132 > > 4 files changed, 403 insertions(+) > > create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c > > create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h > > > > diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig > > index a7d0667..17bd759 100644 > > --- a/drivers/soc/mediatek/Kconfig > > +++ b/drivers/soc/mediatek/Kconfig > > @@ -4,6 +4,18 @@ > > menu "MediaTek SoC drivers" > > depends on ARCH_MEDIATEK || COMPILE_TEST > > > > [...] > > > + > > +int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u32 event) > > +{ > > + u32 arg_b; > > + > > + if (event >= CMDQ_MAX_EVENT || event < 0) > > The type of event is 'u32', so checking 'event < 0' is redundant. will fix. > > > + return -EINVAL; > > + > > + /* > > +* WFE arg_b > > +* bit 0-11: wait value > > +* bit 15: 1 - wait, 0 - no wait > > +* bit 16-27: update value > > +* bit 31: 1 - update, 0 - no update > > +*/ > > + arg_b = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE; > > + > > + return cmdq_pkt_append_command(pkt, CMDQ_CODE_WFE, event, arg_b); > > +} > > +EXPORT_SYMBOL(cmdq_pkt_wfe); > > + > > +int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u32 event) > > +{ > > + if (event >= CMDQ_MAX_EVENT || event < 0) > > The type of event is 'u32', so checking 'event < 0' is redundant. Will fix. > > > + return -EINVAL; > > + > > + return cmdq_pkt_append_command(pkt, CMDQ_CODE_WFE, event, > > + CMDQ_WFE_UPDATE); > > +} > > +EXPORT_SYMBOL(cmdq_pkt_clear_event); > > + > > +static int cmdq_pkt_finalize(struct cmdq_pkt *pkt) > > +{ > > + int err; > > + > > + if (cmdq_pkt_is_finalized(pkt)) > > + return 0; > > + > > + /* insert EOC and generate IRQ for each command iteration */ > > + err = cmdq_pkt_append_command(pkt, CMDQ_CODE_EOC, 0, CMDQ_EOC_IRQ_EN); > > + if (err < 0) > > + return err; > > + > > + /* JUMP to end */ > > + err = cmdq_pkt_append_command(pkt, CMDQ_CODE_JUMP, 0, CMDQ_JUMP_PASS); > > + if (err < 0) > > + return err; > > + > > + return 0; > > +} > > + > > +int cmdq_pkt_flush_async(struct cmdq_client *client, struct cmdq_pkt *pkt, > > +cmdq_async_flush_cb cb, void *data) > > +{ > > + int err; > > + struct device *dev; > > + dma_addr_t dma_addr; > > + > > + err = cmdq_pkt_finalize(pkt); > > + if (err < 0) > > + return err; > > + > > + dev = client->chan->mbox->dev; > > + dma_addr = dma_map_single(dev, pkt->va_base, pkt->cmd_buf_size, > > + DMA_TO_DEVICE); > > You map here, but I could not find unmap, so the unmap should be done in > client driver. I would prefer a symmetric map/unmap which means that > both map and unmap are done in client driver. I think you put map here > because you should map after finalize. The unmap is done before callback to client, in function cmdq_task_exec_done, mtk-cmdq-mailbox.c. > Therefore, export > cmdq_pkt_finalize() to client driver and let client do finalize, so > there is no finalize in flush function. This method have a benefit that > if client reuse command buffer, it need not to map/unmap frequently. If client reuse command buffer or cmdq_pkt(command queue packet), client will add new commands to the cmdq_pkt, so map/unmap are necessary for each cmdq_pkt flush. > > Regards, > CK > > > + if (dma_mapping_error(dev, dma_addr)) { > > + dev_err(client->chan->mbox->dev, "dma map failed\n"); > > + return -ENOMEM; > > + } > > + > > + pkt->pa_base = dma_addr; > > + pkt->cb.cb = cb; > > + pkt->cb.data = data; > > + > > + mbox_send_message(client->chan, pkt); > > + /*
[PATCH v27 0/2] MediaTek MT8173 CMDQ support
Hi, This is Mediatek MT8173 Command Queue(CMDQ) driver. The CMDQ is used to help write registers with critical time limitation, such as updating display configuration during the vblank. It controls Global Command Engine (GCE) hardware to achieve this requirement. Changes since v26: -rebase on v4.20-rc1 -add comment to explain why cmdq_buf_size is increased in case of appending command failure Changes since v25: -Replace WARN_ON() with WARN_ONCE() and add debug information. Changes since v24: -move WARN_ON() into cmdq_pkt_append_command() from outside Changes since v23: -rebase on v4.19-rc1 -revise return value of cmdq_mbox_create() -revise cmdq_pkt_create() -add MODULE_LICENSE() for mtk-cmdq-helper.c -adjust functions order in mtk-cmdq.h Changes since v22: -remove properties 'timeout' and 'thread-num' from device tree -move timer from CMDQ driver to CMDQ helper -move dma unmap from CMDQ driver to CMDQ helper -config thread number in CMDQ match table -remove reallocate mechanism and let client specify the cmdq buffer size -let client specify the timeout time Changes since v21: -rebase on v4.18-rc1 -remove subsys code and event id definition from mtk-cmdq-helper.c -add mt8173-gce.h to define the subsys code and envent id Changes since v20: -rebase on v4.15-rc1 -move dma_map_single outside of spinlock Changes since v19: -rebase to v4.10-rc2 Houlong Wei (2): arm64: dts: mt8173: Add GCE node soc: mediatek: Add Mediatek CMDQ helper arch/arm64/boot/dts/mediatek/mt8173.dtsi | 10 + drivers/soc/mediatek/Kconfig | 12 + drivers/soc/mediatek/Makefile| 1 + drivers/soc/mediatek/mtk-cmdq-helper.c | 300 +++ include/linux/soc/mediatek/mtk-cmdq.h| 133 ++ 5 files changed, 456 insertions(+) create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h -- 2.19.1
[PATCH v27 1/2] arm64: dts: mt8173: Add GCE node
This patch adds the device node of the GCE hardware for CMDQ module. Signed-off-by: Houlong Wei Signed-off-by: HS Liao --- arch/arm64/boot/dts/mediatek/mt8173.dtsi | 10 ++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi index abd2f15..412ffd4 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi @@ -18,6 +18,7 @@ #include #include #include +#include #include "mt8173-pinfunc.h" / { @@ -521,6 +522,15 @@ status = "disabled"; }; + gce: mailbox@10212000 { + compatible = "mediatek,mt8173-gce"; + reg = <0 0x10212000 0 0x1000>; + interrupts = ; + clocks = < CLK_INFRA_GCE>; + clock-names = "gce"; + #mbox-cells = <3>; + }; + mipi_tx0: mipi-dphy@10215000 { compatible = "mediatek,mt8173-mipi-tx"; reg = <0 0x10215000 0 0x1000>; -- 1.7.9.5
[PATCH v27 2/2] soc: mediatek: Add Mediatek CMDQ helper
Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. Signed-off-by: Houlong Wei Signed-off-by: HS Liao --- drivers/soc/mediatek/Kconfig | 12 ++ drivers/soc/mediatek/Makefile |1 + drivers/soc/mediatek/mtk-cmdq-helper.c | 300 include/linux/soc/mediatek/mtk-cmdq.h | 133 ++ 4 files changed, 446 insertions(+) create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig index a7d0667..17bd759 100644 --- a/drivers/soc/mediatek/Kconfig +++ b/drivers/soc/mediatek/Kconfig @@ -4,6 +4,18 @@ menu "MediaTek SoC drivers" depends on ARCH_MEDIATEK || COMPILE_TEST +config MTK_CMDQ + tristate "MediaTek CMDQ Support" + depends on ARCH_MEDIATEK || COMPILE_TEST + select MAILBOX + select MTK_CMDQ_MBOX + select MTK_INFRACFG + help + Say yes here to add support for the MediaTek Command Queue (CMDQ) + driver. The CMDQ is used to help read/write registers with critical + time limitation, such as updating display configuration during the + vblank. + config MTK_INFRACFG bool "MediaTek INFRACFG Support" select REGMAP diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile index 12998b0..64ce5ee 100644 --- a/drivers/soc/mediatek/Makefile +++ b/drivers/soc/mediatek/Makefile @@ -1,3 +1,4 @@ +obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c new file mode 100644 index 000..ff9fef5 --- /dev/null +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -0,0 +1,300 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2018 MediaTek Inc. + +#include +#include +#include +#include +#include +#include + +#define CMDQ_ARG_A_WRITE_MASK 0x +#define CMDQ_WRITE_ENABLE_MASK BIT(0) +#define CMDQ_EOC_IRQ_ENBIT(0) +#define CMDQ_EOC_CMD ((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \ + << 32 | CMDQ_EOC_IRQ_EN) + +static void cmdq_client_timeout(struct timer_list *t) +{ + struct cmdq_client *client = from_timer(client, t, timer); + + dev_err(client->client.dev, "cmdq timeout!\n"); +} + +struct cmdq_client *cmdq_mbox_create(struct device *dev, int index, u32 timeout) +{ + struct cmdq_client *client; + + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client) + return (struct cmdq_client *)-ENOMEM; + + client->timeout_ms = timeout; + if (timeout != CMDQ_NO_TIMEOUT) { + spin_lock_init(>lock); + timer_setup(>timer, cmdq_client_timeout, 0); + } + client->pkt_cnt = 0; + client->client.dev = dev; + client->client.tx_block = false; + client->chan = mbox_request_channel(>client, index); + + if (IS_ERR(client->chan)) { + long err; + + dev_err(dev, "failed to request channel\n"); + err = PTR_ERR(client->chan); + kfree(client); + + return ERR_PTR(err); + } + + return client; +} +EXPORT_SYMBOL(cmdq_mbox_create); + +void cmdq_mbox_destroy(struct cmdq_client *client) +{ + if (client->timeout_ms != CMDQ_NO_TIMEOUT) { + spin_lock(>lock); + del_timer_sync(>timer); + spin_unlock(>lock); + } + mbox_free_channel(client->chan); + kfree(client); +} +EXPORT_SYMBOL(cmdq_mbox_destroy); + +struct cmdq_pkt *cmdq_pkt_create(struct cmdq_client *client, size_t size) +{ + struct cmdq_pkt *pkt; + struct device *dev; + dma_addr_t dma_addr; + + pkt = kzalloc(sizeof(*pkt), GFP_KERNEL); + if (!pkt) + return ERR_PTR(-ENOMEM); + pkt->va_base = kzalloc(size, GFP_KERNEL); + if (!pkt->va_base) { + kfree(pkt); + return ERR_PTR(-ENOMEM); + } + pkt->buf_size = size; + pkt->cl = (void *)client; + + dev = client->chan->mbox->dev; + dma_addr = dma_map_single(dev, pkt->va_base, pkt->buf_size, + DMA_TO_DEVICE); + if (dma_mapping_error(dev, dma_addr)) { + dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size); + kfree(pkt->va_base); + kfree(pkt); + return ERR_PTR(-ENOMEM); + } + + pkt->pa_base = dma_addr; + + return pkt; +} +EXPORT_SYMBOL(cmdq_pkt_create); + +void cmdq_pkt_destroy(struct cmdq_pkt *pk
[PATCH] mailbox: mediatek: Add check for possible failure of kzalloc
The patch 623a6143a845("mailbox: mediatek: Add Mediatek CMDQ driver") introduce the following static checker warning: drivers/mailbox/mtk-cmdq-mailbox.c:366 cmdq_mbox_send_data() error: potential null dereference 'task'. (kzalloc returns null) Fixes: 623a6143a845 ("mailbox: mediatek: Add Mediatek CMDQ driver") Reported-by: Dan Carpenter Signed-off-by: Houlong Wei --- drivers/mailbox/mtk-cmdq-mailbox.c |3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c index aec46d5..f7cc29c 100644 --- a/drivers/mailbox/mtk-cmdq-mailbox.c +++ b/drivers/mailbox/mtk-cmdq-mailbox.c @@ -363,6 +363,9 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data) WARN_ON(cmdq->suspended); task = kzalloc(sizeof(*task), GFP_ATOMIC); + if (!task) + return -ENOMEM; + task->cmdq = cmdq; INIT_LIST_HEAD(>list_entry); task->pa_base = pkt->pa_base; -- 1.7.9.5
Re: [PATCH v23 4/4] soc: mediatek: Add Mediatek CMDQ helper
On Wed, 2018-07-25 at 09:26 +0800, Houlong Wei wrote: > Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. > > Signed-off-by: Houlong Wei > Signed-off-by: HS Liao > --- > drivers/soc/mediatek/Kconfig | 12 ++ > drivers/soc/mediatek/Makefile |1 + > drivers/soc/mediatek/mtk-cmdq-helper.c | 291 > > include/linux/soc/mediatek/mtk-cmdq.h | 135 +++ > 4 files changed, 439 insertions(+) > create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c > create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h > > diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig > index a7d0667..17bd759 100644 > --- a/drivers/soc/mediatek/Kconfig > +++ b/drivers/soc/mediatek/Kconfig > @@ -4,6 +4,18 @@ > menu "MediaTek SoC drivers" > depends on ARCH_MEDIATEK || COMPILE_TEST > > +config MTK_CMDQ > + tristate "MediaTek CMDQ Support" > + depends on ARCH_MEDIATEK || COMPILE_TEST > + select MAILBOX > + select MTK_CMDQ_MBOX > + select MTK_INFRACFG > + help > + Say yes here to add support for the MediaTek Command Queue (CMDQ) > + driver. The CMDQ is used to help read/write registers with critical > + time limitation, such as updating display configuration during the > + vblank. > + > config MTK_INFRACFG > bool "MediaTek INFRACFG Support" > select REGMAP > diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile > index 12998b0..64ce5ee 100644 > --- a/drivers/soc/mediatek/Makefile > +++ b/drivers/soc/mediatek/Makefile > @@ -1,3 +1,4 @@ > +obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o > obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o > obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o > obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o > diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c > b/drivers/soc/mediatek/mtk-cmdq-helper.c > new file mode 100644 > index 000..e4dbb7e > --- /dev/null > +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c > @@ -0,0 +1,291 @@ > +// SPDX-License-Identifier: GPL-2.0 > +// > +// Copyright (c) 2018 MediaTek Inc. > + > +#include > +#include > +#include > +#include > +#include > + > +#define CMDQ_ARG_A_WRITE_MASK0x > +#define CMDQ_WRITE_ENABLE_MASK BIT(0) > +#define CMDQ_EOC_IRQ_EN BIT(0) > +#define CMDQ_EOC_CMD ((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \ > + << 32 | CMDQ_EOC_IRQ_EN) > + > +static void cmdq_client_timeout(struct timer_list *t) > +{ > + struct cmdq_client *client = from_timer(client, t, timer); > + > + dev_err(client->client.dev, "cmdq timeout!\n"); > +} > + > +struct cmdq_client *cmdq_mbox_create(struct device *dev, int index, u32 > timeout) > +{ > + struct cmdq_client *client; > + > + client = kzalloc(sizeof(*client), GFP_KERNEL); > + if (!client) > + return (struct cmdq_client *)-ENOMEM; > + > + client->timeout_ms = timeout; > + if (timeout != CMDQ_NO_TIMEOUT) { > + spin_lock_init(>lock); > + timer_setup(>timer, cmdq_client_timeout, 0); > + } > + client->pkt_cnt = 0; > + client->client.dev = dev; > + client->client.tx_block = false; > + client->chan = mbox_request_channel(>client, index); > + > + if (IS_ERR(client->chan)) { > + long err = 0; > + > + dev_err(dev, "failed to request channel\n"); > + err = PTR_ERR(client->chan); > + kfree(client); > + > + return (struct cmdq_client *)err; > + } > + > + return client; > +} > +EXPORT_SYMBOL(cmdq_mbox_create); > + > +void cmdq_mbox_destroy(struct cmdq_client *client) > +{ > + if (client->timeout_ms != CMDQ_NO_TIMEOUT) { > + spin_lock(>lock); > + del_timer_sync(>timer); > + spin_unlock(>lock); > + } > + mbox_free_channel(client->chan); > + kfree(client); > +} > +EXPORT_SYMBOL(cmdq_mbox_destroy); > + > +int cmdq_pkt_create(struct cmdq_client *client, struct cmdq_pkt **pkt_ptr, > + size_t size) > +{ > + struct cmdq_pkt *pkt; > + struct device *dev; > + dma_addr_t dma_addr; > + > + pkt = kzalloc(sizeof(*pkt), GFP_KERNEL); > + if (!pkt) > + return -ENOMEM; > + pkt->va_base = kzalloc(size, GFP_KERNEL); > + if (!pkt->va_base) { > + kfree(pkt); > + return -ENOMEM; > + } > + pkt-&g
Re: [PATCH v23 3/4] arm64: dts: mt8173: Add GCE node
On Wed, 2018-07-25 at 09:26 +0800, Houlong Wei wrote: > This patch adds the device node of the GCE hardware for CMDQ module. > > Signed-off-by: Houlong Wei > Signed-off-by: HS Liao > --- > arch/arm64/boot/dts/mediatek/mt8173.dtsi | 10 ++ > 1 file changed, 10 insertions(+) > > diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi > b/arch/arm64/boot/dts/mediatek/mt8173.dtsi > index 94597e3..97b1ec6 100644 > --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi > +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi > @@ -18,6 +18,7 @@ > #include > #include > #include > +#include > #include "mt8173-pinfunc.h" > > / { > @@ -519,6 +520,15 @@ > status = "disabled"; > }; > > + gce: mailbox@10212000 { > + compatible = "mediatek,mt8173-gce"; > + reg = <0 0x10212000 0 0x1000>; > + interrupts = ; > + clocks = < CLK_INFRA_GCE>; > + clock-names = "gce"; > + #mbox-cells = <3>; > + }; > + > mipi_tx0: mipi-dphy@10215000 { > compatible = "mediatek,mt8173-mipi-tx"; > reg = <0 0x10215000 0 0x1000>; Hi Matthias, Could you please review this patch when you are available? Thanks a lot.
MediaTek MT8173 CMDQ support
Hi, This is Mediatek MT8173 Command Queue(CMDQ) driver. The CMDQ is used to help write registers with critical time limitation, such as updating display configuration during the vblank. It controls Global Command Engine (GCE) hardware to achieve this requirement. Changes since v24: -move WARN_ON() into cmdq_pkt_append_command() from outside Changes since v23: -rebase on v4.19-rc1 -revise return value of cmdq_mbox_create() -revise cmdq_pkt_create() -add MODULE_LICENSE() for mtk-cmdq-helper.c -adjust functions order in mtk-cmdq.h Changes since v22: -remove properties 'timeout' and 'thread-num' from device tree -move timer from CMDQ driver to CMDQ helper -move dma unmap from CMDQ driver to CMDQ helper -config thread number in CMDQ match table -remove reallocate mechanism and let client specify the cmdq buffer size -let client specify the timeout time Changes since v21: -rebase on v4.18-rc1 -remove subsys code and event id definition from mtk-cmdq-helper.c -add mt8173-gce.h to define the subsys code and envent id Changes since v20: -rebase on v4.15-rc1 -move dma_map_single outside of spinlock Changes since v19: -rebase to v4.10-rc2 Houlong Wei (2): arm64: dts: mt8173: Add GCE node soc: mediatek: Add Mediatek CMDQ helper arch/arm64/boot/dts/mediatek/mt8173.dtsi | 10 + drivers/soc/mediatek/Kconfig | 12 ++ drivers/soc/mediatek/Makefile|1 + drivers/soc/mediatek/mtk-cmdq-helper.c | 291 ++ include/linux/soc/mediatek/mtk-cmdq.h| 133 ++ 5 files changed, 447 insertions(+) create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h -- 1.7.9.5
[PATCH v25 1/2] arm64: dts: mt8173: Add GCE node
This patch adds the device node of the GCE hardware for CMDQ module. Signed-off-by: Houlong Wei Signed-off-by: HS Liao --- arch/arm64/boot/dts/mediatek/mt8173.dtsi | 10 ++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi index abd2f15..412ffd4 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi @@ -18,6 +18,7 @@ #include #include #include +#include #include "mt8173-pinfunc.h" / { @@ -521,6 +522,15 @@ status = "disabled"; }; + gce: mailbox@10212000 { + compatible = "mediatek,mt8173-gce"; + reg = <0 0x10212000 0 0x1000>; + interrupts = ; + clocks = < CLK_INFRA_GCE>; + clock-names = "gce"; + #mbox-cells = <3>; + }; + mipi_tx0: mipi-dphy@10215000 { compatible = "mediatek,mt8173-mipi-tx"; reg = <0 0x10215000 0 0x1000>; -- 1.7.9.5
[PATCH v25 2/2] soc: mediatek: Add Mediatek CMDQ helper
Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. Signed-off-by: Houlong Wei Signed-off-by: HS Liao --- drivers/soc/mediatek/Kconfig | 12 ++ drivers/soc/mediatek/Makefile |1 + drivers/soc/mediatek/mtk-cmdq-helper.c | 291 include/linux/soc/mediatek/mtk-cmdq.h | 133 +++ 4 files changed, 437 insertions(+) create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig index a7d0667..17bd759 100644 --- a/drivers/soc/mediatek/Kconfig +++ b/drivers/soc/mediatek/Kconfig @@ -4,6 +4,18 @@ menu "MediaTek SoC drivers" depends on ARCH_MEDIATEK || COMPILE_TEST +config MTK_CMDQ + tristate "MediaTek CMDQ Support" + depends on ARCH_MEDIATEK || COMPILE_TEST + select MAILBOX + select MTK_CMDQ_MBOX + select MTK_INFRACFG + help + Say yes here to add support for the MediaTek Command Queue (CMDQ) + driver. The CMDQ is used to help read/write registers with critical + time limitation, such as updating display configuration during the + vblank. + config MTK_INFRACFG bool "MediaTek INFRACFG Support" select REGMAP diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile index 12998b0..64ce5ee 100644 --- a/drivers/soc/mediatek/Makefile +++ b/drivers/soc/mediatek/Makefile @@ -1,3 +1,4 @@ +obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c new file mode 100644 index 000..86a7ab5 --- /dev/null +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -0,0 +1,291 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2018 MediaTek Inc. + +#include +#include +#include +#include +#include +#include + +#define CMDQ_ARG_A_WRITE_MASK 0x +#define CMDQ_WRITE_ENABLE_MASK BIT(0) +#define CMDQ_EOC_IRQ_ENBIT(0) +#define CMDQ_EOC_CMD ((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \ + << 32 | CMDQ_EOC_IRQ_EN) + +static void cmdq_client_timeout(struct timer_list *t) +{ + struct cmdq_client *client = from_timer(client, t, timer); + + dev_err(client->client.dev, "cmdq timeout!\n"); +} + +struct cmdq_client *cmdq_mbox_create(struct device *dev, int index, u32 timeout) +{ + struct cmdq_client *client; + + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client) + return (struct cmdq_client *)-ENOMEM; + + client->timeout_ms = timeout; + if (timeout != CMDQ_NO_TIMEOUT) { + spin_lock_init(>lock); + timer_setup(>timer, cmdq_client_timeout, 0); + } + client->pkt_cnt = 0; + client->client.dev = dev; + client->client.tx_block = false; + client->chan = mbox_request_channel(>client, index); + + if (IS_ERR(client->chan)) { + long err; + + dev_err(dev, "failed to request channel\n"); + err = PTR_ERR(client->chan); + kfree(client); + + return ERR_PTR(err); + } + + return client; +} +EXPORT_SYMBOL(cmdq_mbox_create); + +void cmdq_mbox_destroy(struct cmdq_client *client) +{ + if (client->timeout_ms != CMDQ_NO_TIMEOUT) { + spin_lock(>lock); + del_timer_sync(>timer); + spin_unlock(>lock); + } + mbox_free_channel(client->chan); + kfree(client); +} +EXPORT_SYMBOL(cmdq_mbox_destroy); + +struct cmdq_pkt *cmdq_pkt_create(struct cmdq_client *client, size_t size) +{ + struct cmdq_pkt *pkt; + struct device *dev; + dma_addr_t dma_addr; + + pkt = kzalloc(sizeof(*pkt), GFP_KERNEL); + if (!pkt) + return ERR_PTR(-ENOMEM); + pkt->va_base = kzalloc(size, GFP_KERNEL); + if (!pkt->va_base) { + kfree(pkt); + return ERR_PTR(-ENOMEM); + } + pkt->buf_size = size; + pkt->cl = (void *)client; + + dev = client->chan->mbox->dev; + dma_addr = dma_map_single(dev, pkt->va_base, pkt->buf_size, + DMA_TO_DEVICE); + if (dma_mapping_error(dev, dma_addr)) { + dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size); + kfree(pkt->va_base); + kfree(pkt); + return ERR_PTR(-ENOMEM); + } + + pkt->pa_base = dma_addr; + + return pkt; +} +EXPORT_SYMBOL(cmdq_pkt_create); + +void cmdq_pkt_destroy(struct cmdq_pkt *pk
Re: [PATCH] arm64: dts: add gce node for mt8183
On Thu, 2019-03-07 at 09:24 +0800, CK Hu wrote: > Hi, Bibby: > > On Wed, 2019-03-06 at 18:10 +0800, Bibby Hsieh wrote: > > This patch need based on v5.0-rc1 and these series > > http://lists.infradead.org/pipermail/linux-mediatek/2019-February/017570.html > > http://lists.infradead.org/pipermail/linux-mediatek/2019-February/017320.html > > http://lists.infradead.org/pipermail/linux-mediatek/2019-January/017196.html > > http://lists.infradead.org/pipermail/linux-mediatek/2019-March/018005.html > > > > add gce device node for mt8183 > > > > Signed-off-by: Bibby Hsieh > > --- > > arch/arm64/boot/dts/mediatek/mt8183.dtsi | 13 + > > 1 file changed, 13 insertions(+) > > > > diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi > > b/arch/arm64/boot/dts/mediatek/mt8183.dtsi > > index 165b859..5006368 100644 > > --- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi > > +++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi > > @@ -8,6 +8,7 @@ > > #include > > #include > > #include > > +#include > > #include "mt8183-pinfunc.h" > > > > / { > > @@ -238,6 +239,18 @@ > > clock-names = "spi", "wrap"; > > }; > > > > + gce: gce@10238000 { > > + compatible = "mediatek,mt8183-gce"; > > + reg = <0 0x10238000 0 0x4000>; > > + interrupts = ; > > + thread-num = ; > > I does not find 'thread-num' in binding document [1]. > > [1] > https://www.kernel.org/doc/Documentation/devicetree/bindings/mailbox/mtk-gce.txt > > Regards, > CK The property "thread-num" is not used and and it was removed from the properties description, but I forgot to remove it from the example. That is misleading and I'm sorry for that. @Bibby, could you please help remove it from the example in mtk-gce.txt if you would upload a new version? > > > + #mbox-cells = <3>; > > + #gce-event-cells = <1>; > > + #gce-subsys-cells = <2>; > > + clocks = < CLK_INFRA_GCE>; > > + clock-names = "gce"; > > + }; > > + > > uart0: serial@11002000 { > > compatible = "mediatek,mt8183-uart", > > "mediatek,mt6577-uart"; >
Re: [PATCH v23 4/4] soc: mediatek: Add Mediatek CMDQ helper
On Wed, 2018-08-15 at 09:46 +0800, houlong wei wrote: > On Wed, 2018-07-25 at 09:26 +0800, Houlong Wei wrote: > > Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. > >[...] Hello Matthias, Sorry to disturb you. Could you please review this patch and give your comment? Thanks a lot. Regards Houlong
Re: [PATCH v23 3/4] arm64: dts: mt8173: Add GCE node
On Wed, 2018-08-15 at 09:48 +0800, houlong wei wrote: > On Wed, 2018-07-25 at 09:26 +0800, Houlong Wei wrote: > > This patch adds the device node of the GCE hardware for CMDQ module. > > [...] Hello Matthias, Sorry to disturb you. Are you availabe to review this patch and give your comment? Thanks a lot. Regards Houlong
[PATCH v23 0/4] MediaTek MT8173 CMDQ support
Hi, This is Mediatek MT8173 Command Queue(CMDQ) driver. The CMDQ is used to help write registers with critical time limitation, such as updating display configuration during the vblank. It controls Global Command Engine (GCE) hardware to achieve this requirement. Changes since v22: -remove properties 'timeout' and 'thread-num' from device tree -move timer from CMDQ driver to CMDQ helper -move dma unmap from CMDQ driver to CMDQ helper -config thread number in CMDQ match table -remove reallocate mechanism and let client specify the cmdq buffer size -let client specify the timeout time Changes since v21: -rebase on v4.18-rc1 -remove subsys code and event id definition from mtk-cmdq-helper.c -add mt8173-gce.h to define the subsys code and envent id Changes since v20: -rebase on v4.15-rc1 -move dma_map_single outside of spinlock Changes since v19: - rebase to v4.10-rc2 Houlong Wei (4): dt-bindings: soc: Add documentation for the MediaTek GCE unit mailbox: mediatek: Add Mediatek CMDQ driver arm64: dts: mt8173: Add GCE node soc: mediatek: Add Mediatek CMDQ helper .../devicetree/bindings/mailbox/mtk-gce.txt| 57 +++ arch/arm64/boot/dts/mediatek/mt8173.dtsi | 10 + drivers/mailbox/Kconfig| 10 + drivers/mailbox/Makefile | 2 + drivers/mailbox/mtk-cmdq-mailbox.c | 569 + drivers/soc/mediatek/Kconfig | 12 + drivers/soc/mediatek/Makefile | 1 + drivers/soc/mediatek/mtk-cmdq-helper.c | 291 +++ include/dt-bindings/gce/mt8173-gce.h | 44 ++ include/linux/mailbox/mtk-cmdq-mailbox.h | 77 +++ include/linux/soc/mediatek/mtk-cmdq.h | 135 + 11 files changed, 1208 insertions(+) create mode 100644 Documentation/devicetree/bindings/mailbox/mtk-gce.txt create mode 100644 drivers/mailbox/mtk-cmdq-mailbox.c create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c create mode 100644 include/dt-bindings/gce/mt8173-gce.h create mode 100644 include/linux/mailbox/mtk-cmdq-mailbox.h create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h -- 2.12.5
[PATCH v23 1/4] dt-bindings: soc: Add documentation for the MediaTek GCE unit
This adds documentation for the MediaTek Global Command Engine (GCE) unit found in MT8173 SoCs. Signed-off-by: Houlong Wei Signed-off-by: HS Liao --- .../devicetree/bindings/mailbox/mtk-gce.txt| 57 include/dt-bindings/gce/mt8173-gce.h | 44 +++ 2 files changed, 101 insertions(+) create mode 100644 Documentation/devicetree/bindings/mailbox/mtk-gce.txt create mode 100644 include/dt-bindings/gce/mt8173-gce.h diff --git a/Documentation/devicetree/bindings/mailbox/mtk-gce.txt b/Documentation/devicetree/bindings/mailbox/mtk-gce.txt new file mode 100644 index 000..7d72b21 --- /dev/null +++ b/Documentation/devicetree/bindings/mailbox/mtk-gce.txt @@ -0,0 +1,57 @@ +MediaTek GCE +=== + +The Global Command Engine (GCE) is used to help read/write registers with +critical time limitation, such as updating display configuration during the +vblank. The GCE can be used to implement the Command Queue (CMDQ) driver. + +CMDQ driver uses mailbox framework for communication. Please refer to +mailbox.txt for generic information about mailbox device-tree bindings. + +Required properties: +- compatible: Must be "mediatek,mt8173-gce" +- reg: Address range of the GCE unit +- interrupts: The interrupt signal from the GCE block +- clock: Clocks according to the common clock binding +- clock-names: Must be "gce" to stand for GCE clock +- #mbox-cells: Should be 3. + < channel priority atomic_exec> + phandle: Label name of a gce node. + channel: Channel of mailbox. Be equal to the thread id of GCE. + priority: Priority of GCE thread. + atomic_exec: GCE processing continuous packets of commands in atomic + way. + +Required properties for a client device: +- mboxes: Client use mailbox to communicate with GCE, it should have this + property and list of phandle, mailbox specifiers. +- mediatek,gce-subsys: u32, specify the sub-system id which is corresponding + to the register address. + +Some vaules of properties are defined in 'dt-bindings/gce/mt8173-gce.h'. Such as +sub-system ids, thread priority, event ids. + +Example: + + gce: gce@10212000 { + compatible = "mediatek,mt8173-gce"; + reg = <0 0x10212000 0 0x1000>; + interrupts = ; + clocks = < CLK_INFRA_GCE>; + clock-names = "gce"; + thread-num = CMDQ_THR_MAX_COUNT; + #mbox-cells = <3>; + }; + +Example for a client device: + + mmsys: clock-controller@1400 { + compatible = "mediatek,mt8173-mmsys"; + mboxes = < 0 CMDQ_THR_PRIO_LOWEST 1>, +< 1 CMDQ_THR_PRIO_LOWEST 1>; + mediatek,gce-subsys = ; + mutex-event-eof = ; + + ... + }; diff --git a/include/dt-bindings/gce/mt8173-gce.h b/include/dt-bindings/gce/mt8173-gce.h new file mode 100644 index 000..ffcf94b --- /dev/null +++ b/include/dt-bindings/gce/mt8173-gce.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Houlong Wei + * + */ + +#ifndef _DT_BINDINGS_GCE_MT8173_H +#define _DT_BINDINGS_GCE_MT8173_H + +/* GCE HW thread priority */ +#define CMDQ_THR_PRIO_LOWEST 0 +#define CMDQ_THR_PRIO_HIGHEST 1 + +/* GCE SUBSYS */ +#define SUBSYS_14001 +#define SUBSYS_14012 +#define SUBSYS_14023 + +/* GCE HW EVENT */ +#define CMDQ_EVENT_DISP_OVL0_SOF 11 +#define CMDQ_EVENT_DISP_OVL1_SOF 12 +#define CMDQ_EVENT_DISP_RDMA0_SOF 13 +#define CMDQ_EVENT_DISP_RDMA1_SOF 14 +#define CMDQ_EVENT_DISP_RDMA2_SOF 15 +#define CMDQ_EVENT_DISP_WDMA0_SOF 16 +#define CMDQ_EVENT_DISP_WDMA1_SOF 17 +#define CMDQ_EVENT_DISP_OVL0_EOF 39 +#define CMDQ_EVENT_DISP_OVL1_EOF 40 +#define CMDQ_EVENT_DISP_RDMA0_EOF 41 +#define CMDQ_EVENT_DISP_RDMA1_EOF 42 +#define CMDQ_EVENT_DISP_RDMA2_EOF 43 +#define CMDQ_EVENT_DISP_WDMA0_EOF 44 +#define CMDQ_EVENT_DISP_WDMA1_EOF 45 +#define CMDQ_EVENT_MUTEX0_STREAM_EOF 53 +#define CMDQ_EVENT_MUTEX1_STREAM_EOF 54 +#define CMDQ_EVENT_MUTEX2_STREAM_EOF 55 +#define CMDQ_EVENT_MUTEX3_STREAM_EOF 56 +#define CMDQ_EVENT_MUTEX4_STREAM_EOF 57 +#define CMDQ_EVENT_DISP_RDMA0_UNDERRUN 63 +#define CMDQ_EVENT_DISP_RDMA1_UNDERRUN 64 +#define CMDQ_EVENT_DISP_RDMA2_UNDERRUN 65 + +#endif -- 1.7.9.5
[PATCH v23 3/4] arm64: dts: mt8173: Add GCE node
This patch adds the device node of the GCE hardware for CMDQ module. Signed-off-by: Houlong Wei Signed-off-by: HS Liao --- arch/arm64/boot/dts/mediatek/mt8173.dtsi | 10 ++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi index 94597e3..97b1ec6 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi @@ -18,6 +18,7 @@ #include #include #include +#include #include "mt8173-pinfunc.h" / { @@ -519,6 +520,15 @@ status = "disabled"; }; + gce: mailbox@10212000 { + compatible = "mediatek,mt8173-gce"; + reg = <0 0x10212000 0 0x1000>; + interrupts = ; + clocks = < CLK_INFRA_GCE>; + clock-names = "gce"; + #mbox-cells = <3>; + }; + mipi_tx0: mipi-dphy@10215000 { compatible = "mediatek,mt8173-mipi-tx"; reg = <0 0x10215000 0 0x1000>; -- 1.7.9.5
[PATCH v23 2/4] mailbox: mediatek: Add Mediatek CMDQ driver
This patch is first version of Mediatek Command Queue(CMDQ) driver. The CMDQ is used to help write registers with critical time limitation, such as updating display configuration during the vblank. It controls Global Command Engine (GCE) hardware to achieve this requirement. Currently, CMDQ only supports display related hardwares, but we expect it can be extended to other hardwares for future requirements. Signed-off-by: Houlong Wei Signed-off-by: HS Liao Signed-off-by: CK Hu --- drivers/mailbox/Kconfig | 10 + drivers/mailbox/Makefile |2 + drivers/mailbox/mtk-cmdq-mailbox.c | 569 ++ include/linux/mailbox/mtk-cmdq-mailbox.h | 77 4 files changed, 658 insertions(+) create mode 100644 drivers/mailbox/mtk-cmdq-mailbox.c create mode 100644 include/linux/mailbox/mtk-cmdq-mailbox.h diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index e63d29a..2bbabc9 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -189,4 +189,14 @@ config STM32_IPCC Mailbox implementation for STMicroelectonics STM32 family chips with hardware for Inter-Processor Communication Controller (IPCC) between processors. Say Y here if you want to have this support. + +config MTK_CMDQ_MBOX + tristate "MediaTek CMDQ Mailbox Support" + depends on ARCH_MEDIATEK || COMPILE_TEST + select MTK_INFRACFG + help + Say yes here to add support for the MediaTek Command Queue (CMDQ) + mailbox driver. The CMDQ is used to help read/write registers with + critical time limitation, such as updating display configuration + during the vblank. endif diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index 4d501be..4b00804 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -40,3 +40,5 @@ obj-$(CONFIG_QCOM_APCS_IPC) += qcom-apcs-ipc-mailbox.o obj-$(CONFIG_TEGRA_HSP_MBOX) += tegra-hsp.o obj-$(CONFIG_STM32_IPCC) += stm32-ipcc.o + +obj-$(CONFIG_MTK_CMDQ_MBOX)+= mtk-cmdq-mailbox.o diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c new file mode 100644 index 000..6f92c5e --- /dev/null +++ b/drivers/mailbox/mtk-cmdq-mailbox.c @@ -0,0 +1,569 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2018 MediaTek Inc. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CMDQ_OP_CODE_MASK (0xff << CMDQ_OP_CODE_SHIFT) +#define CMDQ_IRQ_MASK 0x +#define CMDQ_NUM_CMD(t)(t->cmd_buf_size / CMDQ_INST_SIZE) + +#define CMDQ_CURR_IRQ_STATUS 0x10 +#define CMDQ_THR_SLOT_CYCLES 0x30 +#define CMDQ_THR_BASE 0x100 +#define CMDQ_THR_SIZE 0x80 +#define CMDQ_THR_WARM_RESET0x00 +#define CMDQ_THR_ENABLE_TASK 0x04 +#define CMDQ_THR_SUSPEND_TASK 0x08 +#define CMDQ_THR_CURR_STATUS 0x0c +#define CMDQ_THR_IRQ_STATUS0x10 +#define CMDQ_THR_IRQ_ENABLE0x14 +#define CMDQ_THR_CURR_ADDR 0x20 +#define CMDQ_THR_END_ADDR 0x24 +#define CMDQ_THR_WAIT_TOKEN0x30 +#define CMDQ_THR_PRIORITY 0x40 + +#define CMDQ_THR_ACTIVE_SLOT_CYCLES0x3200 +#define CMDQ_THR_ENABLED 0x1 +#define CMDQ_THR_DISABLED 0x0 +#define CMDQ_THR_SUSPEND 0x1 +#define CMDQ_THR_RESUME0x0 +#define CMDQ_THR_STATUS_SUSPENDED BIT(1) +#define CMDQ_THR_DO_WARM_RESET BIT(0) +#define CMDQ_THR_IRQ_DONE 0x1 +#define CMDQ_THR_IRQ_ERROR 0x12 +#define CMDQ_THR_IRQ_EN(CMDQ_THR_IRQ_ERROR | CMDQ_THR_IRQ_DONE) +#define CMDQ_THR_IS_WAITINGBIT(31) + +#define CMDQ_JUMP_BY_OFFSET0x1000 +#define CMDQ_JUMP_BY_PA0x1001 + +struct cmdq_thread { + struct mbox_chan*chan; + void __iomem*base; + struct list_headtask_busy_list; + u32 priority; + boolatomic_exec; +}; + +struct cmdq_task { + struct cmdq *cmdq; + struct list_headlist_entry; + dma_addr_t pa_base; + struct cmdq_thread *thread; + struct cmdq_pkt *pkt; /* the packet sent from mailbox client */ +}; + +struct cmdq { + struct mbox_controller mbox; + void __iomem*base; + u32 irq; + u32 thread_nr; + struct cmdq_thread *thread; + struct clk *clock; + boolsuspended; +}; + +static int cmdq_thread_suspend(struct cmdq *cmdq, struct cmdq_thread *thread) +{ + u32 status; + + writel(CMDQ_
[PATCH v23 4/4] soc: mediatek: Add Mediatek CMDQ helper
Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. Signed-off-by: Houlong Wei Signed-off-by: HS Liao --- drivers/soc/mediatek/Kconfig | 12 ++ drivers/soc/mediatek/Makefile |1 + drivers/soc/mediatek/mtk-cmdq-helper.c | 291 include/linux/soc/mediatek/mtk-cmdq.h | 135 +++ 4 files changed, 439 insertions(+) create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig index a7d0667..17bd759 100644 --- a/drivers/soc/mediatek/Kconfig +++ b/drivers/soc/mediatek/Kconfig @@ -4,6 +4,18 @@ menu "MediaTek SoC drivers" depends on ARCH_MEDIATEK || COMPILE_TEST +config MTK_CMDQ + tristate "MediaTek CMDQ Support" + depends on ARCH_MEDIATEK || COMPILE_TEST + select MAILBOX + select MTK_CMDQ_MBOX + select MTK_INFRACFG + help + Say yes here to add support for the MediaTek Command Queue (CMDQ) + driver. The CMDQ is used to help read/write registers with critical + time limitation, such as updating display configuration during the + vblank. + config MTK_INFRACFG bool "MediaTek INFRACFG Support" select REGMAP diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile index 12998b0..64ce5ee 100644 --- a/drivers/soc/mediatek/Makefile +++ b/drivers/soc/mediatek/Makefile @@ -1,3 +1,4 @@ +obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c new file mode 100644 index 000..e4dbb7e --- /dev/null +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -0,0 +1,291 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2018 MediaTek Inc. + +#include +#include +#include +#include +#include + +#define CMDQ_ARG_A_WRITE_MASK 0x +#define CMDQ_WRITE_ENABLE_MASK BIT(0) +#define CMDQ_EOC_IRQ_ENBIT(0) +#define CMDQ_EOC_CMD ((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \ + << 32 | CMDQ_EOC_IRQ_EN) + +static void cmdq_client_timeout(struct timer_list *t) +{ + struct cmdq_client *client = from_timer(client, t, timer); + + dev_err(client->client.dev, "cmdq timeout!\n"); +} + +struct cmdq_client *cmdq_mbox_create(struct device *dev, int index, u32 timeout) +{ + struct cmdq_client *client; + + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client) + return (struct cmdq_client *)-ENOMEM; + + client->timeout_ms = timeout; + if (timeout != CMDQ_NO_TIMEOUT) { + spin_lock_init(>lock); + timer_setup(>timer, cmdq_client_timeout, 0); + } + client->pkt_cnt = 0; + client->client.dev = dev; + client->client.tx_block = false; + client->chan = mbox_request_channel(>client, index); + + if (IS_ERR(client->chan)) { + long err = 0; + + dev_err(dev, "failed to request channel\n"); + err = PTR_ERR(client->chan); + kfree(client); + + return (struct cmdq_client *)err; + } + + return client; +} +EXPORT_SYMBOL(cmdq_mbox_create); + +void cmdq_mbox_destroy(struct cmdq_client *client) +{ + if (client->timeout_ms != CMDQ_NO_TIMEOUT) { + spin_lock(>lock); + del_timer_sync(>timer); + spin_unlock(>lock); + } + mbox_free_channel(client->chan); + kfree(client); +} +EXPORT_SYMBOL(cmdq_mbox_destroy); + +int cmdq_pkt_create(struct cmdq_client *client, struct cmdq_pkt **pkt_ptr, + size_t size) +{ + struct cmdq_pkt *pkt; + struct device *dev; + dma_addr_t dma_addr; + + pkt = kzalloc(sizeof(*pkt), GFP_KERNEL); + if (!pkt) + return -ENOMEM; + pkt->va_base = kzalloc(size, GFP_KERNEL); + if (!pkt->va_base) { + kfree(pkt); + return -ENOMEM; + } + pkt->buf_size = size; + pkt->cl = (void *)client; + + dev = client->chan->mbox->dev; + dma_addr = dma_map_single(dev, pkt->va_base, pkt->buf_size, + DMA_TO_DEVICE); + if (dma_mapping_error(dev, dma_addr)) { + dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size); + kfree(pkt->va_base); + kfree(pkt); + return -ENOMEM; + } + + pkt->pa_base = dma_addr; + *pkt_ptr = pkt; + + return 0; +} +EXPORT_SYMBOL(cmdq_pkt_create); + +void cmdq_pkt_destroy(struct cmdq_pkt *pk
Re: [PATCH v22 1/4] dt-bindings: soc: Add documentation for the MediaTek GCE unit
On Tue, 2018-07-03 at 10:30 +0800, Rob Herring wrote: > On Wed, Jun 27, 2018 at 07:16:09PM +0800, Houlong Wei wrote: > > This adds documentation for the MediaTek Global Command Engine (GCE) unit > > found in MT8173 SoCs. > > > > Signed-off-by: Houlong Wei > > Signed-off-by: HS Liao > > --- > > Hi Rob, > > I don't add your ACK in this version since the dt-binding description > > has been changed. Thanks. > > --- > > .../devicetree/bindings/mailbox/mtk-gce.txt| 65 > > > > include/dt-bindings/gce/mt8173-gce.h | 48 +++ > > 2 files changed, 113 insertions(+) > > create mode 100644 Documentation/devicetree/bindings/mailbox/mtk-gce.txt > > create mode 100644 include/dt-bindings/gce/mt8173-gce.h > > > > diff --git a/Documentation/devicetree/bindings/mailbox/mtk-gce.txt > > b/Documentation/devicetree/bindings/mailbox/mtk-gce.txt > > new file mode 100644 > > index 000..26f65a4 > > --- /dev/null > > +++ b/Documentation/devicetree/bindings/mailbox/mtk-gce.txt > > @@ -0,0 +1,65 @@ > > +MediaTek GCE > > +=== > > + > > +The Global Command Engine (GCE) is used to help read/write registers with > > +critical time limitation, such as updating display configuration during the > > +vblank. The GCE can be used to implement the Command Queue (CMDQ) driver. > > + > > +CMDQ driver uses mailbox framework for communication. Please refer to > > +mailbox.txt for generic information about mailbox device-tree bindings. > > + > > +Required properties: > > +- compatible: Must be "mediatek,mt8173-gce" > > +- reg: Address range of the GCE unit > > +- interrupts: The interrupt signal from the GCE block > > +- clock: Clocks according to the common clock binding > > +- clock-names: Must be "gce" to stand for GCE clock > > +- thread-num: Maximum threads count of GCE. > > mediatek,thread-num > > Is this needed for anything other than error checking the thread id in > the mbox cells? if that's it, then drop it. > 'thread-num' is used to configure the GCE thread number, which is the channel number of gce mailbox. This property is read in cmdq_probe()/mtk-cmdq-mailbox.c and a mailbox's channel array is allocated according to the number. Since the thread number may be different on different SoC, we wish it could be configured in device tree. > > +- #mbox-cells: Should be 4. > > + < channel timeout priority atomic_exec> > > + phandle: Label name of a gce node. > > + channel: Channel of mailbox. Be equal to the thread id of GCE. > > + timeout: Maximum time of software waiting GCE processing done, in unit > > + of millisecond. > > + priority: Priority of GCE thread. > > + atomic_exec: GCE processing continuous packets of commands in atomic > > + way. > > + > > +Required properties for a client device: > > +- mboxes: Client use mailbox to communicate with GCE, it should have this > > + property and list of phandle, mailbox specifiers. > > +- gce-subsys: Specify the sub-system id which is corresponding to the > > register > > + address. > > What is this for? You mean the new added property 'gce-subsys'? It is used for GCE to distinguish the high 16-bit of a hardware register address. When a client driver packets a register setting into a GCE instruction, it uses a sub-system code and register offset instead of the 32-bit register address. Since sub-system code may be different on different SoC, we wish it could be configured in device tree. > > > + > > +Optional properties for a client device: > > +- gce-event: Specify the event if the client has any. Because the event is > > + parsed by client, so client can replace 'gce-event' with other meaningful > > + name. > > If the client sets the name, then no point having here. It must be > documented in the client binding. But then, what is this for in the > first place? Since display driver will use GCE firstly, so we will move the description to 'Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt' when display driver start using the GCE driver. Is that ok? > > > + > > +Some vaules of properties are defined in 'dt-bindings/gce/mt8173-gce.h'. > > Such as > > +thread number, sub-system ids, thread priority, event ids. > > + > > +Example: > > + > > + gce: gce@10212000 { > > mailbox@... Will do. > > > + compatible = "mediatek,mt8173-gce"; > > + reg = <0 0x10212000 0 0x1000>; &
Re: [PATCH v22 2/4] mailbox: mediatek: Add Mediatek CMDQ driver
On Fri, 2018-06-29 at 15:08 +0800, CK Hu wrote: > Hi, Houlong: > > Some inline comment. > > On Wed, 2018-06-27 at 19:16 +0800, Houlong Wei wrote: > > This patch is first version of Mediatek Command Queue(CMDQ) driver. The > > CMDQ is used to help write registers with critical time limitation, > > such as updating display configuration during the vblank. It controls > > Global Command Engine (GCE) hardware to achieve this requirement. > > Currently, CMDQ only supports display related hardwares, but we expect > > it can be extended to other hardwares for future requirements. > > > > Signed-off-by: Houlong Wei > > Signed-off-by: HS Liao > > Signed-off-by: CK Hu > > --- > > drivers/mailbox/Kconfig | 10 + > > drivers/mailbox/Makefile |2 + > > drivers/mailbox/mtk-cmdq-mailbox.c | 634 > > ++ > > include/linux/mailbox/mtk-cmdq-mailbox.h | 70 > > 4 files changed, 716 insertions(+) > > create mode 100644 drivers/mailbox/mtk-cmdq-mailbox.c > > create mode 100644 include/linux/mailbox/mtk-cmdq-mailbox.h > > > > [...] > > > + > > +static int cmdq_thread_reset(struct cmdq *cmdq, struct cmdq_thread *thread) > > +{ > > + u32 warm_reset; > > + > > + writel(CMDQ_THR_DO_WARM_RESET, thread->base + CMDQ_THR_WARM_RESET); > > + if (readl_poll_timeout_atomic(thread->base + CMDQ_THR_WARM_RESET, > > + warm_reset, !(warm_reset & CMDQ_THR_DO_WARM_RESET), > > + 0, 10)) { > > + dev_err(cmdq->mbox.dev, "reset GCE thread 0x%x failed\n", > > + (u32)(thread->base - cmdq->base)); > > + return -EFAULT; > > + } > > + writel(CMDQ_THR_ACTIVE_SLOT_CYCLES, cmdq->base + CMDQ_THR_SLOT_CYCLES); > > The CMDQ_THR_SLOT_CYCLES looks like not relevant to reset. Maybe you > just need to set this value when startup. Will move configuration of CMDQ_THR_SLOT_CYCLES to cmdq_xlate() where is startup of a GCE thread. > > > + > > + return 0; > > +} > > + > > [...] > > > + > > +static void cmdq_task_exec(struct cmdq_pkt *pkt, struct cmdq_thread > > *thread) > > +{ > > + struct cmdq *cmdq; > > + struct cmdq_task *task; > > + unsigned long curr_pa, end_pa; > > + > > + cmdq = dev_get_drvdata(thread->chan->mbox->dev); > > + > > + /* Client should not flush new tasks if suspended. */ > > + WARN_ON(cmdq->suspended); > > + > > + task = kzalloc(sizeof(*task), GFP_ATOMIC); > > + task->cmdq = cmdq; > > + INIT_LIST_HEAD(>list_entry); > > + task->pa_base = pkt->pa_base; > > + task->thread = thread; > > + task->pkt = pkt; > > + > > + if (list_empty(>task_busy_list)) { > > + WARN_ON(clk_enable(cmdq->clock) < 0); > > + WARN_ON(cmdq_thread_reset(cmdq, thread) < 0); > > + > > + writel(task->pa_base, thread->base + CMDQ_THR_CURR_ADDR); > > + writel(task->pa_base + pkt->cmd_buf_size, > > + thread->base + CMDQ_THR_END_ADDR); > > + writel(thread->priority, thread->base + CMDQ_THR_PRIORITY); > > + writel(CMDQ_THR_IRQ_EN, thread->base + CMDQ_THR_IRQ_ENABLE); > > + writel(CMDQ_THR_ENABLED, thread->base + CMDQ_THR_ENABLE_TASK); > > + > > + if (thread->timeout_ms != CMDQ_NO_TIMEOUT) > > + mod_timer(>timeout, > > + jiffies + msecs_to_jiffies(thread->timeout_ms)); > > I think the timeout processing should be done by client driver. The > total time to execute a command buffer does not depend on GCE HW speed > because the WFE (wait for event) command would wait for client HW event, > so the total time depend on how long a client HW send this event to GCE > and the timeout processing should be client driver's job. Each client > may have different timeout processing mechanism, for example, if display > could dynamic change panel frame rate between 120Hz and 60Hz, and the > timeout time is 2 frame, so it may dynamically change timeout time > between 17ms and 33ms. Another reason is that display have interrupt > every vblank, and it could check timeout in that interrupt, so the timer > in cmdq driver looks redundant. Because each client would define its own > timeout processing mechanism, so it's not wise to put timeout processing > in cmdq driver. The client drivers' owners strongly hope to keep th
Re: [PATCH v22 4/4] soc: mediatek: Add Mediatek CMDQ helper
On Fri, 2018-06-29 at 17:22 +0800, CK Hu wrote: > Hi, Houlong: > > On Fri, 2018-06-29 at 07:32 +0800, houlong wei wrote: > > On Thu, 2018-06-28 at 18:41 +0800, CK Hu wrote: > > > Hi, Houlong: > > > > > > Some inline comment. > > > > > > On Wed, 2018-06-27 at 19:16 +0800, Houlong Wei wrote: > > > > Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. > > > > > > > > Signed-off-by: Houlong Wei > > > > Signed-off-by: HS Liao > > > > --- > > > > drivers/soc/mediatek/Kconfig | 12 ++ > > > > drivers/soc/mediatek/Makefile |1 + > > > > drivers/soc/mediatek/mtk-cmdq-helper.c | 258 > > > > > > > > include/linux/soc/mediatek/mtk-cmdq.h | 132 > > > > 4 files changed, 403 insertions(+) > > > > create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c > > > > create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h > > > > > > > > diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig > > > > index a7d0667..17bd759 100644 > > > > --- a/drivers/soc/mediatek/Kconfig > > > > +++ b/drivers/soc/mediatek/Kconfig > > > > @@ -4,6 +4,18 @@ > > > > menu "MediaTek SoC drivers" > > > > depends on ARCH_MEDIATEK || COMPILE_TEST > > > > > > > > > [...] > > > > > + > > > > +static int cmdq_pkt_finalize(struct cmdq_pkt *pkt) > > > > +{ > > > > + int err; > > > > + > > > > + if (cmdq_pkt_is_finalized(pkt)) > > > > + return 0; > > > > + > > > > + /* insert EOC and generate IRQ for each command iteration */ > > > > + err = cmdq_pkt_append_command(pkt, CMDQ_CODE_EOC, 0, > > > > CMDQ_EOC_IRQ_EN); > > > > + if (err < 0) > > > > + return err; > > > > + > > > > + /* JUMP to end */ > > > > + err = cmdq_pkt_append_command(pkt, CMDQ_CODE_JUMP, 0, > > > > CMDQ_JUMP_PASS); > > > > + if (err < 0) > > > > + return err; > > > > + > > > > + return 0; > > > > +} > > > > + > > > > +int cmdq_pkt_flush_async(struct cmdq_client *client, struct cmdq_pkt > > > > *pkt, > > > > +cmdq_async_flush_cb cb, void *data) > > > > +{ > > > > + int err; > > > > + struct device *dev; > > > > + dma_addr_t dma_addr; > > > > + > > > > + err = cmdq_pkt_finalize(pkt); > > > > + if (err < 0) > > > > + return err; > > > > + > > > > + dev = client->chan->mbox->dev; > > > > + dma_addr = dma_map_single(dev, pkt->va_base, pkt->cmd_buf_size, > > > > + DMA_TO_DEVICE); > > > > > > You map here, but I could not find unmap, so the unmap should be done in > > > client driver. I would prefer a symmetric map/unmap which means that > > > both map and unmap are done in client driver. I think you put map here > > > because you should map after finalize. > > > > The unmap is done before callback to client, in function > > cmdq_task_exec_done, mtk-cmdq-mailbox.c. > > You put unmap in mailbox controller, and map here (here would be mailbox > client), so this is not symmetric. If the code is asymmetric, it's easy > to cause bug and not easy to maintain. So I would like move both > map/unmap to client driver. > Since map/unmap is common code for client drivers, can we move unmap to CMDQ helper and do not put in client driver? > > > > > Therefore, export > > > cmdq_pkt_finalize() to client driver and let client do finalize, so > > > there is no finalize in flush function. This method have a benefit that > > > if client reuse command buffer, it need not to map/unmap frequently. > > > > If client reuse command buffer or cmdq_pkt(command queue packet), client > > will add new commands to the cmdq_pkt, so map/unmap are necessary for > > each cmdq_pkt flush. > > If the buffer size is 4K bytes, client driver could map the whole 4K at > initialization. Before it write new command, it call > dma_sync_single_for_cpu(), after it write new command, it call > dma_sync_single_for_dev
Re: [PATCH v22 4/4] soc: mediatek: Add Mediatek CMDQ helper
On Wed, 2018-07-04 at 10:39 +0800, CK Hu wrote: > Hi, Houlong: > > On Wed, 2018-07-04 at 08:47 +0800, houlong wei wrote: > > On Fri, 2018-06-29 at 17:22 +0800, CK Hu wrote: > > > Hi, Houlong: > > > > > > On Fri, 2018-06-29 at 07:32 +0800, houlong wei wrote: > > > > On Thu, 2018-06-28 at 18:41 +0800, CK Hu wrote: > > > > > Hi, Houlong: > > > > > > > > > > Some inline comment. > > > > > > > > > > On Wed, 2018-06-27 at 19:16 +0800, Houlong Wei wrote: > > > > > > Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op > > > > > > code. > > > > > > > > > > > > Signed-off-by: Houlong Wei > > > > > > Signed-off-by: HS Liao > > > > > > --- > > > > > > drivers/soc/mediatek/Kconfig | 12 ++ > > > > > > drivers/soc/mediatek/Makefile |1 + > > > > > > drivers/soc/mediatek/mtk-cmdq-helper.c | 258 > > > > > > > > > > > > include/linux/soc/mediatek/mtk-cmdq.h | 132 > > > > > > 4 files changed, 403 insertions(+) > > > > > > create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c > > > > > > create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h > > > > > > > > > > > > diff --git a/drivers/soc/mediatek/Kconfig > > > > > > b/drivers/soc/mediatek/Kconfig > > > > > > index a7d0667..17bd759 100644 > > > > > > --- a/drivers/soc/mediatek/Kconfig > > > > > > +++ b/drivers/soc/mediatek/Kconfig > > > > > > @@ -4,6 +4,18 @@ > > > > > > menu "MediaTek SoC drivers" > > > > > > depends on ARCH_MEDIATEK || COMPILE_TEST > > > > > > > > > > > > > > > > > [...] > > > > > > > > > + > > > > > > +static int cmdq_pkt_finalize(struct cmdq_pkt *pkt) > > > > > > +{ > > > > > > + int err; > > > > > > + > > > > > > + if (cmdq_pkt_is_finalized(pkt)) > > > > > > + return 0; > > > > > > + > > > > > > + /* insert EOC and generate IRQ for each command iteration */ > > > > > > + err = cmdq_pkt_append_command(pkt, CMDQ_CODE_EOC, 0, > > > > > > CMDQ_EOC_IRQ_EN); > > > > > > + if (err < 0) > > > > > > + return err; > > > > > > + > > > > > > + /* JUMP to end */ > > > > > > + err = cmdq_pkt_append_command(pkt, CMDQ_CODE_JUMP, 0, > > > > > > CMDQ_JUMP_PASS); > > > > > > + if (err < 0) > > > > > > + return err; > > > > > > + > > > > > > + return 0; > > > > > > +} > > > > > > + > > > > > > +int cmdq_pkt_flush_async(struct cmdq_client *client, struct > > > > > > cmdq_pkt *pkt, > > > > > > +cmdq_async_flush_cb cb, void *data) > > > > > > +{ > > > > > > + int err; > > > > > > + struct device *dev; > > > > > > + dma_addr_t dma_addr; > > > > > > + > > > > > > + err = cmdq_pkt_finalize(pkt); > > > > > > + if (err < 0) > > > > > > + return err; > > > > > > + > > > > > > + dev = client->chan->mbox->dev; > > > > > > + dma_addr = dma_map_single(dev, pkt->va_base, pkt->cmd_buf_size, > > > > > > + DMA_TO_DEVICE); > > > > > > > > > > You map here, but I could not find unmap, so the unmap should be done > > > > > in > > > > > client driver. I would prefer a symmetric map/unmap which means that > > > > > both map and unmap are done in client driver. I think you put map here > > > > > because you should map after finalize. > > > > > > > > The unmap is done before callback to client, in function > > > > cmdq_task_exec_done, mtk-cmdq-mailbox.c. > > > > > > You put unmap in mailbox controller, and map here (here would be mailbox > > > client), so this is not symmetric. If the code is asymmetric, it's easy >
Re: [PATCH v22 2/4] mailbox: mediatek: Add Mediatek CMDQ driver
On Wed, 2018-07-04 at 17:03 +0800, CK Hu wrote: > Hi, Houlong: > > On Wed, 2018-07-04 at 08:10 +0800, houlong wei wrote: > > On Fri, 2018-06-29 at 15:08 +0800, CK Hu wrote: > > > Hi, Houlong: > > > > > > Some inline comment. > > > > > > On Wed, 2018-06-27 at 19:16 +0800, Houlong Wei wrote: > > > > This patch is first version of Mediatek Command Queue(CMDQ) driver. The > > > > CMDQ is used to help write registers with critical time limitation, > > > > such as updating display configuration during the vblank. It controls > > > > Global Command Engine (GCE) hardware to achieve this requirement. > > > > Currently, CMDQ only supports display related hardwares, but we expect > > > > it can be extended to other hardwares for future requirements. > > > > > > > > Signed-off-by: Houlong Wei > > > > Signed-off-by: HS Liao > > > > Signed-off-by: CK Hu > > > > --- > > > > drivers/mailbox/Kconfig | 10 + > > > > drivers/mailbox/Makefile |2 + > > > > drivers/mailbox/mtk-cmdq-mailbox.c | 634 > > > > ++ > > > > include/linux/mailbox/mtk-cmdq-mailbox.h | 70 > > > > 4 files changed, 716 insertions(+) > > > > create mode 100644 drivers/mailbox/mtk-cmdq-mailbox.c > > > > create mode 100644 include/linux/mailbox/mtk-cmdq-mailbox.h > > > > > > > > > > [...] > > > > > > > + > > > > +static int cmdq_thread_reset(struct cmdq *cmdq, struct cmdq_thread > > > > *thread) > > > > +{ > > > > + u32 warm_reset; > > > > + > > > > + writel(CMDQ_THR_DO_WARM_RESET, thread->base + > > > > CMDQ_THR_WARM_RESET); > > > > + if (readl_poll_timeout_atomic(thread->base + > > > > CMDQ_THR_WARM_RESET, > > > > + warm_reset, !(warm_reset & > > > > CMDQ_THR_DO_WARM_RESET), > > > > + 0, 10)) { > > > > + dev_err(cmdq->mbox.dev, "reset GCE thread 0x%x > > > > failed\n", > > > > + (u32)(thread->base - cmdq->base)); > > > > + return -EFAULT; > > > > + } > > > > + writel(CMDQ_THR_ACTIVE_SLOT_CYCLES, cmdq->base + > > > > CMDQ_THR_SLOT_CYCLES); > > > > > > The CMDQ_THR_SLOT_CYCLES looks like not relevant to reset. Maybe you > > > just need to set this value when startup. > > > > Will move configuration of CMDQ_THR_SLOT_CYCLES to cmdq_xlate() where is > > startup of a GCE thread. > > Since cmdq_xlate() is called when a client requests a channel, it may be called more than once. Will move it to cmdq_probe(). > > > > > > > + > > > > + return 0; > > > > +} > > > > + > > > > > > [...] > > > > > > > + > > > > +static void cmdq_task_exec(struct cmdq_pkt *pkt, struct cmdq_thread > > > > *thread) > > > > +{ > > > > + struct cmdq *cmdq; > > > > + struct cmdq_task *task; > > > > + unsigned long curr_pa, end_pa; > > > > + > > > > + cmdq = dev_get_drvdata(thread->chan->mbox->dev); > > > > + > > > > + /* Client should not flush new tasks if suspended. */ > > > > + WARN_ON(cmdq->suspended); > > > > + > > > > + task = kzalloc(sizeof(*task), GFP_ATOMIC); > > > > + task->cmdq = cmdq; > > > > + INIT_LIST_HEAD(>list_entry); > > > > + task->pa_base = pkt->pa_base; > > > > + task->thread = thread; > > > > + task->pkt = pkt; > > > > + > > > > + if (list_empty(>task_busy_list)) { > > > > + WARN_ON(clk_enable(cmdq->clock) < 0); > > > > + WARN_ON(cmdq_thread_reset(cmdq, thread) < 0); > > > > + > > > > + writel(task->pa_base, thread->base + > > > > CMDQ_THR_CURR_ADDR); > > > > + writel(task->pa_base + pkt->cmd_buf_size, > > > > + thread->base + CMDQ_THR_END_ADDR); > > > > + writel(thread->priority, thread->base + > > > > CMDQ_THR_PRIORITY);
Re: [PATCH v22 1/4] dt-bindings: soc: Add documentation for the MediaTek GCE unit
On Fri, 2018-07-06 at 04:08 +0800, Rob Herring wrote: > On Tue, Jul 3, 2018 at 5:39 PM houlong wei wrote: > > > > On Tue, 2018-07-03 at 10:30 +0800, Rob Herring wrote: > > > On Wed, Jun 27, 2018 at 07:16:09PM +0800, Houlong Wei wrote: > > > > This adds documentation for the MediaTek Global Command Engine (GCE) > > > > unit > > > > found in MT8173 SoCs. > > > > > > > > Signed-off-by: Houlong Wei > > > > Signed-off-by: HS Liao > > > > --- > > > > Hi Rob, > > > > I don't add your ACK in this version since the dt-binding description > > > > has been changed. Thanks. > > > > --- > > > > .../devicetree/bindings/mailbox/mtk-gce.txt| 65 > > > > > > > > include/dt-bindings/gce/mt8173-gce.h | 48 > > > > +++ > > > > 2 files changed, 113 insertions(+) > > > > create mode 100644 > > > > Documentation/devicetree/bindings/mailbox/mtk-gce.txt > > > > create mode 100644 include/dt-bindings/gce/mt8173-gce.h > > > > > > > > diff --git a/Documentation/devicetree/bindings/mailbox/mtk-gce.txt > > > > b/Documentation/devicetree/bindings/mailbox/mtk-gce.txt > > > > new file mode 100644 > > > > index 000..26f65a4 > > > > --- /dev/null > > > > +++ b/Documentation/devicetree/bindings/mailbox/mtk-gce.txt > > > > @@ -0,0 +1,65 @@ > > > > +MediaTek GCE > > > > +=== > > > > + > > > > +The Global Command Engine (GCE) is used to help read/write registers > > > > with > > > > +critical time limitation, such as updating display configuration > > > > during the > > > > +vblank. The GCE can be used to implement the Command Queue (CMDQ) > > > > driver. > > > > + > > > > +CMDQ driver uses mailbox framework for communication. Please refer to > > > > +mailbox.txt for generic information about mailbox device-tree bindings. > > > > + > > > > +Required properties: > > > > +- compatible: Must be "mediatek,mt8173-gce" > > > > +- reg: Address range of the GCE unit > > > > +- interrupts: The interrupt signal from the GCE block > > > > +- clock: Clocks according to the common clock binding > > > > +- clock-names: Must be "gce" to stand for GCE clock > > > > +- thread-num: Maximum threads count of GCE. > > > > > > mediatek,thread-num > > > > > > Is this needed for anything other than error checking the thread id in > > > the mbox cells? if that's it, then drop it. > > > > > > > 'thread-num' is used to configure the GCE thread number, which is the > > channel number of gce mailbox. This property is read in > > cmdq_probe()/mtk-cmdq-mailbox.c and a mailbox's channel array is > > allocated according to the number. > > Since the thread number may be different on different SoC, we wish it > > could be configured in device tree. > > You should have different compatible strings for different SoCs and > can imply the number of threads from that. > Thanks. Will remove 'thread-num' form device tree and put it in match table of cmdq dirver. > Or if the number of threads doesn't vary greatly, just allocate the > max # of channels. Or allocate the per thread data when a thread is > actually in use. > > > > > > > +- #mbox-cells: Should be 4. > > > > + < channel timeout priority atomic_exec> > > > > + phandle: Label name of a gce node. > > > > + channel: Channel of mailbox. Be equal to the thread id of GCE. > > > > + timeout: Maximum time of software waiting GCE processing done, in > > > > unit > > > > + of millisecond. > > > > + priority: Priority of GCE thread. > > > > + atomic_exec: GCE processing continuous packets of commands in atomic > > > > + way. > > > > + > > > > +Required properties for a client device: > > > > +- mboxes: Client use mailbox to communicate with GCE, it should have > > > > this > > > > + property and list of phandle, mailbox specifiers. > > > > +- gce-subsys: Specify the sub-system id which is corresponding to the > > > > register > > > > + address. > > > > > > What is this for? > > > > You mean the new added property 'gce-subsys'? > > I
Re: [PATCH v26 2/2] soc: mediatek: Add Mediatek CMDQ helper
On Mon, 2018-10-08 at 11:43 +0800, Houlong Wei wrote: > Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code. > > Signed-off-by: Houlong Wei > Signed-off-by: HS Liao > --- > drivers/soc/mediatek/Kconfig | 12 ++ > drivers/soc/mediatek/Makefile |1 + > drivers/soc/mediatek/mtk-cmdq-helper.c | 292 > > include/linux/soc/mediatek/mtk-cmdq.h | 133 +++ > 4 files changed, 438 insertions(+) > create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c > create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h > > diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig > index a7d0667..17bd759 100644 > --- a/drivers/soc/mediatek/Kconfig > +++ b/drivers/soc/mediatek/Kconfig > @@ -4,6 +4,18 @@ > menu "MediaTek SoC drivers" > depends on ARCH_MEDIATEK || COMPILE_TEST > > +config MTK_CMDQ > +tristate "MediaTek CMDQ Support" > +depends on ARCH_MEDIATEK || COMPILE_TEST > +select MAILBOX > +select MTK_CMDQ_MBOX > +select MTK_INFRACFG > +help > + Say yes here to add support for the MediaTek Command Queue (CMDQ) > + driver. The CMDQ is used to help read/write registers with critical > + time limitation, such as updating display configuration during the > + vblank. > + > config MTK_INFRACFG > bool "MediaTek INFRACFG Support" > select REGMAP > diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile > index 12998b0..64ce5ee 100644 > --- a/drivers/soc/mediatek/Makefile > +++ b/drivers/soc/mediatek/Makefile > @@ -1,3 +1,4 @@ > +obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o > obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o > obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o > obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o > diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c > b/drivers/soc/mediatek/mtk-cmdq-helper.c > new file mode 100644 > index 000..45aa0cf > --- /dev/null > +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c > @@ -0,0 +1,292 @@ > +// SPDX-License-Identifier: GPL-2.0 > +// > +// Copyright (c) 2018 MediaTek Inc. > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define CMDQ_ARG_A_WRITE_MASK0x > +#define CMDQ_WRITE_ENABLE_MASKBIT(0) > +#define CMDQ_EOC_IRQ_ENBIT(0) > +#define CMDQ_EOC_CMD((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \ > +<< 32 | CMDQ_EOC_IRQ_EN) > + > +static void cmdq_client_timeout(struct timer_list *t) > +{ > +struct cmdq_client *client = from_timer(client, t, timer); > + > +dev_err(client->client.dev, "cmdq timeout!\n"); > +} > + > +struct cmdq_client *cmdq_mbox_create(struct device *dev, int index, u32 > timeout) > +{ > +struct cmdq_client *client; > + > +client = kzalloc(sizeof(*client), GFP_KERNEL); > +if (!client) > +return (struct cmdq_client *)-ENOMEM; > + > +client->timeout_ms = timeout; > +if (timeout != CMDQ_NO_TIMEOUT) { > +spin_lock_init(>lock); > +timer_setup(>timer, cmdq_client_timeout, 0); > +} > +client->pkt_cnt = 0; > +client->client.dev = dev; > +client->client.tx_block = false; > +client->chan = mbox_request_channel(>client, index); > + > +if (IS_ERR(client->chan)) { > +long err; > + > +dev_err(dev, "failed to request channel\n"); > +err = PTR_ERR(client->chan); > +kfree(client); > + > +return ERR_PTR(err); > +} > + > +return client; > +} > +EXPORT_SYMBOL(cmdq_mbox_create); > + > +void cmdq_mbox_destroy(struct cmdq_client *client) > +{ > +if (client->timeout_ms != CMDQ_NO_TIMEOUT) { > +spin_lock(>lock); > +del_timer_sync(>timer); > +spin_unlock(>lock); > +} > +mbox_free_channel(client->chan); > +kfree(client); > +} > +EXPORT_SYMBOL(cmdq_mbox_destroy); > + > +struct cmdq_pkt *cmdq_pkt_create(struct cmdq_client *client, size_t size) > +{ > +struct cmdq_pkt *pkt; > +struct device *dev; > +dma_addr_t dma_addr; > + > +pkt = kzalloc(sizeof(*pkt), GFP_KERNEL); > +if (!pkt) > +return ERR_PTR(-ENOMEM); > +pkt->va_base = kzalloc(size, GFP_KERNEL); > +if (!pkt->va_base) { > +kfree(pkt); > +return ERR_PTR(-ENOMEM); > +} > +pkt->buf_size = size; > +pkt->cl = (void *)client; > + > +dev = client->chan->mbox->dev; > +dma_addr = dma_map_single(dev, pkt->va_base, pkt->buf_size, > + DMA_TO_DEVICE); > +if (dma_mapping_error(dev, dma_addr)) { > +dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size); > +kfree(pkt->va_base); > +kfree(pkt); > +return ERR_PTR(-ENOMEM); > +} > + > +pkt->pa_base = dma_addr; > + > +return pk