Skip to content

Commit

Permalink
mailbox: cmdq: add multi-gce clocks support for mt8195
Browse files Browse the repository at this point in the history
For the design of GCE hardware event signal transportation,
evnet rx will send the event signal to all GCE event merges
after receiving the event signal from the other hardware.

Because GCE event merges need to response to event rx, their
clocks must be enabled at that time.

To make sure all the gce clock is enabled while receiving the
hardware event, each cmdq mailbox should enable or disable
the others gce clk at the same time.

Signed-off-by: jason-jh.lin <jason-jh.lin@mediatek.com>
Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
  • Loading branch information
jason-jh.lin authored and Jassi Brar committed Sep 1, 2021
1 parent 8d4f5a9 commit 85dfdbf
Showing 1 changed file with 79 additions and 22 deletions.
101 changes: 79 additions & 22 deletions drivers/mailbox/mtk-cmdq-mailbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#define CMDQ_OP_CODE_MASK (0xff << CMDQ_OP_CODE_SHIFT)
#define CMDQ_NUM_CMD(t) (t->cmd_buf_size / CMDQ_INST_SIZE)
#define CMDQ_GCE_NUM_MAX (2)

#define CMDQ_CURR_IRQ_STATUS 0x10
#define CMDQ_SYNC_TOKEN_UPDATE 0x68
Expand Down Expand Up @@ -75,16 +76,18 @@ struct cmdq {
u32 thread_nr;
u32 irq_mask;
struct cmdq_thread *thread;
struct clk *clock;
struct clk_bulk_data clocks[CMDQ_GCE_NUM_MAX];
bool suspended;
u8 shift_pa;
bool control_by_sw;
u32 gce_num;
};

struct gce_plat {
u32 thread_nr;
u8 shift;
bool control_by_sw;
u32 gce_num;
};

u8 cmdq_get_shift_pa(struct mbox_chan *chan)
Expand Down Expand Up @@ -124,13 +127,13 @@ static void cmdq_init(struct cmdq *cmdq)
{
int i;

WARN_ON(clk_enable(cmdq->clock) < 0);
WARN_ON(clk_bulk_enable(cmdq->gce_num, cmdq->clocks));
if (cmdq->control_by_sw)
writel(0x7, cmdq->base + GCE_GCTL_VALUE);
writel(CMDQ_THR_ACTIVE_SLOT_CYCLES, cmdq->base + CMDQ_THR_SLOT_CYCLES);
for (i = 0; i <= CMDQ_MAX_EVENT; i++)
writel(i, cmdq->base + CMDQ_SYNC_TOKEN_UPDATE);
clk_disable(cmdq->clock);
clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
}

static int cmdq_thread_reset(struct cmdq *cmdq, struct cmdq_thread *thread)
Expand Down Expand Up @@ -269,7 +272,7 @@ static void cmdq_thread_irq_handler(struct cmdq *cmdq,

if (list_empty(&thread->task_busy_list)) {
cmdq_thread_disable(cmdq, thread);
clk_disable(cmdq->clock);
clk_bulk_disable(cmdq->gce_num, cmdq->clocks);
}
}

Expand Down Expand Up @@ -314,7 +317,7 @@ static int cmdq_suspend(struct device *dev)
if (task_running)
dev_warn(dev, "exist running task(s) in suspend\n");

clk_unprepare(cmdq->clock);
clk_bulk_unprepare(cmdq->gce_num, cmdq->clocks);

return 0;
}
Expand All @@ -323,7 +326,7 @@ static int cmdq_resume(struct device *dev)
{
struct cmdq *cmdq = dev_get_drvdata(dev);

WARN_ON(clk_prepare(cmdq->clock) < 0);
WARN_ON(clk_bulk_prepare(cmdq->gce_num, cmdq->clocks));
cmdq->suspended = false;
return 0;
}
Expand All @@ -332,8 +335,7 @@ static int cmdq_remove(struct platform_device *pdev)
{
struct cmdq *cmdq = platform_get_drvdata(pdev);

clk_unprepare(cmdq->clock);

clk_bulk_unprepare(cmdq->gce_num, cmdq->clocks);
return 0;
}

Expand All @@ -359,7 +361,8 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data)
task->pkt = pkt;

