summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-01-02 18:41:38 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2019-01-02 18:41:38 -0800
commit35ddb06a467538434b4139fbf5c02a2ef073162a (patch)
tree20bf25b62f6d360adffd4233a971ef53b02019be
parent6aa293d8ff0939802a6c86cee6cd152c1b0a7a0d (diff)
parentd69e11648e486ee0f21cb246f687b083f0d4e124 (diff)
Merge tag 'mailbox-v4.21' of git://git.linaro.org/landing-teams/working/fujitsu/integration
Pull mailbox updates from Jassi Brar: - Introduce device-managed registration devm_mbox_controller_un/register and convert drivers to use it - Introduce flush api to support clients that must busy-wait in atomic context - Support multiple controllers per device - Hi3660: a bugfix and constify ops structure - TI-MsgMgr: off by one bugfix. - BCM: switch to spdx license - Tegra-HSP: support for shared mailboxes and suspend/resume. * tag 'mailbox-v4.21' of git://git.linaro.org/landing-teams/working/fujitsu/integration: (30 commits) mailbox: tegra-hsp: Use device-managed registration API mailbox: tegra-hsp: use devm_kstrdup_const() mailbox: tegra-hsp: Add suspend/resume support mailbox: tegra-hsp: Add support for shared mailboxes dt-bindings: tegra186-hsp: Add shared mailboxes mailbox: Allow multiple controllers per device mailbox: Support blocking transfers in atomic context mailbox: ti-msgmgr: Use device-managed registration API mailbox: stm32-ipcc: Use device-managed registration API mailbox: rockchip: Use device-managed registration API mailbox: qcom-apcs: Use device-managed registration API mailbox: platform-mhu: Use device-managed registration API mailbox: omap: Use device-managed registration API mailbox: mtk-cmdq: Remove needless devm_kfree() calls mailbox: mtk-cmdq: Use device-managed registration API mailbox: xgene-slimpro: Use device-managed registration API mailbox: sti: Use device-managed registration API mailbox: altera: Use device-managed registration API mailbox: imx: Use device-managed registration API mailbox: hi6220: Use device-managed registration API ...
-rw-r--r--Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt30
-rw-r--r--drivers/mailbox/arm_mhu.c12
-rw-r--r--drivers/mailbox/bcm-flexrm-mailbox.c4
-rw-r--r--drivers/mailbox/bcm-pdc-mailbox.c4
-rw-r--r--drivers/mailbox/bcm2835-mailbox.c18
-rw-r--r--drivers/mailbox/hi3660-mailbox.c35
-rw-r--r--drivers/mailbox/hi6220-mailbox.c11
-rw-r--r--drivers/mailbox/imx-mailbox.c3
-rw-r--r--drivers/mailbox/mailbox-altera.c15
-rw-r--r--drivers/mailbox/mailbox-sti.c13
-rw-r--r--drivers/mailbox/mailbox-xgene-slimpro.c11
-rw-r--r--drivers/mailbox/mailbox.c101
-rw-r--r--drivers/mailbox/mtk-cmdq-mailbox.c11
-rw-r--r--drivers/mailbox/omap-mailbox.c4
-rw-r--r--drivers/mailbox/platform_mhu.c12
-rw-r--r--drivers/mailbox/qcom-apcs-ipc-mailbox.c3
-rw-r--r--drivers/mailbox/rockchip-mailbox.c15
-rw-r--r--drivers/mailbox/stm32-ipcc.c4
-rw-r--r--drivers/mailbox/tegra-hsp.c517
-rw-r--r--drivers/mailbox/ti-msgmgr.c15
-rw-r--r--include/dt-bindings/mailbox/tegra186-hsp.h11
-rw-r--r--include/linux/mailbox_client.h1
-rw-r--r--include/linux/mailbox_controller.h9
23 files changed, 612 insertions, 247 deletions
diff --git a/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt b/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt
index b99d25fc2f26..ff3eafc5a882 100644
--- a/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt
+++ b/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt
@@ -15,12 +15,15 @@ Required properties:
Array of strings.
one of:
- "nvidia,tegra186-hsp"
+ - "nvidia,tegra194-hsp", "nvidia,tegra186-hsp"
- reg : Offset and length of the register set for the device.
- interrupt-names
Array of strings.
Contains a list of names for the interrupts described by the interrupt
property. May contain the following entries, in any order:
- "doorbell"
+ - "sharedN", where 'N' is a number from zero up to the number of
+ external interrupts supported by the HSP instance minus one.
Users of this binding MUST look up entries in the interrupt property
by name, using this interrupt-names property to do so.
- interrupts
@@ -29,12 +32,29 @@ Required properties:
in a matching order.
- #mbox-cells : Should be 2.
-The mbox specifier of the "mboxes" property in the client node should
-contain two data. The first one should be the HSP type and the second
-one should be the ID that the client is going to use. Those information
-can be found in the following file.
+The mbox specifier of the "mboxes" property in the client node should contain
+two cells. The first cell determines the HSP type and the second cell is used
+to identify the mailbox that the client is going to use.
-- <dt-bindings/mailbox/tegra186-hsp.h>.
+For doorbells, the second cell specifies the index of the doorbell to use.
+
+For shared mailboxes, the second cell is composed of two fields:
+- bits 31..24:
+ A bit mask of flags that further specify how the shared mailbox will be
+ used. Valid flags are:
+ - bit 31:
+ Defines the direction of the mailbox. If set, the mailbox will be used
+ as a producer (i.e. used to send data). If cleared, the mailbox is the
+ consumer of data sent by a producer.
+
+- bits 23.. 0:
+ The index of the shared mailbox to use. The number of available mailboxes
+ may vary by instance of the HSP block and SoC generation.
+
+The following file contains definitions that can be used to construct mailbox
+specifiers:
+
+ <dt-bindings/mailbox/tegra186-hsp.h>
Example:
diff --git a/drivers/mailbox/arm_mhu.c b/drivers/mailbox/arm_mhu.c
index 99befa76e37c..64d85c6a2bdf 100644
--- a/drivers/mailbox/arm_mhu.c
+++ b/drivers/mailbox/arm_mhu.c
@@ -152,7 +152,7 @@ static int mhu_probe(struct amba_device *adev, const struct amba_id *id)
amba_set_drvdata(adev, mhu);
- err = mbox_controller_register(&mhu->mbox);
+ err = devm_mbox_controller_register(dev, &mhu->mbox);
if (err) {
dev_err(dev, "Failed to register mailboxes %d\n", err);
return err;
@@ -162,15 +162,6 @@ static int mhu_probe(struct amba_device *adev, const struct amba_id *id)
return 0;
}
-static int mhu_remove(struct amba_device *adev)
-{
- struct arm_mhu *mhu = amba_get_drvdata(adev);
-
- mbox_controller_unregister(&mhu->mbox);
-
- return 0;
-}
-
static struct amba_id mhu_ids[] = {
{
.id = 0x1bb098,
@@ -186,7 +177,6 @@ static struct amba_driver arm_mhu_driver = {
},
.id_table = mhu_ids,
.probe = mhu_probe,
- .remove = mhu_remove,
};
module_amba_driver(arm_mhu_driver);
diff --git a/drivers/mailbox/bcm-flexrm-mailbox.c b/drivers/mailbox/bcm-flexrm-mailbox.c
index d7a8ed7d8097..d713271ebf7c 100644
--- a/drivers/mailbox/bcm-flexrm-mailbox.c
+++ b/drivers/mailbox/bcm-flexrm-mailbox.c
@@ -1665,7 +1665,7 @@ skip_debugfs:
mbox->controller.chans[index].con_priv = &mbox->rings[index];
/* Register mailbox controller */
- ret = mbox_controller_register(&mbox->controller);
+ ret = devm_mbox_controller_register(dev, &mbox->controller);
if (ret)
goto fail_free_debugfs_root;
@@ -1691,8 +1691,6 @@ static int flexrm_mbox_remove(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct flexrm_mbox *mbox = platform_get_drvdata(pdev);
- mbox_controller_unregister(&mbox->controller);
-
debugfs_remove_recursive(mbox->root);
platform_msi_domain_free_irqs(dev);
diff --git a/drivers/mailbox/bcm-pdc-mailbox.c b/drivers/mailbox/bcm-pdc-mailbox.c
index 4fe7be0bdd11..ccf3d62af7e7 100644
--- a/drivers/mailbox/bcm-pdc-mailbox.c
+++ b/drivers/mailbox/bcm-pdc-mailbox.c
@@ -1471,7 +1471,7 @@ static int pdc_mb_init(struct pdc_state *pdcs)
mbc->chans[chan_index].con_priv = pdcs;
/* Register mailbox controller */
- err = mbox_controller_register(mbc);
+ err = devm_mbox_controller_register(dev, mbc);
if (err) {
dev_crit(dev,
"Failed to register PDC mailbox controller. Error %d.",
@@ -1641,8 +1641,6 @@ static int pdc_remove(struct platform_device *pdev)
pdc_hw_disable(pdcs);
- mbox_controller_unregister(&pdcs->mbc);
-
dma_pool_destroy(pdcs->rx_buf_pool);
dma_pool_destroy(pdcs->ring_pool);
return 0;
diff --git a/drivers/mailbox/bcm2835-mailbox.c b/drivers/mailbox/bcm2835-mailbox.c
index e92bbc533821..39761d190545 100644
--- a/drivers/mailbox/bcm2835-mailbox.c
+++ b/drivers/mailbox/bcm2835-mailbox.c
@@ -1,15 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2010,2015 Broadcom
* Copyright (C) 2013-2014 Lubomir Rintel
* Copyright (C) 2013 Craig McGeachie
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This device provides a mechanism for writing to the mailboxes,
- * that are shared between the ARM and the VideoCore processor
- *
* Parts of the driver are based on:
* - arch/arm/mach-bcm2708/vcio.c file written by Gray Girling that was
* obtained from branch "rpi-3.6.y" of git://github.com/raspberrypi/
@@ -178,7 +172,7 @@ static int bcm2835_mbox_probe(struct platform_device *pdev)
if (!mbox->controller.chans)
return -ENOMEM;
- ret = mbox_controller_register(&mbox->controller);
+ ret = devm_mbox_controller_register(dev, &mbox->controller);
if (ret)
return ret;
@@ -188,13 +182,6 @@ static int bcm2835_mbox_probe(struct platform_device *pdev)
return ret;
}
-static int bcm2835_mbox_remove(struct platform_device *pdev)
-{
- struct bcm2835_mbox *mbox = platform_get_drvdata(pdev);
- mbox_controller_unregister(&mbox->controller);
- return 0;
-}
-
static const struct of_device_id bcm2835_mbox_of_match[] = {
{ .compatible = "brcm,bcm2835-mbox", },
{},
@@ -207,7 +194,6 @@ static struct platform_driver bcm2835_mbox_driver = {
.of_match_table = bcm2835_mbox_of_match,
},
.probe = bcm2835_mbox_probe,
- .remove = bcm2835_mbox_remove,
};
module_platform_driver(bcm2835_mbox_driver);
diff --git a/drivers/mailbox/hi3660-mailbox.c b/drivers/mailbox/hi3660-mailbox.c
index 3eea6b642484..53f4bc2488c5 100644
--- a/drivers/mailbox/hi3660-mailbox.c
+++ b/drivers/mailbox/hi3660-mailbox.c
@@ -38,6 +38,7 @@
#define MBOX_AUTOMATIC_ACK 1
#define MBOX_STATE_IDLE BIT(4)
+#define MBOX_STATE_READY BIT(5)
#define MBOX_STATE_ACK BIT(7)
#define MBOX_MSG_LEN 8
@@ -91,8 +92,8 @@ static int hi3660_mbox_check_state(struct mbox_chan *chan)
unsigned long val;
unsigned int ret;
- /* Mailbox is idle so directly bail out */
- if (readl(base + MBOX_MODE_REG) & MBOX_STATE_IDLE)
+ /* Mailbox is ready to use */
+ if (readl(base + MBOX_MODE_REG) & MBOX_STATE_READY)
return 0;
/* Wait for acknowledge from remote */
@@ -103,9 +104,9 @@ static int hi3660_mbox_check_state(struct mbox_chan *chan)
return ret;
}
- /* Ensure channel is released */
- writel(0xffffffff, base + MBOX_IMASK_REG);
- writel(BIT(mchan->ack_irq), base + MBOX_SRC_REG);
+ /* clear ack state, mailbox will get back to ready state */
+ writel(BIT(mchan->ack_irq), base + MBOX_ICLR_REG);
+
return 0;
}
@@ -160,10 +161,6 @@ static int hi3660_mbox_startup(struct mbox_chan *chan)
{
int ret;
- ret = hi3660_mbox_check_state(chan);
- if (ret)
- return ret;
-
ret = hi3660_mbox_unlock(chan);
if (ret)
return ret;
@@ -183,10 +180,11 @@ static int hi3660_mbox_send_data(struct mbox_chan *chan, void *msg)
void __iomem *base = MBOX_BASE(mbox, ch);
u32 *buf = msg;
unsigned int i;
+ int ret;
- /* Ensure channel is released */
- writel_relaxed(0xffffffff, base + MBOX_IMASK_REG);
- writel_relaxed(BIT(mchan->ack_irq), base + MBOX_SRC_REG);
+ ret = hi3660_mbox_check_state(chan);
+ if (ret)
+ return ret;
/* Clear mask for destination interrupt */
writel_relaxed(~BIT(mchan->dst_irq), base + MBOX_IMASK_REG);
@@ -206,7 +204,7 @@ static int hi3660_mbox_send_data(struct mbox_chan *chan, void *msg)
return 0;
}
-static struct mbox_chan_ops hi3660_mbox_ops = {
+static const struct mbox_chan_ops hi3660_mbox_ops = {
.startup = hi3660_mbox_startup,
.send_data = hi3660_mbox_send_data,
};
@@ -267,7 +265,7 @@ static int hi3660_mbox_probe(struct platform_device *pdev)
for (ch = 0; ch < MBOX_CHAN_MAX; ch++)
chan[ch].con_priv = (void *)ch;
- err = mbox_controller_register(&mbox->controller);
+ err = devm_mbox_controller_register(dev, &mbox->controller);
if (err) {
dev_err(dev, "Failed to register mailbox %d\n", err);
return err;
@@ -278,17 +276,8 @@ static int hi3660_mbox_probe(struct platform_device *pdev)
return 0;
}
-static int hi3660_mbox_remove(struct platform_device *pdev)
-{
- struct hi3660_mbox *mbox = platform_get_drvdata(pdev);
-
- mbox_controller_unregister(&mbox->controller);
- return 0;
-}
-
static struct platform_driver hi3660_mbox_driver = {
.probe = hi3660_mbox_probe,
- .remove = hi3660_mbox_remove,
.driver = {
.name = "hi3660-mbox",
.of_match_table = hi3660_mbox_of_match,
diff --git a/drivers/mailbox/hi6220-mailbox.c b/drivers/mailbox/hi6220-mailbox.c
index 4fa9803cd204..c32cbfaf223a 100644
--- a/drivers/mailbox/hi6220-mailbox.c
+++ b/drivers/mailbox/hi6220-mailbox.c
@@ -349,7 +349,7 @@ static int hi6220_mbox_probe(struct platform_device *pdev)
mbox->controller.txpoll_period = 5;
}
- err = mbox_controller_register(&mbox->controller);
+ err = devm_mbox_controller_register(dev, &mbox->controller);
if (err) {
dev_err(dev, "Failed to register mailbox %d\n", err);
return err;
@@ -360,14 +360,6 @@ static int hi6220_mbox_probe(struct platform_device *pdev)
return 0;
}
-static int hi6220_mbox_remove(struct platform_device *pdev)
-{
- struct hi6220_mbox *mbox = platform_get_drvdata(pdev);
-
- mbox_controller_unregister(&mbox->controller);
- return 0;
-}
-
static struct platform_driver hi6220_mbox_driver = {
.driver = {
.name = "hi6220-mbox",
@@ -375,7 +367,6 @@ static struct platform_driver hi6220_mbox_driver = {
.of_match_table = hi6220_mbox_of_match,
},
.probe = hi6220_mbox_probe,
- .remove = hi6220_mbox_remove,
};
static int __init hi6220_mbox_init(void)
diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c
index 363d35d5e49d..774362a05159 100644
--- a/drivers/mailbox/imx-mailbox.c
+++ b/drivers/mailbox/imx-mailbox.c
@@ -324,14 +324,13 @@ static int imx_mu_probe(struct platform_device *pdev)
imx_mu_init_generic(priv);
- return mbox_controller_register(&priv->mbox);
+ return devm_mbox_controller_register(dev, &priv->mbox);
}
static int imx_mu_remove(struct platform_device *pdev)
{
struct imx_mu_priv *priv = platform_get_drvdata(pdev);
- mbox_controller_unregister(&priv->mbox);
clk_disable_unprepare(priv->clk);
return 0;
diff --git a/drivers/mailbox/mailbox-altera.c b/drivers/mailbox/mailbox-altera.c
index bcb29df9549e..397e25ddae29 100644
--- a/drivers/mailbox/mailbox-altera.c
+++ b/drivers/mailbox/mailbox-altera.c
@@ -341,7 +341,7 @@ static int altera_mbox_probe(struct platform_device *pdev)
}
}
- ret = mbox_controller_register(&mbox->controller);
+ ret = devm_mbox_controller_register(&pdev->dev, &mbox->controller);
if (ret) {
dev_err(&pdev->dev, "Register mailbox failed\n");
goto err;
@@ -352,18 +352,6 @@ err:
return ret;
}
-static int altera_mbox_remove(struct platform_device *pdev)
-{
- struct altera_mbox *mbox = platform_get_drvdata(pdev);
-
- if (!mbox)
- return -EINVAL;
-
- mbox_controller_unregister(&mbox->controller);
-
- return 0;
-}
-
static const struct of_device_id altera_mbox_match[] = {
{ .compatible = "altr,mailbox-1.0" },
{ /* Sentinel */ }
@@ -373,7 +361,6 @@ MODULE_DEVICE_TABLE(of, altera_mbox_match);
static struct platform_driver altera_mbox_driver = {
.probe = altera_mbox_probe,
- .remove = altera_mbox_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = altera_mbox_match,
diff --git a/drivers/mailbox/mailbox-sti.c b/drivers/mailbox/mailbox-sti.c
index 779d41262ef0..adf82b85dbb2 100644
--- a/drivers/mailbox/mailbox-sti.c
+++ b/drivers/mailbox/mailbox-sti.c
@@ -462,7 +462,7 @@ static int sti_mbox_probe(struct platform_device *pdev)
mbox->chans = chans;
mbox->num_chans = STI_MBOX_CHAN_MAX;
- ret = mbox_controller_register(mbox);
+ ret = devm_mbox_controller_register(&pdev->dev, mbox);
if (ret)
return ret;
@@ -480,7 +480,6 @@ static int sti_mbox_probe(struct platform_device *pdev)
IRQF_ONESHOT, mdev->name, mdev);
if (ret) {
dev_err(&pdev->dev, "Can't claim IRQ %d\n", irq);
- mbox_controller_unregister(mbox);
return -EINVAL;
}
@@ -489,18 +488,8 @@ static int sti_mbox_probe(struct platform_device *pdev)
return 0;
}
-static int sti_mbox_remove(struct platform_device *pdev)
-{
- struct sti_mbox_device *mdev = platform_get_drvdata(pdev);
-
- mbox_controller_unregister(mdev->mbox);
-
- return 0;
-}
-
static struct platform_driver sti_mbox_driver = {
.probe = sti_mbox_probe,
- .remove = sti_mbox_remove,
.driver = {
.name = "sti-mailbox",
.of_match_table = sti_mailbox_match,
diff --git a/drivers/mailbox/mailbox-xgene-slimpro.c b/drivers/mailbox/mailbox-xgene-slimpro.c
index b8b2b3533f46..8f397da1150b 100644
--- a/drivers/mailbox/mailbox-xgene-slimpro.c
+++ b/drivers/mailbox/mailbox-xgene-slimpro.c
@@ -224,7 +224,7 @@ static int slimpro_mbox_probe(struct platform_device *pdev)
ctx->mb_ctrl.ops = &slimpro_mbox_ops;
ctx->mb_ctrl.num_chans = i;
- rc = mbox_controller_register(&ctx->mb_ctrl);
+ rc = devm_mbox_controller_register(&pdev->dev, &ctx->mb_ctrl);
if (rc) {
dev_err(&pdev->dev,
"APM X-Gene SLIMpro MailBox register failed:%d\n", rc);
@@ -235,14 +235,6 @@ static int slimpro_mbox_probe(struct platform_device *pdev)
return 0;
}
-static int slimpro_mbox_remove(struct platform_device *pdev)
-{
- struct slimpro_mbox *smb = platform_get_drvdata(pdev);
-
- mbox_controller_unregister(&smb->mb_ctrl);
- return 0;
-}
-
static const struct of_device_id slimpro_of_match[] = {
{.compatible = "apm,xgene-slimpro-mbox" },
{ },
@@ -259,7 +251,6 @@ MODULE_DEVICE_TABLE(acpi, slimpro_acpi_ids);
static struct platform_driver slimpro_mbox_driver = {
.probe = slimpro_mbox_probe,
- .remove = slimpro_mbox_remove,
.driver = {
.name = "xgene-slimpro-mbox",
.of_match_table = of_match_ptr(slimpro_of_match),
diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c
index 674b35f402f5..c6a7d4582dc6 100644
--- a/drivers/mailbox/mailbox.c
+++ b/drivers/mailbox/mailbox.c
@@ -284,6 +284,34 @@ int mbox_send_message(struct mbox_chan *chan, void *mssg)
EXPORT_SYMBOL_GPL(mbox_send_message);
/**
+ * mbox_flush - flush a mailbox channel
+ * @chan: mailbox channel to flush
+ * @timeout: time, in milliseconds, to allow the flush operation to succeed
+ *
+ * Mailbox controllers that need to work in atomic context can implement the
+ * ->flush() callback to busy loop until a transmission has been completed.
+ * The implementation must call mbox_chan_txdone() upon success. Clients can
+ * call the mbox_flush() function at any time after mbox_send_message() to
+ * flush the transmission. After the function returns success, the mailbox
+ * transmission is guaranteed to have completed.
+ *
+ * Returns: 0 on success or a negative error code on failure.
+ */
+int mbox_flush(struct mbox_chan *chan, unsigned long timeout)
+{
+ int ret;
+
+ if (!chan->mbox->ops->flush)
+ return -ENOTSUPP;
+
+ ret = chan->mbox->ops->flush(chan, timeout);
+ if (ret < 0)
+ tx_tick(chan, ret);
+
+ return ret;
+}
+
+/**
* mbox_request_channel - Request a mailbox channel.
* @cl: Identity of the client requesting the channel.
* @index: Index of mailbox specifier in 'mboxes' property.
@@ -327,7 +355,8 @@ struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)
list_for_each_entry(mbox, &mbox_cons, node)
if (mbox->dev->of_node == spec.np) {
chan = mbox->of_xlate(mbox, &spec);
- break;
+ if (!IS_ERR(chan))
+ break;
}
of_node_put(spec.np);
@@ -515,3 +544,73 @@ void mbox_controller_unregister(struct mbox_controller *mbox)
mutex_unlock(&con_mutex);
}
EXPORT_SYMBOL_GPL(mbox_controller_unregister);
+
+static void __devm_mbox_controller_unregister(struct device *dev, void *res)
+{
+ struct mbox_controller **mbox = res;
+
+ mbox_controller_unregister(*mbox);
+}
+
+static int devm_mbox_controller_match(struct device *dev, void *res, void *data)
+{
+ struct mbox_controller **mbox = res;
+
+ if (WARN_ON(!mbox || !*mbox))
+ return 0;
+
+ return *mbox == data;
+}
+
+/**
+ * devm_mbox_controller_register() - managed mbox_controller_register()
+ * @dev: device owning the mailbox controller being registered
+ * @mbox: mailbox controller being registered
+ *
+ * This function adds a device-managed resource that will make sure that the
+ * mailbox controller, which is registered using mbox_controller_register()
+ * as part of this function, will be unregistered along with the rest of
+ * device-managed resources upon driver probe failure or driver removal.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int devm_mbox_controller_register(struct device *dev,
+ struct mbox_controller *mbox)
+{
+ struct mbox_controller **ptr;
+ int err;
+
+ ptr = devres_alloc(__devm_mbox_controller_unregister, sizeof(*ptr),
+ GFP_KERNEL);
+ if (!ptr)
+ return -ENOMEM;
+
+ err = mbox_controller_register(mbox);
+ if (err < 0) {
+ devres_free(ptr);
+ return err;
+ }
+
+ devres_add(dev, ptr);
+ *ptr = mbox;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(devm_mbox_controller_register);
+
+/**
+ * devm_mbox_controller_unregister() - managed mbox_controller_unregister()
+ * @dev: device owning the mailbox controller being unregistered
+ * @mbox: mailbox controller being unregistered
+ *
+ * This function unregisters the mailbox controller and removes the device-
+ * managed resource that was set up to automatically unregister the mailbox
+ * controller on driver probe failure or driver removal. It's typically not
+ * necessary to call this function.
+ */
+void devm_mbox_controller_unregister(struct device *dev, struct mbox_controller *mbox)
+{
+ WARN_ON(devres_release(dev, __devm_mbox_controller_unregister,
+ devm_mbox_controller_match, mbox));
+}
+EXPORT_SYMBOL_GPL(devm_mbox_controller_unregister);
diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c
index f7cc29c00302..22811784dc7d 100644
--- a/drivers/mailbox/mtk-cmdq-mailbox.c
+++ b/drivers/mailbox/mtk-cmdq-mailbox.c
@@ -337,17 +337,8 @@ static int cmdq_remove(struct platform_device *pdev)
{
struct cmdq *cmdq = platform_get_drvdata(pdev);
- mbox_controller_unregister(&cmdq->mbox);
clk_unprepare(cmdq->clock);
- if (cmdq->mbox.chans)
- devm_kfree(&pdev->dev, cmdq->mbox.chans);
-
- if (cmdq->thread)
- devm_kfree(&pdev->dev, cmdq->thread);
-
- devm_kfree(&pdev->dev, cmdq);
-
return 0;
}
@@ -524,7 +515,7 @@ static int cmdq_probe(struct platform_device *pdev)
cmdq->mbox.chans[i].con_priv = (void *)&cmdq->thread[i];
}
- err = mbox_controller_register(&cmdq->mbox);
+ err = devm_mbox_controller_register(dev, &cmdq->mbox);
if (err < 0) {
dev_err(dev, "failed to register mailbox: %d\n", err);
return err;
diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c
index db66e952a871..ca50177a33f2 100644
--- a/drivers/mailbox/omap-mailbox.c
+++ b/drivers/mailbox/omap-mailbox.c
@@ -486,7 +486,7 @@ static int omap_mbox_register(struct omap_mbox_device *mdev)
list_add(&mdev->elem, &omap_mbox_devices);
mutex_unlock(&omap_mbox_devices_lock);
- ret = mbox_controller_register(&mdev->controller);
+ ret = devm_mbox_controller_register(mdev->dev, &mdev->controller);
err_out:
if (ret) {
@@ -508,8 +508,6 @@ static int omap_mbox_unregister(struct omap_mbox_device *mdev)
list_del(&mdev->elem);
mutex_unlock(&omap_mbox_devices_lock);
- mbox_controller_unregister(&mdev->controller);
-
mboxes = mdev->mboxes;
for (i = 0; mboxes[i]; i++)
device_unregister(mboxes[i]->dev);
diff --git a/drivers/mailbox/platform_mhu.c b/drivers/mailbox/platform_mhu.c
index e13201a5cec6..d2502c5be130 100644
--- a/drivers/mailbox/platform_mhu.c
+++ b/drivers/mailbox/platform_mhu.c
@@ -163,7 +163,7 @@ static int platform_mhu_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, mhu);
- err = mbox_controller_register(&mhu->mbox);
+ err = devm_mbox_controller_register(dev, &mhu->mbox);
if (err) {
dev_err(dev, "Failed to register mailboxes %d\n", err);
return err;
@@ -173,15 +173,6 @@ static int platform_mhu_probe(struct platform_device *pdev)
return 0;
}
-static int platform_mhu_remove(struct platform_device *pdev)
-{
- struct platform_mhu *mhu = platform_get_drvdata(pdev);
-
- mbox_controller_unregister(&mhu->mbox);
-
- return 0;
-}
-
static const struct of_device_id platform_mhu_dt_ids[] = {
{ .compatible = "amlogic,meson-gxbb-mhu", },
{ /* sentinel */ },
@@ -190,7 +181,6 @@ MODULE_DEVICE_TABLE(of, platform_mhu_dt_ids);
static struct platform_driver platform_mhu_driver = {
.probe = platform_mhu_probe,
- .remove = platform_mhu_remove,
.driver = {
.name = "platform-mhu",
.of_match_table = platform_mhu_dt_ids,
diff --git a/drivers/mailbox/qcom-apcs-ipc-mailbox.c b/drivers/mailbox/qcom-apcs-ipc-mailbox.c
index aed23ac9550d..3cf2937be149 100644
--- a/drivers/mailbox/qcom-apcs-ipc-mailbox.c
+++ b/drivers/mailbox/qcom-apcs-ipc-mailbox.c
@@ -91,7 +91,7 @@ static int qcom_apcs_ipc_probe(struct platform_device *pdev)
apcs->mbox.chans = apcs->mbox_chans;
apcs->mbox.num_chans = ARRAY_SIZE(apcs->mbox_chans);
- ret = mbox_controller_register(&apcs->mbox);
+ ret = devm_mbox_controller_register(&pdev->dev, &apcs->mbox);
if (ret) {
dev_err(&pdev->dev, "failed to register APCS IPC controller\n");
return ret;
@@ -115,7 +115,6 @@ static int qcom_apcs_ipc_remove(struct platform_device *pdev)
struct qcom_apcs_ipc *apcs = platform_get_drvdata(pdev);
struct platform_device *clk = apcs->clk;
- mbox_controller_unregister(&apcs->mbox);
platform_device_unregister(clk);
return 0;
diff --git a/drivers/mailbox/rockchip-mailbox.c b/drivers/mailbox/rockchip-mailbox.c
index d702a204f5c1..f24a77b1a0ff 100644
--- a/drivers/mailbox/rockchip-mailbox.c
+++ b/drivers/mailbox/rockchip-mailbox.c
@@ -247,28 +247,15 @@ static int rockchip_mbox_probe(struct platform_device *pdev)
mb->chans[i].msg = NULL;
}
- ret = mbox_controller_register(&mb->mbox);
+ ret = devm_mbox_controller_register(&pdev->dev, &mb->mbox);
if (ret < 0)
dev_err(&pdev->dev, "Failed to register mailbox: %d\n", ret);
return ret;
}
-static int rockchip_mbox_remove(struct platform_device *pdev)
-{
- struct rockchip_mbox *mb = platform_get_drvdata(pdev);
-
- if (!mb)
- return -EINVAL;
-
- mbox_controller_unregister(&mb->mbox);
-
- return 0;
-}
-
static struct platform_driver rockchip_mbox_driver = {
.probe = rockchip_mbox_probe,
- .remove = rockchip_mbox_remove,
.driver = {
.name = "rockchip-mailbox",
.of_match_table = of_match_ptr(rockchip_mbox_of_match),
diff --git a/drivers/mailbox/stm32-ipcc.c b/drivers/mailbox/stm32-ipcc.c
index 533b0da5235d..a338bd4cd7db 100644
--- a/drivers/mailbox/stm32-ipcc.c
+++ b/drivers/mailbox/stm32-ipcc.c
@@ -299,7 +299,7 @@ static int stm32_ipcc_probe(struct platform_device *pdev)
for (i = 0; i < ipcc->controller.num_chans; i++)
ipcc->controller.chans[i].con_priv = (void *)i;
- ret = mbox_controller_register(&ipcc->controller);
+ ret = devm_mbox_controller_register(dev, &ipcc->controller);
if (ret)
goto err_irq_wkp;
@@ -329,8 +329,6 @@ static int stm32_ipcc_remove(struct platform_device *pdev)
{
struct stm32_ipcc *ipcc = platform_get_drvdata(pdev);
- mbox_controller_unregister(&ipcc->controller);
-
if (ipcc->wkp)
dev_pm_clear_wake_irq(&pdev->dev);
diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c
index 0cde356c11ab..e443f6a2ec4b 100644
--- a/drivers/mailbox/tegra-hsp.c
+++ b/drivers/mailbox/tegra-hsp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -11,16 +11,29 @@
* more details.
*/
+#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/mailbox_controller.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include <linux/pm.h>
#include <linux/slab.h>
#include <dt-bindings/mailbox/tegra186-hsp.h>
+#include "mailbox.h"
+
+#define HSP_INT_IE(x) (0x100 + ((x) * 4))
+#define HSP_INT_IV 0x300
+#define HSP_INT_IR 0x304
+
+#define HSP_INT_EMPTY_SHIFT 0
+#define HSP_INT_EMPTY_MASK 0xff
+#define HSP_INT_FULL_SHIFT 8
+#define HSP_INT_FULL_MASK