static int cmdq_probe()

in mtk-cmdq-mailbox.c [524:632]


static int cmdq_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	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;
	static const char * const clk_name = "gce";
	static const char * const clk_names[] = { "gce0", "gce1" };

	cmdq = devm_kzalloc(dev, sizeof(*cmdq), GFP_KERNEL);
	if (!cmdq)
		return -ENOMEM;

	cmdq->base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(cmdq->base))
		return PTR_ERR(cmdq->base);

	cmdq->irq = platform_get_irq(pdev, 0);
	if (cmdq->irq < 0)
		return cmdq->irq;

	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->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);
	if (err < 0) {
		dev_err(dev, "failed to register ISR (%d)\n", err);
		return err;
	}

	dev_dbg(dev, "cmdq device: addr:0x%p, va:0x%p, irq:%d\n",
		dev, cmdq->base, cmdq->irq);

	if (cmdq->gce_num > 1) {
		for_each_child_of_node(phandle->parent, node) {
			alias_id = of_alias_get_id(node, clk_name);
			if (alias_id >= 0 && alias_id < cmdq->gce_num) {
				cmdq->clocks[alias_id].id = clk_names[alias_id];
				cmdq->clocks[alias_id].clk = of_clk_get(node, 0);
				if (IS_ERR(cmdq->clocks[alias_id].clk)) {
					of_node_put(node);
					return dev_err_probe(dev,
							     PTR_ERR(cmdq->clocks[alias_id].clk),
							     "failed to get gce clk: %d\n",
							     alias_id);
				}
			}
		}
	} 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)) {
			return dev_err_probe(dev, PTR_ERR(cmdq->clocks[alias_id].clk),
					     "failed to get gce clk\n");
		}
	}

	cmdq->mbox.dev = dev;
	cmdq->mbox.chans = devm_kcalloc(dev, cmdq->thread_nr,
					sizeof(*cmdq->mbox.chans), GFP_KERNEL);
	if (!cmdq->mbox.chans)
		return -ENOMEM;

	cmdq->mbox.num_chans = cmdq->thread_nr;
	cmdq->mbox.ops = &cmdq_mbox_chan_ops;
	cmdq->mbox.of_xlate = cmdq_xlate;

	/* make use of TXDONE_BY_ACK */
	cmdq->mbox.txdone_irq = false;
	cmdq->mbox.txdone_poll = false;

	cmdq->thread = devm_kcalloc(dev, cmdq->thread_nr,
					sizeof(*cmdq->thread), GFP_KERNEL);
	if (!cmdq->thread)
		return -ENOMEM;

	for (i = 0; i < cmdq->thread_nr; i++) {
		cmdq->thread[i].base = cmdq->base + CMDQ_THR_BASE +
				CMDQ_THR_SIZE * i;
		INIT_LIST_HEAD(&cmdq->thread[i].task_busy_list);
		cmdq->mbox.chans[i].con_priv = (void *)&cmdq->thread[i];
	}

	err = devm_mbox_controller_register(dev, &cmdq->mbox);
	if (err < 0) {
		dev_err(dev, "failed to register mailbox: %d\n", err);
		return err;
	}

	platform_set_drvdata(pdev, cmdq);

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

	cmdq_init(cmdq);

	return 0;
}