if (list_empty(&thread->task_busy_list)) {
WARN_ON(clk_enable(cmdq->clock) < 0);
WARN_ON(clk_bulk_enable(cmdq->gce_num, cmdq->clocks));

/*
* The thread reset will clear thread related register to 0,
* including pc, end, priority, irq, suspend and enable. Thus
Expand Down Expand Up @@ -431,7 +434,8 @@ static void cmdq_mbox_shutdown(struct mbox_chan *chan)
}

cmdq_thread_disable(cmdq, thread);
clk_disable(cmdq->clock);
clk_bulk_disable(cmdq->gce_num, cmdq->clocks);

done:
/*
* The thread->task_busy_list empty means thread already disable. The
Expand Down Expand Up @@ -476,7 +480,7 @@ static int cmdq_mbox_flush(struct mbox_chan *chan, unsigned long timeout)

cmdq_thread_resume(thread);
cmdq_thread_disable(cmdq, thread);
clk_disable(cmdq->clock);
clk_bulk_disable(cmdq->gce_num, cmdq->clocks);

out:
spin_unlock_irqrestore(&thread->chan->lock, flags);
Expand Down Expand Up @@ -525,6 +529,10 @@ static int cmdq_probe(struct platform_device *pdev)
struct cmdq *cmdq;
int err, i;
struct gce_plat *plat_data;
struct device_node *phandle = dev->of_node;
struct device_node *node;
int alias_id = 0;
char clk_name[4] = "gce";

cmdq = devm_kzalloc(dev, sizeof(*cmdq), GFP_KERNEL);
if (!cmdq)
Expand All @@ -548,6 +556,7 @@ static int cmdq_probe(struct platform_device *pdev)
cmdq->thread_nr = plat_data->thread_nr;
cmdq->shift_pa = plat_data->shift;
cmdq->control_by_sw = plat_data->control_by_sw;
cmdq->gce_num = plat_data->gce_num;
cmdq->irq_mask = GENMASK(cmdq->thread_nr - 1, 0);
err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler, IRQF_SHARED,
"mtk_cmdq", cmdq);
Expand All @@ -559,10 +568,28 @@ static int cmdq_probe(struct platform_device *pdev)
dev_dbg(dev, "cmdq device: addr:0x%p, va:0x%p, irq:%d\n",
dev, cmdq->base, cmdq->irq);

cmdq->clock = devm_clk_get(dev, "gce");
if (IS_ERR(cmdq->clock)) {
dev_err(dev, "failed to get gce clk\n");
return PTR_ERR(cmdq->clock);
if (cmdq->gce_num > 1) {
for_each_child_of_node(phandle->parent, node) {
char clk_id[8];

alias_id = of_alias_get_id(node, clk_name);
if (alias_id < cmdq->gce_num) {
snprintf(clk_id, sizeof(clk_id), "%s%d", clk_name, alias_id);
cmdq->clocks[alias_id].id = clk_id;
cmdq->clocks[alias_id].clk = of_clk_get(node, 0);
if (IS_ERR(cmdq->clocks[alias_id].clk)) {
dev_err(dev, "failed to get gce clk: %d\n", alias_id);
return PTR_ERR(cmdq->clocks[alias_id].clk);
}
}
}
} else {
cmdq->clocks[alias_id].id = clk_name;
cmdq->clocks[alias_id].clk = devm_clk_get(&pdev->dev, clk_name);
if (IS_ERR(cmdq->clocks[alias_id].clk)) {
dev_err(dev, "failed to get gce clk\n");
return PTR_ERR(cmdq->clocks[alias_id].clk);
}
}

cmdq->mbox.dev = dev;
Expand Down Expand Up @@ -598,7 +625,8 @@ static int cmdq_probe(struct platform_device *pdev)
}

platform_set_drvdata(pdev, cmdq);
WARN_ON(clk_prepare(cmdq->clock) < 0);

WARN_ON(clk_bulk_prepare(cmdq->gce_num, cmdq->clocks));

cmdq_init(cmdq);

Expand All @@ -610,18 +638,47 @@ static const struct dev_pm_ops cmdq_pm_ops = {
.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 gce_plat gce_plat_v4 = {.thread_nr = 24, .shift = 3};
static const struct gce_plat gce_plat_v5 = {.thread_nr = 24, .shift = 3,
.control_by_sw = true};
static const struct gce_plat gce_plat_v2 = {
.thread_nr = 16,
.shift = 0,
.control_by_sw = false,
.gce_num = 1
};

static const struct gce_plat gce_plat_v3 = {
.thread_nr = 24,
.shift = 0,
.control_by_sw = false,
.gce_num = 1
};

static const struct gce_plat gce_plat_v4 = {
.thread_nr = 24,
.shift = 3,
.control_by_sw = false,
.gce_num = 1
};

static const struct gce_plat gce_plat_v5 = {
.thread_nr = 24,
.shift = 3,
.control_by_sw = true,
.gce_num = 2
};

static const struct gce_plat gce_plat_v6 = {
.thread_nr = 24,
.shift = 3,
.control_by_sw = false,
.gce_num = 2
};

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},
{.compatible = "mediatek,mt8192-gce", .data = (void *)&gce_plat_v5},
{.compatible = "mediatek,mt8195-gce", .data = (void *)&gce_plat_v4},
{.compatible = "mediatek,mt8195-gce", .data = (void *)&gce_plat_v6},
{}
};

Expand Down

0 comments on commit 85dfdbf

Please sign in to comment.