From patchwork Fri May 31 14:33:20 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sudeep Holla X-Patchwork-Id: 165548 Delivered-To: patch@linaro.org Received: by 2002:a92:9e1a:0:0:0:0:0 with SMTP id q26csp836992ili; Fri, 31 May 2019 07:33:57 -0700 (PDT) X-Google-Smtp-Source: APXvYqzW7WAyAbthLnG0NHS8G7tPWqnZrQEew9JgO04OR8N6B+kk4mWTl7WFS9UeyuBAiBOC0iml X-Received: by 2002:a63:5e42:: with SMTP id s63mr9676344pgb.234.1559313237158; Fri, 31 May 2019 07:33:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1559313237; cv=none; d=google.com; s=arc-20160816; b=k7P33cQ78AhIuiORi3bctzKMdy4NJA6E2yzhX36fJvd5WDCF8T2esq66bsEAaqMJ+j FV4i2aFQJmvsIXUI1nJ0fk7Cx4Y1JGefzh/5bgTT6nV3gt/0paHS2cxXFhuPu3u+xAud qLRszRhDHWMOXDkqcN8G47Ry2tiTPs5NCcwcoXJj1uPY7tLPC7QooSMsiv1sC2c/TuFd FrHagNAaishDJ3dMpgT3AOlDwI/qcJFcPKXmJldTctefFVLZncqEgM+Zmk3jA4GjscCJ uOGaoiPcp2qudyIdiWkWQJ73NBR/gXQnp/8QSWjnPrai8dzkiok4GCHUcHT32Nyx2zbo Ci2A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from; bh=xRuU98JySC0MpweUbF63cMywPmCfEz8SSxGj2LOlWOU=; b=sxju71x8LW5tseyqxTyW02SjFNx7vOeusW+Bxbvm/89nycwJ4ctiot49vpSl5qhHJ8 87dGrizXAW3Z+aqfJ3N7DcEKYi+0N6+feSXF3DBth5G1eia1cp9TqS2MZ99iHfnUn55K F0opizchuGjL9cZ509h5lARlajF0iBKSwWiNa+zMTos3jFxxtqQPFT9/w5YNIVhyvPvj FoYOBLFPgLIIKWjCT6GpRXysQ2UMP3eBP41kAwOdn7wCiDZ9m1VD9ukdr1jUb+CT94EV rNoq6kzCpQ3O0uCaqZILnej2voYSa5C7Vyww7Mgxzjqd+oy56M09HP2oHxixjURajliM 8I9A== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id y22si6189623pgj.402.2019.05.31.07.33.54; Fri, 31 May 2019 07:33:57 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726912AbfEaOdx (ORCPT + 30 others); Fri, 31 May 2019 10:33:53 -0400 Received: from usa-sjc-mx-foss1.foss.arm.com ([217.140.101.70]:52514 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726884AbfEaOdt (ORCPT ); Fri, 31 May 2019 10:33:49 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id B12E6341; Fri, 31 May 2019 07:33:48 -0700 (PDT) Received: from usa.arm.com (e107155-lin.cambridge.arm.com [10.1.196.42]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id E467B3F5AF; Fri, 31 May 2019 07:33:46 -0700 (PDT) From: Sudeep Holla To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Jassi Brar , Arnd Bergmann Cc: Sudeep Holla , Bjorn Andersson , Rob Herring , Mark Brown , Cristian Marussi , Jassi Brar Subject: [PATCH 6/6] mailbox: arm_mhu: add full support for the doorbells Date: Fri, 31 May 2019 15:33:20 +0100 Message-Id: <20190531143320.8895-7-sudeep.holla@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190531143320.8895-1-sudeep.holla@arm.com> References: <20190531143320.8895-1-sudeep.holla@arm.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org We now have the basic infrastructure and binding to support doorbells on ARM MHU controller. This patch adds all the necessary mailbox operations to add support for the doorbells. Maximum of 32 doorbells are supported on each physical channel, however the total number of doorbells is restricted to 20 in order to save memory. It can increased if required in future. Cc: Jassi Brar Signed-off-by: Sudeep Holla --- drivers/mailbox/arm_mhu.c | 129 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 125 insertions(+), 4 deletions(-) -- 2.17.1 diff --git a/drivers/mailbox/arm_mhu.c b/drivers/mailbox/arm_mhu.c index c944ca121e9e..ba48d2281dca 100644 --- a/drivers/mailbox/arm_mhu.c +++ b/drivers/mailbox/arm_mhu.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -94,6 +95,14 @@ mhu_mbox_to_channel(struct mbox_controller *mbox, return NULL; } +static void mhu_mbox_clear_irq(struct mbox_chan *chan) +{ + struct mhu_channel *chan_info = chan->con_priv; + void __iomem *base = chan_info->mhu->mlink[chan_info->pchan].rx_reg; + + writel_relaxed(BIT(chan_info->doorbell), base + INTR_CLR_OFS); +} + static unsigned int mhu_mbox_irq_to_pchan_num(struct arm_mhu *mhu, int irq) { unsigned int pchan; @@ -105,6 +114,95 @@ static unsigned int mhu_mbox_irq_to_pchan_num(struct arm_mhu *mhu, int irq) return pchan; } +static struct mbox_chan *mhu_mbox_irq_to_channel(struct arm_mhu *mhu, + unsigned int pchan) +{ + unsigned long bits; + unsigned int doorbell; + struct mbox_chan *chan = NULL; + struct mbox_controller *mbox = &mhu->mbox; + void __iomem *base = mhu->mlink[pchan].rx_reg; + + bits = readl_relaxed(base + INTR_STAT_OFS); + if (!bits) + /* No IRQs fired in specified physical channel */ + return NULL; + + /* An IRQ has fired, find the associated channel */ + for (doorbell = 0; bits; doorbell++) { + if (!test_and_clear_bit(doorbell, &bits)) + continue; + + chan = mhu_mbox_to_channel(mbox, pchan, doorbell); + if (chan) + break; + } + + return chan; +} + +static irqreturn_t mhu_mbox_thread_handler(int irq, void *data) +{ + struct mbox_chan *chan; + struct arm_mhu *mhu = data; + unsigned int pchan = mhu_mbox_irq_to_pchan_num(mhu, irq); + + while (NULL != (chan = mhu_mbox_irq_to_channel(mhu, pchan))) { + mbox_chan_received_data(chan, NULL); + mhu_mbox_clear_irq(chan); + } + + return IRQ_HANDLED; +} + +static bool mhu_doorbell_last_tx_done(struct mbox_chan *chan) +{ + struct mhu_channel *chan_info = chan->con_priv; + void __iomem *base = chan_info->mhu->mlink[chan_info->pchan].tx_reg; + + if (readl_relaxed(base + INTR_STAT_OFS) & BIT(chan_info->doorbell)) + return false; + + return true; +} + +static int mhu_doorbell_send_signal(struct mbox_chan *chan) +{ + struct mhu_channel *chan_info = chan->con_priv; + void __iomem *base = chan_info->mhu->mlink[chan_info->pchan].tx_reg; + + /* Send event to co-processor */ + writel_relaxed(BIT(chan_info->doorbell), base + INTR_SET_OFS); + + return 0; +} + +static int mhu_doorbell_startup(struct mbox_chan *chan) +{ + mhu_mbox_clear_irq(chan); + return 0; +} + +static void mhu_doorbell_shutdown(struct mbox_chan *chan) +{ + struct mhu_channel *chan_info = chan->con_priv; + struct mbox_controller *mbox = &chan_info->mhu->mbox; + int i; + + for (i = 0; i < mbox->num_chans; i++) + if (chan == &mbox->chans[i]) + break; + + if (mbox->num_chans == i) { + dev_warn(mbox->dev, "Request to free non-existent channel\n"); + return; + } + + /* Reset channel */ + mhu_mbox_clear_irq(chan); + chan->con_priv = NULL; +} + static struct mbox_chan *mhu_mbox_xlate(struct mbox_controller *mbox, const struct of_phandle_args *spec) { @@ -222,16 +320,30 @@ static const struct mbox_chan_ops mhu_ops = { .last_tx_done = mhu_last_tx_done, }; +static const struct mbox_chan_ops mhu_doorbell_ops = { + .send_signal = mhu_doorbell_send_signal, + .startup = mhu_doorbell_startup, + .shutdown = mhu_doorbell_shutdown, + .last_tx_done = mhu_doorbell_last_tx_done, +}; + static const struct mhu_mbox_pdata arm_mhu_pdata = { .num_pchans = 3, .num_doorbells = 1, .support_doorbells = false, }; +static const struct mhu_mbox_pdata arm_mhu_doorbell_pdata = { + .num_pchans = 2, /* Secure can't be used */ + .num_doorbells = 32, + .support_doorbells = true, +}; + static int mhu_probe(struct amba_device *adev, const struct amba_id *id) { u32 cell_count; int i, err, max_chans; + irq_handler_t handler; struct arm_mhu *mhu; struct mbox_chan *chans; struct mhu_mbox_pdata *pdata; @@ -251,6 +363,9 @@ static int mhu_probe(struct amba_device *adev, const struct amba_id *id) if (cell_count == 1) { max_chans = MHU_NUM_PCHANS; pdata = (struct mhu_mbox_pdata *)&arm_mhu_pdata; + } else if (cell_count == 2) { + max_chans = MHU_CHAN_MAX; + pdata = (struct mhu_mbox_pdata *)&arm_mhu_doorbell_pdata; } else { dev_err(dev, "incorrect value of #mbox-cells in %s\n", np->full_name); @@ -283,7 +398,6 @@ static int mhu_probe(struct amba_device *adev, const struct amba_id *id) mhu->mbox.dev = dev; mhu->mbox.chans = chans; mhu->mbox.num_chans = max_chans; - mhu->mbox.ops = &mhu_ops; mhu->mbox.txdone_irq = false; mhu->mbox.txdone_poll = true; mhu->mbox.txpoll_period = 1; @@ -291,6 +405,14 @@ static int mhu_probe(struct amba_device *adev, const struct amba_id *id) mhu->mbox.of_xlate = mhu_mbox_xlate; amba_set_drvdata(adev, mhu); + if (pdata->support_doorbells) { + mhu->mbox.ops = &mhu_doorbell_ops; + handler = mhu_mbox_thread_handler; + } else { + mhu->mbox.ops = &mhu_ops; + handler = mhu_rx_interrupt; + } + err = devm_mbox_controller_register(dev, &mhu->mbox); if (err) { dev_err(dev, "Failed to register mailboxes %d\n", err); @@ -308,9 +430,8 @@ static int mhu_probe(struct amba_device *adev, const struct amba_id *id) mhu->mlink[i].rx_reg = mhu->base + mhu_reg[i]; mhu->mlink[i].tx_reg = mhu->mlink[i].rx_reg + TX_REG_OFFSET; - err = devm_request_threaded_irq(dev, irq, NULL, - mhu_rx_interrupt, IRQF_ONESHOT, - "mhu_link", mhu); + err = devm_request_threaded_irq(dev, irq, NULL, handler, + IRQF_ONESHOT, "mhu_link", mhu); if (err) { dev_err(dev, "Can't claim IRQ %d\n", irq); mbox_controller_unregister(&mhu->mbox);