Message ID | 1592745731-14614-1-git-send-email-dennis-yc.hsieh@mediatek.com |
---|---|
Headers | show |
Series | support gce on mt6779 platform | expand |
On Sun, 2020-06-21 at 21:22 +0800, Dennis YC Hsieh wrote: > Some gce hardware shift pc and end address in register to support > large dram addressing. > Implement gce address shift when write or read pc and end register. > And add shift bit in platform definition. > > Signed-off-by: Dennis YC Hsieh <dennis-yc.hsieh@mediatek.com> > --- > drivers/mailbox/mtk-cmdq-mailbox.c | 61 ++++++++++++++++++++++-------- > include/linux/mailbox/mtk-cmdq-mailbox.h | 2 + > 2 files changed, 48 insertions(+), 15 deletions(-) > > diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c > index 9a6ce9f5a7db..4dbee9258127 100644 > --- a/drivers/mailbox/mtk-cmdq-mailbox.c > +++ b/drivers/mailbox/mtk-cmdq-mailbox.c > @@ -76,8 +76,22 @@ struct cmdq { > struct cmdq_thread *thread; > struct clk *clock; > bool suspended; > + u8 shift_pa; > }; > > +struct gce_plat { > + u32 thread_nr; > + u8 shift; > +}; > + > +u8 cmdq_mbox_shift(struct mbox_chan *chan) How about rename this function as cmdq_get_shift_pa()? Bibby > +{ > + struct cmdq *cmdq = container_of(chan->mbox, struct cmdq, mbox); > + > + return cmdq->shift_pa; > +} > +EXPORT_SYMBOL(cmdq_mbox_shift); > + > static int cmdq_thread_suspend(struct cmdq *cmdq, struct cmdq_thread *thread) > { > u32 status; > @@ -183,7 +197,7 @@ static void cmdq_task_remove_wfe(struct cmdq_task *task) > for (i = 0; i < CMDQ_NUM_CMD(task->pkt); i++) > if (cmdq_command_is_wfe(base[i])) > base[i] = (u64)CMDQ_JUMP_BY_OFFSET << 32 | > - CMDQ_JUMP_PASS; > + CMDQ_JUMP_PASS >> task->cmdq->shift_pa; > dma_sync_single_for_device(dev, task->pa_base, task->pkt->cmd_buf_size, > DMA_TO_DEVICE); > } > @@ -221,13 +235,15 @@ static void cmdq_task_handle_error(struct cmdq_task *task) > { > struct cmdq_thread *thread = task->thread; > struct cmdq_task *next_task; > + struct cmdq *cmdq = task->cmdq; > > - dev_err(task->cmdq->mbox.dev, "task 0x%p error\n", task); > - WARN_ON(cmdq_thread_suspend(task->cmdq, thread) < 0); > + dev_err(cmdq->mbox.dev, "task 0x%p error\n", task); > + WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0); > next_task = list_first_entry_or_null(&thread->task_busy_list, > struct cmdq_task, list_entry); > if (next_task) > - writel(next_task->pa_base, thread->base + CMDQ_THR_CURR_ADDR); > + writel(next_task->pa_base >> cmdq->shift_pa, > + thread->base + CMDQ_THR_CURR_ADDR); > cmdq_thread_resume(thread); > } > > @@ -257,7 +273,7 @@ static void cmdq_thread_irq_handler(struct cmdq *cmdq, > else > return; > > - curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR); > + curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR) << cmdq->shift_pa; > > list_for_each_entry_safe(task, tmp, &thread->task_busy_list, > list_entry) { > @@ -373,16 +389,20 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data) > 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, > + writel(task->pa_base >> cmdq->shift_pa, > + thread->base + CMDQ_THR_CURR_ADDR); > + writel((task->pa_base + pkt->cmd_buf_size) >> cmdq->shift_pa, > 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); > } 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); > + curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR) << > + cmdq->shift_pa; > + end_pa = readl(thread->base + CMDQ_THR_END_ADDR) << > + cmdq->shift_pa; > > /* > * Atomic execution should remove the following wfe, i.e. only > @@ -395,7 +415,7 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data) > cmdq_thread_wait_end(thread, end_pa); > WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0); > /* set to this task directly */ > - writel(task->pa_base, > + writel(task->pa_base >> cmdq->shift_pa, > thread->base + CMDQ_THR_CURR_ADDR); > } else { > cmdq_task_insert_into_thread(task); > @@ -407,14 +427,14 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data) > if (curr_pa == end_pa - CMDQ_INST_SIZE || > curr_pa == end_pa) { > /* set to this task directly */ > - writel(task->pa_base, > + writel(task->pa_base >> cmdq->shift_pa, > thread->base + CMDQ_THR_CURR_ADDR); > } else { > cmdq_task_insert_into_thread(task); > smp_mb(); /* modify jump before enable thread */ > } > } > - writel(task->pa_base + pkt->cmd_buf_size, > + writel((task->pa_base + pkt->cmd_buf_size) >> cmdq->shift_pa, > thread->base + CMDQ_THR_END_ADDR); > cmdq_thread_resume(thread); > } > @@ -461,6 +481,7 @@ static int cmdq_probe(struct platform_device *pdev) > struct resource *res; > struct cmdq *cmdq; > int err, i; > + struct gce_plat *plat_data; > > cmdq = devm_kzalloc(dev, sizeof(*cmdq), GFP_KERNEL); > if (!cmdq) > @@ -479,7 +500,14 @@ static int cmdq_probe(struct platform_device *pdev) > return -EINVAL; > } > > - cmdq->thread_nr = (u32)(unsigned long)of_device_get_match_data(dev); > + plat_data = (struct gce_plat *)of_device_get_match_data(dev); > + if (!plat_data) { > + dev_err(dev, "failed to get match data\n"); > + return -EINVAL; > + } > + > + cmdq->thread_nr = plat_data->thread_nr; > + cmdq->shift_pa = plat_data->shift; > cmdq->irq_mask = GENMASK(cmdq->thread_nr - 1, 0); > err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler, IRQF_SHARED, > "mtk_cmdq", cmdq); > @@ -542,9 +570,12 @@ static int cmdq_probe(struct platform_device *pdev) > .resume = cmdq_resume, > }; > > +static const struct gce_plat gce_plat_v2 = {.thread_nr = 16}; > +static const struct gce_plat gce_plat_v3 = {.thread_nr = 24}; > + > static const struct of_device_id cmdq_of_ids[] = { > - {.compatible = "mediatek,mt8173-gce", .data = (void *)16}, > - {.compatible = "mediatek,mt8183-gce", .data = (void *)24}, > + {.compatible = "mediatek,mt8173-gce", .data = (void *)&gce_plat_v2}, > + {.compatible = "mediatek,mt8183-gce", .data = (void *)&gce_plat_v3}, > {} > }; > > diff --git a/include/linux/mailbox/mtk-cmdq-mailbox.h b/include/linux/mailbox/mtk-cmdq-mailbox.h > index a4dc45fbec0a..dfe5b2eb85cc 100644 > --- a/include/linux/mailbox/mtk-cmdq-mailbox.h > +++ b/include/linux/mailbox/mtk-cmdq-mailbox.h > @@ -88,4 +88,6 @@ struct cmdq_pkt { > void *cl; > }; > > +u8 cmdq_mbox_shift(struct mbox_chan *chan); > + > #endif /* __MTK_CMDQ_MAILBOX_H__ */
Reviewed-by: Bibby Hsieh <bibby.hsieh@mediatek.com> Thanks. On Sun, 2020-06-21 at 21:22 +0800, Dennis YC Hsieh wrote: > Add gce v4 hardware support with different thread number and shift. > > Signed-off-by: Dennis YC Hsieh <dennis-yc.hsieh@mediatek.com> > Reviewed-by: CK Hu <ck.hu@mediatek.com> > Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com> > --- > drivers/mailbox/mtk-cmdq-mailbox.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c > index 4dbee9258127..9994ac9426d6 100644 > --- a/drivers/mailbox/mtk-cmdq-mailbox.c > +++ b/drivers/mailbox/mtk-cmdq-mailbox.c > @@ -572,10 +572,12 @@ static int cmdq_probe(struct platform_device *pdev) > > static const struct gce_plat gce_plat_v2 = {.thread_nr = 16}; > static const struct gce_plat gce_plat_v3 = {.thread_nr = 24}; > +static const struct gce_plat gce_plat_v4 = {.thread_nr = 24, .shift = 3}; > > static const struct of_device_id cmdq_of_ids[] = { > {.compatible = "mediatek,mt8173-gce", .data = (void *)&gce_plat_v2}, > {.compatible = "mediatek,mt8183-gce", .data = (void *)&gce_plat_v3}, > + {.compatible = "mediatek,mt6779-gce", .data = (void *)&gce_plat_v4}, > {} > }; >
Reviewed-by: Bibby Hsieh <bibby.hsieh@mediatek.com> Thanks. On Sun, 2020-06-21 at 21:22 +0800, Dennis YC Hsieh wrote: > Do success callback in channel when shutdown. For those task not finish, > callback with error code thus client has chance to cleanup or reset. > > Signed-off-by: Dennis YC Hsieh <dennis-yc.hsieh@mediatek.com> > Reviewed-by: CK Hu <ck.hu@mediatek.com> > --- > drivers/mailbox/mtk-cmdq-mailbox.c | 38 ++++++++++++++++++++++++++++++++++++ > 1 file changed, 38 insertions(+) > > diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c > index 9994ac9426d6..b56d340c8982 100644 > --- a/drivers/mailbox/mtk-cmdq-mailbox.c > +++ b/drivers/mailbox/mtk-cmdq-mailbox.c > @@ -387,6 +387,12 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data) > > if (list_empty(&thread->task_busy_list)) { > WARN_ON(clk_enable(cmdq->clock) < 0); > + /* > + * The thread reset will clear thread related register to 0, > + * including pc, end, priority, irq, suspend and enable. Thus > + * set CMDQ_THR_ENABLED to CMDQ_THR_ENABLE_TASK will enable > + * thread and make it running. > + */ > WARN_ON(cmdq_thread_reset(cmdq, thread) < 0); > > writel(task->pa_base >> cmdq->shift_pa, > @@ -450,6 +456,38 @@ static int cmdq_mbox_startup(struct mbox_chan *chan) > > static void cmdq_mbox_shutdown(struct mbox_chan *chan) > { > + struct cmdq_thread *thread = (struct cmdq_thread *)chan->con_priv; > + struct cmdq *cmdq = dev_get_drvdata(chan->mbox->dev); > + struct cmdq_task *task, *tmp; > + unsigned long flags; > + > + spin_lock_irqsave(&thread->chan->lock, flags); > + if (list_empty(&thread->task_busy_list)) > + goto done; > + > + WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0); > + > + /* make sure executed tasks have success callback */ > + cmdq_thread_irq_handler(cmdq, thread); > + if (list_empty(&thread->task_busy_list)) > + goto done; > + > + list_for_each_entry_safe(task, tmp, &thread->task_busy_list, > + list_entry) { > + cmdq_task_exec_done(task, CMDQ_CB_ERROR); > + kfree(task); > + } > + > + cmdq_thread_disable(cmdq, thread); > + clk_disable(cmdq->clock); > +done: > + /* > + * The thread->task_busy_list empty means thread already disable. The > + * cmdq_mbox_send_data() always reset thread which clear disable and > + * suspend statue when first pkt send to channel, so there is no need > + * to do any operation here, only unlock and leave. > + */ > + spin_unlock_irqrestore(&thread->chan->lock, flags); > } > > static const struct mbox_chan_ops cmdq_mbox_chan_ops = {
Hi Bibby, Thanks for your comment. On Mon, 2020-06-22 at 10:33 +0800, Bibby Hsieh wrote: > On Sun, 2020-06-21 at 21:22 +0800, Dennis YC Hsieh wrote: > > Some gce hardware shift pc and end address in register to support > > large dram addressing. > > Implement gce address shift when write or read pc and end register. > > And add shift bit in platform definition. > > > > Signed-off-by: Dennis YC Hsieh <dennis-yc.hsieh@mediatek.com> > > --- > > drivers/mailbox/mtk-cmdq-mailbox.c | 61 ++++++++++++++++++++++-------- > > include/linux/mailbox/mtk-cmdq-mailbox.h | 2 + > > 2 files changed, 48 insertions(+), 15 deletions(-) > > > > diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c > > index 9a6ce9f5a7db..4dbee9258127 100644 > > --- a/drivers/mailbox/mtk-cmdq-mailbox.c > > +++ b/drivers/mailbox/mtk-cmdq-mailbox.c > > @@ -76,8 +76,22 @@ struct cmdq { > > struct cmdq_thread *thread; > > struct clk *clock; > > bool suspended; > > + u8 shift_pa; > > }; > > > > +struct gce_plat { > > + u32 thread_nr; > > + u8 shift; > > +}; > > + > > +u8 cmdq_mbox_shift(struct mbox_chan *chan) > > How about rename this function as cmdq_get_shift_pa()? ok, I'll rename it, thanks Regards, Dennis > > > Bibby > > > +{ > > + struct cmdq *cmdq = container_of(chan->mbox, struct cmdq, mbox); > > + > > + return cmdq->shift_pa; > > +} > > +EXPORT_SYMBOL(cmdq_mbox_shift); > > + > > static int cmdq_thread_suspend(struct cmdq *cmdq, struct cmdq_thread *thread) > > { > > u32 status; > > @@ -183,7 +197,7 @@ static void cmdq_task_remove_wfe(struct cmdq_task *task) > > for (i = 0; i < CMDQ_NUM_CMD(task->pkt); i++) > > if (cmdq_command_is_wfe(base[i])) > > base[i] = (u64)CMDQ_JUMP_BY_OFFSET << 32 | > > - CMDQ_JUMP_PASS; > > + CMDQ_JUMP_PASS >> task->cmdq->shift_pa; > > dma_sync_single_for_device(dev, task->pa_base, task->pkt->cmd_buf_size, > > DMA_TO_DEVICE); > > } > > @@ -221,13 +235,15 @@ static void cmdq_task_handle_error(struct cmdq_task *task) > > { > > struct cmdq_thread *thread = task->thread; > > struct cmdq_task *next_task; > > + struct cmdq *cmdq = task->cmdq; > > > > - dev_err(task->cmdq->mbox.dev, "task 0x%p error\n", task); > > - WARN_ON(cmdq_thread_suspend(task->cmdq, thread) < 0); > > + dev_err(cmdq->mbox.dev, "task 0x%p error\n", task); > > + WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0); > > next_task = list_first_entry_or_null(&thread->task_busy_list, > > struct cmdq_task, list_entry); > > if (next_task) > > - writel(next_task->pa_base, thread->base + CMDQ_THR_CURR_ADDR); > > + writel(next_task->pa_base >> cmdq->shift_pa, > > + thread->base + CMDQ_THR_CURR_ADDR); > > cmdq_thread_resume(thread); > > } > > > > @@ -257,7 +273,7 @@ static void cmdq_thread_irq_handler(struct cmdq *cmdq, > > else > > return; > > > > - curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR); > > + curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR) << cmdq->shift_pa; > > > > list_for_each_entry_safe(task, tmp, &thread->task_busy_list, > > list_entry) { > > @@ -373,16 +389,20 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data) > > 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, > > + writel(task->pa_base >> cmdq->shift_pa, > > + thread->base + CMDQ_THR_CURR_ADDR); > > + writel((task->pa_base + pkt->cmd_buf_size) >> cmdq->shift_pa, > > 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); > > } 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); > > + curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR) << > > + cmdq->shift_pa; > > + end_pa = readl(thread->base + CMDQ_THR_END_ADDR) << > > + cmdq->shift_pa; > > > > /* > > * Atomic execution should remove the following wfe, i.e. only > > @@ -395,7 +415,7 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data) > > cmdq_thread_wait_end(thread, end_pa); > > WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0); > > /* set to this task directly */ > > - writel(task->pa_base, > > + writel(task->pa_base >> cmdq->shift_pa, > > thread->base + CMDQ_THR_CURR_ADDR); > > } else { > > cmdq_task_insert_into_thread(task); > > @@ -407,14 +427,14 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data) > > if (curr_pa == end_pa - CMDQ_INST_SIZE || > > curr_pa == end_pa) { > > /* set to this task directly */ > > - writel(task->pa_base, > > + writel(task->pa_base >> cmdq->shift_pa, > > thread->base + CMDQ_THR_CURR_ADDR); > > } else { > > cmdq_task_insert_into_thread(task); > > smp_mb(); /* modify jump before enable thread */ > > } > > } > > - writel(task->pa_base + pkt->cmd_buf_size, > > + writel((task->pa_base + pkt->cmd_buf_size) >> cmdq->shift_pa, > > thread->base + CMDQ_THR_END_ADDR); > > cmdq_thread_resume(thread); > > } > > @@ -461,6 +481,7 @@ static int cmdq_probe(struct platform_device *pdev) > > struct resource *res; > > struct cmdq *cmdq; > > int err, i; > > + struct gce_plat *plat_data; > > > > cmdq = devm_kzalloc(dev, sizeof(*cmdq), GFP_KERNEL); > > if (!cmdq) > > @@ -479,7 +500,14 @@ static int cmdq_probe(struct platform_device *pdev) > > return -EINVAL; > > } > > > > - cmdq->thread_nr = (u32)(unsigned long)of_device_get_match_data(dev); > > + plat_data = (struct gce_plat *)of_device_get_match_data(dev); > > + if (!plat_data) { > > + dev_err(dev, "failed to get match data\n"); > > + return -EINVAL; > > + } > > + > > + cmdq->thread_nr = plat_data->thread_nr; > > + cmdq->shift_pa = plat_data->shift; > > cmdq->irq_mask = GENMASK(cmdq->thread_nr - 1, 0); > > err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler, IRQF_SHARED, > > "mtk_cmdq", cmdq); > > @@ -542,9 +570,12 @@ static int cmdq_probe(struct platform_device *pdev) > > .resume = cmdq_resume, > > }; > > > > +static const struct gce_plat gce_plat_v2 = {.thread_nr = 16}; > > +static const struct gce_plat gce_plat_v3 = {.thread_nr = 24}; > > + > > static const struct of_device_id cmdq_of_ids[] = { > > - {.compatible = "mediatek,mt8173-gce", .data = (void *)16}, > > - {.compatible = "mediatek,mt8183-gce", .data = (void *)24}, > > + {.compatible = "mediatek,mt8173-gce", .data = (void *)&gce_plat_v2}, > > + {.compatible = "mediatek,mt8183-gce", .data = (void *)&gce_plat_v3}, > > {} > > }; > > > > diff --git a/include/linux/mailbox/mtk-cmdq-mailbox.h b/include/linux/mailbox/mtk-cmdq-mailbox.h > > index a4dc45fbec0a..dfe5b2eb85cc 100644 > > --- a/include/linux/mailbox/mtk-cmdq-mailbox.h > > +++ b/include/linux/mailbox/mtk-cmdq-mailbox.h > > @@ -88,4 +88,6 @@ struct cmdq_pkt { > > void *cl; > > }; > > > > +u8 cmdq_mbox_shift(struct mbox_chan *chan); > > + > > #endif /* __MTK_CMDQ_MAILBOX_H__ */ > >