in sprd-mailbox.c [301:409]
static int sprd_mbox_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct sprd_mbox_priv *priv;
int ret, inbox_irq, outbox_irq, supp_irq;
unsigned long id, supp;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->dev = dev;
mutex_init(&priv->lock);
/*
* Unisoc mailbox uses an inbox to send messages to the target
* core, and uses (an) outbox(es) to receive messages from other
* cores.
*
* Thus in general the mailbox controller supplies 2 different
* register addresses and IRQ numbers for inbox and outbox.
*
* If necessary, a supplementary inbox could be enabled optionally
* with an independent FIFO and an extra interrupt.
*/
priv->inbox_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->inbox_base))
return PTR_ERR(priv->inbox_base);
priv->outbox_base = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(priv->outbox_base))
return PTR_ERR(priv->outbox_base);
priv->clk = devm_clk_get(dev, "enable");
if (IS_ERR(priv->clk)) {
dev_err(dev, "failed to get mailbox clock\n");
return PTR_ERR(priv->clk);
}
ret = clk_prepare_enable(priv->clk);
if (ret)
return ret;
ret = devm_add_action_or_reset(dev, sprd_mbox_disable, priv);
if (ret) {
dev_err(dev, "failed to add mailbox disable action\n");
return ret;
}
inbox_irq = platform_get_irq_byname(pdev, "inbox");
if (inbox_irq < 0)
return inbox_irq;
ret = devm_request_irq(dev, inbox_irq, sprd_mbox_inbox_isr,
IRQF_NO_SUSPEND, dev_name(dev), priv);
if (ret) {
dev_err(dev, "failed to request inbox IRQ: %d\n", ret);
return ret;
}
outbox_irq = platform_get_irq_byname(pdev, "outbox");
if (outbox_irq < 0)
return outbox_irq;
ret = devm_request_irq(dev, outbox_irq, sprd_mbox_outbox_isr,
IRQF_NO_SUSPEND, dev_name(dev), priv);
if (ret) {
dev_err(dev, "failed to request outbox IRQ: %d\n", ret);
return ret;
}
/* Supplementary outbox IRQ is optional */
supp_irq = platform_get_irq_byname(pdev, "supp-outbox");
if (supp_irq > 0) {
ret = devm_request_irq(dev, supp_irq, sprd_mbox_supp_isr,
IRQF_NO_SUSPEND, dev_name(dev), priv);
if (ret) {
dev_err(dev, "failed to request outbox IRQ: %d\n", ret);
return ret;
}
supp = (unsigned long) of_device_get_match_data(dev);
if (!supp) {
dev_err(dev, "no supplementary outbox specified\n");
return -ENODEV;
}
priv->supp_base = priv->outbox_base + (SPRD_OUTBOX_BASE_SPAN * supp);
}
/* Get the default outbox FIFO depth */
priv->outbox_fifo_depth =
readl(priv->outbox_base + SPRD_MBOX_FIFO_DEPTH) + 1;
priv->mbox.dev = dev;
priv->mbox.chans = &priv->chan[0];
priv->mbox.num_chans = SPRD_MBOX_CHAN_MAX;
priv->mbox.ops = &sprd_mbox_ops;
priv->mbox.txdone_irq = true;
for (id = 0; id < SPRD_MBOX_CHAN_MAX; id++)
priv->chan[id].con_priv = (void *)id;
ret = devm_mbox_controller_register(dev, &priv->mbox);
if (ret) {
dev_err(dev, "failed to register mailbox: %d\n", ret);
return ret;
}
return 0;
